Index: third_party/WebKit/Source/core/loader/ImageLoader.cpp |
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp |
index b137ee673a1e554a5221564c8164d7621be12a4d..eb5a0cfbd7bdc4056f7869338b61e3a5b2387ae6 100644 |
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp |
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp |
@@ -29,6 +29,7 @@ |
#include "core/dom/Element.h" |
#include "core/dom/IncrementLoadEventDelayCount.h" |
#include "core/events/Event.h" |
+#include "core/events/EventSender.h" |
#include "core/frame/LocalFrame.h" |
#include "core/frame/Settings.h" |
#include "core/frame/UseCounter.h" |
@@ -55,6 +56,18 @@ |
namespace blink { |
+static ImageEventSender& LoadEventSender() { |
+ DEFINE_STATIC_LOCAL(ImageEventSender, sender, |
+ (ImageEventSender::Create(EventTypeNames::load))); |
+ return sender; |
+} |
+ |
+static ImageEventSender& ErrorEventSender() { |
+ DEFINE_STATIC_LOCAL(ImageEventSender, sender, |
+ (ImageEventSender::Create(EventTypeNames::error))); |
+ return sender; |
+} |
+ |
static inline bool PageIsBeingDismissed(Document* document) { |
return document->PageDismissalEventBeingDispatched() != |
Document::kNoDismissal; |
@@ -144,6 +157,8 @@ |
ImageLoader::ImageLoader(Element* element) |
: element_(element), |
deref_element_timer_(this, &ImageLoader::TimerFired), |
+ has_pending_load_event_(false), |
+ has_pending_error_event_(false), |
image_complete_(true), |
loading_image_document_(false), |
element_is_protected_(false), |
@@ -156,8 +171,8 @@ |
void ImageLoader::Dispose() { |
RESOURCE_LOADING_DVLOG(1) |
<< "~ImageLoader " << this |
- << "; has pending load event=" << pending_load_event_.IsActive() |
- << ", has pending error event=" << pending_error_event_.IsActive(); |
+ << "; has_pending_load_event_=" << has_pending_load_event_ |
+ << ", has_pending_error_event_=" << has_pending_error_event_; |
if (image_) { |
image_->RemoveObserver(this); |
@@ -215,10 +230,14 @@ |
DCHECK(failed_load_url_.IsEmpty()); |
ImageResourceContent* old_image = image_.Get(); |
if (new_image != old_image) { |
- if (pending_load_event_.IsActive()) |
- pending_load_event_.Cancel(); |
- if (pending_error_event_.IsActive()) |
- pending_error_event_.Cancel(); |
+ if (has_pending_load_event_) { |
+ LoadEventSender().CancelEvent(this); |
+ has_pending_load_event_ = false; |
+ } |
+ if (has_pending_error_event_) { |
+ ErrorEventSender().CancelEvent(this); |
+ has_pending_error_event_ = false; |
+ } |
UpdateImageState(new_image); |
if (new_image) { |
new_image->AddObserver(this); |
@@ -255,18 +274,13 @@ |
inline void ImageLoader::DispatchErrorEvent() { |
// There can be cases where DispatchErrorEvent() is called when there is |
// already a scheduled error event for the previous load attempt. |
- // In such cases we cancel the previous event (by overwriting |
- // |pending_error_event_|) and then re-schedule a new error event here. |
- // crbug.com/722500 |
- pending_error_event_ = |
- TaskRunnerHelper::Get(TaskType::kDOMManipulation, |
- &GetElement()->GetDocument()) |
- ->PostCancellableTask( |
- BLINK_FROM_HERE, |
- WTF::Bind(&ImageLoader::DispatchPendingErrorEvent, |
- WrapPersistent(this), |
- WTF::Passed(IncrementLoadEventDelayCount::Create( |
- GetElement()->GetDocument())))); |
+ // In such cases we cancel the previous event and then re-schedule a new |
+ // error event here. crbug.com/722500 |
+ if (has_pending_error_event_) |
+ ErrorEventSender().CancelEvent(this); |
+ |
+ has_pending_error_event_ = true; |
+ ErrorEventSender().DispatchEventSoon(this); |
} |
inline void ImageLoader::CrossSiteOrCSPViolationOccurred( |
@@ -368,8 +382,10 @@ |
element_->GetLayoutObject()->IsImage() && new_image == old_image) { |
ToLayoutImage(element_->GetLayoutObject())->IntrinsicSizeChanged(); |
} else { |
- if (pending_load_event_.IsActive()) |
- pending_load_event_.Cancel(); |
+ if (has_pending_load_event_) { |
+ LoadEventSender().CancelEvent(this); |
+ has_pending_load_event_ = false; |
+ } |
// Cancel error events that belong to the previous load, which is now |
// cancelled by changing the src attribute. If newImage is null and |
@@ -377,8 +393,10 @@ |
// posted by this load and we should not cancel the event. |
// FIXME: If both previous load and this one got blocked with an error, we |
// can receive one error event instead of two. |
- if (pending_error_event_.IsActive() && new_image) |
- pending_error_event_.Cancel(); |
+ if (has_pending_error_event_ && new_image) { |
+ ErrorEventSender().CancelEvent(this); |
+ has_pending_error_event_ = false; |
+ } |
UpdateImageState(new_image); |
@@ -518,7 +536,7 @@ |
void ImageLoader::ImageNotifyFinished(ImageResourceContent* resource) { |
RESOURCE_LOADING_DVLOG(1) |
<< "ImageLoader::imageNotifyFinished " << this |
- << "; has pending load event=" << pending_load_event_.IsActive(); |
+ << "; has_pending_load_event_=" << has_pending_load_event_; |
DCHECK(failed_load_url_.IsEmpty()); |
DCHECK_EQ(resource, image_.Get()); |
@@ -554,13 +572,12 @@ |
->UpdateUseCounters(GetElement()->GetDocument()); |
} |
- if (loading_image_document_) { |
- CHECK(!pending_load_event_.IsActive()); |
- return; |
- } |
+ if (loading_image_document_) |
+ return; |
if (resource->ErrorOccurred()) { |
- pending_load_event_.Cancel(); |
+ LoadEventSender().CancelEvent(this); |
+ has_pending_load_event_ = false; |
if (resource->GetResourceError().IsAccessCheck()) { |
CrossSiteOrCSPViolationOccurred( |
@@ -579,17 +596,8 @@ |
UpdatedHasPendingEvent(); |
return; |
} |
- |
- CHECK(!pending_load_event_.IsActive()); |
- pending_load_event_ = |
- TaskRunnerHelper::Get(TaskType::kDOMManipulation, |
- &GetElement()->GetDocument()) |
- ->PostCancellableTask( |
- BLINK_FROM_HERE, |
- WTF::Bind(&ImageLoader::DispatchPendingLoadEvent, |
- WrapPersistent(this), |
- WTF::Passed(IncrementLoadEventDelayCount::Create( |
- GetElement()->GetDocument())))); |
+ has_pending_load_event_ = true; |
+ LoadEventSender().DispatchEventSoon(this); |
} |
LayoutImageResource* ImageLoader::GetLayoutImageResource() { |
@@ -632,7 +640,7 @@ |
if (image_ && !image_complete_ && !loading_image_document_) |
return true; |
- if (pending_load_event_.IsActive() || pending_error_event_.IsActive()) |
+ if (has_pending_load_event_ || has_pending_error_event_) |
return true; |
return false; |
@@ -665,11 +673,23 @@ |
keep_alive_.Clear(); |
} |
-void ImageLoader::DispatchPendingLoadEvent( |
- std::unique_ptr<IncrementLoadEventDelayCount> count) { |
+void ImageLoader::DispatchPendingEvent(ImageEventSender* event_sender) { |
+ RESOURCE_LOADING_DVLOG(1) << "ImageLoader::dispatchPendingEvent " << this; |
+ DCHECK(event_sender == &LoadEventSender() || |
+ event_sender == &ErrorEventSender()); |
+ const AtomicString& event_type = event_sender->EventType(); |
+ if (event_type == EventTypeNames::load) |
+ DispatchPendingLoadEvent(); |
+ if (event_type == EventTypeNames::error) |
+ DispatchPendingErrorEvent(); |
+} |
+ |
+void ImageLoader::DispatchPendingLoadEvent() { |
+ CHECK(has_pending_load_event_); |
if (!image_) |
return; |
CHECK(image_complete_); |
+ has_pending_load_event_ = false; |
if (GetElement()->GetDocument().GetFrame()) |
DispatchLoadEvent(); |
@@ -677,14 +697,12 @@ |
// before returning from this function as doing so might result in the |
// destruction of this ImageLoader. |
UpdatedHasPendingEvent(); |
- |
- // Checks Document's load event synchronously here for performance. |
- // This is safe because DispatchPendingLoadEvent() is called asynchronously. |
- count->ClearAndCheckLoadEvent(); |
-} |
- |
-void ImageLoader::DispatchPendingErrorEvent( |
- std::unique_ptr<IncrementLoadEventDelayCount> count) { |
+} |
+ |
+void ImageLoader::DispatchPendingErrorEvent() { |
+ CHECK(has_pending_error_event_); |
+ has_pending_error_event_ = false; |
+ |
if (GetElement()->GetDocument().GetFrame()) |
GetElement()->DispatchEvent(Event::Create(EventTypeNames::error)); |
@@ -692,10 +710,6 @@ |
// before returning from this function as doing so might result in the |
// destruction of this ImageLoader. |
UpdatedHasPendingEvent(); |
- |
- // Checks Document's load event synchronously here for performance. |
- // This is safe because DispatchPendingErrorEvent() is called asynchronously. |
- count->ClearAndCheckLoadEvent(); |
} |
bool ImageLoader::GetImageAnimationPolicy(ImageAnimationPolicy& policy) { |
@@ -704,6 +718,14 @@ |
policy = GetElement()->GetDocument().GetSettings()->GetImageAnimationPolicy(); |
return true; |
+} |
+ |
+void ImageLoader::DispatchPendingLoadEvents() { |
+ LoadEventSender().DispatchPendingEvents(); |
+} |
+ |
+void ImageLoader::DispatchPendingErrorEvents() { |
+ ErrorEventSender().DispatchPendingEvents(); |
} |
void ImageLoader::ElementDidMoveToNewDocument() { |