Backed out 5 changesets (bug 1407351) for causing bug 1409395 and breaking nightlies.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 17 Oct 2017 10:07:55 -0400
changeset 439834 f27105b62753c71ecadad2f8d632ec7e5ac96bbd
parent 439833 0d9c6250f99dc4b6aa1a94f5260737d046c52b1e
child 439835 0f14301a049554492e5db8901536e1c105e3c283
child 439932 102c8e6c30fff39c98cc71dbb63a818fb16b4b6a
child 439952 116b06b3275e91b1ef609903a8c6c05af3d652fb
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1407351, 1409395
milestone58.0a1
backs oute6ee25ad6a9fbd6567b0ec1723d18f670eed3a2c
8e04412824b50fe0096faf3e921f82dc6cf909fe
effeee94316ecc7e82d2a79d1a57b977c57dee3a
a53f34a45f9b718a8b7dee121833acb2d75c8b14
86a360e12b8a7ce3af0fa8e305b9c95c225eb6b5
first release with
nightly linux32
f27105b62753 / 58.0a1 / 20171017141229 / files
nightly linux64
f27105b62753 / 58.0a1 / 20171017141229 / files
nightly mac
f27105b62753 / 58.0a1 / 20171017141229 / files
nightly win32
f27105b62753 / 58.0a1 / 20171017141229 / files
nightly win64
f27105b62753 / 58.0a1 / 20171017141229 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 5 changesets (bug 1407351) for causing bug 1409395 and breaking nightlies. Backed out changeset e6ee25ad6a9f (bug 1407351) Backed out changeset 8e04412824b5 (bug 1407351) Backed out changeset effeee94316e (bug 1407351) Backed out changeset a53f34a45f9b (bug 1407351) Backed out changeset 86a360e12b8a (bug 1407351)
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.xml
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/test/head.js
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/main.xul
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
browser/locales/en-US/chrome/browser/preferences/main.dtd
browser/themes/shared/toolbarbutton-icons.inc.css
devtools/client/locales/en-US/performance.dtd
devtools/client/performance/performance-controller.js
devtools/client/performance/performance.xul
devtools/client/performance/test/browser_perf-recording-notices-05.js
devtools/client/themes/performance.css
moz.configure
toolkit/modules/AppConstants.jsm
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -29,16 +29,22 @@
                           accesskey="&newNavigatorCmd.accesskey;"
                           key="key_newNavigator"
                           command="cmd_newNavigator"/>
                 <menuitem id="menu_newPrivateWindow"
                           label="&newPrivateWindow.label;"
                           accesskey="&newPrivateWindow.accesskey;"
                           command="Tools:PrivateBrowsing"
                           key="key_privatebrowsing"/>
+#ifdef E10S_TESTING_ONLY
+                <menuitem id="menu_newNonRemoteWindow"
+                          label="&newNonRemoteWindow.label;"
+                          hidden="true"
+                          command="Tools:NonRemoteWindow"/>
+#endif
 #ifdef MAC_NON_BROWSER_WINDOW
                 <menuitem id="menu_openLocation"
                           label="&openLocationCmd.label;"
                           command="Browser:OpenLocation"
                           key="focusURLBar"/>
 #endif
                 <menuitem id="menu_openFile"
                           label="&openFileCmd.label;"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -97,16 +97,20 @@
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing"
       oncommand="OpenBrowserWindow({private: true});"/>
+#ifdef E10S_TESTING_ONLY
+    <command id="Tools:NonRemoteWindow"
+      oncommand="OpenBrowserWindow({remote: false});"/>
+#endif
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
   </commandset>
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/>
     <command id="Browser:ShowAllHistory"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1461,16 +1461,19 @@ var gBrowserInit = {
     Services.obs.addObserver(gXPInstallObserver, "addon-install-confirmation");
     Services.obs.addObserver(gXPInstallObserver, "addon-install-complete");
     window.messageManager.addMessageListener("Browser:URIFixup", gKeywordURIFixup);
 
     BrowserOffline.init();
     IndexedDBPromptHelper.init();
     CanvasPermissionPromptHelper.init();
 
+    if (AppConstants.E10S_TESTING_ONLY)
+      gRemoteTabsUI.init();
+
     // Initialize the full zoom setting.
     // We do this before the session restore service gets initialized so we can
     // apply full zoom settings to tabs restored by the session restore service.
     FullZoom.init();
     PanelUI.init();
 
     UpdateUrlbarSearchSplitterState();
 
@@ -1974,16 +1977,19 @@ if (AppConstants.platform == "macosx") {
     this._delayedStartupTimeoutId = null;
 
     // initialise the offline listener
     BrowserOffline.init();
 
     // initialize the private browsing UI
     gPrivateBrowsingUI.init();
 
+    if (AppConstants.E10S_TESTING_ONLY) {
+      gRemoteTabsUI.init();
+    }
   };
 
   gBrowserInit.nonBrowserWindowShutdown = function() {
     let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
                       .getService(Ci.nsIMacDockSupport);
     dockSupport.dockMenu = null;
 
     // If nonBrowserWindowDelayedStartup hasn't run yet, we have no work to do -
@@ -8272,16 +8278,37 @@ var gPrivateBrowsingUI = {
     }
     if (!urlBarSearchParam.includes("private-window")) {
       urlBarSearchParam += " private-window";
     }
     gURLBar.setAttribute("autocompletesearchparam", urlBarSearchParam);
   }
 };
 
