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/BindContext.h"
8 #include "mozilla/dom/HTMLEmbedElement.h"
9 #include "mozilla/dom/HTMLEmbedElementBinding.h"
10 #include "mozilla/dom/ElementInlines.h"
12 #include "mozilla/dom/Document.h"
13 #include "nsObjectLoadingContent.h"
14 #include "nsThreadUtils.h"
15 #include "nsIWidget.h"
16 #include "nsContentUtils.h"
17 #include "nsFrameLoader.h"
19 # include "mozilla/EventDispatcher.h"
20 # include "mozilla/dom/Event.h"
23 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Embed
)
25 namespace mozilla::dom
{
27 HTMLEmbedElement::HTMLEmbedElement(
28 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
29 FromParser aFromParser
)
30 : nsGenericHTMLElement(std::move(aNodeInfo
)) {
31 SetIsNetworkCreated(aFromParser
== FROM_PARSER_NETWORK
);
34 HTMLEmbedElement::~HTMLEmbedElement() = default;
36 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLEmbedElement
)
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEmbedElement
,
40 nsObjectLoadingContent::Traverse(tmp
, cb
);
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
43 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLEmbedElement
,
45 nsObjectLoadingContent::Unlink(tmp
);
46 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
48 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
49 HTMLEmbedElement
, nsGenericHTMLElement
, nsIRequestObserver
,
50 nsIStreamListener
, nsFrameLoaderOwner
, nsIObjectLoadingContent
,
53 NS_IMPL_ELEMENT_CLONE(HTMLEmbedElement
)
55 nsresult
HTMLEmbedElement::BindToTree(BindContext
& aContext
, nsINode
& aParent
) {
56 nsresult rv
= nsGenericHTMLElement::BindToTree(aContext
, aParent
);
57 NS_ENSURE_SUCCESS(rv
, rv
);
59 if (IsInComposedDoc()) {
60 void (HTMLEmbedElement::*start
)() = &HTMLEmbedElement::StartObjectLoad
;
61 nsContentUtils::AddScriptRunner(
62 NewRunnableMethod("dom::HTMLEmbedElement::BindToTree", this, start
));
68 void HTMLEmbedElement::UnbindFromTree(UnbindContext
& aContext
) {
69 nsObjectLoadingContent::UnbindFromTree();
70 nsGenericHTMLElement::UnbindFromTree(aContext
);
73 void HTMLEmbedElement::AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aName
,
74 const nsAttrValue
* aValue
,
75 const nsAttrValue
* aOldValue
,
76 nsIPrincipal
* aSubjectPrincipal
,
79 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
82 if (aNamespaceID
== kNameSpaceID_None
&&
83 aName
== nsGkAtoms::allowfullscreen
&& mFrameLoader
) {
84 if (auto* bc
= mFrameLoader
->GetExtantBrowsingContext()) {
85 MOZ_ALWAYS_SUCCEEDS(bc
->SetFullscreenAllowedByOwner(AllowFullscreen()));
89 return nsGenericHTMLElement::AfterSetAttr(
90 aNamespaceID
, aName
, aValue
, aOldValue
, aSubjectPrincipal
, aNotify
);
93 void HTMLEmbedElement::OnAttrSetButNotChanged(int32_t aNamespaceID
,
95 const nsAttrValueOrString
& aValue
,
97 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
98 return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID
, aName
,
102 void HTMLEmbedElement::AfterMaybeChangeAttr(int32_t aNamespaceID
, nsAtom
* aName
,
104 if (aNamespaceID
!= kNameSpaceID_None
|| aName
!= nsGkAtoms::src
) {
107 // If aNotify is false, we are coming from the parser or some such place;
108 // we'll get bound after all the attributes have been set, so we'll do the
109 // object load from BindToTree.
110 // Skip the LoadObject call in that case.
111 // We also don't want to start loading the object when we're not yet in
112 // a document, just in case that the caller wants to set additional
113 // attributes before inserting the node into the document.
114 if (!aNotify
|| !IsInComposedDoc() || BlockEmbedOrObjectContentLoading()) {
117 nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
118 "HTMLEmbedElement::LoadObject",
119 [self
= RefPtr
<HTMLEmbedElement
>(this), aNotify
]() {
120 if (self
->IsInComposedDoc()) {
121 self
->LoadObject(aNotify
, true);
126 int32_t HTMLEmbedElement::TabIndexDefault() {
127 // Only when we loaded a sub-document, <embed> should be tabbable by default
128 // because it's a navigable containers mentioned in 6.6.3 The tabindex
129 // attribute in the standard (see "If the value is null" section).
130 // https://html.spec.whatwg.org/#the-tabindex-attribute
131 // Otherwise, the default tab-index of <embed> is expected as -1 in a WPT:
132 // https://searchfox.org/mozilla-central/rev/7d98e651953f3135d91e98fa6d33efa131aec7ea/testing/web-platform/tests/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/tabindex-getter.html#63
133 return Type() == ObjectType::Document
? 0 : -1;
136 bool HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse
, bool* aIsFocusable
,
137 int32_t* aTabIndex
) {
138 // Has non-plugin content: let the plugin decide what to do in terms of
139 // internal focus from mouse clicks
141 *aTabIndex
= TabIndex();
144 *aIsFocusable
= true;
146 // Let the plugin decide, so override.
150 bool HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
151 const nsAString
& aValue
,
152 nsIPrincipal
* aMaybeScriptedPrincipal
,
153 nsAttrValue
& aResult
) {
154 if (aNamespaceID
== kNameSpaceID_None
) {
155 if (aAttribute
== nsGkAtoms::align
) {
156 return ParseAlignValue(aValue
, aResult
);
158 if (aAttribute
== nsGkAtoms::width
|| aAttribute
== nsGkAtoms::height
||
159 aAttribute
== nsGkAtoms::hspace
|| aAttribute
== nsGkAtoms::vspace
) {
160 return aResult
.ParseHTMLDimension(aValue
);
164 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
165 aMaybeScriptedPrincipal
, aResult
);
168 static void MapAttributesIntoRuleBase(MappedDeclarationsBuilder
& aBuilder
) {
169 nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder
);
170 nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder
);
171 nsGenericHTMLElement::MapImageAlignAttributeInto(aBuilder
);
174 static void MapAttributesIntoRuleExceptHidden(
175 MappedDeclarationsBuilder
& aBuilder
) {
176 MapAttributesIntoRuleBase(aBuilder
);
177 nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aBuilder
);
180 void HTMLEmbedElement::MapAttributesIntoRule(
181 MappedDeclarationsBuilder
& aBuilder
) {
182 MapAttributesIntoRuleBase(aBuilder
);
183 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
187 HTMLEmbedElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
188 static const MappedAttributeEntry
* const map
[] = {
190 sImageMarginSizeAttributeMap
,
191 sImageBorderAttributeMap
,
192 sImageAlignAttributeMap
,
195 return FindAttributeDependence(aAttribute
, map
);
198 nsMapRuleToAttributesFunc
HTMLEmbedElement::GetAttributeMappingFunction()
200 return &MapAttributesIntoRuleExceptHidden
;
203 void HTMLEmbedElement::StartObjectLoad(bool aNotify
, bool aForceLoad
) {
204 // BindToTree can call us asynchronously, and we may be removed from the tree
206 if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
207 BlockEmbedOrObjectContentLoading()) {
211 LoadObject(aNotify
, aForceLoad
);
212 SetIsNetworkCreated(false);
215 uint32_t HTMLEmbedElement::GetCapabilities() const {
216 return eAllowPluginSkipChannel
| eSupportImages
| eSupportDocuments
;
219 void HTMLEmbedElement::DestroyContent() {
220 nsObjectLoadingContent::Destroy();
221 nsGenericHTMLElement::DestroyContent();
224 nsresult
HTMLEmbedElement::CopyInnerTo(HTMLEmbedElement
* aDest
) {
225 nsresult rv
= nsGenericHTMLElement::CopyInnerTo(aDest
);
226 NS_ENSURE_SUCCESS(rv
, rv
);
228 if (aDest
->OwnerDoc()->IsStaticDocument()) {
229 CreateStaticClone(aDest
);
235 JSObject
* HTMLEmbedElement::WrapNode(JSContext
* aCx
,
236 JS::Handle
<JSObject
*> aGivenProto
) {
237 return HTMLEmbedElement_Binding::Wrap(aCx
, this, aGivenProto
);
240 nsContentPolicyType
HTMLEmbedElement::GetContentPolicyType() const {
241 return nsIContentPolicy::TYPE_INTERNAL_EMBED
;
244 } // namespace mozilla::dom