Line data Source code
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/HTMLSharedObjectElement.h"
9 : #include "mozilla/dom/HTMLEmbedElementBinding.h"
10 : #include "mozilla/dom/HTMLAppletElementBinding.h"
11 : #include "mozilla/dom/ElementInlines.h"
12 :
13 : #include "nsIDocument.h"
14 : #include "nsIPluginDocument.h"
15 : #include "nsIDOMDocument.h"
16 : #include "nsThreadUtils.h"
17 : #include "nsIScriptError.h"
18 : #include "nsIWidget.h"
19 : #include "nsContentUtils.h"
20 : #ifdef XP_MACOSX
21 : #include "mozilla/EventDispatcher.h"
22 : #include "mozilla/dom/Event.h"
23 : #endif
24 : #include "mozilla/dom/HTMLObjectElement.h"
25 :
26 :
27 0 : NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(SharedObject)
28 :
29 : namespace mozilla {
30 : namespace dom {
31 :
32 0 : HTMLSharedObjectElement::HTMLSharedObjectElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
33 0 : FromParser aFromParser)
34 : : nsGenericHTMLElement(aNodeInfo),
35 0 : mIsDoneAddingChildren(mNodeInfo->Equals(nsGkAtoms::embed) || !aFromParser)
36 : {
37 0 : RegisterActivityObserver();
38 0 : SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
39 :
40 : // By default we're in the loading state
41 0 : AddStatesSilently(NS_EVENT_STATE_LOADING);
42 0 : }
43 :
44 0 : HTMLSharedObjectElement::~HTMLSharedObjectElement()
45 : {
46 : #ifdef XP_MACOSX
47 : HTMLObjectElement::OnFocusBlurPlugin(this, false);
48 : #endif
49 0 : UnregisterActivityObserver();
50 0 : DestroyImageLoadingContent();
51 0 : }
52 :
53 : bool
54 0 : HTMLSharedObjectElement::IsDoneAddingChildren()
55 : {
56 0 : return mIsDoneAddingChildren;
57 : }
58 :
59 : void
60 0 : HTMLSharedObjectElement::DoneAddingChildren(bool aHaveNotified)
61 : {
62 0 : if (!mIsDoneAddingChildren) {
63 0 : mIsDoneAddingChildren = true;
64 :
65 : // If we're already in a document, we need to trigger the load
66 : // Otherwise, BindToTree takes care of that.
67 0 : if (IsInComposedDoc()) {
68 0 : StartObjectLoad(aHaveNotified, false);
69 : }
70 : }
71 0 : }
72 :
73 : NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLSharedObjectElement)
74 :
75 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLSharedObjectElement,
76 : nsGenericHTMLElement)
77 0 : nsObjectLoadingContent::Traverse(tmp, cb);
78 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
79 :
80 0 : NS_IMPL_ADDREF_INHERITED(HTMLSharedObjectElement, Element)
81 0 : NS_IMPL_RELEASE_INHERITED(HTMLSharedObjectElement, Element)
82 :
83 0 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLSharedObjectElement)
84 0 : NS_INTERFACE_TABLE_INHERITED(HTMLSharedObjectElement,
85 : nsIRequestObserver,
86 : nsIStreamListener,
87 : nsIFrameLoaderOwner,
88 : nsIObjectLoadingContent,
89 : imgINotificationObserver,
90 : nsIImageLoadingContent,
91 : imgIOnloadBlocker,
92 : nsIChannelEventSink)
93 0 : NS_INTERFACE_TABLE_TO_MAP_SEGUE
94 0 : NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLAppletElement, applet)
95 0 : NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLEmbedElement, embed)
96 0 : NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
97 :
98 0 : NS_IMPL_ELEMENT_CLONE(HTMLSharedObjectElement)
99 :
100 : #ifdef XP_MACOSX
101 :
102 : NS_IMETHODIMP
103 : HTMLSharedObjectElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
104 : {
105 : HTMLObjectElement::HandleFocusBlurPlugin(this, aVisitor.mEvent);
106 : return NS_OK;
107 : }
108 :
109 : #endif // #ifdef XP_MACOSX
110 :
111 : void
112 0 : HTMLSharedObjectElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
113 : {
114 0 : nsImageLoadingContent::AsyncEventRunning(aEvent);
115 0 : }
116 :
117 : nsresult
118 0 : HTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
119 : nsIContent *aParent,
120 : nsIContent *aBindingParent,
121 : bool aCompileEventHandlers)
122 : {
123 0 : nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
124 : aBindingParent,
125 0 : aCompileEventHandlers);
126 0 : NS_ENSURE_SUCCESS(rv, rv);
127 :
128 0 : rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
129 : aBindingParent,
130 0 : aCompileEventHandlers);
131 0 : NS_ENSURE_SUCCESS(rv, rv);
132 :
133 : // Don't kick off load from being bound to a plugin document - the plugin
134 : // document will call nsObjectLoadingContent::InitializeFromChannel() for the
135 : // initial load.
136 0 : nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
137 :
138 : // If we already have all the children, start the load.
139 0 : if (mIsDoneAddingChildren && !pluginDoc) {
140 : void (HTMLSharedObjectElement::*start)() =
141 0 : &HTMLSharedObjectElement::StartObjectLoad;
142 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod(
143 0 : "dom::HTMLSharedObjectElement::BindToTree", this, start));
144 : }
145 :
146 0 : return NS_OK;
147 : }
148 :
149 : void
150 0 : HTMLSharedObjectElement::UnbindFromTree(bool aDeep,
151 : bool aNullParent)
152 : {
153 : #ifdef XP_MACOSX
154 : // When a page is reloaded (when an nsIDocument's content is removed), the
155 : // focused element isn't necessarily sent an eBlur event. See
156 : // nsFocusManager::ContentRemoved(). This means that a widget may think it
157 : // still contains a focused plugin when it doesn't -- which in turn can
158 : // disable text input in the browser window. See bug 1137229.
159 : HTMLObjectElement::OnFocusBlurPlugin(this, false);
160 : #endif
161 0 : nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
162 0 : nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
163 0 : }
164 :
165 : nsresult
166 0 : HTMLSharedObjectElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
167 : const nsAttrValue* aValue,
168 : const nsAttrValue* aOldValue,
169 : bool aNotify)
170 : {
171 0 : if (aValue) {
172 0 : nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
173 0 : NS_ENSURE_SUCCESS(rv, rv);
174 : }
175 :
176 0 : return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
177 0 : aOldValue, aNotify);
178 : }
179 :
180 : nsresult
181 0 : HTMLSharedObjectElement::OnAttrSetButNotChanged(int32_t aNamespaceID,
182 : nsIAtom* aName,
183 : const nsAttrValueOrString& aValue,
184 : bool aNotify)
185 : {
186 0 : nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
187 0 : NS_ENSURE_SUCCESS(rv, rv);
188 :
189 0 : return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName,
190 0 : aValue, aNotify);
191 : }
192 :
193 : nsresult
194 0 : HTMLSharedObjectElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
195 : nsIAtom* aName,
196 : bool aNotify)
197 : {
198 0 : if (aNamespaceID == kNameSpaceID_None) {
199 0 : if (aName == URIAttrName()) {
200 : // If aNotify is false, we are coming from the parser or some such place;
201 : // we'll get bound after all the attributes have been set, so we'll do the
202 : // object load from BindToTree/DoneAddingChildren.
203 : // Skip the LoadObject call in that case.
204 : // We also don't want to start loading the object when we're not yet in
205 : // a document, just in case that the caller wants to set additional
206 : // attributes before inserting the node into the document.
207 0 : if (aNotify && IsInComposedDoc() && mIsDoneAddingChildren &&
208 0 : !BlockEmbedOrObjectContentLoading()) {
209 0 : nsresult rv = LoadObject(aNotify, true);
210 0 : NS_ENSURE_SUCCESS(rv, rv);
211 : }
212 : }
213 : }
214 :
215 0 : return NS_OK;
216 : }
217 :
218 : bool
219 0 : HTMLSharedObjectElement::IsHTMLFocusable(bool aWithMouse,
220 : bool *aIsFocusable,
221 : int32_t *aTabIndex)
222 : {
223 0 : if (mNodeInfo->Equals(nsGkAtoms::embed) || Type() == eType_Plugin) {
224 : // Has plugin content: let the plugin decide what to do in terms of
225 : // internal focus from mouse clicks
226 0 : if (aTabIndex) {
227 0 : GetTabIndex(aTabIndex);
228 : }
229 :
230 0 : *aIsFocusable = true;
231 :
232 : // Let the plugin decide, so override.
233 0 : return true;
234 : }
235 :
236 0 : return nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex);
237 : }
238 :
239 : nsIContent::IMEState
240 0 : HTMLSharedObjectElement::GetDesiredIMEState()
241 : {
242 0 : if (Type() == eType_Plugin) {
243 0 : return IMEState(IMEState::PLUGIN);
244 : }
245 :
246 0 : return nsGenericHTMLElement::GetDesiredIMEState();
247 : }
248 :
249 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Align, align)
250 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Alt, alt)
251 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Archive, archive)
252 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Code, code)
253 0 : NS_IMPL_URI_ATTR(HTMLSharedObjectElement, CodeBase, codebase)
254 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Height, height)
255 0 : NS_IMPL_INT_ATTR(HTMLSharedObjectElement, Hspace, hspace)
256 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Name, name)
257 0 : NS_IMPL_URI_ATTR_WITH_BASE(HTMLSharedObjectElement, Object, object, codebase)
258 0 : NS_IMPL_URI_ATTR(HTMLSharedObjectElement, Src, src)
259 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Type, type)
260 0 : NS_IMPL_INT_ATTR(HTMLSharedObjectElement, Vspace, vspace)
261 0 : NS_IMPL_STRING_ATTR(HTMLSharedObjectElement, Width, width)
262 :
263 : int32_t
264 0 : HTMLSharedObjectElement::TabIndexDefault()
265 : {
266 0 : return -1;
267 : }
268 :
269 : bool
270 0 : HTMLSharedObjectElement::ParseAttribute(int32_t aNamespaceID,
271 : nsIAtom *aAttribute,
272 : const nsAString &aValue,
273 : nsAttrValue &aResult)
274 : {
275 0 : if (aNamespaceID == kNameSpaceID_None) {
276 0 : if (aAttribute == nsGkAtoms::align) {
277 0 : return ParseAlignValue(aValue, aResult);
278 : }
279 0 : if (ParseImageAttribute(aAttribute, aValue, aResult)) {
280 0 : return true;
281 : }
282 : }
283 :
284 0 : return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
285 0 : aResult);
286 : }
287 :
288 : static void
289 0 : MapAttributesIntoRuleBase(const nsMappedAttributes *aAttributes,
290 : GenericSpecifiedValues* aData)
291 : {
292 0 : nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
293 0 : nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
294 0 : nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
295 0 : nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
296 0 : }
297 :
298 : static void
299 0 : MapAttributesIntoRuleExceptHidden(const nsMappedAttributes *aAttributes,
300 : GenericSpecifiedValues* aData)
301 : {
302 0 : MapAttributesIntoRuleBase(aAttributes, aData);
303 0 : nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aData);
304 0 : }
305 :
306 : void
307 0 : HTMLSharedObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
308 : GenericSpecifiedValues* aData)
309 : {
310 0 : MapAttributesIntoRuleBase(aAttributes, aData);
311 0 : nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
312 0 : }
313 :
314 : NS_IMETHODIMP_(bool)
315 0 : HTMLSharedObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
316 : {
317 : static const MappedAttributeEntry* const map[] = {
318 : sCommonAttributeMap,
319 : sImageMarginSizeAttributeMap,
320 : sImageBorderAttributeMap,
321 : sImageAlignAttributeMap,
322 : };
323 :
324 0 : return FindAttributeDependence(aAttribute, map);
325 : }
326 :
327 :
328 : nsMapRuleToAttributesFunc
329 0 : HTMLSharedObjectElement::GetAttributeMappingFunction() const
330 : {
331 0 : if (mNodeInfo->Equals(nsGkAtoms::embed)) {
332 0 : return &MapAttributesIntoRuleExceptHidden;
333 : }
334 :
335 0 : return &MapAttributesIntoRule;
336 : }
337 :
338 : void
339 0 : HTMLSharedObjectElement::StartObjectLoad(bool aNotify, bool aForceLoad)
340 : {
341 : // BindToTree can call us asynchronously, and we may be removed from the tree
342 : // in the interim
343 0 : if (!IsInComposedDoc() || !OwnerDoc()->IsActive() ||
344 0 : BlockEmbedOrObjectContentLoading()) {
345 0 : return;
346 : }
347 :
348 0 : LoadObject(aNotify, aForceLoad);
349 0 : SetIsNetworkCreated(false);
350 : }
351 :
352 : EventStates
353 0 : HTMLSharedObjectElement::IntrinsicState() const
354 : {
355 0 : return nsGenericHTMLElement::IntrinsicState() | ObjectState();
356 : }
357 :
358 : uint32_t
359 0 : HTMLSharedObjectElement::GetCapabilities() const
360 : {
361 0 : uint32_t capabilities = eSupportPlugins | eAllowPluginSkipChannel;
362 0 : if (mNodeInfo->Equals(nsGkAtoms::embed)) {
363 0 : capabilities |= eSupportImages | eSupportDocuments;
364 : }
365 :
366 0 : return capabilities;
367 : }
368 :
369 : void
370 0 : HTMLSharedObjectElement::DestroyContent()
371 : {
372 0 : nsObjectLoadingContent::DestroyContent();
373 0 : nsGenericHTMLElement::DestroyContent();
374 0 : }
375 :
376 : nsresult
377 0 : HTMLSharedObjectElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
378 : {
379 0 : nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
380 0 : NS_ENSURE_SUCCESS(rv, rv);
381 :
382 0 : if (aDest->OwnerDoc()->IsStaticDocument()) {
383 0 : CreateStaticClone(static_cast<HTMLSharedObjectElement*>(aDest));
384 : }
385 :
386 0 : return rv;
387 : }
388 :
389 : JSObject*
390 0 : HTMLSharedObjectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
391 : {
392 : JSObject* obj;
393 0 : if (mNodeInfo->Equals(nsGkAtoms::applet)) {
394 0 : obj = HTMLAppletElementBinding::Wrap(aCx, this, aGivenProto);
395 : } else {
396 0 : MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed));
397 0 : obj = HTMLEmbedElementBinding::Wrap(aCx, this, aGivenProto);
398 : }
399 0 : if (!obj) {
400 0 : return nullptr;
401 : }
402 0 : JS::Rooted<JSObject*> rootedObj(aCx, obj);
403 0 : SetupProtoChain(aCx, rootedObj);
404 0 : return rootedObj;
405 : }
406 :
407 : nsContentPolicyType
408 0 : HTMLSharedObjectElement::GetContentPolicyType() const
409 : {
410 0 : if (mNodeInfo->Equals(nsGkAtoms::applet)) {
411 : // We use TYPE_INTERNAL_OBJECT for applet too, since it is not exposed
412 : // through RequestContext yet.
413 0 : return nsIContentPolicy::TYPE_INTERNAL_OBJECT;
414 : } else {
415 0 : MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed));
416 0 : return nsIContentPolicy::TYPE_INTERNAL_EMBED;
417 : }
418 : }
419 :
420 : } // namespace dom
421 : } // namespace mozilla
|