Merge mozilla-central and fx-team
authorEd Morley <emorley@mozilla.com>
Fri, 15 Aug 2014 17:37:16 +0100
changeset 199770 4f430621992c83787aed08ffe8411841bb82d760
parent 199769 e05ba2d89374f1807f805915b86e1e14b0094044 (current diff)
parent 199683 abd2919b124b47afd188ffe709517835811150a6 (diff)
child 199771 54179c9a121a3d23d3dbc5167fa6b1bcbf65ed52
push id8230
push useremorley@mozilla.com
push dateFri, 15 Aug 2014 16:37:34 +0000
treeherderfx-team@4f430621992c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone34.0a1
Merge mozilla-central and fx-team
browser/components/loop/test/mochitest/browser_mozLoop_charPref.js
browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js
browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js
browser/themes/linux/in-content/common.css
browser/themes/osx/in-content/common.css
browser/themes/shared/in-content/check.png
browser/themes/shared/in-content/check@2x.png
browser/themes/shared/in-content/common.inc.css
browser/themes/shared/in-content/dropdown-disabled.png
browser/themes/shared/in-content/dropdown-disabled@2x.png
browser/themes/shared/in-content/dropdown.png
browser/themes/shared/in-content/dropdown@2x.png
browser/themes/shared/in-content/help-glyph.png
browser/themes/shared/in-content/help-glyph@2x.png
browser/themes/shared/in-content/sorter.png
browser/themes/shared/in-content/sorter@2x.png
browser/themes/windows/in-content/common.css
mobile/android/base/home/SuggestClient.java
mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1275,18 +1275,18 @@ pref("devtools.toolbar.enabled", true);
 pref("devtools.toolbar.visible", false);
 pref("devtools.commands.dir", "");
 
 // Enable the app manager
 pref("devtools.appmanager.enabled", true);
 pref("devtools.appmanager.lastTab", "help");
 pref("devtools.appmanager.manifestEditor.enabled", true);
 
-// Disable devtools webide until bug 1007059
-pref("devtools.webide.enabled", false);
+// Enable DevTools WebIDE by default
+pref("devtools.webide.enabled", true);
 
 // Toolbox preferences
 pref("devtools.toolbox.footer.height", 250);
 pref("devtools.toolbox.sidebar.width", 500);
 pref("devtools.toolbox.host", "bottom");
 pref("devtools.toolbox.selectedTool", "webconsole");
 pref("devtools.toolbox.toolbarSpec", '["splitconsole", "paintflashing toggle","tilt toggle","scratchpad","resize toggle","eyedropper","screenshot --fullpage"]');
 pref("devtools.toolbox.sideEnabled", true);
--- a/browser/base/content/aboutneterror/netError.css
+++ b/browser/base/content/aboutneterror/netError.css
@@ -1,13 +1,13 @@
 /* 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/. */
 
-@import url("chrome://browser/skin/in-content/common.css");
+@import url("chrome://global/skin/in-content/common.css");
 
 body {
   display: flex;
   box-sizing: padding-box;
   min-height: 100vh;
   padding: 0 48px;
   align-items: center;
   justify-content: center;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -18,16 +18,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
                                   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
                                   "resource://gre/modules/CharsetMenu.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
                                   "resource://gre/modules/ShortcutUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
                                   "resource://gre/modules/GMPInstallManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
+                                  "resource:///modules/ContentSearch.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
+                                  "resource:///modules/AboutHome.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
 var gLastBrowserCharset = null;
 var gPrevCharset = null;
@@ -3090,18 +3094,27 @@ const BrowserSearch = {
         win = window.openDialog(getBrowserURL(), "_blank",
                                 "chrome,all,dialog=no", "about:blank");
         Services.obs.addObserver(observer, "browser-delayed-startup-finished", false);
       }
       return;
     }
 #endif
     let openSearchPageIfFieldIsNotActive = function(aSearchBar) {
-      if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField)
+      let doc = gBrowser.selectedBrowser.contentDocument;
+      let url = doc.documentURI.toLowerCase();
+      let mm = gBrowser.selectedBrowser.messageManager;
+
+      if (url === "about:home") {
+        AboutHome.focusInput(mm);
+      } else if (url === "about:newtab") {
+        ContentSearch.focusInput(mm);
+      } else if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) {
         openUILinkIn("about:home", "current");
+      }
     };
 
     let searchBar = this.searchBar;
     let placement = CustomizableUI.getPlacementOfWidget("search-container");
     let focusSearchBar = () => {
       searchBar = this.searchBar;
       searchBar.select();
       openSearchPageIfFieldIsNotActive(searchBar);
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -101,16 +101,19 @@ let AboutHomeListener = {
     }
   },
 
   receiveMessage: function(aMessage) {
     switch (aMessage.name) {
       case "AboutHome:Update":
         this.onUpdate(aMessage.data);
         break;
+      case "AboutHome:FocusInput":
+        this.onFocusInput();
+        break;
     }
   },
 
   onUpdate: function(aData) {
     let doc = content.document;
     if (doc.documentURI.toLowerCase() != "about:home")
       return;
 
@@ -133,16 +136,17 @@ let AboutHomeListener = {
     if (doc.documentURI.toLowerCase() != "about:home" ||
         doc.documentElement.hasAttribute("hasBrowserHandlers")) {
       return;
     }
 
     doc.documentElement.setAttribute("hasBrowserHandlers", "true");
     let self = this;
     addMessageListener("AboutHome:Update", self);
+    addMessageListener("AboutHome:FocusInput", self);
     addEventListener("click", this.onClick, true);
     addEventListener("pagehide", function onPageHide(event) {
       if (event.target.defaultView.frameElement)
         return;
       removeMessageListener("AboutHome:Update", self);
       removeEventListener("click", self.onClick, true);
       removeEventListener("pagehide", onPageHide, true);
       if (event.target.documentElement)
@@ -207,16 +211,20 @@ let AboutHomeListener = {
         sendAsyncMessage("AboutHome:Sync");
         break;
 
       case "settings":
         sendAsyncMessage("AboutHome:Settings");
         break;
     }
   },
+
+  onFocusInput: function () {
+    content.document.getElementById("searchText").focus();
+  },
 };
 AboutHomeListener.init(this);
 
 
 // An event listener for custom "WebChannelMessageToChrome" events on pages
 addEventListener("WebChannelMessageToChrome", function (e) {
   // if target is window then we want the document principal, otherwise fallback to target itself.
   let principal = e.target.nodePrincipal ? e.target.nodePrincipal : e.target.document.nodePrincipal;
--- a/browser/base/content/newtab/search.js
+++ b/browser/base/content/newtab/search.js
@@ -71,16 +71,20 @@ let gSearch = {
 
   onCurrentEngine: function (engineName) {
     if (this._initialStateReceived) {
       this._nodes.panel.hidePopup();
       this._setCurrentEngine(engineName);
     }
   },
 
+  onFocusInput: function () {
+    this._nodes.text.focus();
+  },
+
   _nodeIDSuffixes: [
     "form",
     "logo",
     "manage",
     "panel",
     "text",
   ],
 
--- a/browser/base/content/test/general/browser_aboutHome.js
+++ b/browser/base/content/test/general/browser_aboutHome.js
@@ -414,16 +414,32 @@ let gTests = [
 
       // Empty the search input, causing the suggestions to be hidden.
       EventUtils.synthesizeKey("a", { accelKey: true });
       EventUtils.synthesizeKey("VK_DELETE", {});
       ok(table.hidden, "Search suggestion table hidden");
     });
   }
 },
+{
+  desc: "Cmd+k should focus the search bar element",
+  setup: function () {},
+  run: Task.async(function* () {
+    let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
+    let logo = doc.getElementById("brandLogo");
+    let searchInput = doc.getElementById("searchText");
+
+    EventUtils.synthesizeMouseAtCenter(logo, {});
+    isnot(searchInput, doc.activeElement, "Search input should not be the active element.");
+
+    EventUtils.synthesizeKey("k", { accelKey: true });
+    yield promiseWaitForCondition(() => doc.activeElement === searchInput);
+    is(searchInput, doc.activeElement, "Search input should be the active element.");
+  })
+},
 
 ];
 
 function test()
 {
   waitForExplicitFinish();
   requestLongerTimeout(2);
   ignoreAllUncaughtExceptions();
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -77,16 +77,22 @@ function waitForCondition(condition, nex
     if (conditionPassed) {
       moveOn();
     }
     tries++;
   }, 100);
   var moveOn = function() { clearInterval(interval); nextTest(); };
 }
 