+var gRemoteTabsUI = {
+  init() {
+    if (window.location.href != getBrowserURL() &&
+        // Also check hidden window for the Mac no-window case
+        window.location.href != "chrome://browser/content/hiddenWindow.xul") {
+      return;
+    }
+
+    if (AppConstants.platform == "macosx" &&
+        Services.prefs.getBoolPref("layers.acceleration.disabled")) {
+      // On OS X, "Disable Hardware Acceleration" also disables OMTC and forces
+      // a fallback to Basic Layers. This is incompatible with e10s.
+      return;
+    }
+
+    let newNonRemoteWindow = document.getElementById("menu_newNonRemoteWindow");
+    let autostart = Services.appinfo.browserTabsRemoteAutostart;
+    newNonRemoteWindow.hidden = !autostart;
+  }
+};
+
 /**
  * Switch to a tab that has a given URI, and focuses its browser window.
  * If a matching tab is in this window, it will be switched to. Otherwise, other
  * windows will be searched.
  *
  * @param aURI
  *        URI to search for
  * @param aOpenNew
@@ -8529,16 +8556,26 @@ var TabContextMenu = {
 
     var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple");
     for (let menuItem of menuItems)
       menuItem.disabled = disabled;
 
     if (this.contextTab.hasAttribute("customizemode"))
       document.getElementById("context_openTabInWindow").disabled = true;
 
+    if (AppConstants.E10S_TESTING_ONLY) {
+      menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-remote");
+      for (let menuItem of menuItems) {
+        menuItem.hidden = !gMultiProcessBrowser;
+        if (menuItem.id == "context_openNonRemoteWindow") {
+          menuItem.disabled = !!parseInt(this.contextTab.getAttribute("usercontextid"));
+        }
+      }
+    }
+
     disabled = gBrowser.visibleTabs.length == 1;
     menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple-visible");
     for (let menuItem of menuItems)
       menuItem.disabled = disabled;
 
     // Session store
     document.getElementById("context_undoCloseTab").disabled =
       SessionStore.getClosedTabCount(window) == 0;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -91,16 +91,22 @@
                 oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
       <menuitem id="context_duplicateTab" label="&duplicateTab.label;"
                 accesskey="&duplicateTab.accesskey;"
                 oncommand="duplicateTabIn(TabContextMenu.contextTab, 'tab');"/>
       <menuitem id="context_openTabInWindow" label="&moveToNewWindow.label;"
                 accesskey="&moveToNewWindow.accesskey;"
                 tbattr="tabbrowser-multiple"
                 oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/>
+#ifdef E10S_TESTING_ONLY
+      <menuitem id="context_openNonRemoteWindow" label="Open in new non-e10s window"
+                tbattr="tabbrowser-remote"
+                hidden="true"
+                oncommand="gBrowser.openNonRemoteWindow(TabContextMenu.contextTab);"/>
+#endif
       <menuseparator id="context_sendTabToDevice_separator"/>
       <menu id="context_sendTabToDevice" label="&sendTabToDevice.label;"
             accesskey="&sendTabToDevice.accesskey;">
         <menupopup id="context_sendTabToDevicePopupMenu"
                    onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, TabContextMenu.contextTab.linkedBrowser.currentURI.spec, TabContextMenu.contextTab.linkedBrowser.contentTitle);"/>
       </menu>
       <menuseparator/>
       <menuitem id="context_reloadAllTabs" label="&reloadAllTabs.label;" accesskey="&reloadAllTabs.accesskey;"
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3949,16 +3949,30 @@
             }
 
             // tell a new window to take the "dropped" tab
             return window.openDialog(getBrowserURL(), "_blank", options, aTab);
           ]]>
         </body>
       </method>
 
+      <!-- Opens a given tab to a non-remote window. -->
+      <method name="openNonRemoteWindow">
+        <parameter name="aTab"/>
+        <body>
+          <![CDATA[
+            if (!AppConstants.E10S_TESTING_ONLY) {
+              throw "This method is intended only for e10s testing!";
+            }
+            let url = aTab.linkedBrowser.currentURI.spec;
+            return window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url);
+          ]]>
+        </body>
+      </method>
+
       <method name="moveTabTo">
         <parameter name="aTab"/>
         <parameter name="aIndex"/>
         <parameter name="aKeepRelatedTabs"/>
         <body>
         <![CDATA[
           var oldPosition = aTab._tPos;
           if (oldPosition == aIndex)
@@ -5525,21 +5539,24 @@
                   "tabs.unmuteAudio.background.tooltip" :
                   "tabs.muteAudio.background.tooltip";
               }
 
               label = this.mStringBundle.getString(stringID);
             }
           } else {
             label = tab._fullLabel || tab.getAttribute("label");
-            if (AppConstants.NIGHTLY_BUILD &&
+            if (AppConstants.E10S_TESTING_ONLY &&
                 tab.linkedBrowser &&
-                tab.linkedBrowser.isRemoteBrowser &&
-                tab.linkedBrowser.frameLoader) {
-              label += " (pid " + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
+                tab.linkedBrowser.isRemoteBrowser) {
+              label += " - e10s";
+              if (tab.linkedBrowser.frameLoader &&
+                  Services.appinfo.maxWebProcessCount > 1) {
+                label += " (" + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
+              }
             }
             if (tab.userContextId) {
               label = this.mStringBundle.getFormattedString("tabs.containers.tooltip", [label, ContextualIdentityService.getUserContextLabel(tab.userContextId)]);
             }
           }
 
           event.target.setAttribute("label", label);
         ]]></body>
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -54,17 +54,17 @@ const kSubviewEvents = [
   "ViewShowing",
   "ViewHiding"
 ];
 
 /**
  * The current version. We can use this to auto-add new default widgets as necessary.
  * (would be const but isn't because of testing purposes)
  */
