Bug 1500257 part 8 - Remove dependency on RenderFrame from nsDisplayRemote. r=aosmond
authorRyan Hunt <rhunt@eqrion.net>
Wed, 23 Jan 2019 11:07:57 -0600
changeset 458625 473bed49a2fd6d7a128ef11e778366b5beec897f
parent 458624 0d0e20cf0c2e93e2183209b2f49b61414cd8d702
child 458626 409364e06a94691655aaa3676cb473fd9ba38001
push id35539
push userbtara@mozilla.com
push dateTue, 12 Feb 2019 05:27:54 +0000
treeherdermozilla-central@c0d540e06ce3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaosmond
bugs1500257
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1500257 part 8 - Remove dependency on RenderFrame from nsDisplayRemote. r=aosmond This commit removes the dependency on RenderFrame from nsDisplayRemote so that it can work in child processes with remote subframes. Instead nsDisplayRemote now works with an nsFrameLoader, which will return the LayerId from either the RenderFrame (for top-level remote browsers), or from RemoteFrameChild (for remote subframes). Differential Revision: https://phabricator.services.mozilla.com/D17448
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/ipc/RenderFrame.cpp
layout/ipc/RenderFrame.h
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2602,21 +2602,25 @@ bool nsFrameLoader::IsRemoteFrame() {
   }
   return false;
 }
 
 mozilla::dom::PBrowserParent* nsFrameLoader::GetRemoteBrowser() const {
   return mRemoteBrowser;
 }
 
