forked from mirrors/gecko-dev
We will create the image using the selected position, and the canvas will use the image coordinates, which have not been adjusted for scrolling Differential Revision: https://phabricator.services.mozilla.com/D100291
147 lines
4.5 KiB
JavaScript
147 lines
4.5 KiB
JavaScript
/* 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;
|