-var kVersion = 13;
+var kVersion = 12;
 
 /**
  * Buttons removed from built-ins by version they were removed. kVersion must be
  * bumped any time a new id is added to this. Use the button id as key, and
  * version the button is removed in as the value.  e.g. "pocket-button": 5
  */
 var ObsoleteBuiltinButtons = {
 };
@@ -340,16 +340,17 @@ var CustomizableUIInternal = {
         "save-page-button",
         "print-button",
         "history-panelmenu",
         "fullscreen-button",
         "find-button",
         "preferences-button",
         "add-ons-button",
         "sync-button",
+        "e10s-button",
       ];
 
       if (!AppConstants.MOZ_DEV_EDITION) {
         defaultPlacements.splice(-1, 0, "developer-button");
       }
 
       let showCharacterEncoding = Services.prefs.getComplexValue(
         "browser.menu.showCharacterEncoding",
@@ -446,27 +447,16 @@ var CustomizableUIInternal = {
         for (let button of removedButtons) {
           let buttonIndex = placements.indexOf(button);
           if (buttonIndex != -1) {
             placements.splice(buttonIndex, 1);
           }
         }
       }
     }
-
-    // Remove the old placements from the now-gone Nightly-only
-    // "New non-e10s window" button.
-    if (currentVersion < 13 && gSavedState.placements) {
-      for (let placements of Object.values(gSavedState.placements)) {
-        let buttonIndex = placements.indexOf("e10s-button");
-        if (buttonIndex != -1) {
-          placements.spice(buttonIndex, 1);
-        }
-      }
-    }
   },
 
   /**
    * _markObsoleteBuiltinButtonsSeen
    * when upgrading, ensure obsoleted buttons are in seen state.
    */
   _markObsoleteBuiltinButtonsSeen() {
     if (!gSavedState)
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -992,8 +992,26 @@ if (Services.prefs.getBoolPref("privacy.
       forgetButton.addEventListener("command", this);
     },
     onViewHiding(aEvent) {
       let forgetButton = aEvent.target.querySelector("#PanelUI-panic-view-button");
       forgetButton.removeEventListener("command", this);
     },
   });
 }
