Bug 1483664: Part 0 - Dispatch pagehide/pageshow to all system group listeners on frameloader swap. r=smaug,mconley

Having to add pagehide/pageshow listeners to the chrome event target is a
serious inconvience for the use cases of this bug. Dispatching to system group
listeners has approximately the same effect as the old code, but is much
easier for window-bound code to handle.

--HG--
extra : rebase_source : d67c14e9ba91772d8a9dd82481120b34bdb551e0
This commit is contained in:
Kris Maglione 2018-08-15 20:06:49 -07:00
parent dcee870651
commit 0c6cd02ae1
12 changed files with 57 additions and 34 deletions

View File

@ -42,8 +42,8 @@ class PluginChild extends ActorChild {
// Cache of plugin crash information sent from the parent
this.pluginCrashData = new Map();
this.mm.addEventListener("pagehide", this, true);
this.mm.addEventListener("pageshow", this, true);
this.mm.addEventListener("pagehide", this, {capture: true, mozSystemGroup: true});
this.mm.addEventListener("pageshow", this, {capture: true, mozSystemGroup: true});
}
receiveMessage(msg) {

View File

@ -19,8 +19,8 @@ let ACTORS = {
events: {
"AboutReaderContentLoaded": {wantUntrusted: true},
"DOMContentLoaded": {},
"pageshow": {},
"pagehide": {},
"pageshow": {mozSystemGroup: true},
"pagehide": {mozSystemGroup: true},
},
messages: [
"Reader:ToggleReaderMode",

View File

@ -8503,11 +8503,12 @@ nsContentUtils::SendMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell,
/* static */
void
nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
EventTarget* aChromeEventHandler)
EventTarget* aChromeEventHandler,
bool aOnlySystemGroup)
{
nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
NS_ASSERTION(doc, "What happened here?");
doc->OnPageHide(true, aChromeEventHandler);
doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
int32_t childCount = 0;
aItem->GetChildCount(&childCount);
@ -8519,7 +8520,7 @@ nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
for (uint32_t i = 0; i < kids.Length(); ++i) {
if (kids[i]) {
FirePageHideEvent(kids[i], aChromeEventHandler);
FirePageHideEvent(kids[i], aChromeEventHandler, aOnlySystemGroup);
}
}
}
@ -8532,7 +8533,8 @@ nsContentUtils::FirePageHideEvent(nsIDocShellTreeItem* aItem,
void
nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
EventTarget* aChromeEventHandler,
bool aFireIfShowing)
bool aFireIfShowing,
bool aOnlySystemGroup)
{
int32_t childCount = 0;
aItem->GetChildCount(&childCount);
@ -8544,14 +8546,15 @@ nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
for (uint32_t i = 0; i < kids.Length(); ++i) {
if (kids[i]) {
FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing,
aOnlySystemGroup);
}
}
nsCOMPtr<nsIDocument> doc = aItem->GetDocument();
NS_ASSERTION(doc, "What happened here?");
if (doc->IsShowing() == aFireIfShowing) {
doc->OnPageShow(true, aChromeEventHandler);
doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
}
}

View File

@ -2850,10 +2850,12 @@ public:
static void FirePageShowEvent(nsIDocShellTreeItem* aItem,
mozilla::dom::EventTarget* aChromeEventHandler,
bool aFireIfShowing);
bool aFireIfShowing,
bool aOnlySystemGroup = false);
static void FirePageHideEvent(nsIDocShellTreeItem* aItem,
mozilla::dom::EventTarget* aChromeEventHandler);
mozilla::dom::EventTarget* aChromeEventHandler,
bool aOnlySystemGroup = false);
static already_AddRefed<nsPIWindowRoot> GetWindowRoot(nsIDocument* aDoc);

View File

@ -8328,7 +8328,8 @@ nsIDocument::GetContentInThisDocument(nsIFrame* aFrame) const
void
nsIDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
const nsAString& aType,
bool aPersisted)
bool aPersisted,
bool aOnlySystemGroup)
{
if (!aDispatchTarget) {
return;
@ -8347,6 +8348,9 @@ nsIDocument::DispatchPageTransition(EventTarget* aDispatchTarget,
event->SetTrusted(true);
event->SetTarget(this);
if (aOnlySystemGroup) {
event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatchInContent = true;
}
EventDispatcher::DispatchDOMEvent(aDispatchTarget, nullptr, event,
nullptr, nullptr);
}
@ -8360,7 +8364,8 @@ NotifyPageShow(nsIDocument* aDocument, void* aData)
}
void
nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget)
nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup)
{
mVisible = true;
@ -8413,7 +8418,8 @@ nsIDocument::OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget)
if (!target) {
target = do_QueryInterface(GetWindow());
}
DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted,
aOnlySystemGroup);
}
}
@ -8460,7 +8466,8 @@ HasHttpScheme(nsIURI* aURI)
}
void
nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup)
{
if (IsTopLevelContentDocument() && GetDocGroup() &&
Telemetry::CanRecordExtended()) {
@ -8532,7 +8539,8 @@ nsIDocument::OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget)
}
{
PageUnloadingEventTimeStamp timeStamp(this);
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted,
aOnlySystemGroup);
}
}

