- Revision
- 112190
- Author
- [email protected]
- Date
- 2012-03-26 18:59:06 -0700 (Mon, 26 Mar 2012)
Log Message
When <img crossorigin> fails the CORS check, we should fire the error event
https://bugs.webkit.org/show_bug.cgi?id=81998
Reviewed by Nate Chapin.
Source/WebCore:
The spec says we're supposed to fire the error event when the CORS
check fails, but we haven't been. This patch is larger than it might
otherwise be because we're firing the event asynchronously, but that
seems like the right thing to do.
Tests: http/tests/security/img-with-failed-cors-check-fails-to-load.html
* dom/Document.cpp:
(WebCore::Document::implicitClose):
* loader/ImageLoader.cpp:
(WebCore::errorEventSender):
(WebCore):
(WebCore::ImageLoader::ImageLoader):
(WebCore::ImageLoader::~ImageLoader):
(WebCore::ImageLoader::setImage):
(WebCore::ImageLoader::updateFromElement):
(WebCore::ImageLoader::notifyFinished):
(WebCore::ImageLoader::dispatchPendingEvent):
(WebCore::ImageLoader::dispatchPendingErrorEvent):
(WebCore::ImageLoader::dispatchPendingErrorEvents):
* loader/ImageLoader.h:
(ImageLoader):
LayoutTests:
Check that we're firing the error event in this case.
* http/tests/security/img-with-failed-cors-check-fails-to-load-expected.txt:
* http/tests/security/img-with-failed-cors-check-fails-to-load.html:
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (112189 => 112190)
--- trunk/LayoutTests/ChangeLog 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/LayoutTests/ChangeLog 2012-03-27 01:59:06 UTC (rev 112190)
@@ -1,3 +1,15 @@
+2012-03-26 Adam Barth <[email protected]>
+
+ When <img crossorigin> fails the CORS check, we should fire the error event
+ https://bugs.webkit.org/show_bug.cgi?id=81998
+
+ Reviewed by Nate Chapin.
+
+ Check that we're firing the error event in this case.
+
+ * http/tests/security/img-with-failed-cors-check-fails-to-load-expected.txt:
+ * http/tests/security/img-with-failed-cors-check-fails-to-load.html:
+
2012-03-26 Ryosuke Niwa <[email protected]>
Rebaseline after r112177.
Modified: trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load-expected.txt (112189 => 112190)
--- trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load-expected.txt 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load-expected.txt 2012-03-27 01:59:06 UTC (rev 112190)
@@ -1,2 +1,3 @@
CONSOLE MESSAGE: Cross-origin image load denied by Cross-Origin Resource Sharing policy.
+ALERT: PASS: The error event was called.
This test passes if the image below does not load.
Modified: trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load.html (112189 => 112190)
--- trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load.html 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/LayoutTests/http/tests/security/img-with-failed-cors-check-fails-to-load.html 2012-03-27 01:59:06 UTC (rev 112190)
@@ -10,6 +10,10 @@
alert('FAIL: The image loaded.');
}, false);
+img.addEventListener('error', function(event) {
+ alert('PASS: The error event was called.');
+}, false);
+
img.crossOrigin = "";
img.src = ""
document.body.appendChild(img);
Modified: trunk/Source/WebCore/ChangeLog (112189 => 112190)
--- trunk/Source/WebCore/ChangeLog 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/Source/WebCore/ChangeLog 2012-03-27 01:59:06 UTC (rev 112190)
@@ -1,3 +1,33 @@
+2012-03-26 Adam Barth <[email protected]>
+
+ When <img crossorigin> fails the CORS check, we should fire the error event
+ https://bugs.webkit.org/show_bug.cgi?id=81998
+
+ Reviewed by Nate Chapin.
+
+ The spec says we're supposed to fire the error event when the CORS
+ check fails, but we haven't been. This patch is larger than it might
+ otherwise be because we're firing the event asynchronously, but that
+ seems like the right thing to do.
+
+ Tests: http/tests/security/img-with-failed-cors-check-fails-to-load.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::implicitClose):
+ * loader/ImageLoader.cpp:
+ (WebCore::errorEventSender):
+ (WebCore):
+ (WebCore::ImageLoader::ImageLoader):
+ (WebCore::ImageLoader::~ImageLoader):
+ (WebCore::ImageLoader::setImage):
+ (WebCore::ImageLoader::updateFromElement):
+ (WebCore::ImageLoader::notifyFinished):
+ (WebCore::ImageLoader::dispatchPendingEvent):
+ (WebCore::ImageLoader::dispatchPendingErrorEvent):
+ (WebCore::ImageLoader::dispatchPendingErrorEvents):
+ * loader/ImageLoader.h:
+ (ImageLoader):
+
2012-03-26 Stephen White <[email protected]>
Make filters and the threaded compositor play well together.
Modified: trunk/Source/WebCore/dom/Document.cpp (112189 => 112190)
--- trunk/Source/WebCore/dom/Document.cpp 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-03-27 01:59:06 UTC (rev 112190)
@@ -2317,6 +2317,7 @@
ImageLoader::dispatchPendingBeforeLoadEvents();
ImageLoader::dispatchPendingLoadEvents();
+ ImageLoader::dispatchPendingErrorEvents();
HTMLLinkElement::dispatchPendingLoadEvents();
HTMLStyleElement::dispatchPendingLoadEvents();
Modified: trunk/Source/WebCore/loader/ImageLoader.cpp (112189 => 112190)
--- trunk/Source/WebCore/loader/ImageLoader.cpp 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/Source/WebCore/loader/ImageLoader.cpp 2012-03-27 01:59:06 UTC (rev 112190)
@@ -75,11 +75,18 @@
return sender;
}
+static ImageEventSender& errorEventSender()
+{
+ DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().errorEvent));
+ return sender;
+}
+
ImageLoader::ImageLoader(Element* element)
: m_element(element)
, m_image(0)
, m_firedBeforeLoad(true)
, m_firedLoad(true)
+ , m_firedError(true)
, m_imageComplete(true)
, m_loadManually(false)
{
@@ -97,6 +104,10 @@
ASSERT(!m_firedLoad || !loadEventSender().hasPendingEvents(this));
if (!m_firedLoad)
loadEventSender().cancelEvent(this);
+
+ ASSERT(!m_firedError || !errorEventSender().hasPendingEvents(this));
+ if (!m_firedError)
+ errorEventSender().cancelEvent(this);
}
void ImageLoader::setImage(CachedImage* newImage)
@@ -113,6 +124,10 @@
loadEventSender().cancelEvent(this);
m_firedLoad = true;
}
+ if (!m_firedError) {
+ errorEventSender().cancelEvent(this);
+ m_firedError = true;
+ }
m_imageComplete = true;
if (newImage)
newImage->addClient(this);
@@ -163,8 +178,11 @@
// If we do not have an image here, it means that a cross-site
// violation occurred.
m_failedLoadURL = !newImage ? attr : AtomicString();
- } else if (!attr.isNull()) // Fire an error event if the url is empty.
+ } else if (!attr.isNull()) {
+ // Fire an error event if the url is empty.
+ // FIXME: Should we fire this event asynchronoulsy via errorEventSender()?
m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false));
+ }
CachedImage* oldImage = m_image.get();
if (newImage != oldImage) {
@@ -172,6 +190,8 @@
beforeLoadEventSender().cancelEvent(this);
if (!m_firedLoad)
loadEventSender().cancelEvent(this);
+ if (!m_firedError)
+ errorEventSender().cancelEvent(this);
m_image = newImage;
m_firedBeforeLoad = !newImage;
@@ -222,6 +242,9 @@
setImage(0);
+ m_firedError = false;
+ errorEventSender().dispatchEventSoon(this);
+
DEFINE_STATIC_LOCAL(String, consoleMessage, ("Cross-origin image load denied by Cross-Origin Resource Sharing policy."));
m_element->document()->addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage);
@@ -279,12 +302,14 @@
void ImageLoader::dispatchPendingEvent(ImageEventSender* eventSender)
{
- ASSERT(eventSender == &beforeLoadEventSender() || eventSender == &loadEventSender());
+ ASSERT(eventSender == &beforeLoadEventSender() || eventSender == &loadEventSender() || eventSender == &errorEventSender());
const AtomicString& eventType = eventSender->eventType();
if (eventType == eventNames().beforeloadEvent)
dispatchPendingBeforeLoadEvent();
if (eventType == eventNames().loadEvent)
dispatchPendingLoadEvent();
+ if (eventType == eventNames().errorEvent)
+ dispatchPendingErrorEvent();
}
void ImageLoader::dispatchPendingBeforeLoadEvent()
@@ -324,6 +349,16 @@
dispatchLoadEvent();
}
+void ImageLoader::dispatchPendingErrorEvent()
+{
+ if (m_firedError)
+ return;
+ if (!m_element->document()->attached())
+ return;
+ m_firedError = true;
+ m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false));
+}
+
void ImageLoader::dispatchPendingBeforeLoadEvents()
{
beforeLoadEventSender().dispatchPendingEvents();
@@ -334,6 +369,11 @@
loadEventSender().dispatchPendingEvents();
}
+void ImageLoader::dispatchPendingErrorEvents()
+{
+ errorEventSender().dispatchPendingEvents();
+}
+
void ImageLoader::elementDidMoveToNewDocument()
{
setImage(0);
Modified: trunk/Source/WebCore/loader/ImageLoader.h (112189 => 112190)
--- trunk/Source/WebCore/loader/ImageLoader.h 2012-03-27 01:56:17 UTC (rev 112189)
+++ trunk/Source/WebCore/loader/ImageLoader.h 2012-03-27 01:59:06 UTC (rev 112190)
@@ -66,6 +66,7 @@
static void dispatchPendingBeforeLoadEvents();
static void dispatchPendingLoadEvents();
+ static void dispatchPendingErrorEvents();
protected:
virtual void notifyFinished(CachedResource*);
@@ -76,6 +77,7 @@
void dispatchPendingBeforeLoadEvent();
void dispatchPendingLoadEvent();
+ void dispatchPendingErrorEvent();
RenderImageResource* renderImageResource();
void updateRenderer();
@@ -85,6 +87,7 @@
AtomicString m_failedLoadURL;
bool m_firedBeforeLoad : 1;
bool m_firedLoad : 1;
+ bool m_firedError : 1;
bool m_imageComplete : 1;
bool m_loadManually : 1;
};