+
+if (AppConstants.E10S_TESTING_ONLY) {
+  if (Services.appinfo.browserTabsRemoteAutostart) {
+    CustomizableWidgets.push({
+      id: "e10s-button",
+      defaultArea: CustomizableUI.AREA_PANEL,
+      onBuild(aDocument) {
+        let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
+        node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
+        node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
+      },
+      onCommand(aEvent) {
+        let win = aEvent.view;
+        win.OpenBrowserWindow({remote: false});
+      },
+    });
+  }
+}
--- a/browser/components/customizableui/test/head.js
+++ b/browser/components/customizableui/test/head.js
@@ -12,16 +12,21 @@ Cu.import("resource://gre/modules/AppCon
 var {Promise, CustomizableUI, AppConstants} = tmp;
 
 var EventUtils = {};
 Services.scriptloader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
 
 Services.prefs.setBoolPref("browser.uiCustomization.skipSourceNodeCheck", true);
 registerCleanupFunction(() => Services.prefs.clearUserPref("browser.uiCustomization.skipSourceNodeCheck"));
 
+// Remove temporary e10s related new window options in customize ui,
+// they break a lot of tests.
+CustomizableUI.destroyWidget("e10s-button");
+CustomizableUI.removeWidgetFromArea("e10s-button");
+
 var {synthesizeDragStart, synthesizeDrop} = EventUtils;
 
 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const kTabEventFailureTimeoutInMs = 20000;
 
 const kForceOverflowWidthPx = 300;
 
 function createDummyXULButton(id, label, win = window) {
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -92,16 +92,21 @@ const ICON_URL_APP = AppConstants.platfo
 
 // For CSS. Can be one of "ask", "save", "plugin" or "feed". If absent, the icon URL
 // was set by us to a custom handler icon and CSS should not try to override it.
 const APP_ICON_ATTR_NAME = "appHandlerIcon";
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
   "resource://gre/modules/osfile.jsm");
 
+if (AppConstants.E10S_TESTING_ONLY) {
+  XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
+    "resource://gre/modules/UpdateUtils.jsm");
+}
+
 if (AppConstants.MOZ_DEV_EDITION) {
   XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
     "resource://gre/modules/FxAccounts.jsm");
 }
 
 // A promise that resolves when the list of application handlers is loaded.
 // We store this in a global so tests can await it.
 var promiseLoadHandlersList;
@@ -309,16 +314,36 @@ var gMainPane = {
       row.removeAttribute("hidden");
       // Showing attribution only for Bing Translator.
       Components.utils.import("resource:///modules/translation/Translation.jsm");
       if (Translation.translationEngine == "bing") {
         document.getElementById("bingAttribution").removeAttribute("hidden");
       }
     }
 