+function promiseWaitForCondition(aConditionFn) {
+  let deferred = Promise.defer();
+  waitForCondition(aConditionFn, deferred.resolve, "Condition didn't pass.");
+  return deferred.promise;
+}
+
 function getTestPlugin(aName) {
   var pluginName = aName || "Test Plug-in";
   var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
   var tags = ph.getPluginTags();
 
   // Find the test plugin
   for (var i = 0; i < tags.length; i++) {
     if (tags[i].name == pluginName)
--- a/browser/base/content/test/newtab/browser_newtab_search.js
+++ b/browser/base/content/test/newtab/browser_newtab_search.js
@@ -181,16 +181,26 @@ function runTests() {
   yield undefined;
   yield suggestionsPromise.then(TestRunner.next);
 
   // Empty the search input, causing the suggestions to be hidden.
   EventUtils.synthesizeKey("a", { accelKey: true });
   EventUtils.synthesizeKey("VK_DELETE", {});
   ok(table.hidden, "Search suggestion table hidden");
 
+  // Focus a different element than the search input.
+  let btn = getContentDocument().getElementById("newtab-customize-button");
+  yield promiseClick(btn).then(TestRunner.next);
+
+  isnot(input, getContentDocument().activeElement, "Search input should not be focused");
+  // Test that Ctrl/Cmd + K will focus the input field.
+  EventUtils.synthesizeKey("k", { accelKey: true });
+  yield promiseSearchEvents(["FocusInput"]).then(TestRunner.next);
+  is(input, getContentDocument().activeElement, "Search input should be focused");
+
   // Done.  Revert the current engine and remove the new engines.
   Services.search.currentEngine = oldCurrentEngine;
   yield promiseSearchEvents(["CurrentEngine"]).then(TestRunner.next);
 
   let events = [];
   for (let engine of gNewEngines) {
     Services.search.removeEngine(engine);
     events.push("CurrentState");
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -304,16 +304,18 @@ function openLinkIn(url, where, params) 
       loadInBackground = false;
     }
   }
 
   // Raise the target window before loading the URI, since loading it may
   // result in a new frontmost window (e.g. "javascript:window.open('');").
   w.focus();
 
+  let newTab;
+
   switch (where) {
   case "current":
     let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
 
     if (aAllowThirdPartyFixup) {
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
     }
@@ -327,32 +329,39 @@ function openLinkIn(url, where, params) 
 
     w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData);
     break;
   case "tabshifted":
     loadInBackground = !loadInBackground;
     // fall through
   case "tab":
     let browser = w.gBrowser;
-    browser.loadOneTab(url, {
-                       referrerURI: aReferrerURI,
-                       charset: aCharset,
-                       postData: aPostData,
-                       inBackground: loadInBackground,
-                       allowThirdPartyFixup: aAllowThirdPartyFixup,
-                       relatedToCurrent: aRelatedToCurrent,
-                       skipAnimation: aSkipTabAnimation,
-                       allowMixedContent: aAllowMixedContent });
+    newTab = browser.loadOneTab(url, {
+                                referrerURI: aReferrerURI,
+                                charset: aCharset,
+                                postData: aPostData,
+                                inBackground: loadInBackground,
+                                allowThirdPartyFixup: aAllowThirdPartyFixup,
+                                relatedToCurrent: aRelatedToCurrent,
+                                skipAnimation: aSkipTabAnimation,
+                                allowMixedContent: aAllowMixedContent });
     break;
   }
 
   w.gBrowser.selectedBrowser.focus();
 
-  if (!loadInBackground && w.isBlankPageURL(url))
+  if (!loadInBackground && w.isBlankPageURL(url)) {
+    if (newTab) {
+      // Remote tab content does not focus synchronously, so we set the flag
+      // on this tab to skip focusing the content if we want to focus the URL
+      // bar instead.
+      newTab._urlbarFocused = true;
+    }
     w.focusAndSelectUrlBar();
+  }
 }
 
 // Used as an onclick handler for UI elements with link-like behavior.
 // e.g. onclick="checkForMiddleClick(this, event);"
 function checkForMiddleClick(node, event) {
   // We should be using the disabled property here instead of the attribute,
   // but some elements that this function is used with don't support it (e.g.
   // menuitem).
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -156,16 +156,37 @@ function injectLoopAPI(targetWindow) {
       enumerable: true,
       writable: true,
       value: function(prefName) {
         return MozLoopService.getLoopCharPref(prefName);
       }
     },
 
     /**
+     * Return any preference under "loop." that's coercible to a boolean
+     * preference.
+     *
+     * @param {String} prefName The name of the pref without the preceding
+     * "loop."
+     *
+     * Any errors thrown by the Mozilla pref API are logged to the console
+     * and cause null to be returned. This includes the case of the preference
+     * not being found.
+     *
+     * @return {String} on success, null on error
+     */
+    getLoopBoolPref: {
+      enumerable: true,
+      writable: true,
+      value: function(prefName) {
+        return MozLoopService.getLoopBoolPref(prefName);
+      }
+    },
+
+    /**
      * Starts alerting the user about an incoming call
      */
     startAlerting: {
       enumerable: true,
       writable: true,
       value: function() {
         let chromeWindow = getChromeWindow(targetWindow);
         chromeWindow.getAttention();
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -609,16 +609,39 @@ this.MozLoopService = {
     } catch (ex) {
       console.log("getLoopCharPref had trouble getting " + prefName +
         "; exception: " + ex);
       return null;
     }
   },
 
   /**
+   * Return any preference under "loop." that's coercible to a character
+   * preference.
+   *
+   * @param {String} prefName The name of the pref without the preceding
+   * "loop."
+   *
+   * Any errors thrown by the Mozilla pref API are logged to the console
+   * and cause null to be returned. This includes the case of the preference
+   * not being found.
+   *
+   * @return {String} on success, null on error
+   */
+  getLoopBoolPref: function(prefName) {
+    try {
+      return Services.prefs.getBoolPref("loop." + prefName);
+    } catch (ex) {
+      console.log("getLoopBoolPref had trouble getting " + prefName +
+        "; exception: " + ex);
+      return null;
+    }
+  },
+
+  /**
    * Performs a hawk based request to the loop server.
    *
    * @param {String} path The path to make the request to.
    * @param {String} method The request method, e.g. 'POST', 'GET'.
    * @param {Object} payloadObj An object which is converted to JSON and
    *                            transmitted with the request.
    * @returns {Promise}
    *        Returns a promise that resolves to the response of the API call,
--- a/browser/components/loop/test/mochitest/browser.ini
+++ b/browser/components/loop/test/mochitest/browser.ini
@@ -1,8 +1,8 @@
 [DEFAULT]
 support-files =
     head.js
 
 [browser_mozLoop_appVersionInfo.js]
-[browser_mozLoop_charPref.js]
+[browser_mozLoop_prefs.js]
 [browser_mozLoop_doNotDisturb.js]
 skip-if = buildapp == 'mulet'
rename from browser/components/loop/test/mochitest/browser_mozLoop_charPref.js
rename to browser/components/loop/test/mochitest/browser_mozLoop_prefs.js
--- a/browser/components/loop/test/mochitest/browser_mozLoop_charPref.js
+++ b/browser/components/loop/test/mochitest/browser_mozLoop_prefs.js
@@ -19,8 +19,22 @@ add_task(function* test_mozLoop_charPref
   gMozLoopAPI.setLoopCharPref("test", "foo");
   Assert.equal(Services.prefs.getCharPref("loop.test"), "foo",
                "should set loop pref value correctly");
 
   // Test getLoopCharPref
   Assert.equal(gMozLoopAPI.getLoopCharPref("test"), "foo",
                "should get loop pref value correctly");
 });
+
+add_task(function* test_mozLoop_boolPref() {
+  registerCleanupFunction(function () {
+    Services.prefs.clearUserPref("loop.testBool");
+  });
+
+  Assert.ok(gMozLoopAPI, "mozLoop should exist");
+
+  Services.prefs.setBoolPref("loop.testBool", true);
+
+  // Test getLoopCharPref
+  Assert.equal(gMozLoopAPI.getLoopBoolPref("testBool"), true,
+               "should get loop pref value correctly");
+});
rename from browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js
rename to browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js
--- a/browser/components/loop/test/xpcshell/test_loopservice_get_loop_char_pref.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_loop_prefs.js
@@ -1,47 +1,106 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 /*global XPCOMUtils, Services, Assert */
 
-var fakePrefName = "color";
+var fakeCharPrefName = "color";
+var fakeBoolPrefName = "boolean";
 var fakePrefValue = "green";
 
 function test_getLoopCharPref()
 {
-  Services.prefs.setCharPref("loop." + fakePrefName, fakePrefValue);
+  Services.prefs.setCharPref("loop." + fakeCharPrefName, fakePrefValue);
 
-  var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
+  var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
 
   Assert.equal(returnedPref, fakePrefValue,
     "Should return a char pref under the loop. branch");
-  Services.prefs.clearUserPref("loop." + fakePrefName);
+  Services.prefs.clearUserPref("loop." + fakeCharPrefName);
 }
 
 function test_getLoopCharPref_not_found()
 {
-  var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
+  var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
 
   Assert.equal(returnedPref, null,
     "Should return null if a preference is not found");
 }
 
 function test_getLoopCharPref_non_coercible_type()
 {
-  Services.prefs.setBoolPref("loop." + fakePrefName, false );
+  Services.prefs.setBoolPref("loop." + fakeCharPrefName, false);
 
-  var returnedPref = MozLoopService.getLoopCharPref(fakePrefName);
+  var returnedPref = MozLoopService.getLoopCharPref(fakeCharPrefName);
 
   Assert.equal(returnedPref, null,
     "Should return null if the preference exists & is of a non-coercible type");
 }
 
+function test_setLoopCharPref()
+{
+  Services.prefs.setCharPref("loop." + fakeCharPrefName, "red");
+  MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue);
+
+  var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName);
+
+  Assert.equal(returnedPref, fakePrefValue,
+    "Should set a char pref under the loop. branch");
+  Services.prefs.clearUserPref("loop." + fakeCharPrefName);
+}
+
+function test_setLoopCharPref_new()
+{
+  Services.prefs.clearUserPref("loop." + fakeCharPrefName);
+  MozLoopService.setLoopCharPref(fakeCharPrefName, fakePrefValue);
+
+  var returnedPref = Services.prefs.getCharPref("loop." + fakeCharPrefName);
+
+  Assert.equal(returnedPref, fakePrefValue,
+               "Should set a new char pref under the loop. branch");
+  Services.prefs.clearUserPref("loop." + fakeCharPrefName);
+}
+
+function test_setLoopCharPref_non_coercible_type()
+{
+  MozLoopService.setLoopCharPref(fakeCharPrefName, true);
+
+  ok(true, "Setting non-coercible type should not fail");
+}
+
+
+function test_getLoopBoolPref()
+{
+  Services.prefs.setBoolPref("loop." + fakeBoolPrefName, true);
+
+  var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName);
+
+  Assert.equal(returnedPref, true,
+    "Should return a bool pref under the loop. branch");
+  Services.prefs.clearUserPref("loop." + fakeBoolPrefName);
+}
+
+function test_getLoopBoolPref_not_found()
+{
+  var returnedPref = MozLoopService.getLoopBoolPref(fakeBoolPrefName);
+
+  Assert.equal(returnedPref, null,
+    "Should return null if a preference is not found");
+}
+
 
 function run_test()
 {
   test_getLoopCharPref();
   test_getLoopCharPref_not_found();
   test_getLoopCharPref_non_coercible_type();
+  test_setLoopCharPref();
+  test_setLoopCharPref_new();
+  test_setLoopCharPref_non_coercible_type();
+
+  test_getLoopBoolPref();
+  test_getLoopBoolPref_not_found();
 
   do_register_cleanup(function() {
-    Services.prefs.clearUserPref("loop." + fakePrefName);
+    Services.prefs.clearUserPref("loop." + fakeCharPrefName);
+    Services.prefs.clearUserPref("loop." + fakeBoolPrefName);
   });
 }
deleted file mode 100644
--- a/browser/components/loop/test/xpcshell/test_loopservice_set_loop_char_pref.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-/*global XPCOMUtils, Services, Assert */
-
-var fakePrefName = "color";
-var fakePrefValue = "green";
-
-function test_setLoopCharPref()
-{
-  Services.prefs.setCharPref("loop." + fakePrefName, "red");
-  MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue);
-
-  var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName);
-
-  Assert.equal(returnedPref, fakePrefValue,
-    "Should set a char pref under the loop. branch");
-  Services.prefs.clearUserPref("loop." + fakePrefName);
-}
-
-function test_setLoopCharPref_new()
-{
-  Services.prefs.clearUserPref("loop." + fakePrefName);
-  MozLoopService.setLoopCharPref(fakePrefName, fakePrefValue);
-
-  var returnedPref = Services.prefs.getCharPref("loop." + fakePrefName);
-
-  Assert.equal(returnedPref, fakePrefValue,
-               "Should set a new char pref under the loop. branch");
-  Services.prefs.clearUserPref("loop." + fakePrefName);
-}
-
-function test_setLoopCharPref_non_coercible_type()
-{
-  MozLoopService.setLoopCharPref(fakePrefName, true);
-
-  ok(true, "Setting non-coercible type should not fail");
-}
-
-
-function run_test()
-{
-  test_setLoopCharPref();
-  test_setLoopCharPref_new();
-  test_setLoopCharPref_non_coercible_type();
-
-  do_register_cleanup(function() {
-    Services.prefs.clearUserPref("loop." + fakePrefName);
-  });
-}
--- a/browser/components/loop/test/xpcshell/xpcshell.ini
+++ b/browser/components/loop/test/xpcshell/xpcshell.ini
@@ -1,17 +1,16 @@
 [DEFAULT]
 head = head.js
 tail =
 firefox-appdir = browser
 
 [test_looppush_initialize.js]
 [test_loopservice_dnd.js]
 [test_loopservice_expiry.js]
-[test_loopservice_get_loop_char_pref.js]
-[test_loopservice_set_loop_char_pref.js]
+[test_loopservice_loop_prefs.js]
 [test_loopservice_initialize.js]
 [test_loopservice_locales.js]
 [test_loopservice_registration.js]
 [test_loopservice_token_invalid.js]
 [test_loopservice_token_save.js]
 [test_loopservice_token_send.js]
 [test_loopservice_token_validation.js]
--- a/browser/components/preferences/in-content/preferences.xul
+++ b/browser/components/preferences/in-content/preferences.xul
@@ -3,17 +3,17 @@
    - 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/. -->
 
 <?xml-stylesheet href="chrome://global/skin/global.css"?>
 
 <?xml-stylesheet href="chrome://mozapps/content/preferences/preferences.css"?>
 
 <?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css"?>
