tor-commits
Threads by month
- ----- 2025 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 213898 discussions

[Git][tpo/applications/tor-browser][base-browser-140.2.0esr-15.0-1] fixup! Firefox preference overrides.
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch base-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
53201cbe by Pier Angelo Vendrame at 2025-09-08T15:49:55+02:00
fixup! Firefox preference overrides.
BB 43950: Disable HEVC.
HEVC support can be used for fingerprinting, as it's hardware-dependent
on some systems, or depends on distribution support/installed packages
for Linux.
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -483,6 +483,9 @@ pref("gfx.offscreencanvas.enabled", false);
pref("dom.disable_window_move_resize", true);
// Set video VP9 to 0 for everyone (bug 22548)
pref("media.benchmark.vp9.threshold", 0);
+// tor-browser#43950: Disable HEVC, as it will reveal lacking hardware support,
+// or differences in installed codec for Linux systems.
+pref("media.hevc.enabled", false);
pref("privacy.resistFingerprinting.block_mozAddonManager", true); // Bug 26114
pref("dom.webmidi.enabled", false); // Bug 41398: Disable Web MIDI API
// tor-browser#42043: Stop reporting device IDs (and spoof their number without
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/53201cb…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/53201cb…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-140.2.0esr-15.0-1] fixup! Firefox preference overrides.
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch tor-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
c02477fa by Pier Angelo Vendrame at 2025-09-08T13:44:13+00:00
fixup! Firefox preference overrides.
BB 43950: Disable HEVC.
HEVC support can be used for fingerprinting, as it's hardware-dependent
on some systems, or depends on distribution support/installed packages
for Linux.
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -483,6 +483,9 @@ pref("gfx.offscreencanvas.enabled", false);
pref("dom.disable_window_move_resize", true);
// Set video VP9 to 0 for everyone (bug 22548)
pref("media.benchmark.vp9.threshold", 0);
+// tor-browser#43950: Disable HEVC, as it will reveal lacking hardware support,
+// or differences in installed codec for Linux systems.
+pref("media.hevc.enabled", false);
pref("privacy.resistFingerprinting.block_mozAddonManager", true); // Bug 26114
pref("dom.webmidi.enabled", false); // Bug 41398: Disable Web MIDI API
// tor-browser#42043: Stop reporting device IDs (and spoof their number without
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/c02477f…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/c02477f…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-140.2.0esr-15.0-1] 3 commits: fixup! BB 42019: Empty browser's clipboard on browser shutdown
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch mullvad-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
4c83f2db by Pier Angelo Vendrame at 2025-09-08T12:32:21+02:00
fixup! BB 42019: Empty browser's clipboard on browser shutdown
BB 43770: Follow upstream's BrowserGlue simplifications.
ClipboardPrivacy to its own file and initialize it from the manifest,
rather than from BrowserGlue.
- - - - -
4b7d805c by Pier Angelo Vendrame at 2025-09-08T12:32:32+02:00
fixup! BB 40925: Implemented the Security Level component
BB 43770: Follow upstream's BrowserGlue simplifications.
Initialize the security level notification from the manifest.
Also, since it was the only occurrence of the file path, move it to the
moz-src:// scheme.
- - - - -
7a6cc7a1 by Pier Angelo Vendrame at 2025-09-08T12:35:10+02:00
fixup! BB 42027: Base Browser migration procedures.
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
5 changed files:
- browser/components/BrowserComponents.manifest
- browser/components/BrowserGlue.sys.mjs
- browser/components/ProfileDataUpgrader.sys.mjs
- + browser/modules/ClipboardPrivacy.sys.mjs
- browser/modules/moz.build
Changes:
=====================================
browser/components/BrowserComponents.manifest
=====================================
@@ -50,6 +50,8 @@ category browser-first-window-ready resource://gre/modules/CaptchaDetectionPingU
category browser-first-window-ready resource://gre/modules/SandboxUtils.sys.mjs SandboxUtils.maybeWarnAboutMissingUserNamespaces
#endif
#endif
+category browser-first-window-ready moz-src:///browser/modules/ClipboardPrivacy.sys.mjs ClipboardPrivacy.init
+category browser-first-window-ready moz-src:///browser/modules/SecurityLevelRestartNotification.sys.mjs SecurityLevelRestartNotification.ready
category browser-idle-startup resource:///modules/PlacesUIUtils.sys.mjs PlacesUIUtils.unblockToolbars
category browser-idle-startup resource:///modules/BuiltInThemes.sys.mjs BuiltInThemes.ensureBuiltInThemes
=====================================
browser/components/BrowserGlue.sys.mjs
=====================================
@@ -12,7 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
AWToolbarButton: "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs",
ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
- AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
BackupService: "resource:///modules/backup/BackupService.sys.mjs",
BrowserSearchTelemetry:
"moz-src:///browser/components/search/BrowserSearchTelemetry.sys.mjs",
@@ -61,8 +60,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
SearchSERPTelemetry:
"moz-src:///browser/components/search/SearchSERPTelemetry.sys.mjs",
- SecurityLevelRestartNotification:
- "resource:///modules/SecurityLevelRestartNotification.sys.mjs",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs",
@@ -106,170 +103,6 @@ if (AppConstants.ENABLE_WEBDRIVER) {
const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
-// Empty clipboard content from private windows on exit
-// (tor-browser#42154)
-const ClipboardPrivacy = {
- _lastClipboardHash: null,
- _globalActivation: false,
- _isPrivateClipboard: false,
- _hasher: null,
- _shuttingDown: false,
- _log: null,
-
- _createTransferable() {
- const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
- Ci.nsITransferable
- );
- trans.init(null);
- return trans;
- },
- _computeClipboardHash() {
- const flavors = ["text/x-moz-url", "text/plain"];
- if (
- !Services.clipboard.hasDataMatchingFlavors(
- flavors,
- Ci.nsIClipboard.kGlobalClipboard
- )
- ) {
- return null;
- }
- const trans = this._createTransferable();
- flavors.forEach(trans.addDataFlavor);
- try {
- Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
- const clipboardContent = {};
- trans.getAnyTransferData({}, clipboardContent);
- const { data } = clipboardContent.value.QueryInterface(
- Ci.nsISupportsString
- );
- const bytes = new TextEncoder().encode(data);
- const hasher = (this._hasher ||= Cc[
- "@mozilla.org/security/hash;1"
- ].createInstance(Ci.nsICryptoHash));
- hasher.init(hasher.SHA256);
- hasher.update(bytes, bytes.length);
- return hasher.finish(true);
- } catch (e) {}
- return null;
- },
-
- startup() {
- this._log = console.createInstance({
- prefix: "ClipboardPrivacy",
- });
- this._lastClipboardHash = this._computeClipboardHash();
-
- // Here we track changes in active window / application,
- // by filtering focus events and window closures.
- const handleActivation = (win, activation) => {
- if (activation) {
- if (!this._globalActivation) {
- // focus changed within this window, bail out.
- return;
- }
- this._globalActivation = false;
- } else if (!Services.focus.activeWindow) {
- // focus is leaving this window:
- // let's track whether it remains within the browser.
- lazy.setTimeout(() => {
- this._globalActivation = !Services.focus.activeWindow;
- }, 100);
- }
-
- const checkClipboardContent = () => {
- const clipboardHash = this._computeClipboardHash();
- if (clipboardHash !== this._lastClipboardHash) {
- this._isPrivateClipboard =
- !activation &&
- (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
- lazy.PrivateBrowsingUtils.isWindowPrivate(win));
- this._lastClipboardHash = clipboardHash;
- this._log.debug(
- `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
- );
- }
- };
-
- if (win.closed) {
- checkClipboardContent();
- } else {
- // defer clipboard access on DOM events to work-around tor-browser#42306
- lazy.setTimeout(checkClipboardContent, 0);
- }
- };
- const focusListener = e =>
- e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
- const initWindow = win => {
- for (const e of ["focusin", "focusout"]) {
- win.addEventListener(e, focusListener);
- }
- };
- for (const w of Services.ww.getWindowEnumerator()) {
- initWindow(w);
- }
- Services.ww.registerNotification((win, event) => {
- switch (event) {
- case "domwindowopened":
- initWindow(win);
- break;
- case "domwindowclosed":
- handleActivation(win, false);
- if (
- this._isPrivateClipboard &&
- lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
- (this._shuttingDown ||
- !Array.from(Services.ww.getWindowEnumerator()).find(
- w =>
- lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
- // We need to filter out the HIDDEN WebExtensions window,
- // which might be private as well but is not UI-relevant.
- !w.location.href.startsWith("chrome://extensions/")
- ))
- ) {
- // no more private windows, empty private content if needed
- this.emptyPrivate();
- }
- }
- });
-
- lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
- "ClipboardPrivacy: removing private data",
- () => {
- this._shuttingDown = true;
- this.emptyPrivate();
- }
- );
- },
- emptyPrivate() {
- if (
- this._isPrivateClipboard &&
- !Services.prefs.getBoolPref(
- "browser.privatebrowsing.preserveClipboard",
- false
- ) &&
- this._lastClipboardHash === this._computeClipboardHash()
- ) {
- // nsIClipboard.emptyClipboard() does nothing in Wayland:
- // we'll set an empty string as a work-around.
- const trans = this._createTransferable();
- const flavor = "text/plain";
- trans.addDataFlavor(flavor);
- const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
- Ci.nsISupportsString
- );
- emptyString.data = "";
- trans.setTransferData(flavor, emptyString);
- const { clipboard } = Services,
- { kGlobalClipboard } = clipboard;
- clipboard.setData(trans, null, kGlobalClipboard);
- clipboard.emptyClipboard(kGlobalClipboard);
- this._lastClipboardHash = null;
- this._isPrivateClipboard = false;
- this._log.info("Private clipboard emptied.");
- }
- },
-};
-
ChromeUtils.defineLazyGetter(
lazy,
"WeaveService",
@@ -596,9 +429,7 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
-
- // Base Browser-specific version of _migrateUI.
- this._migrateUIBB();
+ lazy.ProfileDataUpgrader.upgradeBB(this._isNewProfile);
// Mullvad Browser-specific version of _migrateUI.
this._migrateUIMB();
@@ -987,10 +818,6 @@ BrowserGlue.prototype = {
lazy.WeaveService.init();
}
- lazy.SecurityLevelRestartNotification.ready();
-
- ClipboardPrivacy.startup();
-
lazy.BrowserUtils.callModulesFromCategory(
{
categoryName: "browser-first-window-ready",
@@ -1827,83 +1654,6 @@ BrowserGlue.prototype = {
}
},
- _migrateUIBB() {
- // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
- // for tor-browser#41739.
- // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
- // the UI is hidden. tor-browser#42777.
- // Also, do not set
- // dom.security.https_only_mode_send_http_background_request in
- // the security level anymore (tor-browser#42149).
- // Also, reset security.xfocsp.errorReporting.automatic since we
- // hid its neterror checkbox. tor-browser#42653.
- // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
- // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
- const MIGRATION_VERSION = 4;
- const MIGRATION_PREF = "basebrowser.migration.version";
- if (this._isNewProfile) {
- // Do not migrate fresh profiles
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- return;
- } else if (this._isNewProfile === undefined) {
- // If this happens, check if upstream updated their function and do not
- // set this member anymore!
- console.error("_migrateUIBB: this._isNewProfile is undefined.");
- }
- // We do not care whether this is a new or old profile, since in version 1
- // we just quickly clear a user preference, which should not do anything to
- // new profiles.
- // Shall we ever raise the version number and have a watershed, we can add
- // a check easily (any version > 0 will be an old profile).
- const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
- if (currentVersion < 1) {
- Services.prefs.clearUserPref(
- "layout.css.prefers-color-scheme.content-override"
- );
- }
- if (currentVersion < 2) {
- for (const prefName of [
- "privacy.globalprivacycontrol.enabled",
- "privacy.donottrackheader.enabled",
- // Telemetry preference for if the user changed the value.
- "privacy.globalprivacycontrol.was_ever_enabled",
- // The next two preferences have no corresponding UI, but are related.
- "privacy.globalprivacycontrol.functionality.enabled",
- "privacy.globalprivacycontrol.pbmode.enabled",
- "dom.security.https_only_mode_send_http_background_request",
- "security.xfocsp.errorReporting.automatic",
- ]) {
- Services.prefs.clearUserPref(prefName);
- }
- }
- if (currentVersion < 3) {
- Services.prefs.clearUserPref("general.smoothScroll");
- }
- if (currentVersion < 4) {
- for (const prefName of [
- "browser.translations.enable",
- "browser.ml.enable",
- "browser.ml.chat.enabled",
- "browser.ml.linkPreview.enabled",
- "browser.tabs.groups.smart.enabled",
- "browser.tabs.groups.smart.userEnabled",
- "extensions.ml.enabled",
- "pdfjs.enableAltText",
- "pdfjs.enableAltTextForEnglish",
- "pdfjs.enableGuessAltText",
- "pdfjs.enableAltTextModelDownload",
- "browser.urlbar.quicksuggest.mlEnabled",
- "places.semanticHistory.featureGate",
- ]) {
- // Preferences are locked. Do not want user values to linger in the
- // user's profile and become active if these preferences become unlocked
- // in the future.
- Services.prefs.clearUserPref(prefName);
- }
- }
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- },
-
// Use this method for any MB migration that can be run just before showing
// the UI.
// Anything that critically needs to be migrated earlier should not use this.
=====================================
browser/components/ProfileDataUpgrader.sys.mjs
=====================================
@@ -900,4 +900,78 @@ export let ProfileDataUpgrader = {
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", newVersion);
},
+
+ upgradeBB(isNewProfile) {
+ // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
+ // for tor-browser#41739.
+ // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
+ // the UI is hidden. tor-browser#42777.
+ // Also, do not set
+ // dom.security.https_only_mode_send_http_background_request in
+ // the security level anymore (tor-browser#42149).
+ // Also, reset security.xfocsp.errorReporting.automatic since we
+ // hid its neterror checkbox. tor-browser#42653.
+ // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
+ // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
+ const MIGRATION_VERSION = 4;
+ const MIGRATION_PREF = "basebrowser.migration.version";
+
+ if (isNewProfile) {
+ // Do not migrate fresh profiles
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ return;
+ } else if (isNewProfile === undefined) {
+ // If this happens, check if upstream updated their function and do not
+ // set this member anymore!
+ console.error("upgradeBB: isNewProfile is undefined.");
+ }
+
+ const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
+ if (currentVersion < 1) {
+ Services.prefs.clearUserPref(
+ "layout.css.prefers-color-scheme.content-override"
+ );
+ }
+ if (currentVersion < 2) {
+ for (const prefName of [
+ "privacy.globalprivacycontrol.enabled",
+ "privacy.donottrackheader.enabled",
+ // Telemetry preference for if the user changed the value.
+ "privacy.globalprivacycontrol.was_ever_enabled",
+ // The next two preferences have no corresponding UI, but are related.
+ "privacy.globalprivacycontrol.functionality.enabled",
+ "privacy.globalprivacycontrol.pbmode.enabled",
+ "dom.security.https_only_mode_send_http_background_request",
+ "security.xfocsp.errorReporting.automatic",
+ ]) {
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ if (currentVersion < 3) {
+ Services.prefs.clearUserPref("general.smoothScroll");
+ }
+ if (currentVersion < 4) {
+ for (const prefName of [
+ "browser.translations.enable",
+ "browser.ml.enable",
+ "browser.ml.chat.enabled",
+ "browser.ml.linkPreview.enabled",
+ "browser.tabs.groups.smart.enabled",
+ "browser.tabs.groups.smart.userEnabled",
+ "extensions.ml.enabled",
+ "pdfjs.enableAltText",
+ "pdfjs.enableAltTextForEnglish",
+ "pdfjs.enableGuessAltText",
+ "pdfjs.enableAltTextModelDownload",
+ "browser.urlbar.quicksuggest.mlEnabled",
+ "places.semanticHistory.featureGate",
+ ]) {
+ // Preferences are locked. Do not want user values to linger in the
+ // user's profile and become active if these preferences become unlocked
+ // in the future.
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ },
};
=====================================
browser/modules/ClipboardPrivacy.sys.mjs
=====================================
@@ -0,0 +1,178 @@
+/* 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/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+ setTimeout: "resource://gre/modules/Timer.sys.mjs",
+});
+
+/**
+ * Empty clipboard content from private windows on exit.
+ *
+ * See tor-browser#42154.
+ */
+export const ClipboardPrivacy = {
+ _lastClipboardHash: null,
+ _globalActivation: false,
+ _isPrivateClipboard: false,
+ _hasher: null,
+ _shuttingDown: false,
+ _log: null,
+
+ _createTransferable() {
+ const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
+ Ci.nsITransferable
+ );
+ trans.init(null);
+ return trans;
+ },
+ _computeClipboardHash() {
+ const flavors = ["text/x-moz-url", "text/plain"];
+ if (
+ !Services.clipboard.hasDataMatchingFlavors(
+ flavors,
+ Ci.nsIClipboard.kGlobalClipboard
+ )
+ ) {
+ return null;
+ }
+ const trans = this._createTransferable();
+ flavors.forEach(trans.addDataFlavor);
+ try {
+ Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
+ const clipboardContent = {};
+ trans.getAnyTransferData({}, clipboardContent);
+ const { data } = clipboardContent.value.QueryInterface(
+ Ci.nsISupportsString
+ );
+ const bytes = new TextEncoder().encode(data);
+ const hasher = (this._hasher ||= Cc[
+ "@mozilla.org/security/hash;1"
+ ].createInstance(Ci.nsICryptoHash));
+ hasher.init(hasher.SHA256);
+ hasher.update(bytes, bytes.length);
+ return hasher.finish(true);
+ } catch (e) {}
+ return null;
+ },
+
+ init() {
+ this._log = console.createInstance({
+ prefix: "ClipboardPrivacy",
+ });
+ this._lastClipboardHash = this._computeClipboardHash();
+
+ // Here we track changes in active window / application,
+ // by filtering focus events and window closures.
+ const handleActivation = (win, activation) => {
+ if (activation) {
+ if (!this._globalActivation) {
+ // focus changed within this window, bail out.
+ return;
+ }
+ this._globalActivation = false;
+ } else if (!Services.focus.activeWindow) {
+ // focus is leaving this window:
+ // let's track whether it remains within the browser.
+ lazy.setTimeout(() => {
+ this._globalActivation = !Services.focus.activeWindow;
+ }, 100);
+ }
+
+ const checkClipboardContent = () => {
+ const clipboardHash = this._computeClipboardHash();
+ if (clipboardHash !== this._lastClipboardHash) {
+ this._isPrivateClipboard =
+ !activation &&
+ (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win));
+ this._lastClipboardHash = clipboardHash;
+ this._log.debug(
+ `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
+ );
+ }
+ };
+
+ if (win.closed) {
+ checkClipboardContent();
+ } else {
+ // defer clipboard access on DOM events to work-around tor-browser#42306
+ lazy.setTimeout(checkClipboardContent, 0);
+ }
+ };
+ const focusListener = e =>
+ e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
+ const initWindow = win => {
+ for (const e of ["focusin", "focusout"]) {
+ win.addEventListener(e, focusListener);
+ }
+ };
+ for (const w of Services.ww.getWindowEnumerator()) {
+ initWindow(w);
+ }
+ Services.ww.registerNotification((win, event) => {
+ switch (event) {
+ case "domwindowopened":
+ initWindow(win);
+ break;
+ case "domwindowclosed":
+ handleActivation(win, false);
+ if (
+ this._isPrivateClipboard &&
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
+ (this._shuttingDown ||
+ !Array.from(Services.ww.getWindowEnumerator()).find(
+ w =>
+ lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
+ // We need to filter out the HIDDEN WebExtensions window,
+ // which might be private as well but is not UI-relevant.
+ !w.location.href.startsWith("chrome://extensions/")
+ ))
+ ) {
+ // no more private windows, empty private content if needed
+ this.emptyPrivate();
+ }
+ }
+ });
+
+ lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
+ "ClipboardPrivacy: removing private data",
+ () => {
+ this._shuttingDown = true;
+ this.emptyPrivate();
+ }
+ );
+ },
+ emptyPrivate() {
+ if (
+ this._isPrivateClipboard &&
+ !Services.prefs.getBoolPref(
+ "browser.privatebrowsing.preserveClipboard",
+ false
+ ) &&
+ this._lastClipboardHash === this._computeClipboardHash()
+ ) {
+ // nsIClipboard.emptyClipboard() does nothing in Wayland:
+ // we'll set an empty string as a work-around.
+ const trans = this._createTransferable();
+ const flavor = "text/plain";
+ trans.addDataFlavor(flavor);
+ const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+ emptyString.data = "";
+ trans.setTransferData(flavor, emptyString);
+ const { clipboard } = Services,
+ { kGlobalClipboard } = clipboard;
+ clipboard.setData(trans, null, kGlobalClipboard);
+ clipboard.emptyClipboard(kGlobalClipboard);
+ this._lastClipboardHash = null;
+ this._isPrivateClipboard = false;
+ this._log.info("Private clipboard emptied.");
+ }
+ },
+};
=====================================
browser/modules/moz.build
=====================================
@@ -136,7 +136,6 @@ EXTRA_JS_MODULES += [
"PopupBlockerObserver.sys.mjs",
"ProcessHangMonitor.sys.mjs",
"Sanitizer.sys.mjs",
- "SecurityLevelRestartNotification.sys.mjs",
"SelectionChangedMenulist.sys.mjs",
"SharingUtils.sys.mjs",
"SiteDataManager.sys.mjs",
@@ -149,6 +148,8 @@ EXTRA_JS_MODULES += [
MOZ_SRC_FILES += [
"ContextId.sys.mjs",
+ "ClipboardPrivacy.sys.mjs",
+ "SecurityLevelRestartNotification.sys.mjs",
]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/b8…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/b8…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-140.2.0esr-15.0-1] 3 commits: fixup! BB 42019: Empty browser's clipboard on browser shutdown
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch base-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
24214f3e by Pier Angelo Vendrame at 2025-09-08T12:12:36+02:00
fixup! BB 42019: Empty browser's clipboard on browser shutdown
BB 43770: Follow upstream's BrowserGlue simplifications.
ClipboardPrivacy to its own file and initialize it from the manifest,
rather than from BrowserGlue.
- - - - -
92770da8 by Pier Angelo Vendrame at 2025-09-08T12:16:00+02:00
fixup! BB 40925: Implemented the Security Level component
BB 43770: Follow upstream's BrowserGlue simplifications.
Initialize the security level notification from the manifest.
Also, since it was the only occurrence of the file path, move it to the
moz-src:// scheme.
- - - - -
88bb3bc2 by Pier Angelo Vendrame at 2025-09-08T12:25:21+02:00
fixup! BB 42027: Base Browser migration procedures.
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
5 changed files:
- browser/components/BrowserComponents.manifest
- browser/components/BrowserGlue.sys.mjs
- browser/components/ProfileDataUpgrader.sys.mjs
- + browser/modules/ClipboardPrivacy.sys.mjs
- browser/modules/moz.build
Changes:
=====================================
browser/components/BrowserComponents.manifest
=====================================
@@ -50,6 +50,8 @@ category browser-first-window-ready resource://gre/modules/CaptchaDetectionPingU
category browser-first-window-ready resource://gre/modules/SandboxUtils.sys.mjs SandboxUtils.maybeWarnAboutMissingUserNamespaces
#endif
#endif
+category browser-first-window-ready moz-src:///browser/modules/ClipboardPrivacy.sys.mjs ClipboardPrivacy.init
+category browser-first-window-ready moz-src:///browser/modules/SecurityLevelRestartNotification.sys.mjs SecurityLevelRestartNotification.ready
category browser-idle-startup resource:///modules/PlacesUIUtils.sys.mjs PlacesUIUtils.unblockToolbars
category browser-idle-startup resource:///modules/BuiltInThemes.sys.mjs BuiltInThemes.ensureBuiltInThemes
=====================================
browser/components/BrowserGlue.sys.mjs
=====================================
@@ -12,7 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
AWToolbarButton: "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs",
ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
- AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
BackupService: "resource:///modules/backup/BackupService.sys.mjs",
BrowserSearchTelemetry:
"moz-src:///browser/components/search/BrowserSearchTelemetry.sys.mjs",
@@ -61,8 +60,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
SearchSERPTelemetry:
"moz-src:///browser/components/search/SearchSERPTelemetry.sys.mjs",
- SecurityLevelRestartNotification:
- "resource:///modules/SecurityLevelRestartNotification.sys.mjs",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs",
@@ -106,170 +103,6 @@ if (AppConstants.ENABLE_WEBDRIVER) {
const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
-// Empty clipboard content from private windows on exit
-// (tor-browser#42154)
-const ClipboardPrivacy = {
- _lastClipboardHash: null,
- _globalActivation: false,
- _isPrivateClipboard: false,
- _hasher: null,
- _shuttingDown: false,
- _log: null,
-
- _createTransferable() {
- const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
- Ci.nsITransferable
- );
- trans.init(null);
- return trans;
- },
- _computeClipboardHash() {
- const flavors = ["text/x-moz-url", "text/plain"];
- if (
- !Services.clipboard.hasDataMatchingFlavors(
- flavors,
- Ci.nsIClipboard.kGlobalClipboard
- )
- ) {
- return null;
- }
- const trans = this._createTransferable();
- flavors.forEach(trans.addDataFlavor);
- try {
- Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
- const clipboardContent = {};
- trans.getAnyTransferData({}, clipboardContent);
- const { data } = clipboardContent.value.QueryInterface(
- Ci.nsISupportsString
- );
- const bytes = new TextEncoder().encode(data);
- const hasher = (this._hasher ||= Cc[
- "@mozilla.org/security/hash;1"
- ].createInstance(Ci.nsICryptoHash));
- hasher.init(hasher.SHA256);
- hasher.update(bytes, bytes.length);
- return hasher.finish(true);
- } catch (e) {}
- return null;
- },
-
- startup() {
- this._log = console.createInstance({
- prefix: "ClipboardPrivacy",
- });
- this._lastClipboardHash = this._computeClipboardHash();
-
- // Here we track changes in active window / application,
- // by filtering focus events and window closures.
- const handleActivation = (win, activation) => {
- if (activation) {
- if (!this._globalActivation) {
- // focus changed within this window, bail out.
- return;
- }
- this._globalActivation = false;
- } else if (!Services.focus.activeWindow) {
- // focus is leaving this window:
- // let's track whether it remains within the browser.
- lazy.setTimeout(() => {
- this._globalActivation = !Services.focus.activeWindow;
- }, 100);
- }
-
- const checkClipboardContent = () => {
- const clipboardHash = this._computeClipboardHash();
- if (clipboardHash !== this._lastClipboardHash) {
- this._isPrivateClipboard =
- !activation &&
- (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
- lazy.PrivateBrowsingUtils.isWindowPrivate(win));
- this._lastClipboardHash = clipboardHash;
- this._log.debug(
- `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
- );
- }
- };
-
- if (win.closed) {
- checkClipboardContent();
- } else {
- // defer clipboard access on DOM events to work-around tor-browser#42306
- lazy.setTimeout(checkClipboardContent, 0);
- }
- };
- const focusListener = e =>
- e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
- const initWindow = win => {
- for (const e of ["focusin", "focusout"]) {
- win.addEventListener(e, focusListener);
- }
- };
- for (const w of Services.ww.getWindowEnumerator()) {
- initWindow(w);
- }
- Services.ww.registerNotification((win, event) => {
- switch (event) {
- case "domwindowopened":
- initWindow(win);
- break;
- case "domwindowclosed":
- handleActivation(win, false);
- if (
- this._isPrivateClipboard &&
- lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
- (this._shuttingDown ||
- !Array.from(Services.ww.getWindowEnumerator()).find(
- w =>
- lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
- // We need to filter out the HIDDEN WebExtensions window,
- // which might be private as well but is not UI-relevant.
- !w.location.href.startsWith("chrome://extensions/")
- ))
- ) {
- // no more private windows, empty private content if needed
- this.emptyPrivate();
- }
- }
- });
-
- lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
- "ClipboardPrivacy: removing private data",
- () => {
- this._shuttingDown = true;
- this.emptyPrivate();
- }
- );
- },
- emptyPrivate() {
- if (
- this._isPrivateClipboard &&
- !Services.prefs.getBoolPref(
- "browser.privatebrowsing.preserveClipboard",
- false
- ) &&
- this._lastClipboardHash === this._computeClipboardHash()
- ) {
- // nsIClipboard.emptyClipboard() does nothing in Wayland:
- // we'll set an empty string as a work-around.
- const trans = this._createTransferable();
- const flavor = "text/plain";
- trans.addDataFlavor(flavor);
- const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
- Ci.nsISupportsString
- );
- emptyString.data = "";
- trans.setTransferData(flavor, emptyString);
- const { clipboard } = Services,
- { kGlobalClipboard } = clipboard;
- clipboard.setData(trans, null, kGlobalClipboard);
- clipboard.emptyClipboard(kGlobalClipboard);
- this._lastClipboardHash = null;
- this._isPrivateClipboard = false;
- this._log.info("Private clipboard emptied.");
- }
- },
-};
-
ChromeUtils.defineLazyGetter(
lazy,
"WeaveService",
@@ -596,9 +429,7 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
-
- // Base Browser-specific version of _migrateUI.
- this._migrateUIBB();
+ lazy.ProfileDataUpgrader.upgradeBB(this._isNewProfile);
if (!Services.prefs.prefHasUserValue(PREF_PDFJS_ISDEFAULT_CACHE_STATE)) {
lazy.PdfJs.checkIsDefault(this._isNewProfile);
@@ -984,10 +815,6 @@ BrowserGlue.prototype = {
lazy.WeaveService.init();
}
- lazy.SecurityLevelRestartNotification.ready();
-
- ClipboardPrivacy.startup();
-
lazy.BrowserUtils.callModulesFromCategory(
{
categoryName: "browser-first-window-ready",
@@ -1823,83 +1650,6 @@ BrowserGlue.prototype = {
}
},
- _migrateUIBB() {
- // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
- // for tor-browser#41739.
- // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
- // the UI is hidden. tor-browser#42777.
- // Also, do not set
- // dom.security.https_only_mode_send_http_background_request in
- // the security level anymore (tor-browser#42149).
- // Also, reset security.xfocsp.errorReporting.automatic since we
- // hid its neterror checkbox. tor-browser#42653.
- // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
- // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
- const MIGRATION_VERSION = 4;
- const MIGRATION_PREF = "basebrowser.migration.version";
- if (this._isNewProfile) {
- // Do not migrate fresh profiles
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- return;
- } else if (this._isNewProfile === undefined) {
- // If this happens, check if upstream updated their function and do not
- // set this member anymore!
- console.error("_migrateUIBB: this._isNewProfile is undefined.");
- }
- // We do not care whether this is a new or old profile, since in version 1
- // we just quickly clear a user preference, which should not do anything to
- // new profiles.
- // Shall we ever raise the version number and have a watershed, we can add
- // a check easily (any version > 0 will be an old profile).
- const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
- if (currentVersion < 1) {
- Services.prefs.clearUserPref(
- "layout.css.prefers-color-scheme.content-override"
- );
- }
- if (currentVersion < 2) {
- for (const prefName of [
- "privacy.globalprivacycontrol.enabled",
- "privacy.donottrackheader.enabled",
- // Telemetry preference for if the user changed the value.
- "privacy.globalprivacycontrol.was_ever_enabled",
- // The next two preferences have no corresponding UI, but are related.
- "privacy.globalprivacycontrol.functionality.enabled",
- "privacy.globalprivacycontrol.pbmode.enabled",
- "dom.security.https_only_mode_send_http_background_request",
- "security.xfocsp.errorReporting.automatic",
- ]) {
- Services.prefs.clearUserPref(prefName);
- }
- }
- if (currentVersion < 3) {
- Services.prefs.clearUserPref("general.smoothScroll");
- }
- if (currentVersion < 4) {
- for (const prefName of [
- "browser.translations.enable",
- "browser.ml.enable",
- "browser.ml.chat.enabled",
- "browser.ml.linkPreview.enabled",
- "browser.tabs.groups.smart.enabled",
- "browser.tabs.groups.smart.userEnabled",
- "extensions.ml.enabled",
- "pdfjs.enableAltText",
- "pdfjs.enableAltTextForEnglish",
- "pdfjs.enableGuessAltText",
- "pdfjs.enableAltTextModelDownload",
- "browser.urlbar.quicksuggest.mlEnabled",
- "places.semanticHistory.featureGate",
- ]) {
- // Preferences are locked. Do not want user values to linger in the
- // user's profile and become active if these preferences become unlocked
- // in the future.
- Services.prefs.clearUserPref(prefName);
- }
- }
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- },
-
async _showUpgradeDialog() {
const data = await lazy.OnboardingMessageProvider.getUpgradeMessage();
const { gBrowser } = lazy.BrowserWindowTracker.getTopWindow();
=====================================
browser/components/ProfileDataUpgrader.sys.mjs
=====================================
@@ -900,4 +900,78 @@ export let ProfileDataUpgrader = {
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", newVersion);
},
+
+ upgradeBB(isNewProfile) {
+ // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
+ // for tor-browser#41739.
+ // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
+ // the UI is hidden. tor-browser#42777.
+ // Also, do not set
+ // dom.security.https_only_mode_send_http_background_request in
+ // the security level anymore (tor-browser#42149).
+ // Also, reset security.xfocsp.errorReporting.automatic since we
+ // hid its neterror checkbox. tor-browser#42653.
+ // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
+ // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
+ const MIGRATION_VERSION = 4;
+ const MIGRATION_PREF = "basebrowser.migration.version";
+
+ if (isNewProfile) {
+ // Do not migrate fresh profiles
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ return;
+ } else if (isNewProfile === undefined) {
+ // If this happens, check if upstream updated their function and do not
+ // set this member anymore!
+ console.error("upgradeBB: isNewProfile is undefined.");
+ }
+
+ const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
+ if (currentVersion < 1) {
+ Services.prefs.clearUserPref(
+ "layout.css.prefers-color-scheme.content-override"
+ );
+ }
+ if (currentVersion < 2) {
+ for (const prefName of [
+ "privacy.globalprivacycontrol.enabled",
+ "privacy.donottrackheader.enabled",
+ // Telemetry preference for if the user changed the value.
+ "privacy.globalprivacycontrol.was_ever_enabled",
+ // The next two preferences have no corresponding UI, but are related.
+ "privacy.globalprivacycontrol.functionality.enabled",
+ "privacy.globalprivacycontrol.pbmode.enabled",
+ "dom.security.https_only_mode_send_http_background_request",
+ "security.xfocsp.errorReporting.automatic",
+ ]) {
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ if (currentVersion < 3) {
+ Services.prefs.clearUserPref("general.smoothScroll");
+ }
+ if (currentVersion < 4) {
+ for (const prefName of [
+ "browser.translations.enable",
+ "browser.ml.enable",
+ "browser.ml.chat.enabled",
+ "browser.ml.linkPreview.enabled",
+ "browser.tabs.groups.smart.enabled",
+ "browser.tabs.groups.smart.userEnabled",
+ "extensions.ml.enabled",
+ "pdfjs.enableAltText",
+ "pdfjs.enableAltTextForEnglish",
+ "pdfjs.enableGuessAltText",
+ "pdfjs.enableAltTextModelDownload",
+ "browser.urlbar.quicksuggest.mlEnabled",
+ "places.semanticHistory.featureGate",
+ ]) {
+ // Preferences are locked. Do not want user values to linger in the
+ // user's profile and become active if these preferences become unlocked
+ // in the future.
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ },
};
=====================================
browser/modules/ClipboardPrivacy.sys.mjs
=====================================
@@ -0,0 +1,178 @@
+/* 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/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+ setTimeout: "resource://gre/modules/Timer.sys.mjs",
+});
+
+/**
+ * Empty clipboard content from private windows on exit.
+ *
+ * See tor-browser#42154.
+ */
+export const ClipboardPrivacy = {
+ _lastClipboardHash: null,
+ _globalActivation: false,
+ _isPrivateClipboard: false,
+ _hasher: null,
+ _shuttingDown: false,
+ _log: null,
+
+ _createTransferable() {
+ const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
+ Ci.nsITransferable
+ );
+ trans.init(null);
+ return trans;
+ },
+ _computeClipboardHash() {
+ const flavors = ["text/x-moz-url", "text/plain"];
+ if (
+ !Services.clipboard.hasDataMatchingFlavors(
+ flavors,
+ Ci.nsIClipboard.kGlobalClipboard
+ )
+ ) {
+ return null;
+ }
+ const trans = this._createTransferable();
+ flavors.forEach(trans.addDataFlavor);
+ try {
+ Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
+ const clipboardContent = {};
+ trans.getAnyTransferData({}, clipboardContent);
+ const { data } = clipboardContent.value.QueryInterface(
+ Ci.nsISupportsString
+ );
+ const bytes = new TextEncoder().encode(data);
+ const hasher = (this._hasher ||= Cc[
+ "@mozilla.org/security/hash;1"
+ ].createInstance(Ci.nsICryptoHash));
+ hasher.init(hasher.SHA256);
+ hasher.update(bytes, bytes.length);
+ return hasher.finish(true);
+ } catch (e) {}
+ return null;
+ },
+
+ init() {
+ this._log = console.createInstance({
+ prefix: "ClipboardPrivacy",
+ });
+ this._lastClipboardHash = this._computeClipboardHash();
+
+ // Here we track changes in active window / application,
+ // by filtering focus events and window closures.
+ const handleActivation = (win, activation) => {
+ if (activation) {
+ if (!this._globalActivation) {
+ // focus changed within this window, bail out.
+ return;
+ }
+ this._globalActivation = false;
+ } else if (!Services.focus.activeWindow) {
+ // focus is leaving this window:
+ // let's track whether it remains within the browser.
+ lazy.setTimeout(() => {
+ this._globalActivation = !Services.focus.activeWindow;
+ }, 100);
+ }
+
+ const checkClipboardContent = () => {
+ const clipboardHash = this._computeClipboardHash();
+ if (clipboardHash !== this._lastClipboardHash) {
+ this._isPrivateClipboard =
+ !activation &&
+ (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win));
+ this._lastClipboardHash = clipboardHash;
+ this._log.debug(
+ `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
+ );
+ }
+ };
+
+ if (win.closed) {
+ checkClipboardContent();
+ } else {
+ // defer clipboard access on DOM events to work-around tor-browser#42306
+ lazy.setTimeout(checkClipboardContent, 0);
+ }
+ };
+ const focusListener = e =>
+ e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
+ const initWindow = win => {
+ for (const e of ["focusin", "focusout"]) {
+ win.addEventListener(e, focusListener);
+ }
+ };
+ for (const w of Services.ww.getWindowEnumerator()) {
+ initWindow(w);
+ }
+ Services.ww.registerNotification((win, event) => {
+ switch (event) {
+ case "domwindowopened":
+ initWindow(win);
+ break;
+ case "domwindowclosed":
+ handleActivation(win, false);
+ if (
+ this._isPrivateClipboard &&
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
+ (this._shuttingDown ||
+ !Array.from(Services.ww.getWindowEnumerator()).find(
+ w =>
+ lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
+ // We need to filter out the HIDDEN WebExtensions window,
+ // which might be private as well but is not UI-relevant.
+ !w.location.href.startsWith("chrome://extensions/")
+ ))
+ ) {
+ // no more private windows, empty private content if needed
+ this.emptyPrivate();
+ }
+ }
+ });
+
+ lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
+ "ClipboardPrivacy: removing private data",
+ () => {
+ this._shuttingDown = true;
+ this.emptyPrivate();
+ }
+ );
+ },
+ emptyPrivate() {
+ if (
+ this._isPrivateClipboard &&
+ !Services.prefs.getBoolPref(
+ "browser.privatebrowsing.preserveClipboard",
+ false
+ ) &&
+ this._lastClipboardHash === this._computeClipboardHash()
+ ) {
+ // nsIClipboard.emptyClipboard() does nothing in Wayland:
+ // we'll set an empty string as a work-around.
+ const trans = this._createTransferable();
+ const flavor = "text/plain";
+ trans.addDataFlavor(flavor);
+ const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+ emptyString.data = "";
+ trans.setTransferData(flavor, emptyString);
+ const { clipboard } = Services,
+ { kGlobalClipboard } = clipboard;
+ clipboard.setData(trans, null, kGlobalClipboard);
+ clipboard.emptyClipboard(kGlobalClipboard);
+ this._lastClipboardHash = null;
+ this._isPrivateClipboard = false;
+ this._log.info("Private clipboard emptied.");
+ }
+ },
+};
=====================================
browser/modules/moz.build
=====================================
@@ -136,7 +136,6 @@ EXTRA_JS_MODULES += [
"PopupBlockerObserver.sys.mjs",
"ProcessHangMonitor.sys.mjs",
"Sanitizer.sys.mjs",
- "SecurityLevelRestartNotification.sys.mjs",
"SelectionChangedMenulist.sys.mjs",
"SharingUtils.sys.mjs",
"SiteDataManager.sys.mjs",
@@ -149,6 +148,8 @@ EXTRA_JS_MODULES += [
MOZ_SRC_FILES += [
"ContextId.sys.mjs",
+ "ClipboardPrivacy.sys.mjs",
+ "SecurityLevelRestartNotification.sys.mjs",
]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a1886d…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/a1886d…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-140.2.0esr-15.0-1] 9 commits: fixup! BB 42019: Empty browser's clipboard on browser shutdown
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch tor-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
d5582e87 by Pier Angelo Vendrame at 2025-09-08T12:03:34+02:00
fixup! BB 42019: Empty browser's clipboard on browser shutdown
BB 43770: Follow upstream's BrowserGlue simplifications.
ClipboardPrivacy to its own file and initialize it from the manifest,
rather than from BrowserGlue.
- - - - -
d4c6e7a4 by Pier Angelo Vendrame at 2025-09-08T12:03:35+02:00
fixup! BB 40925: Implemented the Security Level component
BB 43770: Follow upstream's BrowserGlue simplifications.
Initialize the security level notification from the manifest.
Also, since it was the only occurrence of the file path, move it to the
moz-src:// scheme.
- - - - -
8eccdc93 by Pier Angelo Vendrame at 2025-09-08T12:03:35+02:00
fixup! TB 40933: Add tor-launcher functionality
BB 43770: Follow upstream's BrowserGlue simplifications.
Moved the call to firstWindowLoaded to the manifest.
- - - - -
167c0116 by Pier Angelo Vendrame at 2025-09-08T12:03:36+02:00
fixup! TB 8324: Prevent DNS proxy bypasses caused by Drag&Drop
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
b45bb7f1 by Pier Angelo Vendrame at 2025-09-08T12:03:37+02:00
fixup! TB 43405: Show a prompt whenever we fail to apply Tor settings.
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
ad267a06 by Pier Angelo Vendrame at 2025-09-08T12:03:37+02:00
fixup! TB 40458: Implement .tor.onion aliases
Use proper private method and members.
- - - - -
a05bd724 by Pier Angelo Vendrame at 2025-09-08T12:03:38+02:00
fixup! TB 40458: Implement .tor.onion aliases
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
a857af7e by Pier Angelo Vendrame at 2025-09-08T12:03:38+02:00
fixup! BB 42027: Base Browser migration procedures.
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
51ca3bdf by Pier Angelo Vendrame at 2025-09-08T12:03:39+02:00
fixup! TB 41435: Add a Tor Browser migration function
BB 43770: Follow upstream's BrowserGlue simplifications.
- - - - -
12 changed files:
- browser/components/BrowserComponents.manifest
- browser/components/BrowserGlue.sys.mjs
- browser/components/ProfileDataUpgrader.sys.mjs
- browser/components/onionservices/OnionAliasStore.sys.mjs
- browser/components/onionservices/moz.build
- browser/components/rulesets/RulesetsParent.sys.mjs
- + browser/modules/ClipboardPrivacy.sys.mjs
- browser/modules/moz.build
- dom/base/ContentAreaDropListener.sys.mjs
- toolkit/components/places/PlacesUtils.sys.mjs
- toolkit/components/tor-launcher/tor-launcher.manifest
- toolkit/modules/moz.build
Changes:
=====================================
browser/components/BrowserComponents.manifest
=====================================
@@ -51,6 +51,11 @@ category browser-first-window-ready resource://gre/modules/CaptchaDetectionPingU
category browser-first-window-ready resource://gre/modules/SandboxUtils.sys.mjs SandboxUtils.maybeWarnAboutMissingUserNamespaces
#endif
#endif
+category browser-first-window-ready moz-src:///browser/modules/ClipboardPrivacy.sys.mjs ClipboardPrivacy.init
+category browser-first-window-ready moz-src:///browser/modules/SecurityLevelRestartNotification.sys.mjs SecurityLevelRestartNotification.ready
+category browser-first-window-ready moz-src:///toolkit/modules/DragDropFilter.sys.mjs DragDropFilter.init
+category browser-first-window-ready moz-src:///browser/modules/TorSettingsNotification.sys.mjs TorSettingsNotification.ready
+category browser-first-window-ready moz-src:///browser/components/onionservices/OnionAliasStore.sys.mjs OnionAliasStore.init
category browser-idle-startup resource:///modules/PlacesUIUtils.sys.mjs PlacesUIUtils.unblockToolbars
category browser-idle-startup resource:///modules/BuiltInThemes.sys.mjs BuiltInThemes.ensureBuiltInThemes
@@ -94,5 +99,6 @@ category browser-quit-application-granted moz-src:///browser/components/search/S
category browser-quit-application-granted resource://gre/modules/UpdateListener.sys.mjs UpdateListener.reset
#endif
category browser-quit-application-granted resource:///modules/UrlbarSearchTermsPersistence.sys.mjs UrlbarSearchTermsPersistence.uninit
+category browser-quit-application-granted moz-src:///browser/components/onionservices/OnionAliasStore.sys.mjs OnionAliasStore.uninit
category search-service-notification moz-src:///browser/components/search/SearchUIUtils.sys.mjs SearchUIUtils.showSearchServiceNotification
=====================================
browser/components/BrowserGlue.sys.mjs
=====================================
@@ -12,7 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
AWToolbarButton: "resource:///modules/aboutwelcome/AWToolbarUtils.sys.mjs",
ASRouter: "resource:///modules/asrouter/ASRouter.sys.mjs",
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
- AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
BackupService: "resource:///modules/backup/BackupService.sys.mjs",
BrowserSearchTelemetry:
"moz-src:///browser/components/search/BrowserSearchTelemetry.sys.mjs",
@@ -31,7 +30,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
DistributionManagement: "resource:///modules/distribution.sys.mjs",
DownloadsViewableInternally:
"resource:///modules/DownloadsViewableInternally.sys.mjs",
- DragDropFilter: "resource://gre/modules/DragDropFilter.sys.mjs",
ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs",
// FilePickerCrashed is used by the `listeners` object below.
// eslint-disable-next-line mozilla/valid-lazy
@@ -42,7 +40,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
MigrationUtils: "resource:///modules/MigrationUtils.sys.mjs",
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
- OnionAliasStore: "resource:///modules/OnionAliasStore.sys.mjs",
OnboardingMessageProvider:
"resource:///modules/asrouter/OnboardingMessageProvider.sys.mjs",
PageDataService: "resource:///modules/pagedata/PageDataService.sys.mjs",
@@ -63,8 +60,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
SearchSERPTelemetry:
"moz-src:///browser/components/search/SearchSERPTelemetry.sys.mjs",
- SecurityLevelRestartNotification:
- "resource:///modules/SecurityLevelRestartNotification.sys.mjs",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
ShortcutUtils: "resource://gre/modules/ShortcutUtils.sys.mjs",
@@ -75,11 +70,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
TelemetryReportingPolicy:
"resource://gre/modules/TelemetryReportingPolicy.sys.mjs",
TRRRacer: "resource:///modules/TRRPerformance.sys.mjs",
- TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
- TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs",
- TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
- TorSettingsNotification:
- "resource:///modules/TorSettingsNotification.sys.mjs",
WebChannel: "resource://gre/modules/WebChannel.sys.mjs",
WebProtocolHandlerRegistrar:
"resource:///modules/WebProtocolHandlerRegistrar.sys.mjs",
@@ -113,170 +103,6 @@ if (AppConstants.ENABLE_WEBDRIVER) {
const PREF_PDFJS_ISDEFAULT_CACHE_STATE = "pdfjs.enabledCache.state";
-// Empty clipboard content from private windows on exit
-// (tor-browser#42154)
-const ClipboardPrivacy = {
- _lastClipboardHash: null,
- _globalActivation: false,
- _isPrivateClipboard: false,
- _hasher: null,
- _shuttingDown: false,
- _log: null,
-
- _createTransferable() {
- const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
- Ci.nsITransferable
- );
- trans.init(null);
- return trans;
- },
- _computeClipboardHash() {
- const flavors = ["text/x-moz-url", "text/plain"];
- if (
- !Services.clipboard.hasDataMatchingFlavors(
- flavors,
- Ci.nsIClipboard.kGlobalClipboard
- )
- ) {
- return null;
- }
- const trans = this._createTransferable();
- flavors.forEach(trans.addDataFlavor);
- try {
- Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
- const clipboardContent = {};
- trans.getAnyTransferData({}, clipboardContent);
- const { data } = clipboardContent.value.QueryInterface(
- Ci.nsISupportsString
- );
- const bytes = new TextEncoder().encode(data);
- const hasher = (this._hasher ||= Cc[
- "@mozilla.org/security/hash;1"
- ].createInstance(Ci.nsICryptoHash));
- hasher.init(hasher.SHA256);
- hasher.update(bytes, bytes.length);
- return hasher.finish(true);
- } catch (e) {}
- return null;
- },
-
- startup() {
- this._log = console.createInstance({
- prefix: "ClipboardPrivacy",
- });
- this._lastClipboardHash = this._computeClipboardHash();
-
- // Here we track changes in active window / application,
- // by filtering focus events and window closures.
- const handleActivation = (win, activation) => {
- if (activation) {
- if (!this._globalActivation) {
- // focus changed within this window, bail out.
- return;
- }
- this._globalActivation = false;
- } else if (!Services.focus.activeWindow) {
- // focus is leaving this window:
- // let's track whether it remains within the browser.
- lazy.setTimeout(() => {
- this._globalActivation = !Services.focus.activeWindow;
- }, 100);
- }
-
- const checkClipboardContent = () => {
- const clipboardHash = this._computeClipboardHash();
- if (clipboardHash !== this._lastClipboardHash) {
- this._isPrivateClipboard =
- !activation &&
- (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
- lazy.PrivateBrowsingUtils.isWindowPrivate(win));
- this._lastClipboardHash = clipboardHash;
- this._log.debug(
- `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
- );
- }
- };
-
- if (win.closed) {
- checkClipboardContent();
- } else {
- // defer clipboard access on DOM events to work-around tor-browser#42306
- lazy.setTimeout(checkClipboardContent, 0);
- }
- };
- const focusListener = e =>
- e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
- const initWindow = win => {
- for (const e of ["focusin", "focusout"]) {
- win.addEventListener(e, focusListener);
- }
- };
- for (const w of Services.ww.getWindowEnumerator()) {
- initWindow(w);
- }
- Services.ww.registerNotification((win, event) => {
- switch (event) {
- case "domwindowopened":
- initWindow(win);
- break;
- case "domwindowclosed":
- handleActivation(win, false);
- if (
- this._isPrivateClipboard &&
- lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
- (this._shuttingDown ||
- !Array.from(Services.ww.getWindowEnumerator()).find(
- w =>
- lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
- // We need to filter out the HIDDEN WebExtensions window,
- // which might be private as well but is not UI-relevant.
- !w.location.href.startsWith("chrome://extensions/")
- ))
- ) {
- // no more private windows, empty private content if needed
- this.emptyPrivate();
- }
- }
- });
-
- lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
- "ClipboardPrivacy: removing private data",
- () => {
- this._shuttingDown = true;
- this.emptyPrivate();
- }
- );
- },
- emptyPrivate() {
- if (
- this._isPrivateClipboard &&
- !Services.prefs.getBoolPref(
- "browser.privatebrowsing.preserveClipboard",
- false
- ) &&
- this._lastClipboardHash === this._computeClipboardHash()
- ) {
- // nsIClipboard.emptyClipboard() does nothing in Wayland:
- // we'll set an empty string as a work-around.
- const trans = this._createTransferable();
- const flavor = "text/plain";
- trans.addDataFlavor(flavor);
- const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
- Ci.nsISupportsString
- );
- emptyString.data = "";
- trans.setTransferData(flavor, emptyString);
- const { clipboard } = Services,
- { kGlobalClipboard } = clipboard;
- clipboard.setData(trans, null, kGlobalClipboard);
- clipboard.emptyClipboard(kGlobalClipboard);
- this._lastClipboardHash = null;
- this._isPrivateClipboard = false;
- this._log.info("Private clipboard emptied.");
- }
- },
-};
-
ChromeUtils.defineLazyGetter(
lazy,
"WeaveService",
@@ -603,13 +429,8 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
-
- // Base Browser-specific version of _migrateUI.
- this._migrateUIBB();
-
- // Handle any TBB-specific migration before showing the UI. Keep after
- // _migrateUI to make sure this._isNewProfile has been defined.
- this._migrateUITBB();
+ lazy.ProfileDataUpgrader.upgradeBB(this._isNewProfile);
+ lazy.ProfileDataUpgrader.upgradeTB(this._isNewProfile);
if (!Services.prefs.prefHasUserValue(PREF_PDFJS_ISDEFAULT_CACHE_STATE)) {
lazy.PdfJs.checkIsDefault(this._isNewProfile);
@@ -995,16 +816,6 @@ BrowserGlue.prototype = {
lazy.WeaveService.init();
}
- lazy.SecurityLevelRestartNotification.ready();
-
- lazy.DragDropFilter.init();
-
- lazy.TorProviderBuilder.firstWindowLoaded();
-
- lazy.TorSettingsNotification.ready();
-
- ClipboardPrivacy.startup();
-
lazy.BrowserUtils.callModulesFromCategory(
{
categoryName: "browser-first-window-ready",
@@ -1104,7 +915,6 @@ BrowserGlue.prototype = {
// can perform at-shutdown tasks later in shutdown.
Services.fog;
},
- () => lazy.OnionAliasStore.uninit(),
];
for (let task of tasks) {
@@ -1375,30 +1185,6 @@ BrowserGlue.prototype = {
},
},
- {
- task: () => {
- if (!lazy.TorConnect.shouldShowTorConnect) {
- // we will take this path when the user is using the legacy tor launcher or
- // when Tor Browser didn't launch its own tor.
- lazy.OnionAliasStore.init();
- } else {
- // this path is taken when using about:torconnect, we wait to init
- // after we are bootstrapped and connected to tor
- const topic = lazy.TorConnectTopics.BootstrapComplete;
- let bootstrapObserver = {
- observe(aSubject, aTopic) {
- if (aTopic === topic) {
- lazy.OnionAliasStore.init();
- // we only need to init once, so remove ourselves as an obvserver
- Services.obs.removeObserver(this, topic);
- }
- },
- };
- Services.obs.addObserver(bootstrapObserver, topic);
- }
- },
- },
-
// Run TRR performance measurements for DoH.
{
name: "doh-rollout.trrRacer.run",
@@ -1865,208 +1651,6 @@ BrowserGlue.prototype = {
}
},
- _migrateUIBB() {
- // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
- // for tor-browser#41739.
- // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
- // the UI is hidden. tor-browser#42777.
- // Also, do not set
- // dom.security.https_only_mode_send_http_background_request in
- // the security level anymore (tor-browser#42149).
- // Also, reset security.xfocsp.errorReporting.automatic since we
- // hid its neterror checkbox. tor-browser#42653.
- // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
- // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
- const MIGRATION_VERSION = 4;
- const MIGRATION_PREF = "basebrowser.migration.version";
- if (this._isNewProfile) {
- // Do not migrate fresh profiles
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- return;
- } else if (this._isNewProfile === undefined) {
- // If this happens, check if upstream updated their function and do not
- // set this member anymore!
- console.error("_migrateUIBB: this._isNewProfile is undefined.");
- }
- // We do not care whether this is a new or old profile, since in version 1
- // we just quickly clear a user preference, which should not do anything to
- // new profiles.
- // Shall we ever raise the version number and have a watershed, we can add
- // a check easily (any version > 0 will be an old profile).
- const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
- if (currentVersion < 1) {
- Services.prefs.clearUserPref(
- "layout.css.prefers-color-scheme.content-override"
- );
- }
- if (currentVersion < 2) {
- for (const prefName of [
- "privacy.globalprivacycontrol.enabled",
- "privacy.donottrackheader.enabled",
- // Telemetry preference for if the user changed the value.
- "privacy.globalprivacycontrol.was_ever_enabled",
- // The next two preferences have no corresponding UI, but are related.
- "privacy.globalprivacycontrol.functionality.enabled",
- "privacy.globalprivacycontrol.pbmode.enabled",
- "dom.security.https_only_mode_send_http_background_request",
- "security.xfocsp.errorReporting.automatic",
- ]) {
- Services.prefs.clearUserPref(prefName);
- }
- }
- if (currentVersion < 3) {
- Services.prefs.clearUserPref("general.smoothScroll");
- }
- if (currentVersion < 4) {
- for (const prefName of [
- "browser.translations.enable",
- "browser.ml.enable",
- "browser.ml.chat.enabled",
- "browser.ml.linkPreview.enabled",
- "browser.tabs.groups.smart.enabled",
- "browser.tabs.groups.smart.userEnabled",
- "extensions.ml.enabled",
- "pdfjs.enableAltText",
- "pdfjs.enableAltTextForEnglish",
- "pdfjs.enableGuessAltText",
- "pdfjs.enableAltTextModelDownload",
- "browser.urlbar.quicksuggest.mlEnabled",
- "places.semanticHistory.featureGate",
- ]) {
- // Preferences are locked. Do not want user values to linger in the
- // user's profile and become active if these preferences become unlocked
- // in the future.
- Services.prefs.clearUserPref(prefName);
- }
- }
- Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
- },
-
- // Use this method for any TBB migration that can be run just before showing
- // the UI.
- // Anything that critically needs to be migrated earlier should not use this.
- async _migrateUITBB() {
- // Version 1: Tor Browser 12.0. We use it to remove langpacks, after the
- // migration to packaged locales.
- // Version 2: Tor Browser 13.0/13.0a1: tor-browser#41845. Also, removed some
- // torbutton preferences that are not used anymore.
- // Version 3: Tor Browser 13.0.7/13.5a3: Remove blockchair
- // (tor-browser#42283).
- // Version 4: Tor Browser 14.0a4 (2024-09-02): Remove Twitter, Yahoo and
- // YouTube search engines (tor-browser#41835).
- // Version 5: Tor Browser 14.0a5: Clear user preference for CFR settings
- // since we hid the UI (tor-browser#43118).
- // Version 6: Tor Browser 14.5a3: Clear preference for TorSettings that is
- // no longer used (tor-browser#41921).
- // Drop unused TorConnect setting (tor-browser#43462).
- // Version 7: Tor Browser 14.5a6: Clear home page update url preference
- // (tor-browser#43567).
- // Version 8: Tor Browser 15.0a2: Remove legacy search addons
- // (tor-browser#43111).
- const TBB_MIGRATION_VERSION = 8;
- const MIGRATION_PREF = "torbrowser.migration.version";
-
- // If we decide to force updating users to pass through any version
- // following 12.0, we can remove this check, and check only whether
- // MIGRATION_PREF has a user value, like Mozilla does.
- if (this._isNewProfile) {
- // Do not migrate fresh profiles
- Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
- return;
- } else if (this._isNewProfile === undefined) {
- // If this happens, check if upstream updated their function and do not
- // set this member anymore!
- console.error("_migrateUITBB: this._isNewProfile is undefined.");
- }
-
- const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
- const removeLangpacks = async () => {
- for (const addon of await AddonManager.getAddonsByTypes(["locale"])) {
- await addon.uninstall();
- }
- };
- if (currentVersion < 1) {
- try {
- await removeLangpacks();
- } catch (err) {
- console.error("Could not remove langpacks", err);
- }
- }
- if (currentVersion < 2) {
- const prefToClear = [
- // tor-browser#41845: We were forcing these value by check the value of
- // automatic PBM. We decided not to change
- "browser.cache.disk.enable",
- "places.history.enabled",
- "security.nocertdb",
- "permissions.memory_only",
- // Old torbutton preferences not used anymore.
- "extensions.torbutton.loglevel",
- "extensions.torbutton.logmethod",
- "extensions.torbutton.pref_fixup_version",
- "extensions.torbutton.resize_new_windows",
- "extensions.torbutton.startup",
- "extensions.torlauncher.prompt_for_locale",
- "extensions.torlauncher.loglevel",
- "extensions.torlauncher.logmethod",
- "extensions.torlauncher.torrc_fixup_version",
- ];
- for (const pref of prefToClear) {
- if (Services.prefs.prefHasUserValue(pref)) {
- Services.prefs.clearUserPref(pref);
- }
- }
- }
- const dropAddons = async list => {
- for (const id of list) {
- try {
- const engine = await lazy.AddonManager.getAddonByID(id);
- await engine?.uninstall();
- } catch {}
- }
- };
- if (currentVersion < 3) {
- await dropAddons([
- "blockchair(a)search.mozilla.org",
- "blockchair-onion(a)search.mozilla.org",
- ]);
- }
- if (currentVersion < 4) {
- await dropAddons([
- "twitter(a)search.mozilla.org",
- "yahoo(a)search.mozilla.org",
- "youtube(a)search.mozilla.org",
- ]);
- }
- if (currentVersion < 5) {
- for (const pref of [
- "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
- "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
- ]) {
- Services.prefs.clearUserPref(pref);
- }
- }
- if (currentVersion < 6) {
- Services.prefs.clearUserPref("torbrowser.settings.enabled");
- Services.prefs.clearUserPref("torbrowser.bootstrap.allow_internet_test");
- }
- if (currentVersion < 7) {
- Services.prefs.clearUserPref("torbrowser.post_update.url");
- }
- if (currentVersion < 8) {
- await dropAddons([
- "ddg(a)search.mozilla.org",
- "ddg-onion(a)search.mozilla.org",
- "google(a)search.mozilla.org",
- "startpage(a)search.mozilla.org",
- "startpage-onion(a)search.mozilla.org",
- "wikipedia(a)search.mozilla.org",
- ]);
- }
-
- Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
- },
-
async _showUpgradeDialog() {
const data = await lazy.OnboardingMessageProvider.getUpgradeMessage();
const { gBrowser } = lazy.BrowserWindowTracker.getTopWindow();
=====================================
browser/components/ProfileDataUpgrader.sys.mjs
=====================================
@@ -900,4 +900,200 @@ export let ProfileDataUpgrader = {
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", newVersion);
},
+
+ upgradeBB(isNewProfile) {
+ // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
+ // for tor-browser#41739.
+ // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
+ // the UI is hidden. tor-browser#42777.
+ // Also, do not set
+ // dom.security.https_only_mode_send_http_background_request in
+ // the security level anymore (tor-browser#42149).
+ // Also, reset security.xfocsp.errorReporting.automatic since we
+ // hid its neterror checkbox. tor-browser#42653.
+ // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
+ // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
+ const MIGRATION_VERSION = 4;
+ const MIGRATION_PREF = "basebrowser.migration.version";
+
+ if (isNewProfile) {
+ // Do not migrate fresh profiles
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ return;
+ } else if (isNewProfile === undefined) {
+ // If this happens, check if upstream updated their function and do not
+ // set this member anymore!
+ console.error("upgradeBB: isNewProfile is undefined.");
+ }
+
+ const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
+ if (currentVersion < 1) {
+ Services.prefs.clearUserPref(
+ "layout.css.prefers-color-scheme.content-override"
+ );
+ }
+ if (currentVersion < 2) {
+ for (const prefName of [
+ "privacy.globalprivacycontrol.enabled",
+ "privacy.donottrackheader.enabled",
+ // Telemetry preference for if the user changed the value.
+ "privacy.globalprivacycontrol.was_ever_enabled",
+ // The next two preferences have no corresponding UI, but are related.
+ "privacy.globalprivacycontrol.functionality.enabled",
+ "privacy.globalprivacycontrol.pbmode.enabled",
+ "dom.security.https_only_mode_send_http_background_request",
+ "security.xfocsp.errorReporting.automatic",
+ ]) {
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ if (currentVersion < 3) {
+ Services.prefs.clearUserPref("general.smoothScroll");
+ }
+ if (currentVersion < 4) {
+ for (const prefName of [
+ "browser.translations.enable",
+ "browser.ml.enable",
+ "browser.ml.chat.enabled",
+ "browser.ml.linkPreview.enabled",
+ "browser.tabs.groups.smart.enabled",
+ "browser.tabs.groups.smart.userEnabled",
+ "extensions.ml.enabled",
+ "pdfjs.enableAltText",
+ "pdfjs.enableAltTextForEnglish",
+ "pdfjs.enableGuessAltText",
+ "pdfjs.enableAltTextModelDownload",
+ "browser.urlbar.quicksuggest.mlEnabled",
+ "places.semanticHistory.featureGate",
+ ]) {
+ // Preferences are locked. Do not want user values to linger in the
+ // user's profile and become active if these preferences become unlocked
+ // in the future.
+ Services.prefs.clearUserPref(prefName);
+ }
+ }
+ Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
+ },
+
+ async upgradeTB(isNewProfile) {
+ // Version 1: Tor Browser 12.0. We use it to remove langpacks, after the
+ // migration to packaged locales.
+ // Version 2: Tor Browser 13.0/13.0a1: tor-browser#41845. Also, removed some
+ // torbutton preferences that are not used anymore.
+ // Version 3: Tor Browser 13.0.7/13.5a3: Remove blockchair
+ // (tor-browser#42283).
+ // Version 4: Tor Browser 14.0a4 (2024-09-02): Remove Twitter, Yahoo and
+ // YouTube search engines (tor-browser#41835).
+ // Version 5: Tor Browser 14.0a5: Clear user preference for CFR settings
+ // since we hid the UI (tor-browser#43118).
+ // Version 6: Tor Browser 14.5a3: Clear preference for TorSettings that is
+ // no longer used (tor-browser#41921).
+ // Drop unused TorConnect setting (tor-browser#43462).
+ // Version 7: Tor Browser 14.5a6: Clear home page update url preference
+ // (tor-browser#43567).
+ // Version 8: Tor Browser 15.0a2: Remove legacy search addons
+ // (tor-browser#43111).
+ const TBB_MIGRATION_VERSION = 8;
+ const MIGRATION_PREF = "torbrowser.migration.version";
+
+ // If we decide to force updating users to pass through any version
+ // following 12.0, we can remove this check, and check only whether
+ // MIGRATION_PREF has a user value, like Mozilla does.
+ if (isNewProfile) {
+ // Do not migrate fresh profiles
+ Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
+ return;
+ } else if (isNewProfile === undefined) {
+ // If this happens, check if upstream updated their function and do not
+ // set this member anymore!
+ console.error("upgradeTB: isNewProfile is undefined.");
+ }
+
+ const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
+ const removeLangpacks = async () => {
+ for (const addon of await AddonManager.getAddonsByTypes(["locale"])) {
+ await addon.uninstall();
+ }
+ };
+ if (currentVersion < 1) {
+ try {
+ await removeLangpacks();
+ } catch (err) {
+ console.error("Could not remove langpacks", err);
+ }
+ }
+ if (currentVersion < 2) {
+ const prefToClear = [
+ // tor-browser#41845: We were forcing these value by check the value of
+ // automatic PBM. We decided not to change
+ "browser.cache.disk.enable",
+ "places.history.enabled",
+ "security.nocertdb",
+ "permissions.memory_only",
+ // Old torbutton preferences not used anymore.
+ "extensions.torbutton.loglevel",
+ "extensions.torbutton.logmethod",
+ "extensions.torbutton.pref_fixup_version",
+ "extensions.torbutton.resize_new_windows",
+ "extensions.torbutton.startup",
+ "extensions.torlauncher.prompt_for_locale",
+ "extensions.torlauncher.loglevel",
+ "extensions.torlauncher.logmethod",
+ "extensions.torlauncher.torrc_fixup_version",
+ ];
+ for (const pref of prefToClear) {
+ if (Services.prefs.prefHasUserValue(pref)) {
+ Services.prefs.clearUserPref(pref);
+ }
+ }
+ }
+ const dropAddons = async list => {
+ for (const id of list) {
+ try {
+ const engine = await lazy.AddonManager.getAddonByID(id);
+ await engine?.uninstall();
+ } catch {}
+ }
+ };
+ if (currentVersion < 3) {
+ await dropAddons([
+ "blockchair(a)search.mozilla.org",
+ "blockchair-onion(a)search.mozilla.org",
+ ]);
+ }
+ if (currentVersion < 4) {
+ await dropAddons([
+ "twitter(a)search.mozilla.org",
+ "yahoo(a)search.mozilla.org",
+ "youtube(a)search.mozilla.org",
+ ]);
+ }
+ if (currentVersion < 5) {
+ for (const pref of [
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
+ ]) {
+ Services.prefs.clearUserPref(pref);
+ }
+ }
+ if (currentVersion < 6) {
+ Services.prefs.clearUserPref("torbrowser.settings.enabled");
+ Services.prefs.clearUserPref("torbrowser.bootstrap.allow_internet_test");
+ }
+ if (currentVersion < 7) {
+ Services.prefs.clearUserPref("torbrowser.post_update.url");
+ }
+ if (currentVersion < 8) {
+ await dropAddons([
+ "ddg(a)search.mozilla.org",
+ "ddg-onion(a)search.mozilla.org",
+ "google(a)search.mozilla.org",
+ "startpage(a)search.mozilla.org",
+ "startpage-onion(a)search.mozilla.org",
+ "wikipedia(a)search.mozilla.org",
+ ]);
+ }
+
+ Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
+ },
};
=====================================
browser/components/onionservices/OnionAliasStore.sys.mjs
=====================================
@@ -1,4 +1,6 @@
-// Copyright (c) 2022, The Tor Project, Inc.
+/* 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/. */
import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs";
@@ -6,7 +8,10 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
JSONFile: "resource://gre/modules/JSONFile.sys.mjs",
- TorRequestWatch: "resource:///modules/TorRequestWatch.sys.mjs",
+ TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
+ TorConnectTopics: "resource://gre/modules/TorConnect.sys.mjs",
+ TorRequestWatch:
+ "moz-src:///browser/components/onionservices/TorRequestWatch.sys.mjs",
});
/* OnionAliasStore observer topics */
@@ -84,12 +89,14 @@ class Channel {
};
}
+ #enabled;
+
constructor(name, pathPrefix, jwk, scope, enabled) {
this.name = name;
this.pathPrefix = pathPrefix;
this.jwk = jwk;
this.scope = scope;
- this._enabled = enabled;
+ this.#enabled = enabled;
this.mappings = [];
this.currentTimestamp = 0;
@@ -158,10 +165,10 @@ class Channel {
log.debug(
`Downloaded and verified rules for ${this.name}, now uncompressing`
);
- this._makeMappings(JSON.parse(await gunzip(rulesGz)));
+ this.#makeMappings(JSON.parse(await gunzip(rulesGz)));
}
- _makeMappings(rules) {
+ #makeMappings(rules) {
const toTest = /^https?:\/\/[a-zA-Z0-9\.]{56}\.onion$/;
const mappings = [];
rules.rulesets.forEach(rule => {
@@ -210,7 +217,7 @@ class Channel {
async updateMappings(force) {
force = force === undefined ? false : !!force;
- if (!this._enabled && !force) {
+ if (!this.#enabled && !force) {
return;
}
await this.updateLatestTimestamp();
@@ -224,10 +231,10 @@ class Channel {
}
get enabled() {
- return this._enabled;
+ return this.#enabled;
}
set enabled(enabled) {
- this._enabled = enabled;
+ this.#enabled = enabled;
if (!enabled) {
this.mappings = [];
this.currentTimestamp = 0;
@@ -243,7 +250,7 @@ class Channel {
pathPrefix: this.pathPrefix,
jwk: this.jwk,
scope,
- enabled: this._enabled,
+ enabled: this.#enabled,
mappings: this.mappings,
currentTimestamp: this.currentTimestamp,
};
@@ -277,37 +284,40 @@ class _OnionAliasStore {
return 86400 * 1000; // 1 day, like HTTPS-Everywhere
}
- constructor() {
- this._channels = new Map();
- this._rulesetTimeout = null;
- this._lastCheck = 0;
- this._storage = null;
- }
+ #channels = new Map();
+ #rulesetTimeout = null;
+ #lastCheck = 0;
+ #storage = null;
async init() {
lazy.TorRequestWatch.start();
- await this._loadSettings();
- if (this.enabled) {
- await this._startUpdates();
+ await this.#loadSettings();
+ if (this.enabled && !lazy.TorConnect.shouldShowTorConnect) {
+ await this.#startUpdates();
+ } else {
+ Services.obs.addObserver(this, lazy.TorConnectTopics.BootstrapComplete);
}
Services.prefs.addObserver(kPrefOnionAliasEnabled, this);
}
uninit() {
- this._clear();
- if (this._rulesetTimeout) {
- clearTimeout(this._rulesetTimeout);
+ this.#clear();
+ if (this.#rulesetTimeout) {
+ clearTimeout(this.#rulesetTimeout);
}
- this._rulesetTimeout = null;
+ this.#rulesetTimeout = null;
+
+ Services.obs.removeObserver(this, lazy.TorConnectTopics.BootstrapComplete);
Services.prefs.removeObserver(kPrefOnionAliasEnabled, this);
+
lazy.TorRequestWatch.stop();
}
async getChannels() {
- if (this._storage === null) {
- await this._loadSettings();
+ if (this.#storage === null) {
+ await this.#loadSettings();
}
- return Array.from(this._channels.values(), ch => ch.toJSON());
+ return Array.from(this.#channels.values(), ch => ch.toJSON());
}
async setChannel(chanData) {
@@ -328,20 +338,20 @@ class _OnionAliasStore {
);
// Call makeKey to make it throw if the key is invalid
await ch.makeKey();
- this._channels.set(name, ch);
- this._applyMappings();
- this._saveSettings();
- setTimeout(this._notifyChanges.bind(this), 1);
+ this.#channels.set(name, ch);
+ this.#applyMappings();
+ this.#saveSettings();
+ setTimeout(this.#notifyChanges.bind(this), 1);
return ch;
}
enableChannel(name, enabled) {
- const channel = this._channels.get(name);
+ const channel = this.#channels.get(name);
if (channel !== null) {
channel.enabled = enabled;
- this._applyMappings();
- this._saveSettings();
- this._notifyChanges();
+ this.#applyMappings();
+ this.#saveSettings();
+ this.#notifyChanges();
if (this.enabled && enabled && !channel.currentTimestamp) {
this.updateChannel(name);
}
@@ -352,46 +362,46 @@ class _OnionAliasStore {
if (!this.enabled) {
throw Error("Onion Aliases are disabled");
}
- const channel = this._channels.get(name);
+ const channel = this.#channels.get(name);
if (channel === null) {
throw Error("Channel not found");
}
await channel.updateMappings(true);
- this._saveSettings();
- this._applyMappings();
- setTimeout(this._notifyChanges.bind(this), 1);
+ this.#saveSettings();
+ this.#applyMappings();
+ setTimeout(this.#notifyChanges.bind(this), 1);
return channel;
}
deleteChannel(name) {
- if (this._channels.delete(name)) {
- this._saveSettings();
- this._applyMappings();
- this._notifyChanges();
+ if (this.#channels.delete(name)) {
+ this.#saveSettings();
+ this.#applyMappings();
+ this.#notifyChanges();
}
}
- async _loadSettings() {
- if (this._storage !== null) {
+ async #loadSettings() {
+ if (this.#storage !== null) {
return;
}
- this._channels = new Map();
- this._storage = new lazy.JSONFile({
+ this.#channels = new Map();
+ this.#storage = new lazy.JSONFile({
path: PathUtils.join(
Services.dirsvc.get("ProfD", Ci.nsIFile).path,
"onion-aliases.json"
),
- dataPostProcessor: this._settingsProcessor.bind(this),
+ dataPostProcessor: this.#settingsProcessor.bind(this),
});
- await this._storage.load();
- log.debug("Loaded settings", this._storage.data, this._storage.path);
- this._applyMappings();
- this._notifyChanges();
+ await this.#storage.load();
+ log.debug("Loaded settings", this.#storage.data, this.#storage.path);
+ this.#applyMappings();
+ this.#notifyChanges();
}
- _settingsProcessor(data) {
+ #settingsProcessor(data) {
if ("lastCheck" in data) {
- this._lastCheck = data.lastCheck;
+ this.#lastCheck = data.lastCheck;
} else {
data.lastCheck = 0;
}
@@ -410,56 +420,56 @@ class _OnionAliasStore {
}
return true;
});
- this._channels = channels;
+ this.#channels = channels;
return data;
}
- _saveSettings() {
- if (this._storage === null) {
+ #saveSettings() {
+ if (this.#storage === null) {
throw Error("Settings have not been loaded");
}
- this._storage.data.lastCheck = this._lastCheck;
- this._storage.data.channels = Array.from(this._channels.values(), ch =>
+ this.#storage.data.lastCheck = this.#lastCheck;
+ this.#storage.data.channels = Array.from(this.#channels.values(), ch =>
ch.toJSON()
);
- this._storage.saveSoon();
+ this.#storage.saveSoon();
}
- _addMapping(shortOnionHost, longOnionHost) {
+ #addMapping(shortOnionHost, longOnionHost) {
const service = Cc["@torproject.org/onion-alias-service;1"].getService(
Ci.IOnionAliasService
);
service.addOnionAlias(shortOnionHost, longOnionHost);
}
- _clear() {
+ #clear() {
const service = Cc["@torproject.org/onion-alias-service;1"].getService(
Ci.IOnionAliasService
);
service.clearOnionAliases();
}
- _applyMappings() {
- this._clear();
- for (const ch of this._channels.values()) {
+ #applyMappings() {
+ this.#clear();
+ for (const ch of this.#channels.values()) {
if (!ch.enabled) {
continue;
}
for (const [short, long] of ch.mappings) {
- this._addMapping(short, long);
+ this.#addMapping(short, long);
}
}
}
- async _periodicRulesetCheck() {
+ async #periodicRulesetCheck() {
if (!this.enabled) {
log.debug("Onion Aliases are disabled, not updating rulesets.");
return;
}
log.debug("Begin scheduled ruleset update");
- this._lastCheck = Date.now();
+ this.#lastCheck = Date.now();
let anyUpdated = false;
- for (const ch of this._channels.values()) {
+ for (const ch of this.#channels.values()) {
if (!ch.enabled) {
log.debug(`Not updating ${ch.name} because not enabled`);
continue;
@@ -473,22 +483,22 @@ class _OnionAliasStore {
}
}
if (anyUpdated) {
- this._saveSettings();
- this._applyMappings();
- this._notifyChanges();
+ this.#saveSettings();
+ this.#applyMappings();
+ this.#notifyChanges();
} else {
log.debug("No channel has been updated, avoid saving");
}
- this._scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL);
+ this.#scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL);
}
- async _startUpdates() {
- // This is a "private" function, so we expect the callers to verify wheter
+ async #startUpdates() {
+ // This is a private function, so we expect the callers to verify whether
// onion aliases are enabled.
// Callees will also do, so we avoid an additional check here.
- const dt = Date.now() - this._lastCheck;
+ const dt = Date.now() - this.#lastCheck;
let force = false;
- for (const ch of this._channels.values()) {
+ for (const ch of this.#channels.values()) {
if (ch.enabled && !ch.currentTimestamp) {
// Edited while being offline or some other error happened
force = true;
@@ -499,34 +509,34 @@ class _OnionAliasStore {
log.debug(
`Mappings are stale (${dt}), or force check requested (${force}), checking them immediately`
);
- await this._periodicRulesetCheck();
+ await this.#periodicRulesetCheck();
} else {
- this._scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL - dt);
+ this.#scheduleCheck(_OnionAliasStore.RULESET_CHECK_INTERVAL - dt);
}
}
- _scheduleCheck(dt) {
- if (this._rulesetTimeout) {
+ #scheduleCheck(dt) {
+ if (this.#rulesetTimeout) {
log.warn("The previous update timeout was not null");
- clearTimeout(this._rulesetTimeout);
+ clearTimeout(this.#rulesetTimeout);
}
if (!this.enabled) {
log.warn(
"Ignoring the scheduling of a new check because the Onion Alias feature is currently disabled."
);
- this._rulesetTimeout = null;
+ this.#rulesetTimeout = null;
return;
}
log.debug(`Scheduling ruleset update in ${dt}`);
- this._rulesetTimeout = setTimeout(() => {
- this._rulesetTimeout = null;
- this._periodicRulesetCheck();
+ this.#rulesetTimeout = setTimeout(() => {
+ this.#rulesetTimeout = null;
+ this.#periodicRulesetCheck();
}, dt);
}
- _notifyChanges() {
+ #notifyChanges() {
Services.obs.notifyObservers(
- Array.from(this._channels.values(), ch => ch.toJSON()),
+ Array.from(this.#channels.values(), ch => ch.toJSON()),
OnionAliasStoreTopics.ChannelsChanged
);
}
@@ -538,11 +548,16 @@ class _OnionAliasStore {
observe(aSubject, aTopic) {
if (aTopic === "nsPref:changed") {
if (this.enabled) {
- this._startUpdates();
- } else if (this._rulesetTimeout) {
- clearTimeout(this._rulesetTimeout);
- this._rulesetTimeout = null;
+ this.#startUpdates();
+ } else if (this.#rulesetTimeout) {
+ clearTimeout(this.#rulesetTimeout);
+ this.#rulesetTimeout = null;
}
+ } else if (
+ aTopic === lazy.TorConnectTopics.BootstrapComplete &&
+ this.enabled
+ ) {
+ this.#startUpdates();
}
}
}
=====================================
browser/components/onionservices/moz.build
=====================================
@@ -1,8 +1,11 @@
JAR_MANIFESTS += ["jar.mn"]
EXTRA_JS_MODULES += [
- "OnionAliasStore.sys.mjs",
"OnionLocationChild.sys.mjs",
"OnionLocationParent.sys.mjs",
+]
+
+MOZ_SRC_FILES += [
+ "OnionAliasStore.sys.mjs",
"TorRequestWatch.sys.mjs",
]
=====================================
browser/components/rulesets/RulesetsParent.sys.mjs
=====================================
@@ -1,9 +1,11 @@
-// Copyright (c) 2022, The Tor Project, Inc.
+/* 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/. */
import {
OnionAliasStore,
OnionAliasStoreTopics,
-} from "resource:///modules/OnionAliasStore.sys.mjs";
+} from "moz-src:///browser/components/onionservices/OnionAliasStore.sys.mjs";
const kShowWarningPref = "torbrowser.rulesets.show_warning";
@@ -56,9 +58,10 @@ export class RulesetsParent extends JSWindowActorParent {
return {
showWarning: Services.prefs.getBoolPref(kShowWarningPref, true),
};
- case "rulesets:set-channel":
+ case "rulesets:set-channel": {
const ch = await OnionAliasStore.setChannel(message.data);
return ch;
+ }
case "rulesets:update-channel":
// We need to catch any error in this way, because in case of an
// exception, RPMSendQuery does not return on the other side
=====================================
browser/modules/ClipboardPrivacy.sys.mjs
=====================================
@@ -0,0 +1,178 @@
+/* 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/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
+ setTimeout: "resource://gre/modules/Timer.sys.mjs",
+});
+
+/**
+ * Empty clipboard content from private windows on exit.
+ *
+ * See tor-browser#42154.
+ */
+export const ClipboardPrivacy = {
+ _lastClipboardHash: null,
+ _globalActivation: false,
+ _isPrivateClipboard: false,
+ _hasher: null,
+ _shuttingDown: false,
+ _log: null,
+
+ _createTransferable() {
+ const trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(
+ Ci.nsITransferable
+ );
+ trans.init(null);
+ return trans;
+ },
+ _computeClipboardHash() {
+ const flavors = ["text/x-moz-url", "text/plain"];
+ if (
+ !Services.clipboard.hasDataMatchingFlavors(
+ flavors,
+ Ci.nsIClipboard.kGlobalClipboard
+ )
+ ) {
+ return null;
+ }
+ const trans = this._createTransferable();
+ flavors.forEach(trans.addDataFlavor);
+ try {
+ Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
+ const clipboardContent = {};
+ trans.getAnyTransferData({}, clipboardContent);
+ const { data } = clipboardContent.value.QueryInterface(
+ Ci.nsISupportsString
+ );
+ const bytes = new TextEncoder().encode(data);
+ const hasher = (this._hasher ||= Cc[
+ "@mozilla.org/security/hash;1"
+ ].createInstance(Ci.nsICryptoHash));
+ hasher.init(hasher.SHA256);
+ hasher.update(bytes, bytes.length);
+ return hasher.finish(true);
+ } catch (e) {}
+ return null;
+ },
+
+ init() {
+ this._log = console.createInstance({
+ prefix: "ClipboardPrivacy",
+ });
+ this._lastClipboardHash = this._computeClipboardHash();
+
+ // Here we track changes in active window / application,
+ // by filtering focus events and window closures.
+ const handleActivation = (win, activation) => {
+ if (activation) {
+ if (!this._globalActivation) {
+ // focus changed within this window, bail out.
+ return;
+ }
+ this._globalActivation = false;
+ } else if (!Services.focus.activeWindow) {
+ // focus is leaving this window:
+ // let's track whether it remains within the browser.
+ lazy.setTimeout(() => {
+ this._globalActivation = !Services.focus.activeWindow;
+ }, 100);
+ }
+
+ const checkClipboardContent = () => {
+ const clipboardHash = this._computeClipboardHash();
+ if (clipboardHash !== this._lastClipboardHash) {
+ this._isPrivateClipboard =
+ !activation &&
+ (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing ||
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win));
+ this._lastClipboardHash = clipboardHash;
+ this._log.debug(
+ `Clipboard changed: private ${this._isPrivateClipboard}, hash ${clipboardHash}.`
+ );
+ }
+ };
+
+ if (win.closed) {
+ checkClipboardContent();
+ } else {
+ // defer clipboard access on DOM events to work-around tor-browser#42306
+ lazy.setTimeout(checkClipboardContent, 0);
+ }
+ };
+ const focusListener = e =>
+ e.isTrusted && handleActivation(e.currentTarget, e.type === "focusin");
+ const initWindow = win => {
+ for (const e of ["focusin", "focusout"]) {
+ win.addEventListener(e, focusListener);
+ }
+ };
+ for (const w of Services.ww.getWindowEnumerator()) {
+ initWindow(w);
+ }
+ Services.ww.registerNotification((win, event) => {
+ switch (event) {
+ case "domwindowopened":
+ initWindow(win);
+ break;
+ case "domwindowclosed":
+ handleActivation(win, false);
+ if (
+ this._isPrivateClipboard &&
+ lazy.PrivateBrowsingUtils.isWindowPrivate(win) &&
+ (this._shuttingDown ||
+ !Array.from(Services.ww.getWindowEnumerator()).find(
+ w =>
+ lazy.PrivateBrowsingUtils.isWindowPrivate(w) &&
+ // We need to filter out the HIDDEN WebExtensions window,
+ // which might be private as well but is not UI-relevant.
+ !w.location.href.startsWith("chrome://extensions/")
+ ))
+ ) {
+ // no more private windows, empty private content if needed
+ this.emptyPrivate();
+ }
+ }
+ });
+
+ lazy.AsyncShutdown.quitApplicationGranted.addBlocker(
+ "ClipboardPrivacy: removing private data",
+ () => {
+ this._shuttingDown = true;
+ this.emptyPrivate();
+ }
+ );
+ },
+ emptyPrivate() {
+ if (
+ this._isPrivateClipboard &&
+ !Services.prefs.getBoolPref(
+ "browser.privatebrowsing.preserveClipboard",
+ false
+ ) &&
+ this._lastClipboardHash === this._computeClipboardHash()
+ ) {
+ // nsIClipboard.emptyClipboard() does nothing in Wayland:
+ // we'll set an empty string as a work-around.
+ const trans = this._createTransferable();
+ const flavor = "text/plain";
+ trans.addDataFlavor(flavor);
+ const emptyString = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+ emptyString.data = "";
+ trans.setTransferData(flavor, emptyString);
+ const { clipboard } = Services,
+ { kGlobalClipboard } = clipboard;
+ clipboard.setData(trans, null, kGlobalClipboard);
+ clipboard.emptyClipboard(kGlobalClipboard);
+ this._lastClipboardHash = null;
+ this._isPrivateClipboard = false;
+ this._log.info("Private clipboard emptied.");
+ }
+ },
+};
=====================================
browser/modules/moz.build
=====================================
@@ -136,12 +136,10 @@ EXTRA_JS_MODULES += [
"PopupBlockerObserver.sys.mjs",
"ProcessHangMonitor.sys.mjs",
"Sanitizer.sys.mjs",
- "SecurityLevelRestartNotification.sys.mjs",
"SelectionChangedMenulist.sys.mjs",
"SharingUtils.sys.mjs",
"SiteDataManager.sys.mjs",
"SitePermissions.sys.mjs",
- "TorSettingsNotification.sys.mjs",
"TorUIUtils.sys.mjs",
"TransientPrefs.sys.mjs",
"URILoadingHelper.sys.mjs",
@@ -151,6 +149,9 @@ EXTRA_JS_MODULES += [
MOZ_SRC_FILES += [
"ContextId.sys.mjs",
+ "ClipboardPrivacy.sys.mjs",
+ "SecurityLevelRestartNotification.sys.mjs",
+ "TorSettingsNotification.sys.mjs",
]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
=====================================
dom/base/ContentAreaDropListener.sys.mjs
=====================================
@@ -5,7 +5,7 @@
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
- OpaqueDrag: "resource://gre/modules/DragDropFilter.sys.mjs",
+ OpaqueDrag: "moz-src:///toolkit/modules/DragDropFilter.sys.mjs",
});
// This component is used for handling dragover and drop of urls.
=====================================
toolkit/components/places/PlacesUtils.sys.mjs
=====================================
@@ -12,7 +12,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
Bookmarks: "resource://gre/modules/Bookmarks.sys.mjs",
History: "resource://gre/modules/History.sys.mjs",
- OpaqueDrag: "resource://gre/modules/DragDropFilter.sys.mjs",
+ OpaqueDrag: "moz-src:///toolkit/modules/DragDropFilter.sys.mjs",
PlacesSyncUtils: "resource://gre/modules/PlacesSyncUtils.sys.mjs",
Sqlite: "resource://gre/modules/Sqlite.sys.mjs",
});
=====================================
toolkit/components/tor-launcher/tor-launcher.manifest
=====================================
@@ -1 +1,2 @@
category profile-after-change TorStartupService @torproject.org/tor-startup-service;1
+category browser-first-window-ready resource://gre/modules/TorProviderBuilder.sys.mjs TorProviderBuilder.firstWindowLoaded
=====================================
toolkit/modules/moz.build
=====================================
@@ -164,7 +164,6 @@ EXTRA_JS_MODULES += [
"DateTimePickerPanel.sys.mjs",
"DeferredTask.sys.mjs",
"DomainFrontedRequests.sys.mjs",
- "DragDropFilter.sys.mjs",
"E10SUtils.sys.mjs",
"EventEmitter.sys.mjs",
"FileUtils.sys.mjs",
@@ -220,6 +219,10 @@ EXTRA_JS_MODULES += [
"WebChannel.sys.mjs",
]
+MOZ_SRC_FILES += [
+ "DragDropFilter.sys.mjs",
+]
+
if CONFIG["MOZ_ASAN_REPORTER"]:
EXTRA_JS_MODULES += [
"AsanReporter.sys.mjs",
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d28d9f…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d28d9f…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-140.2.0esr-15.0-1] BB 43525: Skip Remote Settings for search engine customization.
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch base-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
a1886d8c by Pier Angelo Vendrame at 2025-09-08T11:57:50+02:00
BB 43525: Skip Remote Settings for search engine customization.
Also, add some bundled search engines.
- - - - -
9 changed files:
- toolkit/components/search/AppProvidedSearchEngine.sys.mjs
- toolkit/components/search/SearchEngineSelector.sys.mjs
- + toolkit/components/search/content/base-browser-search-engine-icons.json
- + toolkit/components/search/content/base-browser-search-engines.json
- + toolkit/components/search/content/duckduckgo.ico
- + toolkit/components/search/content/startpage-16.png
- + toolkit/components/search/content/startpage-32.png
- + toolkit/components/search/jar.mn
- toolkit/components/search/moz.build
Changes:
=====================================
toolkit/components/search/AppProvidedSearchEngine.sys.mjs
=====================================
@@ -116,6 +116,10 @@ class IconHandler {
await this.#buildIconMap();
}
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return this.#iconMap.get(engineIdentifier);
+ }
+
let iconList = this.#iconMap.get(this.getKey(engineIdentifier)) || [];
return iconList.filter(r =>
this.#identifierMatches(engineIdentifier, r.engineIdentifiers)
@@ -132,29 +136,7 @@ class IconHandler {
* source object or null of there is no icon with the supplied width.
*/
async createIconURL(iconRecord) {
- let iconData;
- try {
- iconData = await this.#iconCollection.attachments.get(iconRecord);
- } catch (ex) {
- console.error(ex);
- }
- if (!iconData) {
- console.warn("Unable to find the attachment for", iconRecord.id);
- // Queue an update in case we haven't downloaded it yet.
- this.#pendingUpdatesMap.set(iconRecord.id, iconRecord);
- this.#maybeQueueIdle();
- return null;
- }
-
- if (iconData.record.last_modified != iconRecord.last_modified) {
- // The icon we have stored is out of date, queue an update so that we'll
- // download the new icon.
- this.#pendingUpdatesMap.set(iconRecord.id, iconRecord);
- this.#maybeQueueIdle();
- }
- return URL.createObjectURL(
- new Blob([iconData.buffer], { type: iconRecord.attachment.mimetype })
- );
+ return iconRecord.url;
}
QueryInterface = ChromeUtils.generateQI(["nsIObserver"]);
@@ -238,27 +220,23 @@ class IconHandler {
* Obtains the icon list from the remote settings collection.
*/
async #buildIconMap() {
- let iconList = [];
try {
- iconList = await this.#iconCollection.get();
+ this.#iconMap = new Map(
+ Object.entries(
+ await (
+ await fetch(
+ "chrome://global/content/search/base-browser-search-engine-icons.json"
+ )
+ ).json()
+ )
+ );
} catch (ex) {
console.error(ex);
+ this.#iconMap = null;
}
- if (!iconList.length) {
+ if (!this.#iconMap) {
console.error("Failed to obtain search engine icon list records");
}
-
- this.#iconMap = new Map();
- for (let record of iconList) {
- let keys = new Set(record.engineIdentifiers.map(this.getKey));
- for (let key of keys) {
- if (this.#iconMap.has(key)) {
- this.#iconMap.get(key).push(record);
- } else {
- this.#iconMap.set(key, [record]);
- }
- }
- }
}
/**
=====================================
toolkit/components/search/SearchEngineSelector.sys.mjs
=====================================
@@ -2,6 +2,8 @@
* 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/. */
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
/**
* @typedef {import("../uniffi-bindgen-gecko-js/components/generated/RustSearch.sys.mjs").SearchEngineSelector} RustSearchEngineSelector
* We use "Rust" above to avoid conflict with the class name for the JavaScript wrapper.
@@ -92,30 +94,15 @@ export class SearchEngineSelector {
return this._getConfigurationPromise;
}
- this._getConfigurationPromise = Promise.all([
- this._getConfiguration(),
- this._getConfigurationOverrides(),
- ]);
- let remoteSettingsData = await this._getConfigurationPromise;
- this._configuration = remoteSettingsData[0];
- this._configurationOverrides = remoteSettingsData[1];
- delete this._getConfigurationPromise;
-
- if (!this._configuration?.length) {
- throw Components.Exception(
- "Failed to get engine data from Remote Settings",
- Cr.NS_ERROR_UNEXPECTED
- );
- }
-
- if (!this._listenerAdded) {
- this._remoteConfig.on("sync", this._onConfigurationUpdated);
- this._remoteConfigOverrides.on(
- "sync",
- this._onConfigurationOverridesUpdated
- );
- this._listenerAdded = true;
- }
+ let { promise, resolve } = Promise.withResolvers();
+ this._getConfigurationPromise = promise;
+ this._configuration = await (
+ await fetch(
+ "chrome://global/content/search/base-browser-search-engines.json"
+ )
+ ).json();
+ this._configurationOverrides = [];
+ resolve(this._configuration);
if (lazy.SearchUtils.rustSelectorFeatureGate) {
this.#selector.setSearchConfig(
@@ -242,6 +229,12 @@ export class SearchEngineSelector {
* The new configuration object
*/
_onConfigurationUpdated({ data: { current } }) {
+ // tor-browser#43525: Even though RemoteSettings are a no-op for us, we do
+ // not want them to interfere in any way.
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return;
+ }
+
this._configuration = current;
if (lazy.SearchUtils.rustSelectorFeatureGate) {
@@ -268,6 +261,12 @@ export class SearchEngineSelector {
* The new configuration object
*/
_onConfigurationOverridesUpdated({ data: { current } }) {
+ // tor-browser#43525: Even though RemoteSettings are a no-op for us, we do
+ // not want them to interfere in any way.
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return;
+ }
+
this._configurationOverrides = current;
if (lazy.SearchUtils.rustSelectorFeatureGate) {
=====================================
toolkit/components/search/content/base-browser-search-engine-icons.json
=====================================
@@ -0,0 +1,15 @@
+{
+ "ddg": [
+ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 }
+ ],
+ "startpage": [
+ {
+ "url": "chrome://global/content/search/startpage-16.png",
+ "imageSize": 16
+ },
+ {
+ "url": "chrome://global/content/search/startpage-32.png",
+ "imageSize": 32
+ }
+ ]
+}
=====================================
toolkit/components/search/content/base-browser-search-engines.json
=====================================
@@ -0,0 +1,43 @@
+[
+ {
+ "base": {
+ "aliases": ["duckduckgo", "ddg"],
+ "classification": "general",
+ "name": "DuckDuckGo",
+ "urls": {
+ "search": {
+ "base": "https://duckduckgo.com/",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "04e99a38-13ee-47d8-8aa4-64482b3dea99",
+ "identifier": "ddg",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["startpage", "sp"],
+ "classification": "general",
+ "name": "Startpage",
+ "urls": {
+ "search": {
+ "base": "https://www.startpage.com/sp/search",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "927bbd9f-b2f3-48b4-8974-1c1148028f4d",
+ "identifier": "startpage",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "recordType": "defaultEngines",
+ "globalDefault": "ddg",
+ "globalDefaultPrivate": "ddg"
+ }
+]
=====================================
toolkit/components/search/content/duckduckgo.ico
=====================================
Binary files /dev/null and b/toolkit/components/search/content/duckduckgo.ico differ
=====================================
toolkit/components/search/content/startpage-16.png
=====================================
Binary files /dev/null and b/toolkit/components/search/content/startpage-16.png differ
=====================================
toolkit/components/search/content/startpage-32.png
=====================================
Binary files /dev/null and b/toolkit/components/search/content/startpage-32.png differ
=====================================
toolkit/components/search/jar.mn
=====================================
@@ -0,0 +1,6 @@
+# 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/.
+
+toolkit.jar:
+ content/global/search/ (content/*)
=====================================
toolkit/components/search/moz.build
=====================================
@@ -46,5 +46,7 @@ TESTING_JS_MODULES += [
"tests/SearchTestUtils.sys.mjs",
]
+JAR_MANIFESTS += ["jar.mn"]
+
with Files("**"):
BUG_COMPONENT = ("Firefox", "Search")
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/a1886d8…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/a1886d8…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-140.2.0esr-15.0-1] 4 commits: fixup! MB 213: Customize the search engines list
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch mullvad-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
fd210716 by Pier Angelo Vendrame at 2025-09-08T11:52:36+02:00
fixup! MB 213: Customize the search engines list
BB 43525: Skip Remote Settings for search engine customization.
Drop some changes that we are not going to keep with the shared
approach.
- - - - -
0c345e48 by Pier Angelo Vendrame at 2025-09-08T11:53:16+02:00
dropme! MB 213: Customize the search engines list
BB 43525: Skip Remote Settings for search engine customization.
Prepare the tree for the new approach.
- - - - -
e95419fa by Pier Angelo Vendrame at 2025-09-08T11:53:17+02:00
BB 43525: Skip Remote Settings for search engine customization.
Also, add some bundled search engines.
- - - - -
b80c84c1 by Pier Angelo Vendrame at 2025-09-08T11:53:17+02:00
amend! MB 213: Customize the search engines list
MB 213: Customize the search engines list.
- - - - -
6 changed files:
- toolkit/components/search/AppProvidedSearchEngine.sys.mjs
- toolkit/components/search/SearchEngineSelector.sys.mjs
- toolkit/components/search/SearchService.sys.mjs
- toolkit/components/search/content/mullvadBrowserSearchEngineIcons.json → toolkit/components/search/content/base-browser-search-engine-icons.json
- + toolkit/components/search/content/base-browser-search-engines.json
- − toolkit/components/search/content/mullvadBrowserSearchEngines.json
Changes:
=====================================
toolkit/components/search/AppProvidedSearchEngine.sys.mjs
=====================================
@@ -116,7 +116,14 @@ class IconHandler {
await this.#buildIconMap();
}
- return this.#iconMap.get(engineIdentifier);
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return this.#iconMap.get(engineIdentifier);
+ }
+
+ let iconList = this.#iconMap.get(this.getKey(engineIdentifier)) || [];
+ return iconList.filter(r =>
+ this.#identifierMatches(engineIdentifier, r.engineIdentifiers)
+ );
}
/**
@@ -218,7 +225,7 @@ class IconHandler {
Object.entries(
await (
await fetch(
- "chrome://global/content/search/mullvadBrowserSearchEngineIcons.json"
+ "chrome://global/content/search/base-browser-search-engine-icons.json"
)
).json()
)
=====================================
toolkit/components/search/SearchEngineSelector.sys.mjs
=====================================
@@ -2,6 +2,8 @@
* 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/. */
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
/**
* @typedef {import("../uniffi-bindgen-gecko-js/components/generated/RustSearch.sys.mjs").SearchEngineSelector} RustSearchEngineSelector
* We use "Rust" above to avoid conflict with the class name for the JavaScript wrapper.
@@ -92,30 +94,15 @@ export class SearchEngineSelector {
return this._getConfigurationPromise;
}
- this._getConfigurationPromise = Promise.all([
- this._getConfiguration(),
- this._getConfigurationOverrides(),
- ]);
- let remoteSettingsData = await this._getConfigurationPromise;
- this._configuration = remoteSettingsData[0];
- this._configurationOverrides = remoteSettingsData[1];
- delete this._getConfigurationPromise;
-
- if (!this._configuration?.length) {
- throw Components.Exception(
- "Failed to get engine data from Remote Settings",
- Cr.NS_ERROR_UNEXPECTED
- );
- }
-
- if (!this._listenerAdded) {
- this._remoteConfig.on("sync", this._onConfigurationUpdated);
- this._remoteConfigOverrides.on(
- "sync",
- this._onConfigurationOverridesUpdated
- );
- this._listenerAdded = true;
- }
+ let { promise, resolve } = Promise.withResolvers();
+ this._getConfigurationPromise = promise;
+ this._configuration = await (
+ await fetch(
+ "chrome://global/content/search/base-browser-search-engines.json"
+ )
+ ).json();
+ this._configurationOverrides = [];
+ resolve(this._configuration);
if (lazy.SearchUtils.rustSelectorFeatureGate) {
this.#selector.setSearchConfig(
@@ -242,6 +229,12 @@ export class SearchEngineSelector {
* The new configuration object
*/
_onConfigurationUpdated({ data: { current } }) {
+ // tor-browser#43525: Even though RemoteSettings are a no-op for us, we do
+ // not want them to interfere in any way.
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return;
+ }
+
this._configuration = current;
if (lazy.SearchUtils.rustSelectorFeatureGate) {
@@ -268,6 +261,12 @@ export class SearchEngineSelector {
* The new configuration object
*/
_onConfigurationOverridesUpdated({ data: { current } }) {
+ // tor-browser#43525: Even though RemoteSettings are a no-op for us, we do
+ // not want them to interfere in any way.
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return;
+ }
+
this._configurationOverrides = current;
if (lazy.SearchUtils.rustSelectorFeatureGate) {
=====================================
toolkit/components/search/SearchService.sys.mjs
=====================================
@@ -25,7 +25,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
Region: "resource://gre/modules/Region.sys.mjs",
RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
SearchEngine: "moz-src:///toolkit/components/search/SearchEngine.sys.mjs",
- // eslint-disable-next-line mozilla/valid-lazy
SearchEngineSelector:
"moz-src:///toolkit/components/search/SearchEngineSelector.sys.mjs",
SearchSettings: "moz-src:///toolkit/components/search/SearchSettings.sys.mjs",
@@ -579,7 +578,11 @@ export class SearchService {
// Test-only function to reset just the engine selector so that it can
// load a different configuration.
- resetEngineSelector() {}
+ resetEngineSelector() {
+ this.#engineSelector = new lazy.SearchEngineSelector(
+ this.#handleConfigurationUpdated.bind(this)
+ );
+ }
resetToAppDefaultEngine() {
let appDefaultEngine = this.appDefaultEngine;
@@ -1420,6 +1423,10 @@ export class SearchService {
// We need to catch the region being updated during initialization so we
// start listening straight away.
Services.obs.addObserver(this, lazy.Region.REGION_TOPIC);
+
+ this.#engineSelector = new lazy.SearchEngineSelector(
+ this.#handleConfigurationUpdated.bind(this)
+ );
}
/**
@@ -1652,7 +1659,6 @@ export class SearchService {
* Handles the search configuration being - adds a wait on the user
* being idle, before the search engine update gets handled.
*/
- // eslint-disable-next-line no-unused-private-class-members
#handleConfigurationUpdated() {
if (this.#queuedIdle) {
return;
@@ -2622,12 +2628,21 @@ export class SearchService {
// This is prefixed with _ rather than # because it is
// called in test_remove_engine_notification_box.js
async _fetchEngineSelectorEngines() {
- const engines = await (
- await fetch(
- "chrome://global/content/search/mullvadBrowserSearchEngines.json"
- )
- ).json();
- return { engines, privateDefault: undefined };
+ let searchEngineSelectorProperties = {
+ locale: Services.locale.appLocaleAsBCP47,
+ region: lazy.Region.home || "unknown",
+ channel: lazy.SearchUtils.MODIFIED_APP_CHANNEL,
+ experiment: this._experimentPrefValue,
+ distroID: lazy.SearchUtils.distroID ?? "",
+ };
+
+ for (let [key, value] of Object.entries(searchEngineSelectorProperties)) {
+ this._settings.setMetaDataAttribute(key, value);
+ }
+
+ return this.#engineSelector.fetchEngineConfiguration(
+ searchEngineSelectorProperties
+ );
}
#setDefaultFromSelector(refinedConfig) {
=====================================
toolkit/components/search/content/mullvadBrowserSearchEngineIcons.json → toolkit/components/search/content/base-browser-search-engine-icons.json
=====================================
@@ -1,27 +1,33 @@
{
"ddg": [
- { "url": "chrome://global/content/search/duckduckgo.ico", "iconSize": 32 }
+ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 }
],
"ddg-html": [
- { "url": "chrome://global/content/search/duckduckgo.ico", "iconSize": 32 }
+ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 }
],
"mullvad-leta": [
- { "url": "chrome://global/content/search/mullvad-leta.svg", "iconSize": 16 }
+ {
+ "url": "chrome://global/content/search/mullvad-leta.svg",
+ "imageSize": 16
+ }
],
"mojeek": [
- { "url": "chrome://global/content/search/mojeek.ico", "iconSize": 32 }
+ { "url": "chrome://global/content/search/mojeek.ico", "imageSize": 32 }
],
"brave": [
- { "url": "chrome://global/content/search/brave.svg", "iconSize": 16 }
+ { "url": "chrome://global/content/search/brave.svg", "imageSize": 16 }
],
"startpage": [
{
"url": "chrome://global/content/search/startpage-16.png",
- "iconSize": 16
+ "imageSize": 16
},
- { "url": "chrome://global/content/search/startpage-32.png", "iconSize": 32 }
+ {
+ "url": "chrome://global/content/search/startpage-32.png",
+ "imageSize": 32
+ }
],
"metager": [
- { "url": "chrome://global/content/search/metager.ico", "iconSize": 196 }
+ { "url": "chrome://global/content/search/metager.ico", "imageSize": 196 }
]
}
=====================================
toolkit/components/search/content/base-browser-search-engines.json
=====================================
@@ -0,0 +1,133 @@
+[
+ {
+ "base": {
+ "aliases": ["mullvad-leta", "leta", "mullvad", "ml"],
+ "classification": "general",
+ "name": "Mullvad Leta",
+ "urls": {
+ "search": {
+ "base": "https://leta.mullvad.net/",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "ee88d691-6d7a-4adb-9fec-5a205565505a",
+ "identifier": "mullvad-leta",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["duckduckgo", "ddg"],
+ "classification": "general",
+ "name": "DuckDuckGo",
+ "urls": {
+ "search": {
+ "base": "https://duckduckgo.com/",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "04e99a38-13ee-47d8-8aa4-64482b3dea99",
+ "identifier": "ddg",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["ddg-html", "duckduckgohtml", "ddgh"],
+ "classification": "general",
+ "name": "DuckDuckGo (HTML)",
+ "urls": {
+ "search": {
+ "base": "https://html.duckduckgo.com/html/",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "98d8c84b-7455-431d-98b9-890e7bcc0041",
+ "identifier": "ddg-html",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["mojeek", "mj"],
+ "classification": "general",
+ "name": "Mojeek",
+ "urls": {
+ "search": {
+ "base": "https://www.mojeek.com/search",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "10df12ac-2b39-4aa9-8845-d5b35d5bb70c",
+ "identifier": "mojeek",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["brave", "bv"],
+ "classification": "general",
+ "name": "Brave Search",
+ "urls": {
+ "search": {
+ "base": "https://search.brave.com/search",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "f479314b-030b-49a8-a2fe-7e1c5d1d9071",
+ "identifier": "brave",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["startpage", "sp"],
+ "classification": "general",
+ "name": "Startpage",
+ "urls": {
+ "search": {
+ "base": "https://www.startpage.com/sp/search",
+ "params": [],
+ "searchTermParamName": "q"
+ }
+ }
+ },
+ "id": "927bbd9f-b2f3-48b4-8974-1c1148028f4d",
+ "identifier": "startpage",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "base": {
+ "aliases": ["metager", "mg"],
+ "classification": "general",
+ "name": "MetaGer",
+ "urls": {
+ "search": {
+ "base": "https://metager.org/meta/meta.ger3",
+ "params": [],
+ "searchTermParamName": "eingabe"
+ }
+ }
+ },
+ "id": "a9d07d93-469c-4bf4-8dd1-fa137f1cc85f",
+ "identifier": "metager",
+ "recordType": "engine",
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
+ },
+ {
+ "recordType": "defaultEngines",
+ "globalDefault": "mullvad-leta",
+ "globalDefaultPrivate": "mullvad-leta"
+ }
+]
=====================================
toolkit/components/search/content/mullvadBrowserSearchEngines.json deleted
=====================================
@@ -1,114 +0,0 @@
-[
- {
- "aliases": ["mullvad-leta", "leta", "mullvad", "ml"],
- "name": "Mullvad Leta",
- "urls": {
- "search": {
- "base": "https://leta.mullvad.net/",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "ee88d691-6d7a-4adb-9fec-5a205565505a",
- "identifier": "mullvad-leta",
- "recordType": "engine",
- "orderHint": 100,
- "variants": []
- },
- {
- "aliases": ["duckduckgo", "ddg"],
- "name": "DuckDuckGo",
- "urls": {
- "search": {
- "base": "https://duckduckgo.com/",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "04e99a38-13ee-47d8-8aa4-64482b3dea99",
- "identifier": "ddg",
- "recordType": "engine",
- "orderHint": 90,
- "variants": []
- },
- {
- "aliases": ["ddg-html", "duckduckgohtml", "ddgh"],
- "name": "DuckDuckGo (HTML)",
- "urls": {
- "search": {
- "base": "https://html.duckduckgo.com/html/",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "98d8c84b-7455-431d-98b9-890e7bcc0041",
- "identifier": "ddg-html",
- "recordType": "engine",
- "orderHint": 80,
- "variants": []
- },
- {
- "aliases": ["mojeek", "mj"],
- "name": "Mojeek",
- "urls": {
- "search": {
- "base": "https://www.mojeek.com/search",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "10df12ac-2b39-4aa9-8845-d5b35d5bb70c",
- "identifier": "mojeek",
- "recordType": "engine",
- "orderHint": 70,
- "variants": []
- },
- {
- "aliases": ["brave", "bv"],
- "name": "Brave Search",
- "urls": {
- "search": {
- "base": "https://search.brave.com/search",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "f479314b-030b-49a8-a2fe-7e1c5d1d9071",
- "identifier": "brave",
- "recordType": "engine",
- "orderHint": 60,
- "variants": []
- },
- {
- "aliases": ["startpage", "sp"],
- "name": "Startpage",
- "urls": {
- "search": {
- "base": "https://www.startpage.com/sp/search",
- "params": [],
- "searchTermParamName": "q"
- }
- },
- "id": "049f86fd-28fe-4389-910f-aac28f07d745",
- "identifier": "startpage",
- "recordType": "engine",
- "orderHint": 50,
- "variants": []
- },
- {
- "aliases": ["metager", "mg"],
- "name": "MetaGer",
- "urls": {
- "search": {
- "base": "https://metager.org/meta/meta.ger3",
- "params": [],
- "searchTermParamName": "eingabe"
- }
- },
- "id": "a9d07d93-469c-4bf4-8dd1-fa137f1cc85f",
- "identifier": "metager",
- "recordType": "engine",
- "orderHint": 40,
- "variants": []
- }
-]
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/ac…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/ac…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][tor-browser-140.2.0esr-15.0-1] 3 commits: dropme! TB 42891: Set the bundled search engine for Tor Browser.
by Pier Angelo Vendrame (@pierov) 08 Sep '25
by Pier Angelo Vendrame (@pierov) 08 Sep '25
08 Sep '25
Pier Angelo Vendrame pushed to branch tor-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
2404a7c1 by Pier Angelo Vendrame at 2025-09-08T11:39:58+02:00
dropme! TB 42891: Set the bundled search engine for Tor Browser.
BB 43525: Skip Remote Settings for search engine customization.
Undo some changes to this commit, as they need to be moved to Base
Browser.
- - - - -
10cd8e31 by Pier Angelo Vendrame at 2025-09-08T11:39:58+02:00
BB 43525: Skip Remote Settings for search engine customization.
Also, add some bundled search engines.
- - - - -
d28d9f49 by Pier Angelo Vendrame at 2025-09-08T11:39:59+02:00
amend! TB 42891: Set the bundled search engine for Tor Browser.
TB 42891: Set the bundled search engine for Tor Browser.
- - - - -
4 changed files:
- toolkit/components/search/AppProvidedSearchEngine.sys.mjs
- toolkit/components/search/SearchEngineSelector.sys.mjs
- toolkit/components/search/content/torBrowserSearchEngineIcons.json → toolkit/components/search/content/base-browser-search-engine-icons.json
- toolkit/components/search/content/torBrowserSearchEngines.json → toolkit/components/search/content/base-browser-search-engines.json
Changes:
=====================================
toolkit/components/search/AppProvidedSearchEngine.sys.mjs
=====================================
@@ -116,8 +116,10 @@ class IconHandler {
await this.#buildIconMap();
}
- return this.#iconMap.get(engineIdentifier);
- // eslint-disable-next-line no-unreachable
+ if (AppConstants.BASE_BROWSER_VERSION) {
+ return this.#iconMap.get(engineIdentifier);
+ }
+
let iconList = this.#iconMap.get(this.getKey(engineIdentifier)) || [];
return iconList.filter(r =>
this.#identifierMatches(engineIdentifier, r.engineIdentifiers)
@@ -223,7 +225,7 @@ class IconHandler {
Object.entries(
await (
await fetch(
- "chrome://global/content/search/torBrowserSearchEngineIcons.json"
+ "chrome://global/content/search/base-browser-search-engine-icons.json"
)
).json()
)
=====================================
toolkit/components/search/SearchEngineSelector.sys.mjs
=====================================
@@ -97,7 +97,9 @@ export class SearchEngineSelector {
let { promise, resolve } = Promise.withResolvers();
this._getConfigurationPromise = promise;
this._configuration = await (
- await fetch("chrome://global/content/search/torBrowserSearchEngines.json")
+ await fetch(
+ "chrome://global/content/search/base-browser-search-engines.json"
+ )
).json();
this._configurationOverrides = [];
resolve(this._configuration);
=====================================
toolkit/components/search/content/torBrowserSearchEngineIcons.json → toolkit/components/search/content/base-browser-search-engine-icons.json
=====================================
@@ -1,15 +1,9 @@
{
"ddg": [
- {
- "url": "chrome://global/content/search/duckduckgo.ico",
- "imageSize": 32
- }
+ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 }
],
"ddg-onion": [
- {
- "url": "chrome://global/content/search/duckduckgo.ico",
- "imageSize": 32
- }
+ { "url": "chrome://global/content/search/duckduckgo.ico", "imageSize": 32 }
],
"startpage": [
{
@@ -32,9 +26,6 @@
}
],
"wikipedia": [
- {
- "url": "chrome://global/content/search/wikipedia.ico",
- "imageSize": 32
- }
+ { "url": "chrome://global/content/search/wikipedia.ico", "imageSize": 32 }
]
}
=====================================
toolkit/components/search/content/torBrowserSearchEngines.json → toolkit/components/search/content/base-browser-search-engines.json
=====================================
@@ -15,13 +15,7 @@
"id": "04e99a38-13ee-47d8-8aa4-64482b3dea99",
"identifier": "ddg",
"recordType": "engine",
- "variants": [
- {
- "environment": {
- "allRegionsAndLocales": true
- }
- }
- ]
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
},
{
"base": {
@@ -39,13 +33,7 @@
"id": "1e431da4-a60c-4411-9251-a95a841d451f",
"identifier": "ddg-onion",
"recordType": "engine",
- "variants": [
- {
- "environment": {
- "allRegionsAndLocales": true
- }
- }
- ]
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
},
{
"base": {
@@ -63,13 +51,7 @@
"id": "927bbd9f-b2f3-48b4-8974-1c1148028f4d",
"identifier": "startpage",
"recordType": "engine",
- "variants": [
- {
- "environment": {
- "allRegionsAndLocales": true
- }
- }
- ]
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
},
{
"base": {
@@ -87,13 +69,7 @@
"id": "e7eaba8d-6b9e-43fb-a799-b01b096c03ff",
"identifier": "startpage-onion",
"recordType": "engine",
- "variants": [
- {
- "environment": {
- "allRegionsAndLocales": true
- }
- }
- ]
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
},
{
"base": {
@@ -111,13 +87,7 @@
"id": "7f6d23c2-191e-483e-af3a-ce6451e3a8dd",
"identifier": "wikipedia",
"recordType": "engine",
- "variants": [
- {
- "environment": {
- "allRegionsAndLocales": true
- }
- }
- ]
+ "variants": [{ "environment": { "allRegionsAndLocales": true } }]
},
{
"recordType": "defaultEngines",
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d244ff…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/d244ff…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/mullvad-browser][mullvad-browser-140.2.0esr-15.0-1] BB 43664: Automatically check the PBM checkbox when in always-on PBM.
by Pier Angelo Vendrame (@pierov) 05 Sep '25
by Pier Angelo Vendrame (@pierov) 05 Sep '25
05 Sep '25
Pier Angelo Vendrame pushed to branch mullvad-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
ac67b549 by Pier Angelo Vendrame at 2025-09-05T18:56:43+02:00
BB 43664: Automatically check the PBM checkbox when in always-on PBM.
- - - - -
1 changed file:
- browser/base/content/browser-addons.js
Changes:
=====================================
browser/base/content/browser-addons.js
=====================================
@@ -20,6 +20,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.sys.mjs",
OriginControls: "resource://gre/modules/ExtensionPermissions.sys.mjs",
PERMISSION_L10N: "resource://gre/modules/ExtensionPermissionMessages.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
SITEPERMS_ADDON_TYPE:
"resource://gre/modules/addons/siteperms-addon-utils.sys.mjs",
});
@@ -466,7 +467,9 @@ customElements.define(
this.notification.options.customElementOptions;
let checkboxEl = this.ownerDocument.createElement("moz-checkbox");
- checkboxEl.checked = grantPrivateBrowsingAllowed;
+ checkboxEl.checked =
+ grantPrivateBrowsingAllowed ||
+ lazy.PrivateBrowsingUtils.permanentPrivateBrowsing;
checkboxEl.addEventListener("change", () => {
// NOTE: the popupnotification instances will be reused
// and so the callback function is destructured here to
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/ac6…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/ac6…
You're receiving this email because of your account on gitlab.torproject.org.
1
0

[Git][tpo/applications/tor-browser][base-browser-140.2.0esr-15.0-1] BB 43664: Automatically check the PBM checkbox when in always-on PBM.
by Pier Angelo Vendrame (@pierov) 05 Sep '25
by Pier Angelo Vendrame (@pierov) 05 Sep '25
05 Sep '25
Pier Angelo Vendrame pushed to branch base-browser-140.2.0esr-15.0-1 at The Tor Project / Applications / Tor Browser
Commits:
d0b3fa67 by Pier Angelo Vendrame at 2025-09-05T18:56:10+02:00
BB 43664: Automatically check the PBM checkbox when in always-on PBM.
- - - - -
1 changed file:
- browser/base/content/browser-addons.js
Changes:
=====================================
browser/base/content/browser-addons.js
=====================================
@@ -20,6 +20,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.sys.mjs",
OriginControls: "resource://gre/modules/ExtensionPermissions.sys.mjs",
PERMISSION_L10N: "resource://gre/modules/ExtensionPermissionMessages.sys.mjs",
+ PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
SITEPERMS_ADDON_TYPE:
"resource://gre/modules/addons/siteperms-addon-utils.sys.mjs",
});
@@ -466,7 +467,9 @@ customElements.define(
this.notification.options.customElementOptions;
let checkboxEl = this.ownerDocument.createElement("moz-checkbox");
- checkboxEl.checked = grantPrivateBrowsingAllowed;
+ checkboxEl.checked =
+ grantPrivateBrowsingAllowed ||
+ lazy.PrivateBrowsingUtils.permanentPrivateBrowsing;
checkboxEl.addEventListener("change", () => {
// NOTE: the popupnotification instances will be reused
// and so the callback function is destructured here to
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/d0b3fa6…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/d0b3fa6…
You're receiving this email because of your account on gitlab.torproject.org.
1
0