Bug 1703607 - Exempt about:*pages from new bfcache, with the exception of about:blank, r=peterv

This also fixes test
browser/base/content/test/tabs/browser_navigate_through_urls_origin_attributes.js
which was failing for fission + bfcacheInParent, because about:privatebrowsing
was getting bfcached, and an extra XULFrameLoaderCreated event was firing, when
we were not expecting it.

Differential Revision: https://phabricator.services.mozilla.com/D112441
This commit is contained in:
Anny Gakhokidze 2021-04-28 20:17:35 +00:00
Родитель 1a72ada683
Коммит c5100b9329
7 изменённых файлов: 234 добавлений и 10 удалений

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

@ -6,6 +6,7 @@ support-files =
file_mediaPlayback.html
test_process_flags_chrome.html
helper_origin_attrs_testing.js
file_about_srcdoc.html
[browser_accessibility_indicator.js]
skip-if = (verify && debug && (os == 'linux')) || (os == 'win' && processor == 'aarch64')
@ -128,3 +129,5 @@ support-files = file_rel_opener_noopener.html
skip-if = (verify && os == 'mac' && webrender)
[browser_removeTabsToTheStart.js]
[browser_removeTabsToTheEnd.js]
[browser_bfcache_exemption_about_pages.js]
skip-if = !fission

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

