summaryrefslogtreecommitdiffstats
path: root/browser/extensions/screenshots/selector/shooter.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--browser/extensions/screenshots/selector/shooter.js163
1 files changed, 163 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..5d06fbec7b
--- /dev/null
+++ b/browser/extensions/screenshots/selector/shooter.js
@@ -0,0 +1,163 @@
+/* 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, browser, documentMetadata, util, uicontrol, ui, catcher */
+/* globals 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;
+ let backend;
+ let shotObject;
+ const callBackground = global.callBackground;
+
+ 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) {
+ promise = callBackground(
+ "screenshotPage",
+ selectedPos.toJSON(),
+ type,
+ window.devicePixelRatio
+ );
+ }
+
+ catcher.watchPromise(
+ promise.then(dataLoc => {
+ screenshotTaskFn(dataLoc);
+ })
+ );
+ }
+
+ exports.downloadShot = function(selectedPos, previewDataUrl, type) {
+ const shotPromise = previewDataUrl
+ ? Promise.resolve(previewDataUrl)
+ : hideUIFrame();
+ catcher.watchPromise(
+ shotPromise.then(dataUrl => {
+ screenshotPage(dataUrl, selectedPos, type, url => {
+ let typeFromDataUrl = blobConverters.getTypeFromDataUrl(url);
+ typeFromDataUrl = typeFromDataUrl
+ ? typeFromDataUrl.split("/", 2)[1]
+ : null;
+ shotObject.delAllClips();
+ shotObject.addClip({
+ createdDate: Date.now(),
+ image: {
+ url,
+ type: typeFromDataUrl,
+ 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 });
+ }
+ };
+
+ catcher.watchFunction(() => {
+ shotObject = new AbstractShot(
+ backend,
+ randomString(RANDOM_STRING_LENGTH) + "/" + domainFromUrl(location),
+ {
+ origin: shot.originFromUrl(location.href),
+ }
+ );
+ shotObject.update(documentMetadata());
+ })();
+
+ return exports;
+})();
+null;