1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Travis Bogard <travis@netscape.com>
24 * HÂkan Waara <hwaara@chello.se>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * rendering object for replaced elements that contain a document, such
42 * as <frame>, <iframe>, and some <object>s
46 #include "nsLeafFrame.h"
47 #include "nsGenericHTMLElement.h"
48 #include "nsIDocShell.h"
49 #include "nsIDocShellLoadInfo.h"
50 #include "nsIDocShellTreeItem.h"
51 #include "nsIDocShellTreeNode.h"
52 #include "nsIDocShellTreeOwner.h"
53 #include "nsIBaseWindow.h"
54 #include "nsIContentViewer.h"
55 #include "nsIMarkupDocumentViewer.h"
56 #include "nsPresContext.h"
57 #include "nsIPresShell.h"
58 #include "nsIComponentManager.h"
59 #include "nsFrameManager.h"
60 #include "nsIStreamListener.h"
62 #include "nsNetUtil.h"
63 #include "nsIDocument.h"
65 #include "nsIViewManager.h"
66 #include "nsWidgetsCID.h"
67 #include "nsViewsCID.h"
68 #include "nsGkAtoms.h"
69 #include "nsIScrollableView.h"
70 #include "nsStyleCoord.h"
71 #include "nsStyleContext.h"
72 #include "nsStyleConsts.h"
73 #include "nsFrameSetFrame.h"
74 #include "nsIDOMHTMLFrameElement.h"
75 #include "nsIDOMHTMLIFrameElement.h"
76 #include "nsIDOMXULElement.h"
77 #include "nsIFrameLoader.h"
78 #include "nsIScriptSecurityManager.h"
79 #include "nsXPIDLString.h"
80 #include "nsIScrollable.h"
81 #include "nsINameSpaceManager.h"
82 #include "nsIWidget.h"
83 #include "nsWeakReference.h"
84 #include "nsIDOMWindow.h"
85 #include "nsIDOMDocument.h"
86 #include "nsIRenderingContext.h"
87 #include "nsIFrameFrame.h"
88 #include "nsAutoPtr.h"
89 #include "nsIDOMNSHTMLDocument.h"
90 #include "nsDisplayList.h"
91 #include "nsUnicharUtils.h"
92 #include "nsIReflowCallback.h"
93 #include "nsIScrollableFrame.h"
94 #include "nsIObjectLoadingContent.h"
95 #include "nsLayoutUtils.h"
98 #include "nsXULPopupManager.h"
103 #include "nsIAccessibilityService.h"
105 #include "nsIServiceManager.h"
107 static NS_DEFINE_CID(kCChildCID
, NS_CHILD_CID
);
109 /******************************************************************************
111 *****************************************************************************/
112 class nsSubDocumentFrame
: public nsLeafFrame
,
113 public nsIFrameFrame
,
114 public nsIReflowCallback
117 nsSubDocumentFrame(nsStyleContext
* aContext
);
120 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const;
124 NS_IMETHOD
QueryInterface(REFNSIID aIID
, void** aInstancePtr
);
125 NS_IMETHOD_(nsrefcnt
) AddRef(void) { return 2; }
126 NS_IMETHOD_(nsrefcnt
) Release(void) { return 1; }
128 virtual nsIAtom
* GetType() const;
130 virtual PRBool
IsFrameOfType(PRUint32 aFlags
) const
132 // nsLeafFrame is already eReplacedContainsBlock, but that's somewhat bogus
133 return nsLeafFrame::IsFrameOfType(aFlags
&
134 ~(nsIFrame::eReplaced
| nsIFrame::eReplacedContainsBlock
));
137 NS_IMETHOD
Init(nsIContent
* aContent
,
139 nsIFrame
* aPrevInFlow
);
141 virtual void Destroy();
143 virtual nscoord
GetMinWidth(nsIRenderingContext
*aRenderingContext
);
144 virtual nscoord
GetPrefWidth(nsIRenderingContext
*aRenderingContext
);
146 virtual IntrinsicSize
GetIntrinsicSize();
147 virtual nsSize
GetIntrinsicRatio();
149 virtual nsSize
ComputeAutoSize(nsIRenderingContext
*aRenderingContext
,
150 nsSize aCBSize
, nscoord aAvailableWidth
,
151 nsSize aMargin
, nsSize aBorder
,
152 nsSize aPadding
, PRBool aShrinkWrap
);
154 virtual nsSize
ComputeSize(nsIRenderingContext
*aRenderingContext
,
155 nsSize aCBSize
, nscoord aAvailableWidth
,
156 nsSize aMargin
, nsSize aBorder
, nsSize aPadding
,
159 NS_IMETHOD
Reflow(nsPresContext
* aPresContext
,
160 nsHTMLReflowMetrics
& aDesiredSize
,
161 const nsHTMLReflowState
& aReflowState
,
162 nsReflowStatus
& aStatus
);
164 NS_IMETHOD
BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
165 const nsRect
& aDirtyRect
,
166 const nsDisplayListSet
& aLists
);
168 NS_IMETHOD
AttributeChanged(PRInt32 aNameSpaceID
,
172 // if the content is "visibility:hidden", then just hide the view
173 // and all our contents. We don't extend "visibility:hidden" to
174 // the child content ourselves, since it belongs to a different
175 // document and CSS doesn't inherit in there.
176 virtual PRBool
SupportsVisibilityHidden() { return PR_FALSE
; }
179 NS_IMETHOD
GetAccessible(nsIAccessible
** aAccessible
);
183 NS_IMETHOD
GetDocShell(nsIDocShell
**aDocShell
);
184 NS_IMETHOD
BeginSwapDocShells(nsIFrame
* aOther
);
185 virtual void EndSwapDocShells(nsIFrame
* aOther
);
187 NS_IMETHOD
VerifyTree() const;
190 virtual PRBool
ReflowFinished();
191 virtual void ReflowCallbackCanceled();
195 PRBool
IsInline() { return mIsInline
; }
196 nsresult
ShowDocShell();
197 nsresult
CreateViewAndWidget(nsContentType aContentType
);
199 virtual nscoord
GetIntrinsicWidth();
200 virtual nscoord
GetIntrinsicHeight();
202 virtual PRIntn
GetSkipSides() const;
204 // Hide or show our document viewer
208 /* Obtains the frame we should use for intrinsic size information if we are
209 * an HTML <object>, <embed> or <applet> (a replaced element - not <iframe>)
210 * and our sub-document has an intrinsic size. The frame returned is the
211 * frame for the document element of the document we're embedding.
213 * Called "Obtain*" and not "Get*" because of comment on GetDocShell that
214 * says it should be called ObtainDocShell because of it's side effects.
216 nsIFrame
* ObtainIntrinsicSizeFrame();
218 nsCOMPtr
<nsIFrameLoader
> mFrameLoader
;
220 PRPackedBool mDidCreateDoc
;
221 PRPackedBool mIsInline
;
222 PRPackedBool mPostedReflowCallback
;
225 nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext
* aContext
)
226 : nsLeafFrame(aContext
), mDidCreateDoc(PR_FALSE
),
227 mIsInline(PR_FALSE
), mPostedReflowCallback(PR_FALSE
)
232 NS_IMETHODIMP
nsSubDocumentFrame::GetAccessible(nsIAccessible
** aAccessible
)
234 nsCOMPtr
<nsIAccessibilityService
> accService
= do_GetService("@mozilla.org/accessibilityService;1");
237 nsCOMPtr
<nsIDOMNode
> node
= do_QueryInterface(mContent
);
238 return accService
->CreateOuterDocAccessible(node
, aAccessible
);
241 return NS_ERROR_FAILURE
;
245 //--------------------------------------------------------------
246 // Frames are not refcounted, no need to AddRef
248 nsSubDocumentFrame::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
250 NS_PRECONDITION(aInstancePtr
, "null out param");
252 if (aIID
.Equals(NS_GET_IID(nsIFrameFrame
))) {
253 *aInstancePtr
= static_cast<nsIFrameFrame
*>(this);
257 return nsLeafFrame::QueryInterface(aIID
, aInstancePtr
);
261 nsSubDocumentFrame::Init(nsIContent
* aContent
,
263 nsIFrame
* aPrevInFlow
)
265 // determine if we are a <frame> or <iframe>
267 nsCOMPtr
<nsIDOMHTMLFrameElement
> frameElem
= do_QueryInterface(aContent
);
268 mIsInline
= frameElem
? PR_FALSE
: PR_TRUE
;
271 nsresult rv
= nsLeafFrame::Init(aContent
, aParent
, aPrevInFlow
);
275 nsPresContext
*aPresContext
= PresContext();
277 // We are going to create an inner view. If we need a view for the
278 // OuterFrame but we wait for the normal view creation path in
279 // nsCSSFrameConstructor, then we will lose because the inner view's
280 // parent will already have been set to some outer view (e.g., the
281 // canvas) when it really needs to have this frame's view as its
282 // parent. So, create this frame's view right away, whether we
283 // really need it or not, and the inner view will get it as the
286 // To properly initialize the view we need to know the frame for the content
287 // that is the parent of content for this frame. This might not be our actual
288 // frame parent if we are out of flow (e.g., positioned) so our parent frame
289 // may have been set to some other ancestor.
290 // We look for a content parent frame in the frame property list, where it
291 // will have been set by nsCSSFrameConstructor if necessary.
292 nsCOMPtr
<nsIAtom
> contentParentAtom
= do_GetAtom("contentParent");
293 nsIFrame
* contentParent
= nsnull
;
296 aPresContext
->PropertyTable()->UnsetProperty(this,
297 contentParentAtom
, &rv
);
298 if (NS_SUCCEEDED(rv
)) {
299 contentParent
= (nsIFrame
*)value
;
302 rv
= nsHTMLContainerFrame::CreateViewForFrame(this, contentParent
, PR_TRUE
);
303 NS_ENSURE_SUCCESS(rv
, rv
);
305 nsIView
* view
= GetView();
307 if (aParent
->GetStyleDisplay()->mDisplay
== NS_STYLE_DISPLAY_DECK
308 && !view
->HasWidget()) {
309 view
->CreateWidget(kCChildCID
);
317 nsSubDocumentFrame::ShowViewer()
319 if (!PresContext()->IsDynamic()) {
320 // We let the printing code take care of loading the document; just
321 // create a widget for it to use
322 nsresult rv
= CreateViewAndWidget(eContentTypeContent
);
327 nsresult rv
= ShowDocShell();
331 mDidCreateDoc
= PR_TRUE
;
336 nsSubDocumentFrame::GetSkipSides() const
342 nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
343 const nsRect
& aDirtyRect
,
344 const nsDisplayListSet
& aLists
)
346 if (!IsVisibleForPainting(aBuilder
))
349 nsresult rv
= DisplayBorderBackgroundOutline(aBuilder
, aLists
);
350 NS_ENSURE_SUCCESS(rv
, rv
);
354 nsIView
* subdocView
= mInnerView
->GetFirstChild();
357 nsIFrame
* f
= static_cast<nsIFrame
*>(subdocView
->GetClientData());
361 nsRect dirty
= aDirtyRect
- f
->GetOffsetTo(this);
363 aBuilder
->EnterPresShell(f
, dirty
);
365 // Clip children to the child root frame's rectangle
366 nsDisplayList childItems
;
367 rv
= f
->BuildDisplayListForStackingContext(aBuilder
, dirty
, &childItems
);
368 if (NS_SUCCEEDED(rv
)) {
369 rv
= aLists
.Content()->AppendNewToTop(
370 new (aBuilder
) nsDisplayClip(nsnull
, this, &childItems
,
371 nsRect(aBuilder
->ToReferenceFrame(f
), f
->GetSize())));
372 // delete childItems in case of OOM
373 childItems
.DeleteAll();
376 aBuilder
->LeavePresShell(f
, dirty
);
381 nsSubDocumentFrame::GetIntrinsicWidth()
384 return 0; // HTML <frame> has no useful intrinsic width
387 if (mContent
->IsNodeOfType(nsINode::eXUL
)) {
388 return 0; // XUL <iframe> and <browser> have no useful intrinsic width
391 NS_ASSERTION(ObtainIntrinsicSizeFrame() == nsnull
,
392 "Intrinsic width should come from the embedded document.");
394 // We must be an HTML <iframe>. Default to a width of 300, for IE
395 // compat (and per CSS2.1 draft).
396 return nsPresContext::CSSPixelsToAppUnits(300);
400 nsSubDocumentFrame::GetIntrinsicHeight()
402 // <frame> processing does not use this routine, only <iframe>
403 NS_ASSERTION(IsInline(), "Shouldn't have been called");
405 if (mContent
->IsNodeOfType(nsINode::eXUL
)) {
409 NS_ASSERTION(ObtainIntrinsicSizeFrame() == nsnull
,
410 "Intrinsic height should come from the embedded document.");
412 // Use 150px, for compatibility with IE, and per CSS2.1 draft.
413 return nsPresContext::CSSPixelsToAppUnits(150);
417 NS_IMETHODIMP
nsSubDocumentFrame::GetFrameName(nsAString
& aResult
) const
419 return MakeFrameName(NS_LITERAL_STRING("FrameOuter"), aResult
);
424 nsSubDocumentFrame::GetType() const
426 return nsGkAtoms::subDocumentFrame
;
429 /* virtual */ nscoord
430 nsSubDocumentFrame::GetMinWidth(nsIRenderingContext
*aRenderingContext
)
433 DISPLAY_MIN_WIDTH(this, result
);
435 nsIFrame
* subDocRoot
= ObtainIntrinsicSizeFrame();
437 result
= subDocRoot
->GetMinWidth(aRenderingContext
);
439 result
= GetIntrinsicWidth();
445 /* virtual */ nscoord
446 nsSubDocumentFrame::GetPrefWidth(nsIRenderingContext
*aRenderingContext
)
449 DISPLAY_PREF_WIDTH(this, result
);
451 nsIFrame
* subDocRoot
= ObtainIntrinsicSizeFrame();
453 result
= subDocRoot
->GetPrefWidth(aRenderingContext
);
455 result
= GetIntrinsicWidth();
461 /* virtual */ nsIFrame::IntrinsicSize
462 nsSubDocumentFrame::GetIntrinsicSize()
464 nsIFrame
* subDocRoot
= ObtainIntrinsicSizeFrame();
466 return subDocRoot
->GetIntrinsicSize();
468 return nsLeafFrame::GetIntrinsicSize();
472 nsSubDocumentFrame::GetIntrinsicRatio()
474 nsIFrame
* subDocRoot
= ObtainIntrinsicSizeFrame();
476 return subDocRoot
->GetIntrinsicRatio();
478 return nsLeafFrame::GetIntrinsicRatio();
482 nsSubDocumentFrame::ComputeAutoSize(nsIRenderingContext
*aRenderingContext
,
483 nsSize aCBSize
, nscoord aAvailableWidth
,
484 nsSize aMargin
, nsSize aBorder
,
485 nsSize aPadding
, PRBool aShrinkWrap
)
488 return nsFrame::ComputeAutoSize(aRenderingContext
, aCBSize
,
489 aAvailableWidth
, aMargin
, aBorder
,
490 aPadding
, aShrinkWrap
);
493 return nsLeafFrame::ComputeAutoSize(aRenderingContext
, aCBSize
,
494 aAvailableWidth
, aMargin
, aBorder
,
495 aPadding
, aShrinkWrap
);
500 nsSubDocumentFrame::ComputeSize(nsIRenderingContext
*aRenderingContext
,
501 nsSize aCBSize
, nscoord aAvailableWidth
,
502 nsSize aMargin
, nsSize aBorder
, nsSize aPadding
,
505 nsIFrame
* subDocRoot
= ObtainIntrinsicSizeFrame();
507 return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
508 aRenderingContext
, this,
509 subDocRoot
->GetIntrinsicSize(),
510 subDocRoot
->GetIntrinsicRatio(),
511 aCBSize
, aMargin
, aBorder
, aPadding
);
513 return nsLeafFrame::ComputeSize(aRenderingContext
, aCBSize
, aAvailableWidth
,
514 aMargin
, aBorder
, aPadding
, aShrinkWrap
);
518 nsSubDocumentFrame::Reflow(nsPresContext
* aPresContext
,
519 nsHTMLReflowMetrics
& aDesiredSize
,
520 const nsHTMLReflowState
& aReflowState
,
521 nsReflowStatus
& aStatus
)
523 DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame");
524 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
525 // printf("OuterFrame::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight);
526 NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS
,
527 ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d",
528 aReflowState
.availableWidth
, aReflowState
.availableHeight
));
530 aStatus
= NS_FRAME_COMPLETE
;
532 NS_ASSERTION(aPresContext
->GetPresShell()->GetPrimaryFrameFor(mContent
) == this,
535 // "offset" is the offset of our content area from our frame's
537 nsPoint
offset(0, 0);
540 // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed>
541 nsresult rv
= nsLeafFrame::DoReflow(aPresContext
, aDesiredSize
, aReflowState
,
543 NS_ENSURE_SUCCESS(rv
, rv
);
545 offset
= nsPoint(aReflowState
.mComputedBorderPadding
.left
,
546 aReflowState
.mComputedBorderPadding
.top
);
549 SizeToAvailSize(aReflowState
, aDesiredSize
);
552 nsSize
innerSize(aDesiredSize
.width
, aDesiredSize
.height
);
554 innerSize
.width
-= aReflowState
.mComputedBorderPadding
.LeftRight();
555 innerSize
.height
-= aReflowState
.mComputedBorderPadding
.TopBottom();
558 nsIViewManager
* vm
= mInnerView
->GetViewManager();
559 vm
->MoveViewTo(mInnerView
, offset
.x
, offset
.y
);
560 vm
->ResizeView(mInnerView
, nsRect(nsPoint(0, 0), innerSize
), PR_TRUE
);
562 // Determine if we need to repaint our border, background or outline
563 CheckInvalidateSizeChange(aDesiredSize
);
565 FinishAndStoreOverflow(&aDesiredSize
);
567 // Invalidate the frame contents
568 // XXX is this really needed?
569 nsRect
rect(nsPoint(0, 0), GetSize());
572 if (!aPresContext
->IsPaginated() && !mPostedReflowCallback
) {
573 PresContext()->PresShell()->PostReflowCallback(this);
574 mPostedReflowCallback
= PR_TRUE
;
577 // printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
578 // aDesiredSize.width, aDesiredSize.height);
580 NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS
,
581 ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
582 aDesiredSize
.width
, aDesiredSize
.height
, aStatus
));
584 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
589 nsSubDocumentFrame::ReflowFinished()
591 nsCOMPtr
<nsIDocShell
> docShell
;
592 GetDocShell(getter_AddRefs(docShell
));
594 nsCOMPtr
<nsIBaseWindow
> baseWindow(do_QueryInterface(docShell
));
596 // resize the sub document
601 nsWeakFrame
weakFrame(this);
603 nsPresContext
* presContext
= PresContext();
604 baseWindow
->GetPositionAndSize(&x
, &y
, nsnull
, nsnull
);
606 if (!weakFrame
.IsAlive()) {
607 // GetPositionAndSize() killed us
611 // GetPositionAndSize might have resized us. So now is the time to
613 mPostedReflowCallback
= PR_FALSE
;
615 nsSize
innerSize(GetSize());
617 nsMargin usedBorderPadding
= GetUsedBorderAndPadding();
619 // Sadly, XUL smacks the frame size without changing the used
620 // border and padding, so we can't trust those. Subtracting
621 // them might make things negative.
622 innerSize
.width
-= usedBorderPadding
.LeftRight();
623 innerSize
.width
= PR_MAX(innerSize
.width
, 0);
625 innerSize
.height
-= usedBorderPadding
.TopBottom();
626 innerSize
.height
= PR_MAX(innerSize
.height
, 0);
629 PRInt32 cx
= presContext
->AppUnitsToDevPixels(innerSize
.width
);
630 PRInt32 cy
= presContext
->AppUnitsToDevPixels(innerSize
.height
);
631 baseWindow
->SetPositionAndSize(x
, y
, cx
, cy
, PR_FALSE
);
633 // Make sure that we can post a reflow callback in the future.
634 mPostedReflowCallback
= PR_FALSE
;
641 nsSubDocumentFrame::ReflowCallbackCanceled()
643 mPostedReflowCallback
= PR_FALSE
;
647 nsSubDocumentFrame::VerifyTree() const
649 // XXX Completely disabled for now; once pseud-frames are reworked
650 // then we can turn it back on.
655 nsSubDocumentFrame::AttributeChanged(PRInt32 aNameSpaceID
,
659 if (aNameSpaceID
!= kNameSpaceID_None
) {
663 // If the noResize attribute changes, dis/allow frame to be resized
664 if (aAttribute
== nsGkAtoms::noresize
) {
665 // Note that we're not doing content type checks, but that's ok -- if
666 // they'd fail we will just end up with a null framesetFrame.
667 if (mContent
->GetParent()->Tag() == nsGkAtoms::frameset
) {
668 nsIFrame
* parentFrame
= GetParent();
671 // There is no interface for nsHTMLFramesetFrame so QI'ing to
672 // concrete class, yay!
673 nsHTMLFramesetFrame
* framesetFrame
= nsnull
;
674 parentFrame
->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame
),
675 (void **)&framesetFrame
);
678 framesetFrame
->RecalculateBorderResize();
683 else if (aAttribute
== nsGkAtoms::type
) {
687 if (!mContent
->IsNodeOfType(nsINode::eXUL
)) {
691 // Note: This logic duplicates a lot of logic in
692 // nsFrameLoader::EnsureDocShell. We should fix that.
694 // Notify our enclosing chrome that our type has changed. We only do this
695 // if our parent is chrome, since in all other cases we're random content
696 // subframes and the treeowner shouldn't worry about us.
698 nsCOMPtr
<nsIDocShell
> docShell
;
699 mFrameLoader
->GetDocShell(getter_AddRefs(docShell
));
700 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(docShell
));
701 if (!docShellAsItem
) {
705 nsCOMPtr
<nsIDocShellTreeItem
> parentItem
;
706 docShellAsItem
->GetParent(getter_AddRefs(parentItem
));
709 parentItem
->GetItemType(&parentType
);
711 if (parentType
!= nsIDocShellTreeItem::typeChrome
) {
715 nsCOMPtr
<nsIDocShellTreeOwner
> parentTreeOwner
;
716 parentItem
->GetTreeOwner(getter_AddRefs(parentTreeOwner
));
717 if (parentTreeOwner
) {
719 mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::type
, value
);
721 PRBool is_primary
= value
.LowerCaseEqualsLiteral("content-primary");
724 // when a content panel is no longer primary, hide any open popups it may have
726 nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance();
728 pm
->HidePopupsInDocShell(docShellAsItem
);
732 parentTreeOwner
->ContentShellRemoved(docShellAsItem
);
734 if (value
.LowerCaseEqualsLiteral("content") ||
735 StringBeginsWith(value
, NS_LITERAL_STRING("content-"),
736 nsCaseInsensitiveStringComparator())) {
737 PRBool is_targetable
= is_primary
||
738 value
.LowerCaseEqualsLiteral("content-targetable");
740 parentTreeOwner
->ContentShellAdded(docShellAsItem
, is_primary
,
741 is_targetable
, value
);
750 NS_NewSubDocumentFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
752 return new (aPresShell
) nsSubDocumentFrame(aContext
);
756 nsSubDocumentFrame::Destroy()
758 if (mPostedReflowCallback
) {
759 PresContext()->PresShell()->CancelReflowCallback(this);
760 mPostedReflowCallback
= PR_FALSE
;
765 nsLeafFrame::Destroy();
769 nsSubDocumentFrame::HideViewer()
771 if (mFrameLoader
&& mDidCreateDoc
) {
772 // Get the content viewer through the docshell, but don't call
773 // GetDocShell() since we don't want to create one if we don't
776 nsCOMPtr
<nsIDocShell
> docShell
;
777 mFrameLoader
->GetDocShell(getter_AddRefs(docShell
));
780 nsCOMPtr
<nsIContentViewer
> content_viewer
;
781 docShell
->GetContentViewer(getter_AddRefs(content_viewer
));
783 if (content_viewer
) {
784 // Mark the content viewer as non-sticky so that the presentation
785 // can safely go away when this frame is destroyed.
787 content_viewer
->SetSticky(PR_FALSE
);
790 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(docShell
);
791 NS_ASSERTION(baseWin
, "Docshell must be an nsIBaseWindow");
793 // Now reverse the steps we took in ShowDocShell(). But don't call
794 // Destroy(); that will be handled by destroying our frame loader, if
797 // Hide the content viewer now that the frame is going away...
798 baseWin
->SetVisibility(PR_FALSE
);
800 // Clear out the parentWidget, since it might be about to die with us
801 baseWin
->SetParentWidget(nsnull
);
806 nsSize
nsSubDocumentFrame::GetMargin()
808 nsSize
result(-1, -1);
809 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
811 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::marginwidth
);
812 if (attr
&& attr
->Type() == nsAttrValue::eInteger
)
813 result
.width
= attr
->GetIntegerValue();
814 attr
= content
->GetParsedAttr(nsGkAtoms::marginheight
);
815 if (attr
&& attr
->Type() == nsAttrValue::eInteger
)
816 result
.height
= attr
->GetIntegerValue();
821 // XXX this should be called ObtainDocShell or something like that,
822 // to indicate that it could have side effects
824 nsSubDocumentFrame::GetDocShell(nsIDocShell
**aDocShell
)
828 nsIContent
* content
= GetContent();
830 // Hmm, no content in this frame
831 // that's odd, not much to be done here then.
836 nsCOMPtr
<nsIFrameLoaderOwner
> loaderOwner
= do_QueryInterface(content
);
839 loaderOwner
->GetFrameLoader(getter_AddRefs(mFrameLoader
));
842 NS_ENSURE_STATE(mFrameLoader
);
845 return mFrameLoader
->GetDocShell(aDocShell
);
849 nsSubDocumentFrame::BeginSwapDocShells(nsIFrame
* aOther
)
851 if (!aOther
|| aOther
->GetType() != nsGkAtoms::subDocumentFrame
) {
852 return NS_ERROR_NOT_IMPLEMENTED
;
855 nsSubDocumentFrame
* other
= static_cast<nsSubDocumentFrame
*>(aOther
);
856 if (!mFrameLoader
|| !mDidCreateDoc
|| !other
->mFrameLoader
||
857 !other
->mDidCreateDoc
) {
858 return NS_ERROR_NOT_IMPLEMENTED
;
864 mFrameLoader
.swap(other
->mFrameLoader
);
869 nsSubDocumentFrame::EndSwapDocShells(nsIFrame
* aOther
)
871 nsSubDocumentFrame
* other
= static_cast<nsSubDocumentFrame
*>(aOther
);
875 // Now make sure we reflow both frames, in case their contents
876 // determine their size.
877 PresContext()->PresShell()->
878 FrameNeedsReflow(this, nsIPresShell::eTreeChange
, NS_FRAME_IS_DIRTY
);
879 other
->PresContext()->PresShell()->
880 FrameNeedsReflow(other
, nsIPresShell::eTreeChange
, NS_FRAME_IS_DIRTY
);
882 // And repaint them, for good measure, in case there's nothing
883 // interesting that happens during reflow.
884 InvalidateOverflowRect();
885 other
->InvalidateOverflowRect();
888 inline PRInt32
ConvertOverflow(PRUint8 aOverflow
)
891 case NS_STYLE_OVERFLOW_VISIBLE
:
892 case NS_STYLE_OVERFLOW_AUTO
:
893 return nsIScrollable::Scrollbar_Auto
;
894 case NS_STYLE_OVERFLOW_HIDDEN
:
895 case NS_STYLE_OVERFLOW_CLIP
:
896 return nsIScrollable::Scrollbar_Never
;
897 case NS_STYLE_OVERFLOW_SCROLL
:
898 return nsIScrollable::Scrollbar_Always
;
900 NS_NOTREACHED("invalid overflow value passed to ConvertOverflow");
901 return nsIScrollable::Scrollbar_Auto
;
905 nsSubDocumentFrame::ShowDocShell()
907 nsCOMPtr
<nsIDocShell
> docShell
;
908 nsresult rv
= GetDocShell(getter_AddRefs(docShell
));
909 NS_ENSURE_SUCCESS(rv
, rv
);
911 nsCOMPtr
<nsIPresShell
> presShell
;
912 docShell
->GetPresShell(getter_AddRefs(presShell
));
915 // The docshell is already showing, nothing left to do...
916 NS_ASSERTION(mInnerView
, "What's going on?");
920 // pass along marginwidth, marginheight, scrolling so sub document
922 nsSize margin
= GetMargin();
923 docShell
->SetMarginWidth(margin
.width
);
924 docShell
->SetMarginHeight(margin
.height
);
926 // Current and initial scrolling is set so that all succeeding docs
927 // will use the scrolling value set here, regardless if scrolling is
928 // set by viewing a particular document (e.g. XUL turns off scrolling)
929 nsCOMPtr
<nsIScrollable
> sc(do_QueryInterface(docShell
));
932 const nsStyleDisplay
*disp
= GetStyleDisplay();
933 sc
->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X
,
934 ConvertOverflow(disp
->mOverflowX
));
935 sc
->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y
,
936 ConvertOverflow(disp
->mOverflowY
));
939 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
940 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(docShell
));
942 treeItem
->GetItemType(&itemType
);
945 nsContentType contentType
;
946 if (itemType
== nsIDocShellTreeItem::typeChrome
) {
947 contentType
= eContentTypeUI
;
950 nsCOMPtr
<nsIDocShellTreeItem
> sameTypeParent
;
951 treeItem
->GetSameTypeParent(getter_AddRefs(sameTypeParent
));
952 contentType
= sameTypeParent
? eContentTypeContentFrame
: eContentTypeContent
;
954 rv
= CreateViewAndWidget(contentType
);
959 nsCOMPtr
<nsIBaseWindow
> baseWindow(do_QueryInterface(docShell
));
962 baseWindow
->InitWindow(nsnull
, mInnerView
->GetWidget(), 0, 0, 10, 10);
964 // This is kinda whacky, this "Create()" call doesn't really
965 // create anything, one starts to wonder why this was named
968 baseWindow
->Create();
970 baseWindow
->SetVisibility(PR_TRUE
);
973 // Trigger editor re-initialization if midas is turned on in the
974 // sub-document. This shouldn't be necessary, but given the way our
975 // editor works, it is. See
976 // https://bugzilla.mozilla.org/show_bug.cgi?id=284245
977 docShell
->GetPresShell(getter_AddRefs(presShell
));
979 nsCOMPtr
<nsIDOMNSHTMLDocument
> doc
=
980 do_QueryInterface(presShell
->GetDocument());
983 nsAutoString designMode
;
984 doc
->GetDesignMode(designMode
);
986 if (designMode
.EqualsLiteral("on")) {
987 doc
->SetDesignMode(NS_LITERAL_STRING("off"));
988 doc
->SetDesignMode(NS_LITERAL_STRING("on"));
997 nsSubDocumentFrame::CreateViewAndWidget(nsContentType aContentType
)
1000 // Nothing to do here
1004 // create, init, set the parent of the view
1005 nsIView
* outerView
= GetView();
1006 NS_ASSERTION(outerView
, "Must have an outer view already");
1007 nsRect
viewBounds(0, 0, 0, 0); // size will be fixed during reflow
1009 nsIViewManager
* viewMan
= outerView
->GetViewManager();
1010 // Create the inner view hidden if the outer view is already hidden
1011 // (it won't get hidden properly otherwise)
1012 nsIView
* innerView
= viewMan
->CreateView(viewBounds
, outerView
,
1013 outerView
->GetVisibility());
1015 NS_ERROR("Could not create inner view");
1016 return NS_ERROR_OUT_OF_MEMORY
;
1018 mInnerView
= innerView
;
1019 viewMan
->InsertChild(outerView
, innerView
, nsnull
, PR_TRUE
);
1021 return innerView
->CreateWidget(kCChildCID
, nsnull
, nsnull
, PR_TRUE
, PR_TRUE
,
1026 nsSubDocumentFrame::ObtainIntrinsicSizeFrame()
1028 nsCOMPtr
<nsIObjectLoadingContent
> olc
= do_QueryInterface(GetContent());
1030 // We are an HTML <object>, <embed> or <applet> (a replaced element).
1032 // Try to get an nsIFrame for our sub-document's document element
1033 nsIFrame
* subDocRoot
= nsnull
;
1035 nsCOMPtr
<nsIDocShell
> docShell
;
1036 GetDocShell(getter_AddRefs(docShell
));
1038 nsCOMPtr
<nsIPresShell
> presShell
;
1039 docShell
->GetPresShell(getter_AddRefs(presShell
));
1041 nsIScrollableFrame
* scrollable
= presShell
->GetRootScrollFrameAsScrollable();
1043 nsIFrame
* scrolled
= scrollable
->GetScrolledFrame();
1045 subDocRoot
= scrolled
->GetFirstChild(nsnull
);
1052 if (subDocRoot
&& subDocRoot
->GetContent() &&
1053 subDocRoot
->GetContent()->NodeInfo()->Equals(nsGkAtoms::svg
, kNameSpaceID_SVG
)) {
1054 return subDocRoot
; // SVG documents have an intrinsic size