зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1326779
- [e10s] Fire beforeunload event when navigating to a page in different process. r=smaug
--HG-- extra : rebase_source : f1268fbb9c2725e79fef2d6627e9e11e6e000acc
This commit is contained in:
Родитель
6a817e71fd
Коммит
cb707ac950
|
@ -872,6 +872,12 @@ function _loadURIWithFlags(browser, uri, params) {
|
|||
referrer, referrerPolicy,
|
||||
postData, null, null);
|
||||
} else {
|
||||
// Check if the current browser is allowed to unload.
|
||||
let {permitUnload, timedOut} = browser.permitUnload();
|
||||
if (!timedOut && !permitUnload) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (postData) {
|
||||
postData = NetUtil.readInputStreamToString(postData, postData.available());
|
||||
}
|
||||
|
|
|
@ -10467,25 +10467,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
}
|
||||
}
|
||||
|
||||
// Check if the webbrowser chrome wants the load to proceed; this can be
|
||||
// used to cancel attempts to load URIs in the wrong process.
|
||||
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
|
||||
if (browserChrome3) {
|
||||
// In case this is a remote newtab load, set aURI to aOriginalURI (newtab).
|
||||
// This ensures that the verifySignedContent flag is set on loadInfo in
|
||||
// DoURILoad.
|
||||
nsIURI* uriForShouldLoadCheck = aURI;
|
||||
if (IsAboutNewtab(aOriginalURI)) {
|
||||
uriForShouldLoadCheck = aOriginalURI;
|
||||
}
|
||||
bool shouldLoad;
|
||||
rv = browserChrome3->ShouldLoadURI(this, uriForShouldLoadCheck, aReferrer,
|
||||
&shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// mContentViewer->PermitUnload can destroy |this| docShell, which
|
||||
// causes the next call of CanSavePresentation to crash.
|
||||
// Hold onto |this| until we return, to prevent a crash from happening.
|
||||
|
@ -10524,6 +10505,25 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
mTiming->NotifyUnloadAccepted(mCurrentURI);
|
||||
}
|
||||
|
||||
// Check if the webbrowser chrome wants the load to proceed; this can be
|
||||
// used to cancel attempts to load URIs in the wrong process.
|
||||
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
|
||||
if (browserChrome3) {
|
||||
// In case this is a remote newtab load, set aURI to aOriginalURI (newtab).
|
||||
// This ensures that the verifySignedContent flag is set on loadInfo in
|
||||
// DoURILoad.
|
||||
nsIURI* uriForShouldLoadCheck = aURI;
|
||||
if (IsAboutNewtab(aOriginalURI)) {
|
||||
uriForShouldLoadCheck = aOriginalURI;
|
||||
}
|
||||
bool shouldLoad;
|
||||
rv = browserChrome3->ShouldLoadURI(this, uriForShouldLoadCheck, aReferrer,
|
||||
&shouldLoad);
|
||||
if (NS_SUCCEEDED(rv) && !shouldLoad) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (browserChrome3 && aCheckForPrerender) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
|
||||
|
|
|
@ -19,6 +19,8 @@ disabled = Does not reliably pass on 32-bit systems - bug 1314098
|
|||
skip-if = !e10s
|
||||
[browser_autofocus_background.js]
|
||||
[browser_autofocus_preference.js]
|
||||
[browser_beforeunload_between_chrome_content.js]
|
||||
skip-if = !e10s
|
||||
[browser_bug396843.js]
|
||||
[browser_bug1004814.js]
|
||||
[browser_bug1008941_dismissGeolocationHanger.js]
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
const TEST_URL = "http://www.example.com/browser/dom/tests/browser/dummy.html";
|
||||
|
||||
function pageScript() {
|
||||
window.addEventListener("beforeunload", function (event) {
|
||||
var str = "Leaving?";
|
||||
event.returnValue = str;
|
||||
return str;
|
||||
}, true);
|
||||
}
|
||||
|
||||
function frameScript() {
|
||||
content.window.addEventListener("beforeunload", function (event) {
|
||||
sendAsyncMessage("Test:OnBeforeUnloadReceived");
|
||||
var str = "Leaving?";
|
||||
event.returnValue = str;
|
||||
return str;
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Wait for onbeforeunload dialog, and dismiss it immediately.
|
||||
function awaitAndCloseBeforeUnloadDialog(doStayOnPage) {
|
||||
return new Promise(resolve => {
|
||||
function onDialogShown(node) {
|
||||
Services.obs.removeObserver(onDialogShown, "tabmodal-dialog-loaded");
|
||||
let button = doStayOnPage ? node.ui.button1 : node.ui.button0;
|
||||
button.click();
|
||||
resolve();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
|
||||
});
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
/**
|
||||
* Test navigation from a content page to a chrome page. Also check that only
|
||||
* one beforeunload event is fired.
|
||||
*/
|
||||
add_task(function* () {
|
||||
let beforeUnloadCount = 0;
|
||||
messageManager.addMessageListener("Test:OnBeforeUnloadReceived", function() {
|
||||
beforeUnloadCount++;
|
||||
});
|
||||
|
||||
// Open a content page.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
ok(browser.isRemoteBrowser, "Browser should be remote.");
|
||||
browser.messageManager.loadFrameScript(
|
||||
"data:,(" + frameScript.toString() + ")();", true);
|
||||
|
||||
// Navigate to a chrome page.
|
||||
let dialogShown1 = awaitAndCloseBeforeUnloadDialog(false);
|
||||
yield BrowserTestUtils.loadURI(browser, "about:support");
|
||||
yield Promise.all([
|
||||
dialogShown1,
|
||||
BrowserTestUtils.browserLoaded(browser)
|
||||
]);
|
||||
is(beforeUnloadCount, 1, "Should have received one beforeunload event.");
|
||||
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
|
||||
|
||||
// Go back to content page.
|
||||
ok(gBrowser.webNavigation.canGoBack, "Should be able to go back.");
|
||||
gBrowser.goBack();
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
browser.messageManager.loadFrameScript(
|
||||
"data:,(" + frameScript.toString() + ")();", true);
|
||||
|
||||
// Test that going forward triggers beforeunload prompt as well.
|
||||
ok(gBrowser.webNavigation.canGoForward, "Should be able to go forward.");
|
||||
let dialogShown2 = awaitAndCloseBeforeUnloadDialog(false);
|
||||
gBrowser.goForward();
|
||||
yield Promise.all([
|
||||
dialogShown2,
|
||||
BrowserTestUtils.browserLoaded(browser)
|
||||
]);
|
||||
is(beforeUnloadCount, 2, "Should have received two beforeunload events.");
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test navigation from a chrome page to a content page. Also check that only
|
||||
* one beforeunload event is fired.
|
||||
*/
|
||||
add_task(function* () {
|
||||
let beforeUnloadCount = 0;
|
||||
messageManager.addMessageListener("Test:OnBeforeUnloadReceived", function() {
|
||||
beforeUnloadCount++;
|
||||
});
|
||||
|
||||
// Open a chrome page.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||
"about:support");
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
ok(!browser.isRemoteBrowser, "Browser should not be remote.");
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
content.window.addEventListener("beforeunload", function (event) {
|
||||
sendAsyncMessage("Test:OnBeforeUnloadReceived");
|
||||
var str = "Leaving?";
|
||||
event.returnValue = str;
|
||||
return str;
|
||||
}, true);
|
||||
});
|
||||
|
||||
// Navigate to a content page.
|
||||
let dialogShown1 = awaitAndCloseBeforeUnloadDialog(false);
|
||||
yield BrowserTestUtils.loadURI(browser, TEST_URL);
|
||||
yield Promise.all([
|
||||
dialogShown1,
|
||||
BrowserTestUtils.browserLoaded(browser)
|
||||
]);
|
||||
is(beforeUnloadCount, 1, "Should have received one beforeunload event.");
|
||||
ok(browser.isRemoteBrowser, "Browser should be remote.");
|
||||
|
||||
// Go back to chrome page.
|
||||
ok(gBrowser.webNavigation.canGoBack, "Should be able to go back.");
|
||||
gBrowser.goBack();
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
yield ContentTask.spawn(browser, null, function* () {
|
||||
content.window.addEventListener("beforeunload", function (event) {
|
||||
sendAsyncMessage("Test:OnBeforeUnloadReceived");
|
||||
var str = "Leaving?";
|
||||
event.returnValue = str;
|
||||
return str;
|
||||
}, true);
|
||||
});
|
||||
|
||||
// Test that going forward triggers beforeunload prompt as well.
|
||||
ok(gBrowser.webNavigation.canGoForward, "Should be able to go forward.");
|
||||
let dialogShown2 = awaitAndCloseBeforeUnloadDialog(false);
|
||||
gBrowser.goForward();
|
||||
yield Promise.all([
|
||||
dialogShown2,
|
||||
BrowserTestUtils.browserLoaded(browser)
|
||||
]);
|
||||
is(beforeUnloadCount, 2, "Should have received two beforeunload events.");
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
});
|
Загрузка…
Ссылка в новой задаче