diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index daab9d10ec81..e5941c425d5b 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4132,7 +4132,7 @@ function nsBrowserAccess() { }
nsBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]),
- _openURIInNewTab: function(aURI, aOpener, aIsExternal) {
+ _openURIInNewTab: function(aURI, aOpener, aIsExternal, aEnsureNonRemote=false) {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
@@ -4164,6 +4164,15 @@ nsBrowserAccess.prototype = {
inBackground: loadInBackground});
let browser = win.gBrowser.getBrowserForTab(tab);
+ // It's possible that we've been asked to open a new non-remote
+ // browser in a window that defaults to having remote browsers -
+ // this can happen if we're opening the new tab due to a window.open
+ // or _blank anchor in a non-remote browser. If so, we have to force
+ // the newly opened browser to also not be remote.
+ if (win.gMultiProcessBrowser && aEnsureNonRemote) {
+ win.gBrowser.updateBrowserRemoteness(browser, false);
+ }
+
if (needToFocusWin || (!loadInBackground && aIsExternal))
win.focus();
@@ -4171,6 +4180,14 @@ nsBrowserAccess.prototype = {
},
openURI: function (aURI, aOpener, aWhere, aContext) {
+ // This function should only ever be called if we're opening a URI
+ // from a non-remote browser window (via nsContentTreeOwner).
+ if (aOpener && Cu.isCrossProcessWrapper(aOpener)) {
+ Cu.reportError("nsBrowserAccess.openURI was passed a CPOW for aOpener. " +
+ "openURI should only ever be called from non-remote browsers.");
+ throw Cr.NS_ERROR_FAILURE;
+ }
+
var newWindow = null;
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
@@ -4196,7 +4213,7 @@ nsBrowserAccess.prototype = {
newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null);
break;
case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB :
- let browser = this._openURIInNewTab(aURI, aOpener, isExternal);
+ let browser = this._openURIInNewTab(aURI, aOpener, isExternal, true);
if (browser)
newWindow = browser.contentWindow;
break;
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index b0261c5b8fb0..5c99c1423a9d 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -483,3 +483,4 @@ skip-if = e10s
skip-if = e10s # Bug ?????? - test directly manipulates content (content.document.getElementById)
[browser_bug1045809.js]
skip-if = e10s
+[browser_bug1047603.js]
diff --git a/browser/base/content/test/general/browser_bug1047603.js b/browser/base/content/test/general/browser_bug1047603.js
new file mode 100644
index 000000000000..8dce62150307
--- /dev/null
+++ b/browser/base/content/test/general/browser_bug1047603.js
@@ -0,0 +1,139 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const OPEN_LOCATION_PREF = "browser.link.open_newwindow";
+const NON_REMOTE_PAGE = "about:crashes";
+
+const SIMPLE_PAGE_HTML = `
+Open a window
+`;
+
+function frame_script() {
+ addMessageListener("test:click", (message) => {
+ let element = content.document.getElementById("testAnchor");
+ element.click();
+ });
+ sendAsyncMessage("test:ready");
+}
+
+/**
+ * Returns a Promise that resolves once the frame_script is loaded
+ * in the browser, and has seen the DOMContentLoaded event.
+ */
+function waitForFrameScriptReady(mm) {
+ return new Promise((resolve, reject) => {
+ mm.addMessageListener("test:ready", function onTestReady() {
+ mm.removeMessageListener("test:ready", onTestReady);
+ resolve();
+ });
+ });
+}
+
+/**
+ * Takes some browser in some window, and forces that browser
+ * to become non-remote, and then navigates it to a page that
+ * we're not supposed to be displaying remotely. Returns a
+ * Promise that resolves when the browser is no longer remote.
+ */
+function prepareNonRemoteBrowser(aWindow, browser) {
+ aWindow.gBrowser.updateBrowserRemoteness(browser, false);
+ browser.loadURI(NON_REMOTE_PAGE);
+ return new Promise((resolve, reject) => {
+ waitForCondition(() => !browser.isRemoteBrowser, () => {
+ resolve();
+ }, "Waiting for browser to become non-remote");
+ })
+}
+
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(OPEN_LOCATION_PREF);
+});
+
+/**
+ * Test that if we open a new tab from a link in a non-remote
+ * browser in an e10s window, that the new tab's browser is also
+ * not remote. Also tests with a private browsing window.
+ */
+add_task(function* test_new_tab() {
+ let normalWindow = yield promiseOpenAndLoadWindow({
+ remote: true
+ }, true);
+ let privateWindow = yield promiseOpenAndLoadWindow({
+ remote: true,
+ private: true,
+ }, true);
+
+ for (let testWindow of [normalWindow, privateWindow]) {
+ let testBrowser = testWindow.gBrowser.selectedBrowser;
+ yield prepareNonRemoteBrowser(testWindow, testBrowser);
+
+ // Get our framescript ready
+ let mm = testBrowser.messageManager;
+ mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true);
+ let readyPromise = waitForFrameScriptReady(mm);
+ yield readyPromise;
+
+ // Inject our test HTML into our non-remote tab.
+ testBrowser.contentDocument.body.innerHTML = SIMPLE_PAGE_HTML;
+
+ // Click on the link in the browser, and wait for the new tab.
+ mm.sendAsyncMessage("test:click");
+ let tabOpenEvent = yield waitForNewTab(testWindow.gBrowser);
+ let newTab = tabOpenEvent.target;
+ ok(!newTab.linkedBrowser.isRemoteBrowser,
+ "The opened browser should not be remote.");
+
+ testWindow.gBrowser.removeTab(newTab);
+ }
+
+ normalWindow.close();
+ privateWindow.close();
+});
+
+/**
+ * Test that if we open a new window from a link in a non-remote
+ * browser in an e10s window, that the new window is not an e10s
+ * window. Also tests with a private browsing window.
+ */
+add_task(function* test_new_window() {
+ let normalWindow = yield promiseOpenAndLoadWindow({
+ remote: true
+ }, true);
+ let privateWindow = yield promiseOpenAndLoadWindow({
+ remote: true,
+ private: true,
+ }, true);
+
+ // Fiddle with the prefs so that we open target="_blank" links
+ // in new windows instead of new tabs.
+ Services.prefs.setIntPref(OPEN_LOCATION_PREF,
+ Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW);
+
+ for (let testWindow of [normalWindow, privateWindow]) {
+ let testBrowser = testWindow.gBrowser.selectedBrowser;
+ yield prepareNonRemoteBrowser(testWindow, testBrowser);
+
+ // Get our framescript ready
+ let mm = testBrowser.messageManager;
+ mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", true);
+ let readyPromise = waitForFrameScriptReady(mm);
+ yield readyPromise;
+
+ // Inject our test HTML into our non-remote window.
+ testBrowser.contentDocument.body.innerHTML = SIMPLE_PAGE_HTML;
+
+ // Click on the link in the browser, and wait for the new window.
+ let windowOpenPromise = promiseTopicObserved("browser-delayed-startup-finished");
+ mm.sendAsyncMessage("test:click");
+ let [newWindow] = yield windowOpenPromise;
+ ok(!newWindow.gMultiProcessBrowser,
+ "The opened window should not be an e10s window.");
+ newWindow.close();
+ }
+
+ normalWindow.close();
+ privateWindow.close();
+
+ Services.prefs.clearUserPref(OPEN_LOCATION_PREF);
+});
diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js
index 3e45642f45f8..5f15a517d286 100644
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -665,3 +665,7 @@ function assertWebRTCIndicatorStatus(expected) {
}
}
}
+
+function waitForNewTab(aTabBrowser) {
+ return promiseWaitForEvent(aTabBrowser.tabContainer, "TabOpen");
+}
diff --git a/xpfe/appshell/nsAppShellService.cpp b/xpfe/appshell/nsAppShellService.cpp
index 5da29064e39c..a39fb40d8c8d 100644
--- a/xpfe/appshell/nsAppShellService.cpp
+++ b/xpfe/appshell/nsAppShellService.cpp
@@ -630,7 +630,7 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
}
if (parentContext) {
- isUsingRemoteTabs = parentContext->UseRemoteTabs();
+ isUsingRemoteTabs = parentContext->UseRemoteTabs() && aOpeningTab;
}
nsCOMPtr newDomWin =