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 reserv
ed. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserv
ed. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 BypassMainWorldBehavior m_shouldBypassMainWorldCSP; | 140 BypassMainWorldBehavior m_shouldBypassMainWorldCSP; |
141 UpdateFromElementBehavior m_updateBehavior; | 141 UpdateFromElementBehavior m_updateBehavior; |
142 RefPtr<ScriptState> m_scriptState; | 142 RefPtr<ScriptState> m_scriptState; |
143 WeakPtrFactory<Task> m_weakFactory; | 143 WeakPtrFactory<Task> m_weakFactory; |
144 ReferrerPolicy m_referrerPolicy; | 144 ReferrerPolicy m_referrerPolicy; |
145 KURL m_requestURL; | 145 KURL m_requestURL; |
146 }; | 146 }; |
147 | 147 |
148 ImageLoader::ImageLoader(Element* element) | 148 ImageLoader::ImageLoader(Element* element) |
149 : m_element(element) | 149 : m_element(element) |
150 , m_derefElementTimer(this, &ImageLoader::timerFired) | |
151 , m_hasPendingLoadEvent(false) | 150 , m_hasPendingLoadEvent(false) |
152 , m_hasPendingErrorEvent(false) | 151 , m_hasPendingErrorEvent(false) |
153 , m_imageComplete(true) | 152 , m_imageComplete(true) |
154 , m_loadingImageDocument(false) | 153 , m_loadingImageDocument(false) |
155 , m_elementIsProtected(false) | |
156 , m_suppressErrorEvents(false) | 154 , m_suppressErrorEvents(false) |
157 { | 155 { |
158 RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this; | 156 RESOURCE_LOADING_DVLOG(1) << "new ImageLoader " << this; |
159 ThreadState::current()->registerPreFinalizer(this); | 157 ThreadState::current()->registerPreFinalizer(this); |
160 } | 158 } |
161 | 159 |
162 ImageLoader::~ImageLoader() | 160 ImageLoader::~ImageLoader() |
163 { | 161 { |
164 } | 162 } |
165 | 163 |
(...skipping 11 matching lines...) Expand all Loading... |
177 | 175 |
178 DEFINE_TRACE(ImageLoader) | 176 DEFINE_TRACE(ImageLoader) |
179 { | 177 { |
180 visitor->trace(m_image); | 178 visitor->trace(m_image); |
181 visitor->trace(m_element); | 179 visitor->trace(m_element); |
182 } | 180 } |
183 | 181 |
184 void ImageLoader::setImage(ImageResource* newImage) | 182 void ImageLoader::setImage(ImageResource* newImage) |
185 { | 183 { |
186 setImageWithoutConsideringPendingLoadEvent(newImage); | 184 setImageWithoutConsideringPendingLoadEvent(newImage); |
187 | |
188 // Only consider updating the protection ref-count of the Element immediatel
y before returning | |
189 // from this function as doing so might result in the destruction of this Im
ageLoader. | |
190 updatedHasPendingEvent(); | |
191 } | 185 } |
192 | 186 |
193 void ImageLoader::setImageWithoutConsideringPendingLoadEvent(ImageResource* newI
mage) | 187 void ImageLoader::setImageWithoutConsideringPendingLoadEvent(ImageResource* newI
mage) |
194 { | 188 { |
195 ASSERT(m_failedLoadURL.isEmpty()); | 189 ASSERT(m_failedLoadURL.isEmpty()); |
196 ImageResource* oldImage = m_image.get(); | 190 ImageResource* oldImage = m_image.get(); |
197 if (newImage != oldImage) { | 191 if (newImage != oldImage) { |
198 m_image = newImage; | 192 m_image = newImage; |
199 if (m_hasPendingLoadEvent) { | 193 if (m_hasPendingLoadEvent) { |
200 loadEventSender().cancelEvent(this); | 194 loadEventSender().cancelEvent(this); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 if (newImage) { | 330 if (newImage) { |
337 newImage->addObserver(this); | 331 newImage->addObserver(this); |
338 } | 332 } |
339 if (oldImage) { | 333 if (oldImage) { |
340 oldImage->removeObserver(this); | 334 oldImage->removeObserver(this); |
341 } | 335 } |
342 } | 336 } |
343 | 337 |
344 if (LayoutImageResource* imageResource = layoutImageResource()) | 338 if (LayoutImageResource* imageResource = layoutImageResource()) |
345 imageResource->resetAnimation(); | 339 imageResource->resetAnimation(); |
346 | |
347 // Only consider updating the protection ref-count of the Element immediatel
y before returning | |
348 // from this function as doing so might result in the destruction of this Im
ageLoader. | |
349 updatedHasPendingEvent(); | |
350 } | 340 } |
351 | 341 |
352 void ImageLoader::updateFromElement(UpdateFromElementBehavior updateBehavior, Re
ferrerPolicy referrerPolicy) | 342 void ImageLoader::updateFromElement(UpdateFromElementBehavior updateBehavior, Re
ferrerPolicy referrerPolicy) |
353 { | 343 { |
354 AtomicString imageSourceURL = m_element->imageSourceURL(); | 344 AtomicString imageSourceURL = m_element->imageSourceURL(); |
355 m_suppressErrorEvents = (updateBehavior == UpdateSizeChanged); | 345 m_suppressErrorEvents = (updateBehavior == UpdateSizeChanged); |
356 | 346 |
357 if (updateBehavior == UpdateIgnorePreviousError) | 347 if (updateBehavior == UpdateIgnorePreviousError) |
358 clearFailedLoadURL(); | 348 clearFailedLoadURL(); |
359 | 349 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 m_hasPendingLoadEvent = false; | 449 m_hasPendingLoadEvent = false; |
460 | 450 |
461 if (resource->resourceError().isAccessCheck()) | 451 if (resource->resourceError().isAccessCheck()) |
462 crossSiteOrCSPViolationOccurred(AtomicString(resource->resourceError
().failingURL())); | 452 crossSiteOrCSPViolationOccurred(AtomicString(resource->resourceError
().failingURL())); |
463 | 453 |
464 // The error event should not fire if the image data update is a result
of environment change. | 454 // The error event should not fire if the image data update is a result
of environment change. |
465 // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-
element:the-img-element-55 | 455 // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-
element:the-img-element-55 |
466 if (!m_suppressErrorEvents) | 456 if (!m_suppressErrorEvents) |
467 dispatchErrorEvent(); | 457 dispatchErrorEvent(); |
468 | 458 |
469 // Only consider updating the protection ref-count of the Element immedi
ately before returning | |
470 // from this function as doing so might result in the destruction of thi
s ImageLoader. | |
471 updatedHasPendingEvent(); | |
472 return; | 459 return; |
473 } | 460 } |
474 if (resource->wasCanceled()) { | 461 if (resource->wasCanceled()) { |
475 m_hasPendingLoadEvent = false; | 462 m_hasPendingLoadEvent = false; |
476 // Only consider updating the protection ref-count of the Element immedi
ately before returning | |
477 // from this function as doing so might result in the destruction of thi
s ImageLoader. | |
478 updatedHasPendingEvent(); | |
479 return; | 463 return; |
480 } | 464 } |
481 loadEventSender().dispatchEventSoon(this); | 465 loadEventSender().dispatchEventSoon(this); |
482 } | 466 } |
483 | 467 |
484 LayoutImageResource* ImageLoader::layoutImageResource() | 468 LayoutImageResource* ImageLoader::layoutImageResource() |
485 { | 469 { |
486 LayoutObject* layoutObject = m_element->layoutObject(); | 470 LayoutObject* layoutObject = m_element->layoutObject(); |
487 | 471 |
488 if (!layoutObject) | 472 if (!layoutObject) |
(...skipping 21 matching lines...) Expand all Loading... |
510 return; | 494 return; |
511 | 495 |
512 // Only update the layoutObject if it doesn't have an image or if what we ha
ve | 496 // Only update the layoutObject if it doesn't have an image or if what we ha
ve |
513 // is a complete image. This prevents flickering in the case where a dynami
c | 497 // is a complete image. This prevents flickering in the case where a dynami
c |
514 // change is happening between two images. | 498 // change is happening between two images. |
515 ImageResource* cachedImage = imageResource->cachedImage(); | 499 ImageResource* cachedImage = imageResource->cachedImage(); |
516 if (m_image != cachedImage && (m_imageComplete || !cachedImage)) | 500 if (m_image != cachedImage && (m_imageComplete || !cachedImage)) |
517 imageResource->setImageResource(m_image.get()); | 501 imageResource->setImageResource(m_image.get()); |
518 } | 502 } |
519 | 503 |
520 void ImageLoader::updatedHasPendingEvent() | |
521 { | |
522 // If an Element that does image loading is removed from the DOM the load/er
ror event for the image is still observable. | |
523 // As long as the ImageLoader is actively loading, the Element itself needs
to be ref'ed to keep it from being | |
524 // destroyed by DOM manipulation or garbage collection. | |
525 // If such an Element wishes for the load to stop when removed from the DOM
it needs to stop the ImageLoader explicitly. | |
526 bool wasProtected = m_elementIsProtected; | |
527 m_elementIsProtected = m_hasPendingLoadEvent || m_hasPendingErrorEvent; | |
528 if (wasProtected == m_elementIsProtected) | |
529 return; | |
530 | |
531 if (m_elementIsProtected) { | |
532 if (m_derefElementTimer.isActive()) | |
533 m_derefElementTimer.stop(); | |
534 else | |
535 m_keepAlive = m_element; | |
536 } else { | |
537 ASSERT(!m_derefElementTimer.isActive()); | |
538 m_derefElementTimer.startOneShot(0, BLINK_FROM_HERE); | |
539 } | |
540 } | |
541 | |
542 void ImageLoader::timerFired(TimerBase*) | |
543 { | |
544 m_keepAlive.clear(); | |
545 } | |
546 | |
547 void ImageLoader::dispatchPendingEvent(ImageEventSender* eventSender) | 504 void ImageLoader::dispatchPendingEvent(ImageEventSender* eventSender) |
548 { | 505 { |
549 RESOURCE_LOADING_DVLOG(1) << "ImageLoader::dispatchPendingEvent " << this; | 506 RESOURCE_LOADING_DVLOG(1) << "ImageLoader::dispatchPendingEvent " << this; |
550 ASSERT(eventSender == &loadEventSender() || eventSender == &errorEventSender
()); | 507 ASSERT(eventSender == &loadEventSender() || eventSender == &errorEventSender
()); |
551 const AtomicString& eventType = eventSender->eventType(); | 508 const AtomicString& eventType = eventSender->eventType(); |
552 if (eventType == EventTypeNames::load) | 509 if (eventType == EventTypeNames::load) |
553 dispatchPendingLoadEvent(); | 510 dispatchPendingLoadEvent(); |
554 if (eventType == EventTypeNames::error) | 511 if (eventType == EventTypeNames::error) |
555 dispatchPendingErrorEvent(); | 512 dispatchPendingErrorEvent(); |
556 } | 513 } |
557 | 514 |
558 void ImageLoader::dispatchPendingLoadEvent() | 515 void ImageLoader::dispatchPendingLoadEvent() |
559 { | 516 { |
560 if (!m_hasPendingLoadEvent) | 517 if (!m_hasPendingLoadEvent) |
561 return; | 518 return; |
562 if (!m_image) | 519 if (!m_image) |
563 return; | 520 return; |
564 m_hasPendingLoadEvent = false; | 521 m_hasPendingLoadEvent = false; |
565 if (element()->document().frame()) | 522 if (element()->document().frame()) |
566 dispatchLoadEvent(); | 523 dispatchLoadEvent(); |
567 | |
568 // Only consider updating the protection ref-count of the Element immediatel
y before returning | |
569 // from this function as doing so might result in the destruction of this Im
ageLoader. | |
570 updatedHasPendingEvent(); | |
571 } | 524 } |
572 | 525 |
573 void ImageLoader::dispatchPendingErrorEvent() | 526 void ImageLoader::dispatchPendingErrorEvent() |
574 { | 527 { |
575 if (!m_hasPendingErrorEvent) | 528 if (!m_hasPendingErrorEvent) |
576 return; | 529 return; |
577 m_hasPendingErrorEvent = false; | 530 m_hasPendingErrorEvent = false; |
578 | 531 |
579 if (element()->document().frame()) | 532 if (element()->document().frame()) |
580 element()->dispatchEvent(Event::create(EventTypeNames::error)); | 533 element()->dispatchEvent(Event::create(EventTypeNames::error)); |
581 | |
582 // Only consider updating the protection ref-count of the Element immediatel
y before returning | |
583 // from this function as doing so might result in the destruction of this Im
ageLoader. | |
584 updatedHasPendingEvent(); | |
585 } | 534 } |
586 | 535 |
587 bool ImageLoader::getImageAnimationPolicy(ImageAnimationPolicy& policy) | 536 bool ImageLoader::getImageAnimationPolicy(ImageAnimationPolicy& policy) |
588 { | 537 { |
589 if (!element()->document().settings()) | 538 if (!element()->document().settings()) |
590 return false; | 539 return false; |
591 | 540 |
592 policy = element()->document().settings()->imageAnimationPolicy(); | 541 policy = element()->document().settings()->imageAnimationPolicy(); |
593 return true; | 542 return true; |
594 } | 543 } |
(...skipping 10 matching lines...) Expand all Loading... |
605 | 554 |
606 void ImageLoader::elementDidMoveToNewDocument() | 555 void ImageLoader::elementDidMoveToNewDocument() |
607 { | 556 { |
608 if (m_loadDelayCounter) | 557 if (m_loadDelayCounter) |
609 m_loadDelayCounter->documentChanged(m_element->document()); | 558 m_loadDelayCounter->documentChanged(m_element->document()); |
610 clearFailedLoadURL(); | 559 clearFailedLoadURL(); |
611 setImage(0); | 560 setImage(0); |
612 } | 561 } |
613 | 562 |
614 } // namespace blink | 563 } // namespace blink |
OLD | NEW |