Bug 1330340 - Implement support for lightweight theme properties (headerURL, accentcolor, textcolor) for Theming API. r?mikedeboer draft
authorJared Wein <jwein@mozilla.com>
Tue, 24 Jan 2017 11:44:44 -0500
changeset 465732 a9b7238827343fde5c36a2b429830da7675c57a5
parent 464990 5a4412474c63e1d9e66036d603ac42e9cb2b9150
child 543233 a5c80ee86e56583d69db1e4bccb9b8610873dfbd
push id42690
push userjwein@mozilla.com
push dateTue, 24 Jan 2017 19:06:00 +0000
reviewersmikedeboer
bugs1330340
milestone54.0a1
Bug 1330340 - Implement support for lightweight theme properties (headerURL, accentcolor, textcolor) for Theming API. r?mikedeboer MozReview-Commit-ID: GS1Gh4HVcOt
browser/components/extensions/ext-theme.js
browser/components/extensions/schemas/theme.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_themes.js
browser/components/extensions/test/browser/browser_ext_themes_lwtsupport.js
--- a/browser/components/extensions/ext-theme.js
+++ b/browser/components/extensions/ext-theme.js
@@ -1,19 +1,62 @@
 "use strict";
 
+Cu.import("resource://gre/modules/Services.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
                                   "resource://gre/modules/Preferences.jsm");
 
 /* eslint-disable mozilla/balanced-listeners */
 extensions.on("manifest_theme", (type, directive, extension, manifest) => {
   let enabled = Preferences.get("extensions.webextensions.themes.enabled");
-  extension.emit("test-message", "themes-enabled", enabled);
+
+  if (!enabled || !manifest || !manifest.theme) {
+    return;
+  }
+  // Apply theme only if themes are enabled.
+  let lwtStyles = {footerURL: ""};
+  if (manifest.theme.colors) {
+    let colors = manifest.theme.colors;
+    for (let color of Object.getOwnPropertyNames(colors)) {
+      let val = colors[color];
+      // Since values are optional, they may be `null`.
+      if (val === null) {
+        continue;
+      }
 
-  if (enabled) {
-    // Apply theme only if themes are enabled.
+      if (color == "accentcolor") {
+        lwtStyles.accentcolor = val;
+        continue;
+      }
+      if (color == "textcolor") {
+        lwtStyles.textcolor = val;
+      }
+    }
+  }
+
+  if (manifest.theme.images) {
+    let images = manifest.theme.images;
+    for (let image of Object.getOwnPropertyNames(images)) {
+      let val = images[image];
+      if (val === null) {
+        continue;
+      }
+
+      if (image == "headerURL") {
+        lwtStyles.headerURL = val;
+      }
+    }
+  }
+
+  if (lwtStyles.headerURL &&
+      lwtStyles.accentcolor &&
+      lwtStyles.textcolor) {
+    Services.obs.notifyObservers(null,
+      "lightweight-theme-styling-update",
+      JSON.stringify(lwtStyles));
   }
 });
 
 extensions.on("shutdown", (type, extension) => {
-  // Remove theme only if it has been applied.
+  Services.obs.notifyObservers(null, "lightweight-theme-styling-update", null);
 });
 /* eslint-enable mozilla/balanced-listeners */
--- a/browser/components/extensions/schemas/theme.json
+++ b/browser/components/extensions/schemas/theme.json
@@ -3,17 +3,43 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 [
   {
     "namespace": "manifest",
     "types": [
       {
         "id": "ThemeType",
-        "type": "object"
+        "type": "object",
+        "properties": {
+          "images": {
+            "type": "object",
+            "optional": true,
+            "properties": {
+              "headerURL": {
+                "type": "string",
+                "optional": true
+              }
+            }
+          },
+          "colors": {
+            "type": "object",
+            "optional": true,
+            "properties": {
+              "accentcolor": {
+                "type": "string",
+                "optional": true
+              },
+              "textcolor": {
+                "type": "string",
+                "optional": true
+              }
+            }
+          }
+        }
       },
       {
         "$extend": "WebExtensionManifest",
         "properties": {
           "theme": {
             "optional": true,
             "$ref": "ThemeType"
           }
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -100,17 +100,17 @@ support-files =
 [browser_ext_tabs_query.js]
 [browser_ext_tabs_reload.js]
 [browser_ext_tabs_reload_bypass_cache.js]
 [browser_ext_tabs_sendMessage.js]
 [browser_ext_tabs_cookieStoreId.js]
 [browser_ext_tabs_update.js]
 [browser_ext_tabs_zoom.js]
 [browser_ext_tabs_update_url.js]
-[browser_ext_themes.js]
+[browser_ext_themes_lwtsupport.js]
 [browser_ext_topwindowid.js]
 [browser_ext_webRequest.js]
 [browser_ext_webNavigation_frameId0.js]
 [browser_ext_webNavigation_getFrames.js]
 [browser_ext_webNavigation_urlbar_transitions.js]
 [browser_ext_windows.js]
 [browser_ext_windows_create.js]
 tags = fullscreen
deleted file mode 100644
--- a/browser/components/extensions/test/browser/browser_ext_themes.js
+++ /dev/null
@@ -1,23 +0,0 @@
-"use strict";
-
-add_task(function* test_themes_disabled_by_default() {
-  let manifest = {"theme": {}};
-  let extension = ExtensionTestUtils.loadExtension({manifest});
-
-  yield extension.startup();
-  let enabled = yield extension.awaitMessage("themes-enabled");
-  is(enabled, false, "Themes should be disabled");
-  yield extension.unload();
-});
-
-add_task(function* test_themes_enabled_with_preference() {
-  Services.prefs.setBoolPref("extensions.webextensions.themes.enabled", true);
-
-  let manifest = {"theme": {}};
-  let extension = ExtensionTestUtils.loadExtension({manifest});
-
-  yield extension.startup();
-  let enabled = yield extension.awaitMessage("themes-enabled");
-  is(enabled, true, "Themes should be enabled");
-  yield extension.unload();
-});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_themes_lwtsupport.js
@@ -0,0 +1,91 @@
+"use strict";
+
+const kBackground = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
+const kAccentColor = "#a14040";
+const kTextColor = "#fac96e";
+
+function hexToRGB(hex) {
+  hex = parseInt((hex.indexOf("#") > -1 ? hex.substring(1) : hex), 16);
+  return [hex >> 16, (hex & 0x00FF00) >> 8, (hex & 0x0000FF)];
+}
+
+add_task(function* setup() {
+  yield SpecialPowers.pushPrefEnv({
+    set: [["extensions.webextensions.themes.enabled", true]],
+  });
+});
+
+add_task(function* testSupportLWTProperties() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "theme": {
+        "images": {
+          "headerURL": kBackground,
+        },
+        "colors": {
+          "accentcolor": kAccentColor,
+          "textcolor": kTextColor,
+        },
+      },
+    },
+  });
+
+  yield extension.startup();
+
+  let docEl = window.document.documentElement;
+  let style = window.getComputedStyle(docEl);
+
+  Assert.ok(docEl.hasAttribute("lwtheme"), "LWT attribute should be set");
+  Assert.equal(docEl.getAttribute("lwthemetextcolor"), "bright",
+    "LWT text color attribute should be set");
+
+  Assert.equal(style.backgroundImage, 'url("' + kBackground.replace(/"/g, '\\"') + '")',
+    "Expected background image");
+  Assert.equal(style.backgroundColor, "rgb(" + hexToRGB(kAccentColor).join(", ") + ")",
+    "Expected correct background color");
+  Assert.equal(style.color, "rgb(" + hexToRGB(kTextColor).join(", ") + ")",
+    "Expected correct text color");
+
+  yield extension.unload();
+
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+});
+
+add_task(function* testLWTRequiresAllPropertiesDefinedImageOnly() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "theme": {
+        "images": {
+          "headerURL": kBackground,
+        },
+      },
+    },
+  });
+
+  yield extension.startup();
+
+  let docEl = window.document.documentElement;
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  yield extension.unload();
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+});
+
+add_task(function* testLWTRequiresAllPropertiesDefinedColorsOnly() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "theme": {
+        "colors": {
+          "accentcolor": kAccentColor,
+          "textcolor": kTextColor,
+        },
+      },
+    },
+  });
+
+  yield extension.startup();
+
+  let docEl = window.document.documentElement;
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  yield extension.unload();
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+});