NS_IMETHODIMP
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return NS_OK;

  // If mozpasspointerevents is set, then we should allow subdocument content
  // to handle events even if we're pointer-events:none.
  if (aBuilder->IsForEventDelivery() && !PassPointerEventsToChildren())
    return NS_OK;

  nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!mInnerView)
    return NS_OK;

  nsFrameLoader* frameLoader = FrameLoader();
  if (frameLoader) {
    RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame();
    if (rfp) {
      return rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
    }
  }

  nsIView* subdocView = mInnerView->GetFirstChild();
  if (!subdocView)
    return NS_OK;

  nsCOMPtr<nsIPresShell> presShell = nullptr;

  nsIFrame* subdocRootFrame = subdocView->GetFrame();
  if (subdocRootFrame) {
    presShell = subdocRootFrame->PresContext()->PresShell();
  }
  // If painting is suppressed in the presshell, we try to look for a better
  // presshell to use.
  if (!presShell || (presShell->IsPaintingSuppressed() &&
                     !aBuilder->IsIgnoringPaintSuppression())) {
    // During page transition mInnerView will sometimes have two children, the
    // first being the new page that may not have any frame, and the second
    // being the old page that will probably have a frame.
    nsIView* nextView = subdocView->GetNextSibling();
    nsIFrame* frame = nullptr;
    if (nextView) {
      frame = nextView->GetFrame();
    }
    if (frame) {
      nsIPresShell* ps = frame->PresContext()->PresShell();
      if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
        subdocView = nextView;
        subdocRootFrame = frame;
        presShell = ps;
      }
    }
    if (!presShell) {
      // If we don't have a frame we use this roundabout way to get the pres shell.
      if (!mFrameLoader)
        return NS_OK;
      nsCOMPtr<nsIDocShell> docShell;
      mFrameLoader->GetDocShell(getter_AddRefs(docShell));
      if (!docShell)
        return NS_OK;
      docShell->GetPresShell(getter_AddRefs(presShell));
      if (!presShell)
        return NS_OK;
    }
  }

  nsPresContext* presContext = presShell->GetPresContext();

  nsDisplayList childItems;

  int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
  int32_t subdocAPD = presContext->AppUnitsPerDevPixel();

  nsRect dirty;
  if (subdocRootFrame) {
    nsIDocument* doc = subdocRootFrame->PresContext()->Document();
    nsIContent* root = doc ? doc->GetRootElement() : nullptr;
    nsRect displayPort;
    if (root && nsLayoutUtils::GetDisplayPort(root, &displayPort)) {
      dirty = displayPort;
    } else {
      // get the dirty rect relative to the root frame of the subdoc
      dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
      // and convert into the appunits of the subdoc
      dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
    }

    aBuilder->EnterPresShell(subdocRootFrame, dirty);
  }

  nsRect subdocBoundsInParentUnits =
    mInnerView->GetBounds() + aBuilder->ToReferenceFrame(this);

  if (subdocRootFrame) {
    rv = subdocRootFrame->
           BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
  }

  if (!aBuilder->IsForEventDelivery()) {
    // If we are going to use a displayzoom below then any items we put under
    // it need to have underlying frames from the subdocument. So we need to
    // calculate the bounds based on which frame will be the underlying frame
    // for the canvas background color item.
    nsRect bounds;
    if (subdocRootFrame) {
      bounds = subdocBoundsInParentUnits.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
    } else {
      bounds = subdocBoundsInParentUnits;
    }

    // If we are in print preview/page layout we want to paint the grey
    // background behind the page, not the canvas color. The canvas color gets
    // painted on the page itself.
    if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
      rv = presShell->AddPrintPreviewBackgroundItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds);
    } else {
      // Add the canvas background color to the bottom of the list. This
      // happens after we've built the list so that AddCanvasBackgroundColorItem
      // can monkey with the contents if necessary.
      uint32_t flags = nsIPresShell::FORCE_DRAW;
      rv = presShell->AddCanvasBackgroundColorItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds, NS_RGBA(0,0,0,0), flags);
    }
  }

  bool addedLayer = false;

  if (subdocRootFrame && parentAPD != subdocAPD) {
    NS_WARN_IF_FALSE(!addedLayer,
                     "Two container layers have been added. "
                      "Performance may suffer.");
    addedLayer = true;

    nsDisplayZoom* zoomItem =
      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                   subdocAPD, parentAPD, 
                                   nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
    childItems.AppendToTop(zoomItem);
  }

  nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
  if (!addedLayer &&
      (presContext->IsRootContentDocument() ||
       (sf && sf->IsScrollingActive()))) {
    // We always want top level content documents to be in their own layer.
    nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
      aBuilder, subdocRootFrame ? subdocRootFrame : this, 
      &childItems, nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
    childItems.AppendToTop(layerItem);
  }

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, dirty);
  }

  if (ShouldClipSubdocument()) {
    nsDisplayClip* item =
      new (aBuilder) nsDisplayClip(aBuilder, this, &childItems,
                                   subdocBoundsInParentUnits);
    // Clip children to the child root frame's rectangle
    childItems.AppendToTop(item);
  }

  if (mIsInline) {
    WrapReplacedContentForBorderRadius(aBuilder, &childItems, aLists);
  } else {
    aLists.Content()->AppendToTop(&childItems);
  }

  // delete childItems in case of OOM
  childItems.DeleteAll();

  return rv;
}
void
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return;

  nsFrameLoader* frameLoader = FrameLoader();
  RenderFrameParent* rfp = nullptr;
  if (frameLoader) {
    rfp = frameLoader->GetCurrentRemoteFrame();
  }

  // If we are pointer-events:none then we don't need to HitTest background
  bool pointerEventsNone = StyleVisibility()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE;
  if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) {
    nsDisplayListCollection decorations;
    DisplayBorderBackgroundOutline(aBuilder, decorations);
    if (rfp) {
      // 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);
  }

  bool passPointerEventsToChildren = false;
  if (aBuilder->IsForEventDelivery()) {
    passPointerEventsToChildren = PassPointerEventsToChildren();
    // If mozpasspointerevents is set, then we should allow subdocument content
    // to handle events even if we're pointer-events:none.
    if (pointerEventsNone && !passPointerEventsToChildren) {
      return;
    }
  }

  // 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
  // elementFromPoint.
  if (!mInnerView ||
      (!aBuilder->GetDescendIntoSubdocuments() && !passPointerEventsToChildren)) {
    return;
  }

  if (rfp) {
    rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
    return;
  }

  nsView* subdocView = mInnerView->GetFirstChild();
  if (!subdocView)
    return;

  nsCOMPtr<nsIPresShell> presShell = nullptr;

  nsIFrame* subdocRootFrame = subdocView->GetFrame();
  if (subdocRootFrame) {
    presShell = subdocRootFrame->PresContext()->PresShell();
  }
  // If painting is suppressed in the presshell, we try to look for a better
  // presshell to use.
  if (!presShell || (presShell->IsPaintingSuppressed() &&
                     !aBuilder->IsIgnoringPaintSuppression())) {
    // During page transition mInnerView will sometimes have two children, the
    // first being the new page that may not have any frame, and the second
    // being the old page that will probably have a frame.
    nsView* nextView = subdocView->GetNextSibling();
    nsIFrame* frame = nullptr;
    if (nextView) {
      frame = nextView->GetFrame();
    }
    if (frame) {
      nsIPresShell* ps = frame->PresContext()->PresShell();
      if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
        subdocView = nextView;
        subdocRootFrame = frame;
        presShell = ps;
      }
    }
    if (!presShell) {
      // If we don't have a frame we use this roundabout way to get the pres shell.
      if (!mFrameLoader)
        return;
      nsCOMPtr<nsIDocShell> docShell;
      mFrameLoader->GetDocShell(getter_AddRefs(docShell));
      if (!docShell)
        return;
      presShell = docShell->GetPresShell();
      if (!presShell)
        return;
    }
  }

  nsPresContext* presContext = presShell->GetPresContext();

  int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
  int32_t subdocAPD = presContext->AppUnitsPerDevPixel();

  nsRect dirty;
  bool haveDisplayPort = false;
  bool ignoreViewportScrolling = false;
  nsIFrame* savedIgnoreScrollFrame = nullptr;
  if (subdocRootFrame) {
    // get the dirty rect relative to the root frame of the subdoc
    dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
    // and convert into the appunits of the subdoc
    dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);

    if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
      // for root content documents we want the base to be the composition bounds
      nsRect displayportBase = presContext->IsRootContentDocument() ?
          nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)) :
          dirty.Intersect(nsRect(nsPoint(0,0), subdocRootFrame->GetSize()));
      nsRect displayPort;
      if (nsLayoutUtils::GetOrMaybeCreateDisplayPort(
            *aBuilder, rootScrollFrame, displayportBase, &displayPort)) {
        haveDisplayPort = true;
        dirty = displayPort;
      }

      ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
      if (ignoreViewportScrolling) {
        savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
        aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
      }
    }

    aBuilder->EnterPresShell(subdocRootFrame, dirty);
  }

  DisplayListClipState::AutoSaveRestore clipState(aBuilder);
  if (ShouldClipSubdocument()) {
    clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
  }

  nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
  bool constructResolutionItem = subdocRootFrame &&
    (presShell->GetXResolution() != 1.0 || presShell->GetYResolution() != 1.0);
  bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
  bool needsOwnLayer = constructResolutionItem || constructZoomItem ||
    haveDisplayPort ||
    presContext->IsRootContentDocument() || (sf && sf->IsScrollingActive());

  // Don't let in fixed pos propagate down to child documents. This makes
  // it a little less effective but doesn't regress an important case of a
  // child document being in a fixed pos element where we would do no occlusion
  // at all if we let it propagate down.
  nsDisplayListBuilder::AutoInFixedPosSetter
    buildingInFixedPos(aBuilder, false);

  nsDisplayList childItems;

  {
    DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
    if (needsOwnLayer) {
      // Clear current clip. There's no point in propagating it down, since
      // the layer we will construct will be clipped by the current clip.
      // In fact for nsDisplayZoom propagating it down would be incorrect since
      // nsDisplayZoom changes the meaning of appunits.
      nestedClipState.Clear();
    }

    if (subdocRootFrame) {
      nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
          aBuilder,
          ignoreViewportScrolling && subdocRootFrame->GetContent()
              ? nsLayoutUtils::FindOrCreateIDFor(subdocRootFrame->GetContent())
              : aBuilder->GetCurrentScrollParentId());

      aBuilder->SetAncestorHasTouchEventHandler(false);
      subdocRootFrame->
        BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
    }

    if (!aBuilder->IsForEventDelivery()) {
      // If we are going to use a displayzoom below then any items we put under
      // it need to have underlying frames from the subdocument. So we need to
      // calculate the bounds based on which frame will be the underlying frame
      // for the canvas background color item.
      nsRect bounds = GetContentRectRelativeToSelf() +
        aBuilder->ToReferenceFrame(this);
      if (subdocRootFrame) {
        bounds = bounds.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
      }

      // If we are in print preview/page layout we want to paint the grey
      // background behind the page, not the canvas color. The canvas color gets
      // painted on the page itself.
      if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
        presShell->AddPrintPreviewBackgroundItem(
          *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
          bounds);
      } else {
        // Add the canvas background color to the bottom of the list. This
        // happens after we've built the list so that AddCanvasBackgroundColorItem
        // can monkey with the contents if necessary.
        uint32_t flags = nsIPresShell::FORCE_DRAW;
        presShell->AddCanvasBackgroundColorItem(
          *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
          bounds, NS_RGBA(0,0,0,0), flags);
      }
    }
  }

  // Generate a resolution and/or zoom item if needed. If one or both of those is
  // created, we don't need to create a separate nsDisplaySubDocument.

  uint32_t flags = nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS;
  // If ignoreViewportScrolling is true then the top most layer we create here
  // is going to become the scrollable layer for the root scroll frame, so we
  // want to add nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER to whatever layer
  // becomes the topmost. We do this below.
  if (constructZoomItem) {
    uint32_t zoomFlags = flags;
    if (ignoreViewportScrolling && !constructResolutionItem) {
      zoomFlags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
    }
    nsDisplayZoom* zoomItem =
      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                   subdocAPD, parentAPD, zoomFlags);
    childItems.AppendToTop(zoomItem);
    needsOwnLayer = false;
  }
  // Wrap the zoom item in the resolution item if we have both because we want the
  // resolution scale applied on top of the app units per dev pixel conversion.
  if (ignoreViewportScrolling) {
    flags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
  }
  if (constructResolutionItem) {
    nsDisplayResolution* resolutionItem =
      new (aBuilder) nsDisplayResolution(aBuilder, subdocRootFrame, &childItems,
                                         flags);
    childItems.AppendToTop(resolutionItem);
    needsOwnLayer = false;
  }
  if (needsOwnLayer) {
    // We always want top level content documents to be in their own layer.
    nsDisplaySubDocument* layerItem = new (aBuilder) nsDisplaySubDocument(
      aBuilder, subdocRootFrame ? subdocRootFrame : this,
      &childItems, flags);
    childItems.AppendToTop(layerItem);
  }

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, dirty);

    if (ignoreViewportScrolling) {
      aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
    }
  }

  if (aBuilder->IsForImageVisibility()) {
    // We don't add the childItems to the return list as we're dealing with them here.
    presShell->RebuildImageVisibility(childItems);
    childItems.DeleteAll();
  } else {
    aLists.Content()->AppendToTop(&childItems);
  }
}
void
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return;

  nsFrameLoader* frameLoader = FrameLoader();
  RenderFrameParent* rfp = nullptr;
  if (frameLoader) {
    rfp = frameLoader->GetCurrentRenderFrame();
  }

  // If we are pointer-events:none then we don't need to HitTest background
  bool pointerEventsNone =
    StyleUserInterface()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE;
  if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) {
    nsDisplayListCollection decorations;
    DisplayBorderBackgroundOutline(aBuilder, decorations);
    if (rfp) {
      // 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);
  }

  if (aBuilder->IsForEventDelivery() && pointerEventsNone) {
    return;
  }

  // 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 (rfp) {
    rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
    return;
  }

  nsCOMPtr<nsIPresShell> presShell =
    GetSubdocumentPresShellForPainting(
      aBuilder->IsIgnoringPaintSuppression() ? IGNORE_PAINT_SUPPRESSION : 0);

  if (!presShell) {
    return;
  }

  nsIFrame* subdocRootFrame = presShell->GetRootFrame();

  nsPresContext* presContext = presShell->GetPresContext();

  int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
  int32_t subdocAPD = presContext->AppUnitsPerDevPixel();

  nsRect dirty;
  bool haveDisplayPort = false;
  bool ignoreViewportScrolling = false;
  nsIFrame* savedIgnoreScrollFrame = nullptr;
  if (subdocRootFrame) {
    // get the dirty rect relative to the root frame of the subdoc
    dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
    // and convert into the appunits of the subdoc
    dirty = dirty.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);

    if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
      nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
      MOZ_ASSERT(rootScrollableFrame);
      // Use a copy, so the dirty rect doesn't get modified to the display port.
      nsRect copy = dirty;
      haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder,
                          &copy, /* aAllowCreateDisplayPort = */ true);
      if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
        haveDisplayPort = false;
      }

      ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
      if (ignoreViewportScrolling) {
        savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
        aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
      }
    }

    aBuilder->EnterPresShell(subdocRootFrame, pointerEventsNone);
  } else {
    dirty = aDirtyRect;
  }

  DisplayListClipState::AutoSaveRestore clipState(aBuilder);
  if (ShouldClipSubdocument()) {
    clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
  }

  nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
  bool constructResolutionItem = subdocRootFrame &&
    (presShell->GetResolution() != 1.0);
  bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
  bool needsOwnLayer = false;
  if (constructResolutionItem ||
      constructZoomItem ||
      haveDisplayPort ||
      presContext->IsRootContentDocument() ||
      (sf && sf->IsScrollingActive(aBuilder)))
  {
    needsOwnLayer = true;
  }
  if (!needsOwnLayer && aBuilder->IsBuildingLayerEventRegions() &&
      nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell))
  {
    needsOwnLayer = true;
  }

  nsDisplayList childItems;

  {
    DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
    if (needsOwnLayer) {
      // Clear current clip. There's no point in propagating it down, since
      // the layer we will construct will be clipped by the current clip.
      // In fact for nsDisplayZoom propagating it down would be incorrect since
      // nsDisplayZoom changes the meaning of appunits.
      nestedClipState.EnterStackingContextContents(true);
    }

    if (subdocRootFrame) {
      nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
      nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
          aBuilder,
          ignoreViewportScrolling && rootScrollFrame && rootScrollFrame->GetContent()
              ? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent())
              : aBuilder->GetCurrentScrollParentId());

      aBuilder->SetAncestorHasApzAwareEventHandler(false);
      subdocRootFrame->
        BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
    }

    if (!aBuilder->IsForEventDelivery()) {
      // If we are going to use a displayzoom below then any items we put under
      // it need to have underlying frames from the subdocument. So we need to
      // calculate the bounds based on which frame will be the underlying frame
      // for the canvas background color item.
      nsRect bounds = GetContentRectRelativeToSelf() +
        aBuilder->ToReferenceFrame(this);
      if (subdocRootFrame) {
        bounds = bounds.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
      }

      // If we are in print preview/page layout we want to paint the grey
      // background behind the page, not the canvas color. The canvas color gets
      // painted on the page itself.
      if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
        presShell->AddPrintPreviewBackgroundItem(
          *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
          bounds);
      } else {
        // Invoke AutoBuildingDisplayList to ensure that the correct dirty rect
        // is used to compute the visible rect if AddCanvasBackgroundColorItem
        // creates a display item.
        nsIFrame* frame = subdocRootFrame ? subdocRootFrame : this;
        nsDisplayListBuilder::AutoBuildingDisplayList
          building(aBuilder, frame, dirty, true);
        // Add the canvas background color to the bottom of the list. This
        // happens after we've built the list so that AddCanvasBackgroundColorItem
        // can monkey with the contents if necessary.
        uint32_t flags = nsIPresShell::FORCE_DRAW;
        presShell->AddCanvasBackgroundColorItem(
          *aBuilder, childItems, frame, bounds, NS_RGBA(0,0,0,0), flags);
      }
    }
  }

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, &childItems);

    if (ignoreViewportScrolling) {
      aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
    }
  }

  // Generate a resolution and/or zoom item if needed. If one or both of those is
  // created, we don't need to create a separate nsDisplaySubDocument.

  uint32_t flags = nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS;
  // If ignoreViewportScrolling is true then the top most layer we create here
  // is going to become the scrollable layer for the root scroll frame, so we
  // want to add nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER to whatever layer
  // becomes the topmost. We do this below.
  if (constructZoomItem) {
    uint32_t zoomFlags = flags;
    if (ignoreViewportScrolling && !constructResolutionItem) {
      zoomFlags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
    }
    nsDisplayZoom* zoomItem =
      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                   subdocAPD, parentAPD, zoomFlags);
    childItems.AppendToTop(zoomItem);
    needsOwnLayer = false;
  }
  // Wrap the zoom item in the resolution item if we have both because we want the
  // resolution scale applied on top of the app units per dev pixel conversion.
  if (ignoreViewportScrolling) {
    flags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
  }
  if (constructResolutionItem) {
    nsDisplayResolution* resolutionItem =
      new (aBuilder) nsDisplayResolution(aBuilder, subdocRootFrame, &childItems,
                                         flags);
    childItems.AppendToTop(resolutionItem);
    needsOwnLayer = false;
  }
  if (needsOwnLayer) {
    // We always want top level content documents to be in their own layer.
    nsDisplaySubDocument* layerItem = new (aBuilder) nsDisplaySubDocument(
      aBuilder, subdocRootFrame ? subdocRootFrame : this,
      &childItems, flags);
    childItems.AppendToTop(layerItem);
  }

  if (aBuilder->IsForFrameVisibility()) {
    // We don't add the childItems to the return list as we're dealing with them here.
    presShell->RebuildApproximateFrameVisibilityDisplayList(childItems);
    childItems.DeleteAll();
  } else {
    aLists.Content()->AppendToTop(&childItems);
  }
}
Exemple #4
0
void
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return;

  // If mozpasspointerevents is set, then we should allow subdocument content
  // to handle events even if we're pointer-events:none.
  if (aBuilder->IsForEventDelivery() && !PassPointerEventsToChildren())
    return;

  DisplayBorderBackgroundOutline(aBuilder, aLists);

  if (!mInnerView)
    return;

  nsFrameLoader* frameLoader = FrameLoader();
  if (frameLoader) {
    RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame();
    if (rfp) {
      rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
      return;
    }
  }

  nsView* subdocView = mInnerView->GetFirstChild();
  if (!subdocView)
    return;

  nsCOMPtr<nsIPresShell> presShell = nullptr;

  nsIFrame* subdocRootFrame = subdocView->GetFrame();
  if (subdocRootFrame) {
    presShell = subdocRootFrame->PresContext()->PresShell();
  }
  // If painting is suppressed in the presshell, we try to look for a better
  // presshell to use.
  if (!presShell || (presShell->IsPaintingSuppressed() &&
                     !aBuilder->IsIgnoringPaintSuppression())) {
    // During page transition mInnerView will sometimes have two children, the
    // first being the new page that may not have any frame, and the second
    // being the old page that will probably have a frame.
    nsView* nextView = subdocView->GetNextSibling();
    nsIFrame* frame = nullptr;
    if (nextView) {
      frame = nextView->GetFrame();
    }
    if (frame) {
      nsIPresShell* ps = frame->PresContext()->PresShell();
      if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
        subdocView = nextView;
        subdocRootFrame = frame;
        presShell = ps;
      }
    }
    if (!presShell) {
      // If we don't have a frame we use this roundabout way to get the pres shell.
      if (!mFrameLoader)
        return;
      nsCOMPtr<nsIDocShell> docShell;
      mFrameLoader->GetDocShell(getter_AddRefs(docShell));
      if (!docShell)
        return;
      presShell = docShell->GetPresShell();
      if (!presShell)
        return;
    }
  }

  nsPresContext* presContext = presShell->GetPresContext();

  int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
  int32_t subdocAPD = presContext->AppUnitsPerDevPixel();

  nsRect dirty;
  if (subdocRootFrame) {
    nsIDocument* doc = subdocRootFrame->PresContext()->Document();
    nsIContent* root = doc ? doc->GetRootElement() : nullptr;
    nsRect displayPort;
    if (root && nsLayoutUtils::GetDisplayPort(root, &displayPort)) {
      dirty = displayPort;
    } else {
      // get the dirty rect relative to the root frame of the subdoc
      dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
      // and convert into the appunits of the subdoc
      dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
    }

    aBuilder->EnterPresShell(subdocRootFrame, dirty);
  }

  DisplayListClipState::AutoSaveRestore clipState(aBuilder);
  if (ShouldClipSubdocument()) {
    clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
  }

  nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
  bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
  bool needsOwnLayer = constructZoomItem ||
    presContext->IsRootContentDocument() || (sf && sf->IsScrollingActive());

  nsDisplayList childItems;

  {
    DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
    if (needsOwnLayer) {
      // Clear current clip. There's no point in propagating it down, since
      // the layer we will construct will be clipped by the current clip.
      // In fact for nsDisplayZoom propagating it down would be incorrect since
      // nsDisplayZoom changes the meaning of appunits.
      nestedClipState.Clear();
    }

    if (subdocRootFrame) {
      subdocRootFrame->
        BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
    }

    if (!aBuilder->IsForEventDelivery()) {
      // If we are going to use a displayzoom below then any items we put under
      // it need to have underlying frames from the subdocument. So we need to
      // calculate the bounds based on which frame will be the underlying frame
      // for the canvas background color item.
      nsRect bounds;
      nsRect subdocBoundsInParentUnits = GetContentRectRelativeToSelf();
      if (subdocRootFrame) {
        bounds = subdocBoundsInParentUnits.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
      } else {
        bounds = subdocBoundsInParentUnits;
      }

      // If we are in print preview/page layout we want to paint the grey
      // background behind the page, not the canvas color. The canvas color gets
      // painted on the page itself.
      if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
        presShell->AddPrintPreviewBackgroundItem(
          *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
          bounds);
      } else {
        // Add the canvas background color to the bottom of the list. This
        // happens after we've built the list so that AddCanvasBackgroundColorItem
        // can monkey with the contents if necessary.
        uint32_t flags = nsIPresShell::FORCE_DRAW;
        presShell->AddCanvasBackgroundColorItem(
          *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
          bounds, NS_RGBA(0,0,0,0), flags);
      }
    }
  }

  if (constructZoomItem) {
    nsDisplayZoom* zoomItem =
      new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                   subdocAPD, parentAPD,
                                   nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
    childItems.AppendToTop(zoomItem);
  } else if (needsOwnLayer) {
    // We always want top level content documents to be in their own layer.
    nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
      aBuilder, subdocRootFrame ? subdocRootFrame : this,
      &childItems, nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS);
    childItems.AppendToTop(layerItem);
  }

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, dirty);
  }

  if (aBuilder->IsForImageVisibility()) {
    // We don't add the childItems to the return list as we're dealing with them here.
    presShell->RebuildImageVisibility(childItems);
    childItems.DeleteAll();
  } else {
    aLists.Content()->AppendToTop(&childItems);
  }
}
NS_IMETHODIMP
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return NS_OK;

  if (aBuilder->IsForEventDelivery() &&
      GetStyleVisibility()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE)
    return NS_OK;

  nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!mInnerView)
    return NS_OK;

  nsFrameLoader* frameLoader = FrameLoader();
  if (frameLoader) {
    RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame();
    if (rfp) {
      return rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
    }
  }

  nsIView* subdocView = mInnerView->GetFirstChild();
  if (!subdocView)
    return NS_OK;

  nsCOMPtr<nsIPresShell> presShell = nsnull;

  nsIFrame* subdocRootFrame =
    static_cast<nsIFrame*>(subdocView->GetClientData());

  if (subdocRootFrame) {
    presShell = subdocRootFrame->PresContext()->PresShell();
  }
  // If painting is suppressed in the presshell, we try to look for a better
  // presshell to use.
  if (!presShell || (presShell->IsPaintingSuppressed() &&
                     !aBuilder->IsIgnoringPaintSuppression())) {
    // During page transition mInnerView will sometimes have two children, the
    // first being the new page that may not have any frame, and the second
    // being the old page that will probably have a frame.
    nsIView* nextView = subdocView->GetNextSibling();
    nsIFrame* frame = nsnull;
    if (nextView) {
      frame = static_cast<nsIFrame*>(nextView->GetClientData());
    }
    if (frame) {
      nsIPresShell* ps = frame->PresContext()->PresShell();
      if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
        subdocView = nextView;
        subdocRootFrame = frame;
        presShell = ps;
      }
    }
    if (!presShell) {
      // If we don't have a frame we use this roundabout way to get the pres shell.
      if (!mFrameLoader)
        return NS_OK;
      nsCOMPtr<nsIDocShell> docShell;
      mFrameLoader->GetDocShell(getter_AddRefs(docShell));
      if (!docShell)
        return NS_OK;
      docShell->GetPresShell(getter_AddRefs(presShell));
      if (!presShell)
        return NS_OK;
    }
  }

  nsPresContext* presContext = presShell->GetPresContext();

  nsDisplayList childItems;

  PRInt32 parentAPD = PresContext()->AppUnitsPerDevPixel();
  PRInt32 subdocAPD = presContext->AppUnitsPerDevPixel();

  nsRect dirty;
  if (subdocRootFrame) {
    // get the dirty rect relative to the root frame of the subdoc
    dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
    // and convert into the appunits of the subdoc
    dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);

    aBuilder->EnterPresShell(subdocRootFrame, dirty);
  }

  // The subdocView's bounds are in appunits of the subdocument, so adjust
  // them.
  nsRect subdocBoundsInParentUnits =
    subdocView->GetBounds().ConvertAppUnitsRoundOut(subdocAPD, parentAPD);

  // Get the bounds of subdocView relative to the reference frame.
  subdocBoundsInParentUnits = subdocBoundsInParentUnits +
                              mInnerView->GetPosition() +
                              GetOffsetToCrossDoc(aBuilder->ReferenceFrame());

  if (subdocRootFrame && NS_SUCCEEDED(rv)) {
    rv = subdocRootFrame->
           BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
  }

  if (!aBuilder->IsForEventDelivery()) {
    // If we are going to use a displayzoom below then any items we put under
    // it need to have underlying frames from the subdocument. So we need to
    // calculate the bounds based on which frame will be the underlying frame
    // for the canvas background color item.
    nsRect bounds;
    if (subdocRootFrame) {
      nsPoint offset = mInnerView->GetPosition() +
                       GetOffsetToCrossDoc(aBuilder->ReferenceFrame());
      offset = offset.ConvertAppUnits(parentAPD, subdocAPD);
      bounds = subdocView->GetBounds() + offset;
    } else {
      bounds = subdocBoundsInParentUnits;
    }

    // If we are in print preview/page layout we want to paint the grey
    // background behind the page, not the canvas color. The canvas color gets
    // painted on the page itself.
    if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
      rv = presShell->AddPrintPreviewBackgroundItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds);
    } else {
      // Add the canvas background color to the bottom of the list. This
      // happens after we've built the list so that AddCanvasBackgroundColorItem
      // can monkey with the contents if necessary.
      PRUint32 flags = nsIPresShell::FORCE_DRAW;
      rv = presShell->AddCanvasBackgroundColorItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds, NS_RGBA(0,0,0,0), flags);
    }
  }

  if (NS_SUCCEEDED(rv)) {

    bool addedLayer = false;

    if (subdocRootFrame && parentAPD != subdocAPD) {
      NS_WARN_IF_FALSE(!addedLayer,
                       "Two container layers have been added. "
                       "Performance may suffer.");
      addedLayer = true;

      nsDisplayZoom* zoomItem =
        new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                     subdocAPD, parentAPD);
      childItems.AppendToTop(zoomItem);
    }
    
    if (!addedLayer && presContext->IsRootContentDocument()) {
      // We always want top level content documents to be in their own layer.
      nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
        aBuilder, subdocRootFrame ? subdocRootFrame : this, &childItems);
      childItems.AppendToTop(layerItem);
    }

    nsDisplayList list;
    // Clip children to the child root frame's rectangle
    rv = list.AppendNewToTop(
        new (aBuilder) nsDisplayClip(aBuilder, this, &childItems,
                                     subdocBoundsInParentUnits));

    if (mIsInline) {
      WrapReplacedContentForBorderRadius(aBuilder, &list, aLists);
    } else {
      aLists.Content()->AppendToTop(&list);
    }
  }
  // delete childItems in case of OOM
  childItems.DeleteAll();

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, dirty);
  }

  return rv;
}
NS_IMETHODIMP
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
{
  if (!IsVisibleForPainting(aBuilder))
    return NS_OK;

  if (aBuilder->IsForEventDelivery() &&
      GetStyleVisibility()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE)
    return NS_OK;

  nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!mInnerView)
    return NS_OK;

