diff options
Diffstat (limited to 'browser/extensions/screenshots/selector/shooter.js')
-rw-r--r-- | browser/extensions/screenshots/selector/shooter.js | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/browser/extensions/screenshots/selector/shooter.js b/browser/extensions/screenshots/selector/shooter.js new file mode 100644 index 0000000000..d1a4a34e9e --- /dev/null +++ b/browser/extensions/screenshots/selector/shooter.js @@ -0,0 +1,147 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* globals global, documentMetadata, util, uicontrol, ui, catcher */ +/* globals buildSettings, domainFromUrl, randomString, shot, blobConverters */ + +"use strict"; + +this.shooter = (function() { // eslint-disable-line no-unused-vars + const exports = {}; + const { AbstractShot } = shot; + + const RANDOM_STRING_LENGTH = 16; + const MAX_CANVAS_DIMENSION = 32767; + let backend; + let shotObject; + const callBackground = global.callBackground; + const clipboard = global.clipboard; + + function regexpEscape(str) { + // http://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript + return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + } + + function sanitizeError(data) { + const href = new RegExp(regexpEscape(window.location.href), "g"); + const origin = new RegExp(`${regexpEscape(window.location.origin)}[^ \t\n\r",>]*`, "g"); + const json = JSON.stringify(data) + .replace(href, "REDACTED_HREF") + .replace(origin, "REDACTED_URL"); + const result = JSON.parse(json); + return result; + } + + catcher.registerHandler((errorObj) => { + callBackground("reportError", sanitizeError(errorObj)); + }); + + function hideUIFrame() { + ui.iframe.hide(); + return Promise.resolve(null); + } + + function screenshotPage(dataUrl, selectedPos, type, screenshotTaskFn) { + let promise = Promise.resolve(dataUrl); + + if (!dataUrl) { + let isFullPage = type === "fullPage" || type == "fullPageTruncated"; + promise = callBackground( + "screenshotPage", + selectedPos.toJSON(), + isFullPage, + window.devicePixelRatio); + } + + catcher.watchPromise(promise.then((dataUrl) => { + screenshotTaskFn(dataUrl); + })); + } + + exports.downloadShot = function(selectedPos, previewDataUrl, type) { + const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : hideUIFrame(); + catcher.watchPromise(shotPromise.then(dataUrl => { + screenshotPage(dataUrl, selectedPos, type, url => { + let type = blobConverters.getTypeFromDataUrl(url); + type = type ? type.split("/", 2)[1] : null; + shotObject.delAllClips(); + shotObject.addClip({ + createdDate: Date.now(), + image: { + url, + type, + location: selectedPos, + }, + }); + ui.triggerDownload(url, shotObject.filename); + uicontrol.deactivate(); + }); + })); + }; + + exports.preview = function(selectedPos, type) { + catcher.watchPromise(hideUIFrame().then(dataUrl => { + screenshotPage(dataUrl, selectedPos, type, url => { + ui.iframe.usePreview(); + ui.Preview.display(url); + }); + })); + }; + + let copyInProgress = null; + exports.copyShot = function(selectedPos, previewDataUrl, type) { + // This is pretty slow. We'll ignore additional user triggered copy events + // while it is in progress. + if (copyInProgress) { + return; + } + // A max of five seconds in case some error occurs. + copyInProgress = setTimeout(() => { + copyInProgress = null; + }, 5000); + + const unsetCopyInProgress = () => { + if (copyInProgress) { + clearTimeout(copyInProgress); + copyInProgress = null; + } + }; + const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : hideUIFrame(); + catcher.watchPromise(shotPromise.then(dataUrl => { + screenshotPage(dataUrl, selectedPos, type, url => { + const blob = blobConverters.dataUrlToBlob(url); + catcher.watchPromise(callBackground("copyShotToClipboard", blob).then(() => { + uicontrol.deactivate(); + unsetCopyInProgress(); + }, unsetCopyInProgress)); + }); + })); + }; + + exports.sendEvent = function(...args) { + const maybeOptions = args[args.length - 1]; + + if (typeof maybeOptions === "object") { + maybeOptions.incognito = browser.extension.inIncognitoContext; + } else { + args.push({incognito: browser.extension.inIncognitoContext}); + } + + callBackground("sendEvent", ...args); + }; + + catcher.watchFunction(() => { + shotObject = new AbstractShot( + backend, + randomString(RANDOM_STRING_LENGTH) + "/" + domainFromUrl(location), + { + origin: shot.originFromUrl(location.href), + } + ); + shotObject.update(documentMetadata()); + })(); + + return exports; +})(); +null; |