diff --git a/README.MD b/README.MD index 08f3688..1fd1b11 100644 --- a/README.MD +++ b/README.MD @@ -15,3 +15,94 @@ these instructions: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked - Microsoft Edge: https://docs.microsoft.com/en-us/microsoft-edge/extensions-chromium/getting-started/extension-sideloading + + +# How does the extension work. + +Extensions have two types of scripts: background scripts and content scripts. +- Background scripts run in the background of the browser and can be used to + listen to events and perform actions that are common to all tabs. +- Content scripts run in the context of a tab and can be used to interact with + the DOM of the page. + +Here in our extension, we store the spaceId, apiKey, selectedCollection, and selectedDemo. Storing and retrieving these +values is done using the chrome.storage API. The background script does the storing and retrieving of these values. + + +Messaging between the background script and the content script is done using the chrome.runtime API. + +# dodao-upload.js and dodao-content.js +All the content on the DOM is created in dodao-content.js. This is the content script. When any action is done on the +UI, we listen to the action, and pass a message to the background script. + +For example + +# Loading of the extension +When the extension icon is clicked, the background checks if the spaceId and apiKey exists, if it exists, it send a message +to the content script(dodao-content.js), to draw the bottom bar. + +If the spaceId and apiKey does not exist, it sends a message to the content script to draw the modal to capture the spaceId +and apiKey. + +The UI captures it and then sends a message to the background script to store the spaceId and apiKey. + + +# When we enter file name of capture +when user enters the "Html capture" file name, we call the background script and pass the filename. + +Background script has the logic to see what needs to be done, and what UI needs to be shown next. In this case, the +background will initiate download of the file by calling `business.saveTabs` method and passing dodao specific config. + + +# Showing of extension +The extension is shown when the user clicks on the extension icon. The background script listens to the click event. Its +present in `ui-button.js` + +```javascript +browser.action.onClicked.addListener(async tab => { + await business.extensionIconClicked(tab); +}); +``` + +Earlier(base code of extension), used to call saveTab, which used to download the file. Now we show the bottom bar +or the spaceId and apiKey modal. `business.extensionIconClicked(tab)` this function was written by us. + +# Important files +- `dodao-upload.js` - This is the background script. This is the script that listens to the messages from the content script + and does the necessary actions. This has the logic to decide what should be done next, i.e. flow of the extension. +- `dodao-content.js` - This is the content script. This is the script that interacts with the DOM of the page. This is the + script that creates the UI on the page. i.e. the bottom bar or the modals, or the success and error messages. +- `background.js` - This has the logic for post handler of download of the file. This in our flow is called from `content.js` (existing logic of the extension) + ```javascript + const pageData = await processPage(options); + if (pageData) { + await download.downloadPage(pageData, options); + } + ``` + We just modify a couple of lines in download.js. This file then does the post handling of the download and send a message "downloads.download" + + Here is some of the custom logic + ```javascript + if (options.saveWithTidbitsHub) { + // we capture screenshot using options.content as it contains whole page content for the screesnhot + message.dodaoScreenshotBlobUrl = await getDodaoScreenshotBlobUrl(options.content); + } + ``` +- `download.js` - This is the file that handles the download of the file. This is the file that listens to the message "downloads.download" + We added some custom code to this file which looks like + ```javascript + if (message.saveWithTidbitsHub) { + // adding the scripts to the content + message.pageData.content=injectScriptLinkTags(message.pageData.content) + } + ``` + This is the code that injects the scripts to the content. Like the dodao tooltip, selector, css, and tippy scripts + + ```javascript + else if (message.saveWithTidbitsHub) { + const blob = await (await fetch(blobURI)).blob(); + const screenshotBlob = new Blob([await (await fetch(message.dodaoScreenshotBlobUrl)).blob()], { type: "image/png" }); + await uploadFileToDodao(message.captureHtmlScreenFileName, blob, screenshotBlob); + } + ``` + This code send the message to dodao api to upload the html capture. diff --git a/manifest.json b/manifest.json index 6a12087..9edac1c 100644 --- a/manifest.json +++ b/manifest.json @@ -54,14 +54,6 @@ "background": { "service_worker": "lib/single-file-extension-background.js" }, - "side_panel": { - "default_path": "src/ui/pages/panel.html" - }, - "options_ui": { - "browser_style": true, - "page": "src/ui/pages/options.html", - "open_in_tab": false - }, "action": { "default_icon": { "16": "src/ui/resources/icon_16.png", @@ -71,20 +63,7 @@ }, "default_title": "__MSG_buttonDefaultTooltip__" }, - "commands": { - "save-selected-tabs": { - "suggested_key": { - "default": "Ctrl+Shift+Y" - }, - "description": "__MSG_commandSaveSelectedTabs__" - }, - "save-all-tabs": { - "suggested_key": { - "default": "Ctrl+Shift+U" - }, - "description": "__MSG_commandSaveAllTabs__" - } - }, + "commands": {}, "web_accessible_resources": [ { "matches": [ diff --git a/src/core/common/dodao-screenshot.js b/src/core/common/dodao-screenshot.js index 428fd4c..8b9963d 100644 --- a/src/core/common/dodao-screenshot.js +++ b/src/core/common/dodao-screenshot.js @@ -1,32 +1,20 @@ -import html2canvas from "html2canvas"; +import * as ui from "./../../ui/content/content-ui.js"; -export async function getDodaoScreenshotBlobUrl(content) { - const iframe = createIframeWithContent(content); - document.body.appendChild(iframe); +export async function getDodaoScreenshotBlobUrl(options) { + ui.setVisible(false); - const dodaoScreenshotBlobUrl = await new Promise((resolve, reject) => { - iframe.onload = async () => { - const iframeDocument = iframe.contentDocument; - const canvas = await html2canvas(iframeDocument.body, { - width: 1920, - height: 1080, - windowWidth: 1920, - windowHeight: 1080, - useCORS: true, - allowTaint: true, - }); - - const canvasBlob = await canvasToBlob(canvas); - - const dodaoScreenshotBlobUrl = URL.createObjectURL(canvasBlob); - // remove the iframe after screesnhot is taken - document.body.removeChild(iframe); - - resolve(dodaoScreenshotBlobUrl); - }; + const screenshotBlobURI = await browser.runtime.sendMessage({ + method: "tabs.getScreenshot", + width: window.innerWidth, + height: window.innerHeight, + innerHeight: globalThis.innerHeight, }); - - return dodaoScreenshotBlobUrl; + ui.setVisible(true); + const embeddedImage = new Uint8Array( + await (await fetch(screenshotBlobURI)).arrayBuffer() + ); + const blob = new Blob([embeddedImage], { type: "image/png" }); + return URL.createObjectURL(blob); } function createIframeWithContent(htmlContent) { diff --git a/src/core/common/dodao-utils.js b/src/core/common/dodao-utils.js index 48725b4..5a25b97 100644 --- a/src/core/common/dodao-utils.js +++ b/src/core/common/dodao-utils.js @@ -5,11 +5,13 @@ export const CLIKABLE_FILES_HOST_URL = "https://dodao-prod-public-assets.s3.amaz export function injectScriptLinkTags(htmlContent) { console.log("Injecting script and link tags into HTML content"); - const insertionIndex = findInsertionIndex(htmlContent); + // Add `allow-same-origin` to iframes + const updatedHtmlContent = addAllowSameOriginToIframes(htmlContent); + const insertionIndex = findInsertionIndex(updatedHtmlContent); if (insertionIndex !== undefined) { const tags = getScriptLinkTags(); - const modifiedHtml = insertTagsIntoHtml(htmlContent, insertionIndex, tags); + const modifiedHtml = insertTagsIntoHtml(updatedHtmlContent, insertionIndex, tags); return modifiedHtml; } else { console.warn("Unable to find opening style tag in HTML content"); @@ -17,6 +19,31 @@ export function injectScriptLinkTags(htmlContent) { } } +function addAllowSameOriginToIframes(htmlContent) { + // Regular expression to find all