#ifdef MOZ_IPC
  nsFrameLoader* frameLoader = FrameLoader();
  if (frameLoader) {
    RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame();
    if (rfp) {
      return rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
    }
  }
#endif

  nsIView* subdocView = mInnerView->GetFirstChild();
  if (!subdocView)
    return NS_OK;

  nsCOMPtr<nsIPresShell> presShell = nsnull;

  nsIFrame* subdocRootFrame =
    static_cast<nsIFrame*>(subdocView->GetClientData());

  if (subdocRootFrame) {
    presShell = subdocRootFrame->PresContext()->PresShell();
  }
  // If painting is suppressed in the presshell, we try to look for a better
  // presshell to use.
  if (!presShell || (presShell->IsPaintingSuppressed() &&
                     !aBuilder->IsIgnoringPaintSuppression())) {
    // During page transition mInnerView will sometimes have two children, the
    // first being the new page that may not have any frame, and the second
    // being the old page that will probably have a frame.
    nsIView* nextView = subdocView->GetNextSibling();
    nsIFrame* frame = nsnull;
    if (nextView) {
      frame = static_cast<nsIFrame*>(nextView->GetClientData());
    }
    if (frame) {
      nsIPresShell* ps = frame->PresContext()->PresShell();
      if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
        subdocView = nextView;
        subdocRootFrame = frame;
        presShell = ps;
      }
    }
    if (!presShell) {
      // If we don't have a frame we use this roundabout way to get the pres shell.
      if (!mFrameLoader)
        return NS_OK;
      nsCOMPtr<nsIDocShell> docShell;
      mFrameLoader->GetDocShell(getter_AddRefs(docShell));
      if (!docShell)
        return NS_OK;
      docShell->GetPresShell(getter_AddRefs(presShell));
      if (!presShell)
        return NS_OK;
    }
  }

  nsPresContext* presContext = presShell->GetPresContext();

  nsDisplayList childItems;

  PRInt32 parentAPD = PresContext()->AppUnitsPerDevPixel();
  PRInt32 subdocAPD = presContext->AppUnitsPerDevPixel();

  nsIFrame* subdocRootScrollFrame = presShell->GetRootScrollFrame();

  nsRect dirty;
  if (subdocRootFrame) {
    if (presShell->UsingDisplayPort() && subdocRootScrollFrame) {
      dirty = presShell->GetDisplayPort();

      // The visual overflow rect of our viewport frame unfortunately may not
      // intersect with the displayport of that frame. For example, the scroll
      // offset of the frame may be (0, 0) so that the visual overflow rect
      // is (0, 0, 800px, 500px) while the display port may have its top-left
      // corner below y=500px.
      //
      // We have to force the frame to have a little faith and build a display
      // list anyway. (see nsIFrame::BuildDisplayListForChild for the short-
      // circuit code we are evading here).
      //
      subdocRootScrollFrame->AddStateBits(
        NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);

    } else {
      // get the dirty rect relative to the root frame of the subdoc
      dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
      // and convert into the appunits of the subdoc
      dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
    }

    aBuilder->EnterPresShell(subdocRootFrame, dirty);
  }

  // The subdocView's bounds are in appunits of the subdocument, so adjust
  // them.
  nsRect subdocBoundsInParentUnits =
    subdocView->GetBounds().ConvertAppUnitsRoundOut(subdocAPD, parentAPD);

  // Get the bounds of subdocView relative to the reference frame.
  subdocBoundsInParentUnits = subdocBoundsInParentUnits +
                              mInnerView->GetPosition() +
                              GetOffsetToCrossDoc(aBuilder->ReferenceFrame());

  if (subdocRootFrame && NS_SUCCEEDED(rv)) {
    rv = subdocRootFrame->
           BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
  }

  if (!aBuilder->IsForEventDelivery()) {
    // If we are going to use a displayzoom below then any items we put under
    // it need to have underlying frames from the subdocument. So we need to
    // calculate the bounds based on which frame will be the underlying frame
    // for the canvas background color item.
    nsRect bounds;
    if (subdocRootFrame) {
      nsPoint offset = mInnerView->GetPosition() +
                       GetOffsetToCrossDoc(aBuilder->ReferenceFrame());
      offset = offset.ConvertAppUnits(parentAPD, subdocAPD);
      bounds = subdocView->GetBounds() + offset;
    } else {
      bounds = subdocBoundsInParentUnits;
    }

    // If we are in print preview/page layout we want to paint the grey
    // background behind the page, not the canvas color. The canvas color gets
    // painted on the page itself.
    if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
      rv = presShell->AddPrintPreviewBackgroundItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds);
    } else {
      // Add the canvas background color to the bottom of the list. This
      // happens after we've built the list so that AddCanvasBackgroundColorItem
      // can monkey with the contents if necessary.
      PRUint32 flags = nsIPresShell_MOZILLA_2_0_BRANCH::FORCE_DRAW;
      if (presContext->IsRootContentDocument()) {
        flags |= nsIPresShell_MOZILLA_2_0_BRANCH::ROOT_CONTENT_DOC_BG;
      }
      rv = presShell->AddCanvasBackgroundColorItem(
             *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
             bounds, NS_RGBA(0,0,0,0), flags);
    }
  }

  if (NS_SUCCEEDED(rv)) {

    bool addedLayer = false;

#ifdef MOZ_IPC
    // Make a scrollable layer in the child process so it can be manipulated
    // with transforms in the parent process.
    if (XRE_GetProcessType() == GeckoProcessType_Content) {
      nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();

      if (scrollFrame) {
        NS_ASSERTION(subdocRootFrame, "Root scroll frame should be non-null");
        nsRect scrollRange = scrollFrame->GetScrollRange();
        
        // Since making new layers is expensive, only use nsDisplayScrollLayer
        // if the area is scrollable.
        if (scrollRange.width != 0 || scrollRange.height != 0) {
          addedLayer = true;
          nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
            aBuilder,
            &childItems,
            subdocRootScrollFrame,
            subdocRootFrame
          );
          childItems.AppendToTop(layerItem);
        }
      }
    }
#endif

    if (subdocRootFrame && parentAPD != subdocAPD) {
      NS_WARN_IF_FALSE(!addedLayer,
                       "Two container layers have been added. "
                       "Performance may suffer.");
      addedLayer = true;

      nsDisplayZoom* zoomItem =
        new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
                                     subdocAPD, parentAPD);
      childItems.AppendToTop(zoomItem);
    }
    
    if (!addedLayer && presContext->IsRootContentDocument()) {
      // We always want top level content documents to be in their own layer.
      nsDisplayOwnLayer* layerItem = new (aBuilder) nsDisplayOwnLayer(
        aBuilder, subdocRootFrame ? subdocRootFrame : this, &childItems);
      childItems.AppendToTop(layerItem);
    }

    // Clip children to the child root frame's rectangle
    rv = aLists.Content()->AppendNewToTop(
        new (aBuilder) nsDisplayClip(aBuilder, this, &childItems,
                                     subdocBoundsInParentUnits));
  }
  // delete childItems in case of OOM
  childItems.DeleteAll();

  if (subdocRootFrame) {
    aBuilder->LeavePresShell(subdocRootFrame, dirty);
  }

  return rv;
}