Bug 1094821 - Install a devedition lightweight theme on startup, then wait for it to be applied before applying devedition styles;r=Gijs
authorBrian Grinstead <bgrinstead@mozilla.com>
Wed, 25 Mar 2015 06:54:18 -0700
changeset 266012 01482cdccd72b4f36f10ff3706a92c4c77c48253
parent 265861 2894f27c8ca7bf2259f1b6c0b961b01f10376c40
child 266013 2aa9f4d0385dc96b1ce0c5ff4f439ce0f42d7b41
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1094821
milestone39.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 1094821 - Install a devedition lightweight theme on startup, then wait for it to be applied before applying devedition styles;r=Gijs
browser/app/profile/firefox.js
browser/base/content/browser-devedition.js
browser/base/content/browser.js
browser/base/content/defaultthemes/devedition.header.png
browser/base/content/defaultthemes/devedition.icon.png
browser/base/content/test/general/browser_devedition.js
browser/base/jar.mn
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/content/customizeMode.inc.xul
browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
browser/components/customizableui/test/browser_970511_undo_restore_default.js
browser/components/nsBrowserGlue.js
browser/devtools/framework/test/browser.ini
browser/devtools/framework/test/browser_toolbox_options_devedition.js
browser/devtools/framework/toolbox-options.js
browser/devtools/framework/toolbox-options.xul
browser/devtools/framework/toolbox-process-window.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1328,21 +1328,18 @@ pref("services.sync.prefs.sync.security.
 pref("services.sync.prefs.sync.security.tls.version.max", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
 pref("services.sync.prefs.sync.spellchecker.dictionary", true);
 pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
 #endif
 
 // Developer edition preferences
 #ifdef MOZ_DEV_EDITION
+pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
 pref("browser.devedition.theme.enabled", true);
-pref("browser.devedition.theme.showCustomizeButton", true);
-#else
-pref("browser.devedition.theme.enabled", false);
-pref("browser.devedition.theme.showCustomizeButton", false);
 #endif
 
 // Developer edition promo preferences
 pref("devtools.devedition.promo.shown", false);
 pref("devtools.devedition.promo.url", "https://www.mozilla.org/firefox/developer/?utm_source=firefox-dev-tools&utm_medium=firefox-browser&utm_content=betadoorhanger");
 
 // Only potentially show in beta release
 #if MOZ_UPDATE_CHANNEL == beta
--- a/browser/base/content/browser-devedition.js
+++ b/browser/base/content/browser-devedition.js
@@ -2,56 +2,47 @@
 # 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/.
 
 /**
  * Listeners for the DevEdition theme.  This adds an extra stylesheet
  * to browser.xul if a pref is set and no other themes are applied.
  */
 let DevEdition = {
-  _prefName: "browser.devedition.theme.enabled",
-  _themePrefName: "general.skins.selectedSkin",
-  _lwThemePrefName: "lightweightThemes.selectedThemeID",
   _devtoolsThemePrefName: "devtools.theme",
-
   styleSheetLocation: "chrome://browser/skin/devedition.css",
   styleSheet: null,
 
-  init: function () {
-    this._updateDevtoolsThemeAttribute();
-    this._updateStyleSheetFromPrefs();
+  get isThemeCurrentlyApplied() {
+    let theme = LightweightThemeManager.currentTheme;
+    return theme && theme.id == "firefox-devedition@mozilla.org";
+  },
 
-    // Listen for changes to all prefs except for complete themes.
-    // No need for this since changing a complete theme requires a
-    // restart.
-    Services.prefs.addObserver(this._lwThemePrefName, this, false);
-    Services.prefs.addObserver(this._prefName, this, false);
+  init: function () {
     Services.prefs.addObserver(this._devtoolsThemePrefName, this, false);
     Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
+    this._updateDevtoolsThemeAttribute();
+
+    if (this.isThemeCurrentlyApplied) {
+      this._toggleStyleSheet(true);
+    }
   },
 
   observe: function (subject, topic, data) {
     if (topic == "lightweight-theme-styling-update") {
       let newTheme = JSON.parse(data);
-      if (!newTheme) {
-        // A lightweight theme has been unapplied, so just re-read prefs.
-        this._updateStyleSheetFromPrefs();
+      if (newTheme && newTheme.id == "firefox-devedition@mozilla.org") {
+        this._toggleStyleSheet(true);
       } else {
-        // A lightweight theme has been applied, but the pref may not be
-        // set yet if this happened from customize menu or addons page.
         this._toggleStyleSheet(false);
       }
     }
 
-    if (topic == "nsPref:changed") {
-      if (data == this._devtoolsThemePrefName) {
-        this._updateDevtoolsThemeAttribute();
-      } else {
-        this._updateStyleSheetFromPrefs();
-      }
+    if (topic == "nsPref:changed" && data == this._devtoolsThemePrefName) {
+      this._updateDevtoolsThemeAttribute();
     }
   },
 
   _inferBrightness: function() {
     ToolbarIconColor.inferFromText();
     // Get an inverted full screen button if the dark theme is applied.
     if (this.styleSheet &&
         document.documentElement.getAttribute("devtoolstheme") == "dark") {
@@ -65,42 +56,23 @@ let DevEdition = {
     // Set an attribute on root element to make it possible
     // to change colors based on the selected devtools theme.
     let devtoolsTheme = Services.prefs.getCharPref(this._devtoolsThemePrefName);
     if (devtoolsTheme != "dark") {
       devtoolsTheme = "light";
     }
     document.documentElement.setAttribute("devtoolstheme", devtoolsTheme);
     this._inferBrightness();
-    this._updateStyleSheetFromPrefs();
-  },
-
-  _updateStyleSheetFromPrefs: function() {
-    let lightweightThemeSelected = false;
-    try {
-      lightweightThemeSelected = !!Services.prefs.getCharPref(this._lwThemePrefName);
-    } catch(e) {}
-
-    let defaultThemeSelected = false;
-    try {
-       defaultThemeSelected = Services.prefs.getCharPref(this._themePrefName) == "classic/1.0";
-    } catch(e) {}
-
-    let deveditionThemeEnabled = Services.prefs.getBoolPref(this._prefName) &&
-      !lightweightThemeSelected && defaultThemeSelected;
-
-    this._toggleStyleSheet(deveditionThemeEnabled);
   },
 
   handleEvent: function(e) {
     if (e.type === "load") {
       this.styleSheet.removeEventListener("load", this);
       gBrowser.tabContainer._positionPinnedTabs();
       this._inferBrightness();
-      Services.obs.notifyObservers(window, "devedition-theme-state-changed", true);
     }
   },
 
   _toggleStyleSheet: function(deveditionThemeEnabled) {
     if (deveditionThemeEnabled && !this.styleSheet) {
       let styleSheetAttr = `href="${this.styleSheetLocation}" type="text/css"`;
       this.styleSheet = document.createProcessingInstruction(
         'xml-stylesheet', styleSheetAttr);
@@ -109,23 +81,20 @@ let DevEdition = {
       // NB: we'll notify observers once the stylesheet has fully loaded, see
       // handleEvent above.
     } else if (!deveditionThemeEnabled && this.styleSheet) {
       this.styleSheet.removeEventListener("load", this);
       this.styleSheet.remove();
       this.styleSheet = null;
       gBrowser.tabContainer._positionPinnedTabs();
       this._inferBrightness();
-      Services.obs.notifyObservers(window, "devedition-theme-state-changed", false);
     }
   },
 
   uninit: function () {
-    Services.prefs.removeObserver(this._lwThemePrefName, this);
-    Services.prefs.removeObserver(this._prefName, this);
     Services.prefs.removeObserver(this._devtoolsThemePrefName, this);
     Services.obs.removeObserver(this, "lightweight-theme-styling-update", false);
     if (this.styleSheet) {
       this.styleSheet.removeEventListener("load", this);
     }
     this.styleSheet = null;
   }
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -40,16 +40,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
                                    "@mozilla.org/browser/favicon-service;1",
                                    "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
+XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
+                                  "resource://gre/modules/LightweightThemeManager.jsm");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
 var gLastBrowserCharset = null;
 var gProxyFavIcon = null;
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
 var gContextMenu = null; // nsContextMenu instance
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e4e8dcaa3b3cd01a1287359902561166d7f942ee
GIT binary patch
literal 95
zc%17D@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?juK#@*VoWXSL2@NQe!&b5
m&u*jvIb5DDjv*Cul9PaJHU?%h^O_Yv7K5j&pUXO@geCw~dlW4I
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..04cfba796dc6aa0bac6b3b368e929009bf01af52
GIT binary patch
literal 2402
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
UJkx%vwEzGB07*qoM6N<$f}8H2SpWb4
--- a/browser/base/content/test/general/browser_devedition.js
+++ b/browser/base/content/test/general/browser_devedition.js
@@ -1,72 +1,65 @@
 /*
  * Testing changes for Developer Edition theme.
  * A special stylesheet should be added to the browser.xul document
  * when browser.devedition.theme.enabled is set to true and no themes
  * are applied.
  */
 
-const PREF_DEVEDITION_THEME = "browser.devedition.theme.enabled";
-const PREF_LWTHEME = "lightweightThemes.selectedThemeID";
 const PREF_LWTHEME_USED_THEMES = "lightweightThemes.usedThemes";
 const PREF_DEVTOOLS_THEME = "devtools.theme";
 const {LightweightThemeManager} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
 
+LightweightThemeManager.clearBuiltInThemes();
+LightweightThemeManager.addBuiltInTheme(dummyLightweightTheme("firefox-devedition@mozilla.org"));
+
 registerCleanupFunction(() => {
   // Set preferences back to their original values
   LightweightThemeManager.currentTheme = null;
-  Services.prefs.clearUserPref(PREF_DEVEDITION_THEME);
-  Services.prefs.clearUserPref(PREF_LWTHEME);
   Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME);
   Services.prefs.clearUserPref(PREF_LWTHEME_USED_THEMES);
+
+  LightweightThemeManager.currentTheme = null;
+  LightweightThemeManager.clearBuiltInThemes();
 });
 
 add_task(function* startTests() {
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
 
-  info ("Setting browser.devedition.theme.enabled to false.");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false);
-  ok (!DevEdition.styleSheet, "There is no devedition style sheet when the pref is false.");
-
-  info ("Setting browser.devedition.theme.enabled to true.");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
-  ok (DevEdition.styleSheet, "There is a devedition stylesheet when no themes are applied and pref is set.");
+  info ("Setting the current theme to null");
+  LightweightThemeManager.currentTheme = null;
+  ok (!DevEdition.styleSheet, "There is no devedition style sheet when no lw theme is applied.");
 
   info ("Adding a lightweight theme.");
   LightweightThemeManager.currentTheme = dummyLightweightTheme("preview0");
   ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed when a lightweight theme is applied.");
 
-  info ("Removing a lightweight theme.");
+  info ("Applying the devedition lightweight theme.");
   let onAttributeAdded = waitForBrightTitlebarAttribute();
-  LightweightThemeManager.currentTheme = null;
-  ok (DevEdition.styleSheet, "The devedition stylesheet has been added when a lightweight theme is removed.");
+  LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org");
+  ok (DevEdition.styleSheet, "The devedition stylesheet has been added when the devedition lightweight theme is applied");
   yield onAttributeAdded;
-
   is (document.documentElement.getAttribute("brighttitlebarforeground"), "true",
      "The brighttitlebarforeground attribute is set on the window.");
 
-  info ("Setting browser.devedition.theme.enabled to false.");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false);
-  ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed.");
+  info ("Unapplying all themes.");
+  LightweightThemeManager.currentTheme = null;
+  ok (!DevEdition.styleSheet, "There is no devedition style sheet when no lw theme is applied.");
 
-  ok (!document.documentElement.hasAttribute("brighttitlebarforeground"),
-     "The brighttitlebarforeground attribute is not set on the window after devedition.theme is false.");
+  info ("Applying the devedition lightweight theme.");
+  onAttributeAdded = waitForBrightTitlebarAttribute();
+  LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org");
+  ok (DevEdition.styleSheet, "The devedition stylesheet has been added when the devedition lightweight theme is applied");
+  yield onAttributeAdded;
+  ok (document.documentElement.hasAttribute("brighttitlebarforeground"),
+     "The brighttitlebarforeground attribute is set on the window with dark devtools theme.");
 });
 
 add_task(function* testDevtoolsTheme() {
-  info ("Checking that Australis is shown when the light devtools theme is applied.");
-
-  let onAttributeAdded = waitForBrightTitlebarAttribute();
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
-  ok (DevEdition.styleSheet, "The devedition stylesheet exists.");
-  yield onAttributeAdded;
-  ok (document.documentElement.hasAttribute("brighttitlebarforeground"),
-     "The brighttitlebarforeground attribute is set on the window with dark devtools theme.");
-
   info ("Checking stylesheet and :root attributes based on devtools theme.");
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
   is (document.documentElement.getAttribute("devtoolstheme"), "light",
     "The documentElement has an attribute based on devtools theme.");
   ok (DevEdition.styleSheet, "The devedition stylesheet is still there with the light devtools theme.");
   ok (!document.documentElement.hasAttribute("brighttitlebarforeground"),
      "The brighttitlebarforeground attribute is not set on the window with light devtools theme.");
 
@@ -84,52 +77,43 @@ add_task(function* testDevtoolsTheme() {
   ok (!document.documentElement.hasAttribute("brighttitlebarforeground"),
      "The brighttitlebarforeground attribute is not set on the window with light devtools theme.");
 });
 
 function dummyLightweightTheme(id) {
   return {
     id: id,
     name: id,
-    headerURL: "resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg",
-    iconURL: "resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg",
+    headerURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.header.png",
+    iconURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.icon.png",
     textcolor: "red",
     accentcolor: "blue"
   };
 }
 
 add_task(function* testLightweightThemePreview() {
-  info ("Turning the pref on, then previewing lightweight themes");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
+  info ("Setting devedition to current and the previewing others");
+  LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org");
   ok (DevEdition.styleSheet, "The devedition stylesheet is enabled.");
   LightweightThemeManager.previewTheme(dummyLightweightTheme("preview0"));
   ok (!DevEdition.styleSheet, "The devedition stylesheet is not enabled after a lightweight theme preview.");
   LightweightThemeManager.resetPreview();
   LightweightThemeManager.previewTheme(dummyLightweightTheme("preview1"));
   ok (!DevEdition.styleSheet, "The devedition stylesheet is not enabled after a second lightweight theme preview.");
   LightweightThemeManager.resetPreview();
   ok (DevEdition.styleSheet, "The devedition stylesheet is enabled again after resetting the preview.");
+  LightweightThemeManager.currentTheme = null;
+  ok (!DevEdition.styleSheet, "The devedition stylesheet is gone after removing the current theme.");
 
-  info ("Turning the pref on, then previewing a theme, turning it off and resetting the preview");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
+  info ("Previewing the devedition theme");
+  LightweightThemeManager.previewTheme(LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org"));
   ok (DevEdition.styleSheet, "The devedition stylesheet is enabled.");
   LightweightThemeManager.previewTheme(dummyLightweightTheme("preview2"));
-  ok (!DevEdition.styleSheet, "The devedition stylesheet is not enabled after a lightweight theme preview.");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false);
-  ok (!DevEdition.styleSheet, "The devedition stylesheet is not enabled after pref is turned off.");
   LightweightThemeManager.resetPreview();
-  ok (!DevEdition.styleSheet, "The devedition stylesheet is still disabled after resetting the preview.");
-
-  info ("Turning the pref on, then previewing the default theme, turning it off and resetting the preview");
-  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
-  ok (DevEdition.styleSheet, "The devedition stylesheet is enabled.");
-  LightweightThemeManager.previewTheme(null);
-  ok (DevEdition.styleSheet, "The devedition stylesheet is still enabled after the default theme is applied.");
-  LightweightThemeManager.resetPreview();
-  ok (DevEdition.styleSheet, "The devedition stylesheet is still enabled after resetting the preview.");
+  ok (!DevEdition.styleSheet, "The devedition stylesheet is now disabled after resetting the preview.");
 });
 
 // Use a mutation observer to wait for the brighttitlebarforeground
 // attribute to change.  Using this instead of waiting for the load
 // event on the DevEdition styleSheet.
 function waitForBrightTitlebarAttribute() {
   return new Promise((resolve, reject) => {
     let mutationObserver = new MutationObserver(function (mutations) {
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -93,16 +93,18 @@ browser.jar:
         content/browser/defaultthemes/4.footer.png    (content/defaultthemes/4.footer.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.footer.png    (content/defaultthemes/5.footer.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/devedition.header.png   (content/defaultthemes/devedition.header.png)
+        content/browser/defaultthemes/devedition.icon.png     (content/defaultthemes/devedition.icon.png)
         content/browser/newtab/newTab.xul             (content/newtab/newTab.xul)
 *       content/browser/newtab/newTab.js              (content/newtab/newTab.js)
         content/browser/newtab/newTab.css             (content/newtab/newTab.css)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
         content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
         content/browser/pageinfo/pageInfo.xml         (content/pageinfo/pageInfo.xml)
         content/browser/pageinfo/feeds.js             (content/pageinfo/feeds.js)
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -32,17 +32,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const kSpecialWidgetPfx = "customizableui-special-";
 
 const kPrefCustomizationState        = "browser.uiCustomization.state";
 const kPrefCustomizationAutoAdd      = "browser.uiCustomization.autoAdd";
 const kPrefCustomizationDebug        = "browser.uiCustomization.debug";
 const kPrefDrawInTitlebar            = "browser.tabs.drawInTitlebar";
-const kPrefDeveditionTheme           = "browser.devedition.theme.enabled";
 const kPrefWebIDEInNavbar            = "devtools.webide.widget.inNavbarByDefault";
 
 /**
  * The keys are the handlers that are fired when the event type (the value)
  * is fired on the subview. A widget that provides a subview has the option
  * of providing onViewShowing and onViewHiding event handlers.
  */
 const kSubviewEvents = [
@@ -2327,25 +2326,23 @@ let CustomizableUIInternal = {
     }
 
     gResetting = false;
   },
 
   _resetUIState: function() {
     try {
       gUIStateBeforeReset.drawInTitlebar = Services.prefs.getBoolPref(kPrefDrawInTitlebar);
-      gUIStateBeforeReset.deveditionTheme = Services.prefs.getBoolPref(kPrefDeveditionTheme);
       gUIStateBeforeReset.uiCustomizationState = Services.prefs.getCharPref(kPrefCustomizationState);
     } catch(e) { }
 
     this._resetExtraToolbars();
 
     Services.prefs.clearUserPref(kPrefCustomizationState);
     Services.prefs.clearUserPref(kPrefDrawInTitlebar);
-    Services.prefs.clearUserPref(kPrefDeveditionTheme);
     LOG("State reset");
 
     // Reset placements to make restoring default placements possible.
     gPlacements = new Map();
     gDirtyAreaCache = new Set();
     gSeenWidgets = new Set();
     // Clear the saved state to ensure that defaults will be used.
     gSavedState = null;
@@ -2397,33 +2394,30 @@ let CustomizableUIInternal = {
     }
   },
 
   /**
    * Undoes a previous reset, restoring the state of the UI to the state prior to the reset.
    */
   undoReset: function() {
     if (gUIStateBeforeReset.uiCustomizationState == null ||
-        gUIStateBeforeReset.drawInTitlebar == null ||
-        gUIStateBeforeReset.deveditionTheme == null) {
+        gUIStateBeforeReset.drawInTitlebar == null) {
       return;
     }
     gUndoResetting = true;
 
     let uiCustomizationState = gUIStateBeforeReset.uiCustomizationState;
     let drawInTitlebar = gUIStateBeforeReset.drawInTitlebar;
-    let deveditionTheme = gUIStateBeforeReset.deveditionTheme;
 
     // Need to clear the previous state before setting the prefs
     // because pref observers may check if there is a previous UI state.
     this._clearPreviousUIState();
 
     Services.prefs.setCharPref(kPrefCustomizationState, uiCustomizationState);
     Services.prefs.setBoolPref(kPrefDrawInTitlebar, drawInTitlebar);
-    Services.prefs.setBoolPref(kPrefDeveditionTheme, deveditionTheme);
     this.loadSavedState();
     // If the user just customizes toolbar/titlebar visibility, gSavedState will be null
     // and we don't need to do anything else here:
     if (gSavedState) {
       for (let areaId of Object.keys(gSavedState.placements)) {
         let placements = gSavedState.placements[areaId];
         gPlacements.set(areaId, placements);
       }
@@ -2591,20 +2585,16 @@ let CustomizableUIInternal = {
         }
       }
     }
 
     if (Services.prefs.prefHasUserValue(kPrefDrawInTitlebar)) {
       LOG(kPrefDrawInTitlebar + " pref is non-default");
       return false;
     }
-    if (Services.prefs.prefHasUserValue(kPrefDeveditionTheme)) {
-      LOG(kPrefDeveditionTheme + " pref is non-default");
-      return false;
-    }
 
     return true;
   },
 
   setToolbarVisibility: function(aToolbarId, aIsVisible) {
     // We only persist the attribute the first time.
     let isFirstChangedToolbar = true;
     for (let window of CustomizableUI.windows) {
@@ -3295,18 +3285,17 @@ this.CustomizableUI = {
   /**
    * Can the last Restore Defaults operation be undone.
    *
    * @return A boolean stating whether an undo of the
    *         Restore Defaults can be performed.
    */
   get canUndoReset() {
     return gUIStateBeforeReset.uiCustomizationState != null ||
-           gUIStateBeforeReset.drawInTitlebar != null ||
-           gUIStateBeforeReset.deveditionTheme != null;
+           gUIStateBeforeReset.drawInTitlebar != null;
   },
 
   /**
    * Get the placement of a widget. This is by far the best way to obtain
    * information about what the state of your widget is. The internals of
    * this call are cheap (no DOM necessary) and you will know where the user
    * has put your widget.
    *
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -12,19 +12,16 @@ const kPrefCustomizationDebug = "browser
 const kPrefCustomizationAnimation = "browser.uiCustomization.disableAnimation";
 const kPaletteId = "customization-palette";
 const kAboutURI = "about:customizing";
 const kDragDataTypePrefix = "text/toolbarwrapper-id/";
 const kPlaceholderClass = "panel-customization-placeholder";
 const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck";
 const kToolbarVisibilityBtn = "customization-toolbar-visibility-button";
 const kDrawInTitlebarPref = "browser.tabs.drawInTitlebar";
-const kDeveditionThemePref = "browser.devedition.theme.enabled";
-const kDeveditionButtonPref = "browser.devedition.theme.showCustomizeButton";
-const kDeveditionChangedNotification = "devedition-theme-state-changed";
 const kMaxTransitionDurationMs = 2000;
 
 const kPanelItemContextMenu = "customizationPanelItemContextMenu";
 const kPaletteItemContextMenu = "customizationPaletteItemContextMenu";
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/CustomizableUI.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -62,27 +59,22 @@ function CustomizeMode(aWindow) {
   // user. Then there's the visible palette, which gets populated and displayed
   // to the user when in customizing mode.
   this.visiblePalette = this.document.getElementById(kPaletteId);
   this.paletteEmptyNotice = this.document.getElementById("customization-empty");
   this.paletteSpacer = this.document.getElementById("customization-spacer");
   this.tipPanel = this.document.getElementById("customization-tipPanel");
   if (Services.prefs.getCharPref("general.skins.selectedSkin") != "classic/1.0") {
     let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
-    let deveditionButton = this.document.getElementById("customization-devedition-theme-button");
     lwthemeButton.setAttribute("hidden", "true");
-    deveditionButton.setAttribute("hidden", "true");
   }
 #ifdef CAN_DRAW_IN_TITLEBAR
   this._updateTitlebarButton();
   Services.prefs.addObserver(kDrawInTitlebarPref, this, false);
 #endif
-  this._updateDevEditionThemeButton();
-  Services.prefs.addObserver(kDeveditionButtonPref, this, false);
-  Services.obs.addObserver(this, kDeveditionChangedNotification, false);
   this.window.addEventListener("unload", this);
 };
 
 CustomizeMode.prototype = {
   _changed: false,
   _transitioning: false,
   window: null,
   document: null,
@@ -108,18 +100,16 @@ CustomizeMode.prototype = {
   get _handler() {
     return this.window.CustomizationHandler;
   },
 
   uninit: function() {
 #ifdef CAN_DRAW_IN_TITLEBAR
     Services.prefs.removeObserver(kDrawInTitlebarPref, this);
 #endif
-    Services.prefs.removeObserver(kDeveditionButtonPref, this);
-    Services.obs.removeObserver(this, kDeveditionChangedNotification);
   },
 
   toggle: function() {
     if (this._handler.isEnteringCustomizeMode || this._handler.isExitingCustomizeMode) {
       this._wantToBeInCustomizeMode = !this._wantToBeInCustomizeMode;
       return;
     }
     if (this._customizing) {
@@ -1502,23 +1492,16 @@ CustomizeMode.prototype = {
           aData = JSON.parse(aData);
           if (!aData) {
             this.removeLWTStyling();
           } else {
             this.updateLWTStyling(aData);
           }
         }
         break;
-      case kDeveditionChangedNotification:
-        if (aSubject == this.window) {
-          this._updateDevEditionThemeButton();
-          this._updateResetButton();
-          this._updateUndoResetButton();
-        }
-        break;
     }
   },
 
 #ifdef CAN_DRAW_IN_TITLEBAR
   _updateTitlebarButton: function() {
     let drawInTitlebar = true;
     try {
       drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref);
@@ -1533,54 +1516,16 @@ CustomizeMode.prototype = {
   },
 
   toggleTitlebar: function(aShouldShowTitlebar) {
     // Drawing in the titlebar means not showing the titlebar, hence the negation:
     Services.prefs.setBoolPref(kDrawInTitlebarPref, !aShouldShowTitlebar);
   },
 #endif
 
-  _updateDevEditionThemeButton: function() {
-    let button = this.document.getElementById("customization-devedition-theme-button");
-
-    let themeEnabled = !!this.window.DevEdition.styleSheet;
-    if (themeEnabled) {
-      button.setAttribute("checked", "true");
-    } else {
-      button.removeAttribute("checked");
-    }
-
-    let buttonVisible = Services.prefs.getBoolPref(kDeveditionButtonPref);
-    if (buttonVisible) {
-      button.removeAttribute("hidden");
-    } else {
-      button.setAttribute("hidden", "true");
-    }
-  },
-
-  toggleDevEditionTheme: function(shouldEnable) {
-    const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
-
-    Services.prefs.setBoolPref(kDeveditionThemePref, shouldEnable);
-
-    let currentLWT = LightweightThemeManager.currentTheme;
-    if (currentLWT && shouldEnable) {
-      this._lastLightweightTheme = currentLWT;
-      AddonManager.getAddonByID(DEFAULT_THEME_ID, function(aDefaultTheme) {
-        // Theoretically, this could race if people are /very/ quick in switching
-        // something else here, so doublecheck:
-        if (Services.prefs.getBoolPref(kDeveditionThemePref)) {
-          aDefaultTheme.userDisabled = false;
-        }
-      });
-    } else if (!currentLWT && !shouldEnable && this._lastLightweightTheme) {
-      LightweightThemeManager.currentTheme = this._lastLightweightTheme;
-    }
-  },
-
   _onDragStart: function(aEvent) {
     __dumpDragData(aEvent);
     let item = aEvent.target;
     while (item && item.localName != "toolbarpaletteitem") {
       if (item.localName == "toolbar") {
         return;
       }
       item = item.parentNode;
--- a/browser/components/customizableui/content/customizeMode.inc.xul
+++ b/browser/components/customizableui/content/customizeMode.inc.xul
@@ -48,23 +48,16 @@
                            label="&customizeMode.lwthemes.menuGetMore;"
                            accesskey="&customizeMode.lwthemes.menuGetMore.accessKey;"
                            tabindex="0"
                            oncommand="gCustomizeMode.getMoreThemes(event);"/>
           </hbox>
         </panel>
       </button>
 
-      <button id="customization-devedition-theme-button"
-              class="customizationmode-button"
-              hidden="true"
-              label="&customizeMode.deveditionTheme.label2;"
-              oncommand="gCustomizeMode.toggleDevEditionTheme(this.hasAttribute('checked'))"
-              type="checkbox" />
-
       <spacer id="customization-footer-spacer"/>
       <button id="customization-undo-reset-button"
               class="customizationmode-button"
               hidden="true"
               oncommand="gCustomizeMode.undoReset();"
               label="&undoCmd.label;"/>
       <button id="customization-reset-button"
               oncommand="gCustomizeMode.reset();"
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -1,19 +1,21 @@
 /* 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/. */
 
 "use strict";
 
 const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
+const {LightweightThemeManager} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
 
 add_task(function () {
   Services.prefs.clearUserPref("lightweightThemes.usedThemes");
   Services.prefs.clearUserPref("lightweightThemes.recommendedThemes");
+  LightweightThemeManager.clearBuiltInThemes();
 
   yield startCustomizing();
 
   let themesButton = document.getElementById("customization-lwtheme-button");
   let popup = document.getElementById("customization-lwtheme-menu");
 
   let popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
--- a/browser/components/customizableui/test/browser_970511_undo_restore_default.js
+++ b/browser/components/customizableui/test/browser_970511_undo_restore_default.js
@@ -96,54 +96,12 @@ add_task(function() {
   is(Services.prefs.getBoolPref(prefName), !defaultValue, "Undo-reset goes back to previous pref value");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden after undo-reset clicked");
 
   Services.prefs.clearUserPref(prefName);
   ok(CustomizableUI.inDefaultState, "In default state after pref cleared");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden at end of test");
 });
 
-// Bug 1082108 - Restore Defaults should clear user pref for devedition theme
-add_task(function() {
-  let prefName = "browser.devedition.theme.enabled";
-  Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
-  let defaultValue = Services.prefs.getBoolPref(prefName);
-  let restoreDefaultsButton = document.getElementById("customization-reset-button");
-  let deveditionThemeButton = document.getElementById("customization-devedition-theme-button");
-  let undoResetButton = document.getElementById("customization-undo-reset-button");
-  ok(CustomizableUI.inDefaultState, "Should be in default state at start of test");
-  ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled when in default state");
-  is(deveditionThemeButton.hasAttribute("checked"), defaultValue, "Devedition theme button should reflect pref value");
-  is(undoResetButton.hidden, true, "Undo reset button should be hidden at start of test");
-  Services.prefs.setBoolPref(prefName, !defaultValue);
-
-  yield waitForCondition(() => !restoreDefaultsButton.disabled);
-  ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled when pref changed");
-  is(deveditionThemeButton.hasAttribute("checked"), !defaultValue, "Devedition theme button should reflect changed pref value");
-  ok(!CustomizableUI.inDefaultState, "With devedition theme flipped, no longer default");
-  is(undoResetButton.hidden, true, "Undo reset button should be hidden after pref change");
-
-  yield gCustomizeMode.reset();
-  ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled after reset");
-  is(deveditionThemeButton.hasAttribute("checked"), defaultValue, "devedition theme button should reflect default value after reset");
-  is(Services.prefs.getBoolPref(prefName), defaultValue, "Reset should reset devedition.theme.enabled");
-  ok(CustomizableUI.inDefaultState, "In default state after devedition theme reset");
-  is(undoResetButton.hidden, false, "Undo reset button should be visible after reset");
-  ok(!undoResetButton.disabled, "Undo reset button should be enabled after reset");
-
-  yield gCustomizeMode.undoReset();
-  ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled after undo-reset");
-  is(deveditionThemeButton.hasAttribute("checked"), !defaultValue, "devedition theme button should reflect undo-reset value");
-  ok(!CustomizableUI.inDefaultState, "No longer in default state after undo");
-  is(Services.prefs.getBoolPref(prefName), !defaultValue, "Undo-reset goes back to previous pref value");
-  is(undoResetButton.hidden, true, "Undo reset button should be hidden after undo-reset clicked");
-
-  //XXXgijs this line should be removed once bug 1094509 lands
-  Services.prefs.clearUserPref("devtools.theme");
-  Services.prefs.clearUserPref(prefName);
-  ok(CustomizableUI.inDefaultState, "In default state after pref cleared");
-  is(undoResetButton.hidden, true, "Undo reset button should be hidden at end of test");
-});
-
 add_task(function asyncCleanup() {
   yield gCustomizeMode.reset();
   yield endCustomizing();
 });
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -146,16 +146,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/WebChannel.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
                                   "resource:///modules/ReaderParent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
                                   "resource://gre/modules/AddonWatcher.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
+                                  "resource://gre/modules/LightweightThemeManager.jsm");
+
 const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
 const PREF_PLUGINS_UPDATEURL  = "plugins.update.url";
 
 // Seconds of idle before trying to create a bookmarks backup.
 const BOOKMARKS_BACKUP_IDLE_TIME_SEC = 8 * 60;
 // Minimum interval between backups.  We try to not create more than one backup
 // per interval.
 const BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS = 1;
@@ -710,16 +713,31 @@ BrowserGlue.prototype = {
     Services.prefs.addObserver(POLARIS_ENABLED, this, false);
 #endif
 
 #ifdef MOZ_DEBUG_UA
     UserAgentOverrides.init();
     DebugUserAgent.init();
 #endif
 
+#ifndef RELEASE_BUILD
+    let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+    let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
+    let themeName = browserBundle.GetStringFromName("deveditionTheme.name");
+    let vendorShortName = brandBundle.GetStringFromName("vendorShortName");
+
+    LightweightThemeManager.addBuiltInTheme({
+      id: "firefox-devedition@mozilla.org",
+      name: themeName,
+      headerURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.header.png",
+      iconURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.icon.png",
+      author: vendorShortName,
+    });
+#endif
+
     Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
 
     AddonWatcher.init(this._notifySlowAddon);
   },
 
   _checkForOldBuildUpdates: function () {
     // check for update if our build is old
     if (Services.prefs.getBoolPref("app.update.enabled") &&
@@ -1638,17 +1656,17 @@ BrowserGlue.prototype = {
     var notifyBox = win.gBrowser.getNotificationBox();
     var notification = notifyBox.appendNotification(text, title, null,
                                                     notifyBox.PRIORITY_CRITICAL_MEDIUM,
                                                     buttons);
     notification.persistence = -1; // Until user closes it
   },
 
   _migrateUI: function BG__migrateUI() {
-    const UI_VERSION = 27;
+    const UI_VERSION = 28;
     const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
     let currentUIVersion = 0;
     try {
       currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
     } catch(ex) {}
     if (currentUIVersion >= UI_VERSION)
       return;
 
@@ -1957,16 +1975,52 @@ BrowserGlue.prototype = {
       // Fix up document color use:
       const kOldColorPref = "browser.display.use_document_colors";
       if (Services.prefs.prefHasUserValue(kOldColorPref) &&
           !Services.prefs.getBoolPref(kOldColorPref)) {
         Services.prefs.setIntPref("browser.display.document_color_use", 2);
       }
     }
 
+    if (currentUIVersion < 28) {
+      // Convert old devedition theme pref to lightweight theme storage
+      let lightweightThemeSelected = false;
+      let selectedThemeID = null;
+      try {
+        lightweightThemeSelected = Services.prefs.prefHasUserValue("lightweightThemes.selectedThemeID");
+        selectedThemeID = Services.prefs.getCharPref("lightweightThemes.selectedThemeID");
+      } catch(e) {}
+
+      let defaultThemeSelected = false;
+      try {
+         defaultThemeSelected = Services.prefs.getCharPref("general.skins.selectedSkin") == "classic/1.0";
+      } catch(e) {}
+
+      let deveditionThemeEnabled = false;
+      try {
+         deveditionThemeEnabled = Services.prefs.getBoolPref("browser.devedition.theme.enabled");
+      } catch(e) {}
+
+      // If we are on the devedition channel, the devedition theme is on by
+      // default.  But we need to handle the case where they didn't want it
+      // applied, and unapply the theme.
+      let userChoseToNotUseDeveditionTheme =
+        !deveditionThemeEnabled ||
+        !defaultThemeSelected ||
+        (lightweightThemeSelected && selectedThemeID != "firefox-devedition@mozilla.org");
+
+      if (userChoseToNotUseDeveditionTheme && selectedThemeID == "firefox-devedition@mozilla.org") {
+        Services.prefs.setCharPref("lightweightThemes.selectedThemeID", "");
+      }
+
+      // Not clearing browser.devedition.theme.enabled, to preserve user's pref
+      // if for some reason this function runs again (even though it shouldn't)
+      Services.prefs.clearUserPref("browser.devedition.showCustomizeButton");
+    }
+
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   // ------------------------------
   // public nsIBrowserGlue members
   // ------------------------------
 
--- a/browser/devtools/framework/test/browser.ini
+++ b/browser/devtools/framework/test/browser.ini
@@ -18,17 +18,16 @@ support-files =
 [browser_target_remote.js]
 [browser_target_support.js]
 [browser_two_tabs.js]
 [browser_toolbox_dynamic_registration.js]
 [browser_toolbox_getpanelwhenready.js]
 [browser_toolbox_highlight.js]
 [browser_toolbox_hosts.js]
 [browser_toolbox_options.js]
-[browser_toolbox_options_devedition.js]
 [browser_toolbox_options_disable_buttons.js]
 [browser_toolbox_options_disable_cache-01.js]
 skip-if = e10s # Bug 1030318
 [browser_toolbox_options_disable_cache-02.js]
 skip-if = e10s # Bug 1030318
 [browser_toolbox_options_disable_js.js]
 skip-if = e10s # Bug 1030318
 # [browser_toolbox_raise.js] # Bug 962258
deleted file mode 100644
--- a/browser/devtools/framework/test/browser_toolbox_options_devedition.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that changing preferences in the options panel updates the prefs
-// and toggles appropriate things in the toolbox.
-
-let doc = null, toolbox = null, panelWin = null;
-
-const PREF_ENABLED = "browser.devedition.theme.enabled";
-const PREF_SHOW = "browser.devedition.theme.showCustomizeButton";
-
-const URL = "data:text/html;charset=utf8,test for toggling dev edition browser theme toggling";
-
-add_task(function*() {
-  // Set preference to false by default so this could
-  // run in Developer Edition which has it on by default.
-  Services.prefs.setBoolPref(PREF_ENABLED, false);
-  Services.prefs.setBoolPref(PREF_SHOW, true);
-
-  let tab = yield addTab(URL);
-  let target = TargetFactory.forTab(tab);
-  toolbox = yield gDevTools.showToolbox(target);
-  let tool = yield toolbox.selectTool("options");
-  panelWin = tool.panelWin;
-
-  let checkbox = tool.panelDoc.getElementById("devtools-browser-theme");
-
-  ise(Services.prefs.getBoolPref(PREF_ENABLED), false, "Dev Theme pref off on start");
-
-  let themeStatus = yield clickAndWaitForThemeChange(checkbox, panelWin);
-  ise(themeStatus, true, "Theme has been toggled on.");
-
-  themeStatus = yield clickAndWaitForThemeChange(checkbox, panelWin);
-  ise(themeStatus, false, "Theme has been toggled off.");
-
-  yield cleanup();
-});
-
-function clickAndWaitForThemeChange (el, win) {
-  let deferred = promise.defer();
-  gDevTools.on("pref-changed", function handler (event, {pref}) {
-    if (pref === PREF_ENABLED) {
-      gDevTools.off("pref-changed", handler);
-      deferred.resolve(Services.prefs.getBoolPref(PREF_ENABLED));
-    }
-  });
-
-  EventUtils.synthesizeMouseAtCenter(el, {}, win);
-
-  return deferred.promise;
-}
-
-function* cleanup() {
-  yield toolbox.destroy();
-  gBrowser.removeCurrentTab();
-  Services.prefs.clearUserPref(PREF_ENABLED);
-  Services.prefs.clearUserPref(PREF_SHOW);
-  toolbox = doc = panelWin = null;
-}
--- a/browser/devtools/framework/toolbox-options.js
+++ b/browser/devtools/framework/toolbox-options.js
@@ -4,19 +4,16 @@
 
 "use strict";
 
 const {Cu, Cc, Ci} = require("chrome");
 const Services = require("Services");
 const promise = require("promise");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CustomizeMode", "resource:///modules/CustomizeMode.jsm");
-const kDeveditionChangedNotification = "devedition-theme-state-changed";
-const DEVEDITION_THEME_PREF = "browser.devedition.theme.enabled";
 
 exports.OptionsPanel = OptionsPanel;
 
 XPCOMUtils.defineLazyGetter(this, "l10n", function() {
   let bundle = Services.strings.createBundle("chrome://browser/locale/devtools/toolbox.properties");
   let l10n = function(aName, ...aArgs) {
     try {
       if (aArgs.length == 0) {
@@ -82,17 +79,16 @@ function OptionsPanel(iframeWindow, tool
   this._themeRegistered = this._themeRegistered.bind(this);
   this._themeUnregistered = this._themeUnregistered.bind(this);
   this._disableJSClicked = this._disableJSClicked.bind(this);
 
   this.disableJSNode = this.panelDoc.getElementById("devtools-disable-javascript");
 
   this._addListeners();
 
-  Services.obs.addObserver(this, kDeveditionChangedNotification, false);
   const EventEmitter = require("devtools/toolkit/event-emitter");
   EventEmitter.decorate(this);
 }
 
 OptionsPanel.prototype = {
 
   get target() {
     return this.toolbox.target;
@@ -107,17 +103,16 @@ OptionsPanel.prototype = {
     } else {
       targetPromise = promise.resolve(this.target);
     }
 
     return targetPromise.then(() => {
       this.setupToolsList();
       this.setupToolbarButtonsList();
       this.setupThemeList();
-      this.setupBrowserThemeButton();
       this.populatePreferences();
       this.updateDefaultTheme();
     }).then(() => {
       this.isReady = true;
       this.emit("ready");
       return this;
     }).then(null, function onError(aReason) {
       Cu.reportError("OptionsPanel open failed. " +
@@ -141,18 +136,16 @@ OptionsPanel.prototype = {
     if (data.pref === "devtools.cache.disabled") {
       let cacheDisabled = data.newValue;
       let cbx = this.panelDoc.getElementById("devtools-disable-cache");
 
       cbx.checked = cacheDisabled;
     }
     else if (data.pref === "devtools.theme") {
       this.updateCurrentTheme();
-    } else if (data.pref === "browser.devedition.theme.enabled") {
-      this.updateBrowserTheme();
     }
   },
 
   _themeRegistered: function(event, themeId) {
     this.setupThemeList();
   },
 
   _themeUnregistered: function(event, theme) {
@@ -278,62 +271,16 @@ OptionsPanel.prototype = {
     let themes = gDevTools.getThemeDefinitionArray();
     for (let theme of themes) {
       themeBox.appendChild(createThemeOption(theme));
     }
 
     this.updateCurrentTheme();
   },
 
-  /**
-   * Similar to `populatePrefs`, except we want more
-   * special rules for the browser theme button.
-   */
-  setupBrowserThemeButton: function() {
-    let checkbox = this.panelDoc.getElementById("devtools-browser-theme");
-
-    checkbox.addEventListener("command", function() {
-      setPrefAndEmit(DEVEDITION_THEME_PREF, this.checked);
-    }.bind(checkbox));
-
-    this.updateBrowserThemeButton();
-  },
-
-  /**
-   * Called on theme changed via observer of "devedition-theme-state-changed".
-   */
-  updateBrowserThemeButton: function() {
-    let checkbox = this.panelDoc.getElementById("devtools-browser-theme");
-
-    // Check if the dev edition style sheet is applied -- will not
-    // be applied when dev edition theme is disabled, or when there's
-    // a LWT applied.
-    if (this._isDevEditionThemeOn()) {
-      checkbox.setAttribute("checked", "true");
-    } else {
-      checkbox.removeAttribute("checked");
-    }
-
-    // Should the button be shown
-    if (GetPref("browser.devedition.theme.showCustomizeButton")) {
-      checkbox.removeAttribute("hidden");
-    } else {
-      checkbox.setAttribute("hidden", "true");
-    }
-  },
-
-  /**
-   * Called when clicking the browser theme button to enable/disable
-   * the dev edition browser theme.
-   */
-  updateBrowserTheme: function() {
-    let enabled = GetPref("browser.devedition.theme.enabled");
-    CustomizeMode.prototype.toggleDevEditionTheme.call(this, enabled);
-  },
-
   populatePreferences: function() {
     let prefCheckboxes = this.panelDoc.querySelectorAll("checkbox[data-pref]");
     for (let checkbox of prefCheckboxes) {
       checkbox.checked = GetPref(checkbox.getAttribute("data-pref"));
       checkbox.addEventListener("command", function() {
         setPrefAndEmit(this.getAttribute("data-pref"), this.checked);
       }.bind(checkbox));
     }
@@ -412,35 +359,16 @@ OptionsPanel.prototype = {
 
     let options = {
       "javascriptEnabled": !checked
     };
 
     this.target.activeTab.reconfigure(options);
   },
 
-  /**
-   * Returns a boolean indicating whether or not the dev edition
-   * browser theme is applied.
-   */
-  _isDevEditionThemeOn: function() {
-    let win = Services.wm.getMostRecentWindow("navigator:browser");
-    return !!(win && win.DevEdition.styleSheet);
-  },
-
-  /**
-   * Called on observer notification for "devedition-theme-state-changed"
-   * to possibly change the state of the dev edition button
-   */
-  observe: function(aSubject, aTopic, aData) {
-    if (aTopic === kDeveditionChangedNotification) {
-      this.updateBrowserThemeButton();
-    }
-  },
-
   destroy: function() {
     if (this.destroyPromise) {
       return this.destroyPromise;
     }
 
     let deferred = promise.defer();
 
     this.destroyPromise = deferred.promise;
@@ -455,18 +383,16 @@ OptionsPanel.prototype = {
       this.target.activeTab.reconfigure(options, () => {
         this.toolbox = null;
         deferred.resolve();
       }, true);
     }
 
     this.panelWin = this.panelDoc = this.disableJSNode = null;
 
-    Services.obs.removeObserver(this, kDeveditionChangedNotification);
-
     return deferred.promise;
   }
 };
 
 /* Set a pref and emit the pref-changed event if needed. */
 function setPrefAndEmit(prefName, newValue) {
   let data = {
     pref: prefName,
--- a/browser/devtools/framework/toolbox-options.xul
+++ b/browser/devtools/framework/toolbox-options.xul
@@ -30,19 +30,16 @@
       <vbox class="options-vertical-pane" flex="1">
         <label>&options.selectDevToolsTheme.label2;</label>
         <vbox id="theme-options" class="options-groupbox">
           <radiogroup id="devtools-theme-box"
                       class="options-groupbox"
                       data-pref="devtools.theme"
                       orient="horizontal">
           </radiogroup>
-          <checkbox id="devtools-browser-theme"
-                    label="&options.usedeveditiontheme.label;"
-                    tooltiptext="&options.usedeveditiontheme.tooltip;"/>
         </vbox>
         <label>&options.commonPrefs.label;</label>
         <vbox id="commonprefs-options" class="options-groupbox">
           <checkbox label="&options.enablePersistentLogs.label;"
                     tooltiptext="&options.enablePersistentLogs.tooltip;"
                     data-pref="devtools.webconsole.persistlog"/>
         </vbox>
         <label>&options.context.inspector;</label>
--- a/browser/devtools/framework/toolbox-process-window.js
+++ b/browser/devtools/framework/toolbox-process-window.js
@@ -47,17 +47,16 @@ let connect = Task.async(function*() {
     }
   });
 });
 
 // Certain options should be toggled since we can assume chrome debugging here
 function setPrefDefaults() {
   Services.prefs.setBoolPref("devtools.inspector.showUserAgentStyles", true);
   Services.prefs.setBoolPref("devtools.performance.ui.show-platform-data", true);
-  Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", false);
   Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
   Services.prefs.setBoolPref("browser.dom.window.dump.enabled", true);
   Services.prefs.setBoolPref("devtools.command-button-frames.enabled", true);
 }
 
 window.addEventListener("load", function() {
   let cmdClose = document.getElementById("toolbox-cmd-close");
   cmdClose.addEventListener("command", onCloseCommand);
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -737,17 +737,16 @@ just addresses the organization to follo
 <!ENTITY customizeMode.titlebar "Title Bar">
 <!ENTITY customizeMode.lwthemes "Themes">
 <!ENTITY customizeMode.lwthemes.myThemes "My Themes">
 <!ENTITY customizeMode.lwthemes.recommended "Recommended">
 <!ENTITY customizeMode.lwthemes.menuManage "Manage">
 <!ENTITY customizeMode.lwthemes.menuManage.accessKey "M">
 <!ENTITY customizeMode.lwthemes.menuGetMore "Get More Themes">
 <!ENTITY customizeMode.lwthemes.menuGetMore.accessKey "G">
-<!ENTITY customizeMode.deveditionTheme.label2 "Use Developer Edition Theme">
 
 <!ENTITY social.chatBar.commandkey "c">
 <!ENTITY social.chatBar.label "Focus chats">
 <!ENTITY social.chatBar.accesskey "c">
 
 <!ENTITY social.markpageMenu.accesskey "P">
 <!ENTITY social.markpageMenu.label "Save Page To…">
 <!ENTITY social.marklinkMenu.accesskey "L">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -84,16 +84,20 @@ addonError-4=#1 could not be installed b
 # #1 is the add-on name, #3 is the application name, #4 is the application version
 addonLocalError-1=This add-on could not be installed because of a filesystem error.
 addonLocalError-2=This add-on could not be installed because it does not match the add-on #3 expected.
 addonLocalError-3=This add-on could not be installed because it appears to be corrupt.
 addonLocalError-4=#1 could not be installed because #3 cannot modify the needed file.
 addonErrorIncompatible=#1 could not be installed because it is not compatible with #3 #4.
 addonErrorBlocklisted=#1 could not be installed because it has a high risk of causing stability or security problems.
 
+# LOCALIZATION NOTE (deveditionTheme.name): This should be nearly the brand name for aurora.
+# See browser/branding/aurora/locales/*/brand.properties
+deveditionTheme.name=Developer Edition
+
 # LOCALIZATION NOTE (lwthemeInstallRequest.message): %S will be replaced with
 # the host name of the site.
 lwthemeInstallRequest.message=This site (%S) attempted to install a theme.
 lwthemeInstallRequest.allowButton=Allow
 lwthemeInstallRequest.allowButton.accesskey=a
 
 lwthemePostInstallNotification.message=A new theme has been installed.
 lwthemePostInstallNotification.undoButton=Undo