+    if (AppConstants.E10S_TESTING_ONLY) {
+      setEventListener("e10sAutoStart", "command",
+        gMainPane.enableE10SChange);
+      let e10sCheckbox = document.getElementById("e10sAutoStart");
+
+      let e10sPref = document.getElementById("browser.tabs.remote.autostart");
+      let e10sTempPref = document.getElementById("e10sTempPref");
+      let e10sForceEnable = document.getElementById("e10sForceEnable");
+
+      let preffedOn = e10sPref.value || e10sTempPref.value || e10sForceEnable.value;
+
+      if (preffedOn) {
+        // The checkbox is checked if e10s is preffed on and enabled.
+        e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart;
+
+        // but if it's force disabled, then the checkbox is disabled.
+        e10sCheckbox.disabled = !Services.appinfo.browserTabsRemoteAutostart;
+      }
+    }
+
     if (AppConstants.MOZ_DEV_EDITION) {
       let uAppData = OS.Constants.Path.userApplicationDataDir;
       let ignoreSeparateProfile = OS.Path.join(uAppData, "ignore-dev-edition-profile");
 
       setEventListener("separateProfileMode", "command", gMainPane.separateProfileModeChange);
       let separateProfileModeCheckbox = document.getElementById("separateProfileMode");
       setEventListener("getStarted", "click", gMainPane.onGetStarted);
 
@@ -516,16 +541,64 @@ var gMainPane = {
 
     const link = document.getElementById("browserContainersLearnMore");
     link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
 
     document.getElementById("browserContainersbox").hidden = false;
     this.readBrowserContainersCheckbox();
   },
 
+  isE10SEnabled() {
+    let e10sEnabled;
+    try {
+      let e10sStatus = Components.classes["@mozilla.org/supports-PRUint64;1"]
+        .createInstance(Ci.nsISupportsPRUint64);
+      let appinfo = Services.appinfo.QueryInterface(Ci.nsIObserver);
+      appinfo.observe(e10sStatus, "getE10SBlocked", "");
+      e10sEnabled = e10sStatus.data < 2;
+    } catch (e) {
+      e10sEnabled = false;
+    }
+
+    return e10sEnabled;
+  },
+
+  enableE10SChange() {
+    if (AppConstants.E10S_TESTING_ONLY) {
+      let e10sCheckbox = document.getElementById("e10sAutoStart");
+      let e10sPref = document.getElementById("browser.tabs.remote.autostart");
+      let e10sTempPref = document.getElementById("e10sTempPref");
+
+      let prefsToChange;
+      if (e10sCheckbox.checked) {
+        // Enabling e10s autostart
+        prefsToChange = [e10sPref];
+      } else {
+        // Disabling e10s autostart
+        prefsToChange = [e10sPref];
+        if (e10sTempPref.value) {
+          prefsToChange.push(e10sTempPref);
+        }
+      }
+
+      let buttonIndex = confirmRestartPrompt(e10sCheckbox.checked, 0,
+        true, false);
+      if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
+        for (let prefToChange of prefsToChange) {
+          prefToChange.value = e10sCheckbox.checked;
+        }
+
+        Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
+      }
+
+      // Revert the checkbox in case we didn't quit
+      e10sCheckbox.checked = e10sPref.value || e10sTempPref.value;
+    }
+  },
+
   separateProfileModeChange() {
     if (AppConstants.MOZ_DEV_EDITION) {
       function quitApp() {
         Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestartNotSameProfile);
       }
       function revertCheckbox(error) {
         separateProfileModeCheckbox.checked = !separateProfileModeCheckbox.checked;
         if (error) {
@@ -1207,17 +1280,17 @@ var gMainPane = {
         processCountPref.value == processCountPref.defaultValue) {
         processCountPref.value = e10sRolloutProcessCountPref.value;
       }
       performanceSettings.hidden = false;
     }
   },
 
   buildContentProcessCountMenuList() {
-    if (Services.appinfo.browserTabsRemoteAutostart) {
+    if (gMainPane.isE10SEnabled()) {
       let processCountPref = document.getElementById("dom.ipc.processCount");
       let e10sRolloutProcessCountPref =
         document.getElementById("dom.ipc.processCount.web");
       let defaultProcessCount =
         e10sRolloutProcessCountPref.value || processCountPref.defaultValue;
       let bundlePreferences = document.getElementById("bundlePreferences");
       let label = bundlePreferences.getFormattedString("defaultContentProcessCount",
         [defaultProcessCount]);
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -12,16 +12,29 @@
 #endif
 
 <script type="application/javascript"
         src="chrome://mozapps/content/preferences/fontbuilder.js"/>
 
 <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences.properties"/>
 
 <preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
+
+#ifdef E10S_TESTING_ONLY
+    <preference id="browser.tabs.remote.autostart"
+                name="browser.tabs.remote.autostart"
+                type="bool"/>
+    <preference id="e10sTempPref"
+                name="browser.tabs.remote.autostart.2"
+                type="bool"/>
+    <preference id="e10sForceEnable"
+                name="browser.tabs.remote.force-enable"
+                type="bool"/>
+#endif
+
     <!-- Startup -->
     <preference id="browser.startup.page"
                 name="browser.startup.page"
                 type="int"/>
     <preference id="browser.startup.homepage"
                 name="browser.startup.homepage"
                 type="wstring"/>
 
@@ -280,16 +293,21 @@
       <deck id="getStarted">
         <label class="text-link">&getStarted.notloggedin.label;</label>
         <label class="text-link">&getStarted.configured.label;</label>
       </deck>
     </hbox>
   </vbox>
 #endif
 
+#ifdef E10S_TESTING_ONLY
+  <checkbox id="e10sAutoStart"
+            label="&e10sEnabled.label;"/>
+#endif
+
 #ifdef HAVE_SHELL_SERVICE
   <vbox id="defaultBrowserBox">
     <checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
               label="&alwaysCheckDefault2.label;" accesskey="&alwaysCheckDefault2.accesskey;"/>
     <deck id="setDefaultPane">
       <hbox align="center" class="indent">
         <image class="face-sad"/>
         <label id="isNotDefaultLabel" flex="1">&isNotDefault.label;</label>
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -289,16 +289,17 @@ These should match what Safari and other
 <!ENTITY fileMenu.accesskey       "F">
 <!ENTITY newUserContext.label             "New Container Tab">
 <!ENTITY newUserContext.accesskey         "B">
 <!ENTITY newNavigatorCmd.label        "New Window">
 <!ENTITY newNavigatorCmd.key        "N">
 <!ENTITY newNavigatorCmd.accesskey      "N">
 <!ENTITY newPrivateWindow.label     "New Private Window">
 <!ENTITY newPrivateWindow.accesskey "W">
+<!ENTITY newNonRemoteWindow.label   "New Non-e10s Window">
 
 <!ENTITY editMenu.label         "Edit">
 <!ENTITY editMenu.accesskey       "E">
 <!ENTITY undoCmd.label            "Undo">
 <!ENTITY undoCmd.key            "Z">
 <!ENTITY undoCmd.accesskey          "U">
 <!ENTITY redoCmd.label            "Redo">
 <!ENTITY redoCmd.key            "Y">
--- a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
+++ b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties
@@ -96,11 +96,14 @@ panic-button.label = Forget
 panic-button.tooltiptext = Forget about some browsing history
 
 # LOCALIZATION NOTE(devtools-webide-button.label, devtools-webide-button.tooltiptext):
 # widget is only visible after WebIDE has been started once (Tools > Web Developers > WebIDE)
 # %S is the keyboard shortcut
 devtools-webide-button2.label = WebIDE
 devtools-webide-button2.tooltiptext = Open WebIDE (%S)
 
+e10s-button.label = New Non-e10s Window
+e10s-button.tooltiptext = Open a new Non-e10s Window
+
 toolbarspring.label = Flexible Space
 toolbarseparator.label = Separator
 toolbarspacer.label = Space
--- a/browser/locales/en-US/chrome/browser/preferences/main.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/main.dtd
@@ -39,8 +39,10 @@
 <!ENTITY setAsMyDefaultBrowser3.accesskey "D">
 <!ENTITY isDefault.label                  "&brandShortName; is currently your default browser">
 <!ENTITY isNotDefault.label               "&brandShortName; is not your default browser">
 
 <!ENTITY separateProfileMode.label        "Allow &brandShortName; and Firefox to run at the same time">
 <!ENTITY useFirefoxSync.label             "Tip: This uses separate profiles. Use Sync to share data between them.">
 <!ENTITY getStarted.notloggedin.label     "Sign in to &syncBrand.shortName.label;…">
 <!ENTITY getStarted.configured.label      "Open &syncBrand.shortName.label; preferences">
+
+<!ENTITY e10sEnabled.label                "Enable multi-process &brandShortName;">
--- a/browser/themes/shared/toolbarbutton-icons.inc.css
+++ b/browser/themes/shared/toolbarbutton-icons.inc.css
@@ -224,16 +224,24 @@ toolbar[brighttext] {
 #characterencoding-button {
   list-style-image: url("chrome://browser/skin/characterEncoding.svg");
 }
 
 #new-window-button {
   list-style-image: url("chrome://browser/skin/new-window.svg");
 }
 
+#e10s-button {
+  list-style-image: url("chrome://browser/skin/new-window.svg");
+}
+
+#e10s-button > .toolbarbutton-icon {
+  transform: scaleY(-1);
+}
+
 #new-tab-button {
   list-style-image: url("chrome://browser/skin/new-tab.svg");
 }
 
 #privatebrowsing-button {
   list-style-image: url("chrome://browser/skin/privateBrowsing.svg");
 }
 
