[tbb-commits] [tor-browser/tor-browser-78.12.0esr-11.0-1] fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser

sysrqb at torproject.org sysrqb at torproject.org
Mon Aug 2 23:18:37 UTC 2021


commit b3a4fa8c7cdc5c2c013376b3a34458efa342479c
Author: Richard Pospesel <richard at torproject.org>
Date:   Thu Jul 29 17:57:39 2021 +0200

    fixup! Bug 27476: Implement about:torconnect captive portal within Tor Browser
---
 browser/base/content/aboutNetError.js              |  4 +-
 browser/base/content/browser.js                    | 65 +++++++++-------
 browser/base/content/browser.xhtml                 |  1 +
 browser/base/content/utilityOverlay.js             |  8 ++
 .../alpha/content/identity-icons-brand.svg         | 26 +------
 browser/branding/alpha/content/jar.mn              |  1 +
 browser/branding/alpha/content/tor-styles.css      | 13 ++++
 .../nightly/content/identity-icons-brand.svg       | 30 +-------
 browser/branding/nightly/content/jar.mn            |  1 +
 browser/branding/nightly/content/tor-styles.css    | 13 ++++
 .../official/content/identity-icons-brand.svg      | 32 +-------
 browser/branding/official/content/jar.mn           |  1 +
 browser/branding/official/content/tor-styles.css   | 14 ++++
 browser/branding/tor-styles.inc.css                | 87 ++++++++++++++++++++++
 browser/components/BrowserGlue.jsm                 |  2 +-
 browser/components/sessionstore/SessionStore.jsm   | 12 ---
 browser/components/torconnect/TorConnectParent.jsm | 12 ++-
 .../torconnect/content/aboutTorConnect.css         | 24 +++---
 .../torconnect/content/aboutTorConnect.js          | 39 +++++++---
 .../torconnect/content/torBootstrapUrlbar.js       |  6 +-
 .../torconnect/content/torconnect-urlbar.css       | 36 ++++-----
 .../torconnect/content/torconnect-urlbar.inc.xhtml |  1 -
 .../torpreferences/content/torPreferences.css      | 16 ++--
 browser/modules/TorConnect.jsm                     | 78 +++++++++++--------
 browser/modules/TorStrings.jsm                     |  5 ++
 .../shared/identity-block/identity-block.inc.css   | 16 +---
 26 files changed, 321 insertions(+), 222 deletions(-)

diff --git a/browser/base/content/aboutNetError.js b/browser/base/content/aboutNetError.js
index 6844154e16e3..32bd5576de3e 100644
--- a/browser/base/content/aboutNetError.js
+++ b/browser/base/content/aboutNetError.js
@@ -202,7 +202,9 @@ async function initPage() {
     (err === "proxyConnectFailure") &&
     (await RPMSendQuery("ShouldShowTorConnect"))
   ) {
-    document.location.replace("about:torconnect");
+    // pass orginal destination as redirect param
+    const encodedRedirect = encodeURIComponent(document.location.href);
+    document.location.replace(`about:torconnect?redirect=${encodedRedirect}`);
   }
   // List of error pages with an illustration.
   let illustratedErrors = [
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index 996ef6dcdd7f..37d67f7680af 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2494,37 +2494,48 @@ var gBrowserInit = {
       let uri = window.arguments[0];
       let defaultArgs = BrowserHandler.defaultArgs;
 
-      if (TorConnect.shouldShowTorConnect) {
-        TorConnect.setURIsToLoad(uri);
-        return "about:torconnect";
-      }
-
-      // If the given URI is different from the homepage, we want to load it.
-      if (uri != defaultArgs) {
-        AboutNewTab.noteNonDefaultStartup();
+      // figure out which URI to actually load (or a Promise to get the uri)
+      uri = ((uri) => {
+        // If the given URI is different from the homepage, we want to load it.
+        if (uri != defaultArgs) {
+          AboutNewTab.noteNonDefaultStartup();
+
+          if (uri instanceof Ci.nsIArray) {
+            // Transform the nsIArray of nsISupportsString's into a JS Array of
+            // JS strings.
+            return Array.from(
+              uri.enumerate(Ci.nsISupportsString),
+              supportStr => supportStr.data
+            );
+          } else if (uri instanceof Ci.nsISupportsString) {
+            return uri.data;
+          }
+          return uri;
+        }
 
-        if (uri instanceof Ci.nsIArray) {
-          // Transform the nsIArray of nsISupportsString's into a JS Array of
-          // JS strings.
-          return Array.from(
-            uri.enumerate(Ci.nsISupportsString),
-            supportStr => supportStr.data
-          );
-        } else if (uri instanceof Ci.nsISupportsString) {
-          return uri.data;
+        // The URI appears to be the the homepage. We want to load it only if
+        // session restore isn't about to override the homepage.
+        let willOverride = SessionStartup.willOverrideHomepage;
+        if (typeof willOverride == "boolean") {
+          return willOverride ? null : uri;
         }
-        return uri;
-      }
+        return willOverride.then(willOverrideHomepage =>
+          willOverrideHomepage ? null : uri
+        );
+      })(uri);
 
-      // The URI appears to be the the homepage. We want to load it only if
-      // session restore isn't about to override the homepage.
-      let willOverride = SessionStartup.willOverrideHomepage;
-      if (typeof willOverride == "boolean") {
-        return willOverride ? null : uri;
+      // if using TorConnect, convert these uris to redirects
+      if (TorConnect.shouldShowTorConnect) {
+        return Promise.resolve(uri).then((uri) => {
+          if (uri == null) {
+            uri  = [];
+          }
+
+          uri = TorConnect.getURIsToLoad(uri);
+          return uri;
+        });
       }
-      return willOverride.then(willOverrideHomepage =>
-        willOverrideHomepage ? null : uri
-      );
+      return uri;
     })());
   },
 
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
index 032db1967c69..134ab8e087e1 100644
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -10,6 +10,7 @@
      override rules using selectors with the same specificity. This applies to
      both "content" and "skin" packages, which bug 1385444 will unify later. -->
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="chrome://branding/content/tor-styles.css" type="text/css"?>
 
 <!-- While these stylesheets are defined in Toolkit, they are only used in the
      main browser window, so we can load them here. Bug 1474241 is on file to
diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js
index eb13d5a3435c..0b3bdde4b5d4 100644
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -20,6 +20,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
   ExtensionSettingsStore: "resource://gre/modules/ExtensionSettingsStore.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ShellService: "resource:///modules/ShellService.jsm",
+  TorConnect: "resource:///modules/TorConnect.jsm",
 });
 
 XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