@ -0,0 +1,176 @@
requestLongerTimeout(2);
const BASE = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"http://example.com"
);
async function navigateTo(browser, urls, expectedPersist) {
// Navigate to a bunch of urls
for (let url of urls) {
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
BrowserTestUtils.loadURI(browser, url);
await loaded;
}
// When we track pageshow event, save the evt.persisted on a doc element,
// so it can be checked from the test directly.
let pageShowCheck = evt => {
evt.target.ownerGlobal.document.documentElement.setAttribute(
"persisted",
evt.persisted
);
return true;
};
is(
browser.canGoBack,
true,
`After navigating to urls=${urls}, we can go back from uri=${browser.currentURI.spec}`
);
if (expectedPersist) {
// If we expect the page to persist, then the uri we are testing is about:blank.
// Currently we are only testing cases when we go forward to about:blank page,
// because it gets removed from history if it is sandwiched between two
// regular history entries. This means we can't test a scenario such as:
// page X, about:blank, page Y, go back -- about:blank page will be removed, and
// going back from page Y will take us to page X.
// Go back from about:blank (it will be the last uri in 'urls')
let pageShowPromise = BrowserTestUtils.waitForContentEvent(
browser,
"pageshow"
);
info(`Navigating back from uri=${browser.currentURI.spec}`);
browser.goBack();
await pageShowPromise;
info(`Got pageshow event`);
// Now go forward
let forwardPageShow = BrowserTestUtils.waitForContentEvent(
browser,
"pageshow",
false,
pageShowCheck
);
info(`Navigating forward from uri=${browser.currentURI.spec}`);
browser.goForward();
await forwardPageShow;
// Check that the page got persisted
let persisted = await SpecialPowers.spawn(browser, [], async function() {
return content.document.documentElement.getAttribute("persisted");
});
is(
persisted,
expectedPersist.toString(),
`uri ${browser.currentURI.spec} should have persisted`
);
} else {
// Go back
let pageShowPromise = BrowserTestUtils.waitForContentEvent(
browser,
"pageshow",
false,
pageShowCheck
);
info(`Navigating back from uri=${browser.currentURI.spec}`);
browser.goBack();
await pageShowPromise;
info(`Got pageshow event`);
// Check that the page did not get persisted
let persisted = await SpecialPowers.spawn(browser, [], async function() {
return content.document.documentElement.getAttribute("persisted");
});
is(
persisted,
expectedPersist.toString(),
`uri ${browser.currentURI.spec} shouldn't have persisted`
);
}
}
add_task(async function testAboutPagesExemptFromBfcache() {
// If Fission is disabled, the pref is no-op.
await SpecialPowers.pushPrefEnv({ set: [["fission.bfcacheInParent", true]] });
// Navigate to a bunch of urls, then go back once, check that the penultimate page did not go into BFbache
var browser;
// First page is about:privatebrowsing
const private_test_cases = [
["about:blank"],
["about:blank", "about:privatebrowsing", "about:blank"],
];
for (const urls of private_test_cases) {
info(`Private tab - navigate to ${urls} urls`);
let win = await BrowserTestUtils.openNewBrowserWindow({
private: true,
waitForTabURL: "about:privatebrowsing",
});
browser = win.gBrowser.selectedTab.linkedBrowser;
await navigateTo(browser, urls, false);
await BrowserTestUtils.closeWindow(win);
}
// First page is about:blank
const regular_test_cases = [
["about:home"],
["about:home", "about:blank"],
["about:blank", "about:newtab"],
];
for (const urls of regular_test_cases) {
info(`Regular tab - navigate to ${urls} urls`);
let win = await BrowserTestUtils.openNewBrowserWindow();
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser: win.gBrowser,
opening: "about:newtab",
});
browser = tab.linkedBrowser;
await navigateTo(browser, urls, false);
BrowserTestUtils.removeTab(tab);
await BrowserTestUtils.closeWindow(win);
}
});
// Test that about:blank or pages that have about:* subframes get bfcached.
// TODO bug 1705789: add about:reader tests when we make them bfcache compatible.
add_task(async function testAboutPagesBfcacheAllowed() {
// If Fission is disabled, the pref is no-op.
await SpecialPowers.pushPrefEnv({ set: [["fission.bfcacheInParent", true]] });
var browser;
// First page is about:privatebrowsing
// about:privatebrowsing -> about:blank, go back, go forward, - about:blank is bfcached
// about:privatebrowsing -> about:home -> about:blank, go back, go forward, - about:blank is bfcached
// about:privatebrowsing -> file_about_srcdoc.html, go back, go forward - file_about_srcdoc.html is bfcached
const private_test_cases = [
["about:blank"],
["about:home", "about:blank"],
[BASE + "file_about_srcdoc.html"],
];
for (const urls of private_test_cases) {
info(`Private tab - navigate to ${urls} urls`);
let win = await BrowserTestUtils.openNewBrowserWindow({
private: true,
waitForTabURL: "about:privatebrowsing",
});
browser = win.gBrowser.selectedTab.linkedBrowser;
await navigateTo(browser, urls, true);
await BrowserTestUtils.closeWindow(win);
}
// First page is about:blank
// about:blank -> about:home -> about:blank, go back, go forward, - about:blank is bfcached
// about:blank -> about:home -> file_about_srcdoc.html, go back, go forward - file_about_srcdoc.html is bfcached
const regular_test_cases = [
["about:home", "about:blank"],
["about:home", BASE + "file_about_srcdoc.html"],
];
for (const urls of regular_test_cases) {
info(`Regular tab - navigate to ${urls} urls`);
let win = await BrowserTestUtils.openNewBrowserWindow();
let tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser: win.gBrowser,
});
browser = tab.linkedBrowser;
await navigateTo(browser, urls, true);
BrowserTestUtils.removeTab(tab);
await BrowserTestUtils.closeWindow(win);
}
});

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

