Bug 1404688 - Make headerURL optional and remove text-shadow when there is no headerURL. r=jaws
authorTim Nguyen <ntim.bugs@gmail.com>
Thu, 15 Feb 2018 13:37:30 +0000
changeset 403944 58d315ce1f1b2a855174a4e309afa1f3f6578569
parent 403943 f349f28b9689446dfe45b63fd6bbeaa428bdaf44
child 403945 3ffcad22d632d1cd97285b3a54cb469227bd1df1
push id33446
push usernerli@mozilla.com
push dateThu, 15 Feb 2018 19:28:20 +0000
treeherdermozilla-central@dc9ba6649af7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1404688
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1404688 - Make headerURL optional and remove text-shadow when there is no headerURL. r=jaws MozReview-Commit-ID: 5x6SPWEJ3jp
browser/base/content/browser.css
browser/base/content/defaultthemes/compact.header.png
browser/base/content/test/general/browser_compacttheme.js
browser/base/jar.mn
browser/components/nsBrowserGlue.js
browser/themes/shared/compacttheme.inc.css
browser/themes/shared/customizableui/customizeMode.inc.css
browser/themes/shared/tabs.inc.css
browser/themes/windows/browser-aero.css
browser/themes/windows/compacttheme.css
toolkit/components/extensions/ext-theme.js
toolkit/components/extensions/test/browser/browser_ext_themes_lwtsupport.js
toolkit/components/extensions/test/browser/browser_ext_themes_toolbars.js
toolkit/modules/LightweightThemeConsumer.jsm
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
toolkit/themes/linux/global/global.css
toolkit/themes/linux/global/toolbarbutton.css
toolkit/themes/osx/global/global.css
toolkit/themes/windows/global/global.css
toolkit/themes/windows/global/toolbarbutton.css
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -13,21 +13,25 @@
 }
 
 :root:-moz-lwtheme {
   color: var(--lwt-text-color) !important;
 }
 
 :root:-moz-lwtheme {
   background-color: var(--lwt-accent-color) !important;
-  background-image: var(--lwt-header-image), var(--lwt-additional-images) !important;
+  background-image: var(--lwt-additional-images) !important;
   background-position: var(--lwt-background-alignment) !important;
   background-repeat: var(--lwt-background-tiling) !important;
 }
 
+:root:-moz-lwtheme[lwtheme-image] {
+  background-image: var(--lwt-header-image), var(--lwt-additional-images) !important;
+}
+
 :root:-moz-lwtheme:-moz-window-inactive {
   background-color: var(--lwt-accent-color-inactive, var(--lwt-accent-color)) !important;
 }
 
 #main-window:not([chromehidden~="toolbar"]) {
 %ifdef XP_MACOSX
   min-width: 335px;
 %else
