Bug 1438697 - Add inFrameSwap property on page transition. r=mrbkap draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 16 Feb 2018 13:05:06 -0600
changeset 756288 93a94aaf45f3d2078cf03c666db86cc0afb1be5c
parent 755831 3200dd2ad6b0dffccdc9274b02d8632920edc9ef
child 756290 e5ef6965f5ad601526e0a653a988c5fb4edfd690
push id99462
push userbmo:jryans@gmail.com
push dateFri, 16 Feb 2018 20:39:59 +0000
reviewersmrbkap
bugs1438697
milestone60.0a1
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
dom/base/nsDocument.cpp
dom/base/test/chrome/window_swapFrameLoaders.xul
dom/webidl/PageTransitionEvent.webidl
--- 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;
 };