--- a/devtools/client/locales/en-US/performance.dtd
+++ b/devtools/client/locales/en-US/performance.dtd
@@ -10,16 +10,21 @@
   - You want to make that choice consistent across the developer tools.
   - A good criteria is the language in which you'd find the best
   - documentation on web development on the web. -->
 
 <!-- LOCALIZATION NOTE (performanceUI.bufferStatusTooltip): This string
   -  is displayed as the tooltip for the buffer capacity during a recording. -->
 <!ENTITY performanceUI.bufferStatusTooltip "The profiler stores samples in a circular buffer, and once the buffer reaches the limit for a recording, newer samples begin to overwrite samples at the beginning of the recording.">
 
+<!-- LOCALIZATION NOTE (performanceUI.disabledRealTime.nonE10SBuild): This string
+  -  is displayed as a message for why the real time overview graph is disabled
+  -  when running on a non-multiprocess build. -->
+<!ENTITY performanceUI.disabledRealTime.nonE10SBuild "Realtime recording data disabled on non-multiprocess Firefox.">
+
 <!-- LOCALIZATION NOTE (performanceUI.disabledRealTime.disabledE10S): This string
   -  is displayed as a message for why the real time overview graph is disabled
   -  when running on a build that can run multiprocess Firefox, but just is not enabled. -->
 <!ENTITY performanceUI.disabledRealTime.disabledE10S "Enable multiprocess Firefox in preferences for rendering recording data in realtime.">
 
 <!-- LOCALIZATION NOTE (performanceUI.bufferStatusFull): This string
   -  is displayed when the profiler's circular buffer has started to overlap. -->
 <!ENTITY performanceUI.bufferStatusFull "The buffer is full. Older samples are now being overwritten.">
