Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: third_party/WebKit/Source/core/loader/ImageLoader.cpp

Issue 2905233002: Remove the lifetime hack in ImageLoader where it keeps its assoc element alive (Closed)
Patch Set: Rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/loader/ImageLoader.h ('k') | third_party/WebKit/Source/core/svg/SVGImageElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698