deleted file mode 100644
index e4e8dcaa3b3cd01a1287359902561166d7f942ee..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/base/content/test/general/browser_compacttheme.js
+++ b/browser/base/content/test/general/browser_compacttheme.js
@@ -41,17 +41,16 @@ add_task(async function startTests() {
   LightweightThemeManager.currentTheme = null;
   ok(!CompactTheme.isStyleSheetEnabled, "There is no compact style sheet when no lw theme is applied.");
 });
 
 function dummyLightweightTheme(id) {
   return {
     id,
     name: id,
-    headerURL: "resource:///chrome/browser/content/browser/defaultthemes/compact.header.png",
     iconURL: "resource:///chrome/browser/content/browser/defaultthemes/light.icon.svg",
     textcolor: "red",
     accentcolor: "blue"
   };
 }
 
 add_task(async function testLightweightThemePreview() {
   info("Setting compact to current and previewing others");
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -91,17 +91,16 @@ browser.jar:
         content/browser/defaultthemes/3.icon.png      (content/defaultthemes/3.icon.png)
         content/browser/defaultthemes/3.preview.png   (content/defaultthemes/3.preview.png)
         content/browser/defaultthemes/4.header.png    (content/defaultthemes/4.header.png)
         content/browser/defaultthemes/4.icon.png      (content/defaultthemes/4.icon.png)
         content/browser/defaultthemes/4.preview.png   (content/defaultthemes/4.preview.png)
         content/browser/defaultthemes/5.header.png    (content/defaultthemes/5.header.png)
         content/browser/defaultthemes/5.icon.jpg      (content/defaultthemes/5.icon.jpg)
         content/browser/defaultthemes/5.preview.jpg   (content/defaultthemes/5.preview.jpg)
-        content/browser/defaultthemes/compact.header.png    (content/defaultthemes/compact.header.png)
         content/browser/defaultthemes/dark.icon.svg  (content/defaultthemes/dark.icon.svg)
         content/browser/defaultthemes/light.icon.svg (content/defaultthemes/light.icon.svg)
         content/browser/newtab/newTab.xhtml           (content/newtab/newTab.xhtml)
 *       content/browser/newtab/newTab.js              (content/newtab/newTab.js)
         content/browser/newtab/newTab.css             (content/newtab/newTab.css)
         content/browser/newtab/alternativeDefaultSites.json   (content/newtab/alternativeDefaultSites.json)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -695,27 +695,25 @@ BrowserGlue.prototype = {
     SessionStore.init();
 
     let vendorShortName = gBrandBundle.GetStringFromName("vendorShortName");
 
     LightweightThemeManager.addBuiltInTheme({
       id: "firefox-compact-light@mozilla.org",
       name: gBrowserBundle.GetStringFromName("lightTheme.name"),
       description: gBrowserBundle.GetStringFromName("lightTheme.description"),
-      headerURL: "resource:///chrome/browser/content/browser/defaultthemes/compact.header.png",
       iconURL: "resource:///chrome/browser/content/browser/defaultthemes/light.icon.svg",
       textcolor: "black",
       accentcolor: "white",
       author: vendorShortName,
     });
     LightweightThemeManager.addBuiltInTheme({
       id: "firefox-compact-dark@mozilla.org",
       name: gBrowserBundle.GetStringFromName("darkTheme.name"),
       description: gBrowserBundle.GetStringFromName("darkTheme.description"),
-      headerURL: "resource:///chrome/browser/content/browser/defaultthemes/compact.header.png",
       iconURL: "resource:///chrome/browser/content/browser/defaultthemes/dark.icon.svg",
       textcolor: "white",
       accentcolor: "black",
       author: vendorShortName,
     });
 
 
     // Initialize the default l10n resource sources for L10nRegistry.
--- a/browser/themes/shared/compacttheme.inc.css
+++ b/browser/themes/shared/compacttheme.inc.css
@@ -2,18 +2,16 @@
 % 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/.
 
 /* compacttheme.css is loaded in browser.xul after browser.css when it is
    preffed on.  The bulk of the styling is here in the shared file, but
    there are overrides for each platform in their compacttheme.css files. */
 
 :root:-moz-lwtheme {
-  text-shadow: none;
-
   --toolbar-bgcolor: var(--chrome-secondary-background-color);
   --toolbar-gbimage: none;
   --toolbar-non-lwt-bgcolor: var(--toolbar-bgcolor);
   --toolbar-non-lwt-textcolor: var(--chrome-color);
   --toolbar-non-lwt-bgimage: none;
 
   --toolbarbutton-icon-fill-opacity: .7;
 }
@@ -104,14 +102,8 @@ toolbar[brighttext] .toolbarbutton-1 {
 
 #urlbar-zoom-button:-moz-lwtheme-brighttext:hover {
   background-color: rgba(255,255,255,.2);
 }
 
 #urlbar-zoom-button:-moz-lwtheme-brighttext:hover:active {
   background-color: rgba(255,255,255,.3);
 }
-
-.tab-icon-sound[soundplaying],
-.tab-icon-sound[muted] {
-  filter: none !important; /* removes drop-shadow filter */
-}
-
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -14,32 +14,32 @@
 
 #customization-container {
   background-color: var(--toolbar-non-lwt-bgcolor);
   background-image: var(--toolbar-non-lwt-bgimage);
   color: var(--toolbar-non-lwt-textcolor);
   text-shadow: none;
 }
 
-#customization-container:-moz-lwtheme {
+:root[lwtheme-image] #customization-container {
   background-color: transparent;
   background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-non-lwt-bgcolor) 45px);
 }
 
 #customization-palette {
   padding: 5px 20px 20px;
 }
 
 #customization-header {
   font-weight: 500;
   font-size: 1.2em;
   margin: 20px 20px 15px;
 }
 
