summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/ImageLoader.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/loader/ImageLoader.cpp
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-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.cpp135
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();
+}
+
}