Bug 1731210 - pdf.js modal for unsaved data on a pdf page appears twice in private window r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D153612
This commit is contained in:
lyavor 2022-12-20 13:31:07 +00:00
Родитель 64ff8a555a
Коммит b28d8cdf5f
4 изменённых файлов: 246 добавлений и 1 удалений

Просмотреть файл

@ -9488,7 +9488,36 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
if (!isJavaScript && isNotDownload &&
!aLoadState->NotifiedBeforeUnloadListeners() && mContentViewer) {
bool okToUnload;
rv = mContentViewer->PermitUnload(&okToUnload);
// Check if request is exempted from HTTPSOnlyMode and if https-first is
// enabled, if so it means:
// * https-first failed to upgrade request to https
// * we already asked for permission to unload and the user accepted
// otherwise we wouldn't be here.
bool isPrivateWin = GetOriginAttributes().mPrivateBrowsingId > 0;
bool isHistoryOrReload = false;
uint32_t loadType = aLoadState->LoadType();
// Check if request is a reload.
if (loadType == LOAD_RELOAD_NORMAL ||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
loadType == LOAD_HISTORY) {
isHistoryOrReload = true;
}
// If it isn't a reload, the request already failed to be upgraded and
// https-first is enabled then don't ask the user again for permission to
// unload and just unload.
if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSOnlyMode() &&
nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
rv = mContentViewer->PermitUnload(
nsIContentViewer::PermitUnloadAction::eDontPromptAndUnload,
&okToUnload);
} else {
rv = mContentViewer->PermitUnload(&okToUnload);
}
if (NS_SUCCEEDED(rv) && !okToUnload) {
// The user chose not to unload the page, interrupt the

Просмотреть файл

@ -31,3 +31,5 @@ support-files =
pass.png
test.ogv
test.wav
[browser_beforeunload_permit_http.js]
support-files = file_beforeunload_permit_http.html

Просмотреть файл

@ -0,0 +1,205 @@
"use strict";
const { PromptTestUtils } = ChromeUtils.import(
"resource://testing-common/PromptTestUtils.jsm"
);
const TEST_PATH_HTTP = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
"http://nocert.example.com/"
);
/*
* Description of Tests:
*
* Test load page and reload:
* 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
* 2. Open an HTTP site. HTTPS-First will try to upgrade it to https - but since it has no cert that try will fail
* 3. Then simulated user interaction and reload the page with a reload flag.
* 4. That should lead to a beforeUnload prompt that asks for users permission to perform reload. HTTPS-First should not try to upgrade the reload again
*
* Test Navigation:
* 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
* 2. Open an http site. HTTPS-First will try to upgrade it to https - but since it has no cert for https that try will fail
* 3. Then simulated user interaction and navigate to another http page. Again HTTPS-First will try to upgrade to HTTPS
* 4. This attempted navigation leads to a prompt which askes for permission to leave page - accept it
* 5. Since the site is not using a valid HTTPS cert HTTPS-First will downgrade the request back to HTTP
* 6. User should NOT get asked again for permission to unload
*
* Test Session History Navigation:
* 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
* 2. Open an http site. HTTPS-First will try to upgrade it to https - but since it has no cert for https that try will fail
* 3. Then navigate to another http page and simulated a user interaction.
* 4. Trigger a session history navigation by clicking the "back button".
* 5. This attempted navigation leads to a prompt which askes for permission to leave page - accept it
*/
add_setup(async function() {
await SpecialPowers.pushPrefEnv({
set: [
["dom.security.https_first", true],
["dom.require_user_interaction_for_beforeunload", true],
],
});
});
const TESTS = [
{
name: "Normal Reload (No flag)",
reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
},
{
name: "Bypass Cache Reload",
reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE,
},
{
name: "Bypass Proxy Reload",
reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY,
},
{
name: "Bypass Cache and Proxy Reload",
reloadFlag:
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE |
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY,
},
];
add_task(async function testReloadFlags() {
for (let index = 0; index < TESTS.length; index++) {
const testCase = TESTS[index];
// The onbeforeunload dialog should appear
let dialogPromise = PromptTestUtils.waitForPrompt(null, {
modalType: Services.prompt.MODAL_TYPE_CONTENT,
promptType: "confirmEx",
});
let reloadPromise = loadPageAndReload(testCase);
let dialog = await dialogPromise;
Assert.ok(true, "Showed the beforeunload dialog.");
await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
await reloadPromise;
}
});
add_task(async function testNavigation() {
// The onbeforeunload dialog should appear
let dialogPromise = PromptTestUtils.waitForPrompt(null, {
modalType: Services.prompt.MODAL_TYPE_CONTENT,
promptType: "confirmEx",
});
let openPagePromise = openPage();
let dialog = await dialogPromise;
Assert.ok(true, "Showed the beforeunload dialog.");
await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
await openPagePromise;
});
add_task(async function testSessionHistoryNavigation() {
// The onbeforeunload dialog should appear
let dialogPromise = PromptTestUtils.waitForPrompt(null, {
modalType: Services.prompt.MODAL_TYPE_CONTENT,
promptType: "confirmEx",
});
let openPagePromise = loadPagesAndUseBackButton();
let dialog = await dialogPromise;
Assert.ok(true, "Showed the beforeunload dialog.");
await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
await openPagePromise;
});
async function openPage() {
// Open about:blank in a new tab
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
// Load http page
BrowserTestUtils.loadURI(
browser,
`${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
);
await BrowserTestUtils.browserLoaded(browser);
// Interact with page such that unload permit will be necessary
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
let hasInteractedWith = await SpecialPowers.spawn(
browser,
[""],
function() {
return content.document.userHasInteracted;
}
);
is(true, hasInteractedWith, "Simulated successfully user interaction");
// And then navigate away to another site which proves that user won't be asked twice to permit a reload (otherwise the test get timed out)
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
BrowserTestUtils.loadURI(browser, "http://self-signed.example.com/");
await BrowserTestUtils.browserLoaded(browser);
Assert.ok(true, "Navigated successfully.");
}
);
}
async function loadPageAndReload(testCase) {
// Load initial site
// Open about:blank in a new tab
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
BrowserTestUtils.loadURI(
browser,
`${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
);
await BrowserTestUtils.browserLoaded(browser);
// Interact with page such that unload permit will be necessary
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
let hasInteractedWith = await SpecialPowers.spawn(
browser,
[""],
function() {
return content.document.userHasInteracted;
}
);
is(true, hasInteractedWith, "Simulated successfully user interaction");
BrowserReloadWithFlags(testCase.reloadFlag);
await BrowserTestUtils.browserLoaded(browser);
is(true, true, `reload with flag ${testCase.name} was successful`);
}
);
}
async function loadPagesAndUseBackButton() {
// Load initial site
// Open about:blank in a new tab
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
BrowserTestUtils.loadURI(
browser,
`${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
);
await BrowserTestUtils.browserLoaded(browser);
BrowserTestUtils.loadURI(
browser,
`${TEST_PATH_HTTP}file_beforeunload_permit_http.html?getASessionHistoryEntry`
);
await BrowserTestUtils.browserLoaded(browser);
// Interact with page such that unload permit will be necessary
await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
let hasInteractedWith = await SpecialPowers.spawn(
browser,
[""],
function() {
return content.document.userHasInteracted;
}
);
is(true, hasInteractedWith, "Simulated successfully user interaction");
// Go back one site by clicking the back button
info("Clicking back button");
let backButton = document.getElementById("back-button");
backButton.click();
await BrowserTestUtils.browserLoaded(browser);
is(true, true, `Got back successful`);
}
);
}

Просмотреть файл

@ -0,0 +1,9 @@
<!DOCTYPE html><html>
<body>
<script>
window.onbeforeunload = function() {
return "stop";
}
</script>
</body>
</html>