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/. */
7 #include "mozilla/dom/HTMLIFrameElement.h"
8 #include "mozilla/dom/ContentChild.h"
9 #include "mozilla/dom/Document.h"
10 #include "mozilla/dom/HTMLIFrameElementBinding.h"
11 #include "mozilla/dom/FeaturePolicy.h"
12 #include "mozilla/MappedDeclarations.h"
13 #include "mozilla/NullPrincipal.h"
14 #include "mozilla/StaticPrefs_dom.h"
15 #include "nsMappedAttributes.h"
16 #include "nsAttrValueInlines.h"
18 #include "nsStyleConsts.h"
19 #include "nsContentUtils.h"
20 #include "nsSandboxFlags.h"
21 #include "nsNetUtil.h"
23 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame
)
25 namespace mozilla::dom
{
27 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLIFrameElement
)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLIFrameElement
,
30 nsGenericHTMLFrameElement
)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFeaturePolicy
)
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSandbox
)
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLIFrameElement
,
36 nsGenericHTMLFrameElement
)
37 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFeaturePolicy
)
38 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSandbox
)
39 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
41 NS_IMPL_ADDREF_INHERITED(HTMLIFrameElement
, nsGenericHTMLFrameElement
)
42 NS_IMPL_RELEASE_INHERITED(HTMLIFrameElement
, nsGenericHTMLFrameElement
)
44 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLIFrameElement
)
45 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLFrameElement
)
48 const DOMTokenListSupportedToken
HTMLIFrameElement::sSupportedSandboxTokens
[] =
50 #define SANDBOX_KEYWORD(string, atom, flags) string,
51 #include "IframeSandboxKeywordList.h"
52 #undef SANDBOX_KEYWORD
55 HTMLIFrameElement::HTMLIFrameElement(
56 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
57 FromParser aFromParser
)
58 : nsGenericHTMLFrameElement(std::move(aNodeInfo
), aFromParser
) {
59 // We always need a featurePolicy, even if not exposed.
60 mFeaturePolicy
= new mozilla::dom::FeaturePolicy(this);
61 nsCOMPtr
<nsIPrincipal
> origin
= GetFeaturePolicyDefaultOrigin();
63 mFeaturePolicy
->SetDefaultOrigin(origin
);
66 HTMLIFrameElement::~HTMLIFrameElement() = default;
68 NS_IMPL_ELEMENT_CLONE(HTMLIFrameElement
)
70 void HTMLIFrameElement::BindToBrowsingContext(BrowsingContext
*) {
71 RefreshFeaturePolicy(true /* parse the feature policy attribute */);
74 bool HTMLIFrameElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
75 const nsAString
& aValue
,
76 nsIPrincipal
* aMaybeScriptedPrincipal
,
77 nsAttrValue
& aResult
) {
78 if (aNamespaceID
== kNameSpaceID_None
) {
79 if (aAttribute
== nsGkAtoms::marginwidth
) {
80 return aResult
.ParseNonNegativeIntValue(aValue
);
82 if (aAttribute
== nsGkAtoms::marginheight
) {
83 return aResult
.ParseNonNegativeIntValue(aValue
);
85 if (aAttribute
== nsGkAtoms::width
) {
86 return aResult
.ParseHTMLDimension(aValue
);
88 if (aAttribute
== nsGkAtoms::height
) {
89 return aResult
.ParseHTMLDimension(aValue
);
91 if (aAttribute
== nsGkAtoms::frameborder
) {
92 return ParseFrameborderValue(aValue
, aResult
);
94 if (aAttribute
== nsGkAtoms::scrolling
) {
95 return ParseScrollingValue(aValue
, aResult
);
97 if (aAttribute
== nsGkAtoms::align
) {
98 return ParseAlignValue(aValue
, aResult
);
100 if (aAttribute
== nsGkAtoms::sandbox
) {
101 aResult
.ParseAtomArray(aValue
);
106 return nsGenericHTMLFrameElement::ParseAttribute(
107 aNamespaceID
, aAttribute
, aValue
, aMaybeScriptedPrincipal
, aResult
);
110 void HTMLIFrameElement::MapAttributesIntoRule(
111 const nsMappedAttributes
* aAttributes
, MappedDeclarations
& aDecls
) {
112 // frameborder: 0 | 1 (| NO | YES in quirks mode)
113 // If frameborder is 0 or No, set border to 0
114 // else leave it as the value set in html.css
115 const nsAttrValue
* value
= aAttributes
->GetAttr(nsGkAtoms::frameborder
);
116 if (value
&& value
->Type() == nsAttrValue::eEnum
) {
117 auto frameborder
= static_cast<FrameBorderProperty
>(value
->GetEnumValue());
118 if (FrameBorderProperty::No
== frameborder
||
119 FrameBorderProperty::Zero
== frameborder
) {
120 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_top_width
, 0.0f
);
121 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_right_width
, 0.0f
);
122 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_bottom_width
, 0.0f
);
123 aDecls
.SetPixelValueIfUnset(eCSSProperty_border_left_width
, 0.0f
);
127 nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes
, aDecls
);
128 nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes
, aDecls
);
129 nsGenericHTMLElement::MapCommonAttributesInto(aAttributes
, aDecls
);
133 HTMLIFrameElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
134 static const MappedAttributeEntry attributes
[] = {
137 {nsGkAtoms::frameborder
},
141 static const MappedAttributeEntry
* const map
[] = {
143 sImageAlignAttributeMap
,
147 return FindAttributeDependence(aAttribute
, map
);
150 nsMapRuleToAttributesFunc
HTMLIFrameElement::GetAttributeMappingFunction()
152 return &MapAttributesIntoRule
;
155 void HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID
, nsAtom
* aName
,
156 const nsAttrValue
* aValue
,
157 const nsAttrValue
* aOldValue
,
158 nsIPrincipal
* aMaybeScriptedPrincipal
,
160 AfterMaybeChangeAttr(aNameSpaceID
, aName
, aNotify
);
162 if (aNameSpaceID
== kNameSpaceID_None
) {
163 if (aName
== nsGkAtoms::sandbox
) {
165 // If we have an nsFrameLoader, apply the new sandbox flags.
166 // Since this is called after the setter, the sandbox flags have
167 // alreay been updated.
168 mFrameLoader
->ApplySandboxFlags(GetSandboxFlags());
172 if (aName
== nsGkAtoms::allow
|| aName
== nsGkAtoms::src
||
173 aName
== nsGkAtoms::srcdoc
|| aName
== nsGkAtoms::sandbox
) {
174 RefreshFeaturePolicy(true /* parse the feature policy attribute */);
175 } else if (aName
== nsGkAtoms::allowfullscreen
) {
176 RefreshFeaturePolicy(false /* parse the feature policy attribute */);
179 return nsGenericHTMLFrameElement::AfterSetAttr(
180 aNameSpaceID
, aName
, aValue
, aOldValue
, aMaybeScriptedPrincipal
, aNotify
);
183 void HTMLIFrameElement::OnAttrSetButNotChanged(
184 int32_t aNamespaceID
, nsAtom
* aName
, const nsAttrValueOrString
& aValue
,
186 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
188 return nsGenericHTMLFrameElement::OnAttrSetButNotChanged(aNamespaceID
, aName
,
192 void HTMLIFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID
,
193 nsAtom
* aName
, bool aNotify
) {
194 if (aNamespaceID
== kNameSpaceID_None
) {
195 if (aName
== nsGkAtoms::srcdoc
) {
196 // Don't propagate errors from LoadSrc. The attribute was successfully
197 // set/unset, that's what we should reflect.
203 uint32_t HTMLIFrameElement::GetSandboxFlags() const {
204 const nsAttrValue
* sandboxAttr
= GetParsedAttr(nsGkAtoms::sandbox
);
205 // No sandbox attribute, no sandbox flags.
207 return SANDBOXED_NONE
;
209 return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr
);
212 JSObject
* HTMLIFrameElement::WrapNode(JSContext
* aCx
,
213 JS::Handle
<JSObject
*> aGivenProto
) {
214 return HTMLIFrameElement_Binding::Wrap(aCx
, this, aGivenProto
);
217 mozilla::dom::FeaturePolicy
* HTMLIFrameElement::FeaturePolicy() const {
218 return mFeaturePolicy
;
221 void HTMLIFrameElement::MaybeStoreCrossOriginFeaturePolicy() {
226 // If the browsingContext is not ready (because docshell is dead), don't try
228 if (!mFrameLoader
->IsRemoteFrame() && !mFrameLoader
->GetExistingDocShell()) {
232 RefPtr
<BrowsingContext
> browsingContext
= mFrameLoader
->GetBrowsingContext();
234 if (!browsingContext
|| !browsingContext
->IsContentSubframe()) {
238 if (ContentChild
* cc
= ContentChild::GetSingleton()) {
239 Unused
<< cc
->SendSetContainerFeaturePolicy(browsingContext
,
244 already_AddRefed
<nsIPrincipal
>
245 HTMLIFrameElement::GetFeaturePolicyDefaultOrigin() const {
246 nsCOMPtr
<nsIPrincipal
> principal
;
248 if (HasAttr(kNameSpaceID_None
, nsGkAtoms::srcdoc
)) {
249 principal
= NodePrincipal();
250 return principal
.forget();
253 nsCOMPtr
<nsIURI
> nodeURI
;
254 if (GetURIAttr(nsGkAtoms::src
, nullptr, getter_AddRefs(nodeURI
)) && nodeURI
) {
255 principal
= BasePrincipal::CreateContentPrincipal(
256 nodeURI
, BasePrincipal::Cast(NodePrincipal())->OriginAttributesRef());
260 principal
= NodePrincipal();
263 return principal
.forget();
266 void HTMLIFrameElement::RefreshFeaturePolicy(bool aParseAllowAttribute
) {
267 if (aParseAllowAttribute
) {
268 mFeaturePolicy
->ResetDeclaredPolicy();
270 // The origin can change if 'src' and 'srcdoc' attributes change.
271 nsCOMPtr
<nsIPrincipal
> origin
= GetFeaturePolicyDefaultOrigin();
273 mFeaturePolicy
->SetDefaultOrigin(origin
);
276 GetAttr(nsGkAtoms::allow
, allow
);
278 if (!allow
.IsEmpty()) {
279 // Set or reset the FeaturePolicy directives.
280 mFeaturePolicy
->SetDeclaredPolicy(OwnerDoc(), allow
, NodePrincipal(),
285 if (AllowFullscreen()) {
286 mFeaturePolicy
->MaybeSetAllowedPolicy(u
"fullscreen"_ns
);
289 mFeaturePolicy
->InheritPolicy(OwnerDoc()->FeaturePolicy());
290 MaybeStoreCrossOriginFeaturePolicy();
293 } // namespace mozilla::dom