tbb-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- 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
August 2026
- 1 participants
- 182 discussions
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.1.0esr-16.0-1] 3 commits: fixup! BB 40925: Implemented the Security Level component
by morgan (@morgan) 24 Aug '26
by morgan (@morgan) 24 Aug '26
24 Aug '26
morgan pushed to branch mullvad-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
12a5b451 by Henry Wilkes at 2026-08-24T12:22:50+00:00
fixup! BB 40925: Implemented the Security Level component
BB 45201: Move security level settings to the settings config.
- - - - -
893c9384 by Henry Wilkes at 2026-08-24T12:22:54+00:00
fixup! Base Browser strings
BB 45201: Update security level setting strings.
- - - - -
63592373 by Henry Wilkes at 2026-08-24T12:23:39+00:00
BB 45201: Customize moz- input widgets for Base Browser.
- - - - -
21 changed files:
- browser/components/preferences/config/privacy.mjs
- browser/components/preferences/preferences.js
- browser/components/preferences/preferences.xhtml
- browser/components/preferences/privacy.inc.xhtml
- browser/components/preferences/privacy.js
- − browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs
- + browser/components/securitylevel/config/security-level.mjs
- browser/components/securitylevel/content/securityLevel.js
- + browser/components/securitylevel/content/securityLevelDialog.css
- browser/components/securitylevel/content/securityLevelDialog.js
- browser/components/securitylevel/content/securityLevelDialog.xhtml
- − browser/components/securitylevel/content/securityLevelPreferences.css
- − browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
- browser/components/securitylevel/jar.mn
- browser/components/securitylevel/moz.build
- + browser/components/securitylevel/widgets/security-level-description.css
- + browser/components/securitylevel/widgets/security-level-description.mjs
- + browser/components/securitylevel/widgets/security-level-display.css
- + browser/components/securitylevel/widgets/security-level-display.mjs
- toolkit/content/widgets/lit-utils.mjs
- toolkit/locales/en-US/toolkit/global/base-browser.ftl
Changes:
=====================================
browser/components/preferences/config/privacy.mjs
=====================================
@@ -7,6 +7,10 @@
import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
+ChromeUtils.importESModule(
+ "chrome://browser/content/securitylevel/config/security-level.mjs",
+ { global: "current" }
+);
ChromeUtils.importESModule(
"chrome://browser/content/preferences/config/protections-from-apps.mjs",
{ global: "current" }
=====================================
browser/components/preferences/preferences.js
=====================================
@@ -397,6 +397,7 @@ const CONFIG_PANES = Object.freeze({
"ipprotection",
"cookiesAndSiteData2",
"history2",
+ "securityLevelGroup",
"nonTechnicalPrivacy2",
"dnsOverHttps",
"connectionLink",
=====================================
browser/components/preferences/preferences.xhtml
=====================================
@@ -43,7 +43,6 @@
href="chrome://browser/content/preferences/letterboxing.css"
/>
- <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelPreferences.css" />
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/browser.ftl"/>
@@ -106,6 +105,8 @@
<script type="module" src="chrome://browser/content/preferences/widgets/update-information.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/update-state.mjs"></script>
<script type="module" src="chrome://browser/content/ipprotection/bandwidth-usage.mjs"></script>
+ <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"></script>
+ <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-display.mjs"></script>
</head>
<html:body xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
=====================================
browser/components/preferences/privacy.inc.xhtml
=====================================
@@ -578,7 +578,7 @@
<html:h1 data-l10n-id="security-header"/>
</hbox>
-#include ../securitylevel/content/securityLevelPreferences.inc.xhtml
+<html:setting-group groupid="securityLevelGroup" data-category="panePrivacy" hidden="true" data-srd-migrated=""></html:setting-group>
<!-- addons, forgery (phishing) UI Security -->
<html:setting-group groupid="browsingProtection" data-category="panePrivacy" hidden="true" data-hidden-from-search="true" data-srd-migrated=""></html:setting-group>
=====================================
browser/components/preferences/privacy.js
=====================================
@@ -60,13 +60,6 @@ ChromeUtils.defineLazyGetter(lazy, "gParentalControlsService", () =>
: null
);
-// TODO: module import via ChromeUtils.defineModuleGetter
-XPCOMUtils.defineLazyScriptGetter(
- this,
- ["SecurityLevelPreferences"],
- "chrome://browser/content/securitylevel/securityLevel.js"
-);
-
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gIsFirstPartyIsolated",
@@ -150,16 +143,6 @@ function initTCPStandardSection() {
var gPrivacyPane = {
_pane: null,
- /**
- * Show the Security Level UI
- */
- _initSecurityLevel() {
- SecurityLevelPreferences.init();
- window.addEventListener("unload", () => SecurityLevelPreferences.uninit(), {
- once: true,
- });
- },
-
/**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
@@ -653,6 +636,7 @@ var gPrivacyPane = {
initSettingGroup("etpReset");
initSettingGroup("etpCustomize");
initSettingGroup("networkProxy");
+ initSettingGroup("securityLevelGroup");
/* Initialize Content Blocking */
this.initContentBlocking();
@@ -662,7 +646,6 @@ var gPrivacyPane = {
this.networkCookieBehaviorReadPrefs();
this._initTrackingProtectionExtensionControl();
this._ensureTrackingProtectionExceptionListMigration();
- this._initSecurityLevel();
Preferences.get("privacy.trackingprotection.enabled").on(
"change",
=====================================
browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs deleted
=====================================
@@ -1,73 +0,0 @@
-/**
- * Common methods for the desktop security level components.
- */
-export const SecurityLevelUIUtils = {
- /**
- * Create an element that gives a description of the security level. To be
- * used in the settings.
- *
- * @param {string} level - The security level to describe.
- * @param {Document} doc - The document where the element will be inserted.
- *
- * @returns {Element} - The newly created element.
- */
- createDescriptionElement(level, doc) {
- const el = doc.createElement("div");
- el.classList.add("security-level-description");
-
- let l10nIdSummary;
- let bullets;
- switch (level) {
- case "standard":
- l10nIdSummary = "security-level-summary-standard";
- break;
- case "safer":
- l10nIdSummary = "security-level-summary-safer";
- bullets = [
- "security-level-preferences-bullet-https-only-javascript",
- "security-level-preferences-bullet-limit-font-and-symbols",
- "security-level-preferences-bullet-limit-media",
- ];
- break;
- case "safest":
- l10nIdSummary = "security-level-summary-safest";
- bullets = [
- "security-level-preferences-bullet-disabled-javascript",
- "security-level-preferences-bullet-limit-font-and-symbols-and-images",
- "security-level-preferences-bullet-limit-media",
- ];
- break;
- case "custom":
- l10nIdSummary = "security-level-summary-custom";
- break;
- default:
- throw Error(`Unhandled level: ${level}`);
- }
-
- const summaryEl = doc.createElement("div");
- summaryEl.classList.add("security-level-summary");
- doc.l10n.setAttributes(summaryEl, l10nIdSummary);
-
- el.append(summaryEl);
-
- if (!bullets) {
- return el;
- }
-
- const listEl = doc.createElement("ul");
- listEl.classList.add("security-level-description-extra");
- // Add a mozilla styling class as well:
- listEl.classList.add("privacy-extra-information");
- for (const l10nId of bullets) {
- const bulletEl = doc.createElement("li");
- bulletEl.classList.add("security-level-description-bullet");
-
- doc.l10n.setAttributes(bulletEl, l10nId);
-
- listEl.append(bulletEl);
- }
-
- el.append(listEl);
- return el;
- },
-};
=====================================
browser/components/securitylevel/config/security-level.mjs
=====================================
@@ -0,0 +1,81 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
+import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ SecurityLevelPrefs:
+ "moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
+});
+
+SettingGroupManager.registerGroups({
+ securityLevelGroup: {
+ subcategory: "securitylevel",
+ l10nId: "security-level-settings-group",
+ headingLevel: 2,
+ supportPage: "tor-manual:features__security-levels",
+ items: [
+ {
+ id: "securityLevelBoxGroup",
+ control: "moz-box-group",
+ items: [
+ {
+ id: "securityLevelCurrent",
+ control: "security-level-display",
+ },
+ {
+ id: "securityLevelChangeButton",
+ l10nId: "security-level-settings-change-button",
+ control: "moz-box-button",
+ },
+ ],
+ },
+ ],
+ },
+});
+
+Preferences.addSetting({
+ id: "securityLevelCurrent",
+ setup(emitChange) {
+ Services.prefs.addObserver(
+ "browser.security_level.security_slider",
+ emitChange
+ );
+ Services.prefs.addObserver(
+ "browser.security_level.security_custom",
+ emitChange
+ );
+
+ return () => {
+ Services.prefs.removeObserver(
+ "browser.security_level.security_slider",
+ emitChange
+ );
+ Services.prefs.removeObserver(
+ "browser.security_level.security_custom",
+ emitChange
+ );
+ };
+ },
+ get: () => {
+ return lazy.SecurityLevelPrefs.securityLevelSummary;
+ },
+});
+
+Preferences.addSetting({
+ id: "securityLevelBoxGroup",
+});
+
+Preferences.addSetting({
+ id: "securityLevelChangeButton",
+ onUserClick() {
+ window.gSubDialog.open(
+ "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
+ { features: "resizable=yes" }
+ );
+ },
+});
=====================================
browser/components/securitylevel/content/securityLevel.js
=====================================
@@ -5,8 +5,6 @@
ChromeUtils.defineESModuleGetters(this, {
SecurityLevelPrefs:
"moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
- SecurityLevelUIUtils:
- "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs",
});
/*
@@ -263,103 +261,3 @@ var SecurityLevelPanel = {
}
},
}; /* SecurityLevelPanel */
-
-/*
- Security Level Preferences Code
-
- Code to handle init and update of security level section in about:preferences#privacy
-*/
-
-var SecurityLevelPreferences = {
- _securityPrefsBranch: null,
-
- /**
- * The element that shows the current security level.
- *
- * @type {?Element}
- */
- _currentEl: null,
-
- _populateXUL() {
- this._currentEl = document.getElementById("security-level-current");
- const changeButton = document.getElementById("security-level-change");
- const badgeEl = this._currentEl.querySelector(
- ".security-level-current-badge"
- );
-
- for (const { level, nameId } of [
- { level: "standard", nameId: "security-level-panel-level-standard" },
- { level: "safer", nameId: "security-level-panel-level-safer" },
- { level: "safest", nameId: "security-level-panel-level-safest" },
- { level: "custom", nameId: "security-level-panel-level-custom" },
- ]) {
- // Classes that control visibility:
- // security-level-current-standard
- // security-level-current-safer
- // security-level-current-safest
- // security-level-current-custom
- const visibilityClass = `security-level-current-${level}`;
- const nameEl = document.createElement("div");
- nameEl.classList.add("security-level-name", visibilityClass);
- document.l10n.setAttributes(nameEl, nameId);
-
- const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
- level,
- document
- );
- descriptionEl.classList.add(visibilityClass);
-
- this._currentEl.insertBefore(nameEl, badgeEl);
- this._currentEl.insertBefore(descriptionEl, changeButton);
- }
-
- changeButton.addEventListener("click", () => {
- this._openDialog();
- });
- },
-
- _openDialog() {
- gSubDialog.open(
- "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
- { features: "resizable=yes" }
- );
- },
-
- _configUIFromPrefs() {
- // Set a data-current-level attribute for showing the current security
- // level, and hiding the rest.
- this._currentEl.dataset.currentLevel =
- SecurityLevelPrefs.securityLevelSummary;
- },
-
- init() {
- // populate XUL with localized strings
- this._populateXUL();
-
- // read prefs and populate UI
- this._configUIFromPrefs();
-
- // register for pref chagnes
- this._securityPrefsBranch = Services.prefs.getBranch(
- "browser.security_level."
- );
- this._securityPrefsBranch.addObserver("", this);
- },
-
- uninit() {
- // unregister for pref change events
- this._securityPrefsBranch.removeObserver("", this);
- this._securityPrefsBranch = null;
- },
-
- // callback for when prefs change
- observe(subject, topic, data) {
- switch (topic) {
- case "nsPref:changed":
- if (data == "security_slider" || data == "security_custom") {
- this._configUIFromPrefs();
- }
- break;
- }
- },
-}; /* SecurityLevelPreferences */
=====================================
browser/components/securitylevel/content/securityLevelDialog.css
=====================================
@@ -0,0 +1,29 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+/* Hack to gain the internal styling of <moz-badge>.
+ * TODO: Drop this once we can use moz-badge. tor-browser#45229. */
+@import url("chrome://global/content/elements/moz-badge.css");
+
+#security-level-radiogroup {
+ margin-block: var(--space-large) var(--space-xlarge);
+}
+
+.security-level-radio-label {
+ display: inline flex;
+ gap: var(--space-small);
+}
+
+.security-level-radio-label .moz-badge-label > span {
+ /* Still accessible to screen reader, but not visual.
+ * Keep inline, but with no layout width. */
+ display: inline-block;
+ width: 1px;
+ margin-inline-end: -1px;
+ clip-path: inset(50%);
+}
+
+.moz-badge[hidden] {
+ display: none;
+}
=====================================
browser/components/securitylevel/content/securityLevelDialog.js
=====================================
@@ -3,9 +3,6 @@
const { SecurityLevelPrefs } = ChromeUtils.importESModule(
"moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs"
);
-const { SecurityLevelUIUtils } = ChromeUtils.importESModule(
- "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs"
-);
const gSecurityLevelDialog = {
/**
@@ -27,9 +24,9 @@ const gSecurityLevelDialog = {
*/
_radiogroup: null,
/**
- * A list of radio options and their containers.
+ * A list of radio options and their descriptions.
*
- * @type {?Array<{ container: Element, radio: Element }>}
+ * @type {?Array<{ description: Element, radio: Element }>}
*/
_radioOptions: null,
@@ -56,85 +53,42 @@ const gSecurityLevelDialog = {
this._radiogroup = document.getElementById("security-level-radiogroup");
this._radioOptions = Array.from(
- this._radiogroup.querySelectorAll(".security-level-radio-container"),
- container => {
- return {
- container,
- radio: container.querySelector(".security-level-radio"),
- };
+ this._radiogroup.querySelectorAll("moz-radio"),
+ radio => {
+ const description = radio.querySelector("security-level-description");
+ // Hide bullets by default.
+ description.hideBullets = true;
+ return { radio, description };
}
);
- for (const { container, radio } of this._radioOptions) {
- const level = radio.value;
- radio.id = `security-level-radio-${level}`;
- const currentEl = container.querySelector(
- ".security-level-current-badge"
- );
- currentEl.id = `security-level-current-badge-${level}`;
- const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
- level,
- document
- );
- descriptionEl.classList.add("indent");
- descriptionEl.id = `security-level-description-${level}`;
-
- // Wait for the full translation of the element before adding it to the
- // DOM. In particular, we want to make sure the elements have text before
- // we measure the maxHeight below.
- await document.l10n.translateFragment(descriptionEl);
- document.l10n.pauseObserving();
- container.append(descriptionEl);
- document.l10n.resumeObserving();
-
- if (level === this._prevLevel) {
- currentEl.hidden = false;
- // When the currentEl is visible, include it in the accessible name for
- // the radio option.
- // NOTE: The currentEl has an accessible name which includes punctuation
- // to help separate it's content from the security level name.
- // E.g. "Standard (Current level)".
- radio.setAttribute("aria-labelledby", `${radio.id} ${currentEl.id}`);
- } else {
- currentEl.hidden = true;
- }
- // We point the accessible description to the wrapping
- // .security-level-description element, rather than its children
- // that define the actual text content. This means that when the
- // privacy-extra-information is shown or hidden, its text content is
- // included or excluded from the accessible description, respectively.
- radio.setAttribute("aria-describedby", descriptionEl.id);
+ for (const { radio } of this._radioOptions) {
+ radio.querySelector(".moz-badge").hidden =
+ radio.value !== this._prevLevel;
}
- // We want to reserve the maximum height of the radiogroup so that the
+ // We want to reserve the maximum height of the moz-radio-group so that the
// dialog has enough height when the user switches options. So we cycle
// through the options and measure the height when they are selected to set
// a minimum height that fits all of them.
- // NOTE: At the time of implementation, at this point the dialog may not
- // yet have the "subdialog" attribute, which means it is missing the
- // common.css stylesheet from its shadow root, which effects the size of the
- // .radio-check element and the font. Therefore, we have duplicated the
- // import of common.css in SecurityLevelDialog.xhtml to ensure it is applied
- // at this earlier stage.
let maxHeight = 0;
- for (const { container } of this._radioOptions) {
- container.classList.add("selected");
+ for (const { description } of this._radioOptions) {
+ description.hideBullets = false;
+ await this._settled();
maxHeight = Math.max(
maxHeight,
this._radiogroup.getBoundingClientRect().height
);
- container.classList.remove("selected");
+ description.hideBullets = true;
}
this._radiogroup.style.minHeight = `${maxHeight}px`;
if (this._prevLevel !== "custom") {
this._selectedLevel = this._prevLevel;
this._radiogroup.value = this._prevLevel;
- } else {
- this._radiogroup.selectedItem = null;
}
- this._radiogroup.addEventListener("select", () => {
+ this._radiogroup.addEventListener("change", () => {
this._selectedLevel = this._radiogroup.value;
this._updateSelected();
});
@@ -142,16 +96,31 @@ const gSecurityLevelDialog = {
this._updateSelected();
},
+ /**
+ * Wait for the DOM to be settled after some change.
+ */
+ async _settled() {
+ // Wait for the widgets to react to some change.
+ await Promise.all([
+ this._radiogroup.updateComplete,
+ ...this._radioOptions.map(({ radio }) => radio.updateComplete),
+ ]);
+ // Also wait for any string population.
+ if (document.hasPendingL10nMutations) {
+ await new Promise(r =>
+ document.addEventListener("L10nMutationsFinished", r, { once: true })
+ );
+ }
+ },
+
/**
* Update the UI in response to a change in selection.
*/
_updateSelected() {
this._acceptButton.disabled =
!this._selectedLevel || this._selectedLevel === this._prevLevel;
- // Have the container's `selected` CSS class match the selection state of
- // the radio elements.
- for (const { container, radio } of this._radioOptions) {
- container.classList.toggle("selected", radio.selected);
+ for (const { description, radio } of this._radioOptions) {
+ description.hideBullets = !radio.checked;
}
},
=====================================
browser/components/securitylevel/content/securityLevelDialog.xhtml
=====================================
@@ -10,18 +10,6 @@
<dialog id="security-level-dialog" buttons="accept,cancel">
<linkset>
<html:link rel="stylesheet" href="chrome://global/skin/global.css" />
- <!-- NOTE: We include common.css explicitly, rather than relying on
- - the dialog's shadowroot importing it, which is late loaded in
- - response to the dialog's "subdialog" attribute, which is set
- - in response to DOMFrameContentLoaded.
- - In particular, we need the .radio-check rule and font rules from
- - common-shared.css to be in place when gSecurityLevelDialog.init is
- - called, which will help ensure that the radio element has the correct
- - size when we measure its bounding box. -->
- <html:link
- rel="stylesheet"
- href="chrome://global/skin/in-content/common.css"
- />
<html:link
rel="stylesheet"
href="chrome://browser/skin/preferences/preferences.css"
@@ -32,57 +20,77 @@
/>
<html:link
rel="stylesheet"
- href="chrome://browser/content/securitylevel/securityLevelPreferences.css"
+ href="chrome://browser/content/securitylevel/securityLevelDialog.css"
/>
<html:link rel="localization" href="branding/brand.ftl" />
<html:link rel="localization" href="toolkit/global/base-browser.ftl" />
</linkset>
+ <html:script
+ type="module"
+ src="chrome://global/content/elements/moz-radio-group.mjs"
+ ></html:script>
+ <html:script
+ type="module"
+ src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"
+ ></html:script>
<script src="chrome://browser/content/securitylevel/securityLevelDialog.js" />
<description data-l10n-id="security-level-dialog-restart-description" />
- <radiogroup id="security-level-radiogroup" class="highlighting-group">
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ <moz-radio-group
+ xmlns="http://www.w3.org/1999/xhtml"
+ id="security-level-radiogroup"
+ data-l10n-id="security-level-dialog-radio-group"
+ >
+ <moz-radio value="standard" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-standard"></span>
+ <!-- TODO: Use <moz-badge> widget once bugzilla bug 2065204 is
+ - resolved. See tor-browser#45229. -->
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="standard"
- data-l10n-id="security-level-preferences-level-standard"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ ></security-level-description>
+ </moz-radio>
+ <moz-radio value="safer" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-safer"></span>
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="safer"
- data-l10n-id="security-level-preferences-level-safer"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ ></security-level-description>
+ </moz-radio>
+ <moz-radio value="safest" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-safest"></span>
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="safest"
- data-l10n-id="security-level-preferences-level-safest"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- </radiogroup>
+ ></security-level-description>
+ </moz-radio>
+ </moz-radio-group>
</dialog>
</window>
=====================================
browser/components/securitylevel/content/securityLevelPreferences.css deleted
=====================================
@@ -1,171 +0,0 @@
-.security-level-grid {
- display: grid;
- grid-template:
- "icon name badge button" min-content
- "icon summary summary button" auto
- "icon extra extra ." auto
- / max-content max-content 1fr max-content;
-}
-
-.security-level-icon {
- grid-area: icon;
- align-self: start;
- width: var(--icon-size-large);
- height: var(--icon-size-large);
- -moz-context-properties: fill, stroke;
- fill: var(--icon-color);
- stroke: var(--icon-color-warning);
- margin-block-start: var(--space-xsmall);
- margin-inline-end: var(--space-large);
-}
-
-:-moz-locale-dir(rtl) .security-level-icon {
- transform: scaleX(-1);
-}
-
-.security-level-current-badge {
- grid-area: badge;
- align-self: center;
- justify-self: start;
- white-space: nowrap;
- background: var(--background-color-information);
- color: inherit;
- font-size: var(--font-size-small);
- border-radius: var(--border-radius-circle);
- margin-inline-start: var(--space-small);
- padding-block: var(--space-xsmall);
- padding-inline: var(--space-small);
-}
-
-.security-level-current-badge span {
- /* Still accessible to screen reader, but not visual.
- * Keep inline, but with no layout width. */
- display: inline-block;
- width: 1px;
- margin-inline-end: -1px;
- clip-path: inset(50%);
-}
-
-@media (prefers-contrast) and (not (forced-colors)) {
- .security-level-current-badge {
- /* Match the checkbox/radio colors. */
- background: var(--color-accent-primary);
- color: var(--button-text-color-primary);
- }
-}
-
-@media (forced-colors) {
- .security-level-current-badge {
- /* Match the checkbox/radio/selected colors. */
- background: SelectedItem;
- color: SelectedItemText;
- }
-}
-
-.security-level-name {
- grid-area: name;
- font-weight: var(--font-weight-bold);
- align-self: center;
- white-space: nowrap;
-}
-
-.security-level-description {
- display: grid;
- grid-column: summary-start / extra-end;
- grid-row: summary-start / extra-end;
- grid-template-rows: subgrid;
- grid-template-columns: subgrid;
- margin-block-start: var(--space-small);
-}
-
-.security-level-summary {
- grid-area: summary;
-}
-
-.security-level-description-extra {
- grid-area: extra;
- margin-block: var(--space-medium) 0;
- margin-inline: var(--space-large) 0;
- padding: 0;
-}
-
-.security-level-description-bullet:not(:last-child) {
- margin-block-end: var(--space-medium);
-}
-
-/* Tweak current security level display. */
-
-#security-level-current {
- margin-block-start: var(--space-large);
- background: var(--background-color-box);
- border: var(--border-width) solid var(--border-color);
- border-radius: var(--border-radius-small);
- padding: var(--space-medium);
-}
-
-#security-level-change {
- grid-area: button;
- align-self: center;
- margin: 0;
- margin-inline-start: var(--space-large);
-}
-
-/* Adjust which content is visible depending on the current security level. */
-
-#security-level-current:not([data-current-level="standard"]) .security-level-current-standard {
- display: none;
-}
-
-#security-level-current:not([data-current-level="safer"]) .security-level-current-safer {
- display: none;
-}
-
-#security-level-current:not([data-current-level="safest"]) .security-level-current-safest {
- display: none;
-}
-
-#security-level-current:not([data-current-level="custom"]) .security-level-current-custom {
- display: none;
-}
-
-#security-level-current[data-current-level="standard"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-standard.svg");
-}
-
-#security-level-current[data-current-level="safer"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-safer.svg");
-}
-
-#security-level-current[data-current-level="safest"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-safest.svg");
-}
-
-#security-level-current[data-current-level="custom"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-custom.svg");
-}
-
-/* Tweak security level dialog. */
-
-#security-level-radiogroup {
- margin-block: var(--space-large) var(--space-xlarge);
-}
-
-.security-level-radio-container {
- padding-block: var(--space-large);
-}
-
-#security-level-radiogroup .security-level-radio {
- margin: 0;
-}
-
-#security-level-radiogroup .radio-label-box {
- /* .security-level-current-badge already has a margin. */
- margin: 0;
-}
-
-#security-level-radiogroup .privacy-detailedoption.security-level-radio-container:not(.selected) .security-level-description-extra {
- /* .privacy-detailedoption uses visibility: hidden, which does not work with
- * our grid display (the margin is still reserved) so we use display: none
- * instead. */
- display: none;
-}
=====================================
browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml deleted
=====================================
@@ -1,35 +0,0 @@
-<groupbox id="securityLevel-groupbox"
- data-category="panePrivacy"
- data-subcategory="securitylevel"
- hidden="true">
- <label>
- <html:h2 data-l10n-id="security-level-preferences-heading"></html:h2>
- </label>
- <vbox flex="1">
- <description class="description-deemphasized" flex="1">
- <html:span
- id="securityLevel-overview"
- data-l10n-id="security-level-preferences-overview"
- ></html:span>
- <html:a
- is="moz-support-link"
- support-page="tor-manual:features__security-levels"
- data-l10n-id="security-level-preferences-learn-more-link"
- ></html:a>
- </description>
- <html:div id="security-level-current" class="security-level-grid">
- <html:img
- class="security-level-icon"
- alt=""
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- <html:button
- id="security-level-change"
- data-l10n-id="security-level-preferences-change-button"
- ></html:button>
- </html:div>
- </vbox>
-</groupbox>
=====================================
browser/components/securitylevel/jar.mn
=====================================
@@ -1,11 +1,16 @@
browser.jar:
+ content/browser/securitylevel/config/security-level.mjs (config/security-level.mjs)
+ content/browser/securitylevel/widgets/security-level-description.mjs (widgets/security-level-description.mjs)
+ content/browser/securitylevel/widgets/security-level-description.css (widgets/security-level-description.css)
+ content/browser/securitylevel/widgets/security-level-display.mjs (widgets/security-level-display.mjs)
+ content/browser/securitylevel/widgets/security-level-display.css (widgets/security-level-display.css)
content/browser/securitylevel/securityLevel.js (content/securityLevel.js)
content/browser/securitylevel/securityLevelPanel.css (content/securityLevelPanel.css)
content/browser/securitylevel/securityLevelButton.css (content/securityLevelButton.css)
- content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css)
content/browser/securitylevel/security-level-custom.svg (content/security-level-custom.svg)
content/browser/securitylevel/security-level-safer.svg (content/security-level-safer.svg)
content/browser/securitylevel/security-level-safest.svg (content/security-level-safest.svg)
content/browser/securitylevel/security-level-standard.svg (content/security-level-standard.svg)
content/browser/securitylevel/securityLevelDialog.xhtml (content/securityLevelDialog.xhtml)
content/browser/securitylevel/securityLevelDialog.js (content/securityLevelDialog.js)
+ content/browser/securitylevel/securityLevelDialog.css (content/securityLevelDialog.css)
=====================================
browser/components/securitylevel/moz.build
=====================================
@@ -1,5 +1 @@
JAR_MANIFESTS += ["jar.mn"]
-
-MOZ_SRC_FILES += [
- "SecurityLevelUIUtils.sys.mjs",
-]
=====================================
browser/components/securitylevel/widgets/security-level-description.css
=====================================
@@ -0,0 +1,20 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+p {
+ margin: 0;
+}
+
+:host([hide-bullets]) ul {
+ display: none;
+}
+
+ul {
+ margin: 0;
+ padding-inline: var(--space-large) 0;
+}
+
+li {
+ margin-block-start: var(--space-xsmall);
+}
=====================================
browser/components/securitylevel/widgets/security-level-description.mjs
=====================================
@@ -0,0 +1,79 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+import { html, repeat } from "chrome://global/content/vendor/lit.all.mjs";
+
+/**
+ * Widget that displays the description for a given security level.
+ *
+ * @tagname security-level-description
+ * @property {string} value - The security level to show the description for.
+ * @property {boolean} hideBullets - Whether to hide the bullet points for the
+ * description.
+ */
+class SecurityLevelDescription extends MozLitElement {
+ static properties = {
+ value: { type: String },
+ hideBullets: { type: Boolean, reflect: true, attribute: "hide-bullets" },
+ };
+
+ static #config = {
+ standard: {
+ summaryL10nId: "security-level-summary-standard",
+ },
+ safer: {
+ summaryL10nId: "security-level-summary-safer",
+ bullets: [
+ "security-level-preferences-bullet-https-only-javascript",
+ "security-level-preferences-bullet-limit-font-and-symbols",
+ "security-level-preferences-bullet-limit-media",
+ ],
+ },
+ safest: {
+ summaryL10nId: "security-level-summary-safest",
+ bullets: [
+ "security-level-preferences-bullet-disabled-javascript",
+ "security-level-preferences-bullet-limit-font-and-symbols-and-images",
+ "security-level-preferences-bullet-limit-media",
+ ],
+ },
+ custom: {
+ summaryL10nId: "security-level-summary-custom",
+ },
+ };
+
+ listTemplate() {
+ const bullets = SecurityLevelDescription.#config[this.value]?.bullets;
+ if (!bullets) {
+ return "";
+ }
+ return html`
+ <ul>
+ ${repeat(
+ bullets,
+ l10nId => l10nId,
+ l10nId => html`<li data-l10n-id=${l10nId}></li>`
+ )}
+ </ul>
+ `;
+ }
+
+ render() {
+ let l10nId = SecurityLevelDescription.#config[this.value]?.summaryL10nId;
+ if (!l10nId) {
+ return "";
+ }
+
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/securitylevel/widgets/security-level-description.css"
+ />
+ <p data-l10n-id=${l10nId}></p>
+ ${this.listTemplate()}
+ `;
+ }
+}
+customElements.define("security-level-description", SecurityLevelDescription);
=====================================
browser/components/securitylevel/widgets/security-level-display.css
=====================================
@@ -0,0 +1,23 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+:host {
+ --box-icon-stroke: var(--icon-color-warning);
+}
+
+p {
+ margin: 0;
+}
+
+.text-content {
+ padding: var(--box-padding);
+}
+
+.icon:dir(rtl) {
+ transform: scaleX(-1);
+}
+
+security-level-description {
+ grid-area: description;
+}
=====================================
browser/components/securitylevel/widgets/security-level-display.mjs
=====================================
@@ -0,0 +1,71 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { MozBoxBase } from "chrome://global/content/lit-utils.mjs";
+import { html } from "chrome://global/content/vendor/lit.all.mjs";
+
+/**
+ * Widget for displaying the current security level.
+ *
+ * @tagname security-level-display
+ * @property {string} value - The current security level.
+ */
+class SecurityLevelDisplay extends MozBoxBase {
+ static properties = {
+ value: { type: String },
+ _nameL10nId: { type: String },
+ };
+
+ static #config = {
+ standard: {
+ nameL10nId: "security-level-panel-level-standard",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-standard.svg",
+ },
+ safer: {
+ nameL10nId: "security-level-panel-level-safer",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-safer.svg",
+ },
+ safest: {
+ nameL10nId: "security-level-panel-level-safest",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-safest.svg",
+ },
+ custom: {
+ nameL10nId: "security-level-panel-level-custom",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-custom.svg",
+ },
+ };
+
+ willUpdate() {
+ const levelConfig = SecurityLevelDisplay.#config[this.value];
+ this._nameL10nId = levelConfig?.nameL10nId ?? null;
+ this.iconSrc = levelConfig?.iconSrc ?? null;
+ }
+
+ render() {
+ if (!this._nameL10nId) {
+ return "";
+ }
+ // NOTE: styleTemplate and iconTemplate come from MozBoxBase.
+ return html`
+ ${this.stylesTemplate()}
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/securitylevel/widgets/security-level-display.css"
+ />
+ <div class="text-content has-icon has-description">
+ ${this.iconTemplate()}
+ <p class="label" data-l10n-id=${this._nameL10nId}></p>
+ <security-level-description
+ .value=${this.value}
+ class="text-deemphasized"
+ ></security-level-description>
+ </div>
+ `;
+ }
+}
+customElements.define("security-level-display", SecurityLevelDisplay);
=====================================
toolkit/content/widgets/lit-utils.mjs
=====================================
@@ -263,6 +263,9 @@ export class MozBaseInputElement extends MozLitElement {
ariaLabel: { type: String, mapped: true },
ariaDescription: { type: String, mapped: true },
inputLayout: { type: String, reflect: true, attribute: "inputlayout" },
+ // Allow us to set more complex content in a label (e.g. a moz-badge).
+ // See tor-browser#45201.
+ useLabelSlot: { type: Boolean, attribute: "use-label-slot" },
};
/** @type {"inline" | "block" | "inline-end"} */
static inputLayout = "inline";
@@ -461,7 +464,7 @@ export class MozBaseInputElement extends MozLitElement {
}
labelTemplate() {
- if (!this.label) {
+ if (!this.label && !this.useLabelSlot) {
return "";
}
let labelEl;
@@ -474,6 +477,12 @@ export class MozBaseInputElement extends MozLitElement {
class="text text-box-trim-start"
.textContent=${this.label}
></h3>`;
+ } else if (this.useLabelSlot) {
+ labelEl = html`<slot
+ class="text"
+ name="label"
+ @slotchange=${this.onSlotchange}
+ ></slot>`;
} else {
labelEl = html`<span class="text" .textContent=${this.label}></span>`;
}
=====================================
toolkit/locales/en-US/toolkit/global/base-browser.ftl
=====================================
@@ -175,13 +175,11 @@ security-level-panel-open-settings-button = Settings…
## Security level settings.
-security-level-preferences-heading = Security Level
-security-level-preferences-overview = Disable certain web features that can be used to attack your security and anonymity.
-security-level-preferences-learn-more-link = Learn more
-# Text for a badge that labels the currently active security level.
-# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
-security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
-security-level-preferences-change-button = Change…
+security-level-settings-group =
+ .label = Security level
+ .description = Disable certain web features that can be used to attack your security and anonymity.
+security-level-settings-change-button =
+ .label = Change security level
## Security level settings dialog.
@@ -191,13 +189,12 @@ security-level-dialog-window =
# '-brand-short-name' is the localized browser name, like "Tor Browser".
security-level-dialog-restart-description = You will need to restart { -brand-short-name } to apply any changes. This will close all windows and tabs.
-security-level-preferences-level-standard =
- .label = Standard
-security-level-preferences-level-safer =
- .label = Safer
-security-level-preferences-level-safest =
- .label = Safest
-
+# Text for a badge that labels the currently active security level.
+# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
+security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
+# The "aria-label" provides a name for the group of radio options. This is not visibly shown, but it is useful for screen reader users.
+security-level-dialog-radio-group =
+ .aria-label = Security level
security-level-dialog-save-restart =
.label = Save and restart
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/ca…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/compare/ca…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.1.0esr-16.0-1] 3 commits: fixup! BB 40925: Implemented the Security Level component
by morgan (@morgan) 24 Aug '26
by morgan (@morgan) 24 Aug '26
24 Aug '26
morgan pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
c6627585 by Henry Wilkes at 2026-08-24T12:19:25+00:00
fixup! BB 40925: Implemented the Security Level component
BB 45201: Move security level settings to the settings config.
- - - - -
9af10306 by Henry Wilkes at 2026-08-24T12:19:25+00:00
fixup! Base Browser strings
BB 45201: Update security level setting strings.
- - - - -
af669639 by Henry Wilkes at 2026-08-24T12:19:25+00:00
BB 45201: Customize moz- input widgets for Base Browser.
- - - - -
21 changed files:
- browser/components/preferences/config/privacy.mjs
- browser/components/preferences/preferences.js
- browser/components/preferences/preferences.xhtml
- browser/components/preferences/privacy.inc.xhtml
- browser/components/preferences/privacy.js
- − browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs
- + browser/components/securitylevel/config/security-level.mjs
- browser/components/securitylevel/content/securityLevel.js
- + browser/components/securitylevel/content/securityLevelDialog.css
- browser/components/securitylevel/content/securityLevelDialog.js
- browser/components/securitylevel/content/securityLevelDialog.xhtml
- − browser/components/securitylevel/content/securityLevelPreferences.css
- − browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml
- browser/components/securitylevel/jar.mn
- browser/components/securitylevel/moz.build
- + browser/components/securitylevel/widgets/security-level-description.css
- + browser/components/securitylevel/widgets/security-level-description.mjs
- + browser/components/securitylevel/widgets/security-level-display.css
- + browser/components/securitylevel/widgets/security-level-display.mjs
- toolkit/content/widgets/lit-utils.mjs
- toolkit/locales/en-US/toolkit/global/base-browser.ftl
Changes:
=====================================
browser/components/preferences/config/privacy.mjs
=====================================
@@ -7,6 +7,10 @@
import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
+ChromeUtils.importESModule(
+ "chrome://browser/content/securitylevel/config/security-level.mjs",
+ { global: "current" }
+);
ChromeUtils.importESModule(
"chrome://browser/content/preferences/config/protections-from-apps.mjs",
{ global: "current" }
=====================================
browser/components/preferences/preferences.js
=====================================
@@ -409,6 +409,7 @@ const CONFIG_PANES = Object.freeze({
"ipprotection",
"cookiesAndSiteData2",
"history2",
+ "securityLevelGroup",
"nonTechnicalPrivacy2",
"dnsOverHttps",
"connectionLink",
=====================================
browser/components/preferences/preferences.xhtml
=====================================
@@ -43,7 +43,6 @@
href="chrome://browser/content/preferences/letterboxing.css"
/>
- <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelPreferences.css" />
<link rel="stylesheet" href="chrome://browser/content/torpreferences/torPreferences.css" />
<link rel="stylesheet" href="chrome://browser/content/onionservices/authPreferences.css" />
@@ -108,6 +107,8 @@
<script type="module" src="chrome://browser/content/preferences/widgets/update-information.mjs"></script>
<script type="module" src="chrome://browser/content/preferences/widgets/update-state.mjs"></script>
<script type="module" src="chrome://browser/content/ipprotection/bandwidth-usage.mjs"></script>
+ <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"></script>
+ <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-display.mjs"></script>
<script type="module" src="chrome://browser/content/torpreferences/widgets/tor-bridges-display.mjs"></script>
<script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-assist-banner.mjs"></script>
<script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-status.mjs"></script>
=====================================
browser/components/preferences/privacy.inc.xhtml
=====================================
@@ -579,7 +579,7 @@
<html:h1 data-l10n-id="security-header"/>
</hbox>
-#include ../securitylevel/content/securityLevelPreferences.inc.xhtml
+<html:setting-group groupid="securityLevelGroup" data-category="panePrivacy" hidden="true" data-srd-migrated=""></html:setting-group>
<!-- addons, forgery (phishing) UI Security -->
<html:setting-group groupid="browsingProtection" data-category="panePrivacy" hidden="true" data-srd-migrated=""></html:setting-group>
=====================================
browser/components/preferences/privacy.js
=====================================
@@ -60,13 +60,6 @@ ChromeUtils.defineLazyGetter(lazy, "gParentalControlsService", () =>
: null
);
-// TODO: module import via ChromeUtils.defineModuleGetter
-XPCOMUtils.defineLazyScriptGetter(
- this,
- ["SecurityLevelPreferences"],
- "chrome://browser/content/securitylevel/securityLevel.js"
-);
-
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gIsFirstPartyIsolated",
@@ -150,16 +143,6 @@ function initTCPStandardSection() {
var gPrivacyPane = {
_pane: null,
- /**
- * Show the Security Level UI
- */
- _initSecurityLevel() {
- SecurityLevelPreferences.init();
- window.addEventListener("unload", () => SecurityLevelPreferences.uninit(), {
- once: true,
- });
- },
-
/**
* Whether the prompt to restart Firefox should appear when changing the autostart pref.
*/
@@ -654,6 +637,7 @@ var gPrivacyPane = {
initSettingGroup("etpReset");
initSettingGroup("etpCustomize");
initSettingGroup("networkProxy");
+ initSettingGroup("securityLevelGroup");
/* Initialize Content Blocking */
this.initContentBlocking();
@@ -663,7 +647,6 @@ var gPrivacyPane = {
this.networkCookieBehaviorReadPrefs();
this._initTrackingProtectionExtensionControl();
this._ensureTrackingProtectionExceptionListMigration();
- this._initSecurityLevel();
Preferences.get("privacy.trackingprotection.enabled").on(
"change",
=====================================
browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs deleted
=====================================
@@ -1,73 +0,0 @@
-/**
- * Common methods for the desktop security level components.
- */
-export const SecurityLevelUIUtils = {
- /**
- * Create an element that gives a description of the security level. To be
- * used in the settings.
- *
- * @param {string} level - The security level to describe.
- * @param {Document} doc - The document where the element will be inserted.
- *
- * @returns {Element} - The newly created element.
- */
- createDescriptionElement(level, doc) {
- const el = doc.createElement("div");
- el.classList.add("security-level-description");
-
- let l10nIdSummary;
- let bullets;
- switch (level) {
- case "standard":
- l10nIdSummary = "security-level-summary-standard";
- break;
- case "safer":
- l10nIdSummary = "security-level-summary-safer";
- bullets = [
- "security-level-preferences-bullet-https-only-javascript",
- "security-level-preferences-bullet-limit-font-and-symbols",
- "security-level-preferences-bullet-limit-media",
- ];
- break;
- case "safest":
- l10nIdSummary = "security-level-summary-safest";
- bullets = [
- "security-level-preferences-bullet-disabled-javascript",
- "security-level-preferences-bullet-limit-font-and-symbols-and-images",
- "security-level-preferences-bullet-limit-media",
- ];
- break;
- case "custom":
- l10nIdSummary = "security-level-summary-custom";
- break;
- default:
- throw Error(`Unhandled level: ${level}`);
- }
-
- const summaryEl = doc.createElement("div");
- summaryEl.classList.add("security-level-summary");
- doc.l10n.setAttributes(summaryEl, l10nIdSummary);
-
- el.append(summaryEl);
-
- if (!bullets) {
- return el;
- }
-
- const listEl = doc.createElement("ul");
- listEl.classList.add("security-level-description-extra");
- // Add a mozilla styling class as well:
- listEl.classList.add("privacy-extra-information");
- for (const l10nId of bullets) {
- const bulletEl = doc.createElement("li");
- bulletEl.classList.add("security-level-description-bullet");
-
- doc.l10n.setAttributes(bulletEl, l10nId);
-
- listEl.append(bulletEl);
- }
-
- el.append(listEl);
- return el;
- },
-};
=====================================
browser/components/securitylevel/config/security-level.mjs
=====================================
@@ -0,0 +1,81 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
+import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ SecurityLevelPrefs:
+ "moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
+});
+
+SettingGroupManager.registerGroups({
+ securityLevelGroup: {
+ subcategory: "securitylevel",
+ l10nId: "security-level-settings-group",
+ headingLevel: 2,
+ supportPage: "tor-manual:features__security-levels",
+ items: [
+ {
+ id: "securityLevelBoxGroup",
+ control: "moz-box-group",
+ items: [
+ {
+ id: "securityLevelCurrent",
+ control: "security-level-display",
+ },
+ {
+ id: "securityLevelChangeButton",
+ l10nId: "security-level-settings-change-button",
+ control: "moz-box-button",
+ },
+ ],
+ },
+ ],
+ },
+});
+
+Preferences.addSetting({
+ id: "securityLevelCurrent",
+ setup(emitChange) {
+ Services.prefs.addObserver(
+ "browser.security_level.security_slider",
+ emitChange
+ );
+ Services.prefs.addObserver(
+ "browser.security_level.security_custom",
+ emitChange
+ );
+
+ return () => {
+ Services.prefs.removeObserver(
+ "browser.security_level.security_slider",
+ emitChange
+ );
+ Services.prefs.removeObserver(
+ "browser.security_level.security_custom",
+ emitChange
+ );
+ };
+ },
+ get: () => {
+ return lazy.SecurityLevelPrefs.securityLevelSummary;
+ },
+});
+
+Preferences.addSetting({
+ id: "securityLevelBoxGroup",
+});
+
+Preferences.addSetting({
+ id: "securityLevelChangeButton",
+ onUserClick() {
+ window.gSubDialog.open(
+ "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
+ { features: "resizable=yes" }
+ );
+ },
+});
=====================================
browser/components/securitylevel/content/securityLevel.js
=====================================
@@ -5,8 +5,6 @@
ChromeUtils.defineESModuleGetters(this, {
SecurityLevelPrefs:
"moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
- SecurityLevelUIUtils:
- "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs",
});
/*
@@ -263,103 +261,3 @@ var SecurityLevelPanel = {
}
},
}; /* SecurityLevelPanel */
-
-/*
- Security Level Preferences Code
-
- Code to handle init and update of security level section in about:preferences#privacy
-*/
-
-var SecurityLevelPreferences = {
- _securityPrefsBranch: null,
-
- /**
- * The element that shows the current security level.
- *
- * @type {?Element}
- */
- _currentEl: null,
-
- _populateXUL() {
- this._currentEl = document.getElementById("security-level-current");
- const changeButton = document.getElementById("security-level-change");
- const badgeEl = this._currentEl.querySelector(
- ".security-level-current-badge"
- );
-
- for (const { level, nameId } of [
- { level: "standard", nameId: "security-level-panel-level-standard" },
- { level: "safer", nameId: "security-level-panel-level-safer" },
- { level: "safest", nameId: "security-level-panel-level-safest" },
- { level: "custom", nameId: "security-level-panel-level-custom" },
- ]) {
- // Classes that control visibility:
- // security-level-current-standard
- // security-level-current-safer
- // security-level-current-safest
- // security-level-current-custom
- const visibilityClass = `security-level-current-${level}`;
- const nameEl = document.createElement("div");
- nameEl.classList.add("security-level-name", visibilityClass);
- document.l10n.setAttributes(nameEl, nameId);
-
- const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
- level,
- document
- );
- descriptionEl.classList.add(visibilityClass);
-
- this._currentEl.insertBefore(nameEl, badgeEl);
- this._currentEl.insertBefore(descriptionEl, changeButton);
- }
-
- changeButton.addEventListener("click", () => {
- this._openDialog();
- });
- },
-
- _openDialog() {
- gSubDialog.open(
- "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
- { features: "resizable=yes" }
- );
- },
-
- _configUIFromPrefs() {
- // Set a data-current-level attribute for showing the current security
- // level, and hiding the rest.
- this._currentEl.dataset.currentLevel =
- SecurityLevelPrefs.securityLevelSummary;
- },
-
- init() {
- // populate XUL with localized strings
- this._populateXUL();
-
- // read prefs and populate UI
- this._configUIFromPrefs();
-
- // register for pref chagnes
- this._securityPrefsBranch = Services.prefs.getBranch(
- "browser.security_level."
- );
- this._securityPrefsBranch.addObserver("", this);
- },
-
- uninit() {
- // unregister for pref change events
- this._securityPrefsBranch.removeObserver("", this);
- this._securityPrefsBranch = null;
- },
-
- // callback for when prefs change
- observe(subject, topic, data) {
- switch (topic) {
- case "nsPref:changed":
- if (data == "security_slider" || data == "security_custom") {
- this._configUIFromPrefs();
- }
- break;
- }
- },
-}; /* SecurityLevelPreferences */
=====================================
browser/components/securitylevel/content/securityLevelDialog.css
=====================================
@@ -0,0 +1,29 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+/* Hack to gain the internal styling of <moz-badge>.
+ * TODO: Drop this once we can use moz-badge. tor-browser#45229. */
+@import url("chrome://global/content/elements/moz-badge.css");
+
+#security-level-radiogroup {
+ margin-block: var(--space-large) var(--space-xlarge);
+}
+
+.security-level-radio-label {
+ display: inline flex;
+ gap: var(--space-small);
+}
+
+.security-level-radio-label .moz-badge-label > span {
+ /* Still accessible to screen reader, but not visual.
+ * Keep inline, but with no layout width. */
+ display: inline-block;
+ width: 1px;
+ margin-inline-end: -1px;
+ clip-path: inset(50%);
+}
+
+.moz-badge[hidden] {
+ display: none;
+}
=====================================
browser/components/securitylevel/content/securityLevelDialog.js
=====================================
@@ -3,9 +3,6 @@
const { SecurityLevelPrefs } = ChromeUtils.importESModule(
"moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs"
);
-const { SecurityLevelUIUtils } = ChromeUtils.importESModule(
- "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs"
-);
const gSecurityLevelDialog = {
/**
@@ -27,9 +24,9 @@ const gSecurityLevelDialog = {
*/
_radiogroup: null,
/**
- * A list of radio options and their containers.
+ * A list of radio options and their descriptions.
*
- * @type {?Array<{ container: Element, radio: Element }>}
+ * @type {?Array<{ description: Element, radio: Element }>}
*/
_radioOptions: null,
@@ -56,85 +53,42 @@ const gSecurityLevelDialog = {
this._radiogroup = document.getElementById("security-level-radiogroup");
this._radioOptions = Array.from(
- this._radiogroup.querySelectorAll(".security-level-radio-container"),
- container => {
- return {
- container,
- radio: container.querySelector(".security-level-radio"),
- };
+ this._radiogroup.querySelectorAll("moz-radio"),
+ radio => {
+ const description = radio.querySelector("security-level-description");
+ // Hide bullets by default.
+ description.hideBullets = true;
+ return { radio, description };
}
);
- for (const { container, radio } of this._radioOptions) {
- const level = radio.value;
- radio.id = `security-level-radio-${level}`;
- const currentEl = container.querySelector(
- ".security-level-current-badge"
- );
- currentEl.id = `security-level-current-badge-${level}`;
- const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
- level,
- document
- );
- descriptionEl.classList.add("indent");
- descriptionEl.id = `security-level-description-${level}`;
-
- // Wait for the full translation of the element before adding it to the
- // DOM. In particular, we want to make sure the elements have text before
- // we measure the maxHeight below.
- await document.l10n.translateFragment(descriptionEl);
- document.l10n.pauseObserving();
- container.append(descriptionEl);
- document.l10n.resumeObserving();
-
- if (level === this._prevLevel) {
- currentEl.hidden = false;
- // When the currentEl is visible, include it in the accessible name for
- // the radio option.
- // NOTE: The currentEl has an accessible name which includes punctuation
- // to help separate it's content from the security level name.
- // E.g. "Standard (Current level)".
- radio.setAttribute("aria-labelledby", `${radio.id} ${currentEl.id}`);
- } else {
- currentEl.hidden = true;
- }
- // We point the accessible description to the wrapping
- // .security-level-description element, rather than its children
- // that define the actual text content. This means that when the
- // privacy-extra-information is shown or hidden, its text content is
- // included or excluded from the accessible description, respectively.
- radio.setAttribute("aria-describedby", descriptionEl.id);
+ for (const { radio } of this._radioOptions) {
+ radio.querySelector(".moz-badge").hidden =
+ radio.value !== this._prevLevel;
}
- // We want to reserve the maximum height of the radiogroup so that the
+ // We want to reserve the maximum height of the moz-radio-group so that the
// dialog has enough height when the user switches options. So we cycle
// through the options and measure the height when they are selected to set
// a minimum height that fits all of them.
- // NOTE: At the time of implementation, at this point the dialog may not
- // yet have the "subdialog" attribute, which means it is missing the
- // common.css stylesheet from its shadow root, which effects the size of the
- // .radio-check element and the font. Therefore, we have duplicated the
- // import of common.css in SecurityLevelDialog.xhtml to ensure it is applied
- // at this earlier stage.
let maxHeight = 0;
- for (const { container } of this._radioOptions) {
- container.classList.add("selected");
+ for (const { description } of this._radioOptions) {
+ description.hideBullets = false;
+ await this._settled();
maxHeight = Math.max(
maxHeight,
this._radiogroup.getBoundingClientRect().height
);
- container.classList.remove("selected");
+ description.hideBullets = true;
}
this._radiogroup.style.minHeight = `${maxHeight}px`;
if (this._prevLevel !== "custom") {
this._selectedLevel = this._prevLevel;
this._radiogroup.value = this._prevLevel;
- } else {
- this._radiogroup.selectedItem = null;
}
- this._radiogroup.addEventListener("select", () => {
+ this._radiogroup.addEventListener("change", () => {
this._selectedLevel = this._radiogroup.value;
this._updateSelected();
});
@@ -142,16 +96,31 @@ const gSecurityLevelDialog = {
this._updateSelected();
},
+ /**
+ * Wait for the DOM to be settled after some change.
+ */
+ async _settled() {
+ // Wait for the widgets to react to some change.
+ await Promise.all([
+ this._radiogroup.updateComplete,
+ ...this._radioOptions.map(({ radio }) => radio.updateComplete),
+ ]);
+ // Also wait for any string population.
+ if (document.hasPendingL10nMutations) {
+ await new Promise(r =>
+ document.addEventListener("L10nMutationsFinished", r, { once: true })
+ );
+ }
+ },
+
/**
* Update the UI in response to a change in selection.
*/
_updateSelected() {
this._acceptButton.disabled =
!this._selectedLevel || this._selectedLevel === this._prevLevel;
- // Have the container's `selected` CSS class match the selection state of
- // the radio elements.
- for (const { container, radio } of this._radioOptions) {
- container.classList.toggle("selected", radio.selected);
+ for (const { description, radio } of this._radioOptions) {
+ description.hideBullets = !radio.checked;
}
},
=====================================
browser/components/securitylevel/content/securityLevelDialog.xhtml
=====================================
@@ -10,18 +10,6 @@
<dialog id="security-level-dialog" buttons="accept,cancel">
<linkset>
<html:link rel="stylesheet" href="chrome://global/skin/global.css" />
- <!-- NOTE: We include common.css explicitly, rather than relying on
- - the dialog's shadowroot importing it, which is late loaded in
- - response to the dialog's "subdialog" attribute, which is set
- - in response to DOMFrameContentLoaded.
- - In particular, we need the .radio-check rule and font rules from
- - common-shared.css to be in place when gSecurityLevelDialog.init is
- - called, which will help ensure that the radio element has the correct
- - size when we measure its bounding box. -->
- <html:link
- rel="stylesheet"
- href="chrome://global/skin/in-content/common.css"
- />
<html:link
rel="stylesheet"
href="chrome://browser/skin/preferences/preferences.css"
@@ -32,57 +20,77 @@
/>
<html:link
rel="stylesheet"
- href="chrome://browser/content/securitylevel/securityLevelPreferences.css"
+ href="chrome://browser/content/securitylevel/securityLevelDialog.css"
/>
<html:link rel="localization" href="branding/brand.ftl" />
<html:link rel="localization" href="toolkit/global/base-browser.ftl" />
</linkset>
+ <html:script
+ type="module"
+ src="chrome://global/content/elements/moz-radio-group.mjs"
+ ></html:script>
+ <html:script
+ type="module"
+ src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"
+ ></html:script>
<script src="chrome://browser/content/securitylevel/securityLevelDialog.js" />
<description data-l10n-id="security-level-dialog-restart-description" />
- <radiogroup id="security-level-radiogroup" class="highlighting-group">
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ <moz-radio-group
+ xmlns="http://www.w3.org/1999/xhtml"
+ id="security-level-radiogroup"
+ data-l10n-id="security-level-dialog-radio-group"
+ >
+ <moz-radio value="standard" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-standard"></span>
+ <!-- TODO: Use <moz-badge> widget once bugzilla bug 2065204 is
+ - resolved. See tor-browser#45229. -->
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="standard"
- data-l10n-id="security-level-preferences-level-standard"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ ></security-level-description>
+ </moz-radio>
+ <moz-radio value="safer" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-safer"></span>
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="safer"
- data-l10n-id="security-level-preferences-level-safer"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- <html:div
- class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
- >
- <radio
- class="security-level-radio security-level-name"
+ ></security-level-description>
+ </moz-radio>
+ <moz-radio value="safest" use-label-slot="">
+ <span class="security-level-radio-label" slot="label">
+ <span data-l10n-id="security-level-panel-level-safest"></span>
+ <span class="moz-badge" hidden="hidden">
+ <span
+ class="moz-badge-label"
+ data-l10n-id="security-level-preferences-current-badge"
+ ></span>
+ </span>
+ </span>
+ <security-level-description
+ slot="description"
value="safest"
- data-l10n-id="security-level-preferences-level-safest"
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- </html:div>
- </radiogroup>
+ ></security-level-description>
+ </moz-radio>
+ </moz-radio-group>
</dialog>
</window>
=====================================
browser/components/securitylevel/content/securityLevelPreferences.css deleted
=====================================
@@ -1,171 +0,0 @@
-.security-level-grid {
- display: grid;
- grid-template:
- "icon name badge button" min-content
- "icon summary summary button" auto
- "icon extra extra ." auto
- / max-content max-content 1fr max-content;
-}
-
-.security-level-icon {
- grid-area: icon;
- align-self: start;
- width: var(--icon-size-large);
- height: var(--icon-size-large);
- -moz-context-properties: fill, stroke;
- fill: var(--icon-color);
- stroke: var(--icon-color-warning);
- margin-block-start: var(--space-xsmall);
- margin-inline-end: var(--space-large);
-}
-
-:-moz-locale-dir(rtl) .security-level-icon {
- transform: scaleX(-1);
-}
-
-.security-level-current-badge {
- grid-area: badge;
- align-self: center;
- justify-self: start;
- white-space: nowrap;
- background: var(--background-color-information);
- color: inherit;
- font-size: var(--font-size-small);
- border-radius: var(--border-radius-circle);
- margin-inline-start: var(--space-small);
- padding-block: var(--space-xsmall);
- padding-inline: var(--space-small);
-}
-
-.security-level-current-badge span {
- /* Still accessible to screen reader, but not visual.
- * Keep inline, but with no layout width. */
- display: inline-block;
- width: 1px;
- margin-inline-end: -1px;
- clip-path: inset(50%);
-}
-
-@media (prefers-contrast) and (not (forced-colors)) {
- .security-level-current-badge {
- /* Match the checkbox/radio colors. */
- background: var(--color-accent-primary);
- color: var(--button-text-color-primary);
- }
-}
-
-@media (forced-colors) {
- .security-level-current-badge {
- /* Match the checkbox/radio/selected colors. */
- background: SelectedItem;
- color: SelectedItemText;
- }
-}
-
-.security-level-name {
- grid-area: name;
- font-weight: var(--font-weight-bold);
- align-self: center;
- white-space: nowrap;
-}
-
-.security-level-description {
- display: grid;
- grid-column: summary-start / extra-end;
- grid-row: summary-start / extra-end;
- grid-template-rows: subgrid;
- grid-template-columns: subgrid;
- margin-block-start: var(--space-small);
-}
-
-.security-level-summary {
- grid-area: summary;
-}
-
-.security-level-description-extra {
- grid-area: extra;
- margin-block: var(--space-medium) 0;
- margin-inline: var(--space-large) 0;
- padding: 0;
-}
-
-.security-level-description-bullet:not(:last-child) {
- margin-block-end: var(--space-medium);
-}
-
-/* Tweak current security level display. */
-
-#security-level-current {
- margin-block-start: var(--space-large);
- background: var(--background-color-box);
- border: var(--border-width) solid var(--border-color);
- border-radius: var(--border-radius-small);
- padding: var(--space-medium);
-}
-
-#security-level-change {
- grid-area: button;
- align-self: center;
- margin: 0;
- margin-inline-start: var(--space-large);
-}
-
-/* Adjust which content is visible depending on the current security level. */
-
-#security-level-current:not([data-current-level="standard"]) .security-level-current-standard {
- display: none;
-}
-
-#security-level-current:not([data-current-level="safer"]) .security-level-current-safer {
- display: none;
-}
-
-#security-level-current:not([data-current-level="safest"]) .security-level-current-safest {
- display: none;
-}
-
-#security-level-current:not([data-current-level="custom"]) .security-level-current-custom {
- display: none;
-}
-
-#security-level-current[data-current-level="standard"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-standard.svg");
-}
-
-#security-level-current[data-current-level="safer"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-safer.svg");
-}
-
-#security-level-current[data-current-level="safest"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-safest.svg");
-}
-
-#security-level-current[data-current-level="custom"] .security-level-icon {
- content: url("chrome://browser/content/securitylevel/security-level-custom.svg");
-}
-
-/* Tweak security level dialog. */
-
-#security-level-radiogroup {
- margin-block: var(--space-large) var(--space-xlarge);
-}
-
-.security-level-radio-container {
- padding-block: var(--space-large);
-}
-
-#security-level-radiogroup .security-level-radio {
- margin: 0;
-}
-
-#security-level-radiogroup .radio-label-box {
- /* .security-level-current-badge already has a margin. */
- margin: 0;
-}
-
-#security-level-radiogroup .privacy-detailedoption.security-level-radio-container:not(.selected) .security-level-description-extra {
- /* .privacy-detailedoption uses visibility: hidden, which does not work with
- * our grid display (the margin is still reserved) so we use display: none
- * instead. */
- display: none;
-}
=====================================
browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml deleted
=====================================
@@ -1,35 +0,0 @@
-<groupbox id="securityLevel-groupbox"
- data-category="panePrivacy"
- data-subcategory="securitylevel"
- hidden="true">
- <label>
- <html:h2 data-l10n-id="security-level-preferences-heading"></html:h2>
- </label>
- <vbox flex="1">
- <description class="description-deemphasized" flex="1">
- <html:span
- id="securityLevel-overview"
- data-l10n-id="security-level-preferences-overview"
- ></html:span>
- <html:a
- is="moz-support-link"
- support-page="tor-manual:features__security-levels"
- data-l10n-id="security-level-preferences-learn-more-link"
- ></html:a>
- </description>
- <html:div id="security-level-current" class="security-level-grid">
- <html:img
- class="security-level-icon"
- alt=""
- />
- <html:div
- class="security-level-current-badge"
- data-l10n-id="security-level-preferences-current-badge"
- ></html:div>
- <html:button
- id="security-level-change"
- data-l10n-id="security-level-preferences-change-button"
- ></html:button>
- </html:div>
- </vbox>
-</groupbox>
=====================================
browser/components/securitylevel/jar.mn
=====================================
@@ -1,11 +1,16 @@
browser.jar:
+ content/browser/securitylevel/config/security-level.mjs (config/security-level.mjs)
+ content/browser/securitylevel/widgets/security-level-description.mjs (widgets/security-level-description.mjs)
+ content/browser/securitylevel/widgets/security-level-description.css (widgets/security-level-description.css)
+ content/browser/securitylevel/widgets/security-level-display.mjs (widgets/security-level-display.mjs)
+ content/browser/securitylevel/widgets/security-level-display.css (widgets/security-level-display.css)
content/browser/securitylevel/securityLevel.js (content/securityLevel.js)
content/browser/securitylevel/securityLevelPanel.css (content/securityLevelPanel.css)
content/browser/securitylevel/securityLevelButton.css (content/securityLevelButton.css)
- content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css)
content/browser/securitylevel/security-level-custom.svg (content/security-level-custom.svg)
content/browser/securitylevel/security-level-safer.svg (content/security-level-safer.svg)
content/browser/securitylevel/security-level-safest.svg (content/security-level-safest.svg)
content/browser/securitylevel/security-level-standard.svg (content/security-level-standard.svg)
content/browser/securitylevel/securityLevelDialog.xhtml (content/securityLevelDialog.xhtml)
content/browser/securitylevel/securityLevelDialog.js (content/securityLevelDialog.js)
+ content/browser/securitylevel/securityLevelDialog.css (content/securityLevelDialog.css)
=====================================
browser/components/securitylevel/moz.build
=====================================
@@ -1,5 +1 @@
JAR_MANIFESTS += ["jar.mn"]
-
-MOZ_SRC_FILES += [
- "SecurityLevelUIUtils.sys.mjs",
-]
=====================================
browser/components/securitylevel/widgets/security-level-description.css
=====================================
@@ -0,0 +1,20 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+p {
+ margin: 0;
+}
+
+:host([hide-bullets]) ul {
+ display: none;
+}
+
+ul {
+ margin: 0;
+ padding-inline: var(--space-large) 0;
+}
+
+li {
+ margin-block-start: var(--space-xsmall);
+}
=====================================
browser/components/securitylevel/widgets/security-level-description.mjs
=====================================
@@ -0,0 +1,79 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+import { html, repeat } from "chrome://global/content/vendor/lit.all.mjs";
+
+/**
+ * Widget that displays the description for a given security level.
+ *
+ * @tagname security-level-description
+ * @property {string} value - The security level to show the description for.
+ * @property {boolean} hideBullets - Whether to hide the bullet points for the
+ * description.
+ */
+class SecurityLevelDescription extends MozLitElement {
+ static properties = {
+ value: { type: String },
+ hideBullets: { type: Boolean, reflect: true, attribute: "hide-bullets" },
+ };
+
+ static #config = {
+ standard: {
+ summaryL10nId: "security-level-summary-standard",
+ },
+ safer: {
+ summaryL10nId: "security-level-summary-safer",
+ bullets: [
+ "security-level-preferences-bullet-https-only-javascript",
+ "security-level-preferences-bullet-limit-font-and-symbols",
+ "security-level-preferences-bullet-limit-media",
+ ],
+ },
+ safest: {
+ summaryL10nId: "security-level-summary-safest",
+ bullets: [
+ "security-level-preferences-bullet-disabled-javascript",
+ "security-level-preferences-bullet-limit-font-and-symbols-and-images",
+ "security-level-preferences-bullet-limit-media",
+ ],
+ },
+ custom: {
+ summaryL10nId: "security-level-summary-custom",
+ },
+ };
+
+ listTemplate() {
+ const bullets = SecurityLevelDescription.#config[this.value]?.bullets;
+ if (!bullets) {
+ return "";
+ }
+ return html`
+ <ul>
+ ${repeat(
+ bullets,
+ l10nId => l10nId,
+ l10nId => html`<li data-l10n-id=${l10nId}></li>`
+ )}
+ </ul>
+ `;
+ }
+
+ render() {
+ let l10nId = SecurityLevelDescription.#config[this.value]?.summaryL10nId;
+ if (!l10nId) {
+ return "";
+ }
+
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/securitylevel/widgets/security-level-description.css"
+ />
+ <p data-l10n-id=${l10nId}></p>
+ ${this.listTemplate()}
+ `;
+ }
+}
+customElements.define("security-level-description", SecurityLevelDescription);
=====================================
browser/components/securitylevel/widgets/security-level-display.css
=====================================
@@ -0,0 +1,23 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+:host {
+ --box-icon-stroke: var(--icon-color-warning);
+}
+
+p {
+ margin: 0;
+}
+
+.text-content {
+ padding: var(--box-padding);
+}
+
+.icon:dir(rtl) {
+ transform: scaleX(-1);
+}
+
+security-level-description {
+ grid-area: description;
+}
=====================================
browser/components/securitylevel/widgets/security-level-display.mjs
=====================================
@@ -0,0 +1,71 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+import { MozBoxBase } from "chrome://global/content/lit-utils.mjs";
+import { html } from "chrome://global/content/vendor/lit.all.mjs";
+
+/**
+ * Widget for displaying the current security level.
+ *
+ * @tagname security-level-display
+ * @property {string} value - The current security level.
+ */
+class SecurityLevelDisplay extends MozBoxBase {
+ static properties = {
+ value: { type: String },
+ _nameL10nId: { type: String },
+ };
+
+ static #config = {
+ standard: {
+ nameL10nId: "security-level-panel-level-standard",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-standard.svg",
+ },
+ safer: {
+ nameL10nId: "security-level-panel-level-safer",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-safer.svg",
+ },
+ safest: {
+ nameL10nId: "security-level-panel-level-safest",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-safest.svg",
+ },
+ custom: {
+ nameL10nId: "security-level-panel-level-custom",
+ iconSrc:
+ "chrome://browser/content/securitylevel/security-level-custom.svg",
+ },
+ };
+
+ willUpdate() {
+ const levelConfig = SecurityLevelDisplay.#config[this.value];
+ this._nameL10nId = levelConfig?.nameL10nId ?? null;
+ this.iconSrc = levelConfig?.iconSrc ?? null;
+ }
+
+ render() {
+ if (!this._nameL10nId) {
+ return "";
+ }
+ // NOTE: styleTemplate and iconTemplate come from MozBoxBase.
+ return html`
+ ${this.stylesTemplate()}
+ <link
+ rel="stylesheet"
+ href="chrome://browser/content/securitylevel/widgets/security-level-display.css"
+ />
+ <div class="text-content has-icon has-description">
+ ${this.iconTemplate()}
+ <p class="label" data-l10n-id=${this._nameL10nId}></p>
+ <security-level-description
+ .value=${this.value}
+ class="text-deemphasized"
+ ></security-level-description>
+ </div>
+ `;
+ }
+}
+customElements.define("security-level-display", SecurityLevelDisplay);
=====================================
toolkit/content/widgets/lit-utils.mjs
=====================================
@@ -266,6 +266,9 @@ export class MozBaseInputElement extends MozLitElement {
// label-align-before is a customisation for the moz-toggle in about:tor.
// See tor-browser#43727.
labelAlignBefore: { type: Boolean, attribute: "label-align-before" },
+ // Allow us to set more complex content in a label (e.g. a moz-badge).
+ // See tor-browser#45201.
+ useLabelSlot: { type: Boolean, attribute: "use-label-slot" },
};
/** @type {"inline" | "block" | "inline-end"} */
static inputLayout = "inline";
@@ -465,7 +468,7 @@ export class MozBaseInputElement extends MozLitElement {
}
labelTemplate() {
- if (!this.label) {
+ if (!this.label && !this.useLabelSlot) {
return "";
}
let labelEl;
@@ -478,6 +481,12 @@ export class MozBaseInputElement extends MozLitElement {
class="text text-box-trim-start"
.textContent=${this.label}
></h3>`;
+ } else if (this.useLabelSlot) {
+ labelEl = html`<slot
+ class="text"
+ name="label"
+ @slotchange=${this.onSlotchange}
+ ></slot>`;
} else {
labelEl = html`<span class="text" .textContent=${this.label}></span>`;
}
=====================================
toolkit/locales/en-US/toolkit/global/base-browser.ftl
=====================================
@@ -185,13 +185,11 @@ security-level-panel-open-settings-button = Settings…
## Security level settings.
-security-level-preferences-heading = Security Level
-security-level-preferences-overview = Disable certain web features that can be used to attack your security and anonymity.
-security-level-preferences-learn-more-link = Learn more
-# Text for a badge that labels the currently active security level.
-# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
-security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
-security-level-preferences-change-button = Change…
+security-level-settings-group =
+ .label = Security level
+ .description = Disable certain web features that can be used to attack your security and anonymity.
+security-level-settings-change-button =
+ .label = Change security level
## Security level settings dialog.
@@ -201,13 +199,12 @@ security-level-dialog-window =
# '-brand-short-name' is the localized browser name, like "Tor Browser".
security-level-dialog-restart-description = You will need to restart { -brand-short-name } to apply any changes. This will close all windows and tabs.
-security-level-preferences-level-standard =
- .label = Standard
-security-level-preferences-level-safer =
- .label = Safer
-security-level-preferences-level-safest =
- .label = Safest
-
+# Text for a badge that labels the currently active security level.
+# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
+security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
+# The "aria-label" provides a name for the group of radio options. This is not visibly shown, but it is useful for screen reader users.
+security-level-dialog-radio-group =
+ .aria-label = Security level
security-level-dialog-save-restart =
.label = Save and restart
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/891501…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/891501…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.1.0esr-16.0-1] Bug 2053518 - Handle the *-oe-linux-* rust targets added in rustc 1.98 in rust...
by Pier Angelo Vendrame (@pierov) 24 Aug '26
by Pier Angelo Vendrame (@pierov) 24 Aug '26
24 Aug '26
Pier Angelo Vendrame pushed to branch mullvad-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
ca329cd8 by Jesse Schwartzentruber at 2026-08-24T12:36:58+02:00
Bug 2053518 - Handle the *-oe-linux-* rust targets added in rustc 1.98 in rust target detection. r=firefox-build-system-reviewers,glandium
Differential Revision: https://phabricator.services.mozilla.com/D311145
- - - - -
2 changed files:
- build/moz.configure/rust.configure
- python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
Changes:
=====================================
build/moz.configure/rust.configure
=====================================
@@ -300,6 +300,10 @@ def detect_rustc_target(
elif not candidates:
return None
+ # config.guess uses the "pc" vendor for x86/x86_64 where rust uses its
+ # generic "unknown" vendor; normalize so we correlate on the right one.
+ vendor = "unknown" if host_or_target.vendor == "pc" else host_or_target.vendor
+
# We have multiple candidates. There are two cases where we can try to
# narrow further down using extra information from the build system.
# - For windows targets, correlate with the C compiler type
@@ -367,11 +371,19 @@ def detect_rustc_target(
else:
suffix = ""
for p in prefixes:
- for c in candidates:
- if c.rust_target.startswith(
- "{}-".format(p)
- ) and c.rust_target.endswith(suffix):
+ matches = [
+ c
+ for c in candidates
+ if c.rust_target.startswith("{}-".format(p))
+ and c.rust_target.endswith(suffix)
+ ]
+ if not matches:
+ continue
+ # As below, correlate on the (normalized) vendor.
+ for c in matches:
+ if c.target.vendor == vendor:
return c.rust_target
+ return matches[0].rust_target
# See if we can narrow down on the exact alias.
# We use the sub_configure_alias to keep support mingw32 triplets as input.
@@ -400,6 +412,15 @@ def detect_rustc_target(
elif narrowed:
candidates = narrowed
+ # Correlate on the (normalized) vendor, so vendor-specific targets (e.g.
+ # the *-oe-linux-gnu targets added in rust 1.98) don't shadow the
+ # generic ones for aliases whose vendor doesn't match a rust target.
+ narrowed = [c for c in candidates if c.target.vendor == vendor]
+ if len(narrowed) == 1:
+ return narrowed[0].rust_target
+ elif narrowed:
+ candidates = narrowed
+
# See if we can narrow down with the raw OS and raw CPU
narrowed = [
c
=====================================
python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
=====================================
@@ -1779,6 +1779,15 @@ def gen_invoke_rustc(version, rustup_wrapper=False):
"xtensa-esp32s3-espidf",
"xtensa-esp32s3-none-elf",
]
+ # Additional targets from 1.98
+ if Version(version) >= "1.98.0":
+ rust_targets += [
+ "aarch64-oe-linux-gnu",
+ "armv7-oe-linux-gnueabihf",
+ "i686-oe-linux-gnu",
+ "riscv64-oe-linux-gnu",
+ "x86_64-oe-linux-gnu",
+ ]
return 0, "\n".join(sorted(rust_targets)), ""
if (
len(args) == 6
@@ -1869,6 +1878,7 @@ class RustTest(BaseConfigureTest):
("x86_64-unknown-linux-android", "x86_64-linux-android"),
("x86_64-unknown-linux-android21", "x86_64-linux-android"),
("x86_64-pc-linux-gnu", "x86_64-unknown-linux-gnu"),
+ ("riscv64-unknown-linux-gnu", "riscv64gc-unknown-linux-gnu"),
("sparcv9-sun-solaris2", "sparcv9-sun-solaris"),
("x86_64-sun-solaris2", "x86_64-pc-solaris"),
("x86_64-apple-darwin23.3.0", "x86_64-apple-darwin"),
@@ -1970,5 +1980,10 @@ class RustTest(BaseConfigureTest):
self.assertEqual(self.get_rust_target("wasm32-unknown-wasi"), "wasm32-wasip1")
+# Exercises the vendor-specific *-oe-linux-* targets added in rust 1.98.
+class Rust198Test(RustTest):
+ VERSION = "1.98.0"
+
+
if __name__ == "__main__":
main()
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/ca3…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/ca3…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.1.0esr-16.0-1] Bug 2053518 - Handle the *-oe-linux-* rust targets added in rustc 1.98 in rust...
by Pier Angelo Vendrame (@pierov) 24 Aug '26
by Pier Angelo Vendrame (@pierov) 24 Aug '26
24 Aug '26
Pier Angelo Vendrame pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
89150102 by Jesse Schwartzentruber at 2026-08-23T10:45:16+02:00
Bug 2053518 - Handle the *-oe-linux-* rust targets added in rustc 1.98 in rust target detection. r=firefox-build-system-reviewers,glandium
Differential Revision: https://phabricator.services.mozilla.com/D311145
- - - - -
2 changed files:
- build/moz.configure/rust.configure
- python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
Changes:
=====================================
build/moz.configure/rust.configure
=====================================
@@ -300,6 +300,10 @@ def detect_rustc_target(
elif not candidates:
return None
+ # config.guess uses the "pc" vendor for x86/x86_64 where rust uses its
+ # generic "unknown" vendor; normalize so we correlate on the right one.
+ vendor = "unknown" if host_or_target.vendor == "pc" else host_or_target.vendor
+
# We have multiple candidates. There are two cases where we can try to
# narrow further down using extra information from the build system.
# - For windows targets, correlate with the C compiler type
@@ -367,11 +371,19 @@ def detect_rustc_target(
else:
suffix = ""
for p in prefixes:
- for c in candidates:
- if c.rust_target.startswith(
- "{}-".format(p)
- ) and c.rust_target.endswith(suffix):
+ matches = [
+ c
+ for c in candidates
+ if c.rust_target.startswith("{}-".format(p))
+ and c.rust_target.endswith(suffix)
+ ]
+ if not matches:
+ continue
+ # As below, correlate on the (normalized) vendor.
+ for c in matches:
+ if c.target.vendor == vendor:
return c.rust_target
+ return matches[0].rust_target
# See if we can narrow down on the exact alias.
# We use the sub_configure_alias to keep support mingw32 triplets as input.
@@ -400,6 +412,15 @@ def detect_rustc_target(
elif narrowed:
candidates = narrowed
+ # Correlate on the (normalized) vendor, so vendor-specific targets (e.g.
+ # the *-oe-linux-gnu targets added in rust 1.98) don't shadow the
+ # generic ones for aliases whose vendor doesn't match a rust target.
+ narrowed = [c for c in candidates if c.target.vendor == vendor]
+ if len(narrowed) == 1:
+ return narrowed[0].rust_target
+ elif narrowed:
+ candidates = narrowed
+
# See if we can narrow down with the raw OS and raw CPU
narrowed = [
c
=====================================
python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
=====================================
@@ -1779,6 +1779,15 @@ def gen_invoke_rustc(version, rustup_wrapper=False):
"xtensa-esp32s3-espidf",
"xtensa-esp32s3-none-elf",
]
+ # Additional targets from 1.98
+ if Version(version) >= "1.98.0":
+ rust_targets += [
+ "aarch64-oe-linux-gnu",
+ "armv7-oe-linux-gnueabihf",
+ "i686-oe-linux-gnu",
+ "riscv64-oe-linux-gnu",
+ "x86_64-oe-linux-gnu",
+ ]
return 0, "\n".join(sorted(rust_targets)), ""
if (
len(args) == 6
@@ -1869,6 +1878,7 @@ class RustTest(BaseConfigureTest):
("x86_64-unknown-linux-android", "x86_64-linux-android"),
("x86_64-unknown-linux-android21", "x86_64-linux-android"),
("x86_64-pc-linux-gnu", "x86_64-unknown-linux-gnu"),
+ ("riscv64-unknown-linux-gnu", "riscv64gc-unknown-linux-gnu"),
("sparcv9-sun-solaris2", "sparcv9-sun-solaris"),
("x86_64-sun-solaris2", "x86_64-pc-solaris"),
("x86_64-apple-darwin23.3.0", "x86_64-apple-darwin"),
@@ -1970,5 +1980,10 @@ class RustTest(BaseConfigureTest):
self.assertEqual(self.get_rust_target("wasm32-unknown-wasi"), "wasm32-wasip1")
+# Exercises the vendor-specific *-oe-linux-* targets added in rust 1.98.
+class Rust198Test(RustTest):
+ VERSION = "1.98.0"
+
+
if __name__ == "__main__":
main()
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/8915010…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/8915010…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/torbrowser-launcher][main] 2 commits: po:Add Georgian translation
by asciiwolf (@asciiwolf) 21 Aug '26
by asciiwolf (@asciiwolf) 21 Aug '26
21 Aug '26
asciiwolf pushed to branch main at The Tor Project / Applications / torbrowser-launcher
Commits:
aa3de234 by EkaterinePapava at 2026-08-21T14:18:11+00:00
po:Add Georgian translation
- - - - -
9cf17f0c by asciiwolf at 2026-08-21T14:18:11+00:00
Merge branch 'main' into 'main'
po:Add Georgian translation
See merge request tpo/applications/torbrowser-launcher!44
- - - - -
3 changed files:
- + po/ka.po
- share/applications/org.torproject.torbrowser-launcher.desktop
- share/applications/org.torproject.torbrowser-launcher.settings.desktop
Changes:
=====================================
po/ka.po
=====================================
@@ -0,0 +1,254 @@
+# Georgian translation for Tor Broswer Launcher.
+# Copyright (C) 2026 Tor Broswer Launcher's authors
+# This file is distributed under the same license as the Tor Broswer Launcher package.
+# Ekaterine Papava <papava.e(a)gtu.ge>, 2026.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Tor Browser Launcher\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-01-09 17:04+0100\n"
+"PO-Revision-Date: 2026-03-02 22:28+0100\n"
+"Last-Translator: Ekaterine Papava <papava.e(a)gtu.ge>\n"
+"Language-Team: Georgian\n"
+"Language: ka\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 3.8\n"
+
+#: __init__.py:76 launcher.py:520
+msgid "Tor Browser Launcher"
+msgstr "Tor Browser-ის გამშვები"
+
+#: __init__.py:77
+msgid "By Micah Lee & Tor Project, licensed under MIT"
+msgstr "მიკა ლის და Tor Project-ის მიერ. ვრცელდება MIT ლიცენზიით"
+
+#: __init__.py:78
+#, python-brace-format
+msgid "version {0}"
+msgstr "ვერსია {0}"
+
+#: common.py:90
+#, python-brace-format
+msgid "Error creating {0}"
+msgstr "{0}-ის შექმნის შეცდომა"
+
+#: common.py:187
+#, python-brace-format
+msgid "Renamed {0} to {1}"
+msgstr "{0}-ს სახელი გადაერქვა {1}-ზე"
+
+#: common.py:201
+#, python-brace-format
+msgid "Cannot create directory {0}"
+msgstr "ვერ შევქმენი საქაღალდე {0}"
+
+#: common.py:204
+#, python-brace-format
+msgid "{0} is not writable"
+msgstr "{0} ჩაწერადი არაა"
+
+#: common.py:211
+msgid "Creating GnuPG homedir"
+msgstr "GnuPG-ის საწყისი საქაღალდის შექმნა"
+
+#: common.py:302
+#, python-format
+msgid "Could not import key with fingerprint: %s."
+msgstr "ანაბეჭდების მქონე გასაღების შემოტანა შეუძლებელია: %s."
+
+#: common.py:309
+msgid "Not all keys were imported successfully!"
+msgstr "ყველა გასაღები წარმატებით შემოტანილი არ იქნა!"
+
+#: launcher.py:87
+msgid "Downloading Tor Browser for the first time."
+msgstr "Tor Browser-ის გადმოწერა პირველად."
+
+#: launcher.py:90
+msgid ""
+"Your version of Tor Browser is out-of-date. Downloading the newest version."
+msgstr ""
+"Tor Browser-ის თქვენი ვერსია მოძველებულია. მიმდინარეობს ახალი ვერსიის "
+"გადმოწერა."
+
+#: launcher.py:111
+msgid "Downloading over Tor"
+msgstr "გადმოწერა Tor-ით"
+
+#: launcher.py:122
+msgid "Tor Browser"
+msgstr "Tor Browser"
+
+#: launcher.py:141
+msgid "Start"
+msgstr "გაშვება"
+
+#: launcher.py:191
+msgid "Yes"
+msgstr "დიახ"
+
+#: launcher.py:195
+msgid "Exit"
+msgstr "გასვლა"
+
+#: launcher.py:209 settings.py:136
+msgid "Cancel"
+msgstr "გაუქმება"
+
+#: launcher.py:246 launcher.py:267 launcher.py:276 launcher.py:315
+#: launcher.py:318
+msgid "Downloading"
+msgstr "მიმდინარეობს გადმოწერა"
+
+#: launcher.py:257
+msgid "Latest version: {}"
+msgstr "უკანასკნელი ვერსია: {}"
+
+#: launcher.py:261
+msgid "Error detecting Tor Browser version."
+msgstr "Tor Browser-ის ვერსიის დადგენის შეცდომა."
+
+#: launcher.py:291 launcher.py:389
+msgid "Verifying Signature"
+msgstr "ხელმოწერის გადამოწმება"
+
+#: launcher.py:295
+msgid "Extracting"
+msgstr "გაშლა"
+
+#: launcher.py:299
+msgid "Running"
+msgstr "გაშვებულია"
+
+#: launcher.py:303
+msgid "Starting download over again"
+msgstr "გადმოწერა თავიდან იწყება"
+
+#: launcher.py:315 launcher.py:334
+msgid "(over Tor)"
+msgstr "(Tor-ით)"
+
+#: launcher.py:330
+msgid "Downloaded"
+msgstr "გადმოწერილია"
+
+#: launcher.py:431
+msgid "Installing"
+msgstr "დაყენება"
+
+#: launcher.py:440
+#, python-brace-format
+msgid "Tor Browser Launcher doesn't understand the file format of {0}"
+msgstr "Tor Browser-ის გამშვებს {0}-ის ფაილის ფორმატი არ ესმის"
+
+#: launcher.py:471
+msgid ""
+"The version of Tor Browser you have installed is earlier than it should be, "
+"which could be a sign of an attack!"
+msgstr ""
+"Tor Browser-ის ვერსია, რომელიც დაყენებული გაქვთ, უფრო ძველია, ვიდრე ის უნდა "
+"იყოს. ეს, შეიძლება, შეტევის ნიშანს წარმოადგენდეს!"
+
+#: launcher.py:488
+msgid "Downloading Tor Browser over again."
+msgstr "Tor Browser-ის კიდევ ერთხელ გადმოწერა."
+
+#: launcher.py:561 launcher.py:569
+msgid "Download Error:"
+msgstr "გადმოწერის შეცდომა:"
+
+#: launcher.py:563
+msgid "You are currently using a non-default mirror"
+msgstr "ამჟამად იყენებთ არანაგულისხმევ სარკეს"
+
+#: launcher.py:565
+msgid "Would you like to switch back to the default?"
+msgstr "გნებავთ ისევ ნაგულისხმევზე გადართვა?"
+
+#: launcher.py:585
+#, python-brace-format
+msgid ""
+"Invalid SSL certificate for:\n"
+"{0}\n"
+"\n"
+"You may be under attack."
+msgstr ""
+"არასწორი SSL სერტიფიკატი საიტისთვის:\n"
+"{0}\n"
+"\n"
+"შეიძლება, გიტევენ."
+
+#: launcher.py:588
+msgid "Try the download again using Tor?"
+msgstr "ვცადო გადმოწერა კიდევ ერთხელ Tor-ის გამოყენებით?"
+
+#: launcher.py:598
+#, python-brace-format
+msgid ""
+"Error starting download:\n"
+"\n"
+"{0}\n"
+"\n"
+"Trying to download over Tor. Are you sure Tor is configured correctly and "
+"running?"
+msgstr ""
+"გადმოწერის დაწყების შეცდომა:\n"
+"\n"
+"{0}\n"
+"\n"
+"ვცდილობ, Tor-ით გადმოვწერო. დარწმუნებული ბრძანდებით, რომ Tor სწორადაა "
+"მორგებული და გაშვებულია?"
+
+#: launcher.py:604
+#, python-brace-format
+msgid ""
+"Error starting download:\n"
+"\n"
+"{0}\n"
+"\n"
+"Are you connected to the internet?"
+msgstr ""
+"გადმოწერის დაწყების შეცდომა:\n"
+"\n"
+"{0}\n"
+"\n"
+"ინტერნეტი გაქვთ?"
+
+#: settings.py:48
+msgid "Tor Browser Launcher Settings"
+msgstr "Tor Browser-ის გამშვების მორგება"
+
+#: settings.py:52
+msgid "Download over system Tor"
+msgstr "სისტემური Tor-ით გადმოწერა"
+
+#: settings.py:59
+msgid "Tor server"
+msgstr "Tor სერვერი"
+
+#: settings.py:74
+msgid "Status: Installed"
+msgstr "სტატუსი: დაყენებულია"
+
+#: settings.py:76
+msgid "Status: Not Installed"
+msgstr "სტატუსი: დაყენებული არაა"
+
+#: settings.py:79
+msgid "Install Tor Browser"
+msgstr "Tor Browser-ის დაყენება"
+
+#: settings.py:86
+msgid "Reinstall Tor Browser"
+msgstr "Tor Browser-ის თავიდან დაყენება"
+
+#: settings.py:111
+msgid "Mirror"
+msgstr "სარკე"
+
+#: settings.py:129
+msgid "Save && Exit"
+msgstr "შენახვა && გასვლა"
=====================================
share/applications/org.torproject.torbrowser-launcher.desktop
=====================================
@@ -7,6 +7,7 @@ Name[da]=Tor Browser
Name[es]=Navegador Tor
Name[hr]=Tor preglednik
Name[hu]=Tor-böngésző
+Name[ka]=Tor Browser
Name[pt_BR]=Navegador Tor
Name[sv]=Tor Browser
Name[tr]=Tor Browser
@@ -18,6 +19,7 @@ GenericName[da]=Tor Browser
GenericName[es]=Navegador Tor
GenericName[hr]=Tor preglednik
GenericName[hu]=Tor böngésző indító
+GenericName[ka]=Tor Browser
GenericName[tr]=Tor Browser
Comment=Launch Tor Browser
Comment[ar]=شغّل متصفح تور
@@ -27,6 +29,7 @@ Comment[da]=Start Tor Browser
Comment[es]=Iniciar Navegador Tor
Comment[hr]=Pokreni Tor preglednika
Comment[hu]=Tor böngésző indító
+Comment[ka]=Tor Browser-ის გაშვება
Comment[pt_BR]=Navegador Tor
Comment[sv]=Starta Tor Browser
Comment[tr]=Tor Browser Başlat
=====================================
share/applications/org.torproject.torbrowser-launcher.settings.desktop
=====================================
@@ -7,6 +7,7 @@ Name[da]=Indstillinger for Tor Browser-opstarter
Name[fr]=Tor Browser Launcher configurations
Name[hr]=Tor preglednik – postavke pokretanja
Name[hu]=Tor-böngésző indító beállításai
+Name[ka]=Tor Browser-ის გამშვების მორგება
Name[nl]=Tor Browser Launcher Instellingen
Name[pt_BR]=Navegador Tor (Configurações do Lançador)
Name[ru]=Tor Browser (настройки запуска)
@@ -19,6 +20,7 @@ GenericName[cs]=Prohlížeč Tor nastavení spouštěče
GenericName[da]=Indstillinger for Tor Browser-opstarter
GenericName[hr]=Tor preglednik – postavke pokretanja
GenericName[hu]=Tor-böngésző indító beállításai
+GenericName[ka]=Tor Browser-ის გამშვების მორგება
GenericName[tr]=Tor Browser Başlatıcı Ayarları
Comment=Tor Browser Launcher Settings
Comment[ar]=إعدادات مشغّل متصفح تور
@@ -28,6 +30,7 @@ Comment[da]=Indstillinger for Tor Browser-opstarter
Comment[fr]=Tor Browser Launcher configurations
Comment[hr]=Postavke za pokretanje Tor preglednika
Comment[hu]=Tor-böngésző indító beállításai
+Comment[ka]=Tor Browser-ის გამშვების მორგება
Comment[nl]=Tor Browser Launcher Instellingen
Comment[pt_BR]=Navegador Tor (Configurações do Lançador)
Comment[ru]=Tor Browser (настройки запуска)
View it on GitLab: https://gitlab.torproject.org/tpo/applications/torbrowser-launcher/-/compar…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/torbrowser-launcher/-/compar…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/torbrowser-launcher] Deleted branch screenshot
by asciiwolf (@asciiwolf) 21 Aug '26
by asciiwolf (@asciiwolf) 21 Aug '26
21 Aug '26
asciiwolf deleted branch screenshot at The Tor Project / Applications / torbrowser-launcher
--
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/torbrowser-launcher][main] 2 commits: Use GitHub mirror for AppStream screenshot
by asciiwolf (@asciiwolf) 21 Aug '26
by asciiwolf (@asciiwolf) 21 Aug '26
21 Aug '26
asciiwolf pushed to branch main at The Tor Project / Applications / torbrowser-launcher
Commits:
b3aced42 by asciiwolf at 2026-08-21T13:06:49+00:00
Use GitHub mirror for AppStream screenshot
- - - - -
29fc651d by asciiwolf at 2026-08-21T13:06:49+00:00
Merge branch 'screenshot' into 'main'
Use GitHub mirror for AppStream screenshot
See merge request tpo/applications/torbrowser-launcher!50
- - - - -
1 changed file:
- share/metainfo/org.torproject.torbrowser-launcher.metainfo.xml
Changes:
=====================================
share/metainfo/org.torproject.torbrowser-launcher.metainfo.xml
=====================================
@@ -45,7 +45,7 @@
</description>
<screenshots>
<screenshot type="default">
- <image>https://gitlab.torproject.org/tpo/applications/torbrowser-launcher/-/raw/ma…</image>
+ <image>https://raw.githubusercontent.com/torproject/torbrowser-launcher/main/scree…</image>
<caption>Window to change Tor Browser Launcher settings</caption>
<caption xml:lang="ar">نافذة لتغيير إعدادات مشغّل متصفّح تور</caption>
<caption xml:lang="cs">Okno pro změnu nastavení Spouštěče Prohlížeče Tor</caption>
View it on GitLab: https://gitlab.torproject.org/tpo/applications/torbrowser-launcher/-/compar…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/torbrowser-launcher/-/compar…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/mullvad-browser][mullvad-browser-153.1.0esr-16.0-1] fixup! Firefox preference overrides.
by morgan (@morgan) 20 Aug '26
by morgan (@morgan) 20 Aug '26
20 Aug '26
morgan pushed to branch mullvad-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Mullvad Browser
Commits:
2fab73d7 by Pier Angelo Vendrame at 2026-08-20T12:25:21+00:00
fixup! Firefox preference overrides.
BB 44511&45228: Review some urlbar prefs.
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -184,21 +184,14 @@ pref("security.tls.version.enable-deprecated", false, locked);
// more similar.
pref("security.ssl.disable_session_identifiers", true);
-// Misc privacy: Remote
-pref("browser.send_pings", false);
-// Space separated list of URLs that are allowed to send objects (instead of
-// only strings) through webchannels. The default for Firefox is some Mozilla
-// domains.
-pref("webchannel.allowObject.urlWhitelist", "");
-pref("geo.enabled", false);
-pref("geo.provider.network.url", "");
-pref("geo.provider.ms-windows-location", false);
-pref("geo.provider.use_corelocation", false);
-pref("geo.provider.use_gpsd", false);
-pref("geo.provider.use_geoclue", false);
+// URL bar and (remote) suggestions
pref("browser.search.suggest.enabled", false);
pref("browser.search.suggest.enabled.private", false);
pref("browser.urlbar.suggest.searches", false);
+// tor-browser#44511: Global opt-out for rich suggestions.
+// Some of them are not remote, but we do not have the needed remote settings
+// dump, so just disable all of them.
+pref("browser.urlbar.suggest.quicksuggest.all", false);
pref("browser.urlbar.suggest.quicksuggest.nonsponsored", false);
pref("browser.urlbar.suggest.quicksuggest.sponsored", false);
// tor-browser#41576: Do not suggest weather and addons.
@@ -209,8 +202,32 @@ pref("browser.urlbar.weather.featureGate", false);
// tor-browser#42886: Disable trending results.
pref("browser.urlbar.suggest.trending", false);
pref("browser.urlbar.trending.featureGate", false);
+pref("browser.urlbar.suggest.topsites", false);
// tor-browser#41691: Hide "Firefox Suggest" in the UI
pref("browser.urlbar.groupLabels.enabled", false);
+// tor-browser#42735: Disable recent search suggestions
+pref("browser.urlbar.recentsearches.featureGate", false);
+pref("browser.urlbar.suggest.recentsearches", false);
+pref("browser.urlbar.quicksuggest.enabled", false);
+pref("browser.urlbar.quicksuggest.online.available", false);
+pref("browser.urlbar.quicksuggest.online.enabled", false);
+pref("browser.urlbar.richSuggestions.featureGate", false);
+// tor-browser#44511: defense-in-depth to disable remote queries when pasting.
+pref("browser.urlbar.maxCharsForSearchSuggestions", 0);
+
+// Misc privacy: Remote
+pref("browser.send_pings", false);
+// Space separated list of URLs that are allowed to send objects (instead of
+// only strings) through webchannels. The default for Firefox is some Mozilla
+// domains.
+pref("webchannel.allowObject.urlWhitelist", "");
+pref("geo.enabled", false);
+pref("geo.provider.network.url", "");
+pref("geo.provider.ms-windows-location", false);
+pref("geo.provider.use_corelocation", false);
+pref("geo.provider.use_gpsd", false);
+pref("geo.provider.use_geoclue", false);
+
pref("browser.safebrowsing.malware.enabled", false);
pref("browser.safebrowsing.phishing.enabled", false);
pref("browser.safebrowsing.downloads.enabled", false);
@@ -223,12 +240,6 @@ pref("browser.safebrowsing.provider.google4.updateURL", "");
pref("browser.safebrowsing.provider.google4.gethashURL", "");
pref("browser.safebrowsing.provider.mozilla.updateURL", "");
pref("browser.safebrowsing.provider.mozilla.gethashURL", "");
-// tor-browser#42735: Disable recent search suggestions
-pref("browser.urlbar.recentsearches.featureGate", false);
-pref("browser.urlbar.suggest.recentsearches", false);
-
-// tor-browser#44262: Disable adding search engines from HTML forms
-pref("browser.urlbar.update2.engineAliasRefresh", false);
// Disable the UITour API
// See tor-browser#41457 and
@@ -763,14 +774,6 @@ pref("security.certerrors.mitm.auto_enable_enterprise_roots", false);
// Disable share menus on Mac and Windows tor-browser#41117
pref("browser.menu.share_url.allow", false, locked);
-// Disable special URL bar behaviors
-pref("browser.urlbar.suggest.topsites", false);
-pref("browser.urlbar.quicksuggest.enabled", false);
-pref("browser.urlbar.quicksuggest.online.available", false);
-pref("browser.urlbar.quicksuggest.online.enabled", false);
-pref("browser.urlbar.richSuggestions.featureGate", false);
-pref("browser.urlbar.yelp.featureGate", false);
-pref("browser.urlbar.mdn.featureGate", false);
// tor-browser#41884: Do not start a search when clicking on the new tab button
// with the middle mouse button (to prevent searching for anything you might
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/2fa…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/commit/2fa…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.1.0esr-16.0-1] fixup! Firefox preference overrides.
by morgan (@morgan) 20 Aug '26
by morgan (@morgan) 20 Aug '26
20 Aug '26
morgan pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
93114cd9 by Pier Angelo Vendrame at 2026-08-20T12:18:13+00:00
fixup! Firefox preference overrides.
BB 44511&45228: Review some urlbar prefs.
- - - - -
1 changed file:
- browser/app/profile/001-base-profile.js
Changes:
=====================================
browser/app/profile/001-base-profile.js
=====================================
@@ -187,21 +187,14 @@ pref("security.tls.version.enable-deprecated", false, locked);
// more similar.
pref("security.ssl.disable_session_identifiers", true);
-// Misc privacy: Remote
-pref("browser.send_pings", false);
-// Space separated list of URLs that are allowed to send objects (instead of
-// only strings) through webchannels. The default for Firefox is some Mozilla
-// domains.
-pref("webchannel.allowObject.urlWhitelist", "");
-pref("geo.enabled", false);
-pref("geo.provider.network.url", "");
-pref("geo.provider.ms-windows-location", false);
-pref("geo.provider.use_corelocation", false);
-pref("geo.provider.use_gpsd", false);
-pref("geo.provider.use_geoclue", false);
+// URL bar and (remote) suggestions
pref("browser.search.suggest.enabled", false);
pref("browser.search.suggest.enabled.private", false);
pref("browser.urlbar.suggest.searches", false);
+// tor-browser#44511: Global opt-out for rich suggestions.
+// Some of them are not remote, but we do not have the needed remote settings
+// dump, so just disable all of them.
+pref("browser.urlbar.suggest.quicksuggest.all", false);
pref("browser.urlbar.suggest.quicksuggest.nonsponsored", false);
pref("browser.urlbar.suggest.quicksuggest.sponsored", false);
// tor-browser#41576: Do not suggest weather and addons.
@@ -212,8 +205,32 @@ pref("browser.urlbar.weather.featureGate", false);
// tor-browser#42886: Disable trending results.
pref("browser.urlbar.suggest.trending", false);
pref("browser.urlbar.trending.featureGate", false);
+pref("browser.urlbar.suggest.topsites", false);
// tor-browser#41691: Hide "Firefox Suggest" in the UI
pref("browser.urlbar.groupLabels.enabled", false);
+// tor-browser#42735: Disable recent search suggestions
+pref("browser.urlbar.recentsearches.featureGate", false);
+pref("browser.urlbar.suggest.recentsearches", false);
+pref("browser.urlbar.quicksuggest.enabled", false);
+pref("browser.urlbar.quicksuggest.online.available", false);
+pref("browser.urlbar.quicksuggest.online.enabled", false);
+pref("browser.urlbar.richSuggestions.featureGate", false);
+// tor-browser#44511: defense-in-depth to disable remote queries when pasting.
+pref("browser.urlbar.maxCharsForSearchSuggestions", 0);
+
+// Misc privacy: Remote
+pref("browser.send_pings", false);
+// Space separated list of URLs that are allowed to send objects (instead of
+// only strings) through webchannels. The default for Firefox is some Mozilla
+// domains.
+pref("webchannel.allowObject.urlWhitelist", "");
+pref("geo.enabled", false);
+pref("geo.provider.network.url", "");
+pref("geo.provider.ms-windows-location", false);
+pref("geo.provider.use_corelocation", false);
+pref("geo.provider.use_gpsd", false);
+pref("geo.provider.use_geoclue", false);
+
pref("browser.safebrowsing.malware.enabled", false);
pref("browser.safebrowsing.phishing.enabled", false);
pref("browser.safebrowsing.downloads.enabled", false);
@@ -226,12 +243,6 @@ pref("browser.safebrowsing.provider.google4.updateURL", "");
pref("browser.safebrowsing.provider.google4.gethashURL", "");
pref("browser.safebrowsing.provider.mozilla.updateURL", "");
pref("browser.safebrowsing.provider.mozilla.gethashURL", "");
-// tor-browser#42735: Disable recent search suggestions
-pref("browser.urlbar.recentsearches.featureGate", false);
-pref("browser.urlbar.suggest.recentsearches", false);
-
-// tor-browser#44262: Disable adding search engines from HTML forms
-pref("browser.urlbar.update2.engineAliasRefresh", false);
// Disable the UITour API
// See tor-browser#41457 and
@@ -770,14 +781,6 @@ pref("security.certerrors.mitm.auto_enable_enterprise_roots", false);
// Disable share menus on Mac and Windows tor-browser#41117
pref("browser.menu.share_url.allow", false, locked);
-// Disable special URL bar behaviors
-pref("browser.urlbar.suggest.topsites", false);
-pref("browser.urlbar.quicksuggest.enabled", false);
-pref("browser.urlbar.quicksuggest.online.available", false);
-pref("browser.urlbar.quicksuggest.online.enabled", false);
-pref("browser.urlbar.richSuggestions.featureGate", false);
-pref("browser.urlbar.yelp.featureGate", false);
-pref("browser.urlbar.mdn.featureGate", false);
// tor-browser#41884: Do not start a search when clicking on the new tab button
// with the middle mouse button (to prevent searching for anything you might
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/93114cd…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/93114cd…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0
[Git][tpo/applications/tor-browser][tor-browser-153.1.0esr-16.0-1] fixup! TB 34378: [android] Port external helper app prompting
by Dan Ballard (@dan) 19 Aug '26
by Dan Ballard (@dan) 19 Aug '26
19 Aug '26
Dan Ballard pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser
Commits:
cc01e661 by Dan Ballard at 2026-08-19T16:40:44-07:00
fixup! TB 34378: [android] Port external helper app prompting
TB 45221: Remove 'Manage Downloads with another app' pref from download settings
- - - - -
1 changed file:
- mobile/android/fenix/app/src/main/res/xml/downloads_settings_preferences.xml
Changes:
=====================================
mobile/android/fenix/app/src/main/res/xml/downloads_settings_preferences.xml
=====================================
@@ -32,10 +32,4 @@
</androidx.preference.PreferenceCategory>
- <SwitchPreferenceCompat
- android:defaultValue="false"
- android:key="@string/pref_key_external_download_manager"
- android:title="@string/preferences_choose_app_for_downloads"
- app:iconSpaceReserved="false"
- app:allowDividerAbove="true" />
</androidx.preference.PreferenceScreen>
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/cc01e66…
--
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/cc01e66…
You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
1
0