--- a/devtools/client/performance/performance-controller.js
+++ b/devtools/client/performance/performance-controller.js
@@ -512,27 +512,28 @@ var PerformanceController = {
   /**
    * Returns an object with `supported` and `enabled` properties indicating
    * whether or not the platform is capable of turning on e10s and whether or not
    * it's already enabled, respectively.
    *
    * @return {object}
    */
   getMultiprocessStatus: function () {
-    // If testing, set enabled to true so we have realtime rendering tests
-    // in non-e10s. This function is overridden wholesale in tests
-    // when we want to test multiprocess support
+    // If testing, set both supported and enabled to true so we
+    // have realtime rendering tests in non-e10s. This function is
+    // overridden wholesale in tests when we want to test multiprocess support
     // specifically.
     if (flags.testing) {
-      return { enabled: true };
+      return { supported: true, enabled: true };
     }
+    let supported = system.constants.E10S_TESTING_ONLY;
     // This is only checked on tool startup -- requires a restart if
     // e10s subsequently enabled.
     let enabled = this._e10s;
-    return { enabled };
+    return { supported, enabled };
   },
 
   /**
    * Takes a PerformanceRecording and a state, and waits for
    * the event to be emitted from the front for that recording.
    *
    * @param {PerformanceRecordingFront} recording
    * @param {string} expectedState
@@ -550,19 +551,22 @@ var PerformanceController = {
   }),
 
   /**
    * Called on init, sets an `e10s` attribute on the main view container with
    * "disabled" if e10s is possible on the platform and just not on, or "unsupported"
    * if e10s is not possible on the platform. If e10s is on, no attribute is set.
    */
   _setMultiprocessAttributes: function () {
-    let { enabled } = this.getMultiprocessStatus();
-    if (!enabled) {
+    let { enabled, supported } = this.getMultiprocessStatus();
+    if (!enabled && supported) {
       $("#performance-view").setAttribute("e10s", "disabled");
+    } else if (!enabled && !supported) {
+      // Could be a chance where the directive goes away yet e10s is still on
+      $("#performance-view").setAttribute("e10s", "unsupported");
     }
   },
 
   /**
    * Pipes an event from some source to the PerformanceController.
    */
   _pipe: function (eventName, ...data) {
     this.emit(eventName, ...data);
--- a/devtools/client/performance/performance.xul
+++ b/devtools/client/performance/performance.xul
@@ -206,16 +206,18 @@
             <vbox id="recording-notice"
                   class="notice-container"
                   align="center"
                   pack="center"
                   flex="1">
               <hbox pack="center">
                 <html:div class='recording-button-mount'/>
               </hbox>
+              <label class="realtime-disabled-message"
+                     value="&performanceUI.disabledRealTime.nonE10SBuild;"/>
               <label class="realtime-disabled-on-e10s-message"
                      value="&performanceUI.disabledRealTime.disabledE10S;"/>
               <label class="buffer-status-message"
                      tooltiptext="&performanceUI.bufferStatusTooltip;"/>
               <label class="buffer-status-message-full"
                      value="&performanceUI.bufferStatusFull;"/>
             </vbox>
 
@@ -230,16 +232,18 @@
                 <label class="console-profile-command" />
                 <label value="&performanceUI.console.recordingNoticeEnd;" />
               </hbox>
               <hbox class="console-profile-stop-notice">
                 <label value="&performanceUI.console.stopCommandStart;" />
                 <label class="console-profile-command" />
                 <label value="&performanceUI.console.stopCommandEnd;" />
               </hbox>
+              <label class="realtime-disabled-message"
+                     value="&performanceUI.disabledRealTime.nonE10SBuild;"/>
               <label class="realtime-disabled-on-e10s-message"
                      value="&performanceUI.disabledRealTime.disabledE10S;"/>
               <label class="buffer-status-message"
                      tooltiptext="&performanceUI.bufferStatusTooltip;"/>
               <label class="buffer-status-message-full"
                      value="&performanceUI.bufferStatusFull;"/>
             </vbox>
 
--- a/devtools/client/performance/test/browser_perf-recording-notices-05.js
+++ b/devtools/client/performance/test/browser_perf-recording-notices-05.js
@@ -15,26 +15,40 @@ add_task(function* () {
     win: window
   });
 
   let { gFront, $, PerformanceController } = panel.panelWin;
 
   // Set a fast profiler-status update interval
   yield gFront.setProfilerStatusInterval(10);
 
+  let supported = false;
   let enabled = false;
 
   PerformanceController.getMultiprocessStatus = () => {
-    return { enabled };
+    return { supported, enabled };
   };
 
   PerformanceController._setMultiprocessAttributes();
-  ok($("#performance-view").getAttribute("e10s"), "disabled",
-    "When e10s is disabled, container has [e10s=disabled].");
+  ok($("#performance-view").getAttribute("e10s"), "unsupported",
+    "When e10s is disabled and no option to turn on, container has [e10s=unsupported].");
 
+  supported = true;
+  enabled = false;
+  PerformanceController._setMultiprocessAttributes();
+  ok($("#performance-view").getAttribute("e10s"), "disabled",
+    "When e10s is disabled and but is supported, container has [e10s=disabled].");
+
+  supported = false;
   enabled = true;
-
   PerformanceController._setMultiprocessAttributes();
   ok($("#performance-view").getAttribute("e10s"), "",
-    "When e10s is enabled, there should be no e10s attribute.");
+    "When e10s is enabled, but not supported, this probably means we no longer have " +
+    "E10S_TESTING_ONLY, and we have no e10s attribute.");
+
+  supported = true;
+  enabled = true;
+  PerformanceController._setMultiprocessAttributes();
+  ok($("#performance-view").getAttribute("e10s"), "",
+    "When e10s is enabled and supported, there should be no e10s attribute.");
 
   yield teardownToolboxAndRemoveTab(panel);
 });
