1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "nsIBrowser.h"
9 #include "nsIContent.h"
10 #include "nsIOpenWindowInfo.h"
11 #include "nsFrameLoader.h"
12 #include "mozilla/AsyncEventDispatcher.h"
13 #include "mozilla/dom/HTMLIFrameElement.h"
14 #include "mozilla/dom/WindowProxyHolder.h"
15 #include "mozilla/dom/XULFrameElement.h"
16 #include "mozilla/dom/XULFrameElementBinding.h"
18 namespace mozilla::dom
{
20 NS_IMPL_CYCLE_COLLECTION_CLASS(XULFrameElement
)
22 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULFrameElement
, nsXULElement
)
23 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader
)
24 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenWindowInfo
)
25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
27 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULFrameElement
, nsXULElement
)
28 if (tmp
->mFrameLoader
) {
29 tmp
->mFrameLoader
->Destroy();
31 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenWindowInfo
)
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
34 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(XULFrameElement
, nsXULElement
,
37 JSObject
* XULFrameElement::WrapNode(JSContext
* aCx
,
38 JS::Handle
<JSObject
*> aGivenProto
) {
39 return XULFrameElement_Binding::Wrap(aCx
, this, aGivenProto
);
42 nsDocShell
* XULFrameElement::GetDocShell() {
43 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
44 return frameLoader
? frameLoader
->GetDocShell(IgnoreErrors()) : nullptr;
47 already_AddRefed
<nsIWebNavigation
> XULFrameElement::GetWebNavigation() {
48 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell();
49 nsCOMPtr
<nsIWebNavigation
> webnav
= do_QueryInterface(docShell
);
50 return webnav
.forget();
53 Nullable
<WindowProxyHolder
> XULFrameElement::GetContentWindow() {
54 RefPtr
<nsDocShell
> docShell
= GetDocShell();
56 return docShell
->GetWindowProxy();
62 Document
* XULFrameElement::GetContentDocument() {
63 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell();
65 nsCOMPtr
<nsPIDOMWindowOuter
> win
= docShell
->GetWindow();
73 uint64_t XULFrameElement::BrowserId() {
75 if (auto* bc
= mFrameLoader
->GetExtantBrowsingContext()) {
76 return bc
->GetBrowserId();
82 nsIOpenWindowInfo
* XULFrameElement::GetOpenWindowInfo() const {
83 return mOpenWindowInfo
;
86 void XULFrameElement::SetOpenWindowInfo(nsIOpenWindowInfo
* aInfo
) {
87 mOpenWindowInfo
= aInfo
;
90 void XULFrameElement::LoadSrc() {
91 if (!IsInUncomposedDoc() || !OwnerDoc()->GetRootElement()) {
94 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
96 // We may have had a nsIOpenWindowInfo set on us by browser chrome, due to
97 // being used as the target for a `window.open` call. Fetch that information
98 // if it's available, and clear it out so we don't read it again.
99 nsCOMPtr
<nsIOpenWindowInfo
> openWindowInfo
= mOpenWindowInfo
.forget();
101 // false as the networkCreated parameter so that xul:iframe/browser/editor
102 // session history handling works like dynamic html:iframes. Usually xul
103 // elements are used in chrome, which doesn't have session history at all.
104 mFrameLoader
= nsFrameLoader::Create(this, false, openWindowInfo
);
105 if (NS_WARN_IF(!mFrameLoader
)) {
109 AsyncEventDispatcher::RunDOMEventWhenSafe(
110 *this, u
"XULFrameLoaderCreated"_ns
, CanBubble::eYes
);
113 mFrameLoader
->LoadFrame(false);
116 void XULFrameElement::SwapFrameLoaders(HTMLIFrameElement
& aOtherLoaderOwner
,
118 aOtherLoaderOwner
.SwapFrameLoaders(this, rv
);
121 void XULFrameElement::SwapFrameLoaders(XULFrameElement
& aOtherLoaderOwner
,
123 if (&aOtherLoaderOwner
== this) {
128 aOtherLoaderOwner
.SwapFrameLoaders(this, rv
);
131 void XULFrameElement::SwapFrameLoaders(nsFrameLoaderOwner
* aOtherLoaderOwner
,
132 mozilla::ErrorResult
& rv
) {
133 if (RefPtr
<Document
> doc
= GetComposedDoc()) {
134 // SwapWithOtherLoader relies on frames being up-to-date.
135 doc
->FlushPendingNotifications(FlushType::Frames
);
138 RefPtr
<nsFrameLoader
> loader
= GetFrameLoader();
139 RefPtr
<nsFrameLoader
> otherLoader
= aOtherLoaderOwner
->GetFrameLoader();
140 if (!loader
|| !otherLoader
) {
141 rv
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
145 rv
= loader
->SwapWithOtherLoader(otherLoader
, this, aOtherLoaderOwner
);
148 nsresult
XULFrameElement::BindToTree(BindContext
& aContext
, nsINode
& aParent
) {
149 nsresult rv
= nsXULElement::BindToTree(aContext
, aParent
);
150 NS_ENSURE_SUCCESS(rv
, rv
);
152 if (IsInUncomposedDoc()) {
153 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
154 "Missing a script blocker!");
155 // We're in a document now. Kick off the frame load.
162 void XULFrameElement::UnbindFromTree(UnbindContext
& aContext
) {
163 if (RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader()) {
164 frameLoader
->Destroy();
166 mFrameLoader
= nullptr;
168 nsXULElement::UnbindFromTree(aContext
);
171 void XULFrameElement::DestroyContent() {
172 RefPtr
<nsFrameLoader
> frameLoader
= GetFrameLoader();
174 frameLoader
->Destroy();
176 mFrameLoader
= nullptr;
178 nsXULElement::DestroyContent();
181 void XULFrameElement::AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aName
,
182 const nsAttrValue
* aValue
,
183 const nsAttrValue
* aOldValue
,
184 nsIPrincipal
* aSubjectPrincipal
,
186 if (aNamespaceID
== kNameSpaceID_None
) {
187 if (aName
== nsGkAtoms::src
&& aValue
) {
189 } else if (aName
== nsGkAtoms::disablefullscreen
&& mFrameLoader
) {
190 if (auto* bc
= mFrameLoader
->GetExtantBrowsingContext()) {
191 MOZ_ALWAYS_SUCCEEDS(bc
->SetFullscreenAllowedByOwner(!aValue
));
196 return nsXULElement::AfterSetAttr(aNamespaceID
, aName
, aValue
, aOldValue
,
197 aSubjectPrincipal
, aNotify
);
200 } // namespace mozilla::dom