-<?xml-stylesheet href="chrome://browser/skin/in-content/common.css"?>
+<?xml-stylesheet href="chrome://global/skin/in-content/common.css"?>
 <?xml-stylesheet
   href="chrome://browser/skin/preferences/in-content/preferences.css"?>
 <?xml-stylesheet
   href="chrome://browser/content/preferences/handlers.css"?>
 <?xml-stylesheet href="chrome://browser/skin/preferences/applications.css"?>
 
 <!DOCTYPE page [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
--- a/browser/components/preferences/in-content/subdialogs.js
+++ b/browser/components/preferences/in-content/subdialogs.js
@@ -6,17 +6,17 @@
 
 let gSubDialog = {
   _closingCallback: null,
   _frame: null,
   _overlay: null,
   _box: null,
   _injectedStyleSheets: ["chrome://mozapps/content/preferences/preferences.css",
                          "chrome://browser/skin/preferences/preferences.css",
-                         "chrome://browser/skin/in-content/common.css",
+                         "chrome://global/skin/in-content/common.css",
                          "chrome://browser/skin/preferences/in-content/preferences.css"],
 
   init: function() {
     this._frame = document.getElementById("dialogFrame");
     this._overlay = document.getElementById("dialogOverlay");
     this._box = document.getElementById("dialogBox");
 
     // Make the close button work.
--- a/browser/devtools/framework/test/browser_dynamic_tool_enabling.js
+++ b/browser/devtools/framework/test/browser_dynamic_tool_enabling.js
@@ -1,16 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Tests that toggling prefs immediately (de)activates the relevant menuitem
 
 let gItemsToTest = {
   "menu_devToolbar": "devtools.toolbar.enabled",
-  "menu_devAppMgr": "devtools.appmanager.enabled",
   "menu_browserToolbox": ["devtools.chrome.enabled", "devtools.debugger.remote-enabled", "devtools.debugger.chrome-enabled"],
   "javascriptConsole": "devtools.errorconsole.enabled",
   "menu_devtools_connect": "devtools.debugger.remote-enabled",
 };
 
 function expectedAttributeValueFromPrefs(prefs) {
   return prefs.every((pref) => Services.prefs.getBoolPref(pref)) ?
          "" : "true";
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -71,16 +71,17 @@ function Toolbox(target, selectedTool, h
   this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this);
   this.destroy = this.destroy.bind(this);
   this.highlighterUtils = getHighlighterUtils(this);
   this._highlighterReady = this._highlighterReady.bind(this);
   this._highlighterHidden = this._highlighterHidden.bind(this);
   this._prefChanged = this._prefChanged.bind(this);
   this._saveSplitConsoleHeight = this._saveSplitConsoleHeight.bind(this);
+  this._onFocus = this._onFocus.bind(this);
 
   this._target.on("close", this.destroy);
 
   if (!hostType) {
     hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
   }
   if (!selectedTool) {
     selectedTool = Services.prefs.getCharPref(this._prefs.LAST_TOOL);
@@ -248,36 +249,39 @@ Toolbox.prototype = {
         gDevTools.on("pref-changed", this._prefChanged);
 
         this._buildDockButtons();
         this._buildOptions();
         this._buildTabs();
         this._applyCacheSettings();
         this._addKeysToWindow();
         this._addReloadKeys();
-        this._addToolSwitchingKeys();
+        this._addHostListeners();
         this._addZoomKeys();
         this._loadInitialZoom();
 
         this.webconsolePanel = this.doc.querySelector("#toolbox-panel-webconsole");
         this.webconsolePanel.height =
           Services.prefs.getIntPref(SPLITCONSOLE_HEIGHT_PREF);
         this.webconsolePanel.addEventListener("resize",
           this._saveSplitConsoleHeight);
 
-        let splitConsolePromise = promise.resolve();
-        if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
-          splitConsolePromise = this.openSplitConsole();
-        }
-
         let buttonsPromise = this._buildButtons();
 
         this._telemetry.toolOpened("toolbox");
 
         this.selectTool(this._defaultToolId).then(panel => {
+
+          // Wait until the original tool is selected so that the split
+          // console input will receive focus.
+          let splitConsolePromise = promise.resolve();
+          if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
+            splitConsolePromise = this.openSplitConsole();
+          }
+
           promise.all([
             splitConsolePromise,
             buttonsPromise
           ]).then(() => {
             this.emit("ready");
             deferred.resolve();
           }, deferred.reject);
         });
@@ -340,25 +344,27 @@ Toolbox.prototype = {
       ["toolbox-force-reload-key2", true]
     ].forEach(([id, force]) => {
       this.doc.getElementById(id).addEventListener("command", (event) => {
         this.reloadTarget(force);
       }, true);
     });
   },
 
-  _addToolSwitchingKeys: function() {
+  _addHostListeners: function() {
     let nextKey = this.doc.getElementById("toolbox-next-tool-key");
     nextKey.addEventListener("command", this.selectNextTool.bind(this), true);
     let prevKey = this.doc.getElementById("toolbox-previous-tool-key");
     prevKey.addEventListener("command", this.selectPreviousTool.bind(this), true);
 
     // Split console uses keypress instead of command so the event can be
     // cancelled with stopPropagation on the keypress, and not preventDefault.
     this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false);
+
+    this.doc.addEventListener("focus", this._onFocus, true);
   },
 
   _saveSplitConsoleHeight: function() {
     Services.prefs.setIntPref(SPLITCONSOLE_HEIGHT_PREF,
       this.webconsolePanel.height);
   },
 
   /**
@@ -971,49 +977,71 @@ Toolbox.prototype = {
     let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
     iframe.focus();
   },
 
   /**
    * Focus split console's input line
    */
   focusConsoleInput: function() {
-    let hud = this.getPanel("webconsole").hud;
-    if (hud && hud.jsterm) {
-      hud.jsterm.inputNode.focus();
+    let consolePanel = this.getPanel("webconsole");
+    if (consolePanel) {
+      consolePanel.focusInput();
     }
   },
 
   /**
+   * If the console is split and we are focusing an element outside
+   * of the console, then store the newly focused element, so that
+   * it can be restored once the split console closes.
+   */
+  _onFocus: function({originalTarget}) {
+    // Ignore any non element nodes, or any elements contained
+    // within the webconsole frame.
+    let webconsoleURL = gDevTools.getToolDefinition("webconsole").url;
+    if (originalTarget.nodeType !== 1 ||
+        originalTarget.baseURI === webconsoleURL) {
+      return;
+    }
+
+    this._lastFocusedElement = originalTarget;
+  },
+
+  /**
    * Opens the split console.
    *
    * @returns {Promise} a promise that resolves once the tool has been
    *          loaded and focused.
    */
   openSplitConsole: function() {
     this._splitConsole = true;
     Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, true);
     this._refreshConsoleDisplay();
     this.emit("split-console");
+
     return this.loadTool("webconsole").then(() => {
       this.focusConsoleInput();
     });
   },
 
   /**
    * Closes the split console.
    *
    * @returns {Promise} a promise that resolves once the tool has been
    *          closed.
    */
   closeSplitConsole: function() {
     this._splitConsole = false;
     Services.prefs.setBoolPref(SPLITCONSOLE_ENABLED_PREF, false);
     this._refreshConsoleDisplay();
     this.emit("split-console");
+
+    if (this._lastFocusedElement) {
+      this._lastFocusedElement.focus();
+    }
     return promise.resolve();
   },
 
   /**
    * Toggles the split state of the webconsole.  If the webconsole panel
    * is already selected then this command is ignored.
    *
    * @returns {Promise} a promise that resolves once the tool has been
@@ -1307,16 +1335,17 @@ Toolbox.prototype = {
   /**
    * Destroy the current host, and remove event listeners from its frame.
    *
    * @return {promise} to be resolved when the host is destroyed.
    */
   destroyHost: function() {
     this.doc.removeEventListener("keypress",
       this._splitConsoleOnKeypress, false);
+    this.doc.removeEventListener("focus", this._onFocus, true);
     return this._host.destroy();
   },
 
   /**
    * Remove all UI elements, detach from target and clear up
    */
   destroy: function() {
     // If several things call destroy then we give them all the same
@@ -1329,16 +1358,17 @@ Toolbox.prototype = {
     this.off("select", this._refreshHostTitle);
     this.off("host-changed", this._refreshHostTitle);
 
     gDevTools.off("tool-registered", this._toolRegistered);
     gDevTools.off("tool-unregistered", this._toolUnregistered);
 
     gDevTools.off("pref-changed", this._prefChanged);
 
+    this._lastFocusedElement = null;
     this._saveSplitConsoleHeight();
     this.webconsolePanel.removeEventListener("resize",
       this._saveSplitConsoleHeight);
     this.closeButton.removeEventListener("command", this.destroy, true);
 
     let outstanding = [];
     for (let [id, panel] of this._toolPanels) {
       try {
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -1609,18 +1609,21 @@ var Scratchpad = {
     };
 
     this.editor = new Editor(config);
     let editorElement = document.querySelector("#scratchpad-editor");
     this.editor.appendTo(editorElement).then(() => {
       var lines = initialText.split("\n");
 
       this.editor.on("change", this._onChanged);
+      let okstring = this.strings.GetStringFromName("selfxss.okstring");
+      let msg = this.strings.formatStringFromName("selfxss.msg", [okstring], 1);
       this._onPaste = WebConsoleUtils.pasteHandlerGen(this.editor.container.contentDocument.body,
-                                                      document.querySelector('#scratchpad-notificationbox'));
+                                                      document.querySelector('#scratchpad-notificationbox'),
+                                                      msg, okstring);
       editorElement.addEventListener("paste", this._onPaste);
       editorElement.addEventListener("drop", this._onPaste);
       this.editor.on("save", () => this.saveFile());
       this.editor.focus();
       this.editor.setCursor({ line: lines.length, ch: lines.pop().length });
 
       if (state)
         this.dirty = !state.saved;
--- a/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js
+++ b/browser/devtools/webaudioeditor/test/browser_wa_inspector-toggle.js
@@ -53,14 +53,14 @@ function spawnTest() {
 
   click(panelWin, findGraphNode(panelWin, nodeIds[1]));
   yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET);
 
   ok(!isVisible($("#web-audio-editor-details-pane-empty")),
     "Empty message hides even when loading node while open.");
   ok(isVisible($("#web-audio-editor-tabs")),
     "Switches to tab view when loading node while open.");
-  is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")",
+  is($("#web-audio-inspector-title").value, "Oscillator",
     "Inspector title updates when loading node while open.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/webaudioeditor/test/browser_wa_inspector.js
+++ b/browser/devtools/webaudioeditor/test/browser_wa_inspector.js
@@ -38,23 +38,23 @@ function spawnTest() {
   ]);
 
   ok(WebAudioInspectorView.isVisible(), "InspectorView shown once node selected.");
   ok(!isVisible($("#web-audio-editor-details-pane-empty")),
     "InspectorView empty message hidden when node selected.");
   ok(isVisible($("#web-audio-editor-tabs")),
     "InspectorView tabs view visible when node selected.");
 
-  is($("#web-audio-inspector-title").value, "OscillatorNode (" + nodeIds[1] + ")",
+  is($("#web-audio-inspector-title").value, "Oscillator",
     "Inspector should have the node title when a node is selected.");
 
   is($("#web-audio-editor-tabs").selectedIndex, 0,
     "default tab selected should be the parameters tab.");
 
   click(panelWin, findGraphNode(panelWin, nodeIds[2]));
   yield once(panelWin, EVENTS.UI_INSPECTOR_NODE_SET);
 
-  is($("#web-audio-inspector-title").value, "GainNode (" + nodeIds[2] + ")",
+  is($("#web-audio-inspector-title").value, "Gain",
     "Inspector title updates when a new node is selected.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/webaudioeditor/webaudioeditor-view.js
+++ b/browser/devtools/webaudioeditor/webaudioeditor-view.js
@@ -151,17 +151,21 @@ let WebAudioGraphView = {
     // Clear out previous SVG information
     this.clearGraph();
 
     let graph = new dagreD3.Digraph();
     let edges = [];
 
     AudioNodes.forEach(node => {
       // Add node to graph
-      graph.addNode(node.id, { label: node.type, id: node.id });
+      graph.addNode(node.id, {
+        type: node.type,                        // Just for storing type data
+        label: node.type.replace(/Node$/, ""),  // Displayed in SVG node
+        id: node.id                             // Identification
+      });
 
       // Add all of the connections from this node to the edge array to be added
       // after all the nodes are added, otherwise edges will attempted to be created
       // for nodes that have not yet been added
       AudioNodeConnections.get(node, new Set()).forEach(dest => edges.push([node, dest]));
     });
 
     edges.forEach(([node, dest]) => graph.addEdge(null, node.id, dest.id, {
@@ -172,17 +176,17 @@ let WebAudioGraphView = {
     let renderer = new dagreD3.Renderer();
 
     // Post-render manipulation of the nodes
     let oldDrawNodes = renderer.drawNodes();
     renderer.drawNodes(function(graph, root) {
       let svgNodes = oldDrawNodes(graph, root);
       svgNodes.attr("class", (n) => {
         let node = graph.node(n);
-        return "audionode type-" + node.label;
+        return "audionode type-" + node.type;
       });
       svgNodes.attr("data-id", (n) => {
         let node = graph.node(n);
         return node.id;
       });
       return svgNodes;
     });
 
@@ -447,17 +451,17 @@ let WebAudioInspectorView = {
     this.toggleInspector({ visible: false, animated: false, delayed: false });
   },
 
   /**
    * Sets the title of the Inspector view
    */
   _setTitle: function () {
     let node = this._currentNode;
-    let title = node.type + " (" + node.id + ")";
+    let title = node.type.replace(/Node$/, "");
     $("#web-audio-inspector-title").setAttribute("value", title);
   },
 
   /**
    * Reconstructs the `Properties` tab in the inspector
    * with the `this._currentNode` as it's source.
    */
   _buildPropertiesView: Task.async(function* () {
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -276,16 +276,17 @@ skip-if = buildapp == 'mulet'
 [browser_webconsole_notifications.js]
 [browser_webconsole_open-links-without-callback.js]
 [browser_webconsole_output_copy_newlines.js]
 [browser_webconsole_output_order.js]
 [browser_webconsole_property_provider.js]
 [browser_webconsole_scratchpad_panel_link.js]
 [browser_webconsole_split.js]
 [browser_webconsole_split_escape_key.js]
+[browser_webconsole_split_focus.js]
 [browser_webconsole_split_persist.js]
 [browser_webconsole_view_source.js]
 [browser_webconsole_reflow.js]
 [browser_webconsole_log_file_filter.js]
 [browser_webconsole_expandable_timestamps.js]
 [browser_webconsole_autocomplete_in_debugger_stackframe.js]
 [browser_webconsole_autocomplete_popup_close_on_tab_switch.js]
 [browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_split_focus.js
@@ -0,0 +1,74 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function test() {
+  info("Test that the split console state is persisted");
+
+  let toolbox;
+  let TEST_URI = "data:text/html;charset=utf-8,<p>Web Console test for splitting</p>";
+
+  Task.spawn(runner).then(finish);
+
+  function* runner() {
+    info("Opening a tab while there is no user setting on split console pref");
+    let {tab} = yield loadTab(TEST_URI);
+    let target = TargetFactory.forTab(tab);
+    toolbox = yield gDevTools.showToolbox(target, "inspector");
+
+    ok(!toolbox.splitConsole, "Split console is hidden by default");
+
+    info ("Focusing the search box before opening the split console");
+    let inspector = toolbox.getPanel("inspector");
+    inspector.searchBox.focus();
+
+    // Use the binding element since inspector.searchBox is a XUL element.
+    let activeElement = getActiveElement(inspector.panelDoc);
+    activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
+    is (activeElement, inspector.searchBox, "Search box is focused");
+
+    yield toolbox.openSplitConsole();
+
+    ok(toolbox.splitConsole, "Split console is now visible");
+
+    // Use the binding element since jsterm.inputNode is a XUL textarea element.
+    let activeElement = getActiveElement(toolbox.doc);
+    activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
+    let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode;
+    is(activeElement, inputNode, "Split console input is focused by default");
+
+    yield toolbox.closeSplitConsole();
+
+    info ("Making sure that the search box is refocused after closing the split console");
+    // Use the binding element since inspector.searchBox is a XUL element.
+    let activeElement = getActiveElement(inspector.panelDoc);
+    activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
+    is (activeElement, inspector.searchBox, "Search box is focused");
+
+    yield toolbox.destroy();
+  }
+
+  function getActiveElement(doc) {
+    let activeElement = doc.activeElement;
+    while (activeElement && activeElement.contentDocument) {
+      activeElement = activeElement.contentDocument.activeElement;
+    }
+    return activeElement;
+  }
+
+  function toggleSplitConsoleWithEscape() {
+    let onceSplitConsole = toolbox.once("split-console");
+    let contentWindow = toolbox.frame.contentWindow;
+    contentWindow.focus();
+    EventUtils.sendKey("ESCAPE", contentWindow);
+    return onceSplitConsole;
+  }
+
+  function finish() {
+    toolbox = TEST_URI = null;
+    Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
+    Services.prefs.clearUserPref("devtools.toolbox.splitconsoleHeight");
+    finishTest();
+  }
+}
--- a/browser/devtools/webconsole/test/browser_webconsole_split_persist.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_split_persist.js
@@ -30,16 +30,22 @@ function test() {
     info("Opening a tab while there is a true user setting on split console pref");
     let {tab} = yield loadTab(TEST_URI);
     let target = TargetFactory.forTab(tab);
     toolbox = yield gDevTools.showToolbox(target, "inspector");
 
     ok(toolbox.splitConsole, "Split console is visible by default.");
     is(getHeightPrefValue(), 200, "Height is set based on panel height after closing");
 
+    // Use the binding element since jsterm.inputNode is a XUL textarea element.
+    let activeElement = getActiveElement(toolbox.doc);
+    activeElement = activeElement.ownerDocument.getBindingParent(activeElement);
+    let inputNode = toolbox.getPanel("webconsole").hud.jsterm.inputNode;
+    is(activeElement, inputNode, "Split console input is focused by default");
+
     toolbox.webconsolePanel.height = 1;
     ok (toolbox.webconsolePanel.clientHeight > 1,
         "The actual height of the console is bound with a min height");
 
     toolbox.webconsolePanel.height = 10000;
     ok (toolbox.webconsolePanel.clientHeight < 10000,
         "The actual height of the console is bound with a max height");
 
@@ -58,16 +64,24 @@ function test() {
     toolbox = yield gDevTools.showToolbox(target, "inspector");
 
     ok(!toolbox.splitConsole, "Split console is hidden by default.");
     ok(!getVisiblePrefValue(), "Visibility pref is false");
 
     yield toolbox.destroy();
   }
 
+  function getActiveElement(doc) {
+    let activeElement = doc.activeElement;
+    while (activeElement && activeElement.contentDocument) {
+      activeElement = activeElement.contentDocument.activeElement;
+    }
+    return activeElement;
+  }
+
   function getVisiblePrefValue() {
     return Services.prefs.getBoolPref("devtools.toolbox.splitconsoleEnabled");
   }
 
   function getHeightPrefValue() {
     return Services.prefs.getIntPref("devtools.toolbox.splitconsoleHeight");
   }
 
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -3132,17 +3132,21 @@ JSTerm.prototype = {
     this.completeNode = doc.querySelector(".jsterm-complete-node");
     this.inputNode = doc.querySelector(".jsterm-input-node");
 
     if (this.hud.owner._browserConsole &&
         !Services.prefs.getBoolPref("devtools.chrome.enabled")) {
       inputContainer.style.display = "none";
     }
     else {
-      this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode, doc.getElementById("webconsole-notificationbox"));
+      let okstring = l10n.getStr("selfxss.okstring");
+      let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
+      this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode,
+                                                      doc.getElementById("webconsole-notificationbox"),
+                                                      msg, okstring);
       this.inputNode.addEventListener("keypress", this._keyPress, false);
       this.inputNode.addEventListener("paste", this._onPaste);
       this.inputNode.addEventListener("drop", this._onPaste);
       this.inputNode.addEventListener("input", this._inputEventHandler, false);
       this.inputNode.addEventListener("keyup", this._inputEventHandler, false);
       this.inputNode.addEventListener("focus", this._focusEventHandler, false);
     }
 
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -98,8 +98,18 @@ scratchpad.label=Scratchpad
 # LOCALIZATION NOTE (scratchpad.panelLabel): this is used as the
 # label for the toolbox panel.
 scratchpad.panelLabel=Scratchpad Panel
 
 # LOCALIZATION NOTE (scratchpad.tooltip):  This string is displayed in the
 # tooltip of the tab when the Scratchpad is displayed inside the developer tools
 # window.
 scratchpad.tooltip=Scratchpad
+
+# LOCALIZATION NOTE (selfxss.msg): the text that is displayed when
+# a new user of the developer tools pastes code into the console
+# %1 is the text of selfxss.okstring
+selfxss.msg=Scam Warning: Take care when pasting things you don't understand. This could allow attackers to steal your identity or take control of your computer. Please type '%S' in the scratchpad below to allow pasting.
+
+# LOCALIZATION NOTE (selfxss.msg): the string to be typed
+# in by a new user of the developer tools when they receive the sefxss.msg prompt.
+# Please avoid using non-keyboard characters here
+selfxss.okstring=allow pasting
--- a/browser/modules/AboutHome.jsm
+++ b/browser/modules/AboutHome.jsm
@@ -246,9 +246,18 @@ let AboutHome = {
       } else {
         let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
         mm.broadcastAsyncMessage("AboutHome:Update", data);
       }
     }).then(null, function onError(x) {
       Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x);
     });
   },
+
+  /**
+   * Focuses the search input in the page with the given message manager.
+   * @param  messageManager
+   *         The MessageManager object of the selected browser.
+   */
+  focusInput: function (messageManager) {
+    messageManager.sendAsyncMessage("AboutHome:FocusInput");
+  }
 };
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -89,16 +89,27 @@ this.ContentSearch = {
 
   init: function () {
     Cc["@mozilla.org/globalmessagemanager;1"].
       getService(Ci.nsIMessageListenerManager).
       addMessageListener(INBOUND_MESSAGE, this);
     Services.obs.addObserver(this, "browser-search-engine-modified", false);
   },
 
+  /**
+   * Focuses the search input in the page with the given message manager.
+   * @param  messageManager
+   *         The MessageManager object of the selected browser.
+   */
+  focusInput: function (messageManager) {
+    messageManager.sendAsyncMessage(OUTBOUND_MESSAGE, {
+      type: "FocusInput"
+    });
+  },
+
   receiveMessage: function (msg) {
     // Add a temporary event handler that exists only while the message is in
     // the event queue.  If the message's source docshell changes browsers in
     // the meantime, then we need to update msg.target.  event.detail will be
     // the docshell's new parent <xul:browser> element.
     msg.handleEvent = event => {
       let browserData = this._suggestionMap.get(msg.target);
       if (browserData) {
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -876,17 +876,16 @@ toolbarbutton[sdk-button="true"][cui-are
   -moz-box-direction: reverse;
 }
 
 #urlbar-icons {
   -moz-box-align: center;
 }
 
 .urlbar-icon {
-  cursor: pointer;
   padding: 0 3px;
 }
 
 #urlbar-search-splitter {
   -moz-appearance: none;
   width: 8px;
   -moz-margin-start: -4px;
 }
@@ -1519,17 +1518,16 @@ richlistitem[type~="action"][actiontype=
   border-top: 1px solid GrayText;
 }
 
 /* Combined go/reload/stop button in location bar */
 
 #urlbar > toolbarbutton {
   -moz-appearance: none;
   padding: 0 2px;
-  cursor: pointer;
   list-style-image: url("chrome://browser/skin/reload-stop-go.png");
 }
 
 #urlbar-reload-button {
   -moz-image-region: rect(0, 14px, 14px, 0);
 }
 
 #urlbar-reload-button:not([disabled]):hover {
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -30,27 +30,16 @@ browser.jar:
   skin/classic/browser/Geolocation-64.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity-icons-generic.png
   skin/classic/browser/identity-icons-https.png
   skin/classic/browser/identity-icons-https-ev.png
   skin/classic/browser/identity-icons-https-mixed-active.png
   skin/classic/browser/identity-icons-https-mixed-display.png
   skin/classic/browser/Info.png
-* skin/classic/browser/in-content/common.css                    (in-content/common.css)
-  skin/classic/browser/in-content/check.png                 (../shared/in-content/check.png)
-  skin/classic/browser/in-content/check@2x.png              (../shared/in-content/check@2x.png)
-  skin/classic/browser/in-content/dropdown.png              (../shared/in-content/dropdown.png)
-  skin/classic/browser/in-content/dropdown@2x.png           (../shared/in-content/dropdown@2x.png)
-  skin/classic/browser/in-content/dropdown-disabled.png     (../shared/in-content/dropdown-disabled.png)
-  skin/classic/browser/in-content/dropdown-disabled@2x.png  (../shared/in-content/dropdown-disabled@2x.png)
-  skin/classic/browser/in-content/help-glyph.png            (../shared/in-content/help-glyph.png)
-  skin/classic/browser/in-content/help-glyph@2x.png         (../shared/in-content/help-glyph@2x.png)
-  skin/classic/browser/in-content/sorter.png                (../shared/in-content/sorter.png)
-  skin/classic/browser/in-content/sorter@2x.png             (../shared/in-content/sorter@2x.png)
   skin/classic/browser/menuPanel.png
   skin/classic/browser/menuPanel-customize.png
   skin/classic/browser/menuPanel-exit.png
   skin/classic/browser/menuPanel-help.png
   skin/classic/browser/menuPanel-small.png
   skin/classic/browser/mixed-content-blocked-16.png
   skin/classic/browser/mixed-content-blocked-64.png
   skin/classic/browser/monitor.png
--- a/browser/themes/linux/searchbar.css
+++ b/browser/themes/linux/searchbar.css
@@ -52,17 +52,16 @@
 /* Search go button */
 .search-go-container {
   -moz-box-align: center;
 }
 
 .search-go-button {
   padding: 1px;
   list-style-image: url(moz-icon://stock/gtk-find?size=menu);
-  cursor: pointer;
 }
 
 menuitem[cmd="cmd_clearhistory"] {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
 }
 
 menuitem[cmd="cmd_clearhistory"][disabled] {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled");
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -38,27 +38,16 @@ browser.jar:
   skin/classic/browser/identity-icons-https@2x.png
   skin/classic/browser/identity-icons-https-ev.png
   skin/classic/browser/identity-icons-https-ev@2x.png
   skin/classic/browser/identity-icons-https-mixed-active.png
   skin/classic/browser/identity-icons-https-mixed-active@2x.png
   skin/classic/browser/identity-icons-https-mixed-display.png
   skin/classic/browser/identity-icons-https-mixed-display@2x.png
   skin/classic/browser/Info.png
-* skin/classic/browser/in-content/common.css                (in-content/common.css)
-  skin/classic/browser/in-content/check.png                 (../shared/in-content/check.png)
-  skin/classic/browser/in-content/check@2x.png              (../shared/in-content/check@2x.png)
-  skin/classic/browser/in-content/dropdown.png              (../shared/in-content/dropdown.png)
-  skin/classic/browser/in-content/dropdown@2x.png           (../shared/in-content/dropdown@2x.png)
-  skin/classic/browser/in-content/dropdown-disabled.png     (../shared/in-content/dropdown-disabled.png)
-  skin/classic/browser/in-content/dropdown-disabled@2x.png  (../shared/in-content/dropdown-disabled@2x.png)
-  skin/classic/browser/in-content/help-glyph.png            (../shared/in-content/help-glyph.png)
-  skin/classic/browser/in-content/help-glyph@2x.png         (../shared/in-content/help-glyph@2x.png)
-  skin/classic/browser/in-content/sorter.png                (../shared/in-content/sorter.png)
-  skin/classic/browser/in-content/sorter@2x.png             (../shared/in-content/sorter@2x.png)
   skin/classic/browser/keyhole-circle.png
   skin/classic/browser/keyhole-circle@2x.png
   skin/classic/browser/KUI-background.png
   skin/classic/browser/subtle-pattern.png
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/notification-16.png
   skin/classic/browser/notification-16@2x.png
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -892,24 +892,24 @@ toolbarbutton[panel-multiview-anchor="tr
   background-repeat: no-repeat;
   background-color: Highlight;
   background-position: left 10px center, 0; /* this doesn't need to be changed for RTL */
 }
 
 toolbarbutton[panel-multiview-anchor="true"] {
   background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted.png),
                     linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
-  background-position: right 5px center;
+  background-position: right calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
   background-repeat: no-repeat, repeat;
 }
 
 toolbarbutton[panel-multiview-anchor="true"]:-moz-locale-dir(rtl) {
   background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png),
                     linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
-  background-position: left 5px center;
+  background-position: left calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
 }
 
 toolbarpaletteitem[place="palette"] > .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
 #bookmarks-menu-button[cui-areatype="menu-panel"] > .toolbarbutton-menubutton-dropmarker {
   display: none;
 }
 
 #search-container[cui-areatype="menu-panel"],
--- a/browser/themes/shared/devtools/webaudioeditor.inc.css
+++ b/browser/themes/shared/devtools/webaudioeditor.inc.css
@@ -94,16 +94,20 @@ text {
 .theme-light g.selected text {
   fill: #f0f1f2; /* Toolbars */
 }
 
 /**
  * Inspector Styles
  */
 
+#web-audio-inspector-title {
+  margin: 6px;
+}
+
 .web-audio-inspector .error {
   background-image: url(alerticon-warning.png);
   background-size: 13px 12px;
   -moz-appearance: none;
   opacity: 0;
   transition: opacity .5s ease-out 0s;
 }
 
--- a/browser/themes/shared/incontentprefs/preferences.css
+++ b/browser/themes/shared/incontentprefs/preferences.css
@@ -162,32 +162,32 @@ prefpane {
   padding: 0 10px;
 }
 
 #typeColumn > .treecol-sortdirection[sortDirection=ascending],
 #actionColumn > .treecol-sortdirection[sortDirection=ascending],
 #typeColumn > .treecol-sortdirection[sortDirection=descending],
 #actionColumn > .treecol-sortdirection[sortDirection=descending] {
   -moz-appearance: none;
-  list-style-image: url("chrome://browser/skin/in-content/sorter.png");
+  list-style-image: url("chrome://global/skin/in-content/sorter.png");
 }
 
 #typeColumn > .treecol-sortdirection[sortDirection=descending],
 #actionColumn > .treecol-sortdirection[sortDirection=descending] {
   transform: scaleY(-1);
 }
 
 @media (min-resolution: 2dppx) {
   #typeColumn > .treecol-sortdirection[sortDirection=ascending],
   #actionColumn > .treecol-sortdirection[sortDirection=ascending],
   #typeColumn > .treecol-sortdirection[sortDirection=descending],
   #actionColumn > .treecol-sortdirection[sortDirection=descending] {
     width: 12px;
     height: 8px;
-    list-style-image: url("chrome://browser/skin/in-content/sorter@2x.png");
+    list-style-image: url("chrome://global/skin/in-content/sorter@2x.png");
   }
 }
 
 #handlersView > richlistitem {
   min-height: 40px !important;
 }
 
 .typeIcon {
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -32,27 +32,16 @@ browser.jar:
         skin/classic/browser/Geolocation-64.png
         skin/classic/browser/Info.png
         skin/classic/browser/identity.png
         skin/classic/browser/identity-icons-generic.png
         skin/classic/browser/identity-icons-https.png
         skin/classic/browser/identity-icons-https-ev.png
         skin/classic/browser/identity-icons-https-mixed-active.png
         skin/classic/browser/identity-icons-https-mixed-display.png
-*       skin/classic/browser/in-content/common.css                  (in-content/common.css)
-        skin/classic/browser/in-content/check.png                   (../shared/in-content/check.png)
-        skin/classic/browser/in-content/check@2x.png                (../shared/in-content/check@2x.png)
-        skin/classic/browser/in-content/dropdown.png                (../shared/in-content/dropdown.png)
-        skin/classic/browser/in-content/dropdown@2x.png             (../shared/in-content/dropdown@2x.png)
-        skin/classic/browser/in-content/dropdown-disabled.png       (../shared/in-content/dropdown-disabled.png)
-        skin/classic/browser/in-content/dropdown-disabled@2x.png    (../shared/in-content/dropdown-disabled@2x.png)
-        skin/classic/browser/in-content/help-glyph.png              (../shared/in-content/help-glyph.png)
-        skin/classic/browser/in-content/help-glyph@2x.png           (../shared/in-content/help-glyph@2x.png)
-        skin/classic/browser/in-content/sorter.png                  (../shared/in-content/sorter.png)
-        skin/classic/browser/in-content/sorter@2x.png               (../shared/in-content/sorter@2x.png)
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/livemark-folder.png
         skin/classic/browser/menu-back.png
         skin/classic/browser/menu-forward.png
         skin/classic/browser/menuPanel.png
         skin/classic/browser/menuPanel-customize.png
         skin/classic/browser/menuPanel-exit.png
@@ -452,27 +441,16 @@ browser.jar:
         skin/classic/aero/browser/Geolocation-64.png
         skin/classic/aero/browser/Info.png                           (Info-aero.png)
         skin/classic/aero/browser/identity.png                       (identity-aero.png)
         skin/classic/aero/browser/identity-icons-generic.png
         skin/classic/aero/browser/identity-icons-https.png
         skin/classic/aero/browser/identity-icons-https-ev.png
         skin/classic/aero/browser/identity-icons-https-mixed-active.png
         skin/classic/aero/browser/identity-icons-https-mixed-display.png
-*       skin/classic/aero/browser/in-content/common.css               (in-content/common.css)
-        skin/classic/aero/browser/in-content/check.png                (../shared/in-content/check.png)
-        skin/classic/aero/browser/in-content/check@2x.png             (../shared/in-content/check@2x.png)
-        skin/classic/aero/browser/in-content/dropdown.png             (../shared/in-content/dropdown.png)
-        skin/classic/aero/browser/in-content/dropdown@2x.png          (../shared/in-content/dropdown@2x.png)
-        skin/classic/aero/browser/in-content/dropdown-disabled.png    (../shared/in-content/dropdown-disabled.png)
-        skin/classic/aero/browser/in-content/dropdown-disabled@2x.png (../shared/in-content/dropdown-disabled@2x.png)
-        skin/classic/aero/browser/in-content/help-glyph.png           (../shared/in-content/help-glyph.png)
-        skin/classic/aero/browser/in-content/help-glyph@2x.png        (../shared/in-content/help-glyph@2x.png)
-        skin/classic/aero/browser/in-content/sorter.png               (../shared/in-content/sorter.png)
-        skin/classic/aero/browser/in-content/sorter@2x.png            (../shared/in-content/sorter@2x.png)
         skin/classic/aero/browser/keyhole-forward-mask.svg
         skin/classic/aero/browser/KUI-background.png
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/menu-back.png                      (menu-back-aero.png)
         skin/classic/aero/browser/menu-forward.png                   (menu-forward-aero.png)
         skin/classic/aero/browser/menuPanel.png
         skin/classic/aero/browser/menuPanel-aero.png
         skin/classic/aero/browser/menuPanel-customize.png
--- a/dom/plugins/base/nsIPluginTag.idl
+++ b/dom/plugins/base/nsIPluginTag.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(0e56f04d-cda4-4a55-ab83-e5e29ddd370e)]
+[scriptable, uuid(231df043-3a32-43c4-aaac-7ad2da81e84f)]
 interface nsIPluginTag : nsISupports
 {
   // enabledState is stored as one of the following as an integer in prefs,
   // so if new states are added, they must not renumber the existing states.
   const unsigned long STATE_DISABLED = 0;
   const unsigned long STATE_CLICKTOPLAY = 1;
   const unsigned long STATE_ENABLED = 2;
 
@@ -20,16 +20,21 @@ interface nsIPluginTag : nsISupports
   readonly attribute AUTF8String version;
   readonly attribute AUTF8String name;
 
   /**
    * true only if this plugin is "hardblocked" and cannot be enabled.
    */
   readonly attribute boolean blocklisted;
 
+  /**
+   * true if the state is non-default and locked, false otherwise.
+   */
+  readonly attribute boolean isEnabledStateLocked;
+
   readonly attribute boolean disabled;
   readonly attribute boolean clicktoplay;
            attribute unsigned long enabledState;
 
   readonly attribute PRTime lastModifiedTime;
 
   void getMimeTypes([optional] out unsigned long aCount,
                     [retval, array, size_is(aCount)] out wstring aResults);
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -11,16 +11,17 @@
 #include "nsPluginsDir.h"
 #include "nsPluginHost.h"
 #include "nsIBlocklistService.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsIPlatformCharset.h"
 #include "nsPluginLogging.h"
 #include "nsNPAPIPlugin.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/unused.h"
 #include <cctype>
 #include "mozilla/dom/EncodingUtils.h"
 
 using mozilla::dom::EncodingUtils;
 using namespace mozilla;
 
 // These legacy flags are used in the plugin registry. The states are now
 // stored in prefs, but we still need to be able to import them.
@@ -335,16 +336,32 @@ nsPluginTag::IsBlocklisted()
 
 NS_IMETHODIMP
 nsPluginTag::GetBlocklisted(bool* aBlocklisted)
 {
   *aBlocklisted = IsBlocklisted();
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsPluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked)
+{
+  *aIsEnabledStateLocked = false;
+  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+
+  if (NS_WARN_IF(!prefs)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(this).get(),
+                                aIsEnabledStateLocked);
+
+  return NS_OK;
+}
+
 bool
 nsPluginTag::IsClicktoplay()
 {
   const PluginState state = GetPluginState();
   return (state == ePluginState_Clicktoplay);
 }
 
 NS_IMETHODIMP
rename from mobile/android/base/home/SuggestClient.java
rename to mobile/android/base/SuggestClient.java
--- a/mobile/android/base/home/SuggestClient.java
+++ b/mobile/android/base/SuggestClient.java
@@ -1,16 +1,18 @@
 /* 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/. */
 
-package org.mozilla.gecko.home;
+package org.mozilla.gecko;
 
+import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.mozglue.RobocopTarget;
+import org.mozilla.gecko.util.HardwareUtils;
 
 import org.json.JSONArray;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.text.TextUtils;
 import android.util.Log;
@@ -23,17 +25,21 @@ import java.net.URL;
 import java.net.URLEncoder;
 import java.util.ArrayList;
 
 /**
  * Use network-based search suggestions.
  */
 public class SuggestClient {
     private static final String LOGTAG = "GeckoSuggestClient";
-    private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
+
+    // This should go through GeckoInterface to get the UA, but the search activity
+    // doesn't use a GeckoView yet. Until it does, get the UA directly.
+    private static final String USER_AGENT = HardwareUtils.isTablet() ?
+        AppConstants.USER_AGENT_FENNEC_TABLET : AppConstants.USER_AGENT_FENNEC_MOBILE;
 
     private final Context mContext;
     private final int mTimeout;
 
     // should contain the string "__searchTerms__", which is replaced with the query
     private final String mSuggestTemplate;
 
     // the maximum number of suggestions to return
@@ -107,17 +113,17 @@ public class SuggestClient {
 
             if (json != null) {
                 /*
                  * Sample result:
                  * ["foo",["food network","foothill college","foot locker",...]]
                  */
                 JSONArray results = new JSONArray(json);
                 JSONArray jsonSuggestions = results.getJSONArray(1);
-                
+
                 int added = 0;
                 for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) {
                     String suggestion = jsonSuggestions.getString(i);
                     if (!suggestion.equalsIgnoreCase(query)) {
                         suggestions.add(suggestion);
                         added++;
                     }
                 }
--- a/mobile/android/base/home/BrowserSearch.java
+++ b/mobile/android/base/home/BrowserSearch.java
@@ -14,16 +14,17 @@ import java.util.Locale;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.SuggestClient;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.URLColumns;
 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
 import org.mozilla.gecko.home.SearchLoader.SearchCursorLoader;
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -297,17 +297,16 @@ gbjar.sources += [
     'home/PinSiteDialog.java',
     'home/ReadingListPanel.java',
     'home/ReadingListRow.java',
     'home/RecentTabsPanel.java',
     'home/SearchEngine.java',
     'home/SearchEngineRow.java',
     'home/SearchLoader.java',
     'home/SimpleCursorLoader.java',
-    'home/SuggestClient.java',
     'home/TabMenuStrip.java',
     'home/TabMenuStripLayout.java',
     'home/TopSitesGridItemView.java',
     'home/TopSitesGridView.java',
     'home/TopSitesPanel.java',
     'home/TopSitesThumbnailView.java',
     'home/TwoLinePageRow.java',
     'InputMethods.java',
@@ -374,16 +373,17 @@ gbjar.sources += [
     'SessionParser.java',
     'SharedPreferencesHelper.java',
     'SiteIdentity.java',
     'SmsManager.java',
     'sqlite/ByteBufferInputStream.java',
     'sqlite/MatrixBlobCursor.java',
     'sqlite/SQLiteBridge.java',
     'sqlite/SQLiteBridgeException.java',
+    'SuggestClient.java',
     'SurfaceBits.java',
     'Tab.java',
     'Tabs.java',
     'tabs/PrivateTabsPanel.java',
     'tabs/RemoteTabsContainerPanel.java',
     'tabs/RemoteTabsList.java',
     'tabs/RemoteTabsPanel.java',
     'tabs/RemoteTabsSetupPanel.java',
--- a/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml
+++ b/mobile/android/base/resources/layout-large-land-v11/tabs_panel.xml
@@ -41,21 +41,20 @@
                                          gecko:tabs="tabs_normal"/>
 
         <org.mozilla.gecko.tabs.PrivateTabsPanel
                 android:id="@+id/private_tabs_panel"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:visibility="gone"/>
 
-        <org.mozilla.gecko.tabs.RemoteTabsPanel
-                android:id="@+id/remote_tabs"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
-                android:visibility="gone"/>
+        <ViewStub android:id="@+id/remote_tabs_panel_stub"
+                  android:layout="@layout/remote_tabs_panel_view"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"/>
 
     </view>
 
     <RelativeLayout android:id="@+id/tabs_panel_footer"
                     android:layout_width="match_parent"
                     android:layout_height="@dimen/browser_toolbar_height">
 
         <view class="org.mozilla.gecko.tabs.TabsPanel$TabsPanelToolbar"
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/remote_tabs_panel_view.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<org.mozilla.gecko.tabs.RemoteTabsPanel xmlns:android="http://schemas.android.com/apk/res/android"
+                                        android:id="@+id/remote_tabs_panel"
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"/>
--- a/mobile/android/base/resources/layout/tabs_panel.xml
+++ b/mobile/android/base/resources/layout/tabs_panel.xml
@@ -40,17 +40,16 @@
                                          gecko:tabs="tabs_normal"/>
 
         <org.mozilla.gecko.tabs.PrivateTabsPanel
                 android:id="@+id/private_tabs_panel"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:visibility="gone"/>
 
-        <org.mozilla.gecko.tabs.RemoteTabsPanel
-                android:id="@+id/remote_tabs"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
-                android:visibility="gone"/>
+        <ViewStub android:id="@+id/remote_tabs_panel_stub"
+                  android:layout="@layout/remote_tabs_panel_view"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"/>
 
     </view>
 
 </merge>
--- a/mobile/android/base/tabs/TabsPanel.java
+++ b/mobile/android/base/tabs/TabsPanel.java
@@ -27,16 +27,17 @@ import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewStub;
 import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 
 public class TabsPanel extends LinearLayout
                        implements GeckoPopupMenu.OnMenuItemClickListener,
@@ -108,43 +109,56 @@ public class TabsPanel extends LinearLay
         LayoutInflater.from(context).inflate(R.layout.tabs_panel, this);
         initialize();
 
         mAppStateListener = new AppStateListener() {
             @Override
             public void onResume() {
                 if (mPanel == mPanelRemote) {
                     // Refresh the remote panel.
-                    mPanelRemote.show();
+                    getRemotePanelView().show();
                 }
             }
 
             @Override
             public void onOrientationChanged() {
                 // Remote panel is already refreshed by chrome refresh.
             }
 
             @Override
             public void onPause() {}
         };
     }
 
+    /**
+     * Initializes views in tabs_panel layout
+     *
+     * @throws IllegalStateException
+     *             mCurrentPanel must have a non-null value
+     */
     private void initialize() {
+        if (mCurrentPanel == null) {
+            throw new IllegalStateException(
+                    "mCurrentPanel cannot be null in order for RemotePanelView to be initialized");
+        }
+
+        if (mCurrentPanel == Panel.REMOTE_TABS) {
+            // Initializes mPanelRemote
+            getRemotePanelView();
+        }
+
         mHeader = (RelativeLayout) findViewById(R.id.tabs_panel_header);
         mTabsContainer = (TabsListContainer) findViewById(R.id.tabs_container);
 
         mPanelNormal = (PanelView) findViewById(R.id.normal_tabs);
         mPanelNormal.setTabsPanel(this);
 
         mPanelPrivate = (PanelView) findViewById(R.id.private_tabs_panel);
         mPanelPrivate.setTabsPanel(this);
 
-        mPanelRemote = (PanelView) findViewById(R.id.remote_tabs);
-        mPanelRemote.setTabsPanel(this);
-
         mFooter = (RelativeLayout) findViewById(R.id.tabs_panel_footer);
 
         mAddTab = (ImageButton) findViewById(R.id.add_tab);
         mAddTab.setOnClickListener(new Button.OnClickListener() {
             @Override
             public void onClick(View v) {
                 TabsPanel.this.addTab();
             }
@@ -411,17 +425,17 @@ public class TabsPanel extends LinearLay
         switch (panelToShow) {
             case NORMAL_TABS:
                 mPanel = mPanelNormal;
                 break;
             case PRIVATE_TABS:
                 mPanel = mPanelPrivate;
                 break;
             case REMOTE_TABS:
-                mPanel = mPanelRemote;
+                mPanel = getRemotePanelView();
                 break;
 
             default:
                 throw new IllegalArgumentException("Unknown panel type " + panelToShow);
         }
         mPanel.show();
 
         if (mCurrentPanel == Panel.REMOTE_TABS) {
@@ -467,16 +481,19 @@ public class TabsPanel extends LinearLay
             mPopupMenu.dismiss();
             dispatchLayoutChange(0, 0);
         }
     }
 
     public void refresh() {
         removeAllViews();
 
+        // The View that mPanelRemote points to is invalidated because the layout is invalidated.
+        // mPanelRemote must be null in order to properly initialize RemotePanelView.
+        mPanelRemote = null;
         LayoutInflater.from(mContext).inflate(R.layout.tabs_panel, this);
         initialize();
 
         if (mVisible)
             show(mCurrentPanel);
     }
 
     public void autoHidePanel() {
@@ -565,9 +582,23 @@ public class TabsPanel extends LinearLay
      */
     public Drawable getIconDrawable(Panel panel) {
         return mTabWidget.getIconDrawable(panel.ordinal());
     }
 
     public void setIconDrawable(Panel panel, int resource) {
         mTabWidget.setIconDrawable(panel.ordinal(), resource);
     }
+
+    /**
+     * Initializes mPanelRemote if necessary and provides getter because you
+     * should probably not access mPanelRemote directly
+     *
+     * @return PanelView
+     */
+    private PanelView getRemotePanelView() {
+        if (mPanelRemote == null) {
+            mPanelRemote = (PanelView) ((ViewStub) findViewById(R.id.remote_tabs_panel_stub)).inflate();
+            mPanelRemote.setTabsPanel(TabsPanel.this);
+        }
+        return mPanelRemote;
+    }
 }
--- a/mobile/android/base/tests/testSearchSuggestions.java
+++ b/mobile/android/base/tests/testSearchSuggestions.java
@@ -1,17 +1,17 @@
 package org.mozilla.gecko.tests;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 
 import org.mozilla.gecko.Actions;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.SuggestClient;
 import org.mozilla.gecko.home.BrowserSearch;
-import org.mozilla.gecko.home.SuggestClient;
 
 import android.app.Activity;
 import android.support.v4.app.Fragment;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
 /**
deleted file mode 100644
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestClient.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/* 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/. */
-
-package org.mozilla.search.autocomplete;
-
-import org.json.JSONArray;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-
-/**
- * Use network-based search suggestions.
- */
-public class SuggestClient {
-    private static final String LOGTAG = "GeckoSuggestClient";
-    private static final String USER_AGENT = "";
-
-    private final Context mContext;
-    private final int mTimeout;
-
-    // should contain the string "__searchTerms__", which is replaced with the query
-    private final String mSuggestTemplate;
-
-    // the maximum number of suggestions to return
-    private final int mMaxResults;
-
-    // used by robocop for testing
-    private boolean mCheckNetwork;
-
-    // used to make suggestions appear instantly after opt-in
-    private String mPrevQuery;
-    private ArrayList<String> mPrevResults;
-
-    public SuggestClient(Context context, String suggestTemplate, int timeout, int maxResults) {
-        mContext = context;
-        mMaxResults = maxResults;
-        mSuggestTemplate = suggestTemplate;
-        mTimeout = timeout;
-        mCheckNetwork = true;
-    }
-
-    /**
-     * Queries for a given search term and returns an ArrayList of suggestions.
-     */
-    public ArrayList<String> query(String query) {
-        if (query.equals(mPrevQuery))
-            return mPrevResults;
-
-        ArrayList<String> suggestions = new ArrayList<String>();
-        if (TextUtils.isEmpty(mSuggestTemplate) || TextUtils.isEmpty(query)) {
-            return suggestions;
-        }
-
-        if (!isNetworkConnected() && mCheckNetwork) {
-            Log.i(LOGTAG, "Not connected to network");
-            return suggestions;
-        }
-
-        try {
-            String encoded = URLEncoder.encode(query, "UTF-8");
-            String suggestUri = mSuggestTemplate.replace("__searchTerms__", encoded);
-
-            URL url = new URL(suggestUri);
-            String json = null;
-            HttpURLConnection urlConnection = null;
-            InputStream in = null;
-            try {
-                urlConnection = (HttpURLConnection) url.openConnection();
-                urlConnection.setConnectTimeout(mTimeout);
-                urlConnection.setRequestProperty("User-Agent", USER_AGENT);
-                in = new BufferedInputStream(urlConnection.getInputStream());
-                json = convertStreamToString(in);
-            } finally {
-                if (urlConnection != null)
-                    urlConnection.disconnect();
-                if (in != null) {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                        Log.e(LOGTAG, "error", e);
-                    }
-                }
-            }
-
-            if (json != null) {
-                /*
-                 * Sample result:
-                 * ["foo",["food network","foothill college","foot locker",...]]
-                 */
-                JSONArray results = new JSONArray(json);
-                JSONArray jsonSuggestions = results.getJSONArray(1);
-
-                int added = 0;
-                for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) {
-                    String suggestion = jsonSuggestions.getString(i);
-                    if (!suggestion.equalsIgnoreCase(query)) {
-                        suggestions.add(suggestion);
-                        added++;
-                    }
-                }
-            } else {
-                Log.e(LOGTAG, "Suggestion query failed");
-            }
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Error", e);
-        }
-
-        mPrevQuery = query;
-        mPrevResults = suggestions;
-        return suggestions;
-    }
-
-    private boolean isNetworkConnected() {
-        NetworkInfo networkInfo = getActiveNetworkInfo();
-        return networkInfo != null && networkInfo.isConnected();
-    }
-
-    private NetworkInfo getActiveNetworkInfo() {
-        ConnectivityManager connectivity = (ConnectivityManager) mContext
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
-        if (connectivity == null)
-            return null;
-        return connectivity.getActiveNetworkInfo();
-    }
-
-    private String convertStreamToString(java.io.InputStream is) {
-        try {
-            return new java.util.Scanner(is).useDelimiter("\\A").next();
-        } catch (java.util.NoSuchElementException e) {
-            return "";
-        }
-    }
-}
--- a/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java
+++ b/mobile/android/search/java/org/mozilla/search/autocomplete/SuggestionsFragment.java
@@ -16,16 +16,17 @@ import android.text.SpannableString;
 import android.text.style.ForegroundColorSpan;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.ListView;
 
+import org.mozilla.gecko.SuggestClient;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.search.AcceptsSearchQuery;
 import org.mozilla.search.AcceptsSearchQuery.SuggestionAnimation;
 import org.mozilla.search.Constants;
 import org.mozilla.search.R;
 import org.mozilla.search.providers.SearchEngine;
 import org.mozilla.search.providers.SearchEngineManager;
--- a/mobile/android/search/search_activity_sources.mozbuild
+++ b/mobile/android/search/search_activity_sources.mozbuild
@@ -3,17 +3,16 @@
 # 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/.
 
 search_activity_sources = [
     'java/org/mozilla/search/AcceptsSearchQuery.java',
     'java/org/mozilla/search/autocomplete/AutoCompleteAdapter.java',
     'java/org/mozilla/search/autocomplete/ClearableEditText.java',
-    'java/org/mozilla/search/autocomplete/SuggestClient.java',
     'java/org/mozilla/search/autocomplete/SuggestionsFragment.java',
     'java/org/mozilla/search/Constants.java',
     'java/org/mozilla/search/MainActivity.java',
     'java/org/mozilla/search/PostSearchFragment.java',
     'java/org/mozilla/search/PreSearchFragment.java',
     'java/org/mozilla/search/providers/BingSearchEngine.java',
     'java/org/mozilla/search/providers/GoogleSearchEngine.java',
     'java/org/mozilla/search/providers/SearchEngine.java',
--- a/toolkit/devtools/webconsole/utils.js
+++ b/toolkit/devtools/webconsole/utils.js
@@ -565,31 +565,29 @@ let WebConsoleUtils = {
   },
   /**
    * The inputNode "paste" event handler generator. Helps prevent self-xss attacks
    *
    * @param nsIDOMElement inputField
    * @param nsIDOMElement notificationBox
    * @returns A function to be added as a handler to 'paste' and 'drop' events on the input field
    */
-  pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox){
+  pasteHandlerGen: function WCU_pasteHandlerGen(inputField, notificationBox, msg, okstring) {
     let handler = function WCU_pasteHandler(aEvent) {
       if (WebConsoleUtils.usageCount >= CONSOLE_ENTRY_THRESHOLD) {
         inputField.removeEventListener("paste", handler);
         inputField.removeEventListener("drop", handler);
         return true;
       }
       if (notificationBox.getNotificationWithValue("selfxss-notification")) {
         aEvent.preventDefault();
         aEvent.stopPropagation();
         return false;
       }
-      let l10n = new WebConsoleUtils.l10n("chrome://browser/locale/devtools/webconsole.properties");
-      let okstring = l10n.getStr("selfxss.okstring");
-      let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
+
 
       let notification = notificationBox.appendNotification(msg,
         "selfxss-notification", null, notificationBox.PRIORITY_WARNING_HIGH, null,
         function(eventType) {
           // Cleanup function if notification is dismissed
           if (eventType == "removed") {
             inputField.removeEventListener("keyup", pasteKeyUpHandler);
           }
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -3101,31 +3101,34 @@ var gDetailView = {
         warning.textContent = gStrings.ext.GetStringFromName("details.notification.openH264Pending");
       } else {
         this.node.removeAttribute("notification");
       }
     }
 
     let menulist = document.getElementById("detail-state-menulist");
     let addonType = AddonManager.addonTypes[this._addon.type];
-    if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE &&
-        (hasPermission(this._addon, "ask_to_activate") ||
-         hasPermission(this._addon, "enable") ||
-         hasPermission(this._addon, "disable"))) {
+    if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) {
       let askItem = document.getElementById("detail-ask-to-activate-menuitem");
       let alwaysItem = document.getElementById("detail-always-activate-menuitem");
       let neverItem = document.getElementById("detail-never-activate-menuitem");
+      let hasActivatePermission =
+        ["ask_to_activate", "enable", "disable"].some(perm => hasPermission(this._addon, perm));
+
       if (this._addon.userDisabled === true) {
         menulist.selectedItem = neverItem;
       } else if (this._addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) {
         menulist.selectedItem = askItem;
       } else {
         menulist.selectedItem = alwaysItem;
       }
+
+      menulist.disabled = !hasActivatePermission;
       menulist.hidden = false;
+      menulist.classList.add('no-auto-hide');
     } else {
       menulist.hidden = true;
     }
 
     this.node.setAttribute("active", this._addon.isActive);
   },
 
   clearLoading: function gDetailView_clearLoading() {
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -1301,36 +1301,36 @@
               this.removeAttribute("notification");
             }
           }
 
           this._preferencesBtn.hidden = (!this.mAddon.optionsURL) ||
                                         this.mAddon.optionsType == AddonManager.OPTIONS_TYPE_INLINE_INFO;
 
           let addonType = AddonManager.addonTypes[this.mAddon.type];
-          if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE &&
-              (this.hasPermission("ask_to_activate") ||
-               this.hasPermission("enable") ||
-               this.hasPermission("disable"))) {
+          if (addonType.flags & AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE) {
             this._enableBtn.disabled = true;
             this._disableBtn.disabled = true;
             this._askToActivateMenuitem.disabled = !this.hasPermission("ask_to_activate");
             this._alwaysActivateMenuitem.disabled = !this.hasPermission("enable");
             this._neverActivateMenuitem.disabled = !this.hasPermission("disable");
             if (this.mAddon.userDisabled === true) {
               this._stateMenulist.selectedItem = this._neverActivateMenuitem;
             } else if (this.mAddon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) {
               this._stateMenulist.selectedItem = this._askToActivateMenuitem;
             } else {
               this._stateMenulist.selectedItem = this._alwaysActivateMenuitem;
             }
-            this._stateMenulist.selectedItem.disabled = false;
-            this._stateMenulist.disabled = false;
+            let hasActivatePermission =
+              ["ask_to_activate", "enable", "disable"].some(perm => this.hasPermission(perm));
+            this._stateMenulist.disabled = !hasActivatePermission;
+            this._stateMenulist.hidden = false;
+            this._stateMenulist.classList.add('no-auto-hide');
           } else {
-            this._stateMenulist.disabled = true;
+            this._stateMenulist.hidden = true;
             if (this.hasPermission("enable")) {
               this._enableBtn.hidden = false;
               let tooltip = gViewController.commands["cmd_enableItem"]
                                            .getTooltip(this.mAddon);
               this._enableBtn.setAttribute("tooltiptext", tooltip);
             } else {
               this._enableBtn.hidden = true;
             }
--- a/toolkit/mozapps/extensions/internal/PluginProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/PluginProvider.jsm
@@ -456,16 +456,19 @@ function PluginWrapper(aId, aName, aDesc
   });
 
   this.__defineGetter__("operationsRequiringRestart", function() {
     return AddonManager.OP_NEEDS_RESTART_NONE;
   });
 
   this.__defineGetter__("permissions", function() {
     let permissions = 0;
+    if (aTags[0].isEnabledStateLocked) {
+      return permissions;
+    }
     if (!this.appDisabled) {
 
       if (this.userDisabled !== true)
         permissions |= AddonManager.PERM_CAN_DISABLE;
 
       let blocklistState = this.blocklistState;
       let isCTPBlocklisted =
         (blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE ||
--- a/toolkit/mozapps/extensions/test/browser/browser-common.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser-common.ini
@@ -39,16 +39,17 @@ skip-if = e10s # Bug ?????? - test times
 [browser_dragdrop.js]
 skip-if = buildapp == 'mulet'
 [browser_experiments.js]
 [browser_list.js]
 [browser_metadataTimeout.js]
 [browser_searching.js]
 [browser_sorting.js]
 [browser_sorting_plugins.js]
+[browser_plugin_enabled_state_locked.js]
 skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank]
 [browser_uninstalling.js]
 skip-if = e10s # Bug ?????? - leaked until shutdown [nsGlobalWindow #1760 about:blank]
 [browser_install.js]
 [browser_recentupdates.js]
 [browser_manualupdates.js]
 [browser_globalwarnings.js]
 [browser_globalinformations.js]
--- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
@@ -195,26 +195,26 @@ function part11() {
   });
 }
 
 function part12(aWindow) {
   gManagerWindow = aWindow;
   let pluginEl = get_addon_element(gManagerWindow, gTestPluginId);
   pluginEl.parentNode.ensureElementIsVisible(pluginEl);
   let menu = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
-  is_element_hidden(menu, "part12: state menu should be hidden");
+  is(menu.disabled, true, "part12: state menu should be disabled");
 
   let details = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
   EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
   wait_for_view_load(gManagerWindow, part13);
 }
 
 function part13() {
   let menu = gManagerWindow.document.getElementById("detail-state-menulist");
-  is_element_hidden(menu, "part13: detail state menu should be hidden");
+  is(menu.disabled, true, "part13: detail state menu should be disabled");
 
   setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
     run_next_test();
   });
 }
 
 function end_test() {
   Services.prefs.clearUserPref("plugins.click_to_play");
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
@@ -0,0 +1,121 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// Tests that state menu is displayed correctly (enabled or disabled) in the add-on manager
+// when the preference is unlocked / locked
+const {classes: Cc, interfaces: Ci} = Components;
+const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
+const gIsOSX = ("nsILocalFileMac" in Ci);
+const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) ||
+  ("@mozilla.org/gio-service;1" in Cc);
+
+let gManagerWindow;
+let gCategoryUtilities;
+let gPluginElement;
+
+function getTestPluginPref() {
+  let prefix = "plugin.state.";
+  if (gIsWindows)
+    return prefix + "nptest";
+  else if (gIsLinux)
+    return prefix + "libnptest";
+  else
+    return prefix + "test";
+}
+
+registerCleanupFunction(() => {
+  Services.prefs.unlockPref(getTestPluginPref());
+  Services.prefs.clearUserPref(getTestPluginPref());
+});
+
+function getPlugins() {
+  let deferred = Promise.defer();
+  AddonManager.getAddonsByTypes(["plugin"], plugins => deferred.resolve(plugins));
+  return deferred.promise;
+}
+
+function getTestPlugin(aPlugins) {
+  let testPluginId;
+
+  for (let plugin of aPlugins) {
+    if (plugin.name == "Test Plug-in") {
+      testPluginId = plugin.id;
+      break;
+    }
+  }
+
+  Assert.ok(testPluginId, "Test Plug-in should exist");
+
+  let pluginElement = get_addon_element(gManagerWindow, testPluginId);
+  pluginElement.parentNode.ensureElementIsVisible(pluginElement);
+
+  return pluginElement;
+}
+
+function checkStateMenu(locked) {
+  Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
+    "Preference lock state should be correct.");
+  let menuList = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "state-menulist");
+
+  is_element_visible(menuList, "State menu should be visible.");
+  Assert.equal(menuList.disabled, locked,
+    "State menu should" + (locked === true ? "" : " not") + " be disabled.");
+}
+
+function checkStateMenuDetail(locked) {
+  Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
+    "Preference should be " + (locked === true ? "" : "un") + "locked.");
+
+  // open details menu
+  let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn");
+  is_element_visible(details, "Details link should be visible.");
+  EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
+
+  let deferred = Promise.defer();
+  wait_for_view_load(gManagerWindow, function() {
+    let menuList = gManagerWindow.document.getElementById("detail-state-menulist");
+    is_element_visible(menuList, "Details state menu should be visible.");
+    Assert.equal(menuList.disabled, locked,
+      "Details state menu enabled state should be correct.");
+    deferred.resolve();
+  });
+  return deferred.promise;
+}
+
+add_task(function* initializeState() {
+  Services.prefs.setIntPref(getTestPluginPref(), Ci.nsIPluginTag.STATE_ENABLED);
+  Services.prefs.unlockPref(getTestPluginPref());
+  gManagerWindow = yield open_manager();
+  gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+  yield gCategoryUtilities.openType("plugin");
+
+  let plugins = yield getPlugins();
+  gPluginElement = getTestPlugin(plugins);
+});
+
+// Tests that plugin state menu is enabled if the preference is unlocked
+add_task(function* taskCheckStateMenuIsEnabled() {
+  checkStateMenu(false);
+  yield checkStateMenuDetail(false);
+});
+
+// Lock the preference and then reload the plugin category
+add_task(function* reinitializeState() {
+  // lock the preference
+  Services.prefs.lockPref(getTestPluginPref());
+  yield gCategoryUtilities.openType("plugin");
+  // Retrieve the test plugin element
+  let plugins = yield getPlugins();
+  gPluginElement = getTestPlugin(plugins);
+});
+
+// Tests that plugin state menu is disabled if the preference is locked
+add_task(function* taskCheckStateMenuIsDisabled() {
+  checkStateMenu(true);
+  yield checkStateMenuDetail(true);
+});
+
+add_task(function* testCleanup() {
+  yield close_manager(gManagerWindow);
+});
rename from browser/themes/linux/in-content/common.css
rename to toolkit/themes/linux/global/in-content/common.css
--- a/browser/themes/linux/in-content/common.css
+++ b/toolkit/themes/linux/global/in-content/common.css
@@ -1,13 +1,13 @@
 /* - 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/. */
 
-%include ../../shared/in-content/common.inc.css
+%include ../../../shared/in-content/common.inc.css
 
 xul|tab[selected] {
   /* Override styles for tab[selected] from
      toolkit/themes/linux/global/tabbox.css */
   margin-bottom: 0;
   border-bottom-left-radius: 0;
   border-bottom-right-radius: 0;
 }
--- a/toolkit/themes/linux/global/jar.mn
+++ b/toolkit/themes/linux/global/jar.mn
@@ -49,9 +49,20 @@ toolkit.jar:
 +  skin/classic/global/icons/panelarrow-horizontal.svg         (icons/panelarrow-horizontal.svg)
 +  skin/classic/global/icons/panelarrow-vertical.svg           (icons/panelarrow-vertical.svg)
 +  skin/classic/global/icons/resizer.png                       (icons/resizer.png)
 +  skin/classic/global/icons/sslWarning.png                    (icons/sslWarning.png)
 +  skin/classic/global/icons/wrap.png                          (icons/wrap.png)
 +  skin/classic/global/icons/webapps-16.png                    (icons/webapps-16.png)
 +  skin/classic/global/icons/webapps-64.png                    (icons/webapps-64.png)
    skin/classic/global/menu/shared-menu-check.png              (../../shared/menu-check.png)
+*  skin/classic/global/in-content/common.css                   (in-content/common.css)
+   skin/classic/global/in-content/check.png                    (../../shared/in-content/check.png)
+   skin/classic/global/in-content/check@2x.png                 (../../shared/in-content/check@2x.png)
+   skin/classic/global/in-content/dropdown.png                 (../../shared/in-content/dropdown.png)
+   skin/classic/global/in-content/dropdown@2x.png              (../../shared/in-content/dropdown@2x.png)
+   skin/classic/global/in-content/dropdown-disabled.png        (../../shared/in-content/dropdown-disabled.png)
+   skin/classic/global/in-content/dropdown-disabled@2x.png     (../../shared/in-content/dropdown-disabled@2x.png)
+   skin/classic/global/in-content/help-glyph.png               (../../shared/in-content/help-glyph.png)
+   skin/classic/global/in-content/help-glyph@2x.png            (../../shared/in-content/help-glyph@2x.png)
+   skin/classic/global/in-content/sorter.png                   (../../shared/in-content/sorter.png)
+   skin/classic/global/in-content/sorter@2x.png                (../../shared/in-content/sorter@2x.png)
 +  skin/classic/global/toolbar/spring.png                      (toolbar/spring.png)
--- a/toolkit/themes/linux/mozapps/extensions/extensions.css
+++ b/toolkit/themes/linux/mozapps/extensions/extensions.css
@@ -879,16 +879,20 @@ setting[type="radio"] > radiogroup {
 
 
 /*** buttons ***/
 
 .addon-control[disabled="true"] {
   display: none;
 }
 
+.addon-control.no-auto-hide {
+  display: block;
+}
+
 .addon-control.enable {
   list-style-image: url("moz-icon://stock/gtk-yes?size=button");
 }
 
 .addon-control.disable {
   list-style-image: url("moz-icon://stock/gtk-no?size=button");
 }
 
rename from browser/themes/osx/in-content/common.css
rename to toolkit/themes/osx/global/in-content/common.css
--- a/browser/themes/osx/in-content/common.css
+++ b/toolkit/themes/osx/global/in-content/common.css
@@ -1,13 +1,13 @@
 /* - 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/. */
 
-%include ../../shared/in-content/common.inc.css
+%include ../../../shared/in-content/common.inc.css
 
 xul|tabs {
   padding-right: 0;
   padding-left: 0;
 }
 
 xul|tab[selected] {
   text-shadow: none;
--- a/toolkit/themes/osx/global/jar.mn
+++ b/toolkit/themes/osx/global/jar.mn
@@ -179,16 +179,27 @@ toolkit.jar:
   skin/classic/global/media/volume-full.png                          (media/volume-full.png)
   skin/classic/global/media/volume-full@2x.png                       (media/volume-full@2x.png)
   skin/classic/global/media/clicktoplay-bgtexture.png                (media/clicktoplay-bgtexture.png)
   skin/classic/global/media/videoClickToPlayButton.svg               (media/videoClickToPlayButton.svg)
   skin/classic/global/menu/menu-arrow.png                            (menu/menu-arrow.png)
   skin/classic/global/menu/menu-arrow@2x.png                         (menu/menu-arrow@2x.png)
   skin/classic/global/menu/shared-menu-check.png                     (../../shared/menu-check.png)
   skin/classic/global/menu/shared-menu-check@2x.png                  (../../shared/menu-check@2x.png)
+* skin/classic/global/in-content/common.css                          (in-content/common.css)
+  skin/classic/global/in-content/check.png                           (../../shared/in-content/check.png)
+  skin/classic/global/in-content/check@2x.png                        (../../shared/in-content/check@2x.png)
+  skin/classic/global/in-content/dropdown.png                        (../../shared/in-content/dropdown.png)
+  skin/classic/global/in-content/dropdown@2x.png                     (../../shared/in-content/dropdown@2x.png)
+  skin/classic/global/in-content/dropdown-disabled.png               (../../shared/in-content/dropdown-disabled.png)
+  skin/classic/global/in-content/dropdown-disabled@2x.png            (../../shared/in-content/dropdown-disabled@2x.png)
+  skin/classic/global/in-content/help-glyph.png                      (../../shared/in-content/help-glyph.png)
+  skin/classic/global/in-content/help-glyph@2x.png                   (../../shared/in-content/help-glyph@2x.png)
+  skin/classic/global/in-content/sorter.png                          (../../shared/in-content/sorter.png)
+  skin/classic/global/in-content/sorter@2x.png                       (../../shared/in-content/sorter@2x.png)
   skin/classic/global/scale/scale-tray-horiz.gif                     (scale/scale-tray-horiz.gif)
   skin/classic/global/scale/scale-tray-vert.gif                      (scale/scale-tray-vert.gif)
   skin/classic/global/splitter/dimple.png                            (splitter/dimple.png)
   skin/classic/global/splitter/grip-bottom.gif                       (splitter/grip-bottom.gif)
   skin/classic/global/splitter/grip-top.gif                          (splitter/grip-top.gif)
   skin/classic/global/splitter/grip-left.gif                         (splitter/grip-left.gif)
   skin/classic/global/splitter/grip-right.gif                        (splitter/grip-right.gif)
   skin/classic/global/toolbar/spring.png                             (toolbar/spring.png)
--- a/toolkit/themes/osx/mozapps/extensions/extensions.css
+++ b/toolkit/themes/osx/mozapps/extensions/extensions.css
@@ -1103,16 +1103,20 @@ setting[type="radio"] > radiogroup {
 
 
 /*** buttons ***/
 
 .addon-control[disabled="true"] {
   display: none;
 }
 
+.addon-control.no-auto-hide {
+  display: block;
+}
+
 button.button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;
   box-shadow: none;
   text-decoration: underline;
   color: #0066CC;
   cursor: pointer;
rename from browser/themes/shared/in-content/check.png
rename to toolkit/themes/shared/in-content/check.png
rename from browser/themes/shared/in-content/check@2x.png
rename to toolkit/themes/shared/in-content/check@2x.png
rename from browser/themes/shared/in-content/common.inc.css
rename to toolkit/themes/shared/in-content/common.inc.css
--- a/browser/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -189,17 +189,17 @@ xul|button[type="menu"] > xul|*.button-b
   -moz-appearance: none;
   margin: 1px 0;
   -moz-margin-start: 10px;
   padding: 0;
   width: 10px;
   height: 16px;
   border: none;
   background-color: transparent;
-  list-style-image: url("chrome://browser/skin/in-content/dropdown.png");
+  list-style-image: url("chrome://global/skin/in-content/dropdown.png");
 }
 
 xul|*.help-button {
   min-width: 30px;
   border-radius: 2px;
   border: 1px solid #c1c1c1;
   background-color: #ffcb00;
   background-image: none;
@@ -222,24 +222,24 @@ xul|*.help-button > xul|*.button-box {
   padding-bottom: 0;
   padding-right: 0 !important;
   padding-left: 0 !important;
 }
 
 xul|*.help-button > xul|*.button-box > xul|*.button-icon {
   width: 26px;
   height: 26px;
-  background-image: url("chrome://browser/skin/in-content/help-glyph.png");
+  background-image: url("chrome://global/skin/in-content/help-glyph.png");
   background-position: center;
 }
 
 @media (min-resolution: 2dppx) {
   xul|*.help-button > xul|*.button-box > xul|*.button-icon {
     background-size: 26px 26px;
-    background-image: url("chrome://browser/skin/in-content/help-glyph@2x.png");
+    background-image: url("chrome://global/skin/in-content/help-glyph@2x.png");
   }
 }
 
 xul|*.help-button > xul|*.button-box > xul|*.button-text {
   display: none;
 }
 
 xul|*.spinbuttons-button {
@@ -278,31 +278,31 @@ xul|*.spinbuttons-down[disabled="true"] 
 }
 
 xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker {
   -moz-appearance: none;
   -moz-margin-end: 10px;
   padding: 0;
   border: none;
   background-color: transparent;
-  list-style-image: url("chrome://browser/skin/in-content/dropdown.png");
+  list-style-image: url("chrome://global/skin/in-content/dropdown.png");
 }
 
 xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker {
-  list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled.png")
+  list-style-image: url("chrome://global/skin/in-content/dropdown-disabled.png")
 }
 
 @media (min-resolution: 2dppx) {
   xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker,
   xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker {
-    list-style-image: url("chrome://browser/skin/in-content/dropdown@2x.png");
+    list-style-image: url("chrome://global/skin/in-content/dropdown@2x.png");
   }
 
   xul|menulist[disabled="true"]:not([editable="true"]) > xul|*.menulist-dropmarker {
-    list-style-image: url("chrome://browser/skin/in-content/dropdown-disabled@2x.png")
+    list-style-image: url("chrome://global/skin/in-content/dropdown-disabled@2x.png")
   }
 
   xul|menulist:not([editable="true"]) > xul|*.menulist-dropmarker > xul|*.dropmarker-icon,
   xul|button[type="menu"] > xul|*.button-box > xul|*.button-menu-dropmarker > xul|*.dropmarker-icon {
     width: 10px;
     height: 16px;
   }
 }
@@ -426,34 +426,34 @@ xul|*.checkbox-check {
   box-shadow: 0 1px 1px 0 #fff, inset 0 2px 0 0 rgba(0,0,0,0.03);
 }
 
 xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check {
   border-color: #0095dd;
 }
 
 xul|*.checkbox-check[checked] {
-  background-image: url("chrome://browser/skin/in-content/check.png"),
+  background-image: url("chrome://global/skin/in-content/check.png"),
                     /* !important needed to override toolkit !important rule */
                     linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
 }
 
 xul|checkbox[disabled="true"] > xul|*.checkbox-check {
   opacity: 0.5;
 }
 
 xul|*.checkbox-label-box {
   -moz-margin-start: -1px; /* negative margin for the transparent border */
   -moz-padding-start: 0;
 }
 
 @media (min-resolution: 2dppx) {
   xul|*.checkbox-check[checked] {
     background-size: 12px 12px, auto;
-    background-image: url("chrome://browser/skin/in-content/check@2x.png"),
+    background-image: url("chrome://global/skin/in-content/check@2x.png"),
                       linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
   }
 }
 
 xul|*.radio-check {
   -moz-appearance: none;
   width: 23px;
   height: 23px;
rename from browser/themes/shared/in-content/dropdown-disabled.png
rename to toolkit/themes/shared/in-content/dropdown-disabled.png
rename from browser/themes/shared/in-content/dropdown-disabled@2x.png
rename to toolkit/themes/shared/in-content/dropdown-disabled@2x.png
rename from browser/themes/shared/in-content/dropdown.png
rename to toolkit/themes/shared/in-content/dropdown.png
rename from browser/themes/shared/in-content/dropdown@2x.png
rename to toolkit/themes/shared/in-content/dropdown@2x.png
rename from browser/themes/shared/in-content/help-glyph.png
rename to toolkit/themes/shared/in-content/help-glyph.png
rename from browser/themes/shared/in-content/help-glyph@2x.png
rename to toolkit/themes/shared/in-content/help-glyph@2x.png
rename from browser/themes/shared/in-content/sorter.png
rename to toolkit/themes/shared/in-content/sorter.png
rename from browser/themes/shared/in-content/sorter@2x.png
rename to toolkit/themes/shared/in-content/sorter@2x.png
rename from browser/themes/windows/in-content/common.css
rename to toolkit/themes/windows/global/in-content/common.css
--- a/browser/themes/windows/in-content/common.css
+++ b/toolkit/themes/windows/global/in-content/common.css
@@ -1,13 +1,13 @@
 /* - 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/. */
 
-%include ../../shared/in-content/common.inc.css
+%include ../../../shared/in-content/common.inc.css
 
 xul|caption {
   background-color: transparent;
 }
 
 xul|button,
 xul|colorpicker[type="button"],
 xul|menulist {
--- a/toolkit/themes/windows/global/jar.mn
+++ b/toolkit/themes/windows/global/jar.mn
@@ -164,16 +164,27 @@ toolkit.jar:
         skin/classic/global/media/throbber.png                   (media/throbber.png)
         skin/classic/global/media/stalled.png                    (media/stalled.png)
         skin/classic/global/media/volume-empty.png               (media/volume-empty.png)
         skin/classic/global/media/volume-full.png                (media/volume-full.png)
         skin/classic/global/media/error.png                      (media/error.png)
         skin/classic/global/media/clicktoplay-bgtexture.png      (media/clicktoplay-bgtexture.png)
         skin/classic/global/media/videoClickToPlayButton.svg     (media/videoClickToPlayButton.svg)
         skin/classic/global/menu/shared-menu-check.png           (../../shared/menu-check.png)
+*       skin/classic/global/in-content/common.css                (in-content/common.css)
+        skin/classic/global/in-content/check.png                 (../../shared/in-content/check.png)
+        skin/classic/global/in-content/check@2x.png              (../../shared/in-content/check@2x.png)
+        skin/classic/global/in-content/dropdown.png              (../../shared/in-content/dropdown.png)
+        skin/classic/global/in-content/dropdown@2x.png           (../../shared/in-content/dropdown@2x.png)
+        skin/classic/global/in-content/dropdown-disabled.png     (../../shared/in-content/dropdown-disabled.png)
+        skin/classic/global/in-content/dropdown-disabled@2x.png  (../../shared/in-content/dropdown-disabled@2x.png)
+        skin/classic/global/in-content/help-glyph.png            (../../shared/in-content/help-glyph.png)
+        skin/classic/global/in-content/help-glyph@2x.png         (../../shared/in-content/help-glyph@2x.png)
+        skin/classic/global/in-content/sorter.png                (../../shared/in-content/sorter.png)
+        skin/classic/global/in-content/sorter@2x.png             (../../shared/in-content/sorter@2x.png)
         skin/classic/global/printpreview/arrow-left.png          (printpreview/arrow-left.png)
         skin/classic/global/printpreview/arrow-left-end.png      (printpreview/arrow-left-end.png)
         skin/classic/global/printpreview/arrow-right.png         (printpreview/arrow-right.png)
         skin/classic/global/printpreview/arrow-right-end.png     (printpreview/arrow-right-end.png)
         skin/classic/global/radio/radio-check.gif                (radio/radio-check.gif)
         skin/classic/global/radio/radio-check-dis.gif            (radio/radio-check-dis.gif)
         skin/classic/global/scrollbar/slider.gif                 (scrollbar/slider.gif)
         skin/classic/global/splitter/grip-bottom.gif             (splitter/grip-bottom.gif)
@@ -347,16 +358,27 @@ toolkit.jar:
         skin/classic/aero/global/media/throbber.png                      (media/throbber.png)
         skin/classic/aero/global/media/stalled.png                       (media/stalled.png)
         skin/classic/aero/global/media/volume-empty.png                  (media/volume-empty.png)
         skin/classic/aero/global/media/volume-full.png                   (media/volume-full.png)
         skin/classic/aero/global/media/error.png                         (media/error.png)
         skin/classic/aero/global/media/clicktoplay-bgtexture.png         (media/clicktoplay-bgtexture.png)
         skin/classic/aero/global/media/videoClickToPlayButton.svg        (media/videoClickToPlayButton.svg)
         skin/classic/aero/global/menu/shared-menu-check.png              (../../shared/menu-check.png)
+*       skin/classic/aero/global/in-content/common.css                   (in-content/common.css)
+        skin/classic/aero/global/in-content/check.png                    (../../shared/in-content/check.png)
+        skin/classic/aero/global/in-content/check@2x.png                 (../../shared/in-content/check@2x.png)
+        skin/classic/aero/global/in-content/dropdown.png                 (../../shared/in-content/dropdown.png)
+        skin/classic/aero/global/in-content/dropdown@2x.png              (../../shared/in-content/dropdown@2x.png)
+        skin/classic/aero/global/in-content/dropdown-disabled.png        (../../shared/in-content/dropdown-disabled.png)
+        skin/classic/aero/global/in-content/dropdown-disabled@2x.png     (../../shared/in-content/dropdown-disabled@2x.png)
+        skin/classic/aero/global/in-content/help-glyph.png               (../../shared/in-content/help-glyph.png)
+        skin/classic/aero/global/in-content/help-glyph@2x.png            (../../shared/in-content/help-glyph@2x.png)
+        skin/classic/aero/global/in-content/sorter.png                   (../../shared/in-content/sorter.png)
+        skin/classic/aero/global/in-content/sorter@2x.png                (../../shared/in-content/sorter@2x.png)
         skin/classic/aero/global/printpreview/arrow-left.png             (printpreview/arrow-left-aero.png)
         skin/classic/aero/global/printpreview/arrow-left-end.png         (printpreview/arrow-left-end-aero.png)
         skin/classic/aero/global/printpreview/arrow-right.png            (printpreview/arrow-right-aero.png)
         skin/classic/aero/global/printpreview/arrow-right-end.png        (printpreview/arrow-right-end-aero.png)
         skin/classic/aero/global/radio/radio-check.gif                   (radio/radio-check.gif)
         skin/classic/aero/global/radio/radio-check-dis.gif               (radio/radio-check-dis.gif)
         skin/classic/aero/global/scrollbar/slider.gif                    (scrollbar/slider.gif)
         skin/classic/aero/global/splitter/grip-bottom.gif                (splitter/grip-bottom.gif)
--- a/toolkit/themes/windows/mozapps/extensions/extensions.css
+++ b/toolkit/themes/windows/mozapps/extensions/extensions.css
@@ -1119,16 +1119,20 @@ menulist { /* Fixes some styling inconsi
 
 
 /*** buttons ***/
 
 .addon-control[disabled="true"] {
   display: none;
 }
 
+.addon-control.no-auto-hide {
+  display: block;
+}
+
 button.button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;
   box-shadow: none;
   text-decoration: underline;
   color: #0066CC;
   cursor: pointer;