-#customization-header:-moz-lwtheme {
+:root[lwtheme-image] #customization-header {
   text-shadow: 0 0 1em var(--toolbar-non-lwt-bgcolor),
                0 0 1em var(--toolbar-non-lwt-bgcolor),
                0 0 .5em var(--toolbar-non-lwt-bgcolor);
 }
 
 #customization-panel-container {
   padding: 0 20px 25px;
 }
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -406,25 +406,25 @@ tabbrowser {
 .tab-icon-sound[muted] {
   list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio-muted.svg);
 }
 
 .tab-icon-sound[activemedia-blocked] {
   list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio-blocked.svg);
 }
 
-.tab-icon-sound:-moz-lwtheme-darktext[soundplaying],
-.tab-icon-sound:-moz-lwtheme-darktext[muted],
-.tab-icon-sound:-moz-lwtheme-darktext[activemedia-blocked] {
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[soundplaying],
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[muted],
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-darktext[activemedia-blocked] {
   filter: drop-shadow(1px 1px 1px white);
 }
 
-.tab-icon-sound:-moz-lwtheme-brighttext[soundplaying],
-.tab-icon-sound:-moz-lwtheme-brighttext[muted],
-.tab-icon-sound:-moz-lwtheme-brighttext[activemedia-blocked] {
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[soundplaying],
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[muted],
+:root[lwtheme-image] .tab-icon-sound:-moz-lwtheme-brighttext[activemedia-blocked] {
   filter: drop-shadow(1px 1px 1px black);
 }
 
 .tab-icon-sound[soundplaying]:not(:hover),
 .tab-icon-sound[muted]:not(:hover),
 .tab-icon-sound[activemedia-blocked]:not(:hover) {
   opacity: .8;
 }
@@ -525,17 +525,17 @@ tabbrowser {
 }
 
 /*
  * LightweightThemeConsumer will set the current lightweight theme's header
  * image to the lwt-header-image variable, used in each of the following rulesets.
  */
 
 /* Lightweight theme on tabs */
-#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background[selected=true]:-moz-lwtheme {
+:root[lwtheme-image] #tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background[selected=true] {
   background-attachment: scroll, fixed;
   background-color: transparent;
   background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor)),
                     var(--lwt-header-image);
   background-position: 0 0, right top;
   background-repeat: repeat-x, no-repeat;
   background-size: auto 100%, auto auto;
 }
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -101,29 +101,29 @@
       :root[sizemode="maximized"] #titlebar-max {
         list-style-image: url(chrome://browser/skin/window-controls/restore.svg);
       }
 
       #titlebar-close {
         list-style-image: url(chrome://browser/skin/window-controls/close.svg);
       }
 
-      .titlebar-button:-moz-lwtheme {
+      :root[lwtheme-image] .titlebar-button {
         -moz-context-properties: unset;
       }
-      #titlebar-min:-moz-lwtheme {
+      :root[lwtheme-image] #titlebar-min {
         list-style-image: url(chrome://browser/skin/window-controls/minimize-themes.svg);
       }
-      #titlebar-max:-moz-lwtheme {
+      :root[lwtheme-image] #titlebar-max {
         list-style-image: url(chrome://browser/skin/window-controls/maximize-themes.svg);
       }
-      :root[sizemode="maximized"] #titlebar-max:-moz-lwtheme {
+      :root[lwtheme-image][sizemode="maximized"] #titlebar-max {
         list-style-image: url(chrome://browser/skin/window-controls/restore-themes.svg);
       }
-      #titlebar-close:-moz-lwtheme {
+      :root[lwtheme-image] #titlebar-close {
         list-style-image: url(chrome://browser/skin/window-controls/close-themes.svg);
       }
 
       /* the 12px image renders a 10px icon, and the 10px upscaled gets rounded to 12.5, which
        * rounds up to 13px, which makes the icon one pixel too big on 1.25dppx. Fix: */
       @media (min-resolution: 1.20dppx) and (max-resolution: 1.45dppx) {
         .titlebar-button > .toolbarbutton-icon {
           width: 11.5px;
--- a/browser/themes/windows/compacttheme.css
+++ b/browser/themes/windows/compacttheme.css
@@ -26,20 +26,16 @@
       background-color: rgb(185,209,234) !important;
     }
     #main-window:-moz-window-inactive {
       background-color: rgb(215,228,242) !important;
     }
   }
 }
 