@@ -335,6 +336,13 @@ function openUILinkIn(
   aPostData,
   aReferrerInfo
 ) {
+
+  // make sure users are not faced with the scary red 'tor isn't working' screen
+  // if they navigate to about:tor before bootstrapped
+  if (url === "about:tor" && TorConnect.shouldShowTorConnect) {
+    url = `about:torconnect?redirect=${encodeURIComponent("about:tor")}`;
+  }
+
   var params;
 
   if (arguments.length == 3 && typeof arguments[2] == "object") {
diff --git a/browser/branding/alpha/content/identity-icons-brand.svg b/browser/branding/alpha/content/identity-icons-brand.svg
index 9bfa43842e2d..30cd52ba5c51 100644
--- a/browser/branding/alpha/content/identity-icons-brand.svg
+++ b/browser/branding/alpha/content/identity-icons-brand.svg
@@ -1,25 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="512px" height="512px" viewBox="-17 -17 546 546" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <defs>
-        <linearGradient x1="50%" y1="3.27248873%" x2="50%" y2="97.1599968%" id="linearGradient-1">
-            <stop stop-color="#00FEFF" offset="0%"></stop>
-            <stop stop-color="#0BE67D" offset="100%"></stop>
-        </linearGradient>
-        <path d="M25,25 C152.50841,25 255.874399,127.979815 255.874399,255.011855 C255.874399,382.043895 152.50841,485.02371 25,485.02371 L25,25 Z" id="path-2"></path>
-        <filter x="-20.8%" y="-8.7%" width="134.7%" height="117.4%" filterUnits="objectBoundingBox" id="filter-3">
-            <feOffset dx="-8" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
-            <feGaussianBlur stdDeviation="12" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
-            <feColorMatrix values="0 0 0 0 0.0872579578   0 0 0 0 0.00490370801   0 0 0 0 0.234933036  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
-        </filter>
-    </defs>
-    <g id="Alpha" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g>
-            <circle id="background" fill-opacity="0.9" fill="#030004" fill-rule="nonzero" cx="256" cy="256" r="246"></circle>
-            <path d="M256.525143,465.439707 L256.525143,434.406609 C354.826191,434.122748 434.420802,354.364917 434.420802,255.992903 C434.420802,157.627987 354.826191,77.8701558 256.525143,77.5862948 L256.525143,46.5531962 C371.964296,46.8441537 465.446804,140.489882 465.446804,255.992903 C465.446804,371.503022 371.964296,465.155846 256.525143,465.439707 Z M256.525143,356.820314 C311.970283,356.529356 356.8487,311.516106 356.8487,255.992903 C356.8487,200.476798 311.970283,155.463547 256.525143,155.17259 L256.525143,124.146588 C329.115485,124.430449 387.881799,183.338693 387.881799,255.992903 C387.881799,328.654211 329.115485,387.562455 256.525143,387.846316 L256.525143,356.820314 Z M256.525143,201.718689 C286.266674,202.00255 310.3026,226.180407 310.3026,255.992903 C310.3026,285.812497 286.266674,309.990353 256.525143,310.274214 L256.525143,201.718689 Z M0,255.992903 C0,397.384044 114.60886,512 256,512 C397.384044,512 512,397.384044 512,255.992903 C512,114.60886 397.384044,2.842170
 94e-14 256,2.84217094e-14 C114.60886,2.84217094e-14 0,114.60886 0,255.992903 Z" id="center" fill="url(#linearGradient-1)"></path>
-            <g id="half" transform="translate(140.437200, 255.011855) scale(-1, 1) translate(-140.437200, -255.011855) ">
-                <use fill="black" fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-2"></use>
-                <use fill="url(#linearGradient-1)" fill-rule="evenodd" xlink:href="#path-2"></use>
-            </g>
-        </g>
-    </g>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+  <path fill="context-fill" fill-opacity="context-fill-opacity" d="M12.0246161,21.8174863 L12.0246161,20.3628098 C16.6324777,20.3495038 20.3634751,16.6108555 20.3634751,11.9996673 C20.3634751,7.38881189 16.6324777,3.65016355 12.0246161,3.63685757 L12.0246161,2.18218107 C17.4358264,2.1958197 21.8178189,6.58546322 21.8178189,11.9996673 C21.8178189,17.4142042 17.4358264,21.8041803 12.0246161,21.8174863 L12.0246161,21.8174863 Z M12.0246161,16.7259522 C14.623607,16.7123136 16.7272828,14.6023175 16.7272828,11.9996673 C16.7272828,9.39734991 14.623607,7.28735377 12.0246161,7.27371516 L12.0246161,5.81937131 C15.4272884,5.8326773 18.1819593,8.59400123 18.1819593,11.9996673 C18.1819593,15.4056661 15.4272884,18.1669901 12.0246161,18.1802961 L12.0246161,16.7259522 Z M12.0246161,9.45556355 C13.4187503,9.46886953 14.5454344,10.6022066 14.5454344,11.9996673 C14.5454344,13.3974608 13.4187503,14.5307978 12.0246161,14.5441038 L12.0246161,9.45556355 Z M0,11.9996673 C0,18.6273771 5.37229031,24 12,24 C18
 .6273771,24 24,18.6273771 24,11.9996673 C24,5.37229031 18.6273771,0 12,0 C5.37229031,0 0,5.37229031 0,11.9996673 Z"/>
 </svg>
\ No newline at end of file
diff --git a/browser/branding/alpha/content/jar.mn b/browser/branding/alpha/content/jar.mn
index de166fe3636f..5dd066c27f9c 100644
--- a/browser/branding/alpha/content/jar.mn
+++ b/browser/branding/alpha/content/jar.mn
@@ -20,3 +20,4 @@ browser.jar:
   content/branding/identity-icons-brand.svg
   content/branding/aboutDialog.css
   content/branding/horizontal-lockup.svg
+* content/branding/tor-styles.css
diff --git a/browser/branding/alpha/content/tor-styles.css b/browser/branding/alpha/content/tor-styles.css
new file mode 100644
index 000000000000..14c1915ef871
--- /dev/null
+++ b/browser/branding/alpha/content/tor-styles.css
@@ -0,0 +1,13 @@
+%include ../../tor-styles.inc.css
+
+/* default theme*/
+:root,
+/* light theme*/
+:root:-moz-lwtheme-darktext {
+    --tor-branding-color: var(--teal-70);
+}
+
+/* dark theme */
+:root:-moz-lwtheme-brighttext {
+    --tor-branding-color: var(--teal-60);
+}
\ No newline at end of file
diff --git a/browser/branding/nightly/content/identity-icons-brand.svg b/browser/branding/nightly/content/identity-icons-brand.svg
index fc1d9c997aeb..30cd52ba5c51 100644
--- a/browser/branding/nightly/content/identity-icons-brand.svg
+++ b/browser/branding/nightly/content/identity-icons-brand.svg
@@ -1,29 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="512px" height="512px" viewBox="-17 -17 546 546" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <defs>
-        <linearGradient x1="25.1281738%" y1="5.44281006%" x2="54.3792725%" y2="100%" id="linearGradient-1">
-            <stop stop-color="#00E1E8" offset="0%"></stop>
-            <stop stop-color="#3500FF" offset="100%"></stop>
-        </linearGradient>
-        <linearGradient x1="25.1281738%" y1="5.44281006%" x2="54.3792725%" y2="100%" id="linearGradient-2">
-            <stop stop-color="#00E1E8" offset="0%"></stop>
-            <stop stop-color="#3500FF" offset="100%"></stop>
-        </linearGradient>
-        <path d="M25,25 C152.50841,25 255.874399,127.979815 255.874399,255.011855 C255.874399,382.043895 152.50841,485.02371 25,485.02371 L25,25 Z" id="path-3"></path>
-        <filter x="-20.8%" y="-8.7%" width="134.7%" height="117.4%" filterUnits="objectBoundingBox" id="filter-4">
-            <feOffset dx="-8" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
-            <feGaussianBlur stdDeviation="12" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
-            <feColorMatrix values="0 0 0 0 0.0872579578   0 0 0 0 0.00490370801   0 0 0 0 0.234933036  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
-        </filter>
-    </defs>
-    <g id="Nightly" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g>
-            <circle id="background" fill-opacity="0.9" fill="#030004" fill-rule="nonzero" cx="256" cy="256" r="246"></circle>
-            <path d="M256.525143,465.439707 L256.525143,434.406609 C354.826191,434.122748 434.420802,354.364917 434.420802,255.992903 C434.420802,157.627987 354.826191,77.8701558 256.525143,77.5862948 L256.525143,46.5531962 C371.964296,46.8441537 465.446804,140.489882 465.446804,255.992903 C465.446804,371.503022 371.964296,465.155846 256.525143,465.439707 Z M256.525143,356.820314 C311.970283,356.529356 356.8487,311.516106 356.8487,255.992903 C356.8487,200.476798 311.970283,155.463547 256.525143,155.17259 L256.525143,124.146588 C329.115485,124.430449 387.881799,183.338693 387.881799,255.992903 C387.881799,328.654211 329.115485,387.562455 256.525143,387.846316 L256.525143,356.820314 Z M256.525143,201.718689 C286.266674,202.00255 310.3026,226.180407 310.3026,255.992903 C310.3026,285.812497 286.266674,309.990353 256.525143,310.274214 L256.525143,201.718689 Z M0,255.992903 C0,397.384044 114.60886,512 256,512 C397.384044,512 512,397.384044 512,255.992903 C512,114.60886 397.384044,2.842170
 94e-14 256,2.84217094e-14 C114.60886,2.84217094e-14 0,114.60886 0,255.992903 Z" id="center" fill="url(#linearGradient-1)"></path>
-            <g id="half" transform="translate(140.437200, 255.011855) scale(-1, 1) translate(-140.437200, -255.011855) ">
-                <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-3"></use>
-                <use fill="url(#linearGradient-2)" fill-rule="evenodd" xlink:href="#path-3"></use>
-            </g>
-        </g>
-    </g>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+  <path fill="context-fill" fill-opacity="context-fill-opacity" d="M12.0246161,21.8174863 L12.0246161,20.3628098 C16.6324777,20.3495038 20.3634751,16.6108555 20.3634751,11.9996673 C20.3634751,7.38881189 16.6324777,3.65016355 12.0246161,3.63685757 L12.0246161,2.18218107 C17.4358264,2.1958197 21.8178189,6.58546322 21.8178189,11.9996673 C21.8178189,17.4142042 17.4358264,21.8041803 12.0246161,21.8174863 L12.0246161,21.8174863 Z M12.0246161,16.7259522 C14.623607,16.7123136 16.7272828,14.6023175 16.7272828,11.9996673 C16.7272828,9.39734991 14.623607,7.28735377 12.0246161,7.27371516 L12.0246161,5.81937131 C15.4272884,5.8326773 18.1819593,8.59400123 18.1819593,11.9996673 C18.1819593,15.4056661 15.4272884,18.1669901 12.0246161,18.1802961 L12.0246161,16.7259522 Z M12.0246161,9.45556355 C13.4187503,9.46886953 14.5454344,10.6022066 14.5454344,11.9996673 C14.5454344,13.3974608 13.4187503,14.5307978 12.0246161,14.5441038 L12.0246161,9.45556355 Z M0,11.9996673 C0,18.6273771 5.37229031,24 12,24 C18
 .6273771,24 24,18.6273771 24,11.9996673 C24,5.37229031 18.6273771,0 12,0 C5.37229031,0 0,5.37229031 0,11.9996673 Z"/>
 </svg>
\ No newline at end of file
diff --git a/browser/branding/nightly/content/jar.mn b/browser/branding/nightly/content/jar.mn
index de166fe3636f..5dd066c27f9c 100644
--- a/browser/branding/nightly/content/jar.mn
+++ b/browser/branding/nightly/content/jar.mn
@@ -20,3 +20,4 @@ browser.jar:
   content/branding/identity-icons-brand.svg
   content/branding/aboutDialog.css
   content/branding/horizontal-lockup.svg
+* content/branding/tor-styles.css
diff --git a/browser/branding/nightly/content/tor-styles.css b/browser/branding/nightly/content/tor-styles.css
new file mode 100644
index 000000000000..52e1761e5459
--- /dev/null
+++ b/browser/branding/nightly/content/tor-styles.css
@@ -0,0 +1,13 @@
+%include ../../tor-styles.inc.css
+
+/* default theme*/
+:root,
+/* light theme*/
+:root:-moz-lwtheme-darktext {
+    --tor-branding-color: var(--blue-60);
+}
+
+/* dark theme */
+:root:-moz-lwtheme-brighttext {
+    --tor-branding-color: var(--blue-40);
+}
\ No newline at end of file
diff --git a/browser/branding/official/content/identity-icons-brand.svg b/browser/branding/official/content/identity-icons-brand.svg
index 62472ad1826e..30cd52ba5c51 100644
--- a/browser/branding/official/content/identity-icons-brand.svg
+++ b/browser/branding/official/content/identity-icons-brand.svg
@@ -1,31 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="512px" height="512px" viewBox="-17 -17 546 546" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <defs>
-        <linearGradient x1="50%" y1="100%" x2="50%" y2="0%" id="linearGradient-1">
-            <stop stop-color="#420C5D" offset="0%"></stop>
-            <stop stop-color="#951AD1" offset="100%"></stop>
-        </linearGradient>
-        <path d="M25,29 C152.577777,29 256,131.974508 256,259 C256,386.025492 152.577777,489 25,489 L25,29 Z" id="path-2"></path>
-        <filter x="-18.2%" y="-7.4%" width="129.4%" height="114.8%" filterUnits="objectBoundingBox" id="filter-3">
-            <feOffset dx="-8" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
-            <feGaussianBlur stdDeviation="10" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
-            <feColorMatrix values="0 0 0 0 0.250980392   0 0 0 0 0.250980392   0 0 0 0 0.250980392  0 0 0 0.2 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
-        </filter>
-    </defs>
-    <g id="Assets" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="icon_512x512">
-            <g id="Group">
-                <g id="tb_icon/Stable">
-                    <g id="Stable">
-                        <circle id="background" fill="#F2E4FF" fill-rule="nonzero" cx="256" cy="256" r="246"></circle>
-                        <path d="M256.525143,465.439707 L256.525143,434.406609 C354.826191,434.122748 434.420802,354.364917 434.420802,255.992903 C434.420802,157.627987 354.826191,77.8701558 256.525143,77.5862948 L256.525143,46.5531962 C371.964296,46.8441537 465.446804,140.489882 465.446804,255.992903 C465.446804,371.503022 371.964296,465.155846 256.525143,465.439707 Z M256.525143,356.820314 C311.970283,356.529356 356.8487,311.516106 356.8487,255.992903 C356.8487,200.476798 311.970283,155.463547 256.525143,155.17259 L256.525143,124.146588 C329.115485,124.430449 387.881799,183.338693 387.881799,255.992903 C387.881799,328.654211 329.115485,387.562455 256.525143,387.846316 L256.525143,356.820314 Z M256.525143,201.718689 C286.266674,202.00255 310.3026,226.180407 310.3026,255.992903 C310.3026,285.812497 286.266674,309.990353 256.525143,310.274214 L256.525143,201.718689 Z M0,255.992903 C0,397.384044 114.60886,512 256,512 C397.384044,512 512,397.384044 512,255.992903 C512,114.60886 397.384
 044,0 256,0 C114.60886,0 0,114.60886 0,255.992903 Z" id="center" fill="url(#linearGradient-1)"></path>
-                        <g id="half" transform="translate(140.500000, 259.000000) scale(-1, 1) translate(-140.500000, -259.000000) ">
-                            <use fill="black" fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-2"></use>
-                            <use fill="url(#linearGradient-1)" fill-rule="evenodd" xlink:href="#path-2"></use>
-                        </g>
-                    </g>
-                </g>
-            </g>
-        </g>
-    </g>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+  <path fill="context-fill" fill-opacity="context-fill-opacity" d="M12.0246161,21.8174863 L12.0246161,20.3628098 C16.6324777,20.3495038 20.3634751,16.6108555 20.3634751,11.9996673 C20.3634751,7.38881189 16.6324777,3.65016355 12.0246161,3.63685757 L12.0246161,2.18218107 C17.4358264,2.1958197 21.8178189,6.58546322 21.8178189,11.9996673 C21.8178189,17.4142042 17.4358264,21.8041803 12.0246161,21.8174863 L12.0246161,21.8174863 Z M12.0246161,16.7259522 C14.623607,16.7123136 16.7272828,14.6023175 16.7272828,11.9996673 C16.7272828,9.39734991 14.623607,7.28735377 12.0246161,7.27371516 L12.0246161,5.81937131 C15.4272884,5.8326773 18.1819593,8.59400123 18.1819593,11.9996673 C18.1819593,15.4056661 15.4272884,18.1669901 12.0246161,18.1802961 L12.0246161,16.7259522 Z M12.0246161,9.45556355 C13.4187503,9.46886953 14.5454344,10.6022066 14.5454344,11.9996673 C14.5454344,13.3974608 13.4187503,14.5307978 12.0246161,14.5441038 L12.0246161,9.45556355 Z M0,11.9996673 C0,18.6273771 5.37229031,24 12,24 C18
 .6273771,24 24,18.6273771 24,11.9996673 C24,5.37229031 18.6273771,0 12,0 C5.37229031,0 0,5.37229031 0,11.9996673 Z"/>
 </svg>
\ No newline at end of file
diff --git a/browser/branding/official/content/jar.mn b/browser/branding/official/content/jar.mn
index de166fe3636f..5dd066c27f9c 100644
--- a/browser/branding/official/content/jar.mn
+++ b/browser/branding/official/content/jar.mn
@@ -20,3 +20,4 @@ browser.jar:
   content/branding/identity-icons-brand.svg
   content/branding/aboutDialog.css
   content/branding/horizontal-lockup.svg
+* content/branding/tor-styles.css
diff --git a/browser/branding/official/content/tor-styles.css b/browser/branding/official/content/tor-styles.css
new file mode 100644
index 000000000000..e4ccb5c767a9
--- /dev/null
+++ b/browser/branding/official/content/tor-styles.css
@@ -0,0 +1,14 @@
+%include ../../tor-styles.inc.css
+
+/* default theme*/
+:root,
+/* light theme*/
+:root:-moz-lwtheme-darktext {
+    --tor-branding-color: var(--purple-60);
+}
+
+/* dark theme */
+:root:-moz-lwtheme-brighttext {
+    --tor-branding-color: var(--purple-30);
+}
+
diff --git a/browser/branding/tor-styles.inc.css b/browser/branding/tor-styles.inc.css
new file mode 100644
index 000000000000..55dc9b6238b3
--- /dev/null
+++ b/browser/branding/tor-styles.inc.css
@@ -0,0 +1,87 @@
+:root {
+  /* photon colors, not all of them are available for whatever reason
+     in firefox, so here they are */
+
+  --magenta-50: #ff1ad9;
+  --magenta-60: #ed00b5;
+  --magenta-70: #b5007f;
+  --magenta-80: #7d004f;
+  --magenta-90: #440027;
+
+  --purple-30: #c069ff;
+  --purple-40: #ad3bff;
+  --purple-50: #9400ff;
+  --purple-60: #8000d7;
+  --purple-70: #6200a4;
+  --purple-80: #440071;
+  --purple-90: #25003e;
+
+  --blue-40: #45a1ff;
+  --blue-50: #0a84ff;
+  --blue-50-a30: rgba(10, 132, 255, 0.3);
+  --blue-60: #0060df;
+  --blue-70: #003eaa;
+  --blue-80: #002275;
+  --blue-90: #000f40;
+
+  --teal-50: #00feff;
+  --teal-60: #00c8d7;
+  --teal-70: #008ea4;
+  --teal-80: #005a71;
+  --teal-90: #002d3e;
+
+  --green-50: #30e60b;
+  --green-60: #12bc00;
+  --green-70: #058b00;
+  --green-80: #006504;
+  --green-90: #003706;
+
+  --yellow-50: #ffe900;
+  --yellow-60: #d7b600;
+  --yellow-70: #a47f00;
+  --yellow-80: #715100;
+  --yellow-90: #3e2800;
+
+  --red-50: #ff0039;
+  --red-60: #d70022;
+  --red-70: #a4000f;
+  --red-80: #5a0002;
+  --red-90: #3e0200;
+
+  --orange-50: #ff9400;
+  --orange-60: #d76e00;
+  --orange-70: #a44900;
+  --orange-80: #712b00;
+  --orange-90: #3e1300;
+
+  --grey-10: #f9f9fa;
+  --grey-10-a10: rgba(249, 249, 250, 0.1);
+  --grey-10-a20: rgba(249, 249, 250, 0.2);
+  --grey-10-a40: rgba(249, 249, 250, 0.4);
+  --grey-10-a60: rgba(249, 249, 250, 0.6);
+  --grey-10-a80: rgba(249, 249, 250, 0.8);
+  --grey-20: #ededf0;
+  --grey-30: #d7d7db;
+  --grey-40: #b1b1b3;
+  --grey-50: #737373;
+  --grey-60: #4a4a4f;
+  --grey-70: #38383d;
+  --grey-80: #2a2a2e;
+  --grey-90: #0c0c0d;
+  --grey-90-a05: rgba(12, 12, 13, 0.05);
+  --grey-90-a10: rgba(12, 12, 13, 0.1);
+  --grey-90-a20: rgba(12, 12, 13, 0.2);
+  --grey-90-a30: rgba(12, 12, 13, 0.3);
+  --grey-90-a40: rgba(12, 12, 13, 0.4);
+  --grey-90-a50: rgba(12, 12, 13, 0.5);
+  --grey-90-a60: rgba(12, 12, 13, 0.6);
+  --grey-90-a70: rgba(12, 12, 13, 0.7);
+  --grey-90-a80: rgba(12, 12, 13, 0.8);
+  --grey-90-a90: rgba(12, 12, 13, 0.9);
+
+  --ink-70: #363959;
+  --ink-80: #202340;
+  --ink-90: #0f1126;
+
+  --white-100: #ffffff;
+}
\ No newline at end of file
diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm
index cb77f4d82a3e..aae76c7be6bc 100644
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -514,7 +514,7 @@ let JSWINDOWACTORS = {
       },
     },
 
-    matches: ["about:torconnect"],
+    matches: ["about:torconnect","about:torconnect?*"],
   },
 
   Translation: {
diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm
index 2d66422abf58..bf9919041f6b 100644
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -1892,23 +1892,11 @@ var SessionStoreInternal = {
         }, "browser-delayed-startup-finished");
       });
 
-      let bootstrapPromise = new Promise(resolve => {
-        if (TorProtocolService.isBootstrapDone() || !TorProtocolService.ownsTorDaemon) {
-          resolve();
-        } else {
-          Services.obs.addObserver(function obs(subject, topic) {
-            Services.obs.removeObserver(obs, topic);
-            resolve();
-          }, "torconnect:bootstrap-complete");
-        }
-      });
-
       // We are ready for initialization as soon as the session file has been
       // read from disk and the initial window's delayed startup has finished.
       this._promiseReadyForInitialization = Promise.all([
         promise,
         SessionStartup.onceInitialized,
-        bootstrapPromise,
       ]);
     }
 
