Bug 1423208 - Queue pending RenderLayers calls when there are DocShell creation blockers. r?mystor draft
authorMike Conley <mconley@mozilla.com>
Mon, 08 Jan 2018 17:53:09 -0500
changeset 718627 41f9740b62aebbec221bd8dff2ebfb4a79b3a6db
parent 717429 a49ebf16c84658c5c82d3cb7c1918e80cd479186
child 745563 82f0a8e99c63b628a96decb6c23c3b8f1b262f2c
push id95009
push usermconley@mozilla.com
push dateWed, 10 Jan 2018 18:22:25 +0000
reviewersmystor
bugs1423208
milestone59.0a1
Bug 1423208 - Queue pending RenderLayers calls when there are DocShell creation blockers. r?mystor MozReview-Commit-ID: H4MqkWnfCkF
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -432,16 +432,19 @@ TabChild::TabChild(nsIContentChild* aMan
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   , mNativeWindowHandle(0)
 #endif
 #if defined(ACCESSIBILITY)
   , mTopLevelDocAccessibleChild(nullptr)
 #endif
   , mPendingDocShellIsActive(false)
   , mPendingDocShellReceivedMessage(false)
+  , mPendingRenderLayers(false)
+  , mPendingRenderLayersReceivedMessage(false)
+  , mPendingLayerObserverEpoch(0)
   , mPendingDocShellBlockers(0)
   , mWidgetNativeData(0)
 {
   mozilla::HoldJSObjects(this);
 
   nsWeakPtr weakPtrThis(do_GetWeakReference(static_cast<nsITabChild*>(this)));  // for capture by the lambda
   mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId,
                                                    const nsTArray<TouchBehaviorFlags>& aFlags)
@@ -2658,16 +2661,20 @@ TabChild::AddPendingDocShellBlocker()
 void
 TabChild::RemovePendingDocShellBlocker()
 {
   mPendingDocShellBlockers--;
   if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
     mPendingDocShellReceivedMessage = false;
     InternalSetDocShellIsActive(mPendingDocShellIsActive);
   }
+  if (!mPendingDocShellBlockers && mPendingRenderLayersReceivedMessage) {
+    mPendingRenderLayersReceivedMessage = false;
+    RecvRenderLayers(mPendingRenderLayers, mPendingLayerObserverEpoch);
+  }
 }
 
 void
 TabChild::InternalSetDocShellIsActive(bool aIsActive)
 {
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !aIsActive;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
@@ -2691,16 +2698,23 @@ TabChild::RecvSetDocShellIsActive(const 
 
   InternalSetDocShellIsActive(aIsActive);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvRenderLayers(const bool& aEnabled, const uint64_t& aLayerObserverEpoch)
 {
+  if (mPendingDocShellBlockers > 0) {
+    mPendingRenderLayersReceivedMessage = true;
+    mPendingRenderLayers = aEnabled;
+    mPendingLayerObserverEpoch = aLayerObserverEpoch;
+    return IPC_OK();
+  }
+
   // Since requests to change the rendering state come in from both the hang
   // monitor channel and the PContent channel, we have an ordering problem. This
   // code ensures that we respect the order in which the requests were made and
   // ignore stale requests.
   if (mLayerObserverEpoch >= aLayerObserverEpoch) {
     return IPC_OK();
   }
   mLayerObserverEpoch = aLayerObserverEpoch;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -978,18 +978,30 @@ private:
   uintptr_t mNativeWindowHandle;
 #endif // defined(XP_WIN)
 
 #if defined(ACCESSIBILITY)
   PDocAccessibleChild* mTopLevelDocAccessibleChild;
 #endif
   bool mCoalesceMouseMoveEvents;
 
+  // In some circumstances, a DocShell might be in a state where it is
+  // "blocked", and we should not attempt to change its active state or
+  // the underlying PresShell state until the DocShell becomes unblocked.
+  // It is possible, however, for the parent process to send commands to
+  // change those states while the DocShell is blocked. We store those
+  // states temporarily as "pending", and only apply them once the DocShell
+  // is no longer blocked.
   bool mPendingDocShellIsActive;
   bool mPendingDocShellReceivedMessage;
+  bool mPendingRenderLayers;
+  bool mPendingRenderLayersReceivedMessage;
+  uint64_t mPendingLayerObserverEpoch;
+  // When mPendingDocShellBlockers is greater than 0, the DocShell is blocked,
+  // and once it reaches 0, it is no longer blocked.
   uint32_t mPendingDocShellBlockers;
 
   WindowsHandle mWidgetNativeData;
 
   // This state is used to keep track of the current visible tabs (the ones rendering
   // layers). There may be more than one if there are multiple browser windows open, or
   // tabs are being warmed up. There may be none if this process does not host any
   // visible or warming tabs.