-#toolbar-menubar {
-  text-shadow: none !important;
-}
-
 @media (-moz-os-version: windows-win7) {
   @media (-moz-windows-default-theme) {
     /* Always show light toolbar elements on aero surface. */
     #TabsToolbar {
       color: hsl(240,9%,98%);
     }
 
     /* Keep showing the correct color inside the tabs. */
@@ -60,21 +56,16 @@
 }
 
 @media (-moz-windows-glass) {
   /* Set to full fill-opacity to improve visibility of toolbar buttons on aero glass. */
   #TabsToolbar {
     --toolbarbutton-icon-fill-opacity: 1;
   }
 
-  /* Make the menubar text readable on aero glass (copied from browser-aero.css). */
-  #toolbar-menubar {
-    text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
-  }
-
   #main-menubar:not(:-moz-window-inactive) {
     background-color: rgba(255,255,255,.5);
     color: black;
     border-radius: 4px;
   }
 }
 
 @media (-moz-os-version: windows-win7),
@@ -150,28 +141,8 @@
  * over the native border with our custom borders: */
 #navigator-toolbox {
   /* These are !important to avoid specificity-wars with the selectors that add borders here. */
   background-image: none !important;
   border-top: none !important;
   box-shadow: none !important;
   padding-top: 0 !important;
 }
-
-@media (-moz-os-version: windows-win10) {
-  .titlebar-button:-moz-lwtheme {
-    -moz-context-properties: stroke;
-    stroke: currentColor;
-  }
-  #titlebar-min:-moz-lwtheme {
-    list-style-image: url(chrome://browser/skin/window-controls/minimize.svg);
-  }
-  #titlebar-max:-moz-lwtheme {
-    list-style-image: url(chrome://browser/skin/window-controls/maximize.svg);
-  }
-  :root[sizemode="maximized"] #titlebar-max:-moz-lwtheme {
-    list-style-image: url(chrome://browser/skin/window-controls/restore.svg);
-  }
-  #titlebar-close:-moz-lwtheme {
-    list-style-image: url(chrome://browser/skin/window-controls/close.svg);
-  }
-}
-
--- a/toolkit/components/extensions/ext-theme.js
+++ b/toolkit/components/extensions/ext-theme.js
@@ -79,19 +79,18 @@ class Theme {
     if (details.icons) {
       this.loadIcons(details.icons);
     }
 
     if (details.properties) {
       this.loadProperties(details.properties);
     }
 
-    // Lightweight themes require all properties to be defined.
-    if (this.lwtStyles.headerURL &&
-        this.lwtStyles.accentcolor &&
+    // Lightweight themes require accentcolor and textcolor to be defined.
+    if (this.lwtStyles.accentcolor &&
         this.lwtStyles.textcolor) {
       if (this.windowId) {
         windowOverrides.set(this.windowId, this);
       } else {
         windowOverrides.clear();
         defaultTheme = this;
       }
       onUpdatedEmitter.emit("theme-updated", this.details, this.windowId);
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_lwtsupport.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_lwtsupport.js
@@ -25,31 +25,76 @@ add_task(async function test_support_LWT
   });
 
   await extension.startup();
 
   let docEl = window.document.documentElement;
   let style = window.getComputedStyle(docEl);
 
   Assert.ok(docEl.hasAttribute("lwtheme"), "LWT attribute should be set");
+  Assert.ok(docEl.hasAttribute("lwtheme-image"), "LWT image attribute should be set");
   Assert.equal(docEl.getAttribute("lwthemetextcolor"), "bright",
                "LWT text color attribute should be set");
 
   Assert.ok(style.backgroundImage.includes("image1.png"), "Expected background image");
   Assert.equal(style.backgroundColor, "rgb(" + hexToRGB(ACCENT_COLOR).join(", ") + ")",
                "Expected correct background color");
   Assert.equal(style.color, "rgb(" + hexToRGB(TEXT_COLOR).join(", ") + ")",
                "Expected correct text color");
 
   await extension.unload();
 
   Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
 });
 