diff --git a/browser/components/torconnect/TorConnectParent.jsm b/browser/components/torconnect/TorConnectParent.jsm
index 3937bf3ebcf8..792f2af10ea6 100644
--- a/browser/components/torconnect/TorConnectParent.jsm
+++ b/browser/components/torconnect/TorConnectParent.jsm
@@ -25,6 +25,8 @@ class TorConnectParent extends JSWindowActorParent {
 
     this.state = {
       State: TorConnect.state,
+      StateChanged: false,
+      Exit: false,
       ErrorMessage: TorConnect.errorMessage,
       ErrorDetails: TorConnect.errorDetails,
       BootstrapProgress: TorConnect.bootstrapProgress,
@@ -45,9 +47,11 @@ class TorConnectParent extends JSWindowActorParent {
 
         // update our state struct based on received torconnect topics and forward on
         // to aboutTorConnect.js
+        self.state.StateChanged = false;
         switch(aTopic) {
           case TorConnectTopics.StateChange: {
             self.state.State = obj.state;
+            self.state.StateChanged = true;
             // clear any previous error information if we are bootstrapping
             if (self.state.State === TorConnectState.Bootstrapping) {
               self.state.ErrorMessage = null;
@@ -62,12 +66,12 @@ class TorConnectParent extends JSWindowActorParent {
             break;
           }
           case TorConnectTopics.BootstrapComplete: {
-            // tells about:torconnect pages to close themselves
+            // tells about:torconnect pages to close or redirect themselves
             // this flag will only be set if an about:torconnect page
             // reaches the Bootstrapped state, so if a user
             // navigates to about:torconnect manually after bootstrap, the page
             // will not auto-close on them
-            self.state.Close = true;
+            self.state.Exit = true;
             break;
           }
           case TorConnectTopics.BootstrapError: {
@@ -130,6 +134,10 @@ class TorConnectParent extends JSWindowActorParent {
         break;
       case "torconnect:get-init-args":
         // called on AboutTorConnect.init(), pass down all state data it needs to init
+
+        // pretend this is a state transition on init
+        // so we always get fresh UI
+        this.state.StateChanged = true;
         return {
             TorStrings: TorStrings,
             TorConnectState: TorConnectState,
diff --git a/browser/components/torconnect/content/aboutTorConnect.css b/browser/components/torconnect/content/aboutTorConnect.css
index a70904ca0b28..3bdc6ff22192 100644
--- a/browser/components/torconnect/content/aboutTorConnect.css
+++ b/browser/components/torconnect/content/aboutTorConnect.css
@@ -1,8 +1,8 @@
 
 /* Copyright (c) 2021, The Tor Project, Inc. */
 
-
 @import url("chrome://browser/skin/error-pages.css");
+ at import url("chrome://branding/content/tor-styles.css");
 
 :root {
   --onion-opacity: 1;
@@ -13,20 +13,20 @@
 /* override firefox's default blue focus coloring */
 :focus {
   outline:  none!important;
-  box-shadow: 0 0 0 3px #CD8CED !important;
-  border:  1px #59316B solid !important;
+  box-shadow: 0 0 0 3px var(--purple-30) !important;
+  border:  1px var(--purple-80) solid !important;
 }
 
 @media (prefers-color-scheme: dark)
 {
   :focus {
-    box-shadow: 0 0 0 3px #8C689E !important;
+    box-shadow: 0 0 0 3px var(--purple-50)!important;
   }
 }
 
 /* override firefox's default blue border on hover */
 input[type="checkbox"]:not(:disabled):hover {
-  border-color: #59316B;
+  border-color: var(--purple-70);
 }
 
 /* fix checkbox visibility when dark mode enabled */
@@ -35,11 +35,15 @@ input[type="checkbox"]:checked {
 }
 
 #connectButton {
-  background-color: #7D4698;
+  background-color: var(--purple-60);
 }
 
 #connectButton:hover {
-  background-color: #59316B;
+  background-color: var(--purple-70);
+}
+
+#connectButton:active {
+  background-color: var(--purple-80);
 }
 
 #progressBackground {
@@ -111,8 +115,8 @@ input[type="checkbox"]:checked {
 
 /* tooltip content (any content could go here) */
 #copyLogTooltipText {
-  background-color: #30E60B;
-  color: #003706;
+  background-color: var(--green-50);
+  color: var(--green-90);
   border-radius: 2px;
   padding: 4px;
   line-height: 13px;
@@ -129,7 +133,7 @@ input[type="checkbox"]:checked {
   margin-left: -4px;
   border-width: 4px;
   border-style: solid;
-  border-color: #30E60B transparent transparent transparent;
+  border-color: var(--green-50) transparent transparent transparent;
 }
 
 body {
diff --git a/browser/components/torconnect/content/aboutTorConnect.js b/browser/components/torconnect/content/aboutTorConnect.js
index 8b269d2fc82b..4eed3cf6a5c3 100644
--- a/browser/components/torconnect/content/aboutTorConnect.js
+++ b/browser/components/torconnect/content/aboutTorConnect.js
@@ -47,6 +47,10 @@ class AboutTorConnect {
     advancedButton: document.querySelector(this.selectors.buttons.advanced),
   })
 
+  // a redirect url can be passed as a query parameter for the page to
+  // forward us to once bootstrap completes (otherwise the window will just close)
+  redirect = null
+
   beginBootstrap() {
     this.hide(this.elements.connectButton);
     this.show(this.elements.cancelButton);
@@ -100,10 +104,6 @@ class AboutTorConnect {
 
     // calls update_$state()
     this[`update_${state.State}`](state);
-
-    if (state.ShowCopyLog) {
-      this.showCopyLog();
-    }
     this.elements.quickstartCheckbox.checked = state.QuickStartEnabled;
   }
 
@@ -137,7 +137,9 @@ class AboutTorConnect {
       this.elements.connectButton.textContent = TorStrings.torConnect.torConnectButton;
     }
     this.show(this.elements.connectButton);
-    this.elements.connectButton.focus();
+    if (state.StateChanged) {
+      this.elements.connectButton.focus();
+    }
     this.show(this.elements.advancedButton);
     this.hide(this.elements.cancelButton);
   }
@@ -160,7 +162,9 @@ class AboutTorConnect {
     this.hide(this.elements.connectButton);
     this.hide(this.elements.advancedButton);
     this.show(this.elements.cancelButton);
-    this.elements.cancelButton.focus();
+    if (state.StateChanged) {
+      this.elements.cancelButton.focus();
+    }
   }
 
   update_Error(state) {
@@ -190,9 +194,15 @@ class AboutTorConnect {
     this.hide(this.elements.advancedButton);
     this.hide(this.elements.cancelButton);
 
-    // only close the window if directed
-    if (state.Close) {
-      window.close();
+    // only exit about:torconnect if TorConnectParent directs us to
+    if (state.Exit) {
+      if (this.redirect) {
+        // first try to forward to final destination
+        document.location = this.redirect;
+      } else {
+        // or else close the window
+        window.close();
+      }
     }
   }
 
@@ -201,7 +211,7 @@ class AboutTorConnect {
     // it isn't in use (eg using tor-launcher or system tor)
   }
 
-  async initElements(direction, quickstart) {
+  async initElements(direction) {
 
     document.documentElement.setAttribute("dir", direction);
 
@@ -220,13 +230,12 @@ class AboutTorConnect {
 
       // hide tooltip after X ms
       const TOOLTIP_TIMEOUT = 2000;
-      this.copyLogTimeoutId = setTimeout(function() {
+      this.copyLogTimeoutId = setTimeout(() => {
         this.elements.copyLogTooltipText.style.visibility = "hidden";
         this.copyLogTimeoutId = 0;
       }, TOOLTIP_TIMEOUT);
     });
 
-    this.elements.quickstartCheckbox.checked = quickstart
     this.elements.quickstartCheckbox.addEventListener("change", () => {
       const quickstart = this.elements.quickstartCheckbox.checked;
       RPMSendAsyncMessage("torconnect:set-quickstart", quickstart);
@@ -269,6 +278,12 @@ class AboutTorConnect {
   }
 
   async init() {
+    // see if a user has a final destination after bootstrapping
+    let params = new URLSearchParams(new URL(document.location.href).search);
+    if (params.has("redirect")) {
+      const encodedRedirect = params.get("redirect");
+      this.redirect = decodeURIComponent(encodedRedirect);
+    }
 
     let args = await RPMSendQuery("torconnect:get-init-args");
 
diff --git a/browser/components/torconnect/content/torBootstrapUrlbar.js b/browser/components/torconnect/content/torBootstrapUrlbar.js
index e4fd6f5ab910..7843b80be8b9 100644
--- a/browser/components/torconnect/content/torBootstrapUrlbar.js
+++ b/browser/components/torconnect/content/torBootstrapUrlbar.js
@@ -28,7 +28,8 @@ var TorBootstrapUrlbar = {
       case TorConnectState.Error:
       case TorConnectState.FatalError: {
         this.elements.torConnectBox.removeAttribute("hidden");
-        this.elements.torConnectLabel.textContent = TorStrings.torConnect.offline;
+        this.elements.torConnectLabel.textContent =
+          TorStrings.torConnect.torNotConnectedConcise;
         this.elements.inputContainer.setAttribute("torconnect", "offline");
         break;
       }
@@ -74,6 +75,9 @@ var TorBootstrapUrlbar = {
         torConnectLabel: browser.ownerGlobal.document.querySelector(this.selectors.torConnect.label),
         inputContainer: gURLBar._inputContainer,
       })
+      this.elements.torConnectBox.addEventListener("click", () => {
+        window.openTrustedLinkIn("about:torconnect", "tab");
+      });
       Services.obs.addObserver(this, TorConnectTopics.StateChange);
       this.observing = true;
       this.updateTorConnectBox(TorConnect.state);
diff --git a/browser/components/torconnect/content/torconnect-urlbar.css b/browser/components/torconnect/content/torconnect-urlbar.css
index db2f1069b22b..5aabcffedbd0 100644
--- a/browser/components/torconnect/content/torconnect-urlbar.css
+++ b/browser/components/torconnect/content/torconnect-urlbar.css
@@ -3,41 +3,33 @@
 */
 hbox.urlbar-page-action#torconnect-box {
     display: -moz-inline-box!important;
-    margin: 0 6px;
     height: 28px;
 }
-/* disable the button-like default css */
-hbox.urlbar-page-action#torconnect-box:hover,
-hbox.urlbar-page-action#torconnect-box:active {
-    background-color: inherit!important;
-}
 
 label#torconnect-label {
     line-height: 28px;
     margin: 0;
     opacity: 0.6;
+    padding: 0 0.5em;
 }
 
 /* set appropriate sizes for the non-standard ui densities */
-:root[uidensity=compact] {
-    hbox.urlbar-page-action#torconnect-box {
-        margin: 0 4px;
-        height: 24px;
-    }
-    label#torconnect-label {
-        line-height: 24px;
-    }
+:root[uidensity=compact] hbox.urlbar-page-action#torconnect-box {
+    height: 24px;
+}
+:root[uidensity=compact] label#torconnect-label {
+    line-height: 24px;
+}
+
+
+:root[uidensity=touch] hbox.urlbar-page-action#torconnect-box {
+    height: 30px;
 }
-:root[uidensity=touch] {
-    hbox.urlbar-page-action#torconnect-box {
-        margin: 0 7px;
-        height: 30px;
-    }
-    label#torconnect-label {
-        line-height: 30px;
-    }
+:root[uidensity=touch] label#torconnect-label {
+    line-height: 30px;
 }
 
+
 /* hide when hidden attribute is set */
 hbox.urlbar-page-action#torconnect-box[hidden="true"],
 /* hide when user is typing in URL bar */
diff --git a/browser/components/torconnect/content/torconnect-urlbar.inc.xhtml b/browser/components/torconnect/content/torconnect-urlbar.inc.xhtml
index bdf9d8f0df00..60e985a72691 100644
--- a/browser/components/torconnect/content/torconnect-urlbar.inc.xhtml
+++ b/browser/components/torconnect/content/torconnect-urlbar.inc.xhtml
@@ -4,7 +4,6 @@
       class="urlbar-icon-wrapper urlbar-page-action"
       role="status"
       hidden="true">
-    <image id="torconnect-button" role="presentation"/>
     <hbox id="torconnect-container">
         <label id="torconnect-label"/>
     </hbox>
diff --git a/browser/components/torpreferences/content/torPreferences.css b/browser/components/torpreferences/content/torPreferences.css
index f125936dac74..47b8ff18e0af 100644
--- a/browser/components/torpreferences/content/torPreferences.css
+++ b/browser/components/torpreferences/content/torPreferences.css
@@ -1,3 +1,5 @@
+ at import url("chrome://branding/content/tor-styles.css");
+
 #category-tor > .category-icon {
   list-style-image: url("chrome://browser/content/torpreferences/torPreferencesIcon.svg");
 }
@@ -24,8 +26,8 @@
 }
 
 #torPreferences-connectMessageBox.warning {
-  background-color: var(--yellow-50);
-  color: var(--yellow-90);
+  background-color: var(--purple-50);
+  color: white;
 }
 
 #torPreferences-connectMessageBox table {
@@ -61,8 +63,8 @@
 
 #torPreferences-connectMessageBox.warning #torPreferences-connectMessageBox-icon
 {
-  mask: url("chrome://global/skin/icons/warning.svg");
-  background-color: black;
+  mask: url("chrome://browser/skin/onion.svg");
+  background-color: white;
 }
 
 #torPreferences-connectMessageBox-message {
@@ -108,16 +110,16 @@
 }
 
 #torPreferences-connectMessageBox.warning #torPreferences-connectMessageBox-button {
-  background-color: var(--yellow-60);
+  background-color: var(--purple-70);
 }
 
 #torPreferences-connectMessageBox.warning #torPreferences-connectMessageBox-button:hover {
-  background-color: var(--yellow-70);
+  background-color: var(--purple-80);
   color: white!important;
 }
 
 #torPreferences-connectMessageBox.warning #torPreferences-connectMessageBox-button:active {
-  background-color: var(--yellow-80);
+  background-color: var(--purple-90);
   color: white!important;
 }
 
