Bug 1422106 - Show broken heart when unverified in synced tabs sidebar/panel. r?markh draft
authorEdouard Oger <eoger@fastmail.com>
Thu, 30 Nov 2017 16:01:40 -0500
changeset 708611 9eeae3bfa150e2c62eac64bad312b697ca6d93c5
parent 708379 c0c5e19a32b8b1b74b9dc0360800aec01665f9b0
child 743202 790d953883aa1124d848cef5bd12f57bda3e6c0e
push id92395
push userbmo:eoger@fastmail.com
push dateWed, 06 Dec 2017 21:33:56 +0000
reviewersmarkh
bugs1422106
milestone59.0a1
Bug 1422106 - Show broken heart when unverified in synced tabs sidebar/panel. r?markh MozReview-Commit-ID: BDTdmcIOHmn
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser-sync.js
browser/base/content/test/sync/browser_sync.js
browser/components/customizableui/content/panelUI.inc.xul
browser/components/customizableui/test/browser_synced_tabs_menu.js
browser/components/syncedtabs/SyncedTabsDeckComponent.js
browser/components/syncedtabs/sidebar.xhtml
browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js
browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/modules/test/browser/browser_BrowserUITelemetry_syncedtabs.js
browser/themes/shared/customizableui/panelUI.inc.css
browser/themes/shared/fxa/sync-illustration-issue.svg
browser/themes/shared/fxa/sync-illustration.svg
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -472,22 +472,27 @@
                         key="key_openDownloads"
                         command="Tools:Downloads"/>
               <menuitem id="menu_openAddons"
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
 
-              <!-- only one of sync-setup, sync-syncnowitem or sync-reauthitem will be showing at once -->
+              <!-- only one of sync-setup, sync-unverifieditem, sync-syncnowitem or sync-reauthitem will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSignIn.label;"
                         accesskey="&syncSignIn.accesskey;"
                         observes="sync-setup-state"
                         oncommand="gSync.openPrefs('menubar')"/>
+              <menuitem id="sync-unverifieditem"
+                        label="&syncSignIn.label;"
+                        accesskey="&syncSignIn.accesskey;"
+                        observes="sync-unverified-state"
+                        oncommand="gSync.openPrefs('menubar')"/>
               <menuitem id="sync-syncnowitem"
                         label="&syncSyncNowItem.label;"
                         accesskey="&syncSyncNowItem.accesskey;"
                         observes="sync-syncnow-state"
                         oncommand="gSync.doSync(event);"/>
               <menuitem id="sync-reauthitem"
                         label="&syncReAuthItem.label;"
                         accesskey="&syncReAuthItem.accesskey;"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -161,16 +161,17 @@
     <!-- Sync broadcasters -->
     <!-- A broadcaster of a number of attributes suitable for "sync now" UI -
         A 'syncstatus' attribute is set while actively syncing, and the label
         attribute which changes from "sync now" to "syncing" etc. -->
     <broadcaster id="sync-status"/>
     <!-- broadcasters of the "hidden" attribute to reflect setup state for
          menus -->
     <broadcaster id="sync-setup-state"/>
+    <broadcaster id="sync-unverified-state" hidden="true"/>
     <broadcaster id="sync-syncnow-state" hidden="true"/>
     <broadcaster id="sync-reauth-state" hidden="true"/>
     <broadcaster id="viewTabsSidebar" autoCheck="false" sidebartitle="&syncedTabs.sidebar.label;"
                  type="checkbox" group="sidebar"
                  sidebarurl="chrome://browser/content/syncedtabs/sidebar.xhtml"
                  oncommand="SidebarUI.toggle('viewTabsSidebar');"/>
     <broadcaster id="workOfflineMenuitemState"/>
 
