layout/generic/nsSubDocumentFrame.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 /*
     7  * rendering object for replaced elements that contain a document, such
     8  * as <frame>, <iframe>, and some <object>s
     9  */
    11 #include "nsSubDocumentFrame.h"
    13 #include "mozilla/layout/RenderFrameParent.h"
    15 #include "nsCOMPtr.h"
    16 #include "nsGenericHTMLElement.h"
    17 #include "nsGenericHTMLFrameElement.h"
    18 #include "nsAttrValueInlines.h"
    19 #include "nsIDocShell.h"
    20 #include "nsIContentViewer.h"
    21 #include "nsPresContext.h"
    22 #include "nsIPresShell.h"
    23 #include "nsIDocument.h"
    24 #include "nsView.h"
    25 #include "nsViewManager.h"
    26 #include "nsGkAtoms.h"
    27 #include "nsStyleConsts.h"
    28 #include "nsFrameSetFrame.h"
    29 #include "nsIDOMHTMLFrameElement.h"
    30 #include "nsIScrollable.h"
    31 #include "nsNameSpaceManager.h"
    32 #include "nsDisplayList.h"
    33 #include "nsIScrollableFrame.h"
    34 #include "nsIObjectLoadingContent.h"
    35 #include "nsLayoutUtils.h"
    36 #include "FrameLayerBuilder.h"
    37 #include "nsObjectFrame.h"
    38 #include "nsContentUtils.h"
    39 #include "nsIPermissionManager.h"
    40 #include "nsServiceManagerUtils.h"
    42 using namespace mozilla;
    43 using mozilla::layout::RenderFrameParent;
    45 static nsIDocument*
    46 GetDocumentFromView(nsView* aView)
    47 {
    48   NS_PRECONDITION(aView, "");
    50   nsIFrame* f = aView->GetFrame();
    51   nsIPresShell* ps =  f ? f->PresContext()->PresShell() : nullptr;
    52   return ps ? ps->GetDocument() : nullptr;
    53 }
    55 nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
    56   : nsLeafFrame(aContext)
    57   , mIsInline(false)
    58   , mPostedReflowCallback(false)
    59   , mDidCreateDoc(false)
    60   , mCallingShow(false)
    61 {
    62 }
    64 #ifdef ACCESSIBILITY
    65 a11y::AccType
    66 nsSubDocumentFrame::AccessibleType()
    67 {
    68   return a11y::eOuterDocType;
    69 }
    70 #endif
    72 NS_QUERYFRAME_HEAD(nsSubDocumentFrame)
    73   NS_QUERYFRAME_ENTRY(nsSubDocumentFrame)
    74 NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame)
    76 class AsyncFrameInit : public nsRunnable
    77 {
    78 public:
    79   AsyncFrameInit(nsIFrame* aFrame) : mFrame(aFrame) {}
    80   NS_IMETHOD Run()
    81   {
    82     if (mFrame.IsAlive()) {
    83       static_cast<nsSubDocumentFrame*>(mFrame.GetFrame())->ShowViewer();
    84     }
    85     return NS_OK;
    86   }
    87 private:
    88   nsWeakFrame mFrame;
    89 };
    91 static void
    92 InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent);
    94 static void
    95 EndSwapDocShellsForViews(nsView* aView);
    97 void
    98 nsSubDocumentFrame::Init(nsIContent*     aContent,
    99                          nsIFrame*       aParent,
   100                          nsIFrame*       aPrevInFlow)
   101 {
   102   // determine if we are a <frame> or <iframe>
   103   if (aContent) {
   104     nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = do_QueryInterface(aContent);
   105     mIsInline = frameElem ? false : true;
   106   }
   108   nsLeafFrame::Init(aContent, aParent, aPrevInFlow);
   110   // We are going to create an inner view.  If we need a view for the
   111   // OuterFrame but we wait for the normal view creation path in
   112   // nsCSSFrameConstructor, then we will lose because the inner view's
   113   // parent will already have been set to some outer view (e.g., the
   114   // canvas) when it really needs to have this frame's view as its
   115   // parent. So, create this frame's view right away, whether we
   116   // really need it or not, and the inner view will get it as the
   117   // parent.
   118   if (!HasView()) {
   119     nsContainerFrame::CreateViewForFrame(this, true);
   120   }
   121   EnsureInnerView();
   123   // Set the primary frame now so that nsDocumentViewer::FindContainerView
   124   // called from within EndSwapDocShellsForViews below can find it if needed.
   125   aContent->SetPrimaryFrame(this);
   127   // If we have a detached subdoc's root view on our frame loader, re-insert
   128   // it into the view tree. This happens when we've been reframed, and
   129   // ensures the presentation persists across reframes. If the frame element
   130   // has changed documents however, we blow away the presentation.
   131   nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
   132   if (frameloader) {
   133     nsCOMPtr<nsIDocument> oldContainerDoc;
   134     nsView* detachedViews =
   135       frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
   136     if (detachedViews) {
   137       if (oldContainerDoc == aContent->OwnerDoc()) {
   138         // Restore stashed presentation.
   139         ::InsertViewsInReverseOrder(detachedViews, mInnerView);
   140         ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
   141       } else {
   142         // Presentation is for a different document, don't restore it.
   143         frameloader->Hide();
   144       }
   145     }
   146     frameloader->SetDetachedSubdocView(nullptr, nullptr);
   147   }
   149   nsContentUtils::AddScriptRunner(new AsyncFrameInit(this));
   150 }
   152 void
   153 nsSubDocumentFrame::ShowViewer()
   154 {
   155   if (mCallingShow) {
   156     return;
   157   }
   159   if (!PresContext()->IsDynamic()) {
   160     // We let the printing code take care of loading the document; just
   161     // create the inner view for it to use.
   162     (void) EnsureInnerView();
   163   } else {
   164     nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
   165     if (frameloader) {
   166       nsIntSize margin = GetMarginAttributes();
   167       nsWeakFrame weakThis(this);
   168       mCallingShow = true;
   169       const nsAttrValue* attrValue =
   170         GetContent()->AsElement()->GetParsedAttr(nsGkAtoms::scrolling);
   171       int32_t scrolling =
   172         nsGenericHTMLFrameElement::MapScrollingAttribute(attrValue);
   173       bool didCreateDoc =
   174         frameloader->Show(margin.width, margin.height,
   175                           scrolling, scrolling, this);
   176       if (!weakThis.IsAlive()) {
   177         return;
   178       }
   179       mCallingShow = false;
   180       mDidCreateDoc = didCreateDoc;
   181     }
   182   }
   183 }
   185 nsIFrame*
   186 nsSubDocumentFrame::GetSubdocumentRootFrame()
   187 {
   188   if (!mInnerView)
   189     return nullptr;
   190   nsView* subdocView = mInnerView->GetFirstChild();
   191   return subdocView ? subdocView->GetFrame() : nullptr;
   192 }
   194 nsIntSize
   195 nsSubDocumentFrame::GetSubdocumentSize()
   196 {
   197   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
   198     nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
   199     if (frameloader) {
   200       nsCOMPtr<nsIDocument> oldContainerDoc;
   201       nsView* detachedViews =
   202         frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
   203       if (detachedViews) {
   204         nsSize size = detachedViews->GetBounds().Size();
   205         nsPresContext* presContext = detachedViews->GetFrame()->PresContext();
   206         return nsIntSize(presContext->AppUnitsToDevPixels(size.width),
   207                          presContext->AppUnitsToDevPixels(size.height));
   208       }
   209     }
   210     // Pick some default size for now.  Using 10x10 because that's what the
   211     // code used to do.
   212     return nsIntSize(10, 10);
   213   } else {
   214     nsSize docSizeAppUnits;
   215     nsPresContext* presContext = PresContext();
   216     nsCOMPtr<nsIDOMHTMLFrameElement> frameElem =
   217       do_QueryInterface(GetContent());
   218     if (frameElem) {
   219       docSizeAppUnits = GetSize();
   220     } else {
   221       docSizeAppUnits = GetContentRect().Size();
   222     }
   223     return nsIntSize(presContext->AppUnitsToDevPixels(docSizeAppUnits.width),
   224                      presContext->AppUnitsToDevPixels(docSizeAppUnits.height));
   225   }
   226 }
   228 bool
   229 nsSubDocumentFrame::PassPointerEventsToChildren()
   230 {
   231   // Limit use of mozpasspointerevents to documents with embedded:apps/chrome
   232   // permission, because this could be used by the parent document to discover
   233   // which parts of the subdocument are transparent to events (if subdocument
   234   // uses pointer-events:none on its root element, which is admittedly
   235   // unlikely)
   236   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozpasspointerevents)) {
   237       if (PresContext()->IsChrome()) {
   238         return true;
   239       }
   241       nsCOMPtr<nsIPermissionManager> permMgr =
   242         do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
   243       if (permMgr) {
   244         uint32_t permission = nsIPermissionManager::DENY_ACTION;
   245         permMgr->TestPermissionFromPrincipal(GetContent()->NodePrincipal(),
   246                                              "embed-apps", &permission);
   248         return permission == nsIPermissionManager::ALLOW_ACTION;
   249       }
   250   }
   252   return false;
   253 }
   255 static void
   256 WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
   257                               nsIFrame* aFrame,
   258                               nsDisplayList* aList)
   259 {
   260   nsDisplayList tempItems;
   261   nsDisplayItem* item;
   262   while ((item = aList->RemoveBottom()) != nullptr) {
   263     if (item->GetType() == nsDisplayItem::TYPE_BACKGROUND_COLOR) {
   264       nsDisplayList tmpList;
   265       tmpList.AppendToTop(item);
   266       item = new (aBuilder) nsDisplayOwnLayer(aBuilder, aFrame, &tmpList);
   267     }
   268     tempItems.AppendToTop(item);
   269   }
   270   aList->AppendToTop(&tempItems);
   271 }
   273 void
   274 nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   275                                      const nsRect&           aDirtyRect,
   276                                      const nsDisplayListSet& aLists)
   277 {
   278   if (!IsVisibleForPainting(aBuilder))
   279     return;
   281   nsFrameLoader* frameLoader = FrameLoader();
   282   RenderFrameParent* rfp = nullptr;
   283   if (frameLoader) {
   284     rfp = frameLoader->GetCurrentRemoteFrame();
   285   }
   287   // If we are pointer-events:none then we don't need to HitTest background
   288   bool pointerEventsNone = StyleVisibility()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE;
   289   if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) {
   290     nsDisplayListCollection decorations;
   291     DisplayBorderBackgroundOutline(aBuilder, decorations);
   292     if (rfp) {
   293       // Wrap background colors of <iframe>s with remote subdocuments in their
   294       // own layer so we generate a ColorLayer. This is helpful for optimizing
   295       // compositing; we can skip compositing the ColorLayer when the
   296       // remote content is opaque.
   297       WrapBackgroundColorInOwnLayer(aBuilder, this, decorations.BorderBackground());
   298     }
   299     decorations.MoveTo(aLists);
   300   }
   302   bool passPointerEventsToChildren = false;
   303   if (aBuilder->IsForEventDelivery()) {
   304     passPointerEventsToChildren = PassPointerEventsToChildren();
   305     // If mozpasspointerevents is set, then we should allow subdocument content
   306     // to handle events even if we're pointer-events:none.
   307     if (pointerEventsNone && !passPointerEventsToChildren) {
   308       return;
   309     }
   310   }
   312   // If we're passing pointer events to children then we have to descend into
   313   // subdocuments no matter what, to determine which parts are transparent for
   314   // elementFromPoint.
   315   if (!mInnerView ||
   316       (!aBuilder->GetDescendIntoSubdocuments() && !passPointerEventsToChildren)) {
   317     return;
   318   }
   320   if (rfp) {
   321     rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
   322     return;
   323   }
   325   nsView* subdocView = mInnerView->GetFirstChild();
   326   if (!subdocView)
   327     return;
   329   nsCOMPtr<nsIPresShell> presShell = nullptr;
   331   nsIFrame* subdocRootFrame = subdocView->GetFrame();
   332   if (subdocRootFrame) {
   333     presShell = subdocRootFrame->PresContext()->PresShell();
   334   }
   335   // If painting is suppressed in the presshell, we try to look for a better
   336   // presshell to use.
   337   if (!presShell || (presShell->IsPaintingSuppressed() &&
   338                      !aBuilder->IsIgnoringPaintSuppression())) {
   339     // During page transition mInnerView will sometimes have two children, the
   340     // first being the new page that may not have any frame, and the second
   341     // being the old page that will probably have a frame.
   342     nsView* nextView = subdocView->GetNextSibling();
   343     nsIFrame* frame = nullptr;
   344     if (nextView) {
   345       frame = nextView->GetFrame();
   346     }
   347     if (frame) {
   348       nsIPresShell* ps = frame->PresContext()->PresShell();
   349       if (!presShell || (ps && !ps->IsPaintingSuppressed())) {
   350         subdocView = nextView;
   351         subdocRootFrame = frame;
   352         presShell = ps;
   353       }
   354     }
   355     if (!presShell) {
   356       // If we don't have a frame we use this roundabout way to get the pres shell.
   357       if (!mFrameLoader)
   358         return;
   359       nsCOMPtr<nsIDocShell> docShell;
   360       mFrameLoader->GetDocShell(getter_AddRefs(docShell));
   361       if (!docShell)
   362         return;
   363       presShell = docShell->GetPresShell();
   364       if (!presShell)
   365         return;
   366     }
   367   }
   369   nsPresContext* presContext = presShell->GetPresContext();
   371   int32_t parentAPD = PresContext()->AppUnitsPerDevPixel();
   372   int32_t subdocAPD = presContext->AppUnitsPerDevPixel();
   374   nsRect dirty;
   375   bool haveDisplayPort = false;
   376   bool ignoreViewportScrolling = false;
   377   nsIFrame* savedIgnoreScrollFrame = nullptr;
   378   if (subdocRootFrame) {
   379     // get the dirty rect relative to the root frame of the subdoc
   380     dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
   381     // and convert into the appunits of the subdoc
   382     dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
   384     if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
   385       // for root content documents we want the base to be the composition bounds
   386       nsRect displayportBase = presContext->IsRootContentDocument() ?
   387           nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)) :
   388           dirty.Intersect(nsRect(nsPoint(0,0), subdocRootFrame->GetSize()));
   389       nsRect displayPort;
   390       if (nsLayoutUtils::GetOrMaybeCreateDisplayPort(
   391             *aBuilder, rootScrollFrame, displayportBase, &displayPort)) {
   392         haveDisplayPort = true;
   393         dirty = displayPort;
   394       }
   396       ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
   397       if (ignoreViewportScrolling) {
   398         savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
   399         aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
   400       }
   401     }
   403     aBuilder->EnterPresShell(subdocRootFrame, dirty);
   404   }
   406   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
   407   if (ShouldClipSubdocument()) {
   408     clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this);
   409   }
   411   nsIScrollableFrame *sf = presShell->GetRootScrollFrameAsScrollable();
   412   bool constructResolutionItem = subdocRootFrame &&
   413     (presShell->GetXResolution() != 1.0 || presShell->GetYResolution() != 1.0);
   414   bool constructZoomItem = subdocRootFrame && parentAPD != subdocAPD;
   415   bool needsOwnLayer = constructResolutionItem || constructZoomItem ||
   416     haveDisplayPort ||
   417     presContext->IsRootContentDocument() || (sf && sf->IsScrollingActive());
   419   // Don't let in fixed pos propagate down to child documents. This makes
   420   // it a little less effective but doesn't regress an important case of a
   421   // child document being in a fixed pos element where we would do no occlusion
   422   // at all if we let it propagate down.
   423   nsDisplayListBuilder::AutoInFixedPosSetter
   424     buildingInFixedPos(aBuilder, false);
   426   nsDisplayList childItems;
   428   {
   429     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
   430     if (needsOwnLayer) {
   431       // Clear current clip. There's no point in propagating it down, since
   432       // the layer we will construct will be clipped by the current clip.
   433       // In fact for nsDisplayZoom propagating it down would be incorrect since
   434       // nsDisplayZoom changes the meaning of appunits.
   435       nestedClipState.Clear();
   436     }
   438     if (subdocRootFrame) {
   439       nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
   440           aBuilder,
   441           ignoreViewportScrolling && subdocRootFrame->GetContent()
   442               ? nsLayoutUtils::FindOrCreateIDFor(subdocRootFrame->GetContent())
   443               : aBuilder->GetCurrentScrollParentId());
   445       aBuilder->SetAncestorHasTouchEventHandler(false);
   446       subdocRootFrame->
   447         BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
   448     }
   450     if (!aBuilder->IsForEventDelivery()) {
   451       // If we are going to use a displayzoom below then any items we put under
   452       // it need to have underlying frames from the subdocument. So we need to
   453       // calculate the bounds based on which frame will be the underlying frame
   454       // for the canvas background color item.
   455       nsRect bounds = GetContentRectRelativeToSelf() +
   456         aBuilder->ToReferenceFrame(this);
   457       if (subdocRootFrame) {
   458         bounds = bounds.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
   459       }
   461       // If we are in print preview/page layout we want to paint the grey
   462       // background behind the page, not the canvas color. The canvas color gets
   463       // painted on the page itself.
   464       if (nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) {
   465         presShell->AddPrintPreviewBackgroundItem(
   466           *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
   467           bounds);
   468       } else {
   469         // Add the canvas background color to the bottom of the list. This
   470         // happens after we've built the list so that AddCanvasBackgroundColorItem
   471         // can monkey with the contents if necessary.
   472         uint32_t flags = nsIPresShell::FORCE_DRAW;
   473         presShell->AddCanvasBackgroundColorItem(
   474           *aBuilder, childItems, subdocRootFrame ? subdocRootFrame : this,
   475           bounds, NS_RGBA(0,0,0,0), flags);
   476       }
   477     }
   478   }
   480   // Generate a resolution and/or zoom item if needed. If one or both of those is
   481   // created, we don't need to create a separate nsDisplaySubDocument.
   483   uint32_t flags = nsDisplayOwnLayer::GENERATE_SUBDOC_INVALIDATIONS;
   484   // If ignoreViewportScrolling is true then the top most layer we create here
   485   // is going to become the scrollable layer for the root scroll frame, so we
   486   // want to add nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER to whatever layer
   487   // becomes the topmost. We do this below.
   488   if (constructZoomItem) {
   489     uint32_t zoomFlags = flags;
   490     if (ignoreViewportScrolling && !constructResolutionItem) {
   491       zoomFlags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
   492     }
   493     nsDisplayZoom* zoomItem =
   494       new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,
   495                                    subdocAPD, parentAPD, zoomFlags);
   496     childItems.AppendToTop(zoomItem);
   497     needsOwnLayer = false;
   498   }
   499   // Wrap the zoom item in the resolution item if we have both because we want the
   500   // resolution scale applied on top of the app units per dev pixel conversion.
   501   if (ignoreViewportScrolling) {
   502     flags |= nsDisplayOwnLayer::GENERATE_SCROLLABLE_LAYER;
   503   }
   504   if (constructResolutionItem) {
   505     nsDisplayResolution* resolutionItem =
   506       new (aBuilder) nsDisplayResolution(aBuilder, subdocRootFrame, &childItems,
   507                                          flags);
   508     childItems.AppendToTop(resolutionItem);
   509     needsOwnLayer = false;
   510   }
   511   if (needsOwnLayer) {
   512     // We always want top level content documents to be in their own layer.
   513     nsDisplaySubDocument* layerItem = new (aBuilder) nsDisplaySubDocument(
   514       aBuilder, subdocRootFrame ? subdocRootFrame : this,
   515       &childItems, flags);
   516     childItems.AppendToTop(layerItem);
   517   }
   519   if (subdocRootFrame) {
   520     aBuilder->LeavePresShell(subdocRootFrame, dirty);
   522     if (ignoreViewportScrolling) {
   523       aBuilder->SetIgnoreScrollFrame(savedIgnoreScrollFrame);
   524     }
   525   }
   527   if (aBuilder->IsForImageVisibility()) {
   528     // We don't add the childItems to the return list as we're dealing with them here.
   529     presShell->RebuildImageVisibility(childItems);
   530     childItems.DeleteAll();
   531   } else {
   532     aLists.Content()->AppendToTop(&childItems);
   533   }
   534 }
   536 nscoord
   537 nsSubDocumentFrame::GetIntrinsicWidth()
   538 {
   539   if (!IsInline()) {
   540     return 0;  // HTML <frame> has no useful intrinsic width
   541   }
   543   if (mContent->IsXUL()) {
   544     return 0;  // XUL <iframe> and <browser> have no useful intrinsic width
   545   }
   547   NS_ASSERTION(ObtainIntrinsicSizeFrame() == nullptr,
   548                "Intrinsic width should come from the embedded document.");
   550   // We must be an HTML <iframe>.  Default to a width of 300, for IE
   551   // compat (and per CSS2.1 draft).
   552   return nsPresContext::CSSPixelsToAppUnits(300);
   553 }
   555 nscoord
   556 nsSubDocumentFrame::GetIntrinsicHeight()
   557 {
   558   // <frame> processing does not use this routine, only <iframe>
   559   NS_ASSERTION(IsInline(), "Shouldn't have been called");
   561   if (mContent->IsXUL()) {
   562     return 0;
   563   }
   565   NS_ASSERTION(ObtainIntrinsicSizeFrame() == nullptr,
   566                "Intrinsic height should come from the embedded document.");
   568   // Use 150px, for compatibility with IE, and per CSS2.1 draft.
   569   return nsPresContext::CSSPixelsToAppUnits(150);
   570 }
   572 #ifdef DEBUG_FRAME_DUMP
   573 void
   574 nsSubDocumentFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
   575 {
   576   nsCString str;
   577   ListGeneric(str, aPrefix, aFlags);
   578   fprintf_stderr(out, "%s\n", str.get());
   580   if (aFlags & TRAVERSE_SUBDOCUMENT_FRAMES) {
   581     nsSubDocumentFrame* f = const_cast<nsSubDocumentFrame*>(this);
   582     nsIFrame* subdocRootFrame = f->GetSubdocumentRootFrame();
   583     if (subdocRootFrame) {
   584       nsCString pfx(aPrefix);
   585       pfx += "  ";
   586       subdocRootFrame->List(out, pfx.get(), aFlags);
   587     }
   588   }
   589 }
   591 nsresult nsSubDocumentFrame::GetFrameName(nsAString& aResult) const
   592 {
   593   return MakeFrameName(NS_LITERAL_STRING("FrameOuter"), aResult);
   594 }
   595 #endif
   597 nsIAtom*
   598 nsSubDocumentFrame::GetType() const
   599 {
   600   return nsGkAtoms::subDocumentFrame;
   601 }
   603 /* virtual */ nscoord
   604 nsSubDocumentFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   605 {
   606   nscoord result;
   607   DISPLAY_MIN_WIDTH(this, result);
   609   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   610   if (subDocRoot) {
   611     result = subDocRoot->GetMinWidth(aRenderingContext);
   612   } else {
   613     result = GetIntrinsicWidth();
   614   }
   616   return result;
   617 }
   619 /* virtual */ nscoord
   620 nsSubDocumentFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   621 {
   622   nscoord result;
   623   DISPLAY_PREF_WIDTH(this, result);
   625   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   626   if (subDocRoot) {
   627     result = subDocRoot->GetPrefWidth(aRenderingContext);
   628   } else {
   629     result = GetIntrinsicWidth();
   630   }
   632   return result;
   633 }
   635 /* virtual */ IntrinsicSize
   636 nsSubDocumentFrame::GetIntrinsicSize()
   637 {
   638   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   639   if (subDocRoot) {
   640     return subDocRoot->GetIntrinsicSize();
   641   }
   642   return nsLeafFrame::GetIntrinsicSize();
   643 }
   645 /* virtual */ nsSize
   646 nsSubDocumentFrame::GetIntrinsicRatio()
   647 {
   648   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   649   if (subDocRoot) {
   650     return subDocRoot->GetIntrinsicRatio();
   651   }
   652   return nsLeafFrame::GetIntrinsicRatio();
   653 }
   655 /* virtual */ nsSize
   656 nsSubDocumentFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
   657                                     nsSize aCBSize, nscoord aAvailableWidth,
   658                                     nsSize aMargin, nsSize aBorder,
   659                                     nsSize aPadding, bool aShrinkWrap)
   660 {
   661   if (!IsInline()) {
   662     return nsFrame::ComputeAutoSize(aRenderingContext, aCBSize,
   663                                     aAvailableWidth, aMargin, aBorder,
   664                                     aPadding, aShrinkWrap);
   665   }
   667   return nsLeafFrame::ComputeAutoSize(aRenderingContext, aCBSize,
   668                                       aAvailableWidth, aMargin, aBorder,
   669                                       aPadding, aShrinkWrap);  
   670 }
   673 /* virtual */ nsSize
   674 nsSubDocumentFrame::ComputeSize(nsRenderingContext *aRenderingContext,
   675                                 nsSize aCBSize, nscoord aAvailableWidth,
   676                                 nsSize aMargin, nsSize aBorder, nsSize aPadding,
   677                                 uint32_t aFlags)
   678 {
   679   nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
   680   if (subDocRoot) {
   681     return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
   682                             aRenderingContext, this,
   683                             subDocRoot->GetIntrinsicSize(),
   684                             subDocRoot->GetIntrinsicRatio(),
   685                             aCBSize, aMargin, aBorder, aPadding);
   686   }
   687   return nsLeafFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth,
   688                                   aMargin, aBorder, aPadding, aFlags);
   689 }
   691 nsresult
   692 nsSubDocumentFrame::Reflow(nsPresContext*           aPresContext,
   693                            nsHTMLReflowMetrics&     aDesiredSize,
   694                            const nsHTMLReflowState& aReflowState,
   695                            nsReflowStatus&          aStatus)
   696 {
   697   DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame");
   698   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   699   // printf("OuterFrame::Reflow %X (%d,%d) \n", this, aReflowState.AvailableWidth(), aReflowState.AvailableHeight());
   700   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
   701      ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d",
   702       aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
   704   aStatus = NS_FRAME_COMPLETE;
   706   NS_ASSERTION(mContent->GetPrimaryFrame() == this,
   707                "Shouldn't happen");
   709   // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed>
   710   nsresult rv = nsLeafFrame::DoReflow(aPresContext, aDesiredSize, aReflowState,
   711                                       aStatus);
   712   NS_ENSURE_SUCCESS(rv, rv);
   714   // "offset" is the offset of our content area from our frame's
   715   // top-left corner.
   716   nsPoint offset = nsPoint(aReflowState.ComputedPhysicalBorderPadding().left,
   717                            aReflowState.ComputedPhysicalBorderPadding().top);
   719   nsSize innerSize(aDesiredSize.Width(), aDesiredSize.Height());
   720   innerSize.width  -= aReflowState.ComputedPhysicalBorderPadding().LeftRight();
   721   innerSize.height -= aReflowState.ComputedPhysicalBorderPadding().TopBottom();
   723   if (mInnerView) {
   724     nsViewManager* vm = mInnerView->GetViewManager();
   725     vm->MoveViewTo(mInnerView, offset.x, offset.y);
   726     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), true);
   727   }
   729   aDesiredSize.SetOverflowAreasToDesiredBounds();
   730   if (!ShouldClipSubdocument()) {
   731     nsIFrame* subdocRootFrame = GetSubdocumentRootFrame();
   732     if (subdocRootFrame) {
   733       aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset);
   734     }
   735   }
   737   FinishAndStoreOverflow(&aDesiredSize);
   739   if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
   740     PresContext()->PresShell()->PostReflowCallback(this);
   741     mPostedReflowCallback = true;
   742   }
   744   // printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
   745   //        aDesiredSize.Width(), aDesiredSize.Height());
   747   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
   748      ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
   749       aDesiredSize.Width(), aDesiredSize.Height(), aStatus));
   751   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   752   return NS_OK;
   753 }
   755 bool
   756 nsSubDocumentFrame::ReflowFinished()
   757 {
   758   if (mFrameLoader) {
   759     nsWeakFrame weakFrame(this);
   761     mFrameLoader->UpdatePositionAndSize(this);
   763     if (weakFrame.IsAlive()) {
   764       // Make sure that we can post a reflow callback in the future.
   765       mPostedReflowCallback = false;
   766     }
   767   } else {
   768     mPostedReflowCallback = false;
   769   }
   770   return false;
   771 }
   773 void
   774 nsSubDocumentFrame::ReflowCallbackCanceled()
   775 {
   776   mPostedReflowCallback = false;
   777 }
   779 nsresult
   780 nsSubDocumentFrame::AttributeChanged(int32_t aNameSpaceID,
   781                                      nsIAtom* aAttribute,
   782                                      int32_t aModType)
   783 {
   784   if (aNameSpaceID != kNameSpaceID_None) {
   785     return NS_OK;
   786   }
   788   // If the noResize attribute changes, dis/allow frame to be resized
   789   if (aAttribute == nsGkAtoms::noresize) {
   790     // Note that we're not doing content type checks, but that's ok -- if
   791     // they'd fail we will just end up with a null framesetFrame.
   792     if (mContent->GetParent()->Tag() == nsGkAtoms::frameset) {
   793       nsIFrame* parentFrame = GetParent();
   795       if (parentFrame) {
   796         // There is no interface for nsHTMLFramesetFrame so QI'ing to
   797         // concrete class, yay!
   798         nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(parentFrame);
   799         if (framesetFrame) {
   800           framesetFrame->RecalculateBorderResize();
   801         }
   802       }
   803     }
   804   }
   805   else if (aAttribute == nsGkAtoms::showresizer) {
   806     nsIFrame* rootFrame = GetSubdocumentRootFrame();
   807     if (rootFrame) {
   808       rootFrame->PresContext()->PresShell()->
   809         FrameNeedsReflow(rootFrame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
   810     }
   811   }
   812   else if (aAttribute == nsGkAtoms::marginwidth ||
   813            aAttribute == nsGkAtoms::marginheight) {
   815     // Retrieve the attributes
   816     nsIntSize margins = GetMarginAttributes();
   818     // Notify the frameloader
   819     nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
   820     if (frameloader)
   821       frameloader->MarginsChanged(margins.width, margins.height);
   822   }
   824   return NS_OK;
   825 }
   827 nsIFrame*
   828 NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
   829 {
   830   return new (aPresShell) nsSubDocumentFrame(aContext);
   831 }
   833 NS_IMPL_FRAMEARENA_HELPERS(nsSubDocumentFrame)
   835 class nsHideViewer : public nsRunnable {
   836 public:
   837   nsHideViewer(nsIContent* aFrameElement,
   838                nsFrameLoader* aFrameLoader,
   839                nsIPresShell* aPresShell,
   840                bool aHideViewerIfFrameless)
   841     : mFrameElement(aFrameElement),
   842       mFrameLoader(aFrameLoader),
   843       mPresShell(aPresShell),
   844       mHideViewerIfFrameless(aHideViewerIfFrameless)
   845   {
   846     NS_ASSERTION(mFrameElement, "Must have a frame element");
   847     NS_ASSERTION(mFrameLoader, "Must have a frame loader");
   848     NS_ASSERTION(mPresShell, "Must have a presshell");
   849   }
   851   NS_IMETHOD Run()
   852   {
   853     // Flush frames, to ensure any pending display:none changes are made.
   854     // Note it can be unsafe to flush if we've destroyed the presentation
   855     // for some other reason, like if we're shutting down.
   856     if (!mPresShell->IsDestroying()) {
   857       mPresShell->FlushPendingNotifications(Flush_Frames);
   858     }
   859     nsIFrame* frame = mFrameElement->GetPrimaryFrame();
   860     if ((!frame && mHideViewerIfFrameless) ||
   861         mPresShell->IsDestroying()) {
   862       // Either the frame element has no nsIFrame or the presshell is being
   863       // destroyed. Hide the nsFrameLoader, which destroys the presentation,
   864       // and clear our references to the stashed presentation.
   865       mFrameLoader->SetDetachedSubdocView(nullptr, nullptr);
   866       mFrameLoader->Hide();
   867     }
   868     return NS_OK;
   869   }
   870 private:
   871   nsCOMPtr<nsIContent> mFrameElement;
   872   nsRefPtr<nsFrameLoader> mFrameLoader;
   873   nsCOMPtr<nsIPresShell> mPresShell;
   874   bool mHideViewerIfFrameless;
   875 };
   877 static nsView*
   878 BeginSwapDocShellsForViews(nsView* aSibling);
   880 void
   881 nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
   882 {
   883   if (mPostedReflowCallback) {
   884     PresContext()->PresShell()->CancelReflowCallback(this);
   885     mPostedReflowCallback = false;
   886   }
   888   // Detach the subdocument's views and stash them in the frame loader.
   889   // We can then reattach them if we're being reframed (for example if
   890   // the frame has been made position:fixed).
   891   nsFrameLoader* frameloader = FrameLoader();
   892   if (frameloader) {
   893     nsView* detachedViews = ::BeginSwapDocShellsForViews(mInnerView->GetFirstChild());
   894     frameloader->SetDetachedSubdocView(detachedViews, mContent->OwnerDoc());
   896     // We call nsFrameLoader::HideViewer() in a script runner so that we can
   897     // safely determine whether the frame is being reframed or destroyed.
   898     nsContentUtils::AddScriptRunner(
   899       new nsHideViewer(mContent,
   900                        mFrameLoader,
   901                        PresContext()->PresShell(),
   902                        (mDidCreateDoc || mCallingShow)));
   903   }
   905   nsLeafFrame::DestroyFrom(aDestructRoot);
   906 }
   908 nsIntSize
   909 nsSubDocumentFrame::GetMarginAttributes()
   910 {
   911   nsIntSize result(-1, -1);
   912   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
   913   if (content) {
   914     const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::marginwidth);
   915     if (attr && attr->Type() == nsAttrValue::eInteger)
   916       result.width = attr->GetIntegerValue();
   917     attr = content->GetParsedAttr(nsGkAtoms::marginheight);
   918     if (attr && attr->Type() == nsAttrValue::eInteger)
   919       result.height = attr->GetIntegerValue();
   920   }
   921   return result;
   922 }
   924 nsFrameLoader*
   925 nsSubDocumentFrame::FrameLoader()
   926 {
   927   nsIContent* content = GetContent();
   928   if (!content)
   929     return nullptr;
   931   if (!mFrameLoader) {
   932     nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content);
   933     if (loaderOwner) {
   934       nsCOMPtr<nsIFrameLoader> loader;
   935       loaderOwner->GetFrameLoader(getter_AddRefs(loader));
   936       mFrameLoader = static_cast<nsFrameLoader*>(loader.get());
   937     }
   938   }
   939   return mFrameLoader;
   940 }
   942 // XXX this should be called ObtainDocShell or something like that,
   943 // to indicate that it could have side effects
   944 nsresult
   945 nsSubDocumentFrame::GetDocShell(nsIDocShell **aDocShell)
   946 {
   947   *aDocShell = nullptr;
   949   NS_ENSURE_STATE(FrameLoader());
   950   return mFrameLoader->GetDocShell(aDocShell);
   951 }
   953 static void
   954 DestroyDisplayItemDataForFrames(nsIFrame* aFrame)
   955 {
   956   FrameLayerBuilder::DestroyDisplayItemDataFor(aFrame);
   958   nsIFrame::ChildListIterator lists(aFrame);
   959   for (; !lists.IsDone(); lists.Next()) {
   960     nsFrameList::Enumerator childFrames(lists.CurrentList());
   961     for (; !childFrames.AtEnd(); childFrames.Next()) {
   962       DestroyDisplayItemDataForFrames(childFrames.get());
   963     }
   964   }
   965 }
   967 static bool
   968 BeginSwapDocShellsForDocument(nsIDocument* aDocument, void*)
   969 {
   970   NS_PRECONDITION(aDocument, "");
   972   nsIPresShell* shell = aDocument->GetShell();
   973   if (shell) {
   974     // Disable painting while the views are detached, see bug 946929.
   975     shell->SetNeverPainting(true);
   977     nsIFrame* rootFrame = shell->GetRootFrame();
   978     if (rootFrame) {
   979       ::DestroyDisplayItemDataForFrames(rootFrame);
   980     }
   981   }
   982   aDocument->EnumerateFreezableElements(
   983     nsObjectFrame::BeginSwapDocShells, nullptr);
   984   aDocument->EnumerateSubDocuments(BeginSwapDocShellsForDocument, nullptr);
   985   return true;
   986 }
   988 static nsView*
   989 BeginSwapDocShellsForViews(nsView* aSibling)
   990 {
   991   // Collect the removed sibling views in reverse order in 'removedViews'.
   992   nsView* removedViews = nullptr;
   993   while (aSibling) {
   994     nsIDocument* doc = ::GetDocumentFromView(aSibling);
   995     if (doc) {
   996       ::BeginSwapDocShellsForDocument(doc, nullptr);
   997     }
   998     nsView* next = aSibling->GetNextSibling();
   999     aSibling->GetViewManager()->RemoveChild(aSibling);
  1000     aSibling->SetNextSibling(removedViews);
  1001     removedViews = aSibling;
  1002     aSibling = next;
  1004   return removedViews;
  1007 static void
  1008 InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent)
  1010   NS_PRECONDITION(aParent, "");
  1011   NS_PRECONDITION(!aParent->GetFirstChild(), "inserting into non-empty list");
  1013   nsViewManager* vm = aParent->GetViewManager();
  1014   while (aSibling) {
  1015     nsView* next = aSibling->GetNextSibling();
  1016     aSibling->SetNextSibling(nullptr);
  1017     // true means 'after' in document order which is 'before' in view order,
  1018     // so this call prepends the child, thus reversing the siblings as we go.
  1019     vm->InsertChild(aParent, aSibling, nullptr, true);
  1020     aSibling = next;
  1024 nsresult
  1025 nsSubDocumentFrame::BeginSwapDocShells(nsIFrame* aOther)
  1027   if (!aOther || aOther->GetType() != nsGkAtoms::subDocumentFrame) {
  1028     return NS_ERROR_NOT_IMPLEMENTED;
  1031   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
  1032   if (!mFrameLoader || !mDidCreateDoc || mCallingShow ||
  1033       !other->mFrameLoader || !other->mDidCreateDoc) {
  1034     return NS_ERROR_NOT_IMPLEMENTED;
  1037   if (mInnerView && other->mInnerView) {
  1038     nsView* ourSubdocViews = mInnerView->GetFirstChild();
  1039     nsView* ourRemovedViews = ::BeginSwapDocShellsForViews(ourSubdocViews);
  1040     nsView* otherSubdocViews = other->mInnerView->GetFirstChild();
  1041     nsView* otherRemovedViews = ::BeginSwapDocShellsForViews(otherSubdocViews);
  1043     ::InsertViewsInReverseOrder(ourRemovedViews, other->mInnerView);
  1044     ::InsertViewsInReverseOrder(otherRemovedViews, mInnerView);
  1046   mFrameLoader.swap(other->mFrameLoader);
  1047   return NS_OK;
  1050 static bool
  1051 EndSwapDocShellsForDocument(nsIDocument* aDocument, void*)
  1053   NS_PRECONDITION(aDocument, "");
  1055   // Our docshell and view trees have been updated for the new hierarchy.
  1056   // Now also update all nsDeviceContext::mWidget to that of the
  1057   // container view in the new hierarchy.
  1058   nsCOMPtr<nsIDocShell> ds = aDocument->GetDocShell();
  1059   if (ds) {
  1060     nsCOMPtr<nsIContentViewer> cv;
  1061     ds->GetContentViewer(getter_AddRefs(cv));
  1062     while (cv) {
  1063       nsRefPtr<nsPresContext> pc;
  1064       cv->GetPresContext(getter_AddRefs(pc));
  1065       if (pc && pc->GetPresShell()) {
  1066         pc->GetPresShell()->SetNeverPainting(ds->IsInvisible());
  1068       nsDeviceContext* dc = pc ? pc->DeviceContext() : nullptr;
  1069       if (dc) {
  1070         nsView* v = cv->FindContainerView();
  1071         dc->Init(v ? v->GetNearestWidget(nullptr) : nullptr);
  1073       nsCOMPtr<nsIContentViewer> prev;
  1074       cv->GetPreviousViewer(getter_AddRefs(prev));
  1075       cv = prev;
  1079   aDocument->EnumerateFreezableElements(
  1080     nsObjectFrame::EndSwapDocShells, nullptr);
  1081   aDocument->EnumerateSubDocuments(EndSwapDocShellsForDocument, nullptr);
  1082   return true;
  1085 static void
  1086 EndSwapDocShellsForViews(nsView* aSibling)
  1088   for ( ; aSibling; aSibling = aSibling->GetNextSibling()) {
  1089     nsIDocument* doc = ::GetDocumentFromView(aSibling);
  1090     if (doc) {
  1091       ::EndSwapDocShellsForDocument(doc, nullptr);
  1093     nsIFrame *frame = aSibling->GetFrame();
  1094     if (frame) {
  1095       nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
  1096       if (parent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
  1097         nsIFrame::AddInPopupStateBitToDescendants(frame);
  1098       } else {
  1099         nsIFrame::RemoveInPopupStateBitFromDescendants(frame);
  1101       if (frame->HasInvalidFrameInSubtree()) {
  1102         while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
  1103           parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
  1104           parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
  1111 void
  1112 nsSubDocumentFrame::EndSwapDocShells(nsIFrame* aOther)
  1114   nsSubDocumentFrame* other = static_cast<nsSubDocumentFrame*>(aOther);
  1115   nsWeakFrame weakThis(this);
  1116   nsWeakFrame weakOther(aOther);
  1118   if (mInnerView) {
  1119     ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
  1121   if (other->mInnerView) {
  1122     ::EndSwapDocShellsForViews(other->mInnerView->GetFirstChild());
  1125   // Now make sure we reflow both frames, in case their contents
  1126   // determine their size.
  1127   // And repaint them, for good measure, in case there's nothing
  1128   // interesting that happens during reflow.
  1129   if (weakThis.IsAlive()) {
  1130     PresContext()->PresShell()->
  1131       FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
  1132     InvalidateFrameSubtree();
  1134   if (weakOther.IsAlive()) {
  1135     other->PresContext()->PresShell()->
  1136       FrameNeedsReflow(other, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
  1137     other->InvalidateFrameSubtree();
  1141 nsView*
  1142 nsSubDocumentFrame::EnsureInnerView()
  1144   if (mInnerView) {
  1145     return mInnerView;
  1148   // create, init, set the parent of the view
  1149   nsView* outerView = GetView();
  1150   NS_ASSERTION(outerView, "Must have an outer view already");
  1151   nsRect viewBounds(0, 0, 0, 0); // size will be fixed during reflow
  1153   nsViewManager* viewMan = outerView->GetViewManager();
  1154   nsView* innerView = viewMan->CreateView(viewBounds, outerView);
  1155   if (!innerView) {
  1156     NS_ERROR("Could not create inner view");
  1157     return nullptr;
  1159   mInnerView = innerView;
  1160   viewMan->InsertChild(outerView, innerView, nullptr, true);
  1162   return mInnerView;
  1165 nsIFrame*
  1166 nsSubDocumentFrame::ObtainIntrinsicSizeFrame()
  1168   nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(GetContent());
  1169   if (olc) {
  1170     // We are an HTML <object>, <embed> or <applet> (a replaced element).
  1172     // Try to get an nsIFrame for our sub-document's document element
  1173     nsIFrame* subDocRoot = nullptr;
  1175     nsCOMPtr<nsIDocShell> docShell;
  1176     GetDocShell(getter_AddRefs(docShell));
  1177     if (docShell) {
  1178       nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
  1179       if (presShell) {
  1180         nsIScrollableFrame* scrollable = presShell->GetRootScrollFrameAsScrollable();
  1181         if (scrollable) {
  1182           nsIFrame* scrolled = scrollable->GetScrolledFrame();
  1183           if (scrolled) {
  1184             subDocRoot = scrolled->GetFirstPrincipalChild();
  1190     if (subDocRoot && subDocRoot->GetContent() &&
  1191         subDocRoot->GetContent()->NodeInfo()->Equals(nsGkAtoms::svg, kNameSpaceID_SVG)) {
  1192       return subDocRoot; // SVG documents have an intrinsic size
  1195   return nullptr;

mercurial