| 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 |