Bug 1094821 - Backout 01482cdccd72 for test failures in Aurora simulation;r=me;a=RyanVM FIREFOX_AURORA_39_BASE
authorBrian Grinstead <bgrinstead@mozilla.com>
Mon, 30 Mar 2015 09:20:48 -0700
changeset 236481 1b6bf6612c0f4d4fee81d18bf18016e692f874e1
parent 236480 2d96bfd6fdb9795ecb30ed2509b0735d2bef200c
child 236482 cbcf9a71e87b7c5ac242895f24a2d2cb5fb64b77
push idunknown
push userunknown
push dateunknown
reviewersme, RyanVM
bugs1094821
milestone39.0a1
Bug 1094821 - Backout 01482cdccd72 for test failures in Aurora simulation;r=me;a=RyanVM
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
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1323,18 +1323,21 @@ 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,47 +2,56 @@
 # 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,
 
-  get isThemeCurrentlyApplied() {
-    let theme = LightweightThemeManager.currentTheme;
-    return theme && theme.id == "firefox-devedition@mozilla.org";
-  },
+  init: function () {
+    this._updateDevtoolsThemeAttribute();
+    this._updateStyleSheetFromPrefs();
 
-  init: function () {
+    // 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);
     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 && newTheme.id == "firefox-devedition@mozilla.org") {
-        this._toggleStyleSheet(true);
+      if (!newTheme) {
+        // A lightweight theme has been unapplied, so just re-read prefs.
+        this._updateStyleSheetFromPrefs();
       } 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" && data == this._devtoolsThemePrefName) {
-      this._updateDevtoolsThemeAttribute();
+    if (topic == "nsPref:changed") {
+      if (data == this._devtoolsThemePrefName) {
+        this._updateDevtoolsThemeAttribute();
+      } else {
+        this._updateStyleSheetFromPrefs();
+      }
     }
   },
 
   _inferBrightness: function() {
     ToolbarIconColor.inferFromText();
     // Get an inverted full screen button if the dark theme is applied.
     if (this.styleSheet &&
         document.documentElement.getAttribute("devtoolstheme") == "dark") {
@@ -56,23 +65,42 @@ 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);
@@ -81,20 +109,23 @@ 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,18 +40,16 @@ 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
deleted file mode 100644
index e4e8dcaa3b3cd01a1287359902561166d7f942ee..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 04cfba796dc6aa0bac6b3b368e929009bf01af52..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/base/content/test/general/browser_devedition.js
+++ b/browser/base/content/test/general/browser_devedition.js
@@ -1,65 +1,72 @@
 /*
  * 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 the current theme to null");
-  LightweightThemeManager.currentTheme = null;
-  ok (!DevEdition.styleSheet, "There is no devedition style sheet when no lw theme is applied.");
+  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 ("Adding a lightweight theme.");
   LightweightThemeManager.currentTheme = dummyLightweightTheme("preview0");
   ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed when a lightweight theme is applied.");
 
-  info ("Applying the devedition lightweight theme.");
+  info ("Removing a lightweight theme.");
   let 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");
+  LightweightThemeManager.currentTheme = null;
+  ok (DevEdition.styleSheet, "The devedition stylesheet has been added when a lightweight theme is removed.");
   yield onAttributeAdded;
+
   is (document.documentElement.getAttribute("brighttitlebarforeground"), "true",
      "The brighttitlebarforeground attribute is set on the window.");
 
-  info ("Unapplying all themes.");
-  LightweightThemeManager.currentTheme = null;
-  ok (!DevEdition.styleSheet, "There is no devedition style sheet when no lw theme is applied.");
+  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 ("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");
+  ok (!document.documentElement.hasAttribute("brighttitlebarforeground"),
+     "The brighttitlebarforeground attribute is not set on the window after devedition.theme is false.");
+});
+
+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.");
-});
 
-add_task(function* testDevtoolsTheme() {
   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.");
 
@@ -77,43 +84,52 @@ 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/devedition.header.png",
-    iconURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.icon.png",
+    headerURL: "resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg",
+    iconURL: "resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg",
     textcolor: "red",
     accentcolor: "blue"
   };
 }
 
 add_task(function* testLightweightThemePreview() {
-  info ("Setting devedition to current and the previewing others");
-  LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org");
+  info ("Turning the pref on, then previewing lightweight themes");
+  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
   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 ("Previewing the devedition theme");
-  LightweightThemeManager.previewTheme(LightweightThemeManager.getUsedTheme("firefox-devedition@mozilla.org"));
+  info ("Turning the pref on, then previewing a 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(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 now disabled after resetting the preview.");
+  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.");
 });
 
 // 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,18 +93,16 @@ 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,16 +32,17 @@ 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 = [
@@ -2326,23 +2327,25 @@ 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;
@@ -2394,30 +2397,33 @@ 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.drawInTitlebar == null ||
+        gUIStateBeforeReset.deveditionTheme == 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);
       }
@@ -2585,16 +2591,20 @@ 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) {
@@ -3285,17 +3295,18 @@ 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.drawInTitlebar != null ||
+           gUIStateBeforeReset.deveditionTheme != 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,16 +12,19 @@ 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");
@@ -59,22 +62,27 @@ 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,
@@ -100,16 +108,18 @@ 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) {
@@ -1492,16 +1502,23 @@ 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);
@@ -1516,16 +1533,54 @@ 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,16 +48,23 @@
                            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,21 +1,19 @@
 /* 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,12 +96,54 @@ 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,19 +146,16 @@ 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;
@@ -713,31 +710,16 @@ 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") &&
@@ -1975,52 +1957,16 @@ 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");
-    }
-
     if (currentUIVersion < 29) {
       let group = null;
       try {
         group = Services.prefs.getComplexValue("font.language.group",
                                                Ci.nsIPrefLocalizedString);
       } catch (ex) {}
       if (group &&
           ["tr", "x-baltic", "x-central-euro"].some(g => g == group.data)) {
--- a/browser/devtools/framework/test/browser.ini
+++ b/browser/devtools/framework/test/browser.ini
@@ -21,16 +21,17 @@ 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
new file mode 100644
--- /dev/null
+++ b/browser/devtools/framework/test/browser_toolbox_options_devedition.js
@@ -0,0 +1,59 @@
+/* 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,16 +4,19 @@
 
 "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) {
@@ -79,16 +82,17 @@ 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;
@@ -103,16 +107,17 @@ 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. " +
@@ -136,16 +141,18 @@ 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) {
@@ -271,16 +278,62 @@ 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));
     }
@@ -359,16 +412,35 @@ 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;
@@ -383,16 +455,18 @@ 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,16 +30,19 @@
       <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,16 +47,17 @@ 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.profiler.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,16 +737,17 @@ 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">