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/Document.h"
9 #include "mozilla/dom/HTMLObjectElement.h"
10 #include "mozilla/dom/HTMLObjectElementBinding.h"
11 #include "mozilla/dom/ElementInlines.h"
12 #include "mozilla/dom/WindowProxyHolder.h"
13 #include "nsAttrValueInlines.h"
14 #include "nsGkAtoms.h"
16 #include "nsIContentInlines.h"
17 #include "nsIWidget.h"
18 #include "nsContentUtils.h"
20 # include "mozilla/EventDispatcher.h"
21 # include "mozilla/dom/Event.h"
22 # include "nsFocusManager.h"
25 namespace mozilla::dom
{
27 HTMLObjectElement::HTMLObjectElement(
28 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
,
29 FromParser aFromParser
)
30 : nsGenericHTMLFormControlElement(std::move(aNodeInfo
),
31 FormControlType::Object
),
32 mIsDoneAddingChildren(!aFromParser
) {
33 SetIsNetworkCreated(aFromParser
== FROM_PARSER_NETWORK
);
35 // <object> is always barred from constraint validation.
36 SetBarredFromConstraintValidation(true);
39 HTMLObjectElement::~HTMLObjectElement() = default;
41 bool HTMLObjectElement::IsInteractiveHTMLContent() const {
42 return HasAttr(nsGkAtoms::usemap
) ||
43 nsGenericHTMLFormControlElement::IsInteractiveHTMLContent();
46 void HTMLObjectElement::DoneAddingChildren(bool aHaveNotified
) {
47 mIsDoneAddingChildren
= true;
49 // If we're already in a document, we need to trigger the load
50 // Otherwise, BindToTree takes care of that.
51 if (IsInComposedDoc()) {
52 StartObjectLoad(aHaveNotified
, false);
56 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLObjectElement
)
58 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
59 HTMLObjectElement
, nsGenericHTMLFormControlElement
)
60 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity
)
61 nsObjectLoadingContent::Traverse(tmp
, cb
);
62 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
64 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLObjectElement
,
65 nsGenericHTMLFormControlElement
)
66 NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity
)
67 nsObjectLoadingContent::Unlink(tmp
);
68 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
70 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(
71 HTMLObjectElement
, nsGenericHTMLFormControlElement
, nsIRequestObserver
,
72 nsIStreamListener
, nsFrameLoaderOwner
, nsIObjectLoadingContent
,
73 nsIChannelEventSink
, nsIConstraintValidation
)
75 NS_IMPL_ELEMENT_CLONE(HTMLObjectElement
)
77 nsresult
HTMLObjectElement::BindToTree(BindContext
& aContext
,
79 nsresult rv
= nsGenericHTMLFormControlElement::BindToTree(aContext
, aParent
);
80 NS_ENSURE_SUCCESS(rv
, rv
);
82 // If we already have all the children, start the load.
83 if (IsInComposedDoc() && mIsDoneAddingChildren
) {
84 void (HTMLObjectElement::*start
)() = &HTMLObjectElement::StartObjectLoad
;
85 nsContentUtils::AddScriptRunner(
86 NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start
));
92 void HTMLObjectElement::UnbindFromTree(UnbindContext
& aContext
) {
93 nsObjectLoadingContent::UnbindFromTree();
94 nsGenericHTMLFormControlElement::UnbindFromTree(aContext
);
97 void HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID
, nsAtom
* aName
,
98 const nsAttrValue
* aValue
,
99 const nsAttrValue
* aOldValue
,
100 nsIPrincipal
* aSubjectPrincipal
,
102 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
103 return nsGenericHTMLFormControlElement::AfterSetAttr(
104 aNamespaceID
, aName
, aValue
, aOldValue
, aSubjectPrincipal
, aNotify
);
107 void HTMLObjectElement::OnAttrSetButNotChanged(
108 int32_t aNamespaceID
, nsAtom
* aName
, const nsAttrValueOrString
& aValue
,
110 AfterMaybeChangeAttr(aNamespaceID
, aName
, aNotify
);
111 return nsGenericHTMLFormControlElement::OnAttrSetButNotChanged(
112 aNamespaceID
, aName
, aValue
, aNotify
);
115 void HTMLObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID
,
116 nsAtom
* aName
, bool aNotify
) {
117 // if aNotify is false, we are coming from the parser or some such place;
118 // we'll get bound after all the attributes have been set, so we'll do the
119 // object load from BindToTree/DoneAddingChildren.
120 // Skip the LoadObject call in that case.
121 // We also don't want to start loading the object when we're not yet in
122 // a document, just in case that the caller wants to set additional
123 // attributes before inserting the node into the document.
124 if (aNamespaceID
!= kNameSpaceID_None
|| aName
!= nsGkAtoms::data
||
125 !aNotify
|| !IsInComposedDoc() || !mIsDoneAddingChildren
||
126 BlockEmbedOrObjectContentLoading()) {
129 nsContentUtils::AddScriptRunner(NS_NewRunnableFunction(
130 "HTMLObjectElement::LoadObject",
131 [self
= RefPtr
<HTMLObjectElement
>(this), aNotify
]() {
132 if (self
->IsInComposedDoc()) {
133 self
->LoadObject(aNotify
, true);
138 bool HTMLObjectElement::IsHTMLFocusable(bool aWithMouse
, bool* aIsFocusable
,
139 int32_t* aTabIndex
) {
140 // TODO: this should probably be managed directly by IsHTMLFocusable.
142 Document
* doc
= GetComposedDoc();
143 if (!doc
|| IsInDesignMode()) {
148 *aIsFocusable
= false;
152 const nsAttrValue
* attrVal
= mAttrs
.GetAttr(nsGkAtoms::tabindex
);
153 bool isFocusable
= attrVal
&& attrVal
->Type() == nsAttrValue::eInteger
;
155 // This method doesn't call nsGenericHTMLFormControlElement intentionally.
156 // TODO: It should probably be changed when bug 597242 will be fixed.
157 if (IsEditingHost() || Type() == ObjectType::Document
) {
159 *aTabIndex
= isFocusable
? attrVal
->GetIntegerValue() : 0;
162 *aIsFocusable
= true;
166 // TODO: this should probably be managed directly by IsHTMLFocusable.
168 if (aTabIndex
&& isFocusable
) {
169 *aTabIndex
= attrVal
->GetIntegerValue();
170 *aIsFocusable
= true;
176 int32_t HTMLObjectElement::TabIndexDefault() { return 0; }
178 Nullable
<WindowProxyHolder
> HTMLObjectElement::GetContentWindow(
179 nsIPrincipal
& aSubjectPrincipal
) {
180 Document
* doc
= GetContentDocument(aSubjectPrincipal
);
182 nsPIDOMWindowOuter
* win
= doc
->GetWindow();
184 return WindowProxyHolder(win
->GetBrowsingContext());
191 bool HTMLObjectElement::ParseAttribute(int32_t aNamespaceID
, nsAtom
* aAttribute
,
192 const nsAString
& aValue
,
193 nsIPrincipal
* aMaybeScriptedPrincipal
,
194 nsAttrValue
& aResult
) {
195 if (aNamespaceID
== kNameSpaceID_None
) {
196 if (aAttribute
== nsGkAtoms::align
) {
197 return ParseAlignValue(aValue
, aResult
);
199 if (ParseImageAttribute(aAttribute
, aValue
, aResult
)) {
204 return nsGenericHTMLFormControlElement::ParseAttribute(
205 aNamespaceID
, aAttribute
, aValue
, aMaybeScriptedPrincipal
, aResult
);
208 void HTMLObjectElement::MapAttributesIntoRule(
209 MappedDeclarationsBuilder
& aBuilder
) {
210 MapImageAlignAttributeInto(aBuilder
);
211 MapImageBorderAttributeInto(aBuilder
);
212 MapImageMarginAttributeInto(aBuilder
);
213 MapImageSizeAttributesInto(aBuilder
);
214 MapCommonAttributesInto(aBuilder
);
218 HTMLObjectElement::IsAttributeMapped(const nsAtom
* aAttribute
) const {
219 static const MappedAttributeEntry
* const map
[] = {
221 sImageMarginSizeAttributeMap
,
222 sImageBorderAttributeMap
,
223 sImageAlignAttributeMap
,
226 return FindAttributeDependence(aAttribute
, map
);
229 nsMapRuleToAttributesFunc
HTMLObjectElement::GetAttributeMappingFunction()
231 return &MapAttributesIntoRule
;
234 void HTMLObjectElement::StartObjectLoad(bool aNotify
, bool aForce
) {
235 // BindToTree can call us asynchronously, and we may be removed from the tree
237 if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
238 BlockEmbedOrObjectContentLoading()) {
242 LoadObject(aNotify
, aForce
);
243 SetIsNetworkCreated(false);
246 uint32_t HTMLObjectElement::GetCapabilities() const {
247 return nsObjectLoadingContent::GetCapabilities() | eFallbackIfClassIDPresent
;
250 void HTMLObjectElement::DestroyContent() {
251 nsObjectLoadingContent::Destroy();
252 nsGenericHTMLFormControlElement::DestroyContent();
255 nsresult
HTMLObjectElement::CopyInnerTo(Element
* aDest
) {
256 nsresult rv
= nsGenericHTMLFormControlElement::CopyInnerTo(aDest
);
257 NS_ENSURE_SUCCESS(rv
, rv
);
259 if (aDest
->OwnerDoc()->IsStaticDocument()) {
260 CreateStaticClone(static_cast<HTMLObjectElement
*>(aDest
));
266 JSObject
* HTMLObjectElement::WrapNode(JSContext
* aCx
,
267 JS::Handle
<JSObject
*> aGivenProto
) {
268 return HTMLObjectElement_Binding::Wrap(aCx
, this, aGivenProto
);
271 } // namespace mozilla::dom
273 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object
)