1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "mozilla/Util.h"
39 :
40 : #include "nsIDOMHTMLImageElement.h"
41 : #include "nsIDOMEventTarget.h"
42 : #include "nsGenericHTMLElement.h"
43 : #include "nsImageLoadingContent.h"
44 : #include "nsGkAtoms.h"
45 : #include "nsStyleConsts.h"
46 : #include "nsPresContext.h"
47 : #include "nsMappedAttributes.h"
48 : #include "nsIJSNativeInitializer.h"
49 : #include "nsSize.h"
50 : #include "nsIDocument.h"
51 : #include "nsIDOMDocument.h"
52 : #include "nsIScriptContext.h"
53 : #include "nsIURL.h"
54 : #include "nsIIOService.h"
55 : #include "nsIServiceManager.h"
56 : #include "nsNetUtil.h"
57 : #include "nsContentUtils.h"
58 : #include "nsIFrame.h"
59 : #include "nsNodeInfoManager.h"
60 : #include "nsGUIEvent.h"
61 : #include "nsContentPolicyUtils.h"
62 : #include "nsIDOMWindow.h"
63 : #include "nsFocusManager.h"
64 :
65 : #include "imgIContainer.h"
66 : #include "imgILoader.h"
67 : #include "imgIRequest.h"
68 : #include "imgIDecoderObserver.h"
69 :
70 : #include "nsILoadGroup.h"
71 :
72 : #include "nsRuleData.h"
73 :
74 : #include "nsIJSContextStack.h"
75 : #include "nsIDOMHTMLMapElement.h"
76 : #include "nsEventDispatcher.h"
77 :
78 : #include "nsLayoutUtils.h"
79 :
80 : using namespace mozilla;
81 : using namespace mozilla::dom;
82 :
83 : // XXX nav attrs: suppress
84 :
85 : class nsHTMLImageElement : public nsGenericHTMLElement,
86 : public nsImageLoadingContent,
87 : public nsIDOMHTMLImageElement,
88 : public nsIJSNativeInitializer
89 : {
90 : public:
91 : nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo);
92 : virtual ~nsHTMLImageElement();
93 :
94 : // nsISupports
95 : NS_DECL_ISUPPORTS_INHERITED
96 :
97 : // nsIDOMNode
98 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
99 :
100 : // nsIDOMElement
101 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
102 :
103 : // nsIDOMHTMLElement
104 0 : NS_FORWARD_NSIDOMHTMLELEMENT_BASIC(nsGenericHTMLElement::)
105 0 : NS_SCRIPTABLE NS_IMETHOD Click() {
106 0 : return nsGenericHTMLElement::Click();
107 : }
108 0 : NS_SCRIPTABLE NS_IMETHOD GetTabIndex(PRInt32* aTabIndex) {
109 0 : return nsGenericHTMLElement::GetTabIndex(aTabIndex);
110 : }
111 0 : NS_SCRIPTABLE NS_IMETHOD SetTabIndex(PRInt32 aTabIndex) {
112 0 : return nsGenericHTMLElement::SetTabIndex(aTabIndex);
113 : }
114 0 : NS_SCRIPTABLE NS_IMETHOD Focus() {
115 0 : return nsGenericHTMLElement::Focus();
116 : }
117 : NS_SCRIPTABLE NS_IMETHOD GetDraggable(bool* aDraggable);
118 0 : NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) {
119 0 : return nsGenericHTMLElement::GetInnerHTML(aInnerHTML);
120 : }
121 0 : NS_SCRIPTABLE NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML) {
122 0 : return nsGenericHTMLElement::SetInnerHTML(aInnerHTML);
123 : }
124 :
125 : // nsIDOMHTMLImageElement
126 : NS_DECL_NSIDOMHTMLIMAGEELEMENT
127 :
128 : // override from nsImageLoadingContent
129 : CORSMode GetCORSMode();
130 :
131 : // nsIJSNativeInitializer
132 : NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
133 : JSObject* aObj, PRUint32 argc, jsval* argv);
134 :
135 : // nsIContent
136 : virtual bool ParseAttribute(PRInt32 aNamespaceID,
137 : nsIAtom* aAttribute,
138 : const nsAString& aValue,
139 : nsAttrValue& aResult);
140 : virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
141 : PRInt32 aModType) const;
142 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
143 : virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
144 :
145 : virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
146 :
147 : bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
148 :
149 : // SetAttr override. C++ is stupid, so have to override both
150 : // overloaded methods.
151 : nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
152 : const nsAString& aValue, bool aNotify)
153 : {
154 : return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
155 : }
156 : virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
157 : nsIAtom* aPrefix, const nsAString& aValue,
158 : bool aNotify);
159 : virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
160 : bool aNotify);
161 :
162 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
163 : nsIContent* aBindingParent,
164 : bool aCompileEventHandlers);
165 :
166 : virtual nsEventStates IntrinsicState() const;
167 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
168 :
169 : nsresult CopyInnerTo(nsGenericElement* aDest) const;
170 :
171 : void MaybeLoadImage();
172 : virtual nsXPCClassInfo* GetClassInfo();
173 : protected:
174 : nsSize GetWidthHeight();
175 : };
176 :
177 : nsGenericHTMLElement*
178 0 : NS_NewHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo,
179 : FromParser aFromParser)
180 : {
181 : /*
182 : * nsHTMLImageElement's will be created without a nsINodeInfo passed in
183 : * if someone says "var img = new Image();" in JavaScript, in a case like
184 : * that we request the nsINodeInfo from the document's nodeinfo list.
185 : */
186 0 : nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
187 0 : if (!nodeInfo) {
188 : nsCOMPtr<nsIDocument> doc =
189 0 : do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
190 0 : NS_ENSURE_TRUE(doc, nsnull);
191 :
192 : nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::img, nsnull,
193 : kNameSpaceID_XHTML,
194 0 : nsIDOMNode::ELEMENT_NODE);
195 0 : NS_ENSURE_TRUE(nodeInfo, nsnull);
196 : }
197 :
198 0 : return new nsHTMLImageElement(nodeInfo.forget());
199 : }
200 :
201 0 : nsHTMLImageElement::nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
202 0 : : nsGenericHTMLElement(aNodeInfo)
203 : {
204 : // We start out broken
205 0 : AddStatesSilently(NS_EVENT_STATE_BROKEN);
206 0 : }
207 :
208 0 : nsHTMLImageElement::~nsHTMLImageElement()
209 : {
210 0 : DestroyImageLoadingContent();
211 0 : }
212 :
213 :
214 0 : NS_IMPL_ADDREF_INHERITED(nsHTMLImageElement, nsGenericElement)
215 0 : NS_IMPL_RELEASE_INHERITED(nsHTMLImageElement, nsGenericElement)
216 :
217 :
218 0 : DOMCI_NODE_DATA(HTMLImageElement, nsHTMLImageElement)
219 :
220 : // QueryInterface implementation for nsHTMLImageElement
221 0 : NS_INTERFACE_TABLE_HEAD(nsHTMLImageElement)
222 0 : NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLImageElement,
223 : nsIDOMHTMLImageElement,
224 : nsIJSNativeInitializer,
225 : imgIDecoderObserver,
226 : nsIImageLoadingContent,
227 : imgIContainerObserver)
228 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLImageElement,
229 : nsGenericHTMLElement)
230 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLImageElement)
231 :
232 :
233 0 : NS_IMPL_ELEMENT_CLONE(nsHTMLImageElement)
234 :
235 :
236 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, Name, name)
237 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, Align, align)
238 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, Alt, alt)
239 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, Border, border)
240 0 : NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace)
241 0 : NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
242 0 : NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
243 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
244 0 : NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
245 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
246 0 : NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
247 :
248 : // crossorigin is not "limited to only known values" per spec, so it's
249 : // just a string attr purposes of the DOM crossOrigin property.
250 0 : NS_IMPL_STRING_ATTR(nsHTMLImageElement, CrossOrigin, crossorigin)
251 :
252 : NS_IMETHODIMP
253 0 : nsHTMLImageElement::GetDraggable(bool* aDraggable)
254 : {
255 : // images may be dragged unless the draggable attribute is false
256 : *aDraggable = !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
257 0 : nsGkAtoms::_false, eIgnoreCase);
258 0 : return NS_OK;
259 : }
260 :
261 : NS_IMETHODIMP
262 0 : nsHTMLImageElement::GetComplete(bool* aComplete)
263 : {
264 0 : NS_PRECONDITION(aComplete, "Null out param!");
265 0 : *aComplete = true;
266 :
267 0 : if (!mCurrentRequest) {
268 0 : return NS_OK;
269 : }
270 :
271 : PRUint32 status;
272 0 : mCurrentRequest->GetImageStatus(&status);
273 : *aComplete =
274 : (status &
275 0 : (imgIRequest::STATUS_LOAD_COMPLETE | imgIRequest::STATUS_ERROR)) != 0;
276 :
277 0 : return NS_OK;
278 : }
279 :
280 : nsSize
281 0 : nsHTMLImageElement::GetWidthHeight()
282 : {
283 0 : nsSize size(0,0);
284 :
285 0 : nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
286 :
287 0 : if (frame) {
288 0 : size = frame->GetContentRect().Size();
289 :
290 0 : size.width = nsPresContext::AppUnitsToIntCSSPixels(size.width);
291 0 : size.height = nsPresContext::AppUnitsToIntCSSPixels(size.height);
292 : } else {
293 : const nsAttrValue* value;
294 0 : nsCOMPtr<imgIContainer> image;
295 0 : if (mCurrentRequest) {
296 0 : mCurrentRequest->GetImage(getter_AddRefs(image));
297 : }
298 :
299 0 : if ((value = GetParsedAttr(nsGkAtoms::width)) &&
300 0 : value->Type() == nsAttrValue::eInteger) {
301 0 : size.width = value->GetIntegerValue();
302 0 : } else if (image) {
303 0 : image->GetWidth(&size.width);
304 : }
305 :
306 0 : if ((value = GetParsedAttr(nsGkAtoms::height)) &&
307 0 : value->Type() == nsAttrValue::eInteger) {
308 0 : size.height = value->GetIntegerValue();
309 0 : } else if (image) {
310 0 : image->GetHeight(&size.height);
311 : }
312 : }
313 :
314 0 : NS_ASSERTION(size.width >= 0, "negative width");
315 0 : NS_ASSERTION(size.height >= 0, "negative height");
316 : return size;
317 : }
318 :
319 : NS_IMETHODIMP
320 0 : nsHTMLImageElement::GetHeight(PRUint32* aHeight)
321 : {
322 0 : *aHeight = GetWidthHeight().height;
323 :
324 0 : return NS_OK;
325 : }
326 :
327 : NS_IMETHODIMP
328 0 : nsHTMLImageElement::SetHeight(PRUint32 aHeight)
329 : {
330 0 : nsAutoString val;
331 0 : val.AppendInt(aHeight);
332 :
333 : return nsGenericHTMLElement::SetAttr(kNameSpaceID_None, nsGkAtoms::height,
334 0 : val, true);
335 : }
336 :
337 : NS_IMETHODIMP
338 0 : nsHTMLImageElement::GetWidth(PRUint32* aWidth)
339 : {
340 0 : *aWidth = GetWidthHeight().width;
341 :
342 0 : return NS_OK;
343 : }
344 :
345 : NS_IMETHODIMP
346 0 : nsHTMLImageElement::SetWidth(PRUint32 aWidth)
347 : {
348 0 : nsAutoString val;
349 0 : val.AppendInt(aWidth);
350 :
351 : return nsGenericHTMLElement::SetAttr(kNameSpaceID_None, nsGkAtoms::width,
352 0 : val, true);
353 : }
354 :
355 : bool
356 0 : nsHTMLImageElement::ParseAttribute(PRInt32 aNamespaceID,
357 : nsIAtom* aAttribute,
358 : const nsAString& aValue,
359 : nsAttrValue& aResult)
360 : {
361 0 : if (aNamespaceID == kNameSpaceID_None) {
362 0 : if (aAttribute == nsGkAtoms::align) {
363 0 : return ParseAlignValue(aValue, aResult);
364 : }
365 0 : if (aAttribute == nsGkAtoms::crossorigin) {
366 0 : ParseCORSValue(aValue, aResult);
367 0 : return true;
368 : }
369 0 : if (ParseImageAttribute(aAttribute, aValue, aResult)) {
370 0 : return true;
371 : }
372 : }
373 :
374 : return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
375 0 : aResult);
376 : }
377 :
378 : static void
379 0 : MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
380 : nsRuleData* aData)
381 : {
382 0 : nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
383 0 : nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
384 0 : nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
385 0 : nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
386 0 : nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
387 0 : }
388 :
389 : nsChangeHint
390 0 : nsHTMLImageElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
391 : PRInt32 aModType) const
392 : {
393 : nsChangeHint retval =
394 0 : nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
395 0 : if (aAttribute == nsGkAtoms::usemap ||
396 : aAttribute == nsGkAtoms::ismap) {
397 0 : NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
398 : }
399 0 : return retval;
400 : }
401 :
402 : NS_IMETHODIMP_(bool)
403 0 : nsHTMLImageElement::IsAttributeMapped(const nsIAtom* aAttribute) const
404 : {
405 : static const MappedAttributeEntry* const map[] = {
406 : sCommonAttributeMap,
407 : sImageMarginSizeAttributeMap,
408 : sImageBorderAttributeMap,
409 : sImageAlignAttributeMap
410 : };
411 :
412 0 : return FindAttributeDependence(aAttribute, map);
413 : }
414 :
415 :
416 : nsMapRuleToAttributesFunc
417 0 : nsHTMLImageElement::GetAttributeMappingFunction() const
418 : {
419 0 : return &MapAttributesIntoRule;
420 : }
421 :
422 :
423 : nsresult
424 0 : nsHTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
425 : {
426 : // If we are a map and get a mouse click, don't let it be handled by
427 : // the Generic Element as this could cause a click event to fire
428 : // twice, once by the image frame for the map and once by the Anchor
429 : // element. (bug 39723)
430 0 : if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
431 : aVisitor.mEvent->message == NS_MOUSE_CLICK &&
432 : static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
433 : nsMouseEvent::eLeftButton) {
434 0 : bool isMap = false;
435 0 : GetIsMap(&isMap);
436 0 : if (isMap) {
437 0 : aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
438 : }
439 : }
440 0 : return nsGenericHTMLElement::PreHandleEvent(aVisitor);
441 : }
442 :
443 : bool
444 0 : nsHTMLImageElement::IsHTMLFocusable(bool aWithMouse,
445 : bool *aIsFocusable, PRInt32 *aTabIndex)
446 : {
447 : PRInt32 tabIndex;
448 0 : GetTabIndex(&tabIndex);
449 :
450 0 : if (IsInDoc()) {
451 0 : nsAutoString usemap;
452 0 : GetUseMap(usemap);
453 : // XXXbz which document should this be using? sXBL/XBL2 issue! I
454 : // think that OwnerDoc() is right, since we don't want to
455 : // assume stuff about the document we're bound to.
456 0 : if (OwnerDoc()->FindImageMap(usemap)) {
457 0 : if (aTabIndex) {
458 : // Use tab index on individual map areas
459 0 : *aTabIndex = (sTabFocusModel & eTabFocus_linksMask)? 0 : -1;
460 : }
461 : // Image map is not focusable itself, but flag as tabbable
462 : // so that image map areas get walked into.
463 0 : *aIsFocusable = false;
464 :
465 0 : return false;
466 : }
467 : }
468 :
469 0 : if (aTabIndex) {
470 : // Can be in tab order if tabindex >=0 and form controls are tabbable.
471 0 : *aTabIndex = (sTabFocusModel & eTabFocus_formElementsMask)? tabIndex : -1;
472 : }
473 :
474 : *aIsFocusable =
475 : #ifdef XP_MACOSX
476 : (!aWithMouse || nsFocusManager::sMouseFocusesFormControl) &&
477 : #endif
478 0 : (tabIndex >= 0 || HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex));
479 :
480 0 : return false;
481 : }
482 :
483 : nsresult
484 0 : nsHTMLImageElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
485 : nsIAtom* aPrefix, const nsAString& aValue,
486 : bool aNotify)
487 : {
488 : // If we plan to call LoadImage, we want to do it first so that the
489 : // image load kicks off _before_ the reflow triggered by the SetAttr. But if
490 : // aNotify is false, we are coming from the parser or some such place; we'll
491 : // get bound after all the attributes have been set, so we'll do the
492 : // image load from BindToTree. Skip the LoadImage call in that case.
493 0 : if (aNotify &&
494 : aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
495 :
496 : // Prevent setting image.src by exiting early
497 0 : if (nsContentUtils::IsImageSrcSetDisabled()) {
498 0 : return NS_OK;
499 : }
500 :
501 : // A hack to get animations to reset. See bug 594771.
502 0 : mNewRequestsWillNeedAnimationReset = true;
503 :
504 : // Force image loading here, so that we'll try to load the image from
505 : // network if it's set to be not cacheable... If we change things so that
506 : // the state gets in nsGenericElement's attr-setting happen around this
507 : // LoadImage call, we could start passing false instead of aNotify
508 : // here.
509 0 : LoadImage(aValue, true, aNotify);
510 :
511 0 : mNewRequestsWillNeedAnimationReset = false;
512 : }
513 :
514 : return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
515 0 : aNotify);
516 : }
517 :
518 : nsresult
519 0 : nsHTMLImageElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
520 : bool aNotify)
521 : {
522 0 : if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::src) {
523 0 : CancelImageRequests(aNotify);
524 : }
525 :
526 0 : return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
527 : }
528 :
529 : nsresult
530 0 : nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
531 : nsIContent* aBindingParent,
532 : bool aCompileEventHandlers)
533 : {
534 : nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
535 : aBindingParent,
536 0 : aCompileEventHandlers);
537 0 : NS_ENSURE_SUCCESS(rv, rv);
538 :
539 0 : if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
540 : // FIXME: Bug 660963 it would be nice if we could just have
541 : // ClearBrokenState update our state and do it fast...
542 0 : ClearBrokenState();
543 0 : RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
544 : // If loading is temporarily disabled, don't even launch MaybeLoadImage.
545 : // Otherwise MaybeLoadImage may run later when someone has reenabled
546 : // loading.
547 0 : if (LoadingEnabled()) {
548 : nsContentUtils::AddScriptRunner(
549 0 : NS_NewRunnableMethod(this, &nsHTMLImageElement::MaybeLoadImage));
550 : }
551 : }
552 :
553 0 : return rv;
554 : }
555 :
556 : void
557 0 : nsHTMLImageElement::MaybeLoadImage()
558 : {
559 : // Our base URI may have changed; claim that our URI changed, and the
560 : // nsImageLoadingContent will decide whether a new image load is warranted.
561 : // Note, check LoadingEnabled() after LoadImage call.
562 0 : nsAutoString uri;
563 0 : if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) &&
564 0 : (NS_FAILED(LoadImage(uri, false, true)) ||
565 0 : !LoadingEnabled())) {
566 0 : CancelImageRequests(true);
567 : }
568 0 : }
569 :
570 : nsEventStates
571 0 : nsHTMLImageElement::IntrinsicState() const
572 : {
573 : return nsGenericHTMLElement::IntrinsicState() |
574 0 : nsImageLoadingContent::ImageState();
575 : }
576 :
577 : NS_IMETHODIMP
578 0 : nsHTMLImageElement::Initialize(nsISupports* aOwner, JSContext* aContext,
579 : JSObject *aObj, PRUint32 argc, jsval *argv)
580 : {
581 0 : if (argc <= 0) {
582 : // Nothing to do here if we don't get any arguments.
583 :
584 0 : return NS_OK;
585 : }
586 :
587 : // The first (optional) argument is the width of the image
588 : uint32_t width;
589 0 : JSBool ret = JS_ValueToECMAUint32(aContext, argv[0], &width);
590 0 : NS_ENSURE_TRUE(ret, NS_ERROR_INVALID_ARG);
591 :
592 0 : nsresult rv = SetIntAttr(nsGkAtoms::width, static_cast<PRInt32>(width));
593 :
594 0 : if (NS_SUCCEEDED(rv) && (argc > 1)) {
595 : // The second (optional) argument is the height of the image
596 : uint32_t height;
597 0 : ret = JS_ValueToECMAUint32(aContext, argv[1], &height);
598 0 : NS_ENSURE_TRUE(ret, NS_ERROR_INVALID_ARG);
599 :
600 0 : rv = SetIntAttr(nsGkAtoms::height, static_cast<PRInt32>(height));
601 : }
602 :
603 0 : return rv;
604 : }
605 :
606 : NS_IMETHODIMP
607 0 : nsHTMLImageElement::GetNaturalHeight(PRUint32* aNaturalHeight)
608 : {
609 0 : NS_ENSURE_ARG_POINTER(aNaturalHeight);
610 :
611 0 : *aNaturalHeight = 0;
612 :
613 0 : if (!mCurrentRequest) {
614 0 : return NS_OK;
615 : }
616 :
617 0 : nsCOMPtr<imgIContainer> image;
618 0 : mCurrentRequest->GetImage(getter_AddRefs(image));
619 0 : if (!image) {
620 0 : return NS_OK;
621 : }
622 :
623 : PRInt32 height;
624 0 : if (NS_SUCCEEDED(image->GetHeight(&height))) {
625 0 : *aNaturalHeight = height;
626 : }
627 0 : return NS_OK;
628 : }
629 :
630 : NS_IMETHODIMP
631 0 : nsHTMLImageElement::GetNaturalWidth(PRUint32* aNaturalWidth)
632 : {
633 0 : NS_ENSURE_ARG_POINTER(aNaturalWidth);
634 :
635 0 : *aNaturalWidth = 0;
636 :
637 0 : if (!mCurrentRequest) {
638 0 : return NS_OK;
639 : }
640 :
641 0 : nsCOMPtr<imgIContainer> image;
642 0 : mCurrentRequest->GetImage(getter_AddRefs(image));
643 0 : if (!image) {
644 0 : return NS_OK;
645 : }
646 :
647 : PRInt32 width;
648 0 : if (NS_SUCCEEDED(image->GetWidth(&width))) {
649 0 : *aNaturalWidth = width;
650 : }
651 0 : return NS_OK;
652 : }
653 :
654 : nsresult
655 0 : nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
656 : {
657 0 : if (aDest->OwnerDoc()->IsStaticDocument()) {
658 0 : CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest));
659 : }
660 0 : return nsGenericHTMLElement::CopyInnerTo(aDest);
661 : }
662 :
663 : CORSMode
664 0 : nsHTMLImageElement::GetCORSMode()
665 : {
666 0 : return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
667 : }
|