-add_task(async function test_LWT_requires_all_properties_defined_image_only() {
+add_task(async function test_LWT_image_attribute() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "theme": {
+        "colors": {
+          "accentcolor": ACCENT_COLOR,
+          "textcolor": TEXT_COLOR,
+        },
+      },
+    },
+  });
+
+  await extension.startup();
+
+  let docEl = window.document.documentElement;
+  Assert.ok(docEl.hasAttribute("lwtheme"), "LWT attribute should be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
+  await extension.unload();
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
+});
+
+add_task(async function test_LWT_requires_accentcolor_defined_textcolor_only() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      "theme": {
+        "colors": {
+          "textcolor": TEXT_COLOR,
+        },
+      },
+    },
+  });
+
+  await extension.startup();
+
+  let docEl = window.document.documentElement;
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
+  await extension.unload();
+  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
+});
+
+add_task(async function test_LWT_requires_accentcolor_defined_image_only() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "theme": {
         "images": {
           "headerURL": "image1.png",
         },
       },
     },
@@ -57,31 +102,13 @@ add_task(async function test_LWT_require
       "image1.png": BACKGROUND,
     },
   });
 
   await extension.startup();
 
   let docEl = window.document.documentElement;
   Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
   await extension.unload();
   Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
+  Assert.ok(!docEl.hasAttribute("lwtheme-image"), "LWT image attribute should not be set");
 });
