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, 2009, 2010 Apple Inc. All rights | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights |
5 * reserved. | 5 * reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 BypassMainWorldBehavior should_bypass_main_world_csp_; | 149 BypassMainWorldBehavior should_bypass_main_world_csp_; |
150 UpdateFromElementBehavior update_behavior_; | 150 UpdateFromElementBehavior update_behavior_; |
151 RefPtr<ScriptState> script_state_; | 151 RefPtr<ScriptState> script_state_; |
152 WeakPtrFactory<Task> weak_factory_; | 152 WeakPtrFactory<Task> weak_factory_; |
153 ReferrerPolicy referrer_policy_; | 153 ReferrerPolicy referrer_policy_; |
154 KURL request_url_; | 154 KURL request_url_; |
155 }; | 155 }; |
156 | 156 |
157 ImageLoader::ImageLoader(Element* element) | 157 ImageLoader::ImageLoader(Element* element) |
158 : element_(element), | 158 : element_(element), |
159 deref_element_timer_(this, &ImageLoader::TimerFired), | |
160 has_pending_load_event_(false), | 159 has_pending_load_event_(false), |
161 has_pending_error_event_(false), | 160 has_pending_error_event_(false), |
162 image_complete_(true), | 161 image_complete_(true), |
163 loading_image_document_(false), | 162 loading_image_document_(false), |
164 element_is_protected_(false), | |
165 suppress_error_events_(false) { | 163 suppress_error_events_(false) { |
166 RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this; | 164 RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this; |
167 } | 165 } |
168 | 166 |
169 ImageLoader::~ImageLoader() {} | 167 ImageLoader::~ImageLoader() {} |
170 | 168 |
171 void ImageLoader::Dispose() { | 169 void ImageLoader::Dispose() { |
172 RESOURCE_LOADING_DVLOG(1) | 170 RESOURCE_LOADING_DVLOG(1) |
173 << "~ImageLoader " << this | 171 << "~ImageLoader " << this |
174 << "; has_pending_load_event_=" << has_pending_load_event_ | 172 << "; has_pending_load_event_=" << has_pending_load_event_ |
175 << ", has_pending_error_event_=" << has_pending_error_event_; | 173 << ", has_pending_error_event_=" << has_pending_error_event_; |
176 | 174 |
177 if (image_) { | 175 if (image_) { |
178 image_->RemoveObserver(this); | 176 image_->RemoveObserver(this); |
179 image_ = nullptr; | 177 image_ = nullptr; |
180 delay_until_image_notify_finished_ = nullptr; | 178 delay_until_image_notify_finished_ = nullptr; |
181 } | 179 } |
182 } | 180 } |
183 | 181 |
184 DEFINE_TRACE(ImageLoader) { | 182 DEFINE_TRACE(ImageLoader) { |
185 visitor->Trace(image_); | 183 visitor->Trace(image_); |
186 visitor->Trace(image_resource_for_image_document_); | 184 visitor->Trace(image_resource_for_image_document_); |
187 visitor->Trace(element_); | 185 visitor->Trace(element_); |
188 } | 186 } |
189 | 187 |
190 void ImageLoader::SetImageForTest(ImageResourceContent* new_image) { | 188 void ImageLoader::SetImageForTest(ImageResourceContent* new_image) { |
191 DCHECK(new_image); | 189 DCHECK(new_image); |
192 SetImageWithoutConsideringPendingLoadEvent(new_image); | 190 SetImageWithoutConsideringPendingLoadEvent(new_image); |
193 | |
194 // Only consider updating the protection ref-count of the Element immediately | |
195 // before returning from this function as doing so might result in the | |
196 // destruction of this ImageLoader. | |
197 UpdatedHasPendingEvent(); | |
198 } | 191 } |
199 | 192 |
200 void ImageLoader::ClearImage() { | 193 void ImageLoader::ClearImage() { |
201 SetImageWithoutConsideringPendingLoadEvent(nullptr); | 194 SetImageWithoutConsideringPendingLoadEvent(nullptr); |
202 | |
203 // Only consider updating the protection ref-count of the Element immediately | |
204 // before returning from this function as doing so might result in the | |
205 // destruction of this ImageLoader. | |
206 UpdatedHasPendingEvent(); | |
207 } | 195 } |
208 | 196 |
209 void ImageLoader::SetImageForImageDocument(ImageResource* new_image_resource) { | 197 void ImageLoader::SetImageForImageDocument(ImageResource* new_image_resource) { |
210 DCHECK(loading_image_document_); | 198 DCHECK(loading_image_document_); |
211 DCHECK(new_image_resource); | 199 DCHECK(new_image_resource); |
212 DCHECK(new_image_resource->GetContent()); | 200 DCHECK(new_image_resource->GetContent()); |
213 | 201 |
214 image_resource_for_image_document_ = new_image_resource; | 202 image_resource_for_image_document_ = new_image_resource; |
215 SetImageWithoutConsideringPendingLoadEvent(new_image_resource->GetContent()); | 203 SetImageWithoutConsideringPendingLoadEvent(new_image_resource->GetContent()); |
216 | 204 |
217 // |image_complete_| is always true for ImageDocument loading, while the | 205 // |image_complete_| is always true for ImageDocument loading, while the |
218 // loading is just started. | 206 // loading is just started. |
219 // TODO(hiroshige): clean up the behavior of flags. https://crbug.com/719759 | 207 // TODO(hiroshige): clean up the behavior of flags. https://crbug.com/719759 |
220 image_complete_ = true; | 208 image_complete_ = true; |
221 | |
222 // Only consider updating the protection ref-count of the Element immediately | |
223 // before returning from this function as doing so might result in the | |
224 // destruction of this ImageLoader. | |
225 UpdatedHasPendingEvent(); | |
226 } | 209 } |
227 | 210 |
228 void ImageLoader::SetImageWithoutConsideringPendingLoadEvent( | 211 void ImageLoader::SetImageWithoutConsideringPendingLoadEvent( |
229 ImageResourceContent* new_image) { | 212 ImageResourceContent* new_image) { |
230 DCHECK(failed_load_url_.IsEmpty()); | 213 DCHECK(failed_load_url_.IsEmpty()); |
231 ImageResourceContent* old_image = image_.Get(); | 214 ImageResourceContent* old_image = image_.Get(); |
232 if (new_image != old_image) { | 215 if (new_image != old_image) { |
233 if (has_pending_load_event_) { | 216 if (has_pending_load_event_) { |
234 LoadEventSender().CancelEvent(this); | 217 LoadEventSender().CancelEvent(this); |
235 has_pending_load_event_ = false; | 218 has_pending_load_event_ = false; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 if (new_image) { | 390 if (new_image) { |
408 new_image->AddObserver(this); | 391 new_image->AddObserver(this); |
409 } | 392 } |
410 if (old_image) { | 393 if (old_image) { |
411 old_image->RemoveObserver(this); | 394 old_image->RemoveObserver(this); |
412 } | 395 } |
413 } | 396 } |
414 | 397 |
415 if (LayoutImageResource* image_resource = GetLayoutImageResource()) | 398 if (LayoutImageResource* image_resource = GetLayoutImageResource()) |
416 image_resource->ResetAnimation(); | 399 image_resource->ResetAnimation(); |
417 | |
418 // Only consider updating the protection ref-count of the Element immediately | |
419 // before returning from this function as doing so might result in the | |
420 // destruction of this ImageLoader. | |
421 UpdatedHasPendingEvent(); | |
422 } | 400 } |
423 | 401 |
424 void ImageLoader::UpdateFromElement(UpdateFromElementBehavior update_behavior, | 402 void ImageLoader::UpdateFromElement(UpdateFromElementBehavior update_behavior, |
425 ReferrerPolicy referrer_policy) { | 403 ReferrerPolicy referrer_policy) { |
426 AtomicString image_source_url = element_->ImageSourceURL(); | 404 AtomicString image_source_url = element_->ImageSourceURL(); |
427 suppress_error_events_ = (update_behavior == kUpdateSizeChanged); | 405 suppress_error_events_ = (update_behavior == kUpdateSizeChanged); |
428 | 406 |
429 if (update_behavior == kUpdateIgnorePreviousError) | 407 if (update_behavior == kUpdateIgnorePreviousError) |
430 ClearFailedLoadURL(); | 408 ClearFailedLoadURL(); |
431 | 409 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 if (resource->GetResourceError().IsAccessCheck()) { | 560 if (resource->GetResourceError().IsAccessCheck()) { |
583 CrossSiteOrCSPViolationOccurred( | 561 CrossSiteOrCSPViolationOccurred( |
584 AtomicString(resource->GetResourceError().FailingURL())); | 562 AtomicString(resource->GetResourceError().FailingURL())); |
585 } | 563 } |
586 | 564 |
587 // The error event should not fire if the image data update is a result of | 565 // The error event should not fire if the image data update is a result of |
588 // environment change. | 566 // environment change. |
589 // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-elem
ent:the-img-element-55 | 567 // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-elem
ent:the-img-element-55 |
590 if (!suppress_error_events_) | 568 if (!suppress_error_events_) |
591 DispatchErrorEvent(); | 569 DispatchErrorEvent(); |
592 | |
593 // Only consider updating the protection ref-count of the Element | |
594 // immediately before returning from this function as doing so might result | |
595 // in the destruction of this ImageLoader. | |
596 UpdatedHasPendingEvent(); | |
597 return; | 570 return; |
598 } | 571 } |
599 has_pending_load_event_ = true; | 572 has_pending_load_event_ = true; |
600 LoadEventSender().DispatchEventSoon(this); | 573 LoadEventSender().DispatchEventSoon(this); |
601 } | 574 } |
602 | 575 |
603 LayoutImageResource* ImageLoader::GetLayoutImageResource() { | 576 LayoutImageResource* ImageLoader::GetLayoutImageResource() { |
604 LayoutObject* layout_object = element_->GetLayoutObject(); | 577 LayoutObject* layout_object = element_->GetLayoutObject(); |
605 | 578 |
606 if (!layout_object) | 579 if (!layout_object) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 // Regular image loading is in progress. | 612 // Regular image loading is in progress. |
640 if (image_ && !image_complete_ && !loading_image_document_) | 613 if (image_ && !image_complete_ && !loading_image_document_) |
641 return true; | 614 return true; |
642 | 615 |
643 if (has_pending_load_event_ || has_pending_error_event_) | 616 if (has_pending_load_event_ || has_pending_error_event_) |
644 return true; | 617 return true; |
645 | 618 |
646 return false; | 619 return false; |
647 } | 620 } |
648 | 621 |
649 void ImageLoader::UpdatedHasPendingEvent() { | |
650 // If an Element that does image loading is removed from the DOM the | |
651 // load/error event for the image is still observable. As long as the | |
652 // ImageLoader is actively loading, the Element itself needs to be ref'ed to | |
653 // keep it from being destroyed by DOM manipulation or garbage collection. If | |
654 // such an Element wishes for the load to stop when removed from the DOM it | |
655 // needs to stop the ImageLoader explicitly. | |
656 bool was_protected = element_is_protected_; | |
657 element_is_protected_ = HasPendingEvent(); | |
658 if (was_protected == element_is_protected_) | |
659 return; | |
660 | |
661 if (element_is_protected_) { | |
662 if (deref_element_timer_.IsActive()) | |
663 deref_element_timer_.Stop(); | |
664 else | |
665 keep_alive_ = element_; | |
666 } else { | |
667 DCHECK(!deref_element_timer_.IsActive()); | |
668 deref_element_timer_.StartOneShot(0, BLINK_FROM_HERE); | |
669 } | |
670 } | |
671 | |
672 void ImageLoader::TimerFired(TimerBase*) { | |
673 keep_alive_.Clear(); | |
674 } | |
675 | |
676 void ImageLoader::DispatchPendingEvent(ImageEventSender* event_sender) { | 622 void ImageLoader::DispatchPendingEvent(ImageEventSender* event_sender) { |
677 RESOURCE_LOADING_DVLOG(1) << "ImageLoader::dispatchPendingEvent " << this; | 623 RESOURCE_LOADING_DVLOG(1) << "ImageLoader::dispatchPendingEvent " << this; |
678 DCHECK(event_sender == &LoadEventSender() || | 624 DCHECK(event_sender == &LoadEventSender() || |
679 event_sender == &ErrorEventSender()); | 625 event_sender == &ErrorEventSender()); |
680 const AtomicString& event_type = event_sender->EventType(); | 626 const AtomicString& event_type = event_sender->EventType(); |
681 if (event_type == EventTypeNames::load) | 627 if (event_type == EventTypeNames::load) |
682 DispatchPendingLoadEvent(); | 628 DispatchPendingLoadEvent(); |
683 if (event_type == EventTypeNames::error) | 629 if (event_type == EventTypeNames::error) |
684 DispatchPendingErrorEvent(); | 630 DispatchPendingErrorEvent(); |
685 } | 631 } |
686 | 632 |
687 void ImageLoader::DispatchPendingLoadEvent() { | 633 void ImageLoader::DispatchPendingLoadEvent() { |
688 CHECK(has_pending_load_event_); | 634 CHECK(has_pending_load_event_); |
689 if (!image_) | 635 if (!image_) |
690 return; | 636 return; |
691 CHECK(image_complete_); | 637 CHECK(image_complete_); |
692 has_pending_load_event_ = false; | 638 has_pending_load_event_ = false; |
693 if (GetElement()->GetDocument().GetFrame()) | 639 if (GetElement()->GetDocument().GetFrame()) |
694 DispatchLoadEvent(); | 640 DispatchLoadEvent(); |
695 | |
696 // Only consider updating the protection ref-count of the Element immediately | |
697 // before returning from this function as doing so might result in the | |
698 // destruction of this ImageLoader. | |
699 UpdatedHasPendingEvent(); | |
700 } | 641 } |
701 | 642 |
702 void ImageLoader::DispatchPendingErrorEvent() { | 643 void ImageLoader::DispatchPendingErrorEvent() { |
703 CHECK(has_pending_error_event_); | 644 CHECK(has_pending_error_event_); |
704 has_pending_error_event_ = false; | 645 has_pending_error_event_ = false; |
705 | 646 |
706 if (GetElement()->GetDocument().GetFrame()) | 647 if (GetElement()->GetDocument().GetFrame()) |
707 GetElement()->DispatchEvent(Event::Create(EventTypeNames::error)); | 648 GetElement()->DispatchEvent(Event::Create(EventTypeNames::error)); |
708 | |
709 // Only consider updating the protection ref-count of the Element immediately | |
710 // before returning from this function as doing so might result in the | |
711 // destruction of this ImageLoader. | |
712 UpdatedHasPendingEvent(); | |
713 } | 649 } |
714 | 650 |
715 bool ImageLoader::GetImageAnimationPolicy(ImageAnimationPolicy& policy) { | 651 bool ImageLoader::GetImageAnimationPolicy(ImageAnimationPolicy& policy) { |
716 if (!GetElement()->GetDocument().GetSettings()) | 652 if (!GetElement()->GetDocument().GetSettings()) |
717 return false; | 653 return false; |
718 | 654 |
719 policy = GetElement()->GetDocument().GetSettings()->GetImageAnimationPolicy(); | 655 policy = GetElement()->GetDocument().GetSettings()->GetImageAnimationPolicy(); |
720 return true; | 656 return true; |
721 } | 657 } |
722 | 658 |
(...skipping 12 matching lines...) Expand all Loading... |
735 } | 671 } |
736 if (delay_until_image_notify_finished_) { | 672 if (delay_until_image_notify_finished_) { |
737 delay_until_image_notify_finished_->DocumentChanged( | 673 delay_until_image_notify_finished_->DocumentChanged( |
738 element_->GetDocument()); | 674 element_->GetDocument()); |
739 } | 675 } |
740 ClearFailedLoadURL(); | 676 ClearFailedLoadURL(); |
741 ClearImage(); | 677 ClearImage(); |
742 } | 678 } |
743 | 679 |
744 } // namespace blink | 680 } // namespace blink |
OLD | NEW |