--- a/devtools/client/themes/performance.css
+++ b/devtools/client/themes/performance.css
@@ -242,21 +242,23 @@
   overflow: hidden;
 }
 
 .console-profile-command {
   font-family: monospace;
   margin: 3px 2px;
 }
 
+.realtime-disabled-message,
 .realtime-disabled-on-e10s-message {
   display: none;
 }
 
-#performance-view[e10s="disabled"] .realtime-disabled-on-e10s-message {
+#performance-view[e10s="disabled"] .realtime-disabled-on-e10s-message,
+#performance-view[e10s="unsupported"] .realtime-disabled-message {
   display: initial;
   opacity: 0.5;
 }
 
 .buffer-status-message,
 .buffer-status-message-full {
   display: none;
 }
--- a/moz.configure
+++ b/moz.configure
@@ -9,16 +9,27 @@ include('build/moz.configure/init.config
 # Note:
 # - Gecko-specific options and rules should go in toolkit/moz.configure.
 # - Firefox-specific options and rules should go in browser/moz.configure.
 # - Fennec-specific options and rules should go in
 #   mobile/android/moz.configure.
 # - Spidermonkey-specific options and rules should go in js/moz.configure.
 # - etc.
 
+# Multiprocess Firefox Testing UI - Nightly and Aurora
+# To be removed in Bug 1003313
+@depends(milestone)
+def e10s_testing_only(milestone):
+    if not milestone.is_release_or_beta:
+        return True
+
+set_config('E10S_TESTING_ONLY', e10s_testing_only)
+set_define('E10S_TESTING_ONLY', e10s_testing_only)
+
+
 option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
        help='Download and use prebuilt binary artifacts.')
 
 @depends('--enable-artifact-builds')
 def artifact_builds(value):
     if value:
         return True
 
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -175,16 +175,23 @@ this.AppConstants = Object.freeze({
 
   MOZ_MAINTENANCE_SERVICE:
 #ifdef MOZ_MAINTENANCE_SERVICE
   true,
 #else
   false,
 #endif
 
+  E10S_TESTING_ONLY:
+#ifdef E10S_TESTING_ONLY
+  true,
+#else
+  false,
+#endif
+
   DEBUG:
 #ifdef DEBUG
   true,
 #else
   false,
 #endif
 
   ASAN: