Bug 1908205 - Switch to OffscreenCanvas and blobs for screenshots. r=sfoster
Differential Revision: https://phabricator.services.mozilla.com/D216723
This commit is contained in:
@@ -497,6 +497,8 @@ export var ScreenshotsUtils = {
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", this);
|
||||
browser.ownerDocument.removeEventListener("keydown", this);
|
||||
|
||||
this.revokeBlobURL(browser);
|
||||
|
||||
this.browserToScreenshotsState.delete(browser);
|
||||
if (Cu.isInAutomation) {
|
||||
Services.obs.notifyObservers(null, "screenshots-exit");
|
||||
@@ -948,6 +950,32 @@ export var ScreenshotsUtils = {
|
||||
lazy.AlertsService.showAlertNotification(null, title, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Revoke the object url of the current browsers screenshot.
|
||||
*
|
||||
* @param {browser} browser The current browser
|
||||
*/
|
||||
revokeBlobURL(browser) {
|
||||
let browserState = this.browserToScreenshotsState.get(browser);
|
||||
if (browserState.blobURL) {
|
||||
URL.revokeObjectURL(browserState.blobURL);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the blob url on the browser state so we can revoke on exit.
|
||||
*
|
||||
* @param {browser} browser The current browser
|
||||
* @param {string} blobURL The object url for the screenshot
|
||||
*/
|
||||
setBlobURL(browser, blobURL) {
|
||||
// We shouldn't already have a blob URL on the browser
|
||||
// but let's revoke just in case.
|
||||
this.revokeBlobURL(browser);
|
||||
|
||||
this.setPerBrowserState(browser, { blobURL });
|
||||
},
|
||||
|
||||
/**
|
||||
* The max dimension of any side of a canvas is 32767 and the max canvas area is
|
||||
* 124925329. If the width or height is greater or equal to 32766 we will crop the
|
||||
@@ -1017,7 +1045,7 @@ export var ScreenshotsUtils = {
|
||||
});
|
||||
|
||||
let canvas = await this.createCanvas(rect, browser);
|
||||
let url = canvas.toDataURL();
|
||||
let blob = await canvas.convertToBlob();
|
||||
|
||||
let dialog = await this.openPreviewDialog(browser);
|
||||
await dialog._dialogReady;
|
||||
@@ -1025,7 +1053,9 @@ export var ScreenshotsUtils = {
|
||||
"screenshots-preview"
|
||||
);
|
||||
|
||||
screenshotsPreviewEl.previewImg.src = url;
|
||||
let blobURL = URL.createObjectURL(blob);
|
||||
this.setBlobURL(browser, blobURL);
|
||||
screenshotsPreviewEl.previewImg.src = blobURL;
|
||||
screenshotsPreviewEl.focusButton(lazy.SCREENSHOTS_LAST_SAVED_METHOD);
|
||||
|
||||
Services.prefs.setStringPref(
|
||||
@@ -1060,15 +1090,12 @@ export var ScreenshotsUtils = {
|
||||
|
||||
let browsingContext = BrowsingContext.get(browser.browsingContext.id);
|
||||
|
||||
let canvas = browser.ownerDocument.createElementNS(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
"html:canvas"
|
||||
let canvas = new OffscreenCanvas(
|
||||
region.width * devicePixelRatio,
|
||||
region.height * devicePixelRatio
|
||||
);
|
||||
let context = canvas.getContext("2d");
|
||||
|
||||
canvas.width = region.width * devicePixelRatio;
|
||||
canvas.height = region.height * devicePixelRatio;
|
||||
|
||||
const snapshotSize = Math.floor(MAX_SNAPSHOT_DIMENSION * devicePixelRatio);
|
||||
|
||||
for (
|
||||
@@ -1127,9 +1154,9 @@ export var ScreenshotsUtils = {
|
||||
*/
|
||||
async copyScreenshotFromRegion(region, browser) {
|
||||
let canvas = await this.createCanvas(region, browser);
|
||||
let url = canvas.toDataURL();
|
||||
let blob = await canvas.convertToBlob();
|
||||
|
||||
await this.copyScreenshot(url, browser, {
|
||||
await this.copyScreenshot(blob, browser, {
|
||||
object: "overlay_copy",
|
||||
});
|
||||
},
|
||||
@@ -1137,13 +1164,13 @@ export var ScreenshotsUtils = {
|
||||
/**
|
||||
* Copy the image to the clipboard
|
||||
* This is called from the preview dialog
|
||||
* @param dataUrl The image data
|
||||
* @param blob The image data
|
||||
* @param browser The current browser
|
||||
* @param data Telemetry data
|
||||
*/
|
||||
async copyScreenshot(dataUrl, browser, data) {
|
||||
async copyScreenshot(blob, browser, data) {
|
||||
// Guard against missing image data.
|
||||
if (!dataUrl) {
|
||||
if (!blob) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1151,12 +1178,9 @@ export var ScreenshotsUtils = {
|
||||
Ci.imgITools
|
||||
);
|
||||
|
||||
const base64Data = dataUrl.replace("data:image/png;base64,", "");
|
||||
|
||||
const image = atob(base64Data);
|
||||
const imgDecoded = imageTools.decodeImageFromBuffer(
|
||||
image,
|
||||
image.length,
|
||||
let buffer = await blob.arrayBuffer();
|
||||
const imgDecoded = imageTools.decodeImageFromArrayBuffer(
|
||||
buffer,
|
||||
"image/png"
|
||||
);
|
||||
|
||||
@@ -1211,9 +1235,11 @@ export var ScreenshotsUtils = {
|
||||
*/
|
||||
async downloadScreenshotFromRegion(title, region, browser) {
|
||||
let canvas = await this.createCanvas(region, browser);
|
||||
let dataUrl = canvas.toDataURL();
|
||||
let blob = await canvas.convertToBlob();
|
||||
let blobURL = URL.createObjectURL(blob);
|
||||
this.setBlobURL(browser, blobURL);
|
||||
|
||||
return this.downloadScreenshot(title, dataUrl, browser, {
|
||||
return this.downloadScreenshot(title, blobURL, browser, {
|
||||
object: "overlay_download",
|
||||
});
|
||||
},
|
||||
@@ -1224,14 +1250,14 @@ export var ScreenshotsUtils = {
|
||||
* will return true if the screenshot is downloaded successfully.
|
||||
*
|
||||
* @param title The title of the current page or null and getFilename will get the title
|
||||
* @param dataUrl The image data
|
||||
* @param blobURL The image data
|
||||
* @param browser The current browser
|
||||
* @param data Telemetry data
|
||||
* @returns {Promise<boolean>} true if the downnload succeeded, otherwise false
|
||||
*/
|
||||
async downloadScreenshot(title, dataUrl, browser, data) {
|
||||
async downloadScreenshot(title, blobURL, browser, data) {
|
||||
// Guard against missing image data.
|
||||
if (!dataUrl) {
|
||||
if (!blobURL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1246,7 +1272,7 @@ export var ScreenshotsUtils = {
|
||||
// Create download and track its progress.
|
||||
try {
|
||||
const download = await lazy.Downloads.createDownload({
|
||||
source: dataUrl,
|
||||
source: blobURL,
|
||||
target: targetFile,
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<title></title>
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src chrome:;img-src data:; object-src 'none'"
|
||||
content="default-src chrome: blob:;img-src blob:; object-src 'none'"
|
||||
/>
|
||||
|
||||
<link rel="localization" href="browser/screenshots.ftl" />
|
||||
|
||||
@@ -74,7 +74,6 @@ class ScreenshotsPreview extends MozLitElement {
|
||||
|
||||
close() {
|
||||
window.removeEventListener("keydown", this, true);
|
||||
URL.revokeObjectURL(this.previewImg.src);
|
||||
window.close();
|
||||
}
|
||||
|
||||
@@ -205,7 +204,8 @@ class ScreenshotsPreview extends MozLitElement {
|
||||
|
||||
// Wait for the image to be loaded before we copy it
|
||||
let imageSrc = await this.imageLoadedPromise();
|
||||
await lazy.ScreenshotsUtils.copyScreenshot(imageSrc, this.openerBrowser, {
|
||||
let blob = await fetch(imageSrc).then(r => r.blob());
|
||||
await lazy.ScreenshotsUtils.copyScreenshot(blob, this.openerBrowser, {
|
||||
object: "preview_copy",
|
||||
});
|
||||
this.close();
|
||||
|
||||
Reference in New Issue
Block a user