Bug 1358712 - Force the frameloader to go through layout when content causes a TabParent to be created. r?nika draft
authorMike Conley <mconley@mozilla.com>
Thu, 19 Apr 2018 14:26:56 -0700
changeset 785626 296d26305d54840e7f9477bbf09aca1fe505a8c1
parent 785383 ea3555cf12afff38370e7a697db81f181e15dbf6
child 785627 c2b6e458fe2c018d70f5a5381f3e63bdb0f1b2e8
push id107281
push usermconley@mozilla.com
push dateFri, 20 Apr 2018 14:32:02 +0000
reviewersnika
bugs1358712
milestone61.0a1
Bug 1358712 - Force the frameloader to go through layout when content causes a TabParent to be created. r?nika This is necessary to avoid web platform test failures for tests that rely on layout calculations occurring inside a recently opened tab or window. Originally, the layout flush was happening "accidentally" within the StatusPanel that displays loading status for the browser. That flush is being removed in another patch in this series. MozReview-Commit-ID: IUxiBS9CDRY
dom/ipc/ContentParent.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4763,16 +4763,23 @@ ContentParent::CommonCreateWindow(PBrows
                                              aNextTabParentId,
                                              !aSetOpener,
                                              getter_AddRefs(aNewTabParent));
   if (NS_WARN_IF(NS_FAILED(aResult))) {
     return IPC_OK();
   }
 
   MOZ_ASSERT(aNewTabParent);
+
+  // At this point, it's possible the inserted frameloader hasn't gone through
+  // layout yet. To ensure that the dimensions that we send down when telling the
+  // frameloader to display will be correct (instead of falling back to a 10x10
+  // default), we force layout if necessary to get the most up-to-date dimensions.
+  aNewTabParent->ForceFrameLoaderLayoutIfNecessary();
+
   // If we were passed a name for the window which would override the default,
   // we should send it down to the new tab.
   if (nsContentUtils::IsOverridingWindowName(aName)) {
     Unused << TabParent::GetFrom(aNewTabParent)->SendSetWindowName(aName);
   }
 
   // Don't send down the OriginAttributes if the content process is handling
   // setting up the window for us. We only want to send them in the async case.
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -395,16 +395,42 @@ TabParent::Destroy()
     ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->AsContentParent()->ChildID());
   } else {
     ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->ChildID());
   }
 
   mMarkedDestroying = true;
 }
 
+void
+TabParent::ForceFrameLoaderLayoutIfNecessary()
+{
+  RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
+  if (!frameLoader) {
+    return;
+  }
+
+  nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent()
+  if (!targetFrame) {
+    return;
+  }
+
+  nsPresContext* presContext = targetFrame->PresContext();
+  if (!presContext) {
+    return;
+  }
+
+  // Only force the layout flush if the frameloader hasn't ever been
+  // run through layout.
+  if (targetFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW &&
+      nsCOMPtr<nsIPresShell> shell = presContext->GetPresShell()) {
+    shell->FlushPendingNotifications(FlushType::Layout);
+  }
+}
+
 mozilla::ipc::IPCResult
 TabParent::RecvEnsureLayersConnected(CompositorOptions* aCompositorOptions)
 {
   if (RenderFrameParent* frame = GetRenderFrame()) {
     frame->EnsureLayersConnected(aCompositorOptions);
   }
   return IPC_OK();
 }
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -135,16 +135,21 @@ public:
   nsIXULBrowserWindow* GetXULBrowserWindow();
 
   void Destroy();
 
   void RemoveWindowListeners();
 
   void AddWindowListeners();
 
+  // Used when content is causing a TabParent to be created, and
+  // needs to try forcing layout to flush in order to get accurate
+  // dimensions for the content area.
+  void ForceFrameLoaderLayoutIfNecessary();
+
   virtual mozilla::ipc::IPCResult RecvMoveFocus(const bool& aForward,
                                                 const bool& aForDocumentNavigation) override;
 
   virtual mozilla::ipc::IPCResult RecvSizeShellTo(const uint32_t& aFlags,
                                                   const int32_t& aWidth,
                                                   const int32_t& aHeight,
                                                   const int32_t& aShellItemWidth,
                                                   const int32_t& aShellItemHeight) override;