View File

@ -1341,7 +1341,8 @@ protected:
void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget,
const nsAString& aType,
bool aPersisted);
bool aPersisted,
bool aOnlySystemGroup = false);
// Call this before the document does something that will unbind all content.
// That will stop us from doing a lot of work as each element is removed.
@ -2197,12 +2198,14 @@ public:
* PageTransitionEvent.webidl for a description of the |aPersisted|
* parameter. If aDispatchStartTarget is null, the pageshow event is
* dispatched on the ScriptGlobalObject for this document, otherwise it's
* dispatched on aDispatchStartTarget.
* dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is true, the
* event is only dispatched to listeners in the system group.
* Note: if aDispatchStartTarget isn't null, the showing state of the
* document won't be altered.
*/
virtual void OnPageShow(bool aPersisted,
mozilla::dom::EventTarget* aDispatchStartTarget);
mozilla::dom::EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup = false);
/**
* Notification that the page has been hidden, for documents which are loaded
@ -2212,12 +2215,14 @@ public:
* window. See PageTransitionEvent.webidl for a description of the
* |aPersisted| parameter. If aDispatchStartTarget is null, the pagehide
* event is dispatched on the ScriptGlobalObject for this document,
* otherwise it's dispatched on aDispatchStartTarget.
* otherwise it's dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is
* true, the event is only dispatched to listeners in the system group.
* Note: if aDispatchStartTarget isn't null, the showing state of the
* document won't be altered.
*/
void OnPageHide(bool aPersisted,
mozilla::dom::EventTarget* aDispatchStartTarget);
mozilla::dom::EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup = false);
/*
* We record the set of links in the document that are relevant to

View File

@ -51,10 +51,12 @@ function prepareForVisibilityEvents(browser, expectedOrder) {
rmvHide = BrowserTestUtils.addContentEventListener(browser, "pagehide",
() => eventListener("pagehide"),
false, checkFn, false, false);
{mozSystemGroup: true}, checkFn,
false, false);
rmvShow = BrowserTestUtils.addContentEventListener(browser, "pageshow",
() => eventListener("pageshow"),
false, checkFn, false, false);
{mozSystemGroup: true}, checkFn,
false, false);
});
}
@ -93,7 +95,7 @@ add_task(async function test_swap_frameloader_pagevisibility_events() {
await ContentTask.spawn(emptyBrowser, {}, async() => {
if (content.document.visibilityState === "hidden") {
info("waiting for hidden emptyBrowser to pageshow");
await ContentTaskUtils.waitForEvent(content, "pageshow");
await ContentTaskUtils.waitForEvent(content, "pageshow", {mozSystemGroup: true});
}
});

View File

@ -129,7 +129,7 @@ Test swapFrameLoaders with different frame types and remoteness
});
addEventListener("pagehide", function({ inFrameSwap }) {
sendAsyncMessage("pagehide", inFrameSwap);
});
}, {mozSystemGroup: true});
}`;
}

View File

@ -304,7 +304,8 @@ ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
void
ImageDocument::OnPageShow(bool aPersisted,
EventTarget* aDispatchStartTarget)
EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup)
{
if (aPersisted) {
mOriginalZoomLevel = IsSiteSpecific() ? 1.0 : GetZoomLevel();
@ -315,7 +316,8 @@ ImageDocument::OnPageShow(bool aPersisted,
RefPtr<ImageDocument> kungFuDeathGrip(this);
UpdateSizeFromLayout();
MediaDocument::OnPageShow(aPersisted, aDispatchStartTarget);
MediaDocument::OnPageShow(aPersisted, aDispatchStartTarget,
aOnlySystemGroup);
}
NS_IMETHODIMP

View File

@ -43,7 +43,8 @@ public:
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) override;
virtual void Destroy() override;
virtual void OnPageShow(bool aPersisted,
EventTarget* aDispatchStartTarget) override;
EventTarget* aDispatchStartTarget,
bool aOnlySystemGroup = false) override;
NS_DECL_NSIIMAGEDOCUMENT
NS_DECL_IMGINOTIFICATIONOBSERVER

View File

@ -2377,12 +2377,12 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
RefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(ourDocShell.get());
nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
nsCOMPtr<EventTarget> ourEventTarget = nsGlobalWindowOuter::Cast(ourWindow);
docShell->SetInFrameSwap(true);
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false);
nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget);
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false, true);
nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget, true);
// Owner content type may have changed, so store the possibly updated context
// and notify others.
@ -2410,7 +2410,7 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
}
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true);
nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true, true);
docShell->SetInFrameSwap(false);

View File

@ -1054,7 +1054,7 @@ var BrowserTestUtils = {
/* eslint-enable no-eval */
let frameScriptSource =
`data:,(${frameScript.toString()})(${id}, "${eventName}", ${useCapture}, "${checkFnSource}", ${wantsUntrusted})`;
`data:,(${frameScript.toString()})(${id}, "${eventName}", ${uneval(useCapture)}, "${checkFnSource}", ${wantsUntrusted})`;
let mm = Services.mm;