-RenderFrame* nsFrameLoader::GetCurrentRenderFrame() const {
+mozilla::layers::LayersId nsFrameLoader::GetLayersId() const {
+  MOZ_ASSERT(mRemoteFrame);
   if (mRemoteBrowser) {
-    return mRemoteBrowser->GetRenderFrame();
+    return mRemoteBrowser->GetRenderFrame()->GetLayersId();
   }
-  return nullptr;
+  if (mRemoteFrameChild) {
+    return mRemoteFrameChild->GetLayersId();
+  }
+  return mozilla::layers::LayersId{};
 }
 
 void nsFrameLoader::ActivateRemoteFrame(ErrorResult& aRv) {
   if (!mRemoteBrowser) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -19,16 +19,17 @@
 #include "nsSize.h"
 #include "nsWrapperCache.h"
 #include "nsIURI.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ParentSHistory.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/layers/LayersTypes.h"
 #include "nsStubMutationObserver.h"
 #include "Units.h"
 #include "nsIFrame.h"
 #include "nsPluginTags.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
@@ -281,30 +282,21 @@ class nsFrameLoader final : public nsStu
 
   /**
    * Returns the IPDL actor used if this is a top-level remote browser, or null
    * otherwise.
    */
   PBrowserParent* GetRemoteBrowser() const;
 
   /**
-   * The "current" render frame is the one on which the most recent
-   * remote layer-tree transaction was executed.  If no content has
-   * been drawn yet, or the remote browser doesn't have any drawn
-   * content for whatever reason, return nullptr.  The returned render
-   * frame has an associated shadow layer tree.
+   * Returns the layers ID that this remote frame is using to render.
    *
-   * Note that the returned render frame might not be a frame
-   * constructed for this->GetURL().  This can happen, e.g., if the
-   * <browser> was just navigated to a new URL, but hasn't painted the
-   * new page yet.  A render frame for the previous page may be
-   * returned.  (In-process <browser> behaves similarly, and this
-   * behavior seems desirable.)
+   * This must only be called if this is a remote frame.
    */
-  RenderFrame* GetCurrentRenderFrame() const;
+  mozilla::layers::LayersId GetLayersId() const;
 
   mozilla::dom::ChromeMessageSender* GetFrameMessageManager() {
     return mMessageManager;
   }
 
   mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
 
   bool ShouldClampScrollPosition() { return mClampScrollPosition; }
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -296,28 +296,25 @@ static void WrapBackgroundColorInOwnLaye
   aList->AppendToTop(&tempItems);
 }
 
 void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                           const nsDisplayListSet& aLists) {
   if (!IsVisibleForPainting()) return;
 
   nsFrameLoader* frameLoader = FrameLoader();
-  RenderFrame* rf = nullptr;
-  if (frameLoader) {
-    rf = frameLoader->GetCurrentRenderFrame();
-  }
+  bool isRemoteFrame = frameLoader && frameLoader->IsRemoteFrame();
 
   // If we are pointer-events:none then we don't need to HitTest background
   bool pointerEventsNone =
       StyleUI()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE;
   if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) {
     nsDisplayListCollection decorations(aBuilder);
     DisplayBorderBackgroundOutline(aBuilder, decorations);
-    if (rf) {
+    if (isRemoteFrame) {
       // Wrap background colors of <iframe>s with remote subdocuments in their
       // own layer so we generate a ColorLayer. This is helpful for optimizing
       // compositing; we can skip compositing the ColorLayer when the
       // remote content is opaque.
       WrapBackgroundColorInOwnLayer(aBuilder, this,
                                     decorations.BorderBackground());
     }
     decorations.MoveTo(aLists);
@@ -330,17 +327,17 @@ void nsSubDocumentFrame::BuildDisplayLis
   // If we're passing pointer events to children then we have to descend into
   // subdocuments no matter what, to determine which parts are transparent for
   // hit-testing or event regions.
   bool needToDescend = aBuilder->GetDescendIntoSubdocuments();
   if (!mInnerView || !needToDescend) {
     return;
   }
 
-  if (rf) {
+  if (isRemoteFrame) {
     // We're the subdoc for <browser remote="true"> and it has
     // painted content.  Display its shadow layer tree.
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
     nsPoint offset = aBuilder->ToReferenceFrame(this);
     nsRect bounds = this->EnsureInnerView()->GetBounds() + offset;
     clipState.ClipContentDescendants(bounds);
 
@@ -993,20 +990,16 @@ nsFrameLoader* nsSubDocumentFrame::Frame
     nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content);
     if (loaderOwner) {
       mFrameLoader = loaderOwner->GetFrameLoader();
     }
   }
   return mFrameLoader;
 }
 
-mozilla::layout::RenderFrame* nsSubDocumentFrame::GetRenderFrame() const {
-  return FrameLoader() ? FrameLoader()->GetCurrentRenderFrame() : nullptr;
-}
-
 // XXX this should be called ObtainDocShell or something like that,
 // to indicate that it could have side effects
 nsIDocShell* nsSubDocumentFrame::GetDocShell() {
   // How can FrameLoader() return null???
   if (NS_WARN_IF(!FrameLoader())) {
     return nullptr;
   }
   return mFrameLoader->GetDocShell(IgnoreErrors());
--- a/layout/generic/nsSubDocumentFrame.h
+++ b/layout/generic/nsSubDocumentFrame.h
@@ -113,26 +113,24 @@ class nsSubDocumentFrame final : public 
   bool PassPointerEventsToChildren();
 
   void MaybeShowViewer() {
     if (!mDidCreateDoc && !mCallingShow) {
       ShowViewer();
     }
   }
 
-  mozilla::layout::RenderFrame* GetRenderFrame() const;
+  nsFrameLoader* FrameLoader() const;
 
  protected:
   friend class AsyncFrameInit;
 
   // Helper method to look up the HTML marginwidth & marginheight attributes.
   mozilla::CSSIntSize GetMarginAttributes();
 
-  nsFrameLoader* FrameLoader() const;
-
   bool IsInline() { return mIsInline; }
 
   nscoord GetIntrinsicISize();
   nscoord GetIntrinsicBSize();
 
   // Show our document viewer. The document viewer is hidden via a script
   // runner, so that we can save and restore the presentation if we're
   // being reframed.
--- a/layout/ipc/RenderFrame.cpp
+++ b/layout/ipc/RenderFrame.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabParent.h"
+#include "mozilla/dom/RemoteFrameChild.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerTransactionParent.h"
 #include "nsFrameLoader.h"
 #include "nsStyleStructInlines.h"
 #include "nsSubDocumentFrame.h"
 #include "RenderFrame.h"
 #include "mozilla/gfx/GPUProcessManager.h"
@@ -167,78 +168,79 @@ nsDisplayRemote::nsDisplayRemote(nsDispl
   if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) {
     mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion;
   }
   if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(
           aFrame->PresShell())) {
     mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent;
   }
 
-  nsFrameLoader* frameLoader = GetRenderFrame()->GetFrameLoader();
-  if (frameLoader) {
-    TabParent* browser = TabParent::GetFrom(frameLoader);
-    if (browser) {
+  nsFrameLoader* frameLoader = GetFrameLoader();
+  MOZ_ASSERT(frameLoader && frameLoader->IsRemoteFrame());
+  mLayersId = frameLoader->GetLayersId();
+
+  if (nsFrameLoader* frameLoader = GetFrameLoader()) {
+    // TODO: We need to handle acquiring a TabId in the remote sub-frame case
+    // for fission.
+    if (TabParent* browser = TabParent::GetFrom(frameLoader)) {
       mTabId = browser->GetTabId();
     }
   }
 }
 
 mozilla::LayerState nsDisplayRemote::GetLayerState(
     nsDisplayListBuilder* aBuilder, LayerManager* aManager,
     const ContainerLayerParameters& aParameters) {
   if (IsTempLayerManager(aManager)) {
     return mozilla::LAYER_NONE;
   }
   return mozilla::LAYER_ACTIVE_FORCE;
 }
 
 bool nsDisplayRemote::HasDeletedFrame() const {
   // RenderFrame might change without invalidating nsSubDocumentFrame.
-  return !GetRenderFrame() || nsDisplayItem::HasDeletedFrame();
+  return !GetFrameLoader() || nsDisplayItem::HasDeletedFrame();
 }
 
 already_AddRefed<Layer> nsDisplayRemote::BuildLayer(
     nsDisplayListBuilder* aBuilder, LayerManager* aManager,
     const ContainerLayerParameters& aContainerParameters) {
-  MOZ_ASSERT(GetRenderFrame());
   MOZ_ASSERT(mFrame, "Makes no sense to have a shadow tree without a frame");
 
   if (IsTempLayerManager(aManager)) {
     // This can happen if aManager is a "temporary" manager, or if the
     // widget's layer manager changed out from under us.  We need to
     // FIXME handle the former case somehow, probably with an API to
     // draw a manager's subtree.  The latter is bad bad bad, but the the
     // MOZ_ASSERT() above will flag it.  Returning nullptr here will just
     // cause the shadow subtree not to be rendered.
     if (!aContainerParameters.mForEventsAndPluginsOnly) {
       NS_WARNING("Remote iframe not rendered");
     }
     return nullptr;
   }
 
-  LayersId remoteId = GetRenderFrame()->GetLayersId();
-
-  if (!remoteId.IsValid()) {
+  if (!mLayersId.IsValid()) {
     return nullptr;
   }
 
   RefPtr<Layer> layer =
       aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this);
 
   if (!layer) {
     layer = aManager->CreateRefLayer();
   }
 
   if (!layer) {
     // Probably a temporary layer manager that doesn't know how to
     // use ref layers.
     return nullptr;
   }
 
-  static_cast<RefLayer*>(layer.get())->SetReferentId(remoteId);
+  static_cast<RefLayer*>(layer.get())->SetReferentId(mLayersId);
   LayoutDeviceIntPoint offset = GetContentRectLayerOffset(Frame(), aBuilder);
   // We can only have an offset if we're a child of an inactive
   // container, but our display item is LAYER_ACTIVE_FORCE which
   // forces all layers above to be active.
   MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
   Matrix4x4 m = Matrix4x4::Translation(offset.x, offset.y, 0.0);
   // Remote content can't be repainted by us, so we multiply down
   // the resolution that our container expects onto our container.
@@ -266,44 +268,46 @@ void nsDisplayRemote::Paint(nsDisplayLis
 }
 
 bool nsDisplayRemote::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     mozilla::layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
+  if (!mLayersId.IsValid()) {
+    return true;
+  }
+
   mOffset = GetContentRectLayerOffset(mFrame, aDisplayListBuilder);
 
   LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits(
       mFrame->GetContentRectRelativeToSelf(),
       mFrame->PresContext()->AppUnitsPerDevPixel());
   rect += mOffset;
 
   aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect),
-                      !BackfaceIsHidden(),
-                      mozilla::wr::AsPipelineId(GetRemoteLayersId()),
+                      !BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId),
                       /*ignoreMissingPipelines*/ true);
 
   return true;
 }
 
 bool nsDisplayRemote::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
     mozilla::layers::WebRenderLayerScrollData* aLayerData) {
+  if (!mLayersId.IsValid()) {
+    return true;
+  }
+
   if (aLayerData) {
-    aLayerData->SetReferentId(GetRemoteLayersId());
+    aLayerData->SetReferentId(mLayersId);
     aLayerData->SetTransform(
         mozilla::gfx::Matrix4x4::Translation(mOffset.x, mOffset.y, 0.0));
     aLayerData->SetEventRegionsOverride(mEventRegionsOverride);
   }
   return true;
 }
 
