LCOV - code coverage report
Current view: top level - layout/generic - nsSubDocumentFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 258 608 42.4 %
Date: 2017-07-14 16:53:18 Functions: 33 49 67.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  * rendering object for replaced elements that contain a document, such
       8             :  * as <frame>, <iframe>, and some <object>s
       9             :  */
      10             : 
      11             : #include "nsSubDocumentFrame.h"
      12             : 
      13             : #include "gfxPrefs.h"
      14             : 
      15             : #include "mozilla/layout/RenderFrameParent.h"
      16             : 
      17             : #include "nsCOMPtr.h"
      18             : #include "nsGenericHTMLElement.h"
      19             : #include "nsGenericHTMLFrameElement.h"
      20             : #include "nsAttrValueInlines.h"
      21             : #include "nsIDocShell.h"
      22             : #include "nsIContentViewer.h"
      23             : #include "nsPresContext.h"
      24             : #include "nsIPresShell.h"
      25             : #include "nsIDocument.h"
      26             : #include "nsView.h"
      27             : #include "nsViewManager.h"
      28             : #include "nsGkAtoms.h"
      29             : #include "nsStyleConsts.h"
      30             : #include "nsFrameSetFrame.h"
      31             : #include "nsIDOMHTMLFrameElement.h"
      32             : #include "nsIScrollable.h"
      33             : #include "nsNameSpaceManager.h"
      34             : #include "nsDisplayList.h"
      35             : #include "nsIScrollableFrame.h"
      36             : #include "nsIObjectLoadingContent.h"
      37             : #include "nsLayoutUtils.h"
      38             : #include "FrameLayerBuilder.h"
      39             : #include "nsPluginFrame.h"
      40             : #include "nsContentUtils.h"
      41             : #include "nsIPermissionManager.h"
      42             : #include "nsServiceManagerUtils.h"
      43             : #include "nsIDOMMutationEvent.h"
      44             : #include "mozilla/Preferences.h"
      45             : 
      46             : using namespace mozilla;
      47             : using mozilla::layout::RenderFrameParent;
      48             : 
      49             : static bool sShowPreviousPage = true;
      50             : 
      51             : static nsIDocument*
      52           1 : GetDocumentFromView(nsView* aView)
      53             : {
      54           1 :   NS_PRECONDITION(aView, "");
      55             : 
      56           1 :   nsViewManager* vm = aView->GetViewManager();
      57           1 :   nsIPresShell* ps =  vm ? vm->GetPresShell() : nullptr;
      58           1 :   return ps ? ps->GetDocument() : nullptr;
      59             : }
      60             : 
      61           3 : nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
      62             :   : nsAtomicContainerFrame(aContext, kClassID)
      63             :   , mOuterView(nullptr)
      64             :   , mInnerView(nullptr)
      65             :   , mIsInline(false)
      66             :   , mPostedReflowCallback(false)
      67             :   , mDidCreateDoc(false)
      68           3 :   , mCallingShow(false)
      69             : {
      70           3 : }
      71             : 
      72             : #ifdef ACCESSIBILITY
      73             : a11y::AccType
      74           0 : nsSubDocumentFrame::AccessibleType()
      75             : {
      76           0 :   return a11y::eOuterDocType;
      77             : }
      78             : #endif
      79             : 
      80          26 : NS_QUERYFRAME_HEAD(nsSubDocumentFrame)
      81           4 :   NS_QUERYFRAME_ENTRY(nsSubDocumentFrame)
      82          22 : NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
      83             : 
      84           9 : class AsyncFrameInit : public Runnable
      85             : {
      86             : public:
      87           3 :   explicit AsyncFrameInit(nsIFrame* aFrame)
      88           3 :     : mozilla::Runnable("AsyncFrameInit")
      89           3 :     , mFrame(aFrame)
      90             :   {
      91           3 :   }
      92           3 :   NS_IMETHOD Run() override
      93             :   {
      94           6 :     AUTO_PROFILER_LABEL("AsyncFrameInit::Run", OTHER);
      95           3 :     if (mFrame.IsAlive()) {
      96           3 :       static_cast<nsSubDocumentFrame*>(mFrame.GetFrame())->ShowViewer();
      97             :     }
      98           6 :     return NS_OK;
      99             :   }
     100             : private:
     101             :   WeakFrame mFrame;
     102             : };
     103             : 
     104             : static void
     105             : InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent);
     106             : 
     107             : static void
     108             : EndSwapDocShellsForViews(nsView* aView);
     109             : 
     110             : void
     111           3 : nsSubDocumentFrame::Init(nsIContent*       aContent,
     112             :                          nsContainerFrame* aParent,
     113             :                          nsIFrame*         aPrevInFlow)
     114             : {
     115             :   // determine if we are a <frame> or <iframe>
     116           6 :   nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = do_QueryInterface(aContent);
     117           3 :   mIsInline = frameElem ? false : true;
     118             : 
     119             :   static bool addedShowPreviousPage = false;
     120           3 :   if (!addedShowPreviousPage) {
     121             :     // If layout.show_previous_page is true then during loading of a new page we
     122             :     // will draw the previous page if the new page has painting suppressed.
     123           1 :     Preferences::AddBoolVarCache(&sShowPreviousPage, "layout.show_previous_page", true);
     124           1 :     addedShowPreviousPage = true;
     125             :   }
     126             : 
     127           3 :   nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
     128             : 
     129             :   // CreateView() creates this frame's view, stored in mOuterView.  It needs to
     130             :   // be created first since it's the parent of the inner view, stored in
     131             :   // mInnerView.
     132           3 :   CreateView();
     133           3 :   EnsureInnerView();
     134             : 
     135             :   // Set the primary frame now so that nsDocumentViewer::FindContainerView
     136             :   // called from within EndSwapDocShellsForViews below can find it if needed.
     137           3 :   aContent->SetPrimaryFrame(this);
     138             : 
     139             :   // If we have a detached subdoc's root view on our frame loader, re-insert
     140             :   // it into the view tree. This happens when we've been reframed, and
     141             :   // ensures the presentation persists across reframes. If the frame element
     142             :   // has changed documents however, we blow away the presentation.
     143           6 :   RefPtr<nsFrameLoader> frameloader = FrameLoader();
     144           3 :   if (frameloader) {
     145           6 :     nsCOMPtr<nsIDocument> oldContainerDoc;
     146             :     nsIFrame* detachedFrame =
     147           3 :       frameloader->GetDetachedSubdocFrame(getter_AddRefs(oldContainerDoc));
     148           3 :     frameloader->SetDetachedSubdocFrame(nullptr, nullptr);
     149           3 :     MOZ_ASSERT(oldContainerDoc || !detachedFrame);
     150           3 :     if (oldContainerDoc) {
     151             :       nsView* detachedView =
     152           0 :         detachedFrame ? detachedFrame->GetView() : nullptr;
     153           0 :       if (detachedView && oldContainerDoc == aContent->OwnerDoc()) {
     154             :         // Restore stashed presentation.
     155           0 :         ::InsertViewsInReverseOrder(detachedView, mInnerView);
     156           0 :         ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
     157             :       } else {
     158             :         // Presentation is for a different document, don't restore it.
     159           0 :         frameloader->Hide();
     160             :       }
     161             :     }
     162             :   }
     163             : 
     164           3 :   nsContentUtils::AddScriptRunner(new AsyncFrameInit(this));
     165           3 : }
     166             : 
     167             : void
     168           3 : nsSubDocumentFrame::ShowViewer()
     169             : {
     170           3 :   if (mCallingShow) {
     171           0 :     return;
     172             :   }
     173             : 
     174           3 :   if (!PresContext()->IsDynamic()) {
     175             :     // We let the printing code take care of loading the document; just
     176             :     // create the inner view for it to use.
     177           0 :     (void) EnsureInnerView();
     178             :   } else {
     179           6 :     RefPtr<nsFrameLoader> frameloader = FrameLoader();
     180           3 :     if (frameloader) {
     181           3 :       CSSIntSize margin = GetMarginAttributes();
     182           6 :       AutoWeakFrame weakThis(this);
     183           3 :       mCallingShow = true;
     184             :       const nsAttrValue* attrValue =
     185           3 :         GetContent()->AsElement()->GetParsedAttr(nsGkAtoms::scrolling);
     186             :       int32_t scrolling =
     187           3 :         nsGenericHTMLFrameElement::MapScrollingAttribute(attrValue);
     188             :       bool didCreateDoc =
     189           3 :         frameloader->Show(margin.width, margin.height,
     190           3 :                           scrolling, scrolling, this);
     191           3 :       if (!weakThis.IsAlive()) {
     192           0 :         return;
     193             :       }
     194           3 :       mCallingShow = false;
     195           3 :       mDidCreateDoc = didCreateDoc;
     196             :     }
     197             :   }
     198             : }
     199             : 
     200             : nsIFrame*
     201           2 : nsSubDocumentFrame::GetSubdocumentRootFrame()
     202             : {
     203           2 :   if (!mInnerView)
     204           0 :     return nullptr;
     205           2 :   nsView* subdocView = mInnerView->GetFirstChild();
     206           2 :   return subdocView ? subdocView->GetFrame() : nullptr;
     207             : }
     208             : 
     209             : nsIPresShell*
     210           0 : nsSubDocumentFrame::GetSubdocumentPresShellForPainting(uint32_t aFlags)
     211             : {
     212           0 :   if (!mInnerView)
     213           0 :     return nullptr;
     214             : 
     215           0 :   nsView* subdocView = mInnerView->GetFirstChild();
     216           0 :   if (!subdocView)
     217           0 :     return nullptr;
     218             : 
     219           0 :   nsIPresShell* presShell = nullptr;
     220             : 
     221           0 :   nsIFrame* subdocRootFrame = subdocView->GetFrame();
     222           0 :   if (subdocRootFrame) {
     223           0 :     presShell = subdocRootFrame->PresContext()->PresShell();
     224             :   }
     225             : 
     226             :   // If painting is suppressed in the presshell, we try to look for a better
     227             :   // presshell to use.
     228           0 :   if (!presShell || (presShell->IsPaintingSuppressed() &&
     229           0 :                      !(aFlags & IGNORE_PAINT_SUPPRESSION))) {
     230             :     // During page transition mInnerView will sometimes have two children, the
     231             :     // first being the new page that may not have any frame, and the second
     232             :     // being the old page that will probably have a frame.
     233           0 :     nsView* nextView = subdocView->GetNextSibling();
     234           0 :     nsIFrame* frame = nullptr;
     235           0 :     if (nextView) {
     236           0 :       frame = nextView->GetFrame();
     237             :     }
     238           0 :     if (frame) {
     239           0 :       nsIPresShell* ps = frame->PresContext()->PresShell();
     240           0 :       if (!presShell || (ps && !ps->IsPaintingSuppressed() && sShowPreviousPage)) {
     241           0 :         subdocView = nextView;
     242           0 :         subdocRootFrame = frame;
     243           0 :         presShell = ps;
     244             :       }
     245             :     }
     246           0 :     if (!presShell) {
     247             :       // If we don't have a frame we use this roundabout way to get the pres shell.
     248           0 :       if (!mFrameLoader)
     249           0 :         return nullptr;
     250           0 :       nsCOMPtr<nsIDocShell> docShell;
     251           0 :       mFrameLoader->GetDocShell(getter_AddRefs(docShell));
     252           0 :       if (!docShell)
     253           0 :         return nullptr;
     254           0 :       presShell = docShell->GetPresShell();
     255             :     }
     256             :   }
     257             : 
     258           0 :   return presShell;
     259             : }
     260             : 
     261             : 
     262             : 
     263             : 
     264             : ScreenIntSize
     265           6 : nsSubDocumentFrame::GetSubdocumentSize()
     266             : {
     267           6 :   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     268           6 :     RefPtr<nsFrameLoader> frameloader = FrameLoader();
     269           3 :     if (frameloader) {
     270           6 :       nsCOMPtr<nsIDocument> oldContainerDoc;
     271             :       nsIFrame* detachedFrame =
     272           3 :         frameloader->GetDetachedSubdocFrame(getter_AddRefs(oldContainerDoc));
     273           3 :       nsView* view = detachedFrame ? detachedFrame->GetView() : nullptr;
     274           3 :       if (view) {
     275           0 :         nsSize size = view->GetBounds().Size();
     276           0 :         nsPresContext* presContext = detachedFrame->PresContext();
     277           0 :         return ScreenIntSize(presContext->AppUnitsToDevPixels(size.width),
     278           0 :                              presContext->AppUnitsToDevPixels(size.height));
     279             :       }
     280             :     }
     281             :     // Pick some default size for now.  Using 10x10 because that's what the
     282             :     // code used to do.
     283           3 :     return ScreenIntSize(10, 10);
     284             :   } else {
     285           3 :     nsSize docSizeAppUnits;
     286           3 :     nsPresContext* presContext = PresContext();
     287             :     nsCOMPtr<nsIDOMHTMLFrameElement> frameElem =
     288           6 :       do_QueryInterface(GetContent());
     289           3 :     if (frameElem) {
     290           0 :       docSizeAppUnits = GetSize();
     291             :     } else {
     292           3 :       docSizeAppUnits = GetContentRect().Size();
     293             :     }
     294             :     // Adjust subdocument size, according to 'object-fit' and the
     295             :     // subdocument's intrinsic size and ratio.
     296           3 :     nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     297           3 :     if (subDocRoot) {
     298             :       nsRect destRect =
     299           0 :         nsLayoutUtils::ComputeObjectDestRect(nsRect(nsPoint(), docSizeAppUnits),
     300           0 :                                              subDocRoot->GetIntrinsicSize(),
     301           0 :                                              subDocRoot->GetIntrinsicRatio(),
     302           0 :                                              StylePosition());
     303           0 :       docSizeAppUnits = destRect.Size();
     304             :     }
     305             : 
     306           6 :     return ScreenIntSize(presContext->AppUnitsToDevPixels(docSizeAppUnits.width),
     307           3 :                          presContext->AppUnitsToDevPixels(docSizeAppUnits.height));
     308             :   }
     309             : }
     310             : 
     311             : static void
     312          33 : WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
     313             :                               nsIFrame* aFrame,
     314             :                               nsDisplayList* aList)
     315             : {
     316          66 :   nsDisplayList tempItems;
     317             :   nsDisplayItem* item;
     318          51 :   while ((item = aList->RemoveBottom()) != nullptr) {
     319           9 :     if (item->GetType() == nsDisplayItem::TYPE_BACKGROUND_COLOR) {
     320          18 :       nsDisplayList tmpList;
     321           9 :       tmpList.AppendToTop(item);
     322           9 :       item = new (aBuilder) nsDisplayOwnLayer(aBuilder, aFrame, &tmpList, aBuilder->CurrentActiveScrolledRoot());
     323             :     }
     324           9 :     tempItems.AppendToTop(item);
     325             :   }
     326          33 :   aList->AppendToTop(&tempItems);
     327          33 : }
     328             : 
     329             : void
     330          33 : nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     331             :                                      const nsRect&           aDirtyRect,
     332             :                                      const nsDisplayListSet& aLists)
     333             : {
     334          33 :   if (!IsVisibleForPainting(aBuilder))
     335          33 :     return;
     336             : 
     337          33 :   nsFrameLoader* frameLoader = FrameLoader();
     338          33 :   RenderFrameParent* rfp = nullptr;
     339          33 :   if (frameLoader) {
     340          33 :     rfp = frameLoader->GetCurrentRenderFrame();
     341             :   }
     342             : 
     343             :   // If we are pointer-events:none then we don't need to HitTest background
     344             :   bool pointerEventsNone =
     345          33 :     StyleUserInterface()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE;
     346          33 :   if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) {
     347          66 :     nsDisplayListCollection decorations;
     348          33 :     DisplayBorderBackgroundOutline(aBuilder, decorations);
     349          33 :     if (rfp) {
     350             :       // Wrap background colors of <iframe>s with remote subdocuments in their
     351             :       // own layer so we generate a ColorLayer. This is helpful for optimizing
     352             :       // compositing; we can skip compositing the ColorLayer when the
     353             :       // remote content is opaque.
     354          33 :       WrapBackgroundColorInOwnLayer(aBuilder, this, decorations.BorderBackground());
     355             :     }
     356          33 :     decorations.MoveTo(aLists);
     357             :   }
     358             : 
     359          33 :   if (aBuilder->IsForEventDelivery() && pointerEventsNone) {
     360           0 :     return;
     361             :   }
     362             : 
     363             :   // If we're passing pointer events to children then we have to descend into
     364             :   // subdocuments no matter what, to determine which parts are transparent for
     365             :   // hit-testing or event regions.
     366          33 :   bool needToDescend = aBuilder->GetDescendIntoSubdocuments();
     367          33 :   if (!mInnerView || !needToDescend) {
     368           0 :     return;
     369             :   }
     370             : 
     371          33 :   if (rfp) {
     372          33 :     rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
     373          33 :     return;
     374             :   }
     375             : 
     376             :   nsCOMPtr<nsIPresShell> presShell =
     377             :     GetSubdocumentPresShellForPainting(
     378           0 :       aBuilder->IsIgnoringPaintSuppression() ? IGNORE_PAINT_SUPPRESSION : 0);
     379             : 
     380           0 :   if (!presShell) {
     381           0 :     return;
     382             :   }
     383             : 
     384           0 :   nsIFrame* subdocRootFrame = presShell->GetRootFrame();
     385             : 
     386           0 :   nsPresContext* presContext = presShell->GetPresContext();
     387             : 
     388           0 :   int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
     389           0 :   int32_t subdocAPD = presContext->AppUnitsPerDevPixel();
     390             : 
     391           0 :   nsRect dirty;
     392           0 :   bool haveDisplayPort = false;
     393           0 :   bool ignoreViewportScrolling = false;
     394           0 :   nsIFrame* savedIgnoreScrollFrame = nullptr;
     395           0 :   if (subdocRootFrame) {
     396             :     // get the dirty rect relative to the root frame of the subdoc
     397           0 :     dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
     398             :     // and convert into the appunits of the subdoc
     399           0 :     dirty = dirty.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
     400             : 
     401           0 :     if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
     402           0 :       nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
     403           0 :       MOZ_ASSERT(rootScrollableFrame);
     404             :       // Use a copy, so the dirty rect doesn't get modified to the display port.
     405           0 :       nsRect copy = dirty;
     406             :       haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder,
     407           0 :                           &copy, /* aAllowCreateDisplayPort = */ true);
     408             : 
     409           0 :       if (!gfxPrefs::LayoutUseContainersForRootFrames() ||
     410           0 :           !aBuilder->IsPaintingToWindow()) {
     411           0 :         haveDisplayPort = false;
     412             :       }
     413             : 
     414           0 :       ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
     415           0 :       if (ignoreViewportScrolling) {
     416           0 :         savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
     417           0 :         aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
     418             :       }
     419             :     }
     420             : 
     421           0 :     aBuilder->EnterPresShell(subdocRootFrame, pointerEventsNone);
     422             :   } else {
     423           0 :     dirty = aDirtyRect;
     424             :   }
     425             : 
     426           0 :   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     427           0 :   if (ShouldClipSubdocument()) {
     428           0 :     clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
     429             :   }
     430             : 
     431           0 :   nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
     432           0 :   bool constructResolutionItem = subdocRootFrame &&
     433           0 :     (presShell->GetResolution() != 1.0);
     434           0 :   bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
     435           0 :   bool needsOwnLayer = false;
     436           0 :   if (constructResolutionItem ||
     437           0 :       constructZoomItem ||
     438           0 :       haveDisplayPort ||
     439           0 :       presContext->IsRootContentDocument() ||
     440           0 :       (sf && sf->IsScrollingActive(aBuilder)))
     441             :   {
     442           0 :     needsOwnLayer = true;
     443             :   }
     444           0 :   if (!needsOwnLayer && aBuilder->IsBuildingLayerEventRegions() &&
     445           0 :       nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell))
     446             :   {
     447           0 :     needsOwnLayer = true;
     448             :   }
     449             : 
     450           0 :   nsDisplayList childItems;
     451             : 
     452             :   {
     453           0 :     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
     454           0 :     if (needsOwnLayer) {
     455             :       // Clear current clip. There's no point in propagating it down, since
     456             :       // the layer we will construct will be clipped by the current clip.
     457             :       // In fact for nsDisplayZoom propagating it down would be incorrect since
     458             :       // nsDisplayZoom changes the meaning of appunits.
     459           0 :       nestedClipState.Clear();
     460             :     }
     461             : 
     462           0 :     if (subdocRootFrame) {
     463           0 :       nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
     464             :       nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
     465             :           aBuilder,
     466           0 :           ignoreViewportScrolling && rootScrollFrame && rootScrollFrame->GetContent()
     467           0 :               ? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent())
     468           0 :               : aBuilder->GetCurrentScrollParentId());
     469             : 
     470           0 :       aBuilder->SetAncestorHasApzAwareEventHandler(false);
     471             :       subdocRootFrame->
     472           0 :         BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
     473             :     }
     474             : 
     475           0 :     if (!aBuilder->IsForEventDelivery()) {
     476             :       // If we are going to use a displayzoom below then any items we put under
     477             :       // it need to have underlying frames from the subdocument. So we need to
     478             :       // calculate the bounds based on which frame will be the underlying frame
     479             :       // for the canvas background color item.
     480           0 :       nsRect bounds = GetContentRectRelativeToSelf() +
     481           0 :         aBuilder->ToReferenceFrame(this);
     482           0 :       if (subdocRootFrame) {
     483           0 :         bounds = bounds.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
     484             :       }
     485             : 
     486             :       // If we are in print preview/page layout we want to paint the grey
     487             :       // background behind the page, not the canvas color. The canvas color gets
     488             :       // painted on the page itself.
     489           0 :       if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
     490           0 :         presShell->AddPrintPreviewBackgroundItem(
     491             :           *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
     492           0 :           bounds);
     493             :       } else {
     494             :         // Invoke AutoBuildingDisplayList to ensure that the correct dirty rect
     495             :         // is used to compute the visible rect if AddCanvasBackgroundColorItem
     496             :         // creates a display item.
     497           0 :         nsIFrame* frame = subdocRootFrame ? subdocRootFrame : this;
     498             :         nsDisplayListBuilder::AutoBuildingDisplayList
     499           0 :           building(aBuilder, frame, dirty, true);
     500             :         // Add the canvas background color to the bottom of the list. This
     501             :         // happens after we've built the list so that AddCanvasBackgroundColorItem
     502             :         // can monkey with the contents if necessary.
     503           0 :         uint32_t flags = nsIPresShell::FORCE_DRAW | nsIPresShell::ADD_FOR_SUBDOC;
     504           0 :         presShell->AddCanvasBackgroundColorItem(
     505           0 :           *aBuilder, childItems, frame, bounds, NS_RGBA(0,0,0,0), flags);
     506             :       }
     507             :     }
     508             :   }
     509             : 
     510           0 :   if (subdocRootFrame) {
     511           0 :     aBuilder->LeavePresShell(subdocRootFrame, &childItems);
     512             : 
     513           0 :     if (ignoreViewportScrolling) {
     514           0 :       aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
     515             :     }
     516             :   }
     517             : 
     518             :   // Generate a resolution and/or zoom item if needed. If one or both of those is
     519             :   // created, we don't need to create a separate nsDisplaySubDocument.
     520             : 
     521           0 :   uint32_t flags = nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS;
     522             :   // If ignoreViewportScrolling is true then the top most layer we create here
     523             :   // is going to become the scrollable layer for the root scroll frame, so we
     524             :   // want to add nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER to whatever layer
     525             :   // becomes the topmost. We do this below.
     526           0 :   if (constructZoomItem) {
     527           0 :     uint32_t zoomFlags = flags;
     528           0 :     if (ignoreViewportScrolling && !constructResolutionItem) {
     529           0 :       zoomFlags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
     530             :     }
     531             :     nsDisplayZoom* zoomItem =
     532             :       new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
     533           0 :                                    subdocAPD, parentAPD, zoomFlags);
     534           0 :     childItems.AppendToTop(zoomItem);
     535           0 :     needsOwnLayer = false;
     536             :   }
     537             :   // Wrap the zoom item in the resolution item if we have both because we want the
     538             :   // resolution scale applied on top of the app units per dev pixel conversion.
     539           0 :   if (ignoreViewportScrolling) {
     540           0 :     flags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
     541             :   }
     542           0 :   if (constructResolutionItem) {
     543             :     nsDisplayResolution* resolutionItem =
     544             :       new (aBuilder) nsDisplayResolution(aBuilder, subdocRootFrame, &childItems,
     545           0 :                                          flags);
     546           0 :     childItems.AppendToTop(resolutionItem);
     547           0 :     needsOwnLayer = false;
     548             :   }
     549           0 :   if (needsOwnLayer) {
     550             :     // We always want top level content documents to be in their own layer.
     551             :     nsDisplaySubDocument* layerItem = new (aBuilder) nsDisplaySubDocument(
     552             :       aBuilder, subdocRootFrame ? subdocRootFrame : this,
     553           0 :       &childItems, flags);
     554           0 :     childItems.AppendToTop(layerItem);
     555             :   }
     556             : 
     557             :   // If we're using containers for root frames, then the earlier call
     558             :   // to AddCanvasBackgroundColorItem won't have been able to add an
     559             :   // unscrolled color item for overscroll. Try again now that we're
     560             :   // outside the scrolled ContainerLayer.
     561           0 :   if (!aBuilder->IsForEventDelivery() &&
     562           0 :       gfxPrefs::LayoutUseContainersForRootFrames() &&
     563           0 :       !nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
     564           0 :      nsRect bounds = GetContentRectRelativeToSelf() +
     565           0 :        aBuilder->ToReferenceFrame(this);
     566             : 
     567             :     // Invoke AutoBuildingDisplayList to ensure that the correct dirty rect
     568             :     // is used to compute the visible rect if AddCanvasBackgroundColorItem
     569             :     // creates a display item.
     570             :     nsDisplayListBuilder::AutoBuildingDisplayList
     571           0 :       building(aBuilder, this, dirty, true);
     572             :     // Add the canvas background color to the bottom of the list. This
     573             :     // happens after we've built the list so that AddCanvasBackgroundColorItem
     574             :     // can monkey with the contents if necessary.
     575           0 :     uint32_t flags = nsIPresShell::FORCE_DRAW | nsIPresShell::APPEND_UNSCROLLED_ONLY;
     576           0 :     presShell->AddCanvasBackgroundColorItem(
     577           0 :       *aBuilder, childItems, this, bounds, NS_RGBA(0,0,0,0), flags);
     578             :    }
     579             : 
     580           0 :   if (aBuilder->IsForFrameVisibility()) {
     581             :     // We don't add the childItems to the return list as we're dealing with them here.
     582           0 :     presShell->RebuildApproximateFrameVisibilityDisplayList(childItems);
     583           0 :     childItems.DeleteAll();
     584             :   } else {
     585           0 :     aLists.Content()->AppendToTop(&childItems);
     586             :   }
     587             : }
     588             : 
     589             : nscoord
     590           3 : nsSubDocumentFrame::GetIntrinsicISize()
     591             : {
     592           3 :   if (!IsInline()) {
     593           0 :     return 0;  // HTML <frame> has no useful intrinsic isize
     594             :   }
     595             : 
     596           3 :   if (mContent->IsXULElement()) {
     597           3 :     return 0;  // XUL <iframe> and <browser> have no useful intrinsic isize
     598             :   }
     599             : 
     600           0 :   NS_ASSERTION(ObtainIntrinsicSizeFrame() == nullptr,
     601             :                "Intrinsic isize should come from the embedded document.");
     602             : 
     603             :   // We must be an HTML <iframe>.  Default to size of 300px x 150px, for IE
     604             :   // compat (and per CSS2.1 draft).
     605           0 :   WritingMode wm = GetWritingMode();
     606           0 :   return nsPresContext::CSSPixelsToAppUnits(wm.IsVertical() ? 150 : 300);
     607             : }
     608             : 
     609             : nscoord
     610           1 : nsSubDocumentFrame::GetIntrinsicBSize()
     611             : {
     612             :   // <frame> processing does not use this routine, only <iframe>
     613           1 :   NS_ASSERTION(IsInline(), "Shouldn't have been called");
     614             : 
     615           1 :   if (mContent->IsXULElement()) {
     616           1 :     return 0;
     617             :   }
     618             : 
     619           0 :   NS_ASSERTION(ObtainIntrinsicSizeFrame() == nullptr,
     620             :                "Intrinsic bsize should come from the embedded document.");
     621             : 
     622             :   // Use size of 300px x 150px, for compatibility with IE, and per CSS2.1 draft.
     623           0 :   WritingMode wm = GetWritingMode();
     624           0 :   return nsPresContext::CSSPixelsToAppUnits(wm.IsVertical() ? 300 : 150);
     625             : }
     626             : 
     627             : #ifdef DEBUG_FRAME_DUMP
     628             : void
     629           0 : nsSubDocumentFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
     630             : {
     631           0 :   nsCString str;
     632           0 :   ListGeneric(str, aPrefix, aFlags);
     633           0 :   fprintf_stderr(out, "%s\n", str.get());
     634             : 
     635           0 :   if (aFlags & TRAVERSE_SUBDOCUMENT_FRAMES) {
     636           0 :     nsSubDocumentFrame* f = const_cast<nsSubDocumentFrame*>(this);
     637           0 :     nsIFrame* subdocRootFrame = f->GetSubdocumentRootFrame();
     638           0 :     if (subdocRootFrame) {
     639           0 :       nsCString pfx(aPrefix);
     640           0 :       pfx += "  ";
     641           0 :       subdocRootFrame->List(out, pfx.get(), aFlags);
     642             :     }
     643             :   }
     644           0 : }
     645             : 
     646           0 : nsresult nsSubDocumentFrame::GetFrameName(nsAString& aResult) const
     647             : {
     648           0 :   return MakeFrameName(NS_LITERAL_STRING("FrameOuter"), aResult);
     649             : }
     650             : #endif
     651             : 
     652             : /* virtual */ nscoord
     653           1 : nsSubDocumentFrame::GetMinISize(gfxContext *aRenderingContext)
     654             : {
     655             :   nscoord result;
     656           2 :   DISPLAY_MIN_WIDTH(this, result);
     657             : 
     658           1 :   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     659           1 :   if (subDocRoot) {
     660           0 :     result = subDocRoot->GetMinISize(aRenderingContext);
     661             :   } else {
     662           1 :     result = GetIntrinsicISize();
     663             :   }
     664             : 
     665           2 :   return result;
     666             : }
     667             : 
     668             : /* virtual */ nscoord
     669           1 : nsSubDocumentFrame::GetPrefISize(gfxContext *aRenderingContext)
     670             : {
     671             :   nscoord result;
     672           2 :   DISPLAY_PREF_WIDTH(this, result);
     673             : 
     674           1 :   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     675           1 :   if (subDocRoot) {
     676           0 :     result = subDocRoot->GetPrefISize(aRenderingContext);
     677             :   } else {
     678           1 :     result = GetIntrinsicISize();
     679             :   }
     680             : 
     681           2 :   return result;
     682             : }
     683             : 
     684             : /* virtual */ IntrinsicSize
     685           0 : nsSubDocumentFrame::GetIntrinsicSize()
     686             : {
     687           0 :   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     688           0 :   if (subDocRoot) {
     689           0 :     return subDocRoot->GetIntrinsicSize();
     690             :   }
     691           0 :   return nsAtomicContainerFrame::GetIntrinsicSize();
     692             : }
     693             : 
     694             : /* virtual */ nsSize
     695           1 : nsSubDocumentFrame::GetIntrinsicRatio()
     696             : {
     697           1 :   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     698           1 :   if (subDocRoot) {
     699           0 :     return subDocRoot->GetIntrinsicRatio();
     700             :   }
     701           1 :   return nsAtomicContainerFrame::GetIntrinsicRatio();
     702             : }
     703             : 
     704             : /* virtual */
     705             : LogicalSize
     706           1 : nsSubDocumentFrame::ComputeAutoSize(gfxContext*         aRenderingContext,
     707             :                                     WritingMode         aWM,
     708             :                                     const LogicalSize&  aCBSize,
     709             :                                     nscoord             aAvailableISize,
     710             :                                     const LogicalSize&  aMargin,
     711             :                                     const LogicalSize&  aBorder,
     712             :                                     const LogicalSize&  aPadding,
     713             :                                     ComputeSizeFlags    aFlags)
     714             : {
     715           1 :   if (!IsInline()) {
     716             :     return nsFrame::ComputeAutoSize(aRenderingContext, aWM, aCBSize,
     717             :                                     aAvailableISize, aMargin, aBorder,
     718           0 :                                     aPadding, aFlags);
     719             :   }
     720             : 
     721           1 :   const WritingMode wm = GetWritingMode();
     722           1 :   LogicalSize result(wm, GetIntrinsicISize(), GetIntrinsicBSize());
     723           1 :   return result.ConvertTo(aWM, wm);
     724             : }
     725             : 
     726             : 
     727             : /* virtual */
     728             : LogicalSize
     729           1 : nsSubDocumentFrame::ComputeSize(gfxContext*         aRenderingContext,
     730             :                                 WritingMode         aWM,
     731             :                                 const LogicalSize&  aCBSize,
     732             :                                 nscoord             aAvailableISize,
     733             :                                 const LogicalSize&  aMargin,
     734             :                                 const LogicalSize&  aBorder,
     735             :                                 const LogicalSize&  aPadding,
     736             :                                 ComputeSizeFlags    aFlags)
     737             : {
     738           1 :   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     739           1 :   if (subDocRoot) {
     740             :     return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
     741           0 :                                               subDocRoot->GetIntrinsicSize(),
     742           0 :                                               subDocRoot->GetIntrinsicRatio(),
     743             :                                               aCBSize, aMargin, aBorder,
     744           0 :                                               aPadding, aFlags);
     745             :   }
     746             :   return nsAtomicContainerFrame::ComputeSize(aRenderingContext, aWM,
     747             :                                              aCBSize, aAvailableISize,
     748             :                                              aMargin, aBorder, aPadding,
     749           1 :                                              aFlags);
     750             : }
     751             : 
     752             : void
     753           4 : nsSubDocumentFrame::Reflow(nsPresContext*           aPresContext,
     754             :                            ReflowOutput&     aDesiredSize,
     755             :                            const ReflowInput& aReflowInput,
     756             :                            nsReflowStatus&          aStatus)
     757             : {
     758           4 :   MarkInReflow();
     759           4 :   DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame");
     760           8 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     761           4 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     762             :      ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d",
     763             :       aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
     764             : 
     765           4 :   NS_ASSERTION(aReflowInput.ComputedWidth() != NS_UNCONSTRAINEDSIZE,
     766             :                "Shouldn't have unconstrained stuff here "
     767             :                "thanks to the rules of reflow");
     768           4 :   NS_ASSERTION(NS_INTRINSICSIZE != aReflowInput.ComputedHeight(),
     769             :                "Shouldn't have unconstrained stuff here "
     770             :                "thanks to ComputeAutoSize");
     771             : 
     772           4 :   aStatus.Reset();
     773             : 
     774           4 :   NS_ASSERTION(mContent->GetPrimaryFrame() == this,
     775             :                "Shouldn't happen");
     776             : 
     777             :   // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed>
     778           4 :   aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
     779           4 :                        aReflowInput.ComputedSizeWithBorderPadding());
     780             : 
     781             :   // "offset" is the offset of our content area from our frame's
     782             :   // top-left corner.
     783           4 :   nsPoint offset = nsPoint(aReflowInput.ComputedPhysicalBorderPadding().left,
     784           8 :                            aReflowInput.ComputedPhysicalBorderPadding().top);
     785             : 
     786           4 :   if (mInnerView) {
     787           4 :     const nsMargin& bp = aReflowInput.ComputedPhysicalBorderPadding();
     788           4 :     nsSize innerSize(aDesiredSize.Width() - bp.LeftRight(),
     789           8 :                      aDesiredSize.Height() - bp.TopBottom());
     790             : 
     791             :     // Size & position the view according to 'object-fit' & 'object-position'.
     792           4 :     nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
     793           8 :     IntrinsicSize intrinsSize;
     794           4 :     nsSize intrinsRatio;
     795           4 :     if (subDocRoot) {
     796           0 :       intrinsSize = subDocRoot->GetIntrinsicSize();
     797           0 :       intrinsRatio = subDocRoot->GetIntrinsicRatio();
     798             :     }
     799             :     nsRect destRect =
     800           8 :       nsLayoutUtils::ComputeObjectDestRect(nsRect(offset, innerSize),
     801             :                                            intrinsSize, intrinsRatio,
     802          12 :                                            StylePosition());
     803             : 
     804           4 :     nsViewManager* vm = mInnerView->GetViewManager();
     805           4 :     vm->MoveViewTo(mInnerView, destRect.x, destRect.y);
     806           4 :     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), destRect.Size()), true);
     807             :   }
     808             : 
     809           4 :   aDesiredSize.SetOverflowAreasToDesiredBounds();
     810           4 :   if (!ShouldClipSubdocument()) {
     811           0 :     nsIFrame* subdocRootFrame = GetSubdocumentRootFrame();
     812           0 :     if (subdocRootFrame) {
     813           0 :       aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset);
     814             :     }
     815             :   }
     816             : 
     817           4 :   FinishAndStoreOverflow(&aDesiredSize);
     818             : 
     819           4 :   if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
     820           3 :     PresContext()->PresShell()->PostReflowCallback(this);
     821           3 :     mPostedReflowCallback = true;
     822             :   }
     823             : 
     824           4 :   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     825             :      ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%s",
     826             :       aDesiredSize.Width(), aDesiredSize.Height(), ToString(aStatus).c_str()));
     827             : 
     828           4 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     829           4 : }
     830             : 
     831             : bool
     832           3 : nsSubDocumentFrame::ReflowFinished()
     833             : {
     834           3 :   if (mFrameLoader) {
     835           6 :     AutoWeakFrame weakFrame(this);
     836             : 
     837           3 :     mFrameLoader->UpdatePositionAndSize(this);
     838             : 
     839           3 :     if (weakFrame.IsAlive()) {
     840             :       // Make sure that we can post a reflow callback in the future.
     841           3 :       mPostedReflowCallback = false;
     842             :     }
     843             :   } else {
     844           0 :     mPostedReflowCallback = false;
     845             :   }
     846           3 :   return false;
     847             : }
     848             : 
     849             : void
     850           0 : nsSubDocumentFrame::ReflowCallbackCanceled()
     851             : {
     852           0 :   mPostedReflowCallback = false;
     853           0 : }
     854             : 
     855             : nsresult
     856           1 : nsSubDocumentFrame::AttributeChanged(int32_t aNameSpaceID,
     857             :                                      nsIAtom* aAttribute,
     858             :                                      int32_t aModType)
     859             : {
     860           1 :   if (aNameSpaceID != kNameSpaceID_None) {
     861           0 :     return NS_OK;
     862             :   }
     863             : 
     864             :   // If the noResize attribute changes, dis/allow frame to be resized
     865           1 :   if (aAttribute == nsGkAtoms::noresize) {
     866             :     // Note that we're not doing content type checks, but that's ok -- if
     867             :     // they'd fail we will just end up with a null framesetFrame.
     868           0 :     if (mContent->GetParent()->IsHTMLElement(nsGkAtoms::frameset)) {
     869           0 :       nsIFrame* parentFrame = GetParent();
     870             : 
     871           0 :       if (parentFrame) {
     872             :         // There is no interface for nsHTMLFramesetFrame so QI'ing to
     873             :         // concrete class, yay!
     874           0 :         nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(parentFrame);
     875           0 :         if (framesetFrame) {
     876           0 :           framesetFrame->RecalculateBorderResize();
     877             :         }
     878             :       }
     879             :     }
     880             :   }
     881           1 :   else if (aAttribute == nsGkAtoms::showresizer) {
     882           0 :     nsIFrame* rootFrame = GetSubdocumentRootFrame();
     883           0 :     if (rootFrame) {
     884           0 :       rootFrame->PresContext()->PresShell()->
     885           0 :         FrameNeedsReflow(rootFrame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     886             :     }
     887             :   }
     888           2 :   else if (aAttribute == nsGkAtoms::marginwidth ||
     889           1 :            aAttribute == nsGkAtoms::marginheight) {
     890             : 
     891             :     // Retrieve the attributes
     892           0 :     CSSIntSize margins = GetMarginAttributes();
     893             : 
     894             :     // Notify the frameloader
     895           0 :     RefPtr<nsFrameLoader> frameloader = FrameLoader();
     896           0 :     if (frameloader)
     897           0 :       frameloader->MarginsChanged(margins.width, margins.height);
     898             :   }
     899             : 
     900           1 :   return NS_OK;
     901             : }
     902             : 
     903             : nsIFrame*
     904           3 : NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     905             : {
     906           3 :   return new (aPresShell) nsSubDocumentFrame(aContext);
     907             : }
     908             : 
     909           3 : NS_IMPL_FRAMEARENA_HELPERS(nsSubDocumentFrame)
     910             : 
     911           0 : class nsHideViewer : public Runnable {
     912             : public:
     913           0 :   nsHideViewer(nsIContent* aFrameElement,
     914             :                nsFrameLoader* aFrameLoader,
     915             :                nsIPresShell* aPresShell,
     916             :                bool aHideViewerIfFrameless)
     917           0 :     : mozilla::Runnable("nsHideViewer")
     918             :     , mFrameElement(aFrameElement)
     919             :     , mFrameLoader(aFrameLoader)
     920             :     , mPresShell(aPresShell)
     921           0 :     , mHideViewerIfFrameless(aHideViewerIfFrameless)
     922             :   {
     923           0 :     NS_ASSERTION(mFrameElement, "Must have a frame element");
     924           0 :     NS_ASSERTION(mFrameLoader, "Must have a frame loader");
     925           0 :     NS_ASSERTION(mPresShell, "Must have a presshell");
     926           0 :   }
     927             : 
     928           0 :   NS_IMETHOD Run() override
     929             :   {
     930             :     // Flush frames, to ensure any pending display:none changes are made.
     931             :     // Note it can be unsafe to flush if we've destroyed the presentation
     932             :     // for some other reason, like if we're shutting down.
     933           0 :     if (!mPresShell->IsDestroying()) {
     934           0 :       mPresShell->FlushPendingNotifications(FlushType::Frames);
     935             :     }
     936             : 
     937             :     // Either the frame has been constructed by now, or it never will be,
     938             :     // either way we want to clear the stashed views.
     939           0 :     mFrameLoader->SetDetachedSubdocFrame(nullptr, nullptr);
     940             : 
     941           0 :     nsSubDocumentFrame* frame = do_QueryFrame(mFrameElement->GetPrimaryFrame());
     942           0 :     if ((!frame && mHideViewerIfFrameless) ||
     943           0 :         mPresShell->IsDestroying()) {
     944             :       // Either the frame element has no nsIFrame or the presshell is being
     945             :       // destroyed. Hide the nsFrameLoader, which destroys the presentation.
     946           0 :       mFrameLoader->Hide();
     947             :     }
     948           0 :     return NS_OK;
     949             :   }
     950             : private:
     951             :   nsCOMPtr<nsIContent> mFrameElement;
     952             :   RefPtr<nsFrameLoader> mFrameLoader;
     953             :   nsCOMPtr<nsIPresShell> mPresShell;
     954             :   bool mHideViewerIfFrameless;
     955             : };
     956             : 
     957             : static nsView*
     958             : BeginSwapDocShellsForViews(nsView* aSibling);
     959             : 
     960             : void
     961           2 : nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
     962             : {
     963           2 :   if (mPostedReflowCallback) {
     964           0 :     PresContext()->PresShell()->CancelReflowCallback(this);
     965           0 :     mPostedReflowCallback = false;
     966             :   }
     967             : 
     968             :   // Detach the subdocument's views and stash them in the frame loader.
     969             :   // We can then reattach them if we're being reframed (for example if
     970             :   // the frame has been made position:fixed).
     971           4 :   RefPtr<nsFrameLoader> frameloader = FrameLoader();
     972           2 :   if (frameloader) {
     973           2 :     nsView* detachedViews = ::BeginSwapDocShellsForViews(mInnerView->GetFirstChild());
     974             : 
     975           2 :     if (detachedViews && detachedViews->GetFrame()) {
     976           0 :       MOZ_ASSERT(mContent->OwnerDoc());
     977           0 :       frameloader->SetDetachedSubdocFrame(
     978           0 :         detachedViews->GetFrame(), mContent->OwnerDoc());
     979             : 
     980             :       // We call nsFrameLoader::HideViewer() in a script runner so that we can
     981             :       // safely determine whether the frame is being reframed or destroyed.
     982             :       nsContentUtils::AddScriptRunner(
     983             :         new nsHideViewer(mContent,
     984             :                          frameloader,
     985           0 :                          PresContext()->PresShell(),
     986           0 :                          (mDidCreateDoc || mCallingShow)));
     987             :     } else {
     988           2 :       frameloader->SetDetachedSubdocFrame(nullptr, nullptr);
     989           2 :       if (mDidCreateDoc || mCallingShow) {
     990           2 :         frameloader->Hide();
     991             :       }
     992             :     }
     993             :   }
     994             : 
     995           2 :   nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
     996           2 : }
     997             : 
     998             : CSSIntSize
     999           3 : nsSubDocumentFrame::GetMarginAttributes()
    1000             : {
    1001           3 :   CSSIntSize result(-1, -1);
    1002           3 :   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
    1003           3 :   if (content) {
    1004           0 :     const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::marginwidth);
    1005           0 :     if (attr && attr->Type() == nsAttrValue::eInteger)
    1006           0 :       result.width = attr->GetIntegerValue();
    1007           0 :     attr = content->GetParsedAttr(nsGkAtoms::marginheight);
    1008           0 :     if (attr && attr->Type() == nsAttrValue::eInteger)
    1009           0 :       result.height = attr->GetIntegerValue();
    1010             :   }
    1011           3 :   return result;
    1012             : }
    1013             : 
    1014             : nsFrameLoader*
    1015          50 : nsSubDocumentFrame::FrameLoader()
    1016             : {
    1017          50 :   nsIContent* content = GetContent();
    1018          50 :   if (!content)
    1019           0 :     return nullptr;
    1020             : 
    1021          50 :   if (!mFrameLoader) {
    1022           6 :     nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content);
    1023           3 :     if (loaderOwner) {
    1024           3 :       mFrameLoader = loaderOwner->GetFrameLoader();
    1025             :     }
    1026             :   }
    1027          50 :   return mFrameLoader;
    1028             : }
    1029             : 
    1030             : // XXX this should be called ObtainDocShell or something like that,
    1031             : // to indicate that it could have side effects
    1032             : nsresult
    1033           2 : nsSubDocumentFrame::GetDocShell(nsIDocShell **aDocShell)
    1034             : {
    1035           2 :   *aDocShell = nullptr;
    1036             : 
    1037           2 :   NS_ENSURE_STATE(FrameLoader());
    1038           2 :   return mFrameLoader->GetDocShell(aDocShell);
    1039             : }
    1040             : 
    1041             : static void
    1042           0 : DestroyDisplayItemDataForFrames(nsIFrame* aFrame)
    1043             : {
    1044           0 :   FrameLayerBuilder::DestroyDisplayItemDataFor(aFrame);
    1045             : 
    1046           0 :   nsIFrame::ChildListIterator lists(aFrame);
    1047           0 :   for (; !lists.IsDone(); lists.Next()) {
    1048           0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    1049           0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    1050           0 :       DestroyDisplayItemDataForFrames(childFrames.get());
    1051             :     }
    1052             :   }
    1053           0 : }
    1054             : 
    1055             : static bool
    1056           1 : BeginSwapDocShellsForDocument(nsIDocument* aDocument, void*)
    1057             : {
    1058           1 :   NS_PRECONDITION(aDocument, "");
    1059             : 
    1060           1 :   nsIPresShell* shell = aDocument->GetShell();
    1061           1 :   if (shell) {
    1062             :     // Disable painting while the views are detached, see bug 946929.
    1063           1 :     shell->SetNeverPainting(true);
    1064             : 
    1065           1 :     nsIFrame* rootFrame = shell->GetRootFrame();
    1066           1 :     if (rootFrame) {
    1067           0 :       ::DestroyDisplayItemDataForFrames(rootFrame);
    1068             :     }
    1069             :   }
    1070             :   aDocument->EnumerateActivityObservers(
    1071           1 :     nsPluginFrame::BeginSwapDocShells, nullptr);
    1072           1 :   aDocument->EnumerateSubDocuments(BeginSwapDocShellsForDocument, nullptr);
    1073           1 :   return true;
    1074             : }
    1075             : 
    1076             : static nsView*
    1077           2 : BeginSwapDocShellsForViews(nsView* aSibling)
    1078             : {
    1079             :   // Collect the removed sibling views in reverse order in 'removedViews'.
    1080           2 :   nsView* removedViews = nullptr;
    1081           4 :   while (aSibling) {
    1082           1 :     nsIDocument* doc = ::GetDocumentFromView(aSibling);
    1083           1 :     if (doc) {
    1084           1 :       ::BeginSwapDocShellsForDocument(doc, nullptr);
    1085             :     }
    1086           1 :     nsView* next = aSibling->GetNextSibling();
    1087           1 :     aSibling->GetViewManager()->RemoveChild(aSibling);
    1088           1 :     aSibling->SetNextSibling(removedViews);
    1089           1 :     removedViews = aSibling;
    1090           1 :     aSibling = next;
    1091             :   }
    1092           2 :   return removedViews;
    1093             : }
    1094             : 
    1095             : static void
    1096           0 : InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent)
    1097             : {
    1098           0 :   NS_PRECONDITION(aParent, "");
    1099           0 :   NS_PRECONDITION(!aParent->GetFirstChild(), "inserting into non-empty list");
    1100             : 
    1101           0 :   nsViewManager* vm = aParent->GetViewManager();
    1102           0 :   while (aSibling) {
    1103           0 :     nsView* next = aSibling->GetNextSibling();
    1104           0 :     aSibling->SetNextSibling(nullptr);
    1105             :     // true means 'after' in document order which is 'before' in view order,
    1106             :     // so this call prepends the child, thus reversing the siblings as we go.
    1107           0 :     vm->InsertChild(aParent, aSibling, nullptr, true);
    1108           0 :     aSibling = next;
    1109             :   }
    1110           0 : }
    1111             : 
    1112             : nsresult
    1113           0 : nsSubDocumentFrame::BeginSwapDocShells(nsIFrame* aOther)
    1114             : {
    1115           0 :   if (!aOther || !aOther->IsSubDocumentFrame()) {
    1116           0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1117             :   }
    1118             : 
    1119           0 :   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
    1120           0 :   if (!mFrameLoader || !mDidCreateDoc || mCallingShow ||
    1121           0 :       !other->mFrameLoader || !other->mDidCreateDoc) {
    1122           0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1123             :   }
    1124             : 
    1125           0 :   if (mInnerView && other->mInnerView) {
    1126           0 :     nsView* ourSubdocViews = mInnerView->GetFirstChild();
    1127           0 :     nsView* ourRemovedViews = ::BeginSwapDocShellsForViews(ourSubdocViews);
    1128           0 :     nsView* otherSubdocViews = other->mInnerView->GetFirstChild();
    1129           0 :     nsView* otherRemovedViews = ::BeginSwapDocShellsForViews(otherSubdocViews);
    1130             : 
    1131           0 :     ::InsertViewsInReverseOrder(ourRemovedViews, other->mInnerView);
    1132           0 :     ::InsertViewsInReverseOrder(otherRemovedViews, mInnerView);
    1133             :   }
    1134           0 :   mFrameLoader.swap(other->mFrameLoader);
    1135           0 :   return NS_OK;
    1136             : }
    1137             : 
    1138             : static bool
    1139           0 : EndSwapDocShellsForDocument(nsIDocument* aDocument, void*)
    1140             : {
    1141           0 :   NS_PRECONDITION(aDocument, "");
    1142             : 
    1143             :   // Our docshell and view trees have been updated for the new hierarchy.
    1144             :   // Now also update all nsDeviceContext::mWidget to that of the
    1145             :   // container view in the new hierarchy.
    1146           0 :   nsCOMPtr<nsIDocShell> ds = aDocument->GetDocShell();
    1147           0 :   if (ds) {
    1148           0 :     nsCOMPtr<nsIContentViewer> cv;
    1149           0 :     ds->GetContentViewer(getter_AddRefs(cv));
    1150           0 :     while (cv) {
    1151           0 :       RefPtr<nsPresContext> pc;
    1152           0 :       cv->GetPresContext(getter_AddRefs(pc));
    1153           0 :       if (pc && pc->GetPresShell()) {
    1154           0 :         pc->GetPresShell()->SetNeverPainting(ds->IsInvisible());
    1155             :       }
    1156           0 :       nsDeviceContext* dc = pc ? pc->DeviceContext() : nullptr;
    1157           0 :       if (dc) {
    1158           0 :         nsView* v = cv->FindContainerView();
    1159           0 :         dc->Init(v ? v->GetNearestWidget(nullptr) : nullptr);
    1160             :       }
    1161           0 :       nsCOMPtr<nsIContentViewer> prev;
    1162           0 :       cv->GetPreviousViewer(getter_AddRefs(prev));
    1163           0 :       cv = prev;
    1164             :     }
    1165             :   }
    1166             : 
    1167             :   aDocument->EnumerateActivityObservers(
    1168           0 :     nsPluginFrame::EndSwapDocShells, nullptr);
    1169           0 :   aDocument->EnumerateSubDocuments(EndSwapDocShellsForDocument, nullptr);
    1170           0 :   return true;
    1171             : }
    1172             : 
    1173             : static void
    1174           0 : EndSwapDocShellsForViews(nsView* aSibling)
    1175             : {
    1176           0 :   for ( ; aSibling; aSibling = aSibling->GetNextSibling()) {
    1177           0 :     nsIDocument* doc = ::GetDocumentFromView(aSibling);
    1178           0 :     if (doc) {
    1179           0 :       ::EndSwapDocShellsForDocument(doc, nullptr);
    1180             :     }
    1181           0 :     nsIFrame *frame = aSibling->GetFrame();
    1182           0 :     if (frame) {
    1183           0 :       nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
    1184           0 :       if (parent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
    1185           0 :         nsIFrame::AddInPopupStateBitToDescendants(frame);
    1186             :       } else {
    1187           0 :         nsIFrame::RemoveInPopupStateBitFromDescendants(frame);
    1188             :       }
    1189           0 :       if (frame->HasInvalidFrameInSubtree()) {
    1190           0 :         while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT | NS_FRAME_IS_NONDISPLAY)) {
    1191           0 :           parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
    1192           0 :           parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
    1193             :         }
    1194             :       }
    1195             :     }
    1196             :   }
    1197           0 : }
    1198             : 
    1199             : void
    1200           0 : nsSubDocumentFrame::EndSwapDocShells(nsIFrame* aOther)
    1201             : {
    1202           0 :   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
    1203           0 :   AutoWeakFrame weakThis(this);
    1204           0 :   AutoWeakFrame weakOther(aOther);
    1205             : 
    1206           0 :   if (mInnerView) {
    1207           0 :     ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
    1208             :   }
    1209           0 :   if (other->mInnerView) {
    1210           0 :     ::EndSwapDocShellsForViews(other->mInnerView->GetFirstChild());
    1211             :   }
    1212             : 
    1213             :   // Now make sure we reflow both frames, in case their contents
    1214             :   // determine their size.
    1215             :   // And repaint them, for good measure, in case there's nothing
    1216             :   // interesting that happens during reflow.
    1217           0 :   if (weakThis.IsAlive()) {
    1218           0 :     PresContext()->PresShell()->
    1219           0 :       FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
    1220           0 :     InvalidateFrameSubtree();
    1221             :   }
    1222           0 :   if (weakOther.IsAlive()) {
    1223           0 :     other->PresContext()->PresShell()->
    1224           0 :       FrameNeedsReflow(other, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
    1225           0 :     other->InvalidateFrameSubtree();
    1226             :   }
    1227           0 : }
    1228             : 
    1229             : nsView*
    1230          37 : nsSubDocumentFrame::EnsureInnerView()
    1231             : {
    1232          37 :   if (mInnerView) {
    1233          34 :     return mInnerView;
    1234             :   }
    1235             : 
    1236             :   // create, init, set the parent of the view
    1237           3 :   nsView* outerView = GetView();
    1238           3 :   NS_ASSERTION(outerView, "Must have an outer view already");
    1239           6 :   nsRect viewBounds(0, 0, 0, 0); // size will be fixed during reflow
    1240             : 
    1241           3 :   nsViewManager* viewMan = outerView->GetViewManager();
    1242           3 :   nsView* innerView = viewMan->CreateView(viewBounds, outerView);
    1243           3 :   if (!innerView) {
    1244           0 :     NS_ERROR("Could not create inner view");
    1245           0 :     return nullptr;
    1246             :   }
    1247           3 :   mInnerView = innerView;
    1248           3 :   viewMan->InsertChild(outerView, innerView, nullptr, true);
    1249             : 
    1250           3 :   return mInnerView;
    1251             : }
    1252             : 
    1253             : nsIFrame*
    1254          11 : nsSubDocumentFrame::ObtainIntrinsicSizeFrame()
    1255             : {
    1256          22 :   nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(GetContent());
    1257          11 :   if (olc) {
    1258             :     // We are an HTML <object>, <embed> or <applet> (a replaced element).
    1259             : 
    1260             :     // Try to get an nsIFrame for our sub-document's document element
    1261           0 :     nsIFrame* subDocRoot = nullptr;
    1262             : 
    1263           0 :     nsCOMPtr<nsIDocShell> docShell;
    1264           0 :     GetDocShell(getter_AddRefs(docShell));
    1265           0 :     if (docShell) {
    1266           0 :       nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
    1267           0 :       if (presShell) {
    1268           0 :         nsIScrollableFrame* scrollable = presShell->GetRootScrollFrameAsScrollable();
    1269           0 :         if (scrollable) {
    1270           0 :           nsIFrame* scrolled = scrollable->GetScrolledFrame();
    1271           0 :           if (scrolled) {
    1272           0 :             subDocRoot = scrolled->PrincipalChildList().FirstChild();
    1273             :           }
    1274             :         }
    1275             :       }
    1276             :     }
    1277             : 
    1278           0 :     if (subDocRoot && subDocRoot->GetContent() &&
    1279           0 :         subDocRoot->GetContent()->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
    1280           0 :       return subDocRoot; // SVG documents have an intrinsic size
    1281             :     }
    1282             :   }
    1283          11 :   return nullptr;
    1284             : }

Generated by: LCOV version 1.13