Bug 1168705 part 3 - Make MozDOMFullscreen:{Request,Exit,Entered,Exited} be triggered synchronously. r=dao,smaug
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 02 Jul 2015 19:12:31 +1000
changeset 251131 76c1d4339e63022a2b1b53e560b6b33bd68ed210
parent 251130 eaee95d5af13f335b06d39eaf44929352dfe08e5
child 251132 7f3f04e7425279b89fcc1a844f14a1845cd56413
push id13833
push userryanvm@gmail.com
push dateThu, 02 Jul 2015 20:00:55 +0000
treeherderfx-team@98101796b275 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, smaug
bugs1168705
milestone42.0a1
Bug 1168705 part 3 - Make MozDOMFullscreen:{Request,Exit,Entered,Exited} be triggered synchronously. r=dao,smaug MozDOMFullscreen:{Request,Exit} are simply used to redirect the request to the parent process, hence there is no need to align them with refresh driver tick or dispatch asynchronously. MozDOMFullscreen:{Entered,Exited} are also used to notify the content process about the change, hence dispatching them later could cause unwanted delay on fullscreen change. Their handlers are also changed in this patch to avoid recursive fullscreen change.
browser/base/content/browser-fullScreen.js
dom/base/nsDocument.cpp
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -121,22 +121,24 @@ var FullScreen = {
         // request was initiated from an in-process browser, we need
         // to get its corresponding browser here.
         let browser;
         if (event.target == gBrowser) {
           browser = event.originalTarget;
         } else {
           let topWin = event.target.ownerDocument.defaultView.top;
           browser = gBrowser.getBrowserForContentWindow(topWin);
-          if (!browser) {
-            document.mozCancelFullScreen();
-            break;
+        }
+        if (!browser || !this.enterDomFullscreen(browser)) {
+          if (document.mozFullScreen) {
+            // MozDOMFullscreen:Entered is dispatched synchronously in
+            // fullscreen change, hence we have to avoid calling this
+            // method synchronously here.
+            setTimeout(() => document.mozCancelFullScreen(), 0);
           }
-        }
-        if (!this.enterDomFullscreen(browser)) {
           break;
         }
         // If it is a remote browser, send a message to ask the content
         // to enter fullscreen state. We don't need to do so if it is an
         // in-process browser, since all related document should have
         // entered fullscreen state at this point.
         if (this._isRemoteBrowser(browser)) {
           browser.messageManager.sendAsyncMessage("DOMFullscreen:Entered");
@@ -171,25 +173,23 @@ var FullScreen = {
     if (!document.mozFullScreen)
       return false;
 
     // If we've received a fullscreen notification, we have to ensure that the
     // element that's requesting fullscreen belongs to the browser that's currently
     // active. If not, we exit fullscreen since the "full-screen document" isn't
     // actually visible now.
     if (gBrowser.selectedBrowser != aBrowser) {
-      document.mozCancelFullScreen();
       return false;
     }
 
     let focusManager = Services.focus;
     if (focusManager.activeWindow != window) {
       // The top-level window has lost focus since the request to enter
       // full-screen was made. Cancel full-screen.
-      document.mozCancelFullScreen();
       return false;
     }
 
     document.documentElement.setAttribute("inDOMFullscreen", true);
 
     if (gFindBarInitialized)
       gFindBar.close();
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -11165,21 +11165,20 @@ ExitFullscreenInDocTree(nsIDocument* aMa
   }
 
   NS_ASSERTION(!root->IsFullScreenDoc(),
     "Fullscreen root should no longer be a fullscreen doc...");
 
   // Dispatch MozDOMFullscreen:Exited to the last document in
   // the list since we want this event to follow the same path
   // MozDOMFullscreen:Entered dispatched.
-  nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
-    new AsyncEventDispatcher(changed.LastElement(),
-                             NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
-                             true, true);
-  asyncDispatcher->PostDOMEvent();
+  nsContentUtils::DispatchEventOnlyToChrome(
+    changed.LastElement(), ToSupports(changed.LastElement()),
+    NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
+    /* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
   // Move the top-level window out of fullscreen mode.
   FullscreenRoots::Remove(root);
   SetWindowFullScreen(root, false);
 }
 
 /* static */
 void
 nsDocument::ExitFullscreen(nsIDocument* aDoc)
@@ -11248,19 +11247,20 @@ nsDocument::RestorePreviousFullScreenSta
       exitingFullscreen = false;
       break;
     }
   }
   if (exitingFullscreen) {
     // If we are fully exiting fullscreen, don't touch anything here,
     // just wait for the window to get out from fullscreen first.
     if (XRE_GetProcessType() == GeckoProcessType_Content) {
-      (new AsyncEventDispatcher(
-        this, NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
-        /* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
+      nsContentUtils::DispatchEventOnlyToChrome(
+        this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
+        /* Bubbles */ true, /* Cancelable */ false,
+        /* DefaultAction */ nullptr);
     } else {
       SetWindowFullScreen(this, false);
     }
     return;
   }
 
   // If fullscreen mode is updated the pointer should be unlocked
   UnlockPointer();
@@ -11689,19 +11689,19 @@ nsDocument::RequestFullScreen(UniquePtr<
   if (!FullscreenElementReadyCheck(elem, aRequest->mIsCallerChrome)) {
     return;
   }
 
   sPendingFullscreenRequests.insertBack(aRequest.release());
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     // If we are not the top level process, dispatch an event to make
     // our parent process go fullscreen first.
-    (new AsyncEventDispatcher(
-       this, NS_LITERAL_STRING("MozDOMFullscreen:Request"),
-       /* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
+    nsContentUtils::DispatchEventOnlyToChrome(
+      this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Request"),
+      /* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
   } else {
     // Make the window fullscreen.
     FullscreenRequest* lastRequest = sPendingFullscreenRequests.getLast();
     SetWindowFullScreen(this, true, lastRequest->mVRHMDDevice);
   }
 }
 
 /* static */ bool
@@ -11838,21 +11838,19 @@ nsDocument::ApplyFullscreen(const Fullsc
   FullscreenRoots::Add(this);
 
   // If it is the first entry of the fullscreen, trigger an event so
   // that the UI can response to this change, e.g. hide chrome, or
   // notifying parent process to enter fullscreen. Note that chrome
   // code may also want to listen to MozDOMFullscreen:NewOrigin event
   // to pop up warning/approval UI.
   if (!previousFullscreenDoc) {
-    nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
-      new AsyncEventDispatcher(
-        elem, NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
-        /* Bubbles */ true, /* ChromeOnly */ true);
-    asyncDispatcher->PostDOMEvent();
+    nsContentUtils::DispatchEventOnlyToChrome(
+      this, ToSupports(elem), NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
+      /* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
   }
 
   // The origin which is fullscreen gets changed. Trigger an event so
   // that the chrome knows to pop up a warning/approval UI. Note that
   // previousFullscreenDoc == nullptr upon first entry, so we always
   // take this path on the first entry. Also note that, in a multi-
   // process browser, the code in content process is responsible for
   // sending message with the origin to its parent, and the parent