Bug 1719855 - Take over preventDefaulted infomation for long-tap events to the origin...
[gecko.git] / dom / html / HTMLIFrameElement.cpp
blob3e99ed425e9717ed4f8b1f0e1dd9a8ecf85b7e9b
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"
17 #include "nsError.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)
47 // static
48 const DOMTokenListSupportedToken HTMLIFrameElement::sSupportedSandboxTokens[] =
50 #define SANDBOX_KEYWORD(string, atom, flags) string,
51 #include "IframeSandboxKeywordList.h"
52 #undef SANDBOX_KEYWORD
53 nullptr};
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();
62 MOZ_ASSERT(origin);
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);
102 return true;
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);
132 NS_IMETHODIMP_(bool)
133 HTMLIFrameElement::IsAttributeMapped(const nsAtom* aAttribute) const {
134 static const MappedAttributeEntry attributes[] = {
135 {nsGkAtoms::width},
136 {nsGkAtoms::height},
137 {nsGkAtoms::frameborder},
138 {nullptr},
141 static const MappedAttributeEntry* const map[] = {
142 attributes,
143 sImageAlignAttributeMap,
144 sCommonAttributeMap,
147 return FindAttributeDependence(aAttribute, map);
150 nsMapRuleToAttributesFunc HTMLIFrameElement::GetAttributeMappingFunction()
151 const {
152 return &MapAttributesIntoRule;
155 void HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
156 const nsAttrValue* aValue,
157 const nsAttrValue* aOldValue,
158 nsIPrincipal* aMaybeScriptedPrincipal,
159 bool aNotify) {
160 AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify);
162 if (aNameSpaceID == kNameSpaceID_None) {
163 if (aName == nsGkAtoms::sandbox) {
164 if (mFrameLoader) {
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,
185 bool aNotify) {
186 AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
188 return nsGenericHTMLFrameElement::OnAttrSetButNotChanged(aNamespaceID, aName,
189 aValue, aNotify);
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.
198 LoadSrc();
203 uint32_t HTMLIFrameElement::GetSandboxFlags() const {
204 const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox);
205 // No sandbox attribute, no sandbox flags.
206 if (!sandboxAttr) {
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() {
222 if (!mFrameLoader) {
223 return;
226 // If the browsingContext is not ready (because docshell is dead), don't try
227 // to create one.
228 if (!mFrameLoader->IsRemoteFrame() && !mFrameLoader->GetExistingDocShell()) {
229 return;
232 RefPtr<BrowsingContext> browsingContext = mFrameLoader->GetBrowsingContext();
234 if (!browsingContext || !browsingContext->IsContentSubframe()) {
235 return;
238 if (ContentChild* cc = ContentChild::GetSingleton()) {
239 Unused << cc->SendSetContainerFeaturePolicy(browsingContext,
240 mFeaturePolicy);
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());
259 if (!principal) {
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();
272 MOZ_ASSERT(origin);
273 mFeaturePolicy->SetDefaultOrigin(origin);
275 nsAutoString allow;
276 GetAttr(nsGkAtoms::allow, allow);
278 if (!allow.IsEmpty()) {
279 // Set or reset the FeaturePolicy directives.
280 mFeaturePolicy->SetDeclaredPolicy(OwnerDoc(), allow, NodePrincipal(),
281 origin);
285 if (AllowFullscreen()) {
286 mFeaturePolicy->MaybeSetAllowedPolicy(u"fullscreen"_ns);
289 mFeaturePolicy->InheritPolicy(OwnerDoc()->FeaturePolicy());
290 MaybeStoreCrossOriginFeaturePolicy();
293 } // namespace mozilla::dom