Bug 1148996 - 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>
Tue, 31 Mar 2015 20:00:32 -0700
changeset 255788 10160e5098c8c84d0a5506b9633c275a46d655ff
parent 255787 e9e89c1c7e41859d5c18812342e69977fbcbc48b
child 255789 4d9d80b41d62f91f4fdfad5f35831601a2728050
push id8007
push userraliiev@mozilla.com
push dateMon, 11 May 2015 19:23:16 +0000
treeherdermozilla-aurora@e2ce1aac996e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1148996
milestone40.0a1
Bug 1148996 - 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
toolkit/mozapps/extensions/LightweightThemeManager.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1323,21 +1323,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 0000000000000000000000000000000000000000..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 0000000000000000000000000000000000000000..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) {
@@ -1504,23 +1494,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);
@@ -1535,54 +1518,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
@@ -155,16 +155,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;
@@ -719,16 +722,29 @@ BrowserGlue.prototype = {
     Services.prefs.addObserver(POLARIS_ENABLED, this, false);
 #endif
 
 #ifdef MOZ_DEBUG_UA
     UserAgentOverrides.init();
     DebugUserAgent.init();
 #endif
 
+#ifndef RELEASE_BUILD
+    let themeName = gBrowserBundle.GetStringFromName("deveditionTheme.name");
+    let vendorShortName = gBrandBundle.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 +1654,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 = 29;
+    const UI_VERSION = 30;
     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;
 
@@ -1972,16 +1988,52 @@ BrowserGlue.prototype = {
           ["tr", "x-baltic", "x-central-euro"].some(g => g == group.data)) {
         // Latin groups were consolidated.
         group.data = "x-western";
         Services.prefs.setComplexValue("font.language.group",
                                        Ci.nsIPrefLocalizedString, group);
       }
     }
 
+    if (currentUIVersion < 30) {
+      // 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
@@ -21,17 +21,16 @@ support-files =
 [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_hosts_size.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/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -297,17 +297,17 @@ this.LightweightThemeManager = {
           _notifyWindows(this.currentThemeForDisplay);
         }.bind(this));
       }
     }
 
     if (aData)
       _prefs.setCharPref("selectedThemeID", aData.id);
     else
-      _prefs.clearUserPref("selectedThemeID");
+      _prefs.deleteBranch("selectedThemeID");
 
     _notifyWindows(aData);
     Services.obs.notifyObservers(null, "lightweight-theme-changed", null);
   },
 
   /**
    * Starts the Addons provider and enables the new lightweight theme if
    * necessary.