OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights |
5 * reserved. | 5 * reserved. |
6 * Copyright (C) 2010 Google Inc. All rights reserved. | 6 * Copyright (C) 2010 Google Inc. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "core/html/HTMLImageElement.h" | 24 #include "core/html/HTMLImageElement.h" |
25 | 25 |
26 #include "bindings/core/v8/ScriptEventListener.h" | 26 #include "bindings/core/v8/ScriptEventListener.h" |
27 #include "core/CSSPropertyNames.h" | 27 #include "core/CSSPropertyNames.h" |
28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
29 #include "core/MediaTypeNames.h" | 29 #include "core/MediaTypeNames.h" |
30 #include "core/css/MediaQueryMatcher.h" | 30 #include "core/css/MediaQueryMatcher.h" |
31 #include "core/css/MediaValuesDynamic.h" | 31 #include "core/css/MediaValuesDynamic.h" |
32 #include "core/css/parser/SizesAttributeParser.h" | 32 #include "core/css/parser/SizesAttributeParser.h" |
33 #include "core/dom/Attribute.h" | 33 #include "core/dom/Attribute.h" |
| 34 #include "core/dom/DOMException.h" |
34 #include "core/dom/NodeTraversal.h" | 35 #include "core/dom/NodeTraversal.h" |
35 #include "core/dom/shadow/ShadowRoot.h" | 36 #include "core/dom/shadow/ShadowRoot.h" |
36 #include "core/frame/Deprecation.h" | 37 #include "core/frame/Deprecation.h" |
37 #include "core/frame/ImageBitmap.h" | 38 #include "core/frame/ImageBitmap.h" |
38 #include "core/frame/LocalDOMWindow.h" | 39 #include "core/frame/LocalDOMWindow.h" |
39 #include "core/html/FormAssociated.h" | 40 #include "core/html/FormAssociated.h" |
40 #include "core/html/HTMLAnchorElement.h" | 41 #include "core/html/HTMLAnchorElement.h" |
41 #include "core/html/HTMLCanvasElement.h" | 42 #include "core/html/HTMLCanvasElement.h" |
42 #include "core/html/HTMLFormElement.h" | 43 #include "core/html/HTMLFormElement.h" |
43 #include "core/html/HTMLImageFallbackHelper.h" | 44 #include "core/html/HTMLImageFallbackHelper.h" |
44 #include "core/html/HTMLPictureElement.h" | 45 #include "core/html/HTMLPictureElement.h" |
45 #include "core/html/HTMLSourceElement.h" | 46 #include "core/html/HTMLSourceElement.h" |
46 #include "core/html/parser/HTMLParserIdioms.h" | 47 #include "core/html/parser/HTMLParserIdioms.h" |
47 #include "core/html/parser/HTMLSrcsetParser.h" | 48 #include "core/html/parser/HTMLSrcsetParser.h" |
48 #include "core/imagebitmap/ImageBitmapOptions.h" | 49 #include "core/imagebitmap/ImageBitmapOptions.h" |
49 #include "core/inspector/ConsoleMessage.h" | 50 #include "core/inspector/ConsoleMessage.h" |
50 #include "core/layout/LayoutBlockFlow.h" | 51 #include "core/layout/LayoutBlockFlow.h" |
51 #include "core/layout/LayoutImage.h" | 52 #include "core/layout/LayoutImage.h" |
52 #include "core/layout/api/LayoutImageItem.h" | 53 #include "core/layout/api/LayoutImageItem.h" |
53 #include "core/loader/resource/ImageResourceContent.h" | 54 #include "core/loader/resource/ImageResourceContent.h" |
| 55 #include "core/page/ChromeClient.h" |
54 #include "core/page/Page.h" | 56 #include "core/page/Page.h" |
55 #include "core/style/ContentData.h" | 57 #include "core/style/ContentData.h" |
56 #include "core/svg/graphics/SVGImageForContainer.h" | 58 #include "core/svg/graphics/SVGImageForContainer.h" |
57 #include "platform/EventDispatchForbiddenScope.h" | 59 #include "platform/EventDispatchForbiddenScope.h" |
58 #include "platform/network/mime/ContentType.h" | 60 #include "platform/network/mime/ContentType.h" |
59 #include "platform/network/mime/MIMETypeRegistry.h" | 61 #include "platform/network/mime/MIMETypeRegistry.h" |
60 #include "platform/weborigin/SecurityPolicy.h" | 62 #include "platform/weborigin/SecurityPolicy.h" |
61 | 63 |
62 namespace blink { | 64 namespace blink { |
63 | 65 |
(...skipping 21 matching lines...) Expand all Loading... |
85 : element_(element) {} | 87 : element_(element) {} |
86 Member<HTMLImageElement> element_; | 88 Member<HTMLImageElement> element_; |
87 }; | 89 }; |
88 | 90 |
89 HTMLImageElement::HTMLImageElement(Document& document, bool created_by_parser) | 91 HTMLImageElement::HTMLImageElement(Document& document, bool created_by_parser) |
90 : HTMLElement(imgTag, document), | 92 : HTMLElement(imgTag, document), |
91 image_loader_(HTMLImageLoader::Create(this)), | 93 image_loader_(HTMLImageLoader::Create(this)), |
92 image_device_pixel_ratio_(1.0f), | 94 image_device_pixel_ratio_(1.0f), |
93 source_(nullptr), | 95 source_(nullptr), |
94 layout_disposition_(LayoutDisposition::kPrimaryContent), | 96 layout_disposition_(LayoutDisposition::kPrimaryContent), |
| 97 decode_sequence_id_(0), |
95 form_was_set_by_parser_(false), | 98 form_was_set_by_parser_(false), |
96 element_created_by_parser_(created_by_parser), | 99 element_created_by_parser_(created_by_parser), |
97 is_fallback_image_(false), | 100 is_fallback_image_(false), |
98 referrer_policy_(kReferrerPolicyDefault) { | 101 referrer_policy_(kReferrerPolicyDefault) { |
99 SetHasCustomStyleCallbacks(); | 102 SetHasCustomStyleCallbacks(); |
100 } | 103 } |
101 | 104 |
102 HTMLImageElement* HTMLImageElement::Create(Document& document) { | 105 HTMLImageElement* HTMLImageElement::Create(Document& document) { |
103 return new HTMLImageElement(document); | 106 return new HTMLImageElement(document); |
104 } | 107 } |
105 | 108 |
106 HTMLImageElement* HTMLImageElement::Create(Document& document, | 109 HTMLImageElement* HTMLImageElement::Create(Document& document, |
107 bool created_by_parser) { | 110 bool created_by_parser) { |
108 return new HTMLImageElement(document, created_by_parser); | 111 return new HTMLImageElement(document, created_by_parser); |
109 } | 112 } |
110 | 113 |
111 HTMLImageElement::~HTMLImageElement() {} | 114 HTMLImageElement::~HTMLImageElement() {} |
112 | 115 |
113 DEFINE_TRACE(HTMLImageElement) { | 116 DEFINE_TRACE(HTMLImageElement) { |
114 visitor->Trace(image_loader_); | 117 visitor->Trace(image_loader_); |
115 visitor->Trace(listener_); | 118 visitor->Trace(listener_); |
116 visitor->Trace(form_); | 119 visitor->Trace(form_); |
117 visitor->Trace(source_); | 120 visitor->Trace(source_); |
| 121 visitor->Trace(decode_promise_resolvers_); |
118 HTMLElement::Trace(visitor); | 122 HTMLElement::Trace(visitor); |
119 } | 123 } |
120 | 124 |
121 void HTMLImageElement::NotifyViewportChanged() { | 125 void HTMLImageElement::NotifyViewportChanged() { |
122 // Re-selecting the source URL in order to pick a more fitting resource | 126 // Re-selecting the source URL in order to pick a more fitting resource |
123 // And update the image's intrinsic dimensions when the viewport changes. | 127 // And update the image's intrinsic dimensions when the viewport changes. |
124 // Picking of a better fitting resource is UA dependant, not spec required. | 128 // Picking of a better fitting resource is UA dependant, not spec required. |
125 SelectSourceURL(ImageLoader::kUpdateSizeChanged); | 129 SelectSourceURL(ImageLoader::kUpdateSizeChanged); |
126 } | 130 } |
127 | 131 |
| 132 void HTMLImageElement::RequestDecode() { |
| 133 DCHECK(!decode_promise_resolvers_.IsEmpty()); |
| 134 LocalFrame* frame = GetDocument().GetFrame(); |
| 135 // If we don't have the image, or the document doesn't have a frame, then |
| 136 // reject the decode, since we can't plumb the request to the correct place. |
| 137 if (!GetImageLoader().GetImage() || |
| 138 !GetImageLoader().GetImage()->GetImage() || !frame) { |
| 139 DecodeRequestFinished(decode_sequence_id_, false); |
| 140 return; |
| 141 } |
| 142 Image* image = GetImageLoader().GetImage()->GetImage(); |
| 143 frame->GetChromeClient().RequestDecode( |
| 144 frame, image->ImageForCurrentFrame(), |
| 145 WTF::Bind(&HTMLImageElement::DecodeRequestFinished, |
| 146 WrapWeakPersistent(this), decode_sequence_id_)); |
| 147 } |
| 148 |
| 149 void HTMLImageElement::DecodeRequestFinished(uint32_t sequence_id, |
| 150 bool success) { |
| 151 // If the sequence id attached with this callback doesn't match our current |
| 152 // sequence id, then the source of the image has changed. In other words, the |
| 153 // decode resolved/rejected by this callback was already rejected. Since we |
| 154 // could have had a new decode request, we have to make sure not to |
| 155 // resolve/reject those using the stale callback. |
| 156 if (sequence_id != decode_sequence_id_) |
| 157 return; |
| 158 |
| 159 if (success) { |
| 160 for (auto& resolver : decode_promise_resolvers_) |
| 161 resolver->Resolve(); |
| 162 } else { |
| 163 for (auto& resolver : decode_promise_resolvers_) { |
| 164 resolver->Reject(DOMException::Create( |
| 165 kEncodingError, "The source image cannot be decoded")); |
| 166 } |
| 167 } |
| 168 decode_promise_resolvers_.clear(); |
| 169 } |
| 170 |
128 HTMLImageElement* HTMLImageElement::CreateForJSConstructor(Document& document) { | 171 HTMLImageElement* HTMLImageElement::CreateForJSConstructor(Document& document) { |
129 HTMLImageElement* image = new HTMLImageElement(document); | 172 HTMLImageElement* image = new HTMLImageElement(document); |
130 image->element_created_by_parser_ = false; | 173 image->element_created_by_parser_ = false; |
131 return image; | 174 return image; |
132 } | 175 } |
133 | 176 |
134 HTMLImageElement* HTMLImageElement::CreateForJSConstructor(Document& document, | 177 HTMLImageElement* HTMLImageElement::CreateForJSConstructor(Document& document, |
135 unsigned width) { | 178 unsigned width) { |
136 HTMLImageElement* image = new HTMLImageElement(document); | 179 HTMLImageElement* image = new HTMLImageElement(document); |
137 image->setWidth(width); | 180 image->setWidth(width); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 const QualifiedName& name = params.name; | 296 const QualifiedName& name = params.name; |
254 if (name == altAttr || name == titleAttr) { | 297 if (name == altAttr || name == titleAttr) { |
255 if (UserAgentShadowRoot()) { | 298 if (UserAgentShadowRoot()) { |
256 Element* text = UserAgentShadowRoot()->getElementById("alttext"); | 299 Element* text = UserAgentShadowRoot()->getElementById("alttext"); |
257 String value = AltText(); | 300 String value = AltText(); |
258 if (text && text->textContent() != params.new_value) | 301 if (text && text->textContent() != params.new_value) |
259 text->setTextContent(AltText()); | 302 text->setTextContent(AltText()); |
260 } | 303 } |
261 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { | 304 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { |
262 SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError); | 305 SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError); |
| 306 // Ensure to fail any pending decodes on possible source changes. |
| 307 if (!decode_promise_resolvers_.IsEmpty() && |
| 308 params.old_value != params.new_value) { |
| 309 DecodeRequestFinished(decode_sequence_id_, false); |
| 310 // Increment the sequence id so that any in flight decode completion tasks |
| 311 // will not trigger promise resolution for new decode requests. |
| 312 ++decode_sequence_id_; |
| 313 } |
263 } else if (name == usemapAttr) { | 314 } else if (name == usemapAttr) { |
264 SetIsLink(!params.new_value.IsNull()); | 315 SetIsLink(!params.new_value.IsNull()); |
265 } else if (name == referrerpolicyAttr) { | 316 } else if (name == referrerpolicyAttr) { |
266 referrer_policy_ = kReferrerPolicyDefault; | 317 referrer_policy_ = kReferrerPolicyDefault; |
267 if (!params.new_value.IsNull()) { | 318 if (!params.new_value.IsNull()) { |
268 SecurityPolicy::ReferrerPolicyFromString( | 319 SecurityPolicy::ReferrerPolicyFromString( |
269 params.new_value, kSupportReferrerPolicyLegacyKeywords, | 320 params.new_value, kSupportReferrerPolicyLegacyKeywords, |
270 &referrer_policy_); | 321 &referrer_policy_); |
271 UseCounter::Count(GetDocument(), | 322 UseCounter::Count(GetDocument(), |
272 UseCounter::kHTMLImageElementReferrerPolicyAttribute); | 323 UseCounter::kHTMLImageElementReferrerPolicyAttribute); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); | 641 GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); |
591 LayoutObject* r = GetLayoutObject(); | 642 LayoutObject* r = GetLayoutObject(); |
592 if (!r) | 643 if (!r) |
593 return 0; | 644 return 0; |
594 | 645 |
595 // FIXME: This doesn't work correctly with transforms. | 646 // FIXME: This doesn't work correctly with transforms. |
596 FloatPoint abs_pos = r->LocalToAbsolute(); | 647 FloatPoint abs_pos = r->LocalToAbsolute(); |
597 return abs_pos.Y(); | 648 return abs_pos.Y(); |
598 } | 649 } |
599 | 650 |
| 651 ScriptPromise HTMLImageElement::decode(ScriptState* script_state, |
| 652 ExceptionState& exception_state) { |
| 653 if (!script_state->ContextIsValid()) { |
| 654 exception_state.ThrowDOMException(kEncodingError, |
| 655 "The source image cannot be decoded"); |
| 656 return ScriptPromise(); |
| 657 } |
| 658 exception_state.ClearException(); |
| 659 decode_promise_resolvers_.push_back( |
| 660 ScriptPromiseResolver::Create(script_state)); |
| 661 ScriptPromise promise = decode_promise_resolvers_.back()->Promise(); |
| 662 if (complete()) |
| 663 RequestDecode(); |
| 664 return promise; |
| 665 } |
| 666 |
600 bool HTMLImageElement::complete() const { | 667 bool HTMLImageElement::complete() const { |
601 return GetImageLoader().ImageComplete(); | 668 return GetImageLoader().ImageComplete(); |
602 } | 669 } |
603 | 670 |
604 void HTMLImageElement::DidMoveToNewDocument(Document& old_document) { | 671 void HTMLImageElement::DidMoveToNewDocument(Document& old_document) { |
605 SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError); | 672 SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError); |
606 GetImageLoader().ElementDidMoveToNewDocument(); | 673 GetImageLoader().ElementDidMoveToNewDocument(); |
607 HTMLElement::DidMoveToNewDocument(old_document); | 674 HTMLElement::DidMoveToNewDocument(old_document); |
608 } | 675 } |
609 | 676 |
610 bool HTMLImageElement::IsServerMap() const { | 677 bool HTMLImageElement::IsServerMap() const { |
611 if (!FastHasAttribute(ismapAttr)) | 678 if (!FastHasAttribute(ismapAttr)) |
612 return false; | 679 return false; |
613 | 680 |
614 const AtomicString& usemap = FastGetAttribute(usemapAttr); | 681 const AtomicString& usemap = FastGetAttribute(usemapAttr); |
615 | 682 |
616 // If the usemap attribute starts with '#', it refers to a map element in the | 683 // If the usemap attribute starts with '#', it refers to a map element in |
617 // document. | 684 // the document. |
618 if (usemap[0] == '#') | 685 if (usemap[0] == '#') |
619 return false; | 686 return false; |
620 | 687 |
621 return GetDocument() | 688 return GetDocument() |
622 .CompleteURL(StripLeadingAndTrailingHTMLSpaces(usemap)) | 689 .CompleteURL(StripLeadingAndTrailingHTMLSpaces(usemap)) |
623 .IsEmpty(); | 690 .IsEmpty(); |
624 } | 691 } |
625 | 692 |
626 Image* HTMLImageElement::ImageContents() { | 693 Image* HTMLImageElement::ImageContents() { |
627 if (!GetImageLoader().ImageComplete()) | 694 if (!GetImageLoader().ImageComplete()) |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 return OriginalStyleForLayoutObject(); | 872 return OriginalStyleForLayoutObject(); |
806 case LayoutDisposition::kFallbackContent: | 873 case LayoutDisposition::kFallbackContent: |
807 return HTMLImageFallbackHelper::CustomStyleForAltText( | 874 return HTMLImageFallbackHelper::CustomStyleForAltText( |
808 *this, ComputedStyle::Clone(*OriginalStyleForLayoutObject())); | 875 *this, ComputedStyle::Clone(*OriginalStyleForLayoutObject())); |
809 default: | 876 default: |
810 NOTREACHED(); | 877 NOTREACHED(); |
811 return nullptr; | 878 return nullptr; |
812 } | 879 } |
813 } | 880 } |
814 | 881 |
| 882 void HTMLImageElement::ImageNotifyFinished(bool success) { |
| 883 if (decode_promise_resolvers_.IsEmpty()) |
| 884 return; |
| 885 if (success) |
| 886 RequestDecode(); |
| 887 else |
| 888 DecodeRequestFinished(decode_sequence_id_, false); |
| 889 } |
| 890 |
815 void HTMLImageElement::AssociateWith(HTMLFormElement* form) { | 891 void HTMLImageElement::AssociateWith(HTMLFormElement* form) { |
816 if (form && form->isConnected()) { | 892 if (form && form->isConnected()) { |
817 form_ = form; | 893 form_ = form; |
818 form_was_set_by_parser_ = true; | 894 form_was_set_by_parser_ = true; |
819 form_->Associate(*this); | 895 form_->Associate(*this); |
820 form_->DidAssociateByParser(); | 896 form_->DidAssociateByParser(); |
821 } | 897 } |
822 }; | 898 }; |
823 | 899 |
824 FloatSize HTMLImageElement::SourceDefaultObjectSize() { | 900 FloatSize HTMLImageElement::SourceDefaultObjectSize() { |
825 return FloatSize(width(), height()); | 901 return FloatSize(width(), height()); |
826 } | 902 } |
827 | 903 |
828 } // namespace blink | 904 } // namespace blink |
OLD | NEW |