diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/loader/ImageLoader.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/loader/ImageLoader.cpp')
-rw-r--r-- | Source/WebCore/loader/ImageLoader.cpp | 135 |
1 files changed, 82 insertions, 53 deletions
diff --git a/Source/WebCore/loader/ImageLoader.cpp b/Source/WebCore/loader/ImageLoader.cpp index c717f915c..4ac8c476d 100644 --- a/Source/WebCore/loader/ImageLoader.cpp +++ b/Source/WebCore/loader/ImageLoader.cpp @@ -28,13 +28,12 @@ #include "CrossOriginAccessControl.h" #include "Document.h" #include "Element.h" -#include "ElementShadow.h" #include "Event.h" #include "EventSender.h" +#include "Frame.h" #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "HTMLParserIdioms.h" -#include "ImageLoaderClient.h" #include "RenderImage.h" #include "ScriptCallStack.h" #include "SecurityOrigin.h" @@ -56,8 +55,8 @@ template<> struct ValueCheck<WebCore::ImageLoader*> { { if (!p) return; - ASSERT(p->client()->imageElement()); - ValueCheck<WebCore::Element*>::checkConsistency(p->client()->imageElement()); + ASSERT(p->element()); + ValueCheck<WebCore::Element*>::checkConsistency(p->element()); } }; @@ -84,9 +83,16 @@ static ImageEventSender& errorEventSender() return sender; } -ImageLoader::ImageLoader(ImageLoaderClient* client) - : m_client(client) +static inline bool pageIsBeingDismissed(Document* document) +{ + Frame* frame = document->frame(); + return frame && frame->loader()->pageDismissalEventBeingDispatched() != FrameLoader::NoDismissal; +} + +ImageLoader::ImageLoader(Element* element) + : m_element(element) , m_image(0) + , m_derefElementTimer(this, &ImageLoader::timerFired) , m_hasPendingBeforeLoadEvent(false) , m_hasPendingLoadEvent(false) , m_hasPendingErrorEvent(false) @@ -116,12 +122,7 @@ ImageLoader::~ImageLoader() // If the ImageLoader is being destroyed but it is still protecting its image-loading Element, // remove that protection here. if (m_elementIsProtected) - client()->derefSourceElement(); -} - -inline Document* ImageLoader::document() -{ - return client()->sourceElement()->document(); + m_element->deref(); } void ImageLoader::setImage(CachedImage* newImage) @@ -166,10 +167,11 @@ void ImageLoader::updateFromElement() { // If we're not making renderers for the page, then don't load images. We don't want to slow // down the raw HTML parsing case by loading images we don't intend to display. - if (!document()->renderer()) + Document* document = m_element->document(); + if (!document->renderer()) return; - AtomicString attr = client()->sourceElement()->getAttribute(client()->sourceElement()->imageSourceAttributeName()); + AtomicString attr = m_element->imageSourceURL(); if (attr == m_failedLoadURL) return; @@ -178,58 +180,70 @@ void ImageLoader::updateFromElement() // an empty string. CachedResourceHandle<CachedImage> newImage = 0; if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { - CachedResourceRequest request(ResourceRequest(document()->completeURL(sourceURI(attr)))); - request.setInitiator(client()->sourceElement()); + CachedResourceRequest request(ResourceRequest(document->completeURL(sourceURI(attr)))); + request.setInitiator(element()); - String crossOriginMode = client()->sourceElement()->fastGetAttribute(HTMLNames::crossoriginAttr); + String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) { StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; - updateRequestForAccessControl(request.mutableResourceRequest(), document()->securityOrigin(), allowCredentials); + updateRequestForAccessControl(request.mutableResourceRequest(), document->securityOrigin(), allowCredentials); } if (m_loadManually) { - bool autoLoadOtherImages = document()->cachedResourceLoader()->autoLoadImages(); - document()->cachedResourceLoader()->setAutoLoadImages(false); + bool autoLoadOtherImages = document->cachedResourceLoader()->autoLoadImages(); + document->cachedResourceLoader()->setAutoLoadImages(false); newImage = new CachedImage(request.resourceRequest()); newImage->setLoading(true); - newImage->setOwningCachedResourceLoader(document()->cachedResourceLoader()); - document()->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage.get()); - document()->cachedResourceLoader()->setAutoLoadImages(autoLoadOtherImages); + newImage->setOwningCachedResourceLoader(document->cachedResourceLoader()); + document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage.get()); + document->cachedResourceLoader()->setAutoLoadImages(autoLoadOtherImages); } else - newImage = document()->cachedResourceLoader()->requestImage(request); + newImage = document->cachedResourceLoader()->requestImage(request); // If we do not have an image here, it means that a cross-site // violation occurred, or that the image was blocked via Content - // Security Policy. Either way, trigger an error event. - if (!newImage) { + // Security Policy, or the page is being dismissed. Trigger an + // error event if the page is not being dismissed. + if (!newImage && !pageIsBeingDismissed(document)) { m_failedLoadURL = attr; m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(this); } else - m_failedLoadURL = AtomicString(); + clearFailedLoadURL(); } else if (!attr.isNull()) { // Fire an error event if the url is empty. // FIXME: Should we fire this event asynchronoulsy via errorEventSender()? - client()->imageElement()->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); + m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); } CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { - if (m_hasPendingBeforeLoadEvent) + if (m_hasPendingBeforeLoadEvent) { beforeLoadEventSender().cancelEvent(this); - if (m_hasPendingLoadEvent) + m_hasPendingBeforeLoadEvent = false; + } + if (m_hasPendingLoadEvent) { loadEventSender().cancelEvent(this); - if (m_hasPendingErrorEvent) + m_hasPendingLoadEvent = false; + } + + // Cancel error events that belong to the previous load, which is now cancelled by changing the src attribute. + // If newImage is null and m_hasPendingErrorEvent is true, we know the error event has been just 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 (m_hasPendingErrorEvent && newImage) { errorEventSender().cancelEvent(this); + m_hasPendingErrorEvent = false; + } m_image = newImage; - m_hasPendingBeforeLoadEvent = !document()->isImageDocument() && newImage; + m_hasPendingBeforeLoadEvent = !m_element->document()->isImageDocument() && newImage; m_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; if (newImage) { - if (!document()->isImageDocument()) { - if (!document()->hasListenerType(Document::BEFORELOAD_LISTENER)) + if (!m_element->document()->isImageDocument()) { + if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) dispatchPendingBeforeLoadEvent(); else beforeLoadEventSender().dispatchEventSoon(this); @@ -255,8 +269,7 @@ void ImageLoader::updateFromElement() void ImageLoader::updateFromElementIgnoringPreviousError() { - // Clear previous error. - m_failedLoadURL = AtomicString(); + clearFailedLoadURL(); updateFromElement(); } @@ -272,9 +285,9 @@ void ImageLoader::notifyFinished(CachedResource* resource) if (!m_hasPendingLoadEvent) return; - if (client()->sourceElement()->fastHasAttribute(HTMLNames::crossoriginAttr) - && !document()->securityOrigin()->canRequest(image()->response().url()) - && !resource->passesAccessControlCheck(document()->securityOrigin())) { + if (m_element->fastHasAttribute(HTMLNames::crossoriginAttr) + && !m_element->document()->securityOrigin()->canRequest(image()->response().url()) + && !resource->passesAccessControlCheck(m_element->document()->securityOrigin())) { setImageWithoutConsideringPendingLoadEvent(0); @@ -282,7 +295,7 @@ void ImageLoader::notifyFinished(CachedResource* resource) errorEventSender().dispatchEventSoon(this); DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Cross-origin image load denied by Cross-Origin Resource Sharing policy."))); - document()->addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage); + m_element->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, consoleMessage); ASSERT(!m_hasPendingLoadEvent); @@ -305,7 +318,7 @@ void ImageLoader::notifyFinished(CachedResource* resource) RenderImageResource* ImageLoader::renderImageResource() { - RenderObject* renderer = client()->imageElement()->renderer(); + RenderObject* renderer = m_element->renderer(); if (!renderer) return 0; @@ -354,10 +367,20 @@ void ImageLoader::updatedHasPendingEvent() if (wasProtected == m_elementIsProtected) return; - if (m_elementIsProtected) - client()->refSourceElement(); - else - client()->derefSourceElement(); + if (m_elementIsProtected) { + if (m_derefElementTimer.isActive()) + m_derefElementTimer.stop(); + else + m_element->ref(); + } else { + ASSERT(!m_derefElementTimer.isActive()); + m_derefElementTimer.startOneShot(0); + } +} + +void ImageLoader::timerFired(Timer<ImageLoader>*) +{ + m_element->deref(); } void ImageLoader::dispatchPendingEvent(ImageEventSender* eventSender) @@ -378,10 +401,10 @@ void ImageLoader::dispatchPendingBeforeLoadEvent() return; if (!m_image) return; - if (!document()->attached()) + if (!m_element->document()->attached()) return; m_hasPendingBeforeLoadEvent = false; - if (client()->sourceElement()->dispatchBeforeLoadEvent(m_image->url())) { + if (m_element->dispatchBeforeLoadEvent(m_image->url())) { updateRenderer(); return; } @@ -392,9 +415,9 @@ void ImageLoader::dispatchPendingBeforeLoadEvent() loadEventSender().cancelEvent(this); m_hasPendingLoadEvent = false; - - if (client()->sourceElement()->hasTagName(HTMLNames::objectTag)) - static_cast<HTMLObjectElement*>(client()->sourceElement())->renderFallbackContent(); + + if (m_element->hasTagName(HTMLNames::objectTag)) + static_cast<HTMLObjectElement*>(m_element)->renderFallbackContent(); // Only consider updating the protection ref-count of the Element immediately before returning // from this function as doing so might result in the destruction of this ImageLoader. @@ -408,7 +431,7 @@ void ImageLoader::dispatchPendingLoadEvent() if (!m_image) return; m_hasPendingLoadEvent = false; - if (document()->attached()) + if (element()->document()->attached()) dispatchLoadEvent(); // Only consider updating the protection ref-count of the Element immediately before returning @@ -421,8 +444,8 @@ void ImageLoader::dispatchPendingErrorEvent() if (!m_hasPendingErrorEvent) return; m_hasPendingErrorEvent = false; - if (document()->attached()) - client()->imageElement()->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); + if (element()->document()->attached()) + element()->dispatchEvent(Event::create(eventNames().errorEvent, false, false)); // Only consider updating the protection ref-count of the Element immediately before returning // from this function as doing so might result in the destruction of this ImageLoader. @@ -446,7 +469,13 @@ void ImageLoader::dispatchPendingErrorEvents() void ImageLoader::elementDidMoveToNewDocument() { + clearFailedLoadURL(); setImage(0); } +inline void ImageLoader::clearFailedLoadURL() +{ + m_failedLoadURL = AtomicString(); +} + } |