/src/mozilla-central/dom/html/HTMLEmbedElement.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #include "mozilla/EventStates.h" |
8 | | #include "mozilla/dom/HTMLEmbedElement.h" |
9 | | #include "mozilla/dom/HTMLEmbedElementBinding.h" |
10 | | #include "mozilla/dom/ElementInlines.h" |
11 | | |
12 | | #include "nsIDocument.h" |
13 | | #include "nsIPluginDocument.h" |
14 | | #include "nsThreadUtils.h" |
15 | | #include "nsIScriptError.h" |
16 | | #include "nsIWidget.h" |
17 | | #include "nsContentUtils.h" |
18 | | #ifdef XP_MACOSX |
19 | | #include "mozilla/EventDispatcher.h" |
20 | | #include "mozilla/dom/Event.h" |
21 | | #endif |
22 | | #include "mozilla/dom/HTMLObjectElement.h" |
23 | | |
24 | | |
25 | | NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Embed) |
26 | | |
27 | | namespace mozilla { |
28 | | namespace dom { |
29 | | |
30 | | HTMLEmbedElement::HTMLEmbedElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, |
31 | | FromParser aFromParser) |
32 | | : nsGenericHTMLElement(std::move(aNodeInfo)) |
33 | 0 | { |
34 | 0 | RegisterActivityObserver(); |
35 | 0 | SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK); |
36 | 0 |
|
37 | 0 | // By default we're in the loading state |
38 | 0 | AddStatesSilently(NS_EVENT_STATE_LOADING); |
39 | 0 | } |
40 | | |
41 | | HTMLEmbedElement::~HTMLEmbedElement() |
42 | 0 | { |
43 | | #ifdef XP_MACOSX |
44 | | HTMLObjectElement::OnFocusBlurPlugin(this, false); |
45 | | #endif |
46 | | UnregisterActivityObserver(); |
47 | 0 | DestroyImageLoadingContent(); |
48 | 0 | } |
49 | | |
50 | | NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLEmbedElement) |
51 | | |
52 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLEmbedElement, |
53 | 0 | nsGenericHTMLElement) |
54 | 0 | nsObjectLoadingContent::Traverse(tmp, cb); |
55 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END |
56 | | |
57 | | NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLEmbedElement, |
58 | | nsGenericHTMLElement, |
59 | | nsIRequestObserver, |
60 | | nsIStreamListener, |
61 | | nsIFrameLoaderOwner, |
62 | | nsIObjectLoadingContent, |
63 | | imgINotificationObserver, |
64 | | nsIImageLoadingContent, |
65 | | nsIChannelEventSink) |
66 | | |
67 | | NS_IMPL_ELEMENT_CLONE(HTMLEmbedElement) |
68 | | |
69 | | #ifdef XP_MACOSX |
70 | | |
71 | | NS_IMETHODIMP |
72 | | HTMLEmbedElement::PostHandleEvent(EventChainPostVisitor& aVisitor) |
73 | | { |
74 | | HTMLObjectElement::HandleFocusBlurPlugin(this, aVisitor.mEvent); |
75 | | return NS_OK; |
76 | | } |
77 | | |
78 | | #endif // #ifdef XP_MACOSX |
79 | | |
80 | | void |
81 | | HTMLEmbedElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) |
82 | 0 | { |
83 | 0 | nsImageLoadingContent::AsyncEventRunning(aEvent); |
84 | 0 | } |
85 | | |
86 | | nsresult |
87 | | HTMLEmbedElement::BindToTree(nsIDocument *aDocument, |
88 | | nsIContent *aParent, |
89 | | nsIContent *aBindingParent) |
90 | 0 | { |
91 | 0 | nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, |
92 | 0 | aBindingParent); |
93 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
94 | 0 |
|
95 | 0 | rv = nsObjectLoadingContent::BindToTree(aDocument, aParent, |
96 | 0 | aBindingParent); |
97 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
98 | 0 |
|
99 | 0 | // Don't kick off load from being bound to a plugin document - the plugin |
100 | 0 | // document will call nsObjectLoadingContent::InitializeFromChannel() for the |
101 | 0 | // initial load. |
102 | 0 | nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument); |
103 | 0 |
|
104 | 0 | if (!pluginDoc) { |
105 | 0 | void (HTMLEmbedElement::*start)() = &HTMLEmbedElement::StartObjectLoad; |
106 | 0 | nsContentUtils::AddScriptRunner(NewRunnableMethod( |
107 | 0 | "dom::HTMLEmbedElement::BindToTree", this, start)); |
108 | 0 | } |
109 | 0 |
|
110 | 0 | return NS_OK; |
111 | 0 | } |
112 | | |
113 | | void |
114 | | HTMLEmbedElement::UnbindFromTree(bool aDeep, |
115 | | bool aNullParent) |
116 | 0 | { |
117 | | #ifdef XP_MACOSX |
118 | | // When a page is reloaded (when an nsIDocument's content is removed), the |
119 | | // focused element isn't necessarily sent an eBlur event. See |
120 | | // nsFocusManager::ContentRemoved(). This means that a widget may think it |
121 | | // still contains a focused plugin when it doesn't -- which in turn can |
122 | | // disable text input in the browser window. See bug 1137229. |
123 | | HTMLObjectElement::OnFocusBlurPlugin(this, false); |
124 | | #endif |
125 | | nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent); |
126 | 0 | nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); |
127 | 0 | } |
128 | | |
129 | | nsresult |
130 | | HTMLEmbedElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, |
131 | | const nsAttrValue* aValue, |
132 | | const nsAttrValue* aOldValue, |
133 | | nsIPrincipal* aSubjectPrincipal, |
134 | | bool aNotify) |
135 | 0 | { |
136 | 0 | if (aValue) { |
137 | 0 | nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); |
138 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
139 | 0 | } |
140 | 0 |
|
141 | 0 | return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue, |
142 | 0 | aOldValue, aSubjectPrincipal, aNotify); |
143 | 0 | } |
144 | | |
145 | | nsresult |
146 | | HTMLEmbedElement::OnAttrSetButNotChanged(int32_t aNamespaceID, |
147 | | nsAtom* aName, |
148 | | const nsAttrValueOrString& aValue, |
149 | | bool aNotify) |
150 | 0 | { |
151 | 0 | nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify); |
152 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
153 | 0 |
|
154 | 0 | return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName, |
155 | 0 | aValue, aNotify); |
156 | 0 | } |
157 | | |
158 | | nsresult |
159 | | HTMLEmbedElement::AfterMaybeChangeAttr(int32_t aNamespaceID, |
160 | | nsAtom* aName, |
161 | | bool aNotify) |
162 | 0 | { |
163 | 0 | if (aNamespaceID == kNameSpaceID_None) { |
164 | 0 | if (aName == nsGkAtoms::src) { |
165 | 0 | // If aNotify is false, we are coming from the parser or some such place; |
166 | 0 | // we'll get bound after all the attributes have been set, so we'll do the |
167 | 0 | // object load from BindToTree. |
168 | 0 | // Skip the LoadObject call in that case. |
169 | 0 | // We also don't want to start loading the object when we're not yet in |
170 | 0 | // a document, just in case that the caller wants to set additional |
171 | 0 | // attributes before inserting the node into the document. |
172 | 0 | if (aNotify && IsInComposedDoc() && |
173 | 0 | !BlockEmbedOrObjectContentLoading()) { |
174 | 0 | nsresult rv = LoadObject(aNotify, true); |
175 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
176 | 0 | } |
177 | 0 | } |
178 | 0 | } |
179 | 0 |
|
180 | 0 | return NS_OK; |
181 | 0 | } |
182 | | |
183 | | bool |
184 | | HTMLEmbedElement::IsHTMLFocusable(bool aWithMouse, |
185 | | bool *aIsFocusable, |
186 | | int32_t *aTabIndex) |
187 | 0 | { |
188 | 0 | // Has plugin content: let the plugin decide what to do in terms of |
189 | 0 | // internal focus from mouse clicks |
190 | 0 | if (aTabIndex) { |
191 | 0 | *aTabIndex = TabIndex(); |
192 | 0 | } |
193 | 0 |
|
194 | 0 | *aIsFocusable = true; |
195 | 0 |
|
196 | 0 | // Let the plugin decide, so override. |
197 | 0 | return true; |
198 | 0 | } |
199 | | |
200 | | nsIContent::IMEState |
201 | | HTMLEmbedElement::GetDesiredIMEState() |
202 | 0 | { |
203 | 0 | if (Type() == eType_Plugin) { |
204 | 0 | return IMEState(IMEState::PLUGIN); |
205 | 0 | } |
206 | 0 | |
207 | 0 | return nsGenericHTMLElement::GetDesiredIMEState(); |
208 | 0 | } |
209 | | |
210 | | int32_t |
211 | | HTMLEmbedElement::TabIndexDefault() |
212 | 0 | { |
213 | 0 | return -1; |
214 | 0 | } |
215 | | |
216 | | bool |
217 | | HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID, |
218 | | nsAtom *aAttribute, |
219 | | const nsAString &aValue, |
220 | | nsIPrincipal* aMaybeScriptedPrincipal, |
221 | | nsAttrValue &aResult) |
222 | 0 | { |
223 | 0 | if (aNamespaceID == kNameSpaceID_None) { |
224 | 0 | if (aAttribute == nsGkAtoms::align) { |
225 | 0 | return ParseAlignValue(aValue, aResult); |
226 | 0 | } |
227 | 0 | if (ParseImageAttribute(aAttribute, aValue, aResult)) { |
228 | 0 | return true; |
229 | 0 | } |
230 | 0 | } |
231 | 0 | |
232 | 0 | return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, |
233 | 0 | aMaybeScriptedPrincipal, aResult); |
234 | 0 | } |
235 | | |
236 | | static void |
237 | | MapAttributesIntoRuleBase(const nsMappedAttributes *aAttributes, |
238 | | MappedDeclarations& aDecls) |
239 | 0 | { |
240 | 0 | nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aDecls); |
241 | 0 | nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls); |
242 | 0 | nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls); |
243 | 0 | nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls); |
244 | 0 | } |
245 | | |
246 | | static void |
247 | | MapAttributesIntoRuleExceptHidden(const nsMappedAttributes *aAttributes, |
248 | | MappedDeclarations& aDecls) |
249 | 0 | { |
250 | 0 | MapAttributesIntoRuleBase(aAttributes, aDecls); |
251 | 0 | nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aDecls); |
252 | 0 | } |
253 | | |
254 | | void |
255 | | HTMLEmbedElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes, |
256 | | MappedDeclarations& aDecls) |
257 | 0 | { |
258 | 0 | MapAttributesIntoRuleBase(aAttributes, aDecls); |
259 | 0 | nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls); |
260 | 0 | } |
261 | | |
262 | | NS_IMETHODIMP_(bool) |
263 | | HTMLEmbedElement::IsAttributeMapped(const nsAtom *aAttribute) const |
264 | 0 | { |
265 | 0 | static const MappedAttributeEntry* const map[] = { |
266 | 0 | sCommonAttributeMap, |
267 | 0 | sImageMarginSizeAttributeMap, |
268 | 0 | sImageBorderAttributeMap, |
269 | 0 | sImageAlignAttributeMap, |
270 | 0 | }; |
271 | 0 |
|
272 | 0 | return FindAttributeDependence(aAttribute, map); |
273 | 0 | } |
274 | | |
275 | | |
276 | | nsMapRuleToAttributesFunc |
277 | | HTMLEmbedElement::GetAttributeMappingFunction() const |
278 | 0 | { |
279 | 0 | return &MapAttributesIntoRuleExceptHidden; |
280 | 0 | } |
281 | | |
282 | | void |
283 | | HTMLEmbedElement::StartObjectLoad(bool aNotify, bool aForceLoad) |
284 | 0 | { |
285 | 0 | // BindToTree can call us asynchronously, and we may be removed from the tree |
286 | 0 | // in the interim |
287 | 0 | if (!IsInComposedDoc() || !OwnerDoc()->IsActive() || |
288 | 0 | BlockEmbedOrObjectContentLoading()) { |
289 | 0 | return; |
290 | 0 | } |
291 | 0 | |
292 | 0 | LoadObject(aNotify, aForceLoad); |
293 | 0 | SetIsNetworkCreated(false); |
294 | 0 | } |
295 | | |
296 | | EventStates |
297 | | HTMLEmbedElement::IntrinsicState() const |
298 | 0 | { |
299 | 0 | return nsGenericHTMLElement::IntrinsicState() | ObjectState(); |
300 | 0 | } |
301 | | |
302 | | uint32_t |
303 | | HTMLEmbedElement::GetCapabilities() const |
304 | 0 | { |
305 | 0 | return eSupportPlugins | eAllowPluginSkipChannel | eSupportImages | eSupportDocuments; |
306 | 0 | } |
307 | | |
308 | | void |
309 | | HTMLEmbedElement::DestroyContent() |
310 | 0 | { |
311 | 0 | nsObjectLoadingContent::DestroyContent(); |
312 | 0 | nsGenericHTMLElement::DestroyContent(); |
313 | 0 | } |
314 | | |
315 | | nsresult |
316 | | HTMLEmbedElement::CopyInnerTo(HTMLEmbedElement* aDest) |
317 | 0 | { |
318 | 0 | nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest); |
319 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
320 | 0 |
|
321 | 0 | if (aDest->OwnerDoc()->IsStaticDocument()) { |
322 | 0 | CreateStaticClone(aDest); |
323 | 0 | } |
324 | 0 |
|
325 | 0 | return rv; |
326 | 0 | } |
327 | | |
328 | | JSObject* |
329 | | HTMLEmbedElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) |
330 | 0 | { |
331 | 0 | JSObject* obj; |
332 | 0 | obj = HTMLEmbedElement_Binding::Wrap(aCx, this, aGivenProto); |
333 | 0 |
|
334 | 0 | if (!obj) { |
335 | 0 | return nullptr; |
336 | 0 | } |
337 | 0 | JS::Rooted<JSObject*> rootedObj(aCx, obj); |
338 | 0 | SetupProtoChain(aCx, rootedObj); |
339 | 0 | return rootedObj; |
340 | 0 | } |
341 | | |
342 | | nsContentPolicyType |
343 | | HTMLEmbedElement::GetContentPolicyType() const |
344 | 0 | { |
345 | 0 | return nsIContentPolicy::TYPE_INTERNAL_EMBED; |
346 | 0 | } |
347 | | |
348 | | } // namespace dom |
349 | | } // namespace mozilla |