Bug 1325902 - add container tab experiment styling code for increasing visibility of tabs r?baku draft
authorJonathan Kingston <jkt@mozilla.com>
Thu, 29 Dec 2016 01:17:47 +0000
changeset 454829 4a434c768868db9cc6202ee56526858c27d90d87
parent 454828 06e1019d77a67d259e3c605c2cdd71528a04a513
child 540833 29ccab90019547ace590cc7e8f9de0dadd79c18e
push id40066
push userjkingston@mozilla.com
push dateFri, 30 Dec 2016 14:37:59 +0000
reviewersbaku
bugs1325902
milestone53.0a1
Bug 1325902 - add container tab experiment styling code for increasing visibility of tabs r?baku MozReview-Commit-ID: 88I83RrNgCo
browser/app/profile/firefox.js
browser/base/content/tabbrowser.xml
browser/components/contextualidentity/content/usercontext.css
toolkit/components/contextualidentity/ContextualIdentityService.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1411,16 +1411,17 @@ pref("privacy.trackingprotection.introUR
 pref("privacy.userContext.enabled", true);
 pref("privacy.userContext.ui.enabled", true);
 pref("privacy.usercontext.about_newtab_segregation.enabled", true);
 #else
 pref("privacy.userContext.enabled", false);
 pref("privacy.userContext.ui.enabled", false);
 pref("privacy.usercontext.about_newtab_segregation.enabled", false);
 #endif
+pref("privacy.userContext.ui.tabStyleExperiment", "");
 
 #ifndef RELEASE_OR_BETA
 // At the moment, autostart.2 is used, while autostart.1 is unused.
 // We leave it here set to false to reset users' defaults and allow
 // us to change everybody to true in the future, when desired.
 pref("browser.tabs.remote.autostart.1", false);
 pref("browser.tabs.remote.autostart.2", true);
 #endif
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4910,26 +4910,30 @@
                 if (fl && fl.tabParent) {
                   fl.tabParent.suppressDisplayport(false);
                   this.mActiveResizeDisplayportSuppression = null;
                 }
               }
               break;
             }
             case "contextual-identity-updated": {
-              for (let tab of this.tabs) {
-                if (tab.getAttribute("usercontextid") == aData) {
-                  ContextualIdentityService.setTabStyle(tab);
-                }
-              }
+              ContextualIdentityService.restyleTabs(this.tabs, aData);
               break;
             }
             case "nsPref:changed": {
-              // This is the only pref observed.
-              this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
+              switch (aData) {
+                case "accessibility.typeaheadfind": {
+                  this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
+                  break;
+                }
+                case "privacy.userContext.ui.tabStyleExperiment": {
+                  ContextualIdentityService.restyleTabs(this.tabs, false);
+                  break;
+                }
+              }
               break;
             }
           }
         ]]></body>
       </method>
 
       <constructor>
         <![CDATA[
@@ -5014,16 +5018,18 @@
           this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
           Services.prefs.addObserver("accessibility.typeaheadfind", this, false);
           messageManager.addMessageListener("Findbar:Keypress", this);
 
           // Add listeners for prerender messages
           messageManager.addMessageListener("Prerender:Request", this);
           messageManager.addMessageListener("Prerender:Cancel", this);
           messageManager.addMessageListener("Prerender:Swap", this);
+
+          Services.prefs.addObserver("privacy.userContext.ui.tabStyleExperiment", this, false);
         ]]>
       </constructor>
 
       <method name="_generateUniquePanelID">
         <body><![CDATA[
           if (!this._uniquePanelIDCounter) {
             this._uniquePanelIDCounter = 0;
           }
@@ -5078,16 +5084,17 @@
             window.messageManager.removeMessageListener("contextmenu", this);
 
             if (this._switcher) {
               this._switcher.destroy();
             }
           }
 
           Services.prefs.removeObserver("accessibility.typeaheadfind", this);
+          Services.prefs.removeObserver("privacy.userContext.ui.tabStyleExperiment", this);
         ]]>
       </destructor>
 
       <!-- Deprecated stuff, implemented for backwards compatibility. -->
       <method name="enterTabbedMode">
         <body>
           Services.console.logStringMessage("enterTabbedMode is an obsolete method and " +
                                             "will be removed in a future release.");
--- a/browser/components/contextualidentity/content/usercontext.css
+++ b/browser/components/contextualidentity/content/usercontext.css
@@ -73,16 +73,93 @@
 }
 
 .tabbrowser-tab[usercontextid] {
   background-image: linear-gradient(to right, transparent 20%, var(--identity-tab-color) 30%, var(--identity-tab-color) 70%, transparent 80%);
   background-size: auto 2px;
   background-repeat: no-repeat;
 }
 
