richard pushed to branch tor-browser-115.5.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits: 9d6ca8ac by Pier Angelo Vendrame at 2023-12-05T11:00:25+01:00 fixup! Bug 3455: Add DomainIsolator, for isolating circuit by domain.
Collect the browsers also on Android.
- - - - - 9e239230 by Pier Angelo Vendrame at 2023-12-05T11:08:42+01:00 fixup! Bug 40597: Implement TorSettings module
Moved the creation of Meek credentials to a function on its own that we will reuse also with the Android version of MeekTransport.
- - - - - 6a649d7f by Pier Angelo Vendrame at 2023-12-05T11:25:06+01:00 fixup! Bug 40933: Add tor-launcher functionality
Store the SOCKS settings as a member, so that we can customize them if needed before applying them.
Also, cleanup the public interface of TorProcess. E.g., removed TorProcess.connectionWorked, since we do not use this information anymore.
Finally, added a TorLauncherUtil.isAndroid.
- - - - - 1ad1d839 by Pier Angelo Vendrame at 2023-12-05T13:48:35+01:00 fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
HTML-ize about:torconnect.
Changed file extension, updated the HTML tag, removed short-tags on tags that are expected to have a closing tag. Also, removed the preprocessor and moved the onion pattern to this commit, since it is used only here.
- - - - - fbd5b4bb by Pier Angelo Vendrame at 2023-12-05T13:48:42+01:00 fixup! Bug 2176: Rebrand Firefox to TorBrowser
Move the onion pattern files to the commit of about:torconnect.
- - - - - 3649cc3f by Pier Angelo Vendrame at 2023-12-05T18:48:25+01:00 Temporary changes to about:torconnect for Android.
We are planning of tempoorarily using about:torconnect on Android, until the native UX is ready.
- - - - -
14 changed files:
- docshell/base/nsAboutRedirector.cpp - toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs - toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs - toolkit/components/tor-launcher/TorProcess.sys.mjs - toolkit/components/tor-launcher/TorProvider.sys.mjs - toolkit/components/torconnect/content/aboutTorConnect.css - toolkit/components/torconnect/content/aboutTorConnect.xhtml → toolkit/components/torconnect/content/aboutTorConnect.html - toolkit/components/torconnect/content/aboutTorConnect.js - toolkit/themes/shared/onionPattern.svg → toolkit/components/torconnect/content/onion-pattern.svg - toolkit/components/torconnect/jar.mn - toolkit/modules/Moat.sys.mjs - toolkit/themes/shared/minimal-toolkit.jar.inc.mn - − toolkit/themes/shared/onionPattern.css - − toolkit/themes/shared/onionPattern.inc.xhtml
Changes:
===================================== docshell/base/nsAboutRedirector.cpp ===================================== @@ -169,7 +169,7 @@ static const RedirEntry kRedirMap[] = { #endif {"telemetry", "chrome://global/content/aboutTelemetry.xhtml", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::IS_SECURE_CHROME_UI}, - {"torconnect", "chrome://global/content/torconnect/aboutTorConnect.xhtml", + {"torconnect", "chrome://global/content/torconnect/aboutTorConnect.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT |
===================================== toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs ===================================== @@ -475,9 +475,19 @@ class TorDomainIsolatorImpl { * @returns {MozBrowser?} The browser the channel is associated to */ #getBrowserForChannel(channel) { + const currentBrowser = + channel.loadInfo.browsingContext?.topChromeWindow?.browser; + if ( + channel.loadInfo.browsingContext && + currentBrowser?.browsingContext === channel.loadInfo.browsingContext + ) { + // Android has only one browser, and does not have the browsers property. + return currentBrowser; + } const browsers = channel.loadInfo.browsingContext?.topChromeWindow?.gBrowser?.browsers; if (!browsers || !channel.loadInfo.browsingContext?.browserId) { + logger.debug("Missing data to associate to a browser", channel.loadInfo); return null; } for (const browser of browsers) {
===================================== toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs ===================================== @@ -325,6 +325,10 @@ class TorFile { }
export const TorLauncherUtil = Object.freeze({ + get isAndroid() { + return Services.appinfo.OS === "Android"; + }, + get isMac() { return Services.appinfo.OS === "Darwin"; },
===================================== toolkit/components/tor-launcher/TorProcess.sys.mjs ===================================== @@ -33,8 +33,6 @@ export class TorProcess { #args = []; #subprocess = null; #status = TorProcessStatus.Unknown; - // Have we ever made a connection on the control port? - #didConnectToTorControlPort = false;
onExit = exitCode => {};
@@ -69,10 +67,6 @@ export class TorProcess { } }
- get status() { - return this.#status; - } - get isRunning() { return ( this.#status === TorProcessStatus.Starting || @@ -102,7 +96,6 @@ export class TorProcess { }
this.#status = TorProcessStatus.Starting; - this.#didConnectToTorControlPort = false;
// useful for simulating slow tor daemon launch const kPrefTorDaemonLaunchDelay = "extensions.torlauncher.launch_delay"; @@ -155,13 +148,6 @@ export class TorProcess { this.#status = TorProcessStatus.Exited; }
- // The owner of the process can use this function to tell us that they - // successfully connected to the control port. This information will be used - // only to decide which text to show in the confirmation dialog if tor exits. - connectionWorked() { - this.#didConnectToTorControlPort = true; - } - async #dumpStdout() { let string; while ( @@ -201,20 +187,6 @@ export class TorProcess { #processExitedUnexpectedly(exitCode) { this.#subprocess = null; this.#status = TorProcessStatus.Exited; - // FIXME: We can probably drop #didConnectToTorControlPort and use only one - // callback. Then we can let the provider actually distinguish between the - // cases. - if (!this.#didConnectToTorControlPort) { - logger.warn("Tor exited before we could connect to its control port."); - // tor might be misconfigured, because we could never connect to it. - // Two instances of Tor Browser trying to use the same port numbers is - // also a typical scenario for this. - // This might happen very early, before the browser UI is actually - // available. So, we will tell the process owner that the process exited, - // without trying to restart it. - this.onExit(exitCode); - return; - } logger.warn("Tor exited suddenly."); this.onExit(exitCode); }
===================================== toolkit/components/tor-launcher/TorProvider.sys.mjs ===================================== @@ -35,6 +35,15 @@ const logger = new ConsoleAPI({ * @property {string=} host The host to connect for a TCP control port * @property {number=} port The port number to use for a TCP control port */ +/** + * @typedef {object} SocksSettings An object that includes the proxy settings to + * be configured in the browser. + * @property {boolean=} transproxy If true, no proxy is configured + * @property {nsIFile=} ipcFile The nsIFile object with the path to a Unix + * socket to use for an IPC proxy + * @property {string=} host The host to connect for a TCP proxy + * @property {number=} port The port number to use for a TCP proxy + */ /** * @typedef {object} LogEntry An object with a log message * @property {Date} date The date at which we received the message @@ -111,6 +120,13 @@ export class TorProvider { */ #torProcess = null;
+ /** + * The settings for the SOCKS proxy. + * + * @type {SocksSettings?} + */ + #socksSettings = null; + /** * The logs we received over the control port. * We store a finite number of log entries which can be configured with @@ -165,8 +181,9 @@ export class TorProvider { async init() { logger.debug("Initializing the Tor provider.");
- const socksSettings = TorLauncherUtil.getPreferredSocksConfiguration(); - logger.debug("Requested SOCKS configuration", socksSettings); + // These settings might be customized in the following steps. + this.#socksSettings = TorLauncherUtil.getPreferredSocksConfiguration(); + logger.debug("Requested SOCKS configuration", this.#socksSettings);
try { await this.#setControlPortConfiguration(); @@ -175,11 +192,11 @@ export class TorProvider { throw e; }
- if (socksSettings.transproxy) { + if (this.#socksSettings.transproxy) { logger.info("Transparent proxy required, not starting a Tor daemon."); } else if (this.ownsTorDaemon) { try { - await this.#startDaemon(socksSettings); + await this.#startDaemon(); } catch (e) { logger.error("Failed to start the tor daemon", e); throw e; @@ -197,8 +214,7 @@ export class TorProvider { throw e; }
- // We do not customize SOCKS settings, at least for now. - TorLauncherUtil.setProxyConfiguration(socksSettings); + TorLauncherUtil.setProxyConfiguration(this.#socksSettings);
logger.info("The Tor provider is ready.");
@@ -464,7 +480,7 @@ export class TorProvider {
// Process management
- async #startDaemon(socksSettings) { + async #startDaemon() { // TorProcess should be instanced once, then always reused and restarted // only through the prompt it exposes when the controlled process dies. if (this.#torProcess) { @@ -476,7 +492,7 @@ export class TorProvider {
this.#torProcess = new lazy.TorProcess( this.#controlPortSettings, - socksSettings + this.#socksSettings ); // Use a closure instead of bind because we reassign #cancelConnection. // Also, we now assign an exit handler that cancels the first connection, @@ -619,7 +635,6 @@ export class TorProvider { } this.#openControlPort() .then(controller => { - this.#torProcess?.connectionWorked(); this.#cancelConnection = () => {}; // The cancel function should have already called reject. if (!canceled) {
===================================== toolkit/components/torconnect/content/aboutTorConnect.css ===================================== @@ -10,6 +10,11 @@ --onion-radius: 75px; }
+html { + width: 100%; + height: 100%; +} + input[type="checkbox"]:focus, select:focus { outline: none!important; box-shadow: 0 0 0 3px var(--purple-30) !important; @@ -330,3 +335,166 @@ body { background-image: url("chrome://global/content/torconnect/connection-location.svg"); stroke: var(--warning-color); } + +.onion-pattern-container { + flex: auto; /* grow to consume remaining space on the page */ + display: flex; + margin: 0 auto; + width: 100%; + /* two onions tall, 4x the radius */ + height: calc(4 * var(--onion-radius)); + max-height: calc(4 * var(--onion-radius)); + min-height: calc(4 * var(--onion-radius)); + direction: ltr; +} + +.onion-pattern-crop { + height: 100%; + width: 100%; + + -moz-context-properties: fill; + fill: var(--onion-color, currentColor); + /* opacity of the entire div, not context-opacity */ + opacity: var(--onion-opacity, 1); + + background-image: url("chrome://global/content/torconnect/onion-pattern.svg"); + background-repeat: repeat; + background-attachment: local; + background-position: center; + /* svg source is 6 onions wide and 2 onions tall */ + background-size: calc(6 * 2 * var(--onion-radius)) calc(2 * 2 * var(--onion-radius));; +} + +:root { + --android-dark-accents-buttons: #9059FF; + --android-dark-background-secondary: #E1E0E7; + --android-dark-text-primary: #FBFBFE; + --android-light-text-primary: #15141A; +} + +[hidden=true] { + display: none !important; +} + +body.android { + --onion-color: var(--android-dark-text-primary); + width: 100%; + height: 100%; + box-sizing: border-box; + margin: 0; + padding: 0 24px !important; + color: var(--onion-color); + background: linear-gradient(194deg, #692E9D -0.93%, #393270 48.91%); + font: menu; + font-size: 14px; + display: flex; +} + +.android #connectPageContainer { + max-width: none; + display: flex; + flex-direction: column; + flex: 1; +} + +.android #breadcrumbs { + display: none; +} + +.android #text-container { + display: flex; + flex-direction: column; + flex: 1; +} + +.android .title { + background-position: left 0; + background-repeat: no-repeat; + background-size: 40px; + padding-top: 64px; + font-size: 22px; + line-height: 28px; +} + +.android h1 { + font-weight: normal; + font-size: 100%; + margin: 0 0 16px 0; +} + +.android p { + margin: 0; + padding-bottom: 8px; + line-height: 20px; +} + +.android #quickstartContainer { + margin-top: 24px; +} + +.android .button-container { + display: flex; + flex: 1; + flex-direction: column; +} + +.android #locationDropdown { + width: 100%; + max-width: none; + margin: 0; +} + +.android select { + background: transparent; + border: none; + border-bottom: 1px solid var(--android-dark-text-primary); + color: var(--android-dark-text-primary); + display: block; + width: 100%; + margin-top: 10px; + padding: 8px; +} + +.android #buttonPadding { + flex: 1; +} + +.android #connectButtonContainer { + width: 100%; + padding-bottom: 18px; + display: grid; +} + +/* Be sure not to match the togglee */ +.android #connectButtonContainer button { + display: block; + width: 100%; + margin: 4px 0; + padding: 11px 30px; + font-size: 14px; + font-weight: 500; + border: none; + border-radius: 4px; +} + +.android #connectButton, .android #tryBridgeButton, .android #configureButton.primary { + color: var(--android-dark-text-primary); + background-color: var(--android-dark-accents-buttons); +} + +.android #configureButton { + order: 1; +} + +.android #restartButton { + order: 2; +} + +.android #restartButton, .android #cancelButton, .android #configureButton { + color: var(--android-light-text-primary); + background-color: var(--android-dark-background-secondary); +} + +.android .onion-pattern-container { + display: none; +}
===================================== toolkit/components/torconnect/content/aboutTorConnect.xhtml → toolkit/components/torconnect/content/aboutTorConnect.html ===================================== @@ -1,17 +1,12 @@ <!-- Copyright (c) 2021, The Tor Project, Inc. --> <!DOCTYPE html> -<html xmlns="http://www.w3.org/1999/xhtml"> +<html> <head> <meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" /> - <link - rel="stylesheet" - href="chrome://global/skin/onionPattern.css" - type="text/css" - media="all" - /> + <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="chrome://global/content/torconnect/aboutTorConnect.css" @@ -21,64 +16,69 @@ </head> <body> <div id="progressBar"> - <div id="progressBackground" /> - <div id="progressSolid" /> + <div id="progressBackground"></div> + <div id="progressSolid"></div> </div> <div id="connectPageContainer" class="container"> <div id="breadcrumbs" class="hidden"> <span id="connect-to-tor" class="breadcrumb-item"> - <span id="connect-to-tor-icon" class="breadcrumb-icon" /> - <span class="breadcrumb-label" /> + <span id="connect-to-tor-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> </span> <span id="connection-assist-separator" class="breadcrumb-separator breadcrumb-icon" - /> + ></span> <span id="connection-assist" class="breadcrumb-item"> - <span id="connection-assist-icon" class="breadcrumb-icon" /> - <span class="breadcrumb-label" /> + <span id="connection-assist-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> </span> <span id="try-bridge-separator" class="breadcrumb-separator breadcrumb-icon" - /> + ></span> <span id="try-bridge" class="breadcrumb-item"> - <span id="try-bridge-icon" class="breadcrumb-icon" /> - <span class="breadcrumb-label" /> + <span id="try-bridge-icon" class="breadcrumb-icon"></span> + <span class="breadcrumb-label"></span> </span> </div> <div id="text-container"> <div class="title"> - <h1 class="title-text" /> + <h1 class="title-text"></h1> </div> <div id="connectLongContent"> - <p id="connectLongContentText" /> + <p id="connectLongContentText"></p> </div> <div id="connectShortDesc"> - <p id="connectShortDescText" /> + <p id="connectShortDescText"></p> </div>
<button id="viewLogButton"></button>
<div id="quickstartContainer"> <input id="quickstartCheckbox" type="checkbox" /> - <label id="quickstartCheckboxLabel" for="quickstartCheckbox" /> + <label id="quickstartCheckboxLabel" for="quickstartCheckbox"></label> </div>
- <div id="connectButtonContainer" class="button-container"> - <button id="restartButton" hidden="true"></button> - <button id="configureButton" hidden="true"></button> - <button id="cancelButton" hidden="true"></button> - <button id="connectButton" class="primary" hidden="true"></button> - <label id="locationDropdownLabel" for="countries" /> + <div class="button-container"> + <label id="locationDropdownLabel" for="countries"></label> <form id="locationDropdown" hidden="true"> <select id="countries"></select> </form> - <button id="tryBridgeButton" class="primary" hidden="true"></button> + <span id="buttonPadding"></span> + <span id="connectButtonContainer"> + <button id="restartButton" hidden="true"></button> + <button id="configureButton" hidden="true"></button> + <button id="cancelButton" hidden="true"></button> + <button id="connectButton" class="primary" hidden="true"></button> + <button id="tryBridgeButton" class="primary" hidden="true"></button> + </span> </div> </div> </div> -#include ../../../themes/shared/onionPattern.inc.xhtml + <div class="onion-pattern-container"> + <div class="onion-pattern-crop"></div> + </div> + <script src="chrome://global/content/torconnect/aboutTorConnect.js"></script> </body> - <script src="chrome://global/content/torconnect/aboutTorConnect.js" /> </html>
===================================== toolkit/components/torconnect/content/aboutTorConnect.js ===================================== @@ -70,8 +70,8 @@ class AboutTorConnect { connect: "button#connectButton", tryBridge: "button#tryBridgeButton", locationDropdownLabel: "#locationDropdownLabel", - locationDropdown: "form#locationDropdown", - locationDropdownSelect: "form#locationDropdown select", + locationDropdown: "#locationDropdown", + locationDropdownSelect: "#locationDropdown select", }, });
@@ -666,6 +666,9 @@ class AboutTorConnect { }
initElements(direction) { + const isAndroid = navigator.userAgent.indexOf("Android") !== -1; + document.body.classList.toggle("android", isAndroid); + document.documentElement.setAttribute("dir", direction);
this.elements.connectToTorLink.addEventListener("click", event => {
===================================== toolkit/themes/shared/onionPattern.svg → toolkit/components/torconnect/content/onion-pattern.svg =====================================
===================================== toolkit/components/torconnect/jar.mn ===================================== @@ -3,12 +3,13 @@ toolkit.jar: content/global/torconnect/torConnectTitlebarStatus.js (content/torConnectTitlebarStatus.js) content/global/torconnect/torConnectTitlebarStatus.css (content/torConnectTitlebarStatus.css) content/global/torconnect/aboutTorConnect.css (content/aboutTorConnect.css) -* content/global/torconnect/aboutTorConnect.xhtml (content/aboutTorConnect.xhtml) + content/global/torconnect/aboutTorConnect.html (content/aboutTorConnect.html) content/global/torconnect/aboutTorConnect.js (content/aboutTorConnect.js) content/global/torconnect/arrow-right.svg (content/arrow-right.svg) content/global/torconnect/bridge.svg (content/bridge.svg) content/global/torconnect/connection-failure.svg (content/connection-failure.svg) content/global/torconnect/connection-location.svg (content/connection-location.svg) + content/global/torconnect/onion-pattern.svg (content/onion-pattern.svg) content/global/torconnect/tor-connect.svg (content/tor-connect.svg) content/global/torconnect/tor-not-connected-to-connected-animated.svg (content/tor-not-connected-to-connected-animated.svg) content/global/torconnect/tor-connect-broken.svg (content/tor-connect-broken.svg)
===================================== toolkit/modules/Moat.sys.mjs ===================================== @@ -21,6 +21,56 @@ const TorLauncherPrefs = Object.freeze({ moat_service: "extensions.torlauncher.moat_service", });
+function makeMeekCredentials(proxyType) { + // Construct the per-connection arguments. + let meekClientEscapedArgs = ""; + const meekReflector = Services.prefs.getStringPref( + TorLauncherPrefs.bridgedb_reflector + ); + + // Escape aValue per section 3.5 of the PT specification: + // First the "<Key>=<Value>" formatted arguments MUST be escaped, + // such that all backslash, equal sign, and semicolon characters + // are escaped with a backslash. + const escapeArgValue = aValue => + aValue + ? aValue + .replaceAll("\", "\\") + .replaceAll("=", "\=") + .replaceAll(";", "\;") + : ""; + + if (meekReflector) { + meekClientEscapedArgs += "url="; + meekClientEscapedArgs += escapeArgValue(meekReflector); + } + const meekFront = Services.prefs.getStringPref( + TorLauncherPrefs.bridgedb_front + ); + if (meekFront) { + if (meekClientEscapedArgs.length) { + meekClientEscapedArgs += ";"; + } + meekClientEscapedArgs += "front="; + meekClientEscapedArgs += escapeArgValue(meekFront); + } + + // socks5 + if (proxyType === "socks") { + if (meekClientEscapedArgs.length <= 255) { + return [meekClientEscapedArgs, "\x00"]; + } else { + return [ + meekClientEscapedArgs.substring(0, 255), + meekClientEscapedArgs.substring(255), + ]; + } + // socks4 + } else { + return [meekClientEscapedArgs, undefined]; + } +} + // // Launches and controls the PT process lifetime // @@ -70,39 +120,6 @@ class MeekTransport { proxy.pathToBinary = meekPath.path; }
- // Construct the per-connection arguments. - let meekClientEscapedArgs = ""; - const meekReflector = Services.prefs.getStringPref( - TorLauncherPrefs.bridgedb_reflector - ); - - // Escape aValue per section 3.5 of the PT specification: - // First the "<Key>=<Value>" formatted arguments MUST be escaped, - // such that all backslash, equal sign, and semicolon characters - // are escaped with a backslash. - const escapeArgValue = aValue => - aValue - ? aValue - .replaceAll("\", "\\") - .replaceAll("=", "\=") - .replaceAll(";", "\;") - : ""; - - if (meekReflector) { - meekClientEscapedArgs += "url="; - meekClientEscapedArgs += escapeArgValue(meekReflector); - } - const meekFront = Services.prefs.getStringPref( - TorLauncherPrefs.bridgedb_front - ); - if (meekFront) { - if (meekClientEscapedArgs.length) { - meekClientEscapedArgs += ";"; - } - meekClientEscapedArgs += "front="; - meekClientEscapedArgs += escapeArgValue(meekFront); - } - // Setup env and start meek process const ptStateDir = lazy.TorLauncherUtil.getTorFile("tordatadir", false); ptStateDir.append("pt_state"); // Match what tor uses. @@ -247,22 +264,9 @@ class MeekTransport { this.#meekClientProcess = null; this.uninit(); }); - - // socks5 - if (this.proxyType === "socks") { - if (meekClientEscapedArgs.length <= 255) { - this.proxyUsername = meekClientEscapedArgs; - this.proxyPassword = "\x00"; - } else { - this.proxyUsername = meekClientEscapedArgs.substring(0, 255); - this.proxyPassword = meekClientEscapedArgs.substring(255); - } - // socks4 - } else { - this.proxyUsername = meekClientEscapedArgs; - this.proxyPassword = undefined; - } - + [this.proxyUsername, this.proxyPassword] = makeMeekCredentials( + this.proxyType + ); this.#inited = true; } catch (ex) { if (this.#meekClientProcess) { @@ -403,7 +407,7 @@ export class MoatRPC { throw new Error("MoatRPC: Already initialized"); }
- let meekTransport = new MeekTransport(); + const meekTransport = new MeekTransport(); await meekTransport.init(); this.#meekTransport = meekTransport; this.#inited = true;
===================================== toolkit/themes/shared/minimal-toolkit.jar.inc.mn ===================================== @@ -47,7 +47,3 @@ toolkit.jar: skin/classic/global/media/textrecognition.css (../../shared/media/textrecognition.css)
skin/classic/global/browser-colors.css (../../shared/browser-colors.css) - -# Tor customization - skin/classic/global/onionPattern.css (../../shared/onionPattern.css) - skin/classic/global/onionPattern.svg (../../shared/onionPattern.svg)
===================================== toolkit/themes/shared/onionPattern.css deleted ===================================== @@ -1,31 +0,0 @@ -/* Onion pattern */ - -.onion-pattern-container { - - flex: auto; /* grow to consume remaining space on the page */ - display: flex; - margin: 0 auto; - width: 100%; - /* two onions tall, 4x the radius */ - height: calc(4 * var(--onion-radius)); - max-height: calc(4 * var(--onion-radius)); - min-height: calc(4 * var(--onion-radius)); - direction: ltr; -} - -.onion-pattern-crop { - height: 100%; - width: 100%; - - -moz-context-properties: fill; - fill: var(--onion-color, currentColor); - /* opacity of the entire div, not context-opacity */ - opacity: var(--onion-opacity, 1); - - background-image: url("chrome://global/skin/onionPattern.svg"); - background-repeat: repeat; - background-attachment: local; - background-position: center; - /* svg source is 6 onions wide and 2 onions tall */ - background-size: calc(6 * 2 * var(--onion-radius)) calc(2 * 2 * var(--onion-radius));; -}
===================================== toolkit/themes/shared/onionPattern.inc.xhtml deleted ===================================== @@ -1,12 +0,0 @@ -<!-- - Container div that holds onionPattern.svg - It is expected the includer of this xhtml file also includes onionPattern.css - and define the following vars: - onion-radius : radius of an onion - onion-color : the base color of the onion pattern - onion-opacity : the opacity of the entire repeating pattern ---> - -<div class="onion-pattern-container"> - <div class="onion-pattern-crop"/> -</div> \ No newline at end of file
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/410b9a4...
tbb-commits@lists.torproject.org