Bug 1698549 - Call FireDelayedDOMEvents when restoring a bfcached page, r=peterv

The test isn't testing anything mApplicationCache related, since appcache is basically
no-op code.

Depends on D107930

Differential Revision: https://phabricator.services.mozilla.com/D108487
This commit is contained in:
Olli Pettay 2021-03-21 21:46:25 +00:00
Родитель dc0a4c5e6c
Коммит dd5347ded5
9 изменённых файлов: 160 добавлений и 9 удалений

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

@ -1245,6 +1245,10 @@ void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
if (presShell) {
presShell->Thaw(false);
}
if (inner) {
inner->FireDelayedDOMEvents(false);
}
}
} else if (!mFiredUnloadEvent) {
// XXXBFCache check again that the page can enter bfcache.
@ -7878,7 +7882,7 @@ nsresult nsDocShell::RestoreFromHistory() {
presShell->Thaw();
}
return privWin->FireDelayedDOMEvents();
return privWin->FireDelayedDOMEvents(true);
}
nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,

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

@ -0,0 +1,41 @@
<html>
<head>
<script>
onpageshow = function(pageshowEvent) {
let bc = new BroadcastChannel("online_offline_bfcache");
bc.onmessage = function(event) {
if (event.data == "nextpage") {
bc.close();
location.href = location.href + "?nextpage";
} else if (event.data == "back") {
bc.close();
history.back();
} else if (event.data == "forward") {
bc.close();
history.forward();
} else if (event.data == "close") {
bc.postMessage("closed");
bc.close();
window.close();
}
};
bc.postMessage({ event: pageshowEvent.type, persisted: pageshowEvent.persisted });
}
onoffline = function(event) {
let bc = new BroadcastChannel("online_offline_bfcache");
bc.postMessage(event.type);
bc.close();
}
ononline = function(event) {
let bc = new BroadcastChannel("online_offline_bfcache");
bc.postMessage(event.type);
bc.close();
}
</script>
</head>
<body>
</body>
</html>

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

@ -107,6 +107,8 @@ support-files = file_meta_refresh.html
[test_navigation_type.html]
support-files = file_navigation_type.html
[test_not-opener.html]
[test_online_offline_bfcache.html]
support-files = file_online_offline_bfcache.html
[test_opener.html]
[test_popup-navigates-children.html]
[test_reload.html]

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

@ -0,0 +1,99 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Online/Offline with BFCache</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
<script>
/*
* The test is designed to work with and without bfcache.
* (1) First the test opens a window which then loads another page which
* goes back to the original page to detect if bfcache is enabled. If
* bfcache isn't enabled, close message is sent to the opened window and it
* closes itself and sends a message back and the test finishes.
* (2) The browser is set to offline mode. The opened page sends message
* that it has received offline event. This controller page then asks the
* page to go forward. The page which comes out from the bfcache gets
* offline event and sends message about that to this controller.
* (3) Browser is set to online mode. Similar cycle as with offline happens.
* (4) Controller page sends close message to the opened window and it
* closes itself and sends a message back and the test finishes.
*/
function offlineOnline(online) {
function offlineFn() {
Services.io.offline = true;
}
function onlineFn() {
Services.io.offline = false;
}
SpecialPowers.loadChromeScript(online ? onlineFn : offlineFn);
}
var bc = new BroadcastChannel("online_offline_bfcache");
var pageshowCount = 0;
var offlineCount = 0;
var onlineCount = 0;
bc.onmessage = function(event) {
if (event.data.event == "pageshow") {
++pageshowCount;
info("pageshow " + pageshowCount);
if (pageshowCount == 1) {
ok(!event.data.persisted);
bc.postMessage("nextpage");
} else if (pageshowCount == 2) {
ok(!event.data.persisted);
bc.postMessage("back");
} else if (pageshowCount == 3) {
if (!event.data.persisted) {
info("BFCache is not enabled, return early");
bc.postMessage("close");
} else {
offlineOnline(false);
}
}
} else if (event.data == "offline") {
++offlineCount;
info("offline " + offlineCount);
if (offlineCount == 1) {
bc.postMessage("forward");
} else if (offlineCount == 2) {
offlineOnline(true);
} else {
ok(false, "unexpected offline event");
}
} else if (event.data == "online") {
++onlineCount;
info("online " + onlineCount);
if (onlineCount == 1) {
bc.postMessage("back");
} else if (onlineCount == 2) {
bc.postMessage("close");
} else {
ok(false, "unexpected online event");
}
} else if ("closed") {
ok(true, "Did pass the test");
bc.close();
SimpleTest.finish();
}
};
function runTest() {
SpecialPowers.pushPrefEnv({"set": [["network.manage-offline-status", false]]}, function() {
window.open("file_online_offline_bfcache.html", "", "noopener");
});
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="runTest()">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</html>

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

@ -5873,7 +5873,7 @@ nsGlobalWindowInner::GetOrCreateServiceWorkerRegistration(
return ref;
}
nsresult nsGlobalWindowInner::FireDelayedDOMEvents() {
nsresult nsGlobalWindowInner::FireDelayedDOMEvents(bool aIncludeSubWindows) {
if (mApplicationCache) {
static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())
->FirePendingEvents();
@ -5882,6 +5882,10 @@ nsresult nsGlobalWindowInner::FireDelayedDOMEvents() {
// Fires an offline status event if the offline status has changed
FireOfflineStatusEventIfChanged();
if (!aIncludeSubWindows) {
return NS_OK;
}
nsCOMPtr<nsIDocShell> docShell = GetDocShell();
if (docShell) {
int32_t childCount = 0;
@ -5901,7 +5905,7 @@ nsresult nsGlobalWindowInner::FireDelayedDOMEvents() {
for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) {
if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
auto* win = nsGlobalWindowOuter::Cast(pWin);
win->FireDelayedDOMEvents();
win->FireDelayedDOMEvents(true);
}
}
}

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

@ -355,7 +355,7 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void NoteDOMContentLoaded();
virtual nsresult FireDelayedDOMEvents() override;
virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) override;
virtual void MaybeUpdateTouchState() override;

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

@ -6885,8 +6885,9 @@ bool nsGlobalWindowOuter::IsFrozen() const {
return mInnerWindow->IsFrozen();
}
nsresult nsGlobalWindowOuter::FireDelayedDOMEvents() {
FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
nsresult nsGlobalWindowOuter::FireDelayedDOMEvents(bool aIncludeSubWindows) {
FORWARD_TO_INNER(FireDelayedDOMEvents, (aIncludeSubWindows),
NS_ERROR_UNEXPECTED);
}
//*****************************************************************************

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

@ -307,7 +307,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
virtual bool IsSuspended() const override;
virtual bool IsFrozen() const override;
virtual nsresult FireDelayedDOMEvents() override;
virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) override;
// Outer windows only.
bool WouldReuseInnerWindow(Document* aNewDocument);

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

@ -418,7 +418,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// Fire any DOM notification events related to things that happened while
// the window was frozen.
virtual nsresult FireDelayedDOMEvents() = 0;
virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) = 0;
/**
* Get the docshell in this window.
@ -873,7 +873,7 @@ class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
// Fire any DOM notification events related to things that happened while
// the window was frozen.
virtual nsresult FireDelayedDOMEvents() = 0;
virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) = 0;
/**
* Get the docshell in this window.