+/* containers experiment */
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] {
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 100%);
+  background-size: var(--identity-stroke-background-size);
+  background-repeat: no-repeat;
+  background-position: 0 29px;
+  --identity-stroke-background-size: auto 2px;
+}
+
+[data-identity-color="blue"][data-tab-experiment="under"] {
+  --identity-tab-color: blue;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-start:not([selected="true"]) {
+  _background-image: linear-gradient(to right, transparent 50%, var(--identity-tab-color) 53%, var(--identity-tab-color) 70%);
+  background-image: linear-gradient(to left, var(--identity-tab-color) 0%, var(--identity-tab-color) 50%, transparent 50%, transparent 100%);
+  background-position: 0 28px;
+  background-size: var(--identity-stroke-background-size);
+  background-repeat: no-repeat;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"][afterhovered=true] .tab-background-start:not([selected="true"]) {
+  background-image: linear-gradient(to left, var(--identity-tab-color) 0%, var(--identity-tab-color) 22%, transparent 30%, transparent 100%);
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"]:hover .tab-background-start:not([selected="true"]) {
+  background-image: linear-gradient(to left, var(--identity-tab-color) 0%, var(--identity-tab-color) 70%, transparent 80%, transparent 100%);
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-start[selected="true"]::before {
+  background-image: linear-gradient(to left, var(--identity-tab-color) 0%, var(--identity-tab-color) 30%, transparent 100%),
+                    url(chrome://browser/skin/tabbrowser/tab-selected-start.svg) !important;
+  background-size: var(--identity-stroke-background-size), 100% 100% !important;
+  background-position: 0px 28px, 0;
+  background-repeat: no-repeat;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-end:not([selected="true"]) {
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 50%, transparent 50%, transparent 100%);
+  background-position: 0 28px;
+  background-size: var(--identity-stroke-background-size);
+  background-repeat: no-repeat;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"][beforehovered=true] .tab-background-end:not([selected="true"]) {
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 22%, transparent 30%, transparent 100%);
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"]:hover .tab-background-end:not([selected="true"]) {
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 70%, transparent 80%, transparent 100%);
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-end[selected="true"]::before {
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 30%, transparent 100%),
+                    url(chrome://browser/skin/tabbrowser/tab-selected-end.svg) !important;
+  background-size: var(--identity-stroke-background-size), 100% 100% !important;
+  background-position: 0 28px, 0;
+  background-repeat: no-repeat;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-middle {
+  background-position: 0 28px, 0;
+  background-repeat: repeat-x;
+  background-size: var(--identity-stroke-background-size), auto;
+  background-image: linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 100%), none;
+}
+
+.tabbrowser-tab[usercontextid][data-tab-experiment="under"] .tab-background-middle[selected="true"] {
+  background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
+                    linear-gradient(to right, var(--identity-tab-color) 0%, var(--identity-tab-color) 100%),
+                    none;
+  background-position: 0, 0 28px, 0;
+  background-size: var(--tab-stroke-background-size), var(--identity-stroke-background-size), auto;
+  background-repeat: repeat-x;
+}
+/* end containers experiment */
+
 .userContext-icon,
 .menuitem-iconic[data-usercontextid] > .menu-iconic-left > .menu-iconic-icon,
 .subviewbutton[usercontextid] > .toolbarbutton-icon,
 #userContext-indicator {
   background-image: var(--identity-icon);
   filter: url(chrome://global/skin/filters.svg#fill);
   fill: var(--identity-icon-color);
   background-size: contain;
--- a/toolkit/components/contextualidentity/ContextualIdentityService.jsm
+++ b/toolkit/components/contextualidentity/ContextualIdentityService.jsm
@@ -90,16 +90,18 @@ function _ContextualIdentityService(path
 
   init(path) {
     this._path = path;
     this._saver = new DeferredTask(() => this.save(), SAVE_DELAY_MS);
     AsyncShutdown.profileBeforeChange.addBlocker("ContextualIdentityService: writing data",
                                                  () => this._saver.finalize());
 
     this.load();
+    this.observe(null, "nsPref:changed", "privacy.userContext.ui.tabStyleExperiment");
+    Services.prefs.addObserver("privacy.userContext.ui.tabStyleExperiment", this, false);
   },
 
   load() {
     OS.File.read(this._path).then(bytes => {
       // If synchronous loading happened in the meantime, exit now.
       if (this._dataReady) {
         return;
       }
@@ -122,16 +124,21 @@ function _ContextualIdentityService(path
       } catch (error) {
         this.loadError(error);
       }
     }, (error) => {
       this.loadError(error);
     });
   },
 
+  observe() {
+    // This is the only pref observed.
+    this.tabExperiment = Services.prefs.getCharPref("privacy.userContext.ui.tabStyleExperiment");
+  },
+
   resetDefault() {
     this._identities = this._defaultIdentities;
     this._lastUserContextId = this._defaultIdentities.length;
 
     this._dataReady = true;
 
     this.saveSoon();
   },
@@ -270,24 +277,41 @@ function _ContextualIdentityService(path
     // We cannot localize the user-created identity names.
     if (identity.name) {
       return identity.name;
     }
 
     return gBrowserBundle.GetStringFromName(identity.l10nID);
   },
 
+  restyleTabs(tabs, userContextId = false) {
+    // this is triggered when the pref changes, the restyle happens before we observe the change
+    this.tabExperiment = Services.prefs.getCharPref("privacy.userContext.ui.tabStyleExperiment");
+
+    for (let tab of tabs) {
+      if (tab.hasAttribute("usercontextid") &&
+          (userContextId == false || tab.getAttribute("usercontextid") == userContextId)) {
+        this.setTabStyle(tab);
+      }
+    }
+  },
+
   setTabStyle(tab) {
     if (!tab.hasAttribute("usercontextid")) {
       return;
     }
 
     let userContextId = tab.getAttribute("usercontextid");
     let identity = this.getIdentityFromId(userContextId);
     tab.setAttribute("data-identity-color", identity ? identity.color : "");
+    if (this.tabExperiment.length > 0) {
+      tab.setAttribute("data-tab-experiment", this.tabExperiment);
+    } else {
+      tab.removeAttribute("data-tab-experiment");
+    }
   },
 
   countContainerTabs(userContextId = 0) {
     let count = 0;
     this._forEachContainerTab(function() {
       ++count;
     }, userContextId);
     return count;