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 RegisterActivityObserver();
32 SetIsNetworkCreated(aFromParser
== FROM_PARSER_NETWORK
);
35 HTMLEmbedElement::~HTMLEmbedElement() {
36 UnregisterActivityObserver();
37 nsImageLoadingContent::Destroy();
40 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLEmbedElement
)
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEmbedElement
,
44 nsObjectLoadingContent::Traverse(tmp
, cb
);
45 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
47 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLEmbedElement
,
49 nsObjectLoadingContent::Unlink(tmp
);
50 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
52 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
53 HTMLEmbedElement
, nsGenericHTMLElement
, nsIRequestObserver
,
54 nsIStreamListener
, nsFrameLoaderOwner
, nsIObjectLoadingContent
,
55 imgINotificationObserver
, nsIImageLoadingContent
, nsIChannelEventSink
)
57 NS_IMPL_ELEMENT_CLONE(HTMLEmbedElement
)
59 void HTMLEmbedElement::AsyncEventRunning(AsyncEventDispatcher
* aEvent
) {
60 nsImageLoadingContent::AsyncEventRunning(aEvent
);
63 nsresult
HTMLEmbedElement::BindToTree(BindContext
& aContext
, nsINode
& aParent
) {
64 nsresult rv
= nsGenericHTMLElement::BindToTree(aContext
, aParent
);
65 NS_ENSURE_SUCCESS(rv
, rv
);
67 rv
= nsObjectLoadingContent::BindToTree(aContext
, aParent
);
68 NS_ENSURE_SUCCESS(rv
, rv
);
70 if (IsInComposedDoc()) {
71 void (HTMLEmbedElement::*start
)() = &HTMLEmbedElement::StartObjectLoad
;
72 nsContentUtils::AddScriptRunner(
73 NewRunnableMethod("dom::HTMLEmbedElement::BindToTree", this, start
));
79 void HTMLEmbedElement::UnbindFromTree(bool aNullParent
) {
80 nsObjectLoadingContent::UnbindFromTree(aNullParent
);
81 nsGenericHTMLElement::UnbindFromTree(aNullParent
);
84 void HTMLEmbedElement::AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aName
,
85 const nsAttrValue
* aValue
,
86 const nsAttrValue
* aOldValue
,
87 nsIPrincipal
* aSubjectPrincipal
,
90 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
93 if (aNamespaceID
== kNameSpaceID_None
&&
94 aName
== nsGkAtoms::allowfullscreen
&& mFrameLoader
) {
95 if (auto* bc
= mFrameLoader
->GetExtantBrowsingContext()) {
96 MOZ_ALWAYS_SUCCEEDS(bc
->SetFullscreenAllowedByOwner(AllowFullscreen()));
100 return nsGenericHTMLElement::AfterSetAttr(
101 aNamespaceID
, aName
, aValue
, aOldValue
, aSubjectPrincipal
, aNotify
);
104 void HTMLEmbedElement::OnAttrSetButNotChanged(int32_t aNamespaceID
,
106 const nsAttrValueOrString
& aValue
,
108 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
109 return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID
, aName
,
113 void HTMLEmbedElement::AfterMaybeChangeAttr(int32_t aNamespaceID
, nsAtom
* aName
,
115 if (aNamespaceID
!= kNameSpaceID_None
|| aName
!= nsGkAtoms::src
) {
118 // If aNotify is false, we are coming from the parser or some such place;
119 // we'll get bound after all the attributes have been set, so we'll do the
120 // object load from BindToTree.
121 // Skip the LoadObject call in that case.
122 // We also don't want to start loading the object when we're not yet in
123 // a document, just in case that the caller wants to set additional
124 // attributes before inserting the node into the document.
125 if (!aNotify
|| !IsInComposedDoc() || BlockEmbedOrObjectContentLoading()) {
128 nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
129 "HTMLEmbedElement::LoadObject",
130 [self
= RefPtr
<HTMLEmbedElement
>(this), aNotify
]() {
131 if (self
->IsInComposedDoc()) {
132 self
->LoadObject(aNotify
, true);
137 int32_t HTMLEmbedElement::TabIndexDefault() {
138 // Only when we loaded a sub-document, <embed> should be tabbable by default
139 // because it's a navigable containers mentioned in 6.6.3 The tabindex
140 // attribute in the standard (see "If the value is null" section).
141 // https://html.spec.whatwg.org/#the-tabindex-attribute
142 // Otherwise, the default tab-index of <embed> is expected as -1 in a WPT:
143 // 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
144 return Type() == eType_Document
? 0 : -1;
147 bool HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse
, bool* aIsFocusable
,
148 int32_t* aTabIndex
) {
149 // Plugins that show the empty fallback should not accept focus.
150 if (Type() == eType_Fallback
) {
155 *aIsFocusable
= false;
159 // Has non-plugin content: let the plugin decide what to do in terms of
160 // internal focus from mouse clicks
162 *aTabIndex
= TabIndex();
165 *aIsFocusable
= true;
167 // Let the plugin decide, so override.
171 bool HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
172 const nsAString
& aValue
,
173 nsIPrincipal
* aMaybeScriptedPrincipal
,
174 nsAttrValue
& aResult
) {
175 if (aNamespaceID
== kNameSpaceID_None
) {
176 if (aAttribute
== nsGkAtoms::align
) {
177 return ParseAlignValue(aValue
, aResult
);
179 if (aAttribute
== nsGkAtoms::width
|| aAttribute
== nsGkAtoms::height
||
180 aAttribute
== nsGkAtoms::hspace
|| aAttribute
== nsGkAtoms::vspace
) {
181 return aResult
.ParseHTMLDimension(aValue
);
185 return nsGenericHTMLElement::ParseAttribute(aNamespaceID
, aAttribute
, aValue
,
186 aMaybeScriptedPrincipal
, aResult
);
189 static void MapAttributesIntoRuleBase(MappedDeclarationsBuilder
& aBuilder
) {
190 nsGenericHTMLElement::MapImageMarginAttributeInto(aBuilder
);
191 nsGenericHTMLElement::MapImageSizeAttributesInto(aBuilder
);
192 nsGenericHTMLElement::MapImageAlignAttributeInto(aBuilder
);
195 static void MapAttributesIntoRuleExceptHidden(
196 MappedDeclarationsBuilder
& aBuilder
) {
197 MapAttributesIntoRuleBase(aBuilder
);
198 nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aBuilder
);
201 void HTMLEmbedElement::MapAttributesIntoRule(
202 MappedDeclarationsBuilder
& aBuilder
) {
203 MapAttributesIntoRuleBase(aBuilder
);
204 nsGenericHTMLElement::MapCommonAttributesInto(aBuilder
);
208 HTMLEmbedElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
209 static const MappedAttributeEntry
* const map
[] = {
211 sImageMarginSizeAttributeMap
,
212 sImageBorderAttributeMap
,
213 sImageAlignAttributeMap
,
216 return FindAttributeDependence(aAttribute
, map
);
219 nsMapRuleToAttributesFunc
HTMLEmbedElement::GetAttributeMappingFunction()
221 return &MapAttributesIntoRuleExceptHidden
;
224 void HTMLEmbedElement::StartObjectLoad(bool aNotify
, bool aForceLoad
) {
225 // BindToTree can call us asynchronously, and we may be removed from the tree
227 if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
228 BlockEmbedOrObjectContentLoading()) {
232 LoadObject(aNotify
, aForceLoad
);
233 SetIsNetworkCreated(false);
236 uint32_t HTMLEmbedElement::GetCapabilities() const {
237 return eSupportPlugins
| eAllowPluginSkipChannel
| eSupportImages
|
241 void HTMLEmbedElement::DestroyContent() {
242 nsObjectLoadingContent::Destroy();
243 nsGenericHTMLElement::DestroyContent();
246 nsresult
HTMLEmbedElement::CopyInnerTo(HTMLEmbedElement
* aDest
) {
247 nsresult rv
= nsGenericHTMLElement::CopyInnerTo(aDest
);
248 NS_ENSURE_SUCCESS(rv
, rv
);
250 if (aDest
->OwnerDoc()->IsStaticDocument()) {
251 CreateStaticClone(aDest
);
257 JSObject
* HTMLEmbedElement::WrapNode(JSContext
* aCx
,
258 JS::Handle
<JSObject
*> aGivenProto
) {
259 return HTMLEmbedElement_Binding::Wrap(aCx
, this, aGivenProto
);
262 nsContentPolicyType
HTMLEmbedElement::GetContentPolicyType() const {
263 return nsIContentPolicy::TYPE_INTERNAL_EMBED
;
266 } // namespace mozilla::dom