--- a/browser/base/content/browser-sync.js
+++ b/browser/base/content/browser-sync.js
@@ -213,23 +213,25 @@ var gSync = {
 
   updateStateBroadcasters(state) {
     const status = state.status;
 
     // Start off with a clean slate
     document.getElementById("sync-reauth-state").hidden = true;
     document.getElementById("sync-setup-state").hidden = true;
     document.getElementById("sync-syncnow-state").hidden = true;
+    document.getElementById("sync-unverified-state").hidden = true;
 
     if (status == UIState.STATUS_LOGIN_FAILED) {
       // unhiding this element makes the menubar show the login failure state.
       document.getElementById("sync-reauth-state").hidden = false;
-    } else if (status == UIState.STATUS_NOT_CONFIGURED ||
-               status == UIState.STATUS_NOT_VERIFIED) {
+    } else if (status == UIState.STATUS_NOT_CONFIGURED) {
       document.getElementById("sync-setup-state").hidden = false;
+    } else if (status == UIState.STATUS_NOT_VERIFIED) {
+      document.getElementById("sync-unverified-state").hidden = false;
     } else {
       document.getElementById("sync-syncnow-state").hidden = false;
     }
   },
 
   updateSyncStatus(state) {
     const broadcaster = document.getElementById("sync-status");
     const syncingUI = broadcaster.getAttribute("syncstatus") == "active";
--- a/browser/base/content/test/sync/browser_sync.js
+++ b/browser/base/content/test/sync/browser_sync.js
@@ -103,18 +103,18 @@ add_task(async function test_ui_state_un
   checkPanelUIStatusBar({
     label: expectedLabel,
     tooltip: tooltipText,
     fxastatus: "unverified",
     avatarURL: null,
     syncing: false,
     syncNowTooltip: tooltipText
   });
-  checkRemoteTabsPanel("PanelUI-remotetabs-setupsync", false);
-  checkMenuBarItem("sync-setup");
+  checkRemoteTabsPanel("PanelUI-remotetabs-unverified", false);
+  checkMenuBarItem("sync-unverifieditem");
 });
 
 add_task(async function test_ui_state_loginFailed() {
   let state = {
     status: UIState.STATUS_LOGIN_FAILED,
     email: "foo@bar.com"
   };
 
@@ -171,26 +171,27 @@ function checkPanelUIStatusBar({label, t
   if (syncing != undefined && syncNowTooltip != undefined) {
     checkSyncNowButton("appMenu-fxa-icon", syncing, syncNowTooltip);
   }
 }
 
 function checkRemoteTabsPanel(expectedShownItemId, syncing, syncNowTooltip) {
   checkItemsVisiblities(["PanelUI-remotetabs-main",
                          "PanelUI-remotetabs-setupsync",
-                         "PanelUI-remotetabs-reauthsync"],
+                         "PanelUI-remotetabs-reauthsync",
+                         "PanelUI-remotetabs-unverified"],
                         expectedShownItemId);
 
   if (syncing != undefined && syncNowTooltip != undefined) {
     checkSyncNowButton("PanelUI-remotetabs-syncnow", syncing, syncNowTooltip);
   }
 }
 
 function checkMenuBarItem(expectedShownItemId) {
-  checkItemsVisiblities(["sync-setup", "sync-syncnowitem", "sync-reauthitem"],
+  checkItemsVisiblities(["sync-setup", "sync-syncnowitem", "sync-reauthitem", "sync-unverifieditem"],
                         expectedShownItemId);
 }
 
 function checkSyncNowButton(buttonId, syncing, tooltip = null) {
   const remoteTabsButton = document.getElementById(buttonId);
 
   is(remoteTabsButton.getAttribute("syncstatus"), syncing ? "active" : "", "button active has the right value");
   if (tooltip) {
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -486,16 +486,27 @@
                 class="PanelUI-remotetabs-instruction-box"
                 observes="sync-reauth-state">
             <image class="fxaSyncIllustrationIssue"/>
             <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.notsignedin.label;</label>
             <toolbarbutton class="PanelUI-remotetabs-button"
                            label="&appMenuRemoteTabs.signin.label;"
                            oncommand="gSync.openPrefs('synced-tabs');"/>
           </vbox>
+          <vbox id="PanelUI-remotetabs-unverified"
+                flex="1"
+                align="center"
+                class="PanelUI-remotetabs-instruction-box"
+                observes="sync-unverified-state">
+            <image class="fxaSyncIllustrationIssue"/>
+            <label class="PanelUI-remotetabs-instruction-label">&appMenuRemoteTabs.unverified.label;</label>
+            <toolbarbutton class="PanelUI-remotetabs-button"
+                           label="&appMenuRemoteTabs.signin.label;"
+                           oncommand="gSync.openPrefs('synced-tabs');"/>
+          </vbox>
         </hbox>
       </vbox>
     </panelview>
 
     <panelview id="PanelUI-bookmarks" flex="1" class="PanelUI-subView">
       <vbox class="panel-subview-body">
         <toolbarbutton id="panelMenuBookmarkThisPage"
                        class="subviewbutton subviewbutton-iconic"
--- a/browser/components/customizableui/test/browser_synced_tabs_menu.js
+++ b/browser/components/customizableui/test/browser_synced_tabs_menu.js
@@ -134,16 +134,23 @@ async function asyncCleanup() {
 
 // When Sync is not setup.
 add_task(async function() {
   gSync.updateAllUI({ status: UIState.STATUS_NOT_CONFIGURED });
   await openPrefsFromMenuPanel("PanelUI-remotetabs-setupsync", "synced-tabs");
 });
 add_task(asyncCleanup);
 
+// When Sync is configured in an unverified state.
+add_task(async function() {
+  gSync.updateAllUI({ status: UIState.STATUS_NOT_VERIFIED, email: "foo@bar.com" });
+  await openPrefsFromMenuPanel("PanelUI-remotetabs-unverified", "synced-tabs");
+});
+add_task(asyncCleanup);
+
 // When Sync is configured in a "needs reauthentication" state.
 add_task(async function() {
   gSync.updateAllUI({ status: UIState.STATUS_LOGIN_FAILED, email: "foo@bar.com" });
   await openPrefsFromMenuPanel("PanelUI-remotetabs-reauthsync", "synced-tabs");
 });
 
 // Test the Connect Another Device button
 add_task(async function() {
--- a/browser/components/syncedtabs/SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/SyncedTabsDeckComponent.js
@@ -58,16 +58,17 @@ function SyncedTabsDeckComponent({
 
 SyncedTabsDeckComponent.prototype = {
   PANELS: {
     TABS_CONTAINER: "tabs-container",
     TABS_FETCHING: "tabs-fetching",
     NOT_AUTHED_INFO: "notAuthedInfo",
     SINGLE_DEVICE_INFO: "singleDeviceInfo",
     TABS_DISABLED: "tabs-disabled",
+    UNVERIFIED: "unverified"
   },
 
   get container() {
     return this._deckView ? this._deckView.container : null;
   },
 
   init() {
     Services.obs.addObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED);
@@ -125,19 +126,22 @@ SyncedTabsDeckComponent.prototype = {
   // There's no good way to mock fxAccounts in browser tests where it's already
   // been instantiated, so we have this method for stubbing.
   _getSignedInUser() {
     return this._fxAccounts.getSignedInUser();
   },
 
   getPanelStatus() {
     return this._getSignedInUser().then(user => {
-      if (!user || !user.verified || this._SyncedTabs.loginFailed) {
+      if (!user || this._SyncedTabs.loginFailed) {
         return this.PANELS.NOT_AUTHED_INFO;
       }
+      if (!user.verified) {
+        return this.PANELS.UNVERIFIED;
+      }
       if (!this._SyncedTabs.isConfiguredToSyncTabs) {
         return this.PANELS.TABS_DISABLED;
       }
       if (!this._SyncedTabs.hasSyncedThisSession) {
         return this.PANELS.TABS_FETCHING;
       }
       return this._SyncedTabs.getTabClients().then(clients => {
         if (clients.length) {
--- a/browser/components/syncedtabs/sidebar.xhtml
+++ b/browser/components/syncedtabs/sidebar.xhtml
@@ -75,16 +75,21 @@
         <div class="tabs-fetching sync-state">
           <!-- Show intentionally blank panel, see bug 1239845 -->
         </div>
         <div class="notAuthedInfo sync-state">
           <div class="syncIllustration"></div>
           <p class="instructions">&syncedTabs.sidebar.notsignedin.label;</p>
           <button class="button sync-prefs">&fxaSignIn.label;</button>
         </div>
+        <div class="unverified sync-state">
+          <div class="syncIllustration"></div>
+          <p class="instructions">&syncedTabs.sidebar.unverified.label;</p>
+          <button class="button sync-prefs">&syncedTabs.sidebar.openprefs.label;</button>
+        </div>
         <div class="singleDeviceInfo sync-state">
           <div class="syncIllustrationIssue"></div>
           <p class="instructions">&syncedTabs.sidebar.noclients.subtitle;</p>
           <button class="button connect-device">&syncedTabs.sidebar.connectAnotherDevice;</button>
         </div>
         <div class="tabs-disabled sync-state">
           <div class="syncIllustrationIssue"></div>
           <p class="instructions">&syncedTabs.sidebar.tabsnotsyncing.label;</p>
--- a/browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js
+++ b/browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js
@@ -223,16 +223,22 @@ add_task(async function testSyncedTabsSi
 
   syncedTabsDeckComponent._getSignedInUser.restore();
   sinon.stub(syncedTabsDeckComponent, "_getSignedInUser", () => Promise.resolve(account));
   await syncedTabsDeckComponent.updatePanel();
   selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected");
   Assert.ok(selectedPanel.classList.contains("notAuthedInfo"),
     "not-authed panel is selected");
 
+  account = {verified: false};
+  await syncedTabsDeckComponent.updatePanel();
+  selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected");
+  Assert.ok(selectedPanel.classList.contains("unverified"),
+    "unverified panel is selected");
+
   account = {verified: true};
   await syncedTabsDeckComponent.updatePanel();
   selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected");
   Assert.ok(selectedPanel.classList.contains("tabs-disabled"),
     "tabs disabled panel is selected");
 
   SyncedTabs._internal.isConfiguredToSyncTabs = true;
   await syncedTabsDeckComponent.updatePanel();
--- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js
@@ -154,17 +154,17 @@ add_task(async function testPanelStatus(
   let account = null;
   sinon.stub(fxAccounts, "getSignedInUser", () => Promise.resolve(account));
   let result = await component.getPanelStatus();
   Assert.equal(result, component.PANELS.NOT_AUTHED_INFO);
 
   account = {verified: false};
 
   result = await component.getPanelStatus();
-  Assert.equal(result, component.PANELS.NOT_AUTHED_INFO);
+  Assert.equal(result, component.PANELS.UNVERIFIED);
 
   account = {verified: true};
 
   SyncedTabsMock.loginFailed = true;
   result = await component.getPanelStatus();
   Assert.equal(result, component.PANELS.NOT_AUTHED_INFO);
   SyncedTabsMock.loginFailed = false;
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -376,16 +376,17 @@ These should match what Safari and other
      when Sync is configured but syncing tabs is disabled. -->
 <!ENTITY appMenuRemoteTabs.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
 <!-- LOCALIZATION NOTE (appMenuRemoteTabs.noclients.label): This is shown
      when Sync is configured but this appears to be the only device attached to
      the account. We also show links to download Firefox for android/ios. -->
 <!ENTITY appMenuRemoteTabs.noclients.subtitle "Want to see your tabs from other devices here?">
 <!ENTITY appMenuRemoteTabs.openprefs.label "Sync Preferences">
 <!ENTITY appMenuRemoteTabs.notsignedin.label "Sign in to view a list of tabs from your other devices.">
+<!ENTITY appMenuRemoteTabs.unverified.label "Your account needs to be verified.">
 <!ENTITY appMenuRemoteTabs.signin.label "Sign in to Sync">
 <!ENTITY appMenuRemoteTabs.managedevices.label "Manage Devices…">
 <!ENTITY appMenuRemoteTabs.sidebar.label "View Synced Tabs Sidebar">
 <!ENTITY appMenuRemoteTabs.connectdevice.label "Connect Another Device">
 
 <!ENTITY appMenuRecentHighlights.label "Recent Highlights">
 
 <!ENTITY customizeMenu.addToToolbar.label "Add to Toolbar">
@@ -789,16 +790,17 @@ you can use these alternative items. Oth
 
 <!-- LOCALIZATION NOTE (syncTabsMenu3.label): This appears in the history menu -->
 <!ENTITY syncTabsMenu3.label     "Synced Tabs">
 
 <!ENTITY syncedTabs.sidebar.label              "Synced Tabs">
 <!ENTITY syncedTabs.sidebar.noclients.label    "Sign in to Firefox from your other devices to view their tabs here.">
 <!ENTITY syncedTabs.sidebar.noclients.subtitle "Want to see your tabs from other devices here?">
 <!ENTITY syncedTabs.sidebar.notsignedin.label  "Sign in to view a list of tabs from your other devices.">
+<!ENTITY syncedTabs.sidebar.unverified.label   "Your account needs to be verified.">
 <!ENTITY syncedTabs.sidebar.notabs.label       "No open tabs">
 <!ENTITY syncedTabs.sidebar.openprefs.label    "Open &syncBrand.shortName.label; Preferences">
 <!-- LOCALIZATION NOTE (syncedTabs.sidebar.tabsnotsyncing.label): This is shown
      when Sync is configured but syncing tabs is disabled. -->
 <!ENTITY syncedTabs.sidebar.tabsnotsyncing.label       "Turn on tab syncing to view a list of tabs from your other devices.">
 <!ENTITY syncedTabs.sidebar.searchPlaceholder  "Search synced tabs">
 <!ENTITY syncedTabs.sidebar.connectAnotherDevice  "Connect Another Device">
 
--- a/browser/modules/test/browser/browser_BrowserUITelemetry_syncedtabs.js
+++ b/browser/modules/test/browser/browser_BrowserUITelemetry_syncedtabs.js
@@ -31,23 +31,25 @@ function mockSyncedTabs() {
   };
 
   let oldInternal = SyncedTabs._internal;
   SyncedTabs._internal = mockedInternal;
 
   // configure our broadcasters so we are in the right state.
   document.getElementById("sync-reauth-state").hidden = true;
   document.getElementById("sync-setup-state").hidden = true;
+  document.getElementById("sync-unverified-state").hidden = true;
   document.getElementById("sync-syncnow-state").hidden = false;
 
   registerCleanupFunction(() => {
     SyncedTabs._internal = oldInternal;
 
     document.getElementById("sync-reauth-state").hidden = true;
     document.getElementById("sync-setup-state").hidden = false;
+    document.getElementById("sync-unverified-state").hidden = true;
     document.getElementById("sync-syncnow-state").hidden = true;
   });
 }
 
 mockSyncedTabs();
 
 function promiseTabsUpdated() {
   return new Promise(resolve => {
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -713,16 +713,17 @@ toolbarbutton[constrain-size="true"][cui
   min-width: 19em;
 }
 
 /* Work around bug 1224412 - these boxes will cause scrollbars to appear when
    the panel is anchored to a toolbar button.
 */
 #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync,
 #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-reauthsync,
+#PanelUI-remotetabs[mainview] #PanelUI-remotetabs-unverified,
 #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-nodevicespane,
 #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-tabsdisabledpane {
   min-height: calc(var(--panel-ui-sync-illustration-height) +
                    20px + /* margin of .PanelUI-remotetabs-button */
                    16px + /* padding of .PanelUI-remotetabs-button */
                    30px + /* margin of .PanelUI-remotetabs-instruction-label */
                    30px + 15px + /* padding of .PanelUI-remotetabs-instruction-box */
                    11em);
--- a/browser/themes/shared/fxa/sync-illustration-issue.svg
+++ b/browser/themes/shared/fxa/sync-illustration-issue.svg
@@ -1,14 +1,14 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 173.9 156.5">
   <style>
-    .st0{opacity:0.1;fill:#0C0C0D;enable-background:new ;} .st1{fill:#FFFFFF;} .st2{fill:url(#SVGID_1_);} .st3{fill:#F9F9FA;} .st4{fill:url(#SVGID_2_);} .st5{fill:url(#SVGID_3_);} .st6{fill:url(#SVGID_4_);} .st7{fill:url(#SVGID_5_);} .st8{fill:url(#SVGID_6_);} .st9{fill:url(#SVGID_7_);}
+    .st0{opacity:0.1;fill:#0C0C0D;} .st1{fill:#FFFFFF;} .st2{fill:url(#SVGID_1_);} .st3{fill:#F9F9FA;} .st4{fill:url(#SVGID_2_);} .st5{fill:url(#SVGID_3_);} .st6{fill:url(#SVGID_4_);} .st7{fill:url(#SVGID_5_);} .st8{fill:url(#SVGID_6_);} .st9{fill:url(#SVGID_7_);}
   </style>
   <path class="st0" d="M140.9 152h-69c-.6 0-1-.4-1-1s.4-1 1-1H141c.6 0 1 .4 1 1s-.5 1-1.1 1zm-9.3-5.1h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-15.7 9.6h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5z"/>
   <path class="st1" d="M85 20.4h21.3s-6.7-14.9 7.5-16.8c12.6-1.7 17.6 11.3 17.6 11.3s1.5-7.5 9-6.1 12.9 13.3 12.9 13.3h18.6"/>
   <path class="st0" d="M172.2 18.6h-4c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h4c.3 0 .5.2.5.5s-.2.5-.5.5zm-13 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-5 0h-.8c-.1-.1-.2-.1-.2-.2-.1-.2-.5-1-1.2-2.1-.1-.2-.1-.5.2-.7.2-.1.5-.1.7.2.5.8.9 1.5 1.1 1.9h.2c.3 0 .5.2.5.5s-.2.4-.5.4zm-47.5-.6h-1.3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h.6c-.1-.2-.2-.6-.3-.9-.1-.3.1-.6.3-.7.3-.1.6.1.7.3.3.9.6 1.5.6 1.5.1.3 0 .5-.3.7-.1.1-.2.1-.3.1zm-9.3 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.3.5-.5.5zm7.8-5.5c-.3 0-.5-.2-.5-.4 0-.3-.1-.7-.1-1s.2-.5.5-.5.5.2.5.5 0 .6.1 1c.1.2-.1.4-.5.4.1.1.1.1 0 0zm26.2-1c-.2 0-.4-.1-.4-.3-.1-.2-.3-.5-.4-.9-.1-.2 0-.5.2-.7.2-.1.5 0 .7.2.2.3.3.6.5.9.1.2 0 .5-.2.7-.3.1-.3.1-.4.1zm16.1-1.3c-.1 0-.3 0-.4-.1-1.7-1.8-4-3.1-6.4-3.7-1.3-.3-2.6-.2-3.9.2-.3.1-.5-.1-.6-.3-.1-.3.1-.5.3-.6 1.4-.4 2.9-.5 4.4-.2 2.6.6 5.1 2 6.9 4 .2.2.2.5 0 .7-.1-.1-.2 0-.3 0zm-18.8-3c-.2 0-.3-.1-.4-.2-.6-.8-1.3-1.5-2-2.1-.2-.2-.1-.5.1-.7.2-.1.4-.1.6 0 .8.7 1.5 1.4 2.1 2.2.2.2.1.5-.1.7 0 .1-.2.1-.3.1zm-20.5-3.8c-.3 0-.5-.2-.5-.5 0-.2.1-.3.2-.4 1.8-1.3 4-2.2 6.2-2.4 1.9-.3 3.8-.2 5.7.2.3.1.5.3.4.6s-.3.5-.6.4c-1.7-.4-3.5-.4-5.3-.2-2.1.2-4.1.9-5.7 2.2-.2.1-.3.1-.4.1z"/>
   <path class="st1" d="M172.9 22.4H85c-.6 0-1-.4-1-1s.4-1 1-1h87.9c.6 0 1 .4 1 1s-.5 1-1 1zM.8 37.7h11.9s-3.7-8.3 4.2-9.4c7-1 9.8 6.3 9.8 6.3s.8-4.2 5-3.4 7.2 7.4 7.2 7.4h10.3"/>
   <path class="st0" d="M13 36.4H1.1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h11.5c.2-.2.5-.2.7 0l.1.1v.1c.1.3 0 .5-.3.7 0 .1-.1.1-.1.1zm32.9-.2h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zM27 33h-.1c-.3-.1-.4-.4-.3-.6.5-2 2.3-3.5 4.4-3.5.4 0 .7 0 1.1.1 1.9.5 3.6 1.5 4.9 3 .2.2.2.5 0 .7s-.5.2-.7 0c-1.1-1.3-2.6-2.3-4.3-2.7-.3-.1-.6-.1-.9-.1-1.7 0-3.1 1.2-3.4 2.8-.3.2-.5.3-.7.3zm-13.6-4.3c-.3 0-.5-.2-.5-.5 0-.1.1-.3.1-.4.8-.8 1.8-1.3 2.8-1.6.3-.1.6.1.6.4s-.1.6-.4.6c-.9.2-1.7.7-2.4 1.3.1.2 0 .2-.2.2zm7.5-1.3h-.1c-.3-.1-.6-.2-.9-.2-.3-.1-.5-.3-.4-.6.1-.3.3-.5.6-.4.3.1.7.2 1 .3.3 0 .5.3.4.6 0 .1-.3.3-.6.3z"/>
   <path class="st1" d="M49.9 39.7H1c-.6 0-1-.4-1-1s.4-1 1-1h48.8c.6 0 1 .4 1 1s-.4 1-.9 1zm85.5 37.5h-15.3V60.3c0-4.2-3.4-7.5-7.6-7.5H51.1c-4.2 0-7.5 3.4-7.5 7.5V101c0 1.3.4 2.6 1 3.7-.4.5-.8 1-1 1.6l-6.9 16.1c-.3.7-.5 1.5-.5 2.3v1.1c.1 3.4 2.8 6.1 6.2 6h60v3.2c0 4.1 3.3 7.4 7.4 7.4h25.6c4.1 0 7.4-3.3 7.4-7.4V84.7c.1-4.2-3.2-7.5-7.4-7.5z"/>
   <path class="st1" d="M50.8 56.5h61.4c2 0 3.6 1.6 3.6 3.5v40.7c0 2-1.6 3.6-3.6 3.6H50.8c-2 0-3.5-1.6-3.5-3.6V60.1c0-2 1.6-3.6 3.5-3.6z"/>
--- a/browser/themes/shared/fxa/sync-illustration.svg
+++ b/browser/themes/shared/fxa/sync-illustration.svg
@@ -1,14 +1,14 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 173.9 156.5">
   <style>
-    .st0{opacity:0.1;fill:#0C0C0D;enable-background:new ;} .st1{fill:#FFFFFF;} .st2{fill:url(#SVGID_1_);} .st3{fill:#F9F9FA;} .st4{fill:url(#SVGID_2_);} .st5{fill:url(#SVGID_3_);} .st6{fill:url(#SVGID_4_);} .st7{fill:url(#SVGID_5_);} .st8{fill:url(#SVGID_6_);} .st9{fill:url(#SVGID_7_);}
+    .st0{opacity:0.1;fill:#0C0C0D;} .st1{fill:#FFFFFF;} .st2{fill:url(#SVGID_1_);} .st3{fill:#F9F9FA;} .st4{fill:url(#SVGID_2_);} .st5{fill:url(#SVGID_3_);} .st6{fill:url(#SVGID_4_);} .st7{fill:url(#SVGID_5_);} .st8{fill:url(#SVGID_6_);} .st9{fill:url(#SVGID_7_);}
   </style>
   <path class="st0" d="M140.9 152h-69c-.6 0-1-.4-1-1s.4-1 1-1H141c.6 0 1 .4 1 1s-.5 1-1.1 1zm-9.3-5.1h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-15.7 9.6h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5z"/>
   <path class="st1" d="M85 20.4h21.3s-6.7-14.9 7.5-16.8c12.6-1.7 17.6 11.3 17.6 11.3s1.5-7.5 9-6.1 12.9 13.3 12.9 13.3h18.6"/>
   <path class="st0" d="M172.2 18.6h-4c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h4c.3 0 .5.2.5.5s-.2.5-.5.5zm-13 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-5 0h-.8c-.1-.1-.2-.1-.2-.2-.1-.2-.5-1-1.2-2.1-.1-.2-.1-.5.2-.7.2-.1.5-.1.7.2.5.8.9 1.5 1.1 1.9h.2c.3 0 .5.2.5.5s-.2.4-.5.4zm-47.5-.6h-1.3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h.6c-.1-.2-.2-.6-.3-.9-.1-.3.1-.6.3-.7.3-.1.6.1.7.3.3.9.6 1.5.6 1.5.1.3 0 .5-.3.7-.1.1-.2.1-.3.1zm-9.3 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.3.5-.5.5zm7.8-5.5c-.3 0-.5-.2-.5-.4 0-.3-.1-.7-.1-1s.2-.5.5-.5.5.2.5.5 0 .6.1 1c.1.2-.1.4-.5.4.1.1.1.1 0 0zm26.2-1c-.2 0-.4-.1-.4-.3-.1-.2-.3-.5-.4-.9-.1-.2 0-.5.2-.7.2-.1.5 0 .7.2.2.3.3.6.5.9.1.2 0 .5-.2.7-.3.1-.3.1-.4.1zm16.1-1.3c-.1 0-.3 0-.4-.1-1.7-1.8-4-3.1-6.4-3.7-1.3-.3-2.6-.2-3.9.2-.3.1-.5-.1-.6-.3-.1-.3.1-.5.3-.6 1.4-.4 2.9-.5 4.4-.2 2.6.6 5.1 2 6.9 4 .2.2.2.5 0 .7-.1-.1-.2 0-.3 0zm-18.8-3c-.2 0-.3-.1-.4-.2-.6-.8-1.3-1.5-2-2.1-.2-.2-.1-.5.1-.7.2-.1.4-.1.6 0 .8.7 1.5 1.4 2.1 2.2.2.2.1.5-.1.7 0 .1-.2.1-.3.1zm-20.5-3.8c-.3 0-.5-.2-.5-.5 0-.2.1-.3.2-.4 1.8-1.3 4-2.2 6.2-2.4 1.9-.3 3.8-.2 5.7.2.3.1.5.3.4.6s-.3.5-.6.4c-1.7-.4-3.5-.4-5.3-.2-2.1.2-4.1.9-5.7 2.2-.2.1-.3.1-.4.1z"/>
   <path class="st1" d="M172.9 22.4H85c-.6 0-1-.4-1-1s.4-1 1-1h87.9c.6 0 1 .4 1 1s-.5 1-1 1zM.8 37.7h11.9s-3.7-8.3 4.2-9.4c7-1 9.8 6.3 9.8 6.3s.8-4.2 5-3.4 7.2 7.4 7.2 7.4h10.3"/>
   <path class="st0" d="M13 36.4H1.1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h11.5c.2-.2.5-.2.7 0l.1.1v.1c.1.3 0 .5-.3.7 0 .1-.1.1-.1.1zm32.9-.2h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zM27 33h-.1c-.3-.1-.4-.4-.3-.6.5-2 2.3-3.5 4.4-3.5.4 0 .7 0 1.1.1 1.9.5 3.6 1.5 4.9 3 .2.2.2.5 0 .7s-.5.2-.7 0c-1.1-1.3-2.6-2.3-4.3-2.7-.3-.1-.6-.1-.9-.1-1.7 0-3.1 1.2-3.4 2.8-.3.2-.5.3-.7.3zm-13.6-4.3c-.3 0-.5-.2-.5-.5 0-.1.1-.3.1-.4.8-.8 1.8-1.3 2.8-1.6.3-.1.6.1.6.4s-.1.6-.4.6c-.9.2-1.7.7-2.4 1.3.1.2 0 .2-.2.2zm7.5-1.3h-.1c-.3-.1-.6-.2-.9-.2-.3-.1-.5-.3-.4-.6.1-.3.3-.5.6-.4.3.1.7.2 1 .3.3 0 .5.3.4.6 0 .1-.3.3-.6.3z"/>
   <path class="st1" d="M49.9 39.7H1c-.6 0-1-.4-1-1s.4-1 1-1h48.8c.6 0 1 .4 1 1s-.4 1-.9 1zm85.5 37.5h-15.3V60.3c0-4.2-3.4-7.5-7.6-7.5H51.1c-4.2 0-7.5 3.4-7.5 7.5V101c0 1.3.4 2.6 1 3.7-.4.5-.8 1-1 1.6l-6.9 16.1c-.3.7-.5 1.5-.5 2.3v1.1c.1 3.4 2.8 6.1 6.2 6h60v3.2c0 4.1 3.3 7.4 7.4 7.4h25.6c4.1 0 7.4-3.3 7.4-7.4V84.7c.1-4.2-3.2-7.5-7.4-7.5z"/>
   <path class="st1" d="M50.8 56.5h61.4c2 0 3.6 1.6 3.6 3.5v40.7c0 2-1.6 3.6-3.6 3.6H50.8c-2 0-3.5-1.6-3.5-3.6V60.1c0-2 1.6-3.6 3.5-3.6z"/>