mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-15 04:39:31 +00:00
Bug 1415918 - Allow discarding browsers that have beforeunload handlers in tabbrowser.discardBrowser. r=bz
MozReview-Commit-ID: 5KQcrOQTSpK
This commit is contained in:
parent
ecd94ed690
commit
25bd05b91c
@ -2539,19 +2539,22 @@
|
||||
|
||||
<method name="discardBrowser">
|
||||
<parameter name="aBrowser"/>
|
||||
<parameter name="aForceDiscard"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
"use strict";
|
||||
|
||||
let tab = this.getTabForBrowser(aBrowser);
|
||||
|
||||
let permitUnloadFlags = aForceDiscard ? aBrowser.dontPromptAndUnload : aBrowser.dontPromptAndDontUnload;
|
||||
|
||||
if (!tab ||
|
||||
tab.selected ||
|
||||
tab.closing ||
|
||||
this._windowIsClosing ||
|
||||
!aBrowser.isConnected ||
|
||||
!aBrowser.isRemoteBrowser ||
|
||||
aBrowser.frameLoader.tabParent.hasBeforeUnload) {
|
||||
!aBrowser.permitUnload(permitUnloadFlags).permitUnload) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ support-files =
|
||||
restore_redirect_target.html
|
||||
browser_1234021_page.html
|
||||
browser_1284886_suspend_tab.html
|
||||
browser_1284886_suspend_tab_2.html
|
||||
|
||||
#NB: the following are disabled
|
||||
# browser_464620_a.html
|
||||
|
@ -2,6 +2,12 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(async function test() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.require_user_interaction_for_beforeunload", false],
|
||||
]
|
||||
});
|
||||
|
||||
let url = "about:robots";
|
||||
let tab0 = gBrowser.tabs[0];
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
@ -23,18 +29,35 @@ add_task(async function test() {
|
||||
|
||||
gBrowser._endRemoveTab(tab1);
|
||||
|
||||
// Test that tab with beforeunload handler is not able to be suspended.
|
||||
// Open tab containing a page which has a beforeunload handler which shows a prompt.
|
||||
url = "http://example.com/browser/browser/components/sessionstore/test/browser_1284886_suspend_tab.html";
|
||||
|
||||
tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser1 = tab1.linkedBrowser;
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab0);
|
||||
|
||||
gBrowser.discardBrowser(tab1.linkedBrowser);
|
||||
ok(tab1.linkedPanel, "cannot suspend a tab with beforeunload handler");
|
||||
// Test that tab with beforeunload handler which would show a prompt cannot be suspended.
|
||||
gBrowser.discardBrowser(browser1);
|
||||
ok(tab1.linkedPanel, "cannot suspend a tab with beforeunload handler which would show a prompt");
|
||||
|
||||
// Test that tab with beforeunload handler which would show a prompt will be suspended if forced.
|
||||
gBrowser.discardBrowser(browser1, true);
|
||||
ok(!tab1.linkedPanel, "force suspending a tab with beforeunload handler which would show a prompt");
|
||||
|
||||
await promiseRemoveTab(tab1);
|
||||
|
||||
// Test that remote tab is not able to be suspended.
|
||||
// Open tab containing a page which has a beforeunload handler which does not show a prompt.
|
||||
url = "http://example.com/browser/browser/components/sessionstore/test/browser_1284886_suspend_tab_2.html";
|
||||
tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
browser1 = tab1.linkedBrowser;
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab0);
|
||||
|
||||
// Test that tab with beforeunload handler which would not show a prompt can be suspended.
|
||||
gBrowser.discardBrowser(browser1);
|
||||
ok(!tab1.linkedPanel, "can suspend a tab with beforeunload handler which would not show a prompt");
|
||||
|
||||
await promiseRemoveTab(tab1);
|
||||
|
||||
// Test that non-remote tab is not able to be suspended.
|
||||
url = "about:robots";
|
||||
tab1 = BrowserTestUtils.addTab(gBrowser, url, { forceNotRemote: true });
|
||||
await promiseBrowserLoaded(tab1.linkedBrowser, true, url);
|
||||
|
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
</body>
|
||||
</html>
|
@ -50,10 +50,35 @@ interface nsIContentViewer : nsISupports
|
||||
[noscript] readonly attribute boolean isStopped;
|
||||
|
||||
/**
|
||||
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||
* the document, and if it does, prompts the user. The result is returned.
|
||||
* aPermitUnloadFlags are passed to PermitUnload to indicate what action to take
|
||||
* if a beforeunload handler wants to prompt the user. It is also used by
|
||||
* permitUnloadInternal to ensure we only prompt once.
|
||||
*
|
||||
* ePrompt: Prompt and return the user's choice (default).
|
||||
* eDontPromptAndDontUnload: Don't prompt and return false (unload not permitted)
|
||||
* if the document (or its children) asks us to prompt.
|
||||
* eDontPromptAndUnload: Don't prompt and return true (unload permitted) no matter what.
|
||||
*/
|
||||
boolean permitUnload();
|
||||
const unsigned long ePrompt = 0;
|
||||
const unsigned long eDontPromptAndDontUnload = 1;
|
||||
const unsigned long eDontPromptAndUnload = 2;
|
||||
|
||||
/**
|
||||
* Overload PermitUnload method for C++ consumers with no aPermitUnloadFlags
|
||||
* argument.
|
||||
*/
|
||||
%{C++
|
||||
nsresult PermitUnload(bool* canUnload) {
|
||||
return PermitUnload(ePrompt, canUnload);
|
||||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||
* the document, and if it does, takes action directed by aPermitUnloadFlags.
|
||||
* The result is returned.
|
||||
*/
|
||||
boolean permitUnload([optional] in unsigned long aPermitUnloadFlags);
|
||||
|
||||
/**
|
||||
* Exposes whether we're blocked in a call to permitUnload.
|
||||
@ -61,11 +86,11 @@ interface nsIContentViewer : nsISupports
|
||||
readonly attribute boolean inPermitUnload;
|
||||
|
||||
/**
|
||||
* As above, but this passes around the aShouldPrompt argument to keep
|
||||
* As above, but this passes around the aPermitUnloadFlags argument to keep
|
||||
* track of whether the user has responded to a prompt.
|
||||
* Used internally by the scriptable version to ensure we only prompt once.
|
||||
*/
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout boolean aShouldPrompt);
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout unsigned long aPermitUnloadFlags);
|
||||
|
||||
/**
|
||||
* Exposes whether we're in the process of firing the beforeunload event.
|
||||
|
@ -39,6 +39,11 @@ support-files =
|
||||
file_bug1328501.html
|
||||
file_bug1328501_frame.html
|
||||
file_bug1328501_framescript.js
|
||||
file_bug1415918_beforeunload_2.html
|
||||
file_bug1415918_beforeunload_3.html
|
||||
file_bug1415918_beforeunload_iframe_2.html
|
||||
file_bug1415918_beforeunload_iframe.html
|
||||
file_bug1415918_beforeunload.html
|
||||
file_multiple_pushState.html
|
||||
print_postdata.sjs
|
||||
test-form_sjis.html
|
||||
@ -56,6 +61,7 @@ support-files =
|
||||
[browser_bug1328501.js]
|
||||
[browser_bug1347823.js]
|
||||
[browser_bug134911.js]
|
||||
[browser_bug1415918_beforeunload_options.js]
|
||||
[browser_bug234628-1.js]
|
||||
[browser_bug234628-10.js]
|
||||
[browser_bug234628-11.js]
|
||||
|
242
docshell/test/browser/browser_bug1415918_beforeunload_options.js
Normal file
242
docshell/test/browser/browser_bug1415918_beforeunload_options.js
Normal file
@ -0,0 +1,242 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
|
||||
|
||||
add_task(async function test() {
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.require_user_interaction_for_beforeunload", false],
|
||||
]
|
||||
});
|
||||
|
||||
let url = TEST_PATH + "file_bug1415918_beforeunload.html";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser = tab.linkedBrowser;
|
||||
let stack = browser.parentNode;
|
||||
let buttonId;
|
||||
let promptShown = false;
|
||||
|
||||
let observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (buttonId && mutation.type == "attributes" && browser.hasAttribute("tabmodalPromptShowing")) {
|
||||
let prompt = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt")[0];
|
||||
document.getAnonymousElementByAttribute(prompt, "anonid", buttonId).click();
|
||||
promptShown = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(browser, { attributes: true });
|
||||
|
||||
/*
|
||||
* Check condition where beforeunload handlers request a prompt.
|
||||
*/
|
||||
|
||||
// Prompt is shown, user clicks OK.
|
||||
buttonId = "button0";
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is shown, user clicks CANCEL.
|
||||
buttonId = "button1";
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload().permitUnload, "permit unload should be false");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
buttonId = "";
|
||||
|
||||
// Check that only the parent beforeunload handler fired, and reset attribute.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(!frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should not fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is not shown, don't permit unload.
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be false");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that only the parent beforeunload handler fired, and reset attribute.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(!frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should not fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is not shown, permit unload.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Check condition where no one requests a prompt. In all cases,
|
||||
* permitUnload should be true, and all handlers fired.
|
||||
*/
|
||||
|
||||
buttonId = "button0";
|
||||
url = TEST_PATH + "file_bug1415918_beforeunload_2.html";
|
||||
browser.loadURI(url);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
buttonId = "";
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Check condition where the parent beforeunload handler does not request a prompt,
|
||||
* but a child beforeunload handler does.
|
||||
*/
|
||||
|
||||
buttonId = "button0";
|
||||
url = TEST_PATH + "file_bug1415918_beforeunload_3.html";
|
||||
browser.loadURI(url);
|
||||
await BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
|
||||
// Prompt is shown, user clicks OK.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload().permitUnload, "permit unload should be true");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired and reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
});
|
||||
|
||||
// Prompt is shown, user clicks CANCEL.
|
||||
buttonId = "button1";
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload().permitUnload, "permit unload should be false");
|
||||
ok(promptShown, "prompt should have been displayed");
|
||||
buttonId = "";
|
||||
|
||||
// Check that the parent beforeunload handler fired, and only one child beforeunload
|
||||
// handler fired. Reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
let count = 0;
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
if (frame.document.body.hasAttribute("fired")) {
|
||||
count++;
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
}
|
||||
is(count, 1, "only one frame document beforeunload handler should fire");
|
||||
});
|
||||
|
||||
// Prompt is not shown, don't permit unload.
|
||||
promptShown = false;
|
||||
ok(!browser.permitUnload(browser.dontPromptAndDontUnload).permitUnload, "permit unload should be false");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that the parent beforeunload handler fired, and only one child beforeunload
|
||||
// handler fired. Reset attributes.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
content.window.document.body.removeAttribute("fired");
|
||||
|
||||
let count = 0;
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
if (frame.document.body.hasAttribute("fired")) {
|
||||
count++;
|
||||
frame.document.body.removeAttribute("fired");
|
||||
}
|
||||
}
|
||||
is(count, 1, "only one frame document beforeunload handler should fire");
|
||||
});
|
||||
|
||||
// Prompt is not shown, permit unload.
|
||||
promptShown = false;
|
||||
ok(browser.permitUnload(browser.dontPromptAndUnload).permitUnload, "permit unload should be true");
|
||||
ok(!promptShown, "prompt should not have been displayed");
|
||||
|
||||
// Check that all beforeunload handlers fired.
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
ok(content.window.document.body.hasAttribute("fired"), "parent document beforeunload handler should fire");
|
||||
|
||||
for (let frame of Array.from(content.window.frames)) {
|
||||
ok(frame.document.body.hasAttribute("fired"), "frame document beforeunload handler should fire");
|
||||
}
|
||||
});
|
||||
|
||||
// Remove tab.
|
||||
buttonId = "button0";
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
22
docshell/test/browser/file_bug1415918_beforeunload.html
Normal file
22
docshell/test/browser/file_bug1415918_beforeunload.html
Normal file
@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
return "Parent document prompt";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
21
docshell/test/browser/file_bug1415918_beforeunload_2.html
Normal file
21
docshell/test/browser/file_bug1415918_beforeunload_2.html
Normal file
@ -0,0 +1,21 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe_2.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe_2.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
21
docshell/test/browser/file_bug1415918_beforeunload_3.html
Normal file
21
docshell/test/browser/file_bug1415918_beforeunload_3.html
Normal file
@ -0,0 +1,21 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #f00;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
TEST PAGE
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
<iframe style="width: 150px; height: 60px" src="file_bug1415918_beforeunload_iframe.html">
|
||||
</iframe>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #0f0;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
return "Frame document prompt";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
</body>
|
||||
FRAME
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body[fired] {
|
||||
background-color: #0f0;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onbeforeunload = function() {
|
||||
document.body.setAttribute("fired", true);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
</body>
|
||||
FRAME
|
||||
</body>
|
||||
</html>
|
@ -1144,15 +1144,14 @@ nsDocumentViewer::GetIsStopped(bool* aOutIsStopped)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentViewer::PermitUnload(bool *aPermitUnload)
|
||||
nsDocumentViewer::PermitUnload(uint32_t aPermitUnloadFlags, bool *aPermitUnload)
|
||||
{
|
||||
bool shouldPrompt = true;
|
||||
return PermitUnloadInternal(&shouldPrompt, aPermitUnload);
|
||||
return PermitUnloadInternal(&aPermitUnloadFlags, aPermitUnload);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
||||
nsDocumentViewer::PermitUnloadInternal(uint32_t *aPermitUnloadFlags,
|
||||
bool *aPermitUnload)
|
||||
{
|
||||
AutoDontWarnAboutSyncXHR disableSyncXHRWarning;
|
||||
@ -1238,12 +1237,23 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
||||
nsAutoString text;
|
||||
event->GetReturnValue(text);
|
||||
|
||||
if (sIsBeforeUnloadDisabled) {
|
||||
*aPermitUnloadFlags = eDontPromptAndUnload;
|
||||
}
|
||||
|
||||
// NB: we nullcheck mDocument because it might now be dead as a result of
|
||||
// the event being dispatched.
|
||||
if (!sIsBeforeUnloadDisabled && *aShouldPrompt && dialogsAreEnabled &&
|
||||
if (*aPermitUnloadFlags != eDontPromptAndUnload && dialogsAreEnabled &&
|
||||
mDocument && !(mDocument->GetSandboxFlags() & SANDBOXED_MODALS) &&
|
||||
(!sBeforeUnloadRequiresInteraction || mDocument->UserHasInteracted()) &&
|
||||
(event->WidgetEventPtr()->DefaultPrevented() || !text.IsEmpty())) {
|
||||
// If the consumer wants prompt requests to just stop unloading, we don't
|
||||
// need to prompt and can return immediately.
|
||||
if (*aPermitUnloadFlags == eDontPromptAndDontUnload) {
|
||||
*aPermitUnload = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Ask the user if it's ok to unload the current page
|
||||
|
||||
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(docShell);
|
||||
@ -1322,7 +1332,7 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
||||
// If the user decided to go ahead, make sure not to prompt the user again
|
||||
// by toggling the internal prompting bool to false:
|
||||
if (*aPermitUnload) {
|
||||
*aShouldPrompt = false;
|
||||
*aPermitUnloadFlags = eDontPromptAndUnload;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1342,7 +1352,7 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt,
|
||||
docShell->GetContentViewer(getter_AddRefs(cv));
|
||||
|
||||
if (cv) {
|
||||
cv->PermitUnloadInternal(aShouldPrompt, aPermitUnload);
|
||||
cv->PermitUnloadInternal(aPermitUnloadFlags, aPermitUnload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ addMessageListener("PermitUnload", msg => {
|
||||
|
||||
let permitUnload = true;
|
||||
if (docShell && docShell.contentViewer) {
|
||||
permitUnload = docShell.contentViewer.permitUnload();
|
||||
permitUnload = docShell.contentViewer.permitUnload(msg.data.aPermitUnloadFlags);
|
||||
}
|
||||
|
||||
sendAsyncMessage("PermitUnload", {id: msg.data.id, kind: "end", permitUnload});
|
||||
|
@ -1594,13 +1594,23 @@
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="dontPromptAndDontUnload"
|
||||
onget="return 1;"
|
||||
readonly="true"/>
|
||||
|
||||
<property name="dontPromptAndUnload"
|
||||
onget="return 2;"
|
||||
readonly="true"/>
|
||||
|
||||
<method name="permitUnload">
|
||||
<parameter name="aPermitUnloadFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this.docShell || !this.docShell.contentViewer) {
|
||||
return {permitUnload: true, timedOut: false};
|
||||
}
|
||||
return {permitUnload: this.docShell.contentViewer.permitUnload(), timedOut: false};
|
||||
return {permitUnload: this.docShell.contentViewer.permitUnload(aPermitUnloadFlags),
|
||||
timedOut: false};
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -285,6 +285,7 @@
|
||||
</method>
|
||||
|
||||
<method name="permitUnload">
|
||||
<parameter name="aPermitUnloadFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
let {tabParent} = this.frameLoader;
|
||||
@ -326,7 +327,7 @@
|
||||
Services.obs.removeObserver(observer, "message-manager-close");
|
||||
}
|
||||
|
||||
mm.sendAsyncMessage("PermitUnload", {id});
|
||||
mm.sendAsyncMessage("PermitUnload", {id, aPermitUnloadFlags});
|
||||
mm.addMessageListener("PermitUnload", msgListener);
|
||||
Services.obs.addObserver(observer, "message-manager-close");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user