-LayersId nsDisplayRemote::GetRemoteLayersId() const {
-  MOZ_ASSERT(GetRenderFrame());
-  return GetRenderFrame()->GetLayersId();
-}
-
-mozilla::layout::RenderFrame* nsDisplayRemote::GetRenderFrame() const {
-  return mFrame ? static_cast<nsSubDocumentFrame*>(mFrame)->GetRenderFrame()
+nsFrameLoader* nsDisplayRemote::GetFrameLoader() const {
+  return mFrame ? static_cast<nsSubDocumentFrame*>(mFrame)->FrameLoader()
                 : nullptr;
 }
--- a/layout/ipc/RenderFrame.h
+++ b/layout/ipc/RenderFrame.h
@@ -123,17 +123,17 @@ class nsDisplayRemote final : public nsD
       nsDisplayListBuilder* aDisplayListBuilder) override;
   bool UpdateScrollData(
       mozilla::layers::WebRenderScrollData* aData,
       mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
 
   NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE)
 
  private:
-  LayersId GetRemoteLayersId() const;
-  RenderFrame* GetRenderFrame() const;
+  nsFrameLoader* GetFrameLoader() const;
 
   TabId mTabId;
+  LayersId mLayersId;
   LayoutDeviceIntPoint mOffset;
   EventRegionsOverride mEventRegionsOverride;
 };
 
 #endif  // mozilla_layout_RenderFrame_h