@ -79,7 +79,7 @@ function setupRemoteTypes() {
async function testNavigate() {
setupRemoteTypes();
/**
* Open a regular tab, 3 container tabs and a private window, load about:blank
* Open a regular tab, 3 container tabs and a private window, load about:blank or about:privatebrowsing
* For each test case
* load the uri
* verify correct remote type
@ -104,7 +104,7 @@ async function testNavigate() {
containerPages.push(containerPage);
}
let privatePage = await openURIInPrivateTab("about:blank");
let privatePage = await openURIInPrivateTab();
gPrevRemoteTypePrivateTab = privatePage.tab.linkedBrowser.remoteType;
for (const testCase of TEST_CASES) {

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

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<iframe srcdoc="hello world!"></iframe>
</body>
</html>

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

@ -78,28 +78,51 @@ async function openURIInContainer(uri, win, userContextId) {
}
async function openURIInPrivateTab(uri) {
info(`Opening url ${uri} in a private browsing tab`);
info(
`Opening url ${
uri ? uri : "about:privatebrowsing"
} in a private browsing tab`
);
let win = await BrowserTestUtils.openNewBrowserWindow({
private: true,
waitForTabURL: "about:privatebrowsing",
});
if (!uri) {
return { tab: win.gBrowser.selectedTab, uri: "about:privatebrowsing" };
}
initXulFrameLoaderListenerInfo();
win.gBrowser.addEventListener("XULFrameLoaderCreated", handleEvent);
const browser = win.gBrowser.selectedTab.linkedBrowser;
let prevRemoteType = browser.remoteType;
let loaded = BrowserTestUtils.browserLoaded(browser, false, uri);
BrowserTestUtils.loadURI(browser, uri);
await BrowserTestUtils.browserLoaded(browser, false, uri);
await loaded;
let currRemoteType = browser.remoteType;
info(
`XULFrameLoaderCreated was fired ${xulFrameLoaderCreatedListenerInfo.numCalledSoFar} time(s) for ${uri} in private tab`
);
is(
xulFrameLoaderCreatedListenerInfo.numCalledSoFar,
currRemoteType == prevRemoteType ? 0 : 1,
"XULFrameLoaderCreated fired correct number of times"
);
if (
SpecialPowers.Services.prefs.getBoolPref("fission.bfcacheInParent") &&
currRemoteType == prevRemoteType &&
uri == "about:blank"
) {
// about:blank page gets flagged for being eligible to go into bfcache
// and thus we create a new XULFrameLoader for these pages
is(
xulFrameLoaderCreatedListenerInfo.numCalledSoFar,
1,
"XULFrameLoaderCreated fired correct number of times"
);
} else {
is(
xulFrameLoaderCreatedListenerInfo.numCalledSoFar,
currRemoteType == prevRemoteType ? 0 : 1,
"XULFrameLoaderCreated fired correct number of times"
);
}
win.gBrowser.removeEventListener("XULFrameLoaderCreated", handleEvent);
return { tab: win.gBrowser.selectedTab, uri };

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

@ -2123,6 +2123,18 @@ bool CanonicalBrowsingContext::AllowedInBFCache(
(" * auxiliary BrowsingContexts"));
}
// There are not a lot of about:* pages that are allowed to load in
// subframes, so it's OK to allow those few about:* pages enter BFCache.
MOZ_ASSERT(IsTop(), "Trying to put a non top level BC into BFCache");
nsCOMPtr<nsIURI> currentURI = GetCurrentURI();
// Exempt about:* pages from bfcache, with the exception of about:blank
if (currentURI && currentURI->SchemeIs("about") &&
!currentURI->GetSpecOrDefault().EqualsLiteral("about:blank")) {
bfcacheCombo |= BFCacheStatus::ABOUT_PAGE;
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug, (" * about:* page"));
}
// For telemetry we're collecting all the flags for all the BCs hanging
// from this top-level BC.
PreOrderWalk([&](BrowsingContext* aBrowsingContext) {

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

@ -302,7 +302,8 @@ enum BFCacheStatus {
HAS_ACTIVE_SPEECH_SYNTHESIS = 1 << 9, // Status 9
HAS_USED_VR = 1 << 10, // Status 10
CONTAINS_REMOTE_SUBFRAMES = 1 << 11, // Status 11
NOT_ONLY_TOPLEVEL_IN_BCG = 1 << 12 // Status 12
NOT_ONLY_TOPLEVEL_IN_BCG = 1 << 12, // Status 12
ABOUT_PAGE = 1 << 13, // Status 13
};
} // namespace dom