-
-add_task(async function test_LWT_requires_all_properties_defined_colors_only() {
-  let extension = ExtensionTestUtils.loadExtension({
-    manifest: {
-      "theme": {
-        "colors": {
-          "accentcolor": ACCENT_COLOR,
-          "textcolor": TEXT_COLOR,
-        },
-      },
-    },
-  });
-
-  await extension.startup();
-
-  let docEl = window.document.documentElement;
-  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
-  await extension.unload();
-  Assert.ok(!docEl.hasAttribute("lwtheme"), "LWT attribute should not be set");
-});
--- a/toolkit/components/extensions/test/browser/browser_ext_themes_toolbars.js
+++ b/toolkit/components/extensions/test/browser/browser_ext_themes_toolbars.js
@@ -10,30 +10,24 @@ add_task(async function setup() {
 });
 
 add_task(async function test_support_toolbar_property() {
   const TOOLBAR_COLOR = "#ff00ff";
   const TOOLBAR_TEXT_COLOR = "#9400ff";
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "theme": {
-        "images": {
-          "headerURL": "image1.png",
-        },
         "colors": {
           "accentcolor": ACCENT_COLOR,
           "textcolor": TEXT_COLOR,
           "toolbar": TOOLBAR_COLOR,
           "toolbar_text": TOOLBAR_TEXT_COLOR,
         },
       },
     },
-    files: {
-      "image1.png": BACKGROUND,
-    },
   });
 
   await extension.startup();
 
   let toolbox = document.querySelector("#navigator-toolbox");
   let toolbars = [...toolbox.querySelectorAll("toolbar:not(#TabsToolbar)")].filter(toolbar => {
     let bounds = toolbar.getBoundingClientRect();
     return bounds.width > 0 && bounds.height > 0;
@@ -60,30 +54,24 @@ add_task(async function test_support_too
 });
 
 add_task(async function test_bookmark_text_property() {
   const TOOLBAR_COLOR = [255, 0, 255];
   const TOOLBAR_TEXT_COLOR = [48, 0, 255];
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       "theme": {
-        "images": {
-          "headerURL": "image1.png",
-        },
         "colors": {
           "frame": ACCENT_COLOR,
           "background_tab_text": TEXT_COLOR,
           "toolbar": TOOLBAR_COLOR,
           "bookmark_text": TOOLBAR_TEXT_COLOR,
         },
       },
     },
-    files: {
-      "image1.png": BACKGROUND,
-    },
   });
 
   await extension.startup();
 
   let toolbox = document.querySelector("#navigator-toolbox");
   let toolbars = [...toolbox.querySelectorAll("toolbar:not(#TabsToolbar)")].filter(toolbar => {
     let bounds = toolbar.getBoundingClientRect();
     return bounds.width > 0 && bounds.height > 0;
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -104,17 +104,17 @@ LightweightThemeConsumer.prototype = {
     } else {
       this._lastData = aData;
       aData = LightweightThemeImageOptimizer.optimize(aData, this._win.screen);
     }
     if (!this._enabled)
       return;
 
     let root = this._doc.documentElement;
-    let active = !!aData.headerURL;
+    let active = !!aData.accentcolor;
 
     // We need to clear these either way: either because the theme is being removed,
     // or because we are applying a new theme and the data might be bogus CSS,
     // so if we don't reset first, it'll keep the old value.
     root.style.removeProperty("--lwt-text-color");
     root.style.removeProperty("--lwt-accent-color");
     let textcolor = aData.textcolor || "black";
     _setProperty(root, active, "--lwt-text-color", textcolor);
@@ -127,16 +127,22 @@ LightweightThemeConsumer.prototype = {
       let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
       root.setAttribute("lwthemetextcolor", luminance <= 110 ? "dark" : "bright");
       root.setAttribute("lwtheme", "true");
     } else {
       root.removeAttribute("lwthemetextcolor");
       root.removeAttribute("lwtheme");
     }
 
+    if (aData.headerURL) {
+      root.setAttribute("lwtheme-image", "true");
+    } else {
+      root.removeAttribute("lwtheme-image");
+    }
+
     this._active = active;
 
     if (aData.icons) {
       let activeIcons = active ? Object.keys(aData.icons).join(" ") : "";
       root.setAttribute("lwthemeicons", activeIcons);
       for (let [name, value] of Object.entries(aData.icons)) {
         _setImage(root, active, name, value);
       }
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -19,20 +19,20 @@ const ADDON_TYPE             = "theme";
 const ADDON_TYPE_WEBEXT      = "webextension-theme";
 
 const URI_EXTENSION_STRINGS  = "chrome://mozapps/locale/extensions/extensions.properties";
 
 const DEFAULT_MAX_USED_THEMES_COUNT = 30;
 
 const MAX_PREVIEW_SECONDS = 30;
 
-const MANDATORY = ["id", "name", "headerURL"];
-const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
-                  "previewURL", "author", "description", "homepageURL",
-                  "updateURL", "version"];
+const MANDATORY = ["id", "name"];
+const OPTIONAL = ["headerURL", "footerURL", "textcolor", "accentcolor",
+                  "iconURL", "previewURL", "author", "description",
+                  "homepageURL", "updateURL", "version"];
 
 const PERSIST_ENABLED = true;
 const PERSIST_BYPASS_CACHE = false;
 const PERSIST_FILES = {
   headerURL: "lightweighttheme-header",
   footerURL: "lightweighttheme-footer"
 };
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js
@@ -1,12 +1,12 @@
-const MANDATORY = ["id", "name", "headerURL"];
-const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
-                  "previewURL", "author", "description", "homepageURL",
-                  "updateURL", "version"];
+const MANDATORY = ["id", "name"];
+const OPTIONAL = ["headerURL", "footerURL", "textcolor", "accentcolor",
+                  "iconURL", "previewURL", "author", "description",
+                  "homepageURL", "updateURL", "version"];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 function dummy(id) {
   return {
     id: id || Math.random().toString(),
     name: Math.random().toString(),
     headerURL: "http://lwttest.invalid/a.png",
@@ -307,42 +307,42 @@ function run_test() {
   delete data.name;
   try {
     ltm.currentTheme = data;
     do_throw("Should have rejected a theme with no name");
   } catch (e) {
     // Expected exception
   }
 
+  // Sanitize themes with a bad headerURL
   data = dummy();
   data.headerURL = "foo";
-  try {
-    ltm.currentTheme = data;
-    do_throw("Should have rejected a theme with a bad headerURL");
-  } catch (e) {
-    // Expected exception
-  }
+  ltm.currentTheme = data;
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.headerURL, undefined);
+  ltm.forgetUsedTheme(ltm.currentTheme.id);
+  Assert.equal(ltm.usedThemes.length, 0);
 
+  // Sanitize themes with a non-http(s) headerURL
   data = dummy();
   data.headerURL = "ftp://lwtest.invalid/test.png";
-  try {
-    ltm.currentTheme = data;
-    do_throw("Should have rejected a theme with a non-http(s) headerURL");
-  } catch (e) {
-    // Expected exception
-  }
+  ltm.currentTheme = data;
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.headerURL, undefined);
+  ltm.forgetUsedTheme(ltm.currentTheme.id);
+  Assert.equal(ltm.usedThemes.length, 0);
 
+  // Sanitize themes with a non-http(s) headerURL
   data = dummy();
   data.headerURL = "file:///test.png";
-  try {
-    ltm.currentTheme = data;
-    do_throw("Should have rejected a theme with a non-http(s) headerURL");
-  } catch (e) {
-    // Expected exception
-  }
+  ltm.currentTheme = data;
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.headerURL, undefined);
+  ltm.forgetUsedTheme(ltm.currentTheme.id);
+  Assert.equal(ltm.usedThemes.length, 0);
 
   data = dummy();
   data.updateURL = "file:///test.json";
   ltm.setLocalTheme(data);
   Assert.equal(ltm.usedThemes.length, 1);
   Assert.equal(ltm.currentTheme.updateURL, undefined);
   ltm.forgetUsedTheme(ltm.currentTheme.id);
   Assert.equal(ltm.usedThemes.length, 0);
@@ -352,22 +352,21 @@ function run_test() {
   ltm.setLocalTheme(data);
   Assert.equal(ltm.usedThemes.length, 1);
   Assert.equal(ltm.currentTheme.headerURL, "file:///test.png");
   ltm.forgetUsedTheme(ltm.currentTheme.id);
   Assert.equal(ltm.usedThemes.length, 0);
 
   data = dummy();
   data.headerURL = "ftp://lwtest.invalid/test.png";
-  try {
-    ltm.setLocalTheme(data);
-    do_throw("Should have rejected a theme with a non-http(s), non-file headerURL");
-  } catch (e) {
-    // Expected exception
-  }
+  ltm.setLocalTheme(data);
+  Assert.equal(ltm.usedThemes.length, 1);
+  Assert.equal(ltm.currentTheme.updateURL, undefined);
+  ltm.forgetUsedTheme(ltm.currentTheme.id);
+  Assert.equal(ltm.usedThemes.length, 0);
 
   data = dummy();
   delete data.id;
   try {
     ltm.currentTheme = data;
     do_throw("Should have rejected a theme with no ID");
   } catch (e) {
     // Expected exception
--- a/toolkit/themes/linux/global/global.css
+++ b/toolkit/themes/linux/global/global.css
@@ -117,21 +117,21 @@ toolbar[mode="text"] .toolbarbutton-text
 }
 
 /* ::::: miscellaneous formatting ::::: */
 
 :root:-moz-lwtheme {
   -moz-appearance: none;
 }
 
-:root:-moz-lwtheme-darktext {
+:root[lwtheme-image]:-moz-lwtheme-darktext {
   text-shadow: 0 -0.5px 1.5px white;
 }
 
-:root:-moz-lwtheme-brighttext {
+:root[lwtheme-image]:-moz-lwtheme-brighttext {
   text-shadow: 1px 1px 1.5px black;
 }
 
 .inset {
   border: 1px solid ThreeDShadow;
   border-right-color: ThreeDHighlight;
   border-bottom-color: ThreeDHighlight;
   margin: 0 5px 5px;
--- a/toolkit/themes/linux/global/toolbarbutton.css
+++ b/toolkit/themes/linux/global/toolbarbutton.css
@@ -13,17 +13,17 @@
 toolbarbutton {
   -moz-appearance: toolbarbutton;
   -moz-box-align: center;
   -moz-box-pack: center;
   margin: 0;
   padding: 3px;
 }
 
-toolbarbutton:-moz-lwtheme {
+:root[lwtheme-image] toolbarbutton {
   text-shadow: none;
 }
 
 .toolbarbutton-icon[label]:not([label=""]),
 .toolbarbutton-icon[type="menu"] {
   margin-inline-end: 2px;
 }
 
--- a/toolkit/themes/osx/global/global.css
+++ b/toolkit/themes/osx/global/global.css
@@ -98,21 +98,21 @@ sidebarheader {
   color: -moz-dialogText;
   text-shadow: none;
 }
 
 :root:-moz-lwtheme {
   -moz-appearance: none;
 }
 
-:root:-moz-lwtheme-darktext {
+:root[lwtheme-image]:-moz-lwtheme-darktext {
   text-shadow: 0 -0.5px 1.5px white;
 }
 
-:root:-moz-lwtheme-brighttext {
+:root[lwtheme-image]:-moz-lwtheme-brighttext {
   text-shadow: 1px 1px 1.5px black;
 }
 
 .inset {
   border: 1px solid ThreeDShadow;
   border-right-color: ThreeDHighlight;
   border-bottom-color: ThreeDHighlight;
   margin: 0 5px 5px;
--- a/toolkit/themes/windows/global/global.css
+++ b/toolkit/themes/windows/global/global.css
@@ -124,21 +124,21 @@ sidebarheader > label {
 
 toolbar[mode="text"] .toolbarbutton-text {
   padding: 0 !important;
   margin: 3px 5px !important;
 }
 
 /* ::::: miscellaneous formatting ::::: */
 
-:root:-moz-lwtheme-darktext {
+:root[lwtheme-image]:-moz-lwtheme-darktext {
   text-shadow: 0 -0.5px 1.5px white;
 }
 
-:root:-moz-lwtheme-brighttext {
+:root[lwtheme-image]:-moz-lwtheme-brighttext {
   text-shadow: 1px 1px 1.5px black;
 }
 
 .inset {
   border: 1px solid ThreeDShadow;
   border-right-color: ThreeDHighlight;
   border-bottom-color: ThreeDHighlight;
   margin: 0 5px 5px;
--- a/toolkit/themes/windows/global/toolbarbutton.css
+++ b/toolkit/themes/windows/global/toolbarbutton.css
@@ -65,31 +65,31 @@ toolbarbutton[checked="true"]:not([disab
   padding-top: 4px;
   padding-bottom: 2px;
   padding-inline-start: 4px;
   padding-inline-end: 2px;
   color: ButtonText;
 }
 
 @media (-moz-windows-default-theme) {
-  toolbarbutton:-moz-lwtheme {
+  :root[lwtheme-image] toolbarbutton {
     text-shadow: none;
   }
 
-  toolbarbutton:-moz-lwtheme:not([disabled="true"]) {
+  :root[lwtheme-image] toolbarbutton:not([disabled="true"]) {
     text-shadow: inherit;
   }
 }
 
 @media (-moz-windows-default-theme: 0) {
-  toolbarbutton:-moz-lwtheme {
+  :root[lwtheme-image] toolbarbutton {
     -moz-appearance: none;
   }
 
-  toolbarbutton:-moz-lwtheme:not([disabled="true"]) {
+  :root[lwtheme-image] toolbarbutton:not([disabled="true"]) {
     text-shadow: inherit;
   }
 }
 
 /* ::::: toolbarbutton menu ::::: */
 
 .toolbarbutton-menu-dropmarker {
   -moz-appearance: none !important;