Bug 1438697 - Add inFrameSwap property on page transition. r=mrbkap
During a frame swap (using the `swapFrameLoaders` API on a frame loader owner),
we dispatch `pagehide` events before swapping and `pageshow` events after
swapping.
For some consumers that watch these events (such as DevTools), it would be
helpful to filter out the ones that sent because of frame swapping. This change
adds a chrome-only `inFrameSwap` property to such events so that we can tell
them apart.
MozReview-Commit-ID: QzIDuaF2zC
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -8567,16 +8567,19 @@ nsDocument::DispatchPageTransition(Event
return;
}
PageTransitionEventInit init;
init.mBubbles = true;
init.mCancelable = true;
init.mPersisted = aPersisted;
+ nsDocShell* docShell = mDocumentContainer.get();
+ init.mInFrameSwap = docShell && docShell->InFrameSwap();
+
RefPtr<PageTransitionEvent> event =
PageTransitionEvent::Constructor(this, aType, init);
event->SetTrusted(true);
event->SetTarget(this);
EventDispatcher::DispatchDOMEvent(aDispatchTarget, nullptr, event,
nullptr, nullptr);
}
--- a/dom/base/test/chrome/window_swapFrameLoaders.xul
+++ b/dom/base/test/chrome/window_swapFrameLoaders.xul
@@ -116,16 +116,19 @@ Test swapFrameLoaders with different fra
});
addMessageListener("check-browser-api", function() {
let exists = "api" in this;
sendAsyncMessage("check-browser-api", {
exists,
running: exists && !this.api._shuttingDown,
});
});
+ addEventListener("pagehide", function({ inFrameSwap }) {
+ sendAsyncMessage("pagehide", inFrameSwap);
+ });
}`;
}
// Load frame script into each frame
{
let mmA = frameA.frameLoader.messageManager;
let mmB = frameB.frameLoader.messageManager;
@@ -164,19 +167,27 @@ Test swapFrameLoaders with different fra
}
}
// Ping after swap using message managers acquired before
{
let mmA = frameA.frameLoader.messageManager;
let mmB = frameB.frameLoader.messageManager;
+ let pagehideA = once(mmA, "pagehide");
+ let pagehideB = once(mmB, "pagehide");
+
info("swapFrameLoaders");
frameA.swapFrameLoaders(frameB);
+ let [ { data: inFrameSwapA } ] = await pagehideA;
+ ok(inFrameSwapA, "Frame A got pagehide with inFrameSwap: true");
+ let [ { data: inFrameSwapB } ] = await pagehideB;
+ ok(inFrameSwapB, "Frame B got pagehide with inFrameSwap: true");
+
let inflightA = once(mmA, "pong");
let inflightB = once(mmB, "pong");
info("Ping message manager for frame A");
mmA.sendAsyncMessage("ping");
let [ { data: pongA } ] = await inflightA;
is(pongA, "B", "Frame A message manager acquired before swap gets reply B after swap");
--- a/dom/webidl/PageTransitionEvent.webidl
+++ b/dom/webidl/PageTransitionEvent.webidl
@@ -14,14 +14,19 @@
interface PageTransitionEvent : Event
{
/**
* Set to true if the document has been or will be persisted across
* firing of the event. For example, if a document is being cached in
* session history, |persisted| is true for the PageHide event.
*/
readonly attribute boolean persisted;
+
+ // Whether the document is in the middle of a frame swap.
+ [ChromeOnly]
+ readonly attribute boolean inFrameSwap;
};
dictionary PageTransitionEventInit : EventInit
{
boolean persisted = false;
+ boolean inFrameSwap = false;
};