Bug 1878038 - show entire viewport in tab preview. a=RyanVM

Original Revision: https://phabricator.services.mozilla.com/D212709

Differential Revision: https://phabricator.services.mozilla.com/D214432
This commit is contained in:
DJ 2024-06-21 23:17:25 +00:00
parent 0ac701f376
commit 2361bd68c9
5 changed files with 148 additions and 14 deletions

View file

@ -74,12 +74,12 @@ export default class TabHoverPreviewPanel {
if (!this._prefDisplayThumbnail || !this._hasValidThumbnailState(tab)) {
return;
}
let thumbnailCanvas = this._win.PageThumbs.createCanvas(this._win);
thumbnailCanvas.width = 280;
thumbnailCanvas.height = 125;
let thumbnailCanvas = this._win.document.createElement("canvas");
this._win.PageThumbs.captureToCanvas(tab.linkedBrowser, thumbnailCanvas, {
fullViewport: true,
targetWidth: 280,
preserveAspectRatio: true,
})
.then(() => {
// in case we've changed tabs after capture started, ensure we still want to show the thumbnail

View file

@ -223,6 +223,17 @@ export var PageThumbUtils = {
aDestCanvas.width = contentWidth;
aDestCanvas.height = contentHeight;
}
} else if (contentHeight && aArgs.preserveAspectRatio) {
// Calculate the thumbnail height based on thumbnail width
// and content aspect ratio
if (aArgs.targetWidth) {
thumbnailWidth = aArgs.targetWidth;
}
thumbnailHeight = thumbnailWidth / (contentWidth / contentHeight);
if (aDestCanvas) {
aDestCanvas.width = thumbnailWidth;
aDestCanvas.height = thumbnailHeight;
}
}
let intermediateWidth = thumbnailWidth * 2;
@ -254,13 +265,17 @@ export var PageThumbUtils = {
// content dims.
// Also by default, canvas does not draw the scrollbars, so no need to
// remove the scrollbar sizes.
let scale = Math.min(
Math.max(
let targetScale;
if (aArgs.preserveAspectRatio) {
// always scale based on width, as we resize height to accommodate
targetScale = intermediateWidth / contentWidth;
} else {
targetScale = Math.max(
intermediateWidth / contentWidth,
intermediateHeight / contentHeight
),
1
);
);
}
let scale = Math.min(targetScale, 1);
let snapshotCtx = snapshotCanvas.getContext("2d");
snapshotCtx.save();

View file

@ -213,6 +213,7 @@ export var PageThumbs = {
* isImage - indicate that this should be treated as an image url.
* backgroundColor - background color to draw behind images.
* targetWidth - desired width for images.
* preserveAspectRatio - resize image height based on targetWidth
* isBackgroundThumb - true if request is from the background thumb service.
* fullViewport - request that a screenshot for the viewport be
* captured. This makes it possible to get a screenshot that reflects
@ -228,6 +229,7 @@ export var PageThumbs = {
aArgs?.backgroundColor ?? lazy.PageThumbUtils.THUMBNAIL_BG_COLOR,
targetWidth:
aArgs?.targetWidth ?? lazy.PageThumbUtils.THUMBNAIL_DEFAULT_SIZE,
preserveAspectRatio: aArgs?.preserveAspectRatio ?? false,
isBackgroundThumb: aArgs ? aArgs.isBackgroundThumb : false,
fullViewport: aArgs?.fullViewport ?? false,
};
@ -313,6 +315,7 @@ export var PageThumbs = {
* isImage - indicate that this should be treated as an image url.
* backgroundColor - background color to draw behind images.
* targetWidth - desired width for images.
* preserveAspectRatio - resize image height based on targetWidth
* isBackgroundThumb - true if request is from the background thumb service.
* fullViewport - request that a screenshot for the viewport be
* captured. This makes it possible to get a screenshot that reflects
@ -341,6 +344,7 @@ export var PageThumbs = {
if (contentWidth == 0 || contentHeight == 0) {
throw new Error("IMAGE_ZERO_DIMENSION");
}
let aspectRatio = contentWidth / contentHeight;
if (!aBrowser.isConnected) {
return null;
@ -363,9 +367,21 @@ export var PageThumbs = {
});
} else {
let fullScale = aArgs ? aArgs.fullScale : false;
let scale = fullScale
? 1
: Math.min(Math.max(aWidth / contentWidth, aHeight / contentHeight), 1);
let targetWidth = aArgs.targetWidth ? aArgs.targetWidth : aWidth;
let preserveAspectRatio = aArgs ? aArgs.preserveAspectRatio : false;
let scale = 1;
if (!fullScale) {
let targetScale;
if (preserveAspectRatio) {
targetScale = targetWidth / contentWidth;
} else {
targetScale = Math.max(
aWidth / contentWidth,
aHeight / contentHeight
);
}
scale = Math.min(targetScale, 1);
}
image = await aBrowser.drawSnapshot(
0,
@ -380,8 +396,13 @@ export var PageThumbs = {
return null;
}
thumbnail.width = fullScale ? contentWidth : aWidth;
thumbnail.height = fullScale ? contentHeight : aHeight;
if (preserveAspectRatio) {
thumbnail.width = targetWidth;
thumbnail.height = targetWidth / aspectRatio;
} else {
thumbnail.width = fullScale ? contentWidth : aWidth;
thumbnail.height = fullScale ? contentHeight : aHeight;
}
}
thumbnail.getContext("2d").drawImage(image, 0, 0);

View file

@ -21,7 +21,9 @@ support-files = [
["browser_thumbnails_bg_crash_during_capture.js"]
run-if = ["crashreporter"]
skip-if = ["apple_silicon"] # Disabled due to bleedover with other tests when run in regular suites; passes in "failures" jobs
skip-if = [
"apple_silicon",
] # Disabled due to bleedover with other tests when run in regular suites; passes in "failures" jobs
["browser_thumbnails_bg_crash_while_idle.js"]
run-if = ["crashreporter"]
@ -66,6 +68,8 @@ skip-if = ["true"] # bug 1314039 # Bug 1345418
["browser_thumbnails_fullViewport.js"]
["browser_thumbnails_preserveAspectRatio.js"]
["browser_thumbnails_privacy.js"]
["browser_thumbnails_redirect.js"]

View file

@ -0,0 +1,94 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { PageThumbUtils } = ChromeUtils.importESModule(
"resource://gre/modules/PageThumbUtils.sys.mjs"
);
/**
* Returns the width & height of the content area for a given browser
*
* @param browser the browser to get dimensions for
*/
async function getContentDimensions(browser) {
let thumbnailsActor =
browser.browsingContext.currentWindowGlobal.getActor("Thumbnails");
let contentInfo = await thumbnailsActor.sendQuery(
"Browser:Thumbnail:ContentInfo"
);
return [contentInfo.width, contentInfo.height];
}
/**
* Verify that preserveAspectRatio generates a sized canvas
* that matches the window's aspect ratio
*
* @param windowWidth width of the browser window
* @param windowHeight height of the browser window
* @param useRemote Whether to use a remote or local browser (these use different PageThumbs APIs)
* @param win the window to test
*/
async function testPreserveAspectRatio(
windowWidth,
windowHeight,
useRemote,
win
) {
let resizeComplete = BrowserTestUtils.waitForEvent(win, "resize");
win.resizeTo(windowWidth, windowHeight);
await resizeComplete;
await BrowserTestUtils.withNewTab(
{
gBrowser: win.gBrowser,
url: useRemote ? "https://example.com" : "about:about",
},
async browser => {
let canvas = PageThumbUtils.createCanvas(win);
let [, defaultThumbnailHeight] = PageThumbUtils.getThumbnailSize(win);
await PageThumbs.captureToCanvas(browser, canvas, {
targetWidth: 300,
preserveAspectRatio: false,
});
Assert.equal(
canvas.height,
defaultThumbnailHeight,
"canvas uses default thumbnail height"
);
await PageThumbs.captureToCanvas(browser, canvas, {
targetWidth: 300,
preserveAspectRatio: true,
});
let [contentWidth, contentHeight] = await getContentDimensions(browser);
let aspectRatio = contentWidth / contentHeight;
let expectedHeight = canvas.width / aspectRatio;
// Calculation may be off by a pixel here and there due to floating point math;
// assume it's correct if error is within 1%
let deviation = Math.abs(expectedHeight - canvas.height) / expectedHeight;
Assert.ok(deviation < 0.01, "canvas height within 1% of expected height");
}
);
}
/**
* Tests PageThumbs' preserveAspectRatio option for a variety
* of window aspect ratios.
*/
add_task(async function thumbnails_preserveAspectRatio() {
let win = await BrowserTestUtils.openNewBrowserWindow();
await testPreserveAspectRatio(600, 900, true, win);
await testPreserveAspectRatio(900, 600, true, win);
await testPreserveAspectRatio(450, 1000, true, win);
await testPreserveAspectRatio(600, 900, false, win);
await testPreserveAspectRatio(900, 600, false, win);
await testPreserveAspectRatio(450, 1000, false, win);
await BrowserTestUtils.closeWindow(win);
});