diff --git a/browser/modules/TorConnect.jsm b/browser/modules/TorConnect.jsm
index 5d2b826cfa10..ddf658b1462a 100644
--- a/browser/modules/TorConnect.jsm
+++ b/browser/modules/TorConnect.jsm
@@ -159,26 +159,24 @@ const TorConnect = (() => {
         _errorMessage: null,
         _errorDetails: null,
         _logHasWarningOrError: false,
-        // init to about:tor as fallback in case setURIsToLoad is somehow never called
-        _urisToLoad: ["about:tor"],
 
         /* These functions are called after transitioning to a new state */
         _transitionCallbacks: Object.freeze(new Map([
             /* Initial is never transitioned to */
             [TorConnectState.Initial, null],
             /* Configuring */
-            [TorConnectState.Configuring, (self) => {
+            [TorConnectState.Configuring, (self, prevState) => {
                 // TODO move this to the transition function
-                if (this._state === TorConnectState.Bootstrapping) {
+                if (prevState === TorConnectState.Bootstrapping) {
                     TorProtocolService.torStopBootstrap();
                 }
             }],
             /* AutoConfiguring */
-            [TorConnectState.AutoConfiguring, (self) => {
+            [TorConnectState.AutoConfiguring, (self, prevState) => {
 
             }],
             /* Bootstrapping */
-            [TorConnectState.Bootstrapping, (self) => {
+            [TorConnectState.Bootstrapping, (self, prevState) => {
                 let error = TorProtocolService.connect();
                 if (error) {
                     self.onError(error.message, error.details);
@@ -187,20 +185,12 @@ const TorConnect = (() => {
                 }
             }],
             /* Bootstrapped */
-            [TorConnectState.Bootstrapped, (self) => {
-                // open home page(s) in new tabs
-                const win = BrowserWindowTracker.getTopWindow()
-
-                let location="tab";
-                for (const uri of self._urisToLoad) {
-                    win.openTrustedLinkIn(uri, location);
-                    // open subsequent tabs behind first tab
-                    location = "tabshifted";
-                }
+            [TorConnectState.Bootstrapped, (self,prevState) => {
+                // notify observers of bootstrap completion
                 Services.obs.notifyObservers(null, TorConnectTopics.BootstrapComplete);
             }],
             /* Error */
-            [TorConnectState.Error, (self, errorMessage, errorDetails, fatal) => {
+            [TorConnectState.Error, (self, prevState, errorMessage, errorDetails, fatal) => {
                 self._errorMessage = errorMessage;
                 self._errorDetails = errorDetails;
 
@@ -212,31 +202,32 @@ const TorConnect = (() => {
                 }
             }],
             /* FatalError */
-            [TorConnectState.FatalError, (self) => {
+            [TorConnectState.FatalError, (self, prevState) => {
                 Services.obs.notifyObservers(null, TorConnectTopics.FatalError);
             }],
             /* Disabled */
-            [TorConnectState.Disabled, (self) => {
+            [TorConnectState.Disabled, (self, prevState) => {
 
             }],
         ])),
 
         _changeState: function(newState, ...args) {
-            const oldState = this._state;
+            const prevState = this._state;
 
             // ensure this is a valid state transition
-            if (!TorConnectStateTransitions.get(oldState)?.includes(newState)) {
-                throw Error(`TorConnect: Attempted invalid state transition from ${oldState} to ${newState}`);
+            if (!TorConnectStateTransitions.get(prevState)?.includes(newState)) {
+                throw Error(`TorConnect: Attempted invalid state transition from ${prevState} to ${newState}`);
             }
 
-            console.log(`TorConnect: transitioning state from ${oldState} to ${newState}`);
-
-            // call our transition function and forward any args
-            this._transitionCallbacks.get(newState)(this, ...args);
+            console.log(`TorConnect: transitioning state from ${prevState} to ${newState}`);
 
-            // finally, set our new state
+            // set our new state first so that state transitions can themselves trigger
+            // a state transition
             this._state = newState;
 
+            // call our transition function and forward any args
+            this._transitionCallbacks.get(newState)(this, prevState, ...args);
+
             Services.obs.notifyObservers({state: newState}, TorConnectTopics.StateChange);
         },
 
@@ -456,10 +447,12 @@ const TorConnect = (() => {
         },
 
         // called from browser.js on browser startup, passed in either the user's homepage(s)
-        // or uris passed via command-line
-        setURIsToLoad: function(uriVariant) {
+        // or uris passed via command-line; we want to replace them with about:torconnect uris
+        // which redirect after bootstrapping
+        getURIsToLoad: function(uriVariant) {
             // convert the object we get from browser.js
-            let uris = ((v) => {
+            let uriStrings = ((v) => {
+                // an interop array
                 if (v instanceof Ci.nsIArray) {
                     // Transform the nsIArray of nsISupportsString's into a JS Array of
                     // JS strings.
@@ -467,17 +460,38 @@ const TorConnect = (() => {
                       v.enumerate(Ci.nsISupportsString),
                       supportStr => supportStr.data
                     );
+                // an interop string
                 } else if (v instanceof Ci.nsISupportsString) {
                     return [v.data];
+                // a js string
                 } else if (typeof v === "string") {
                     return v.split("|");
+                // a js array of js strings
+                } else if (Array.isArray(v) &&
+                           v.reduce((allStrings, entry) => {return allStrings && (typeof entry === "string");}, true)) {
+                    return v;
                 }
                 // about:tor as safe fallback
+                console.log(`TorConnect: setURIsToLoad() received unknown variant '${JSON.stringify(v)}'`);
                 return ["about:tor"];
             })(uriVariant);
 
-            console.log(`TorConnect: will load after bootstrap => ${uris.join(", ")}`);
-            this._urisToLoad = uris;
+            // will attempt to convert user-supplied string to a uri, fallback to about:tor if cannot convert
+            // to valid uri object
+            let uriStringToUri = (uriString) => {
+                let uri = Services.uriFixup.createFixupURI(uriString, 0);
+                return uri ? uri : Services.io.newURI("about:tor");
+            };
+            let uris = uriStrings.map(uriStringToUri);
+
+            // assume we have a valid uri and generate an about:torconnect redirect uri
+            let uriToRedirectUri = (uri) => {
+                return`about:torconnect?redirect=${encodeURIComponent(uri.spec)}`;
+            };
+            let redirectUris = uris.map(uriToRedirectUri);
+
+            console.log(`TorConnect: will load after bootstrap => [${uris.map((uri) => {return uri.spec;}).join(", ")}]`);
+            return redirectUris;
         },
     };
     retval.init();
diff --git a/browser/modules/TorStrings.jsm b/browser/modules/TorStrings.jsm
index 6eeb2ea06a04..d8b9e9d9a399 100644
--- a/browser/modules/TorStrings.jsm
+++ b/browser/modules/TorStrings.jsm
@@ -396,6 +396,11 @@ var TorStrings = {
         "Establishing a Connection"
       ),
 
+      torNotConnectedConcise: getStringNet(
+        "torConnect.notConnectedConcise",
+        "Not Connected"
+      ),
+
       torConnectingConcise: getStringNet(
         "torConnect.connectingConcise",
         "Connecting…"
diff --git a/browser/themes/shared/identity-block/identity-block.inc.css b/browser/themes/shared/identity-block/identity-block.inc.css
index 936ab00d2080..ce8a2b44e60a 100644
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -61,19 +61,9 @@
   -moz-outline-radius: var(--toolbarbutton-border-radius);
 }
 
-%ifdef MOZ_OFFICIAL_BRANDING
 #identity-box[pageproxystate="valid"].chromeUI > #identity-icon-label {
-  color: #420C5D;
-}
-
-toolbar[brighttext] #identity-box[pageproxystate="valid"].chromeUI > #identity-icon-label {
-  color: #CC80FF;
-}
-%endif
-
-#identity-box[pageproxystate="valid"].chromeUI > #identity-icon-label,
-.urlbar-label {
-  opacity: .6;
+  color: var(--tor-branding-color);
+  opacity: 1;
 }
 
 #identity-icon-label {
@@ -132,6 +122,8 @@ toolbar[brighttext] #identity-box[pageproxystate="valid"].chromeUI > #identity-i
 
 #identity-box[pageproxystate="valid"].chromeUI > #identity-icon {
   list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
+  fill: var(--tor-branding-color);
+  fill-opacity: 1;
 }
 
 #urlbar:not(.searchButton) > #urlbar-input-container > #identity-box[pageproxystate="invalid"] > #identity-icon {





More information about the tbb-commits mailing list