Bug 1273628 - Containers tabs use inline CSS styling because of performances issues with CSS vars, r=mconley, a=lizzard
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 06 Jun 2016 09:13:37 +0200
changeset 339596 e0da663d6fe5e71dabe5f87c9cc7c7ce6ffe7b7d
parent 339595 214e3a1a150a65e5400ff67f5eb5fb048929b183
child 339597 1ae7a82e2b1d2b18ccfa9a578040b46c774bc501
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley, lizzard
bugs1273628
milestone49.0a2
Bug 1273628 - Containers tabs use inline CSS styling because of performances issues with CSS vars, r=mconley, a=lizzard
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/components/contextualidentity/ContextualIdentityService.jsm
browser/components/contextualidentity/content/usercontext.css
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1299,18 +1299,16 @@ var gBrowserInit = {
       gDataNotificationInfoBar.init();
 
     gBrowserThumbnails.init();
 
     gMenuButtonBadgeManager.init();
 
     gMenuButtonUpdateBadge.init();
 
-    UserContextStyleManager.init();
-
     window.addEventListener("mousemove", MousePosTracker, false);
     window.addEventListener("dragover", MousePosTracker, false);
 
     gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
     gNavToolbox.addEventListener("customizationchange", CustomizationHandler);
     gNavToolbox.addEventListener("customizationending", CustomizationHandler);
 
     // End startup crash tracking after a delay to catch crashes while restoring
@@ -7947,37 +7945,8 @@ TabModalPromptBox.prototype = {
   get browser() {
     let browser = this._weakBrowserRef.get();
     if (!browser) {
       throw "Stale promptbox! The associated browser is gone.";
     }
     return browser;
   },
 };
-
-let UserContextStyleManager = {
-  init() {
-    for (let styleId in document.styleSheets) {
-      let styleSheet = document.styleSheets[styleId];
-      if (styleSheet.href != "chrome://browser/content/usercontext/usercontext.css") {
-        continue;
-      }
-
-      if (ContextualIdentityService.needsCssRule()) {
-        for (let ruleId in styleSheet.cssRules) {
-          let cssRule = styleSheet.cssRules[ruleId];
-          if (cssRule.selectorText != ":root") {
-            continue;
-          }
-
-          ContextualIdentityService.storeCssRule(cssRule.cssText);
-          break;
-        }
-      }
-
-      ContextualIdentityService.cssRules().forEach(rule => {
-        styleSheet.insertRule(rule, styleSheet.cssRules.length);
-      });
-
-      break;
-    }
-  },
-};
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1962,18 +1962,21 @@
 
             if (!aURI || isBlankPageURL(aURI)) {
               t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle"));
             } else if (aURI.toLowerCase().startsWith("javascript:")) {
               // This can go away when bug 672618 or bug 55696 are fixed.
               t.setAttribute("label", aURI);
             }
 
-            if (aUserContextId)
+            if (aUserContextId) {
               t.setAttribute("usercontextid", aUserContextId);
+              ContextualIdentityService.setTabStyle(t);
+            }
+
             t.setAttribute("crop", "end");
             t.setAttribute("onerror", "this.removeAttribute('image');");
             t.className = "tabbrowser-tab";
 
             this.tabContainer._unlockTabSizing();
 
             // When overflowing, new tabs are scrolled into view smoothly, which
             // doesn't go well together with the width transition. So we skip the
@@ -2610,16 +2613,17 @@
               modifiedAttrs.push("muted");
             }
             if (aOtherTab.hasAttribute("soundplaying")) {
               aOurTab.setAttribute("soundplaying", "true");
               modifiedAttrs.push("soundplaying");
             }
             if (aOtherTab.hasAttribute("usercontextid")) {
               aOurTab.setAttribute("usercontextid", aOtherTab.getAttribute("usercontextid"));
+              ContextualIdentityService.setTabStyle(aOurTab);
               modifiedAttrs.push("usercontextid");
             }
 
             // If the other tab is pending (i.e. has not been restored, yet)
             // then do not switch docShells but retrieve the other tab's state
             // and apply it to our tab.
             if (isPending) {
               SessionStore.setTabState(aOurTab, SessionStore.getTabState(aOtherTab));
--- a/browser/components/contextualidentity/ContextualIdentityService.jsm
+++ b/browser/components/contextualidentity/ContextualIdentityService.jsm
@@ -4,16 +4,18 @@
 
 this.EXPORTED_SYMBOLS = ["ContextualIdentityService"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm")
 
+const DEFAULT_TAB_COLOR = "#909090"
+
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
   return Services.strings.createBundle("chrome://browser/locale/browser.properties");
 });
 
 this.ContextualIdentityService = {
   _identities: [
     { userContextId: 1,
       icon: "chrome://browser/skin/usercontext/personal.svg",
@@ -47,38 +49,27 @@ this.ContextualIdentityService = {
     return this._identities.find(info => info.userContextId == userContextId);
   },
 
   getUserContextLabel(userContextId) {
     let identity = this.getIdentityFromId(userContextId);
     return gBrowserBundle.GetStringFromName(identity.label);
   },
 
-  needsCssRule() {
-    return !this._cssRule;
-  },
-
-  storeCssRule(cssRule) {
-    this._cssRule = cssRule;
-  },
-
-  cssRules() {
-    let rules = [];
-
-    if (this.needsCssRule()) {
-      return rules;
+  setTabStyle(tab) {
+    // inline style is only a temporary fix for some bad performances related
+    // to the use of CSS vars. This code will be removed in bug 1278177.
+    if (!tab.hasAttribute("usercontextid")) {
+      tab.style.removeProperty("background-image");
+      tab.style.removeProperty("background-size");
+      tab.style.removeProperty("background-repeat");
+      return;
     }
 
-    /* The CSS Rules for the ContextualIdentity tabs are set up like this:
-     * 1. :root { --usercontext-color-<id>: #color }
-     * 2. the template, replacing 'id' with the userContextId.
-     * 3. tabbrowser-tab[usercontextid="<id>"] { background-image: var(--usercontext-tab-<id>) }
-     */
-    for (let identity of this._identities) {
-      rules.push(":root { --usercontext-color-" + identity.userContextId + ": " + identity.color + " }");
+    let userContextId = tab.getAttribute("usercontextid");
+    let identity = this.getIdentityFromId(userContextId);
 
-      rules.push(this._cssRule.replace(/id/g, identity.userContextId));
-      rules.push(".tabbrowser-tab[usercontextid=\"" + identity.userContextId + "\"] { background-image: var(--usercontext-tab-" + identity.userContextId + ") }");
-    }
-
-    return rules;
+    let color = identity ? identity.color : DEFAULT_TAB_COLOR;
+    tab.style.backgroundImage = "linear-gradient(to right, transparent 20%, " + color + " 30%, " + color + " 70%, transparent 80%)";
+    tab.style.backgroundSize = "auto 2px";
+    tab.style.backgroundRepeat = "no-repeat";
   },
 }
--- a/browser/components/contextualidentity/content/usercontext.css
+++ b/browser/components/contextualidentity/content/usercontext.css
@@ -1,27 +1,13 @@
-:root {
-  /* This is used as a template for ContextualIdentityService. 'id' will be
-   * replaced with the userContextId */
-  --usercontext-tab-id: linear-gradient(to right, transparent 20%, var(--usercontext-color-id) 30%, var(--usercontext-color-id) 70%, transparent 80%);
-}
-
 #userContext-indicator {
   height: 16px;
   width: 16px;
 }
 
 #userContext-label {
   margin-inline-end: 3px;
   color: #909090;
 }
 
 #userContext-icons {
   -moz-box-align: center;
 }
-
-/* User Context UI - change tab decoration depending on userContextId.
-   Defaults to gray for unknown usercontextids. */
-.tabbrowser-tab[usercontextid] {
-  background-image: linear-gradient(to right, transparent 20%, #909090 30%, #909090 70%, transparent 80%);
-  background-size: auto 2px;
-  background-repeat: no-repeat;
-}