Bug 1342712 - Allow scoping a theme per-window. r=jaws draft
authorTim Nguyen <ntim.bugs@gmail.com>
Fri, 04 Aug 2017 19:56:21 +0000
changeset 621405 e7df2ce040712a4d1c89351a3ecbc27ae8cd42d1
parent 621399 4cfb674227051e22bab651e5759f3de503a50560
child 724659 0c92571d39b9849a49b8382d7351b77d1cf31458
push id72367
push userbmo:ntim.bugs@gmail.com
push dateFri, 04 Aug 2017 19:56:29 +0000
reviewersjaws
bugs1342712
milestone57.0a1
Bug 1342712 - Allow scoping a theme per-window. r=jaws MozReview-Commit-ID: 1tSXAm3ycjN
npm-shrinkwrap.json
toolkit/components/extensions/ext-theme.js
toolkit/components/extensions/schemas/theme.json
toolkit/modules/LightweightThemeConsumer.jsm
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1,11 +1,10 @@
 {
   "name": "mozillaeslintsetup",
-  "requires": true,
   "lockfileVersion": 1,
   "dependencies": {
     "acorn": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz",
       "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw=="
     },
     "acorn-jsx": {
@@ -388,25 +387,17 @@
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz",
       "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc=",
       "requires": {
         "htmlparser2": "3.9.2"
       }
     },
     "eslint-plugin-mozilla": {
-      "version": "file:tools/lint/eslint/eslint-plugin-mozilla",
-      "requires": {
-        "escope": "3.6.0",
-        "espree": "3.4.3",
-        "estraverse": "4.2.0",
-        "globals": "9.18.0",
-        "ini-parser": "0.0.2",
-        "sax": "1.2.4"
-      }
+      "version": "file:tools/lint/eslint/eslint-plugin-mozilla"
     },
     "eslint-plugin-no-unsanitized": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-2.0.1.tgz",
       "integrity": "sha1-yt7dDQrRfI3FIm23/4hATlmo1n8=",
       "requires": {
         "eslint": "3.19.0"
       }
--- a/toolkit/components/extensions/ext-theme.js
+++ b/toolkit/components/extensions/ext-theme.js
@@ -1,10 +1,12 @@
 "use strict";
 
+/* global windowTracker */
+
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "gThemesEnabled", () => {
   return Services.prefs.getBoolPref("extensions.webextensions.themes.enabled");
 });
@@ -31,18 +33,26 @@ class Theme {
   }
 
   /**
    * Loads a theme by reading the properties from the extension's manifest.
    * This method will override any currently applied theme.
    *
    * @param {Object} details Theme part of the manifest. Supported
    *   properties can be found in the schema under ThemeType.
+   * @param {Object} targetWindow The window to apply the theme to. Ommiting
+   *   this parameter will apply the theme globally.
    */
-  load(details) {
+  load(details, targetWindow) {
+    if (targetWindow) {
+      this.lwtStyles.window = targetWindow
+        .QueryInterface(Ci.nsIInterfaceRequestor)
+        .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
+    }
+
     if (details.colors) {
       this.loadColors(details.colors);
     }
 
     if (details.images) {
       this.loadImages(details.images);
     }
 
@@ -268,30 +278,34 @@ this.theme = class extends ExtensionAPI 
     }
   }
 
   getAPI(context) {
     let {extension} = context;
 
     return {
       theme: {
-        update: (details) => {
+        update: (windowId, details) => {
           if (!gThemesEnabled) {
             // Return early if themes are disabled.
             return;
           }
 
           if (!this.theme) {
             // WebExtensions using the Theme API will not have a theme defined
             // in the manifest. Therefore, we need to initialize the theme the
             // first time browser.theme.update is called.
             this.theme = new Theme(extension.baseURI, extension.logger);
           }
 
-          this.theme.load(details);
+          let browserWindow;
+          if (windowId !== null) {
+            browserWindow = windowTracker.getWindow(windowId, context);
+          }
+          this.theme.load(details, browserWindow);
         },
         reset: () => {
           if (!gThemesEnabled) {
             // Return early if themes are disabled.
             return;
           }
 
           if (!this.theme) {
--- a/toolkit/components/extensions/schemas/theme.json
+++ b/toolkit/components/extensions/schemas/theme.json
@@ -452,16 +452,22 @@
     "functions": [
       {
         "name": "update",
         "type": "function",
         "async": true,
         "description": "Make complete or partial updates to the theme. Resolves when the update has completed.",
         "parameters": [
           {
+            "type": "integer",
+            "name": "windowId",
+            "optional": true,
+            "description": "The id of the window to update. No id updates all windows."
+          },
+          {
             "name": "details",
             "$ref": "manifest.ThemeType",
             "description": "The properties of the theme to update."
           }
         ]
       },
       {
         "name": "reset",
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -1,15 +1,15 @@
 /* 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/. */
 
 this.EXPORTED_SYMBOLS = ["LightweightThemeConsumer"];
 
-const {utils: Cu} = Components;
+const {utils: Cu, interfaces: Ci, classes: Cc} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
   "resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm");
 
@@ -61,17 +61,26 @@ LightweightThemeConsumer.prototype = {
   getData() {
     return this._enabled ? Cu.cloneInto(this._lastData, this._win) : null;
   },
 
   observe(aSubject, aTopic, aData) {
     if (aTopic != "lightweight-theme-styling-update")
       return;
 
-    this._update(JSON.parse(aData));
+    const { outerWindowID } = this._win
+      .QueryInterface(Ci.nsIInterfaceRequestor)
+      .getInterface(Ci.nsIDOMWindowUtils);
+
+    const parsedData = JSON.parse(aData);
+    if (parsedData.window && parsedData.window !== outerWindowID) {
+      return;
+    }
+
+    this._update(parsedData);
   },
 
   handleEvent(aEvent) {
     let {width, height} = this._win.screen;
 
     if (this._lastScreenWidth != width || this._lastScreenHeight != height) {
       this._lastScreenWidth = width;
       this._lastScreenHeight = height;