[tbb-commits] [Git][tpo/applications/tor-browser][tor-browser-102.5.0esr-12.5-1] Bug 32308: use direct browser sizing for letterboxing.
Richard Pospesel (@richard)
git at gitlab.torproject.org
Tue Dec 20 18:21:10 UTC 2022
Richard Pospesel pushed to branch tor-browser-102.5.0esr-12.5-1 at The Tor Project / Applications / Tor Browser
Commits:
1f87c8fb by hackademix at 2022-12-20T18:26:01+01:00
Bug 32308: use direct browser sizing for letterboxing.
- - - - -
8 changed files:
- − browser/actors/RFPHelperChild.jsm
- − browser/actors/RFPHelperParent.jsm
- browser/actors/moz.build
- browser/base/content/browser.css
- browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js
- layout/style/res/ua.css
- toolkit/components/resistfingerprinting/RFPHelper.jsm
- toolkit/modules/FinderParent.jsm
Changes:
=====================================
browser/actors/RFPHelperChild.jsm deleted
=====================================
@@ -1,27 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* 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/. */
-
-var EXPORTED_SYMBOLS = ["RFPHelperChild"];
-
-const { XPCOMUtils } = ChromeUtils.import(
- "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing";
-
-XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "isLetterboxingEnabled",
- kPrefLetterboxing,
- false
-);
-
-class RFPHelperChild extends JSWindowActorChild {
- handleEvent(event) {
- if (isLetterboxingEnabled && event.type == "resize") {
- this.sendAsyncMessage("Letterboxing:ContentSizeUpdated");
- }
- }
-}
=====================================
browser/actors/RFPHelperParent.jsm deleted
=====================================
@@ -1,32 +0,0 @@
-1; /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* 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/. */
-
-var EXPORTED_SYMBOLS = ["RFPHelperParent"];
-
-const { XPCOMUtils } = ChromeUtils.import(
- "resource://gre/modules/XPCOMUtils.jsm"
-);
-
-const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing";
-
-XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "isLetterboxingEnabled",
- kPrefLetterboxing,
- false
-);
-
-class RFPHelperParent extends JSWindowActorParent {
- receiveMessage(aMessage) {
- if (
- isLetterboxingEnabled &&
- aMessage.name == "Letterboxing:ContentSizeUpdated"
- ) {
- let browser = this.browsingContext.top.embedderElement;
- let window = browser.ownerGlobal;
- window.RFPHelper.contentSizeUpdated(window);
- }
- }
-}
=====================================
browser/actors/moz.build
=====================================
@@ -82,8 +82,6 @@ FINAL_TARGET_FILES.actors += [
"PromptParent.jsm",
"RefreshBlockerChild.jsm",
"RefreshBlockerParent.jsm",
- "RFPHelperChild.jsm",
- "RFPHelperParent.jsm",
"ScreenshotsComponentChild.jsm",
"SearchSERPTelemetryChild.jsm",
"SearchSERPTelemetryParent.jsm",
=====================================
browser/base/content/browser.css
=====================================
@@ -102,16 +102,19 @@ body {
Never modify the following selector without synchronizing
LETTERBOX_CSS_SELECTOR in RFPHelper.jsm!
**/
-.letterboxing .browserStack > browser:not(.exclude-letterboxing) {
- margin: 0; /* to be dynamically set by RFHelper.jsm */
+.letterboxing .browserStack:not(.exclude-letterboxing) > browser {
+ /* width & height to be dynamically set by RFPHelper.jsm */
outline: 1px solid var(--chrome-content-separator-color);
}
-browser.exclude-letterboxing {
- margin: 0 !important;
+.exclude-letterboxing > browser {
outline: initial;
}
+.letterboxing-ready .browserStack:not(.exclude-letterboxing) {
+ place-content: start center;
+}
+
/* extend down the toolbar's colors when letterboxing is enabled */
.letterboxing {
background-color: var(--toolbar-bgcolor);
=====================================
browser/components/resistfingerprinting/test/browser/browser_dynamical_window_rounding.js
=====================================
@@ -82,7 +82,7 @@ async function test_dynamical_window_rounding(aWindow, aCheckFunc) {
// We need to wait for the updating the margins for the newly opened tab, or
// it will affect the following tests.
let promiseForTheFirstRounding = TestUtils.topicObserved(
- "test:letterboxing:update-margin-finish"
+ "test:letterboxing:update-size-finish"
);
info("Open a content tab for testing.");
@@ -108,7 +108,7 @@ async function test_dynamical_window_rounding(aWindow, aCheckFunc) {
let caseString = "Case " + width + "x" + height + ": ";
// Create a promise for waiting for the margin update.
let promiseRounding = TestUtils.topicObserved(
- "test:letterboxing:update-margin-finish"
+ "test:letterboxing:update-size-finish"
);
let { containerWidth, containerHeight } = getContainerSize(tab);
@@ -316,7 +316,7 @@ async function test_findbar(aWindow) {
);
let promiseRounding = TestUtils.topicObserved(
- "test:letterboxing:update-margin-finish"
+ "test:letterboxing:update-size-finish"
);
let findBarOpenPromise = BrowserTestUtils.waitForEvent(
@@ -330,7 +330,7 @@ async function test_findbar(aWindow) {
ok(true, "Margin updated when findbar opened");
promiseRounding = TestUtils.topicObserved(
- "test:letterboxing:update-margin-finish"
+ "test:letterboxing:update-size-finish"
);
let findBarClosePromise = BrowserTestUtils.waitForEvent(
=====================================
layout/style/res/ua.css
=====================================
@@ -356,8 +356,8 @@
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
- width: 100% !important;
- height: 100% !important;
+ width: 100%;
+ height: 100%;
margin: 0 !important;
min-width: 0 !important;
max-width: none !important;
@@ -368,6 +368,11 @@
transform: none !important;
}
+*|*:fullscreen:not(:root, .letterboxing .browserStack:not(.exclude-letterboxing) > browser) {
+ width: 100% !important;
+ height: 100% !important;
+}
+
xul|*:fullscreen:not(:root, [hidden="true"]) {
/* The position: fixed; property above used to force the computed display
* value to block. It is no longer the case now, so we manually set it here to
=====================================
toolkit/components/resistfingerprinting/RFPHelper.jsm
=====================================
@@ -95,7 +95,7 @@ class _RFPHelper {
case kTopicDOMWindowOpened:
// We attach to the newly created window by adding tabsProgressListener
// and event listener on it. We listen for new tabs being added or
- // the change of the content principal and apply margins accordingly.
+ // the change of the content principal and round browser sizes accordingly.
this._handleDOMWindowOpened(subject);
break;
default:
@@ -106,8 +106,9 @@ class _RFPHelper {
handleEvent(aMessage) {
switch (aMessage.type) {
case "TabOpen": {
- let tab = aMessage.target;
- this._addOrClearContentMargin(tab.linkedBrowser, /* isNewTab = */ true);
+ let browser = aMessage.target.linkedBrowser;
+ this._roundOrResetContentSize(browser, /* isNewTab = */ true);
+ browser.ownerGlobal._rfpResizeObserver.observe(browser.parentElement);
break;
}
default:
@@ -131,10 +132,6 @@ class _RFPHelper {
}
}
- contentSizeUpdated(win) {
- this._updateMarginsForTabsInWindow(win);
- }
-
// ============================================================================
// Language Prompt
// ============================================================================
@@ -291,44 +288,22 @@ class _RFPHelper {
// ============================================================================
/**
* We use the TabsProgressListener to catch the change of the content
- * principal. We would clear the margins around the content viewport if
- * it is the system principal.
+ * principal. We would reset browser size if it is the system principal.
*/
onLocationChange(aBrowser) {
- this._addOrClearContentMargin(aBrowser);
+ this._roundOrResetContentSize(aBrowser);
}
_handleLetterboxingPrefChanged() {
if (Services.prefs.getBoolPref(kPrefLetterboxing, false)) {
Services.ww.registerNotification(this);
- this._registerActor();
this._attachAllWindows();
} else {
- this._unregisterActor();
this._detachAllWindows();
Services.ww.unregisterNotification(this);
}
}
- _registerActor() {
- ChromeUtils.registerWindowActor("RFPHelper", {
- parent: {
- moduleURI: "resource:///actors/RFPHelperParent.jsm",
- },
- child: {
- moduleURI: "resource:///actors/RFPHelperChild.jsm",
- events: {
- resize: {},
- },
- },
- allFrames: true,
- });
- }
-
- _unregisterActor() {
- ChromeUtils.unregisterWindowActor("RFPHelper");
- }
-
// The function to parse the dimension set from the pref value. The pref value
// should be formated as 'width1xheight1, width2xheight2, ...'. For
// example, '100x100, 200x200, 400x200 ...'.
@@ -354,13 +329,13 @@ class _RFPHelper {
getLetterboxingDefaultRule(aBrowser) {
let document = aBrowser.ownerDocument;
- return (document._letterboxingMarginsRule ||= (() => {
+ return (document._letterBoxingSizingRule ||= (() => {
// If not already cached on the document object, traverse the CSSOM and
// find the rule applying the default letterboxing styles to browsers
// preemptively in order to beat race conditions on tab/window creation
const LETTERBOX_CSS_URL = "chrome://browser/content/browser.css";
const LETTERBOX_CSS_SELECTOR =
- ".letterboxing .browserStack > browser:not(.exclude-letterboxing)";
+ ".letterboxing .browserStack:not(.exclude-letterboxing) > browser";
for (let ss of document.styleSheets) {
if (ss.href !== LETTERBOX_CSS_URL) {
continue;
@@ -389,23 +364,23 @@ class _RFPHelper {
);
}
- _addOrClearContentMargin(aBrowser, isNewTab = false) {
+ _roundOrResetContentSize(aBrowser, isNewTab = false) {
// We won't do anything for lazy browsers.
- if (!aBrowser.isConnected) {
+ if (!aBrowser?.isConnected) {
return;
}
if (this._noLetterBoxingFor(aBrowser)) {
// this tab doesn't need letterboxing
- this._clearContentViewMargin(aBrowser);
+ this._resetContentSize(aBrowser);
} else {
- this._roundContentView(aBrowser, isNewTab);
+ this._roundContentSize(aBrowser, isNewTab);
}
}
/**
- * Given a width or height, returns the appropriate margin to apply.
+ * Given a width or height, rounds it with the proper stepping.
*/
- steppedRange(aDimension) {
+ steppedSize(aDimension) {
let stepping;
if (aDimension <= 50) {
return 0;
@@ -417,22 +392,21 @@ class _RFPHelper {
stepping = 200;
}
- return (aDimension % stepping) / 2;
+ return aDimension - (aDimension % stepping);
}
/**
- * The function will round the given browser by adding margins around the
- * content viewport.
+ * The function will round the given browser size
*/
- async _roundContentView(aBrowser, isNewTab = false) {
- let logPrefix = `_roundContentView[${Math.random()}]`;
+ async _roundContentSize(aBrowser, isNewTab = false) {
+ let logPrefix = `_roundContentSize[${Math.random()}]`;
log(logPrefix);
- aBrowser.classList.remove("exclude-letterboxing");
let win = aBrowser.ownerGlobal;
let browserContainer = aBrowser
.getTabBrowser()
.getBrowserContainer(aBrowser);
let browserParent = aBrowser.parentElement;
+ browserParent.classList.remove("exclude-letterboxing");
let [
[contentWidth, contentHeight],
[parentWidth, parentHeight],
@@ -455,25 +429,27 @@ class _RFPHelper {
return;
}
- const calcMargins = (aWidth, aHeight) => {
+ const roundDimensions = (aWidth, aHeight) => {
+ const r = (aWidth, aHeight) => ({
+ width: `${aWidth}px`,
+ height: `${aHeight}px`,
+ });
+
let result;
- log(`${logPrefix} calcMargins(${aWidth}, ${aHeight})`);
+ log(`${logPrefix} roundDimensions(${aWidth}, ${aHeight})`);
// If the set is empty, we will round the content with the default
// stepping size.
if (!this._letterboxingDimensions.length) {
- result = {
- width: this.steppedRange(aWidth),
- height: this.steppedRange(aHeight),
- };
+ result = r(this.steppedSize(aWidth), this.steppedSize(aHeight));
log(
- `${logPrefix} calcMargins(${aWidth}, ${aHeight}) = ${result.width} x ${result.height}`
+ `${logPrefix} roundDimensions(${aWidth}, ${aHeight}) = ${result.width} x ${result.height}`
);
return result;
}
let matchingArea = aWidth * aHeight;
let minWaste = Number.MAX_SAFE_INTEGER;
- let targetDimensions = undefined;
+ let targetDimensions;
// Find the desired dimensions which waste the least content area.
for (let dim of this._letterboxingDimensions) {
@@ -493,119 +469,119 @@ class _RFPHelper {
// If we cannot find any dimensions match to the real content window, this
// means the content area is smaller the smallest size in the set. In this
- // case, we won't apply any margins.
- if (!targetDimensions) {
- result = {
- width: 0,
- height: 0,
- };
- } else {
- result = {
- width: (aWidth - targetDimensions.width) / 2,
- height: (aHeight - targetDimensions.height) / 2,
- };
- }
+ // case, we won't round the size and default to the max.
+ result = targetDimensions
+ ? r(targetDimensions.width, targetDimensions.height)
+ : r(aWidth, aHeight);
log(
- `${logPrefix} calcMargins(${aWidth}, ${aHeight}) = ${result.width} x ${result.height}`
+ `${logPrefix} roundDimensions(${aWidth}, ${aHeight}) = ${result.width} x ${result.height}`
);
return result;
};
- // Calculating the margins around the browser element in order to round the
- // content viewport. We will use a 200x100 stepping if the dimension set
- // is not given.
- // Margin and outline colors are set in browser.css (.letterboxing * selectors).
-
- const buildMarginStyleString = (aWidth, aHeight) => {
- const marginDims = calcMargins(aWidth, aHeight);
-
- // snap browser element to top
- const top = 0,
- // and leave 'double' margin at the bottom
- bottom = 2 * marginDims.height,
- // identical margins left and right
- left = marginDims.width,
- right = marginDims.width;
-
- return `${top}px ${right}px ${bottom}px ${left}px`;
- };
-
- const marginChanges = Object.assign([], {
- queueIfNeeded({ style }, margin) {
- if (style.margin !== margin) {
- this.push(() => {
- style.margin = margin;
- });
+ const styleChanges = Object.assign([], {
+ queueIfNeeded({ style }, props) {
+ for (let [name, value] of Object.entries(props)) {
+ if (style[name] !== value) {
+ this.push(() => {
+ style.setProperty(name, value, "important");
+ });
+ }
}
},
perform() {
win.requestAnimationFrame(() => {
for (let change of this) {
- change();
+ try {
+ change();
+ } catch (e) {
+ logConsole.error(e);
+ }
}
});
},
});
- marginChanges.queueIfNeeded(
+ const roundedDefault = roundDimensions(containerWidth, containerHeight);
+
+ styleChanges.queueIfNeeded(
this.getLetterboxingDefaultRule(aBrowser),
- buildMarginStyleString(containerWidth, containerHeight)
+ roundedDefault
);
- const marginStyleString =
+ const roundedInline =
!isNewTab && // new tabs cannot have extra UI components
(containerHeight > parentHeight || containerWidth > parentWidth)
? // optional UI components such as the notification box, the find bar
// or devtools are constraining this browser's size: recompute custom
- buildMarginStyleString(parentWidth, parentHeight)
- : ""; // otherwise we can keep the default letterboxing margins
- marginChanges.queueIfNeeded(aBrowser, marginStyleString);
+ roundDimensions(parentWidth, parentHeight)
+ : { width: "", height: "" }; // otherwise we can keep the default (rounded) size
+ styleChanges.queueIfNeeded(aBrowser, roundedInline);
// If the size of the content is already quantized, we do nothing.
- if (!marginChanges.length) {
+ if (!styleChanges.length) {
log(`${logPrefix} is_rounded == true`);
if (this._isLetterboxingTesting) {
log(
- `${logPrefix} is_rounded == true test:letterboxing:update-margin-finish`
+ `${logPrefix} is_rounded == true test:letterboxing:update-size-finish`
);
Services.obs.notifyObservers(
null,
- "test:letterboxing:update-margin-finish"
+ "test:letterboxing:update-size-finish"
);
}
return;
}
- log(`${logPrefix} setting margins to ${marginStyleString}`);
- // Here we set the browser's margin to round its content size.
+ log(
+ `${logPrefix} setting size to ${JSON.stringify({
+ roundedDefault,
+ roundedInline,
+ })}`
+ );
+ // Here we round the browser's size through CSS.
// A "border" visual is created by using a CSS outline, which does't
// affect layout, while the background appearance is borrowed from the
// toolbar and set in the .letterboxing ancestor (see browser.css).
- marginChanges.perform();
+ styleChanges.perform();
}
- _clearContentViewMargin(aBrowser) {
- aBrowser.classList.add("exclude-letterboxing");
+ _resetContentSize(aBrowser) {
+ aBrowser.parentElement.classList.add("exclude-letterboxing");
}
- _updateMarginsForTabsInWindow(aWindow) {
+ _updateSizeForTabsInWindow(aWindow) {
let tabBrowser = aWindow.gBrowser;
tabBrowser.tabpanels?.classList.add("letterboxing");
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
- this._addOrClearContentMargin(browser);
+ this._roundOrResetContentSize(browser);
}
+ // we need to add this class late because otherwise new windows get maximized
+ aWindow.setTimeout(() => {
+ tabBrowser.tabpanels?.classList.add("letterboxing-ready");
+ });
}
_attachWindow(aWindow) {
aWindow.gBrowser.addTabsProgressListener(this);
aWindow.addEventListener("TabOpen", this);
-
+ const resizeObserver = (aWindow._rfpResizeObserver = new aWindow.ResizeObserver(
+ entries => {
+ for (let { target } of entries) {
+ this._roundOrResetContentSize(target.querySelector("browser"));
+ }
+ }
+ ));
+ // observe resizing of each browser's parent (gets rid of RPC from content windows)
+ for (let bs of aWindow.document.querySelectorAll(".browserStack")) {
+ resizeObserver.observe(bs);
+ }
// Rounding the content viewport.
- this._updateMarginsForTabsInWindow(aWindow);
+ this._updateSizeForTabsInWindow(aWindow);
}
_attachAllWindows() {
@@ -625,15 +601,17 @@ class _RFPHelper {
_detachWindow(aWindow) {
let tabBrowser = aWindow.gBrowser;
tabBrowser.removeTabsProgressListener(this);
+ aWindow._rfpResizeObserver.disconnect();
+ delete aWindow._rfpResizeObserver;
aWindow.removeEventListener("TabOpen", this);
// revert tabpanel's style to default
tabBrowser.tabpanels?.classList.remove("letterboxing");
- // and restore default margins on each browser element
+ // and restore default size on each browser element
for (let tab of tabBrowser.tabs) {
let browser = tab.linkedBrowser;
- this._clearContentViewMargin(browser);
+ this._resetContentSize(browser);
}
}
=====================================
toolkit/modules/FinderParent.jsm
=====================================
@@ -27,15 +27,6 @@ ChromeUtils.defineModuleGetter(
"resource://gre/modules/Geometry.jsm"
);
-const kPrefLetterboxing = "privacy.resistFingerprinting.letterboxing";
-
-XPCOMUtils.defineLazyPreferenceGetter(
- this,
- "isLetterboxingEnabled",
- kPrefLetterboxing,
- false
-);
-
XPCOMUtils.defineLazyPreferenceGetter(
this,
"isSoundEnabled",
@@ -586,24 +577,10 @@ FinderParent.prototype = {
onFindbarClose() {
this._lastFoundBrowsingContext = null;
this.sendMessageToAllContexts("Finder:FindbarClose");
-
- if (isLetterboxingEnabled) {
- let window = this._browser.ownerGlobal;
- if (window.RFPHelper) {
- window.RFPHelper.contentSizeUpdated(window);
- }
- }
},
onFindbarOpen() {
this.sendMessageToAllContexts("Finder:FindbarOpen");
-
- if (isLetterboxingEnabled) {
- let window = this._browser.ownerGlobal;
- if (window.RFPHelper) {
- window.RFPHelper.contentSizeUpdated(window);
- }
- }
},
onModalHighlightChange(aUseModalHighlight) {
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/1f87c8fb054635a9abcc48d1419591c2d593cf62
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/1f87c8fb054635a9abcc48d1419591c2d593cf62
You're receiving this email because of your account on gitlab.torproject.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20221220/791132a6/attachment-0001.htm>
More information about the tbb-commits
mailing list