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(bool aNullParent
) {
69 nsObjectLoadingContent::UnbindFromTree(aNullParent
);
70 nsGenericHTMLElement::UnbindFromTree(aNullParent
);
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() == eType_Document
? 0 : -1;
136 bool HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse
, bool* aIsFocusable
,
137 int32_t* aTabIndex
) {
138 // Plugins that show the empty fallback should not accept focus.
139 if (Type() == eType_Fallback
) {
144 *aIsFocusable
= false;
148 // Has non-plugin content: let the plugin decide what to do in terms of
149 // internal focus from mouse clicks
151 *aTabIndex
= TabIndex();
154 *aIsFocusable
= true;
156 // Let the plugin decide, so override.
160 bool HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
161 const nsAString
& aValue
,
162 nsIPrincipal
* aMaybeScriptedPrincipal
,
163 nsAttrValue
& aResult
) {
164 if (aNamespaceID
== kNameSpaceID_None
) {
165 if (aAttribute
== nsGkAtoms::align
) {
166 return ParseAlignValue(aValue
, aResult
);
168 if (aAttribute
== nsGkAtoms::width
|| aAttribute
== nsGkAtoms::height
||
169 aAttribute
== nsGkAtoms::hspace
|| aAttribute
== nsGkAtoms::vspace
) {
170 return aResult
.ParseHTMLDimension(aValue
);
174 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
175 aMaybeScriptedPrincipal
, aResult
);
178 static void MapAttributesIntoRuleBase(MappedDeclarationsBuilder
& aBuilder
) {
179 nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder
);
180 nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder
);
181 nsGenericHTMLElement::MapImageAlignAttributeInto(aBuilder
);
184 static void MapAttributesIntoRuleExceptHidden(
185 MappedDeclarationsBuilder
& aBuilder
) {
186 MapAttributesIntoRuleBase(aBuilder
);
187 nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aBuilder
);
190 void HTMLEmbedElement::MapAttributesIntoRule(
191 MappedDeclarationsBuilder
& aBuilder
) {
192 MapAttributesIntoRuleBase(aBuilder
);
193 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
197 HTMLEmbedElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
198 static const MappedAttributeEntry
* const map
[] = {
200 sImageMarginSizeAttributeMap
,
201 sImageBorderAttributeMap
,
202 sImageAlignAttributeMap
,
205 return FindAttributeDependence(aAttribute
, map
);
208 nsMapRuleToAttributesFunc
HTMLEmbedElement::GetAttributeMappingFunction()
210 return &MapAttributesIntoRuleExceptHidden
;
213 void HTMLEmbedElement::StartObjectLoad(bool aNotify
, bool aForceLoad
) {
214 // BindToTree can call us asynchronously, and we may be removed from the tree
216 if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
217 BlockEmbedOrObjectContentLoading()) {
221 LoadObject(aNotify
, aForceLoad
);
222 SetIsNetworkCreated(false);
225 uint32_t HTMLEmbedElement::GetCapabilities() const {
226 return eSupportPlugins
| eAllowPluginSkipChannel
| eSupportImages
|
230 void HTMLEmbedElement::DestroyContent() {
231 nsObjectLoadingContent::Destroy();
232 nsGenericHTMLElement::DestroyContent();
235 nsresult
HTMLEmbedElement::CopyInnerTo(HTMLEmbedElement
* aDest
) {
236 nsresult rv
= nsGenericHTMLElement::CopyInnerTo(aDest
);
237 NS_ENSURE_SUCCESS(rv
, rv
);
239 if (aDest
->OwnerDoc()->IsStaticDocument()) {
240 CreateStaticClone(aDest
);
246 JSObject
* HTMLEmbedElement::WrapNode(JSContext
* aCx
,
247 JS::Handle
<JSObject
*> aGivenProto
) {
248 return HTMLEmbedElement_Binding::Wrap(aCx
, this, aGivenProto
);
251 nsContentPolicyType
HTMLEmbedElement::GetContentPolicyType() const {
252 return nsIContentPolicy::TYPE_INTERNAL_EMBED
;
255 } // namespace mozilla::dom