- Revision
- 149098
- Author
- [email protected]
- Date
- 2013-04-25 02:51:36 -0700 (Thu, 25 Apr 2013)
Log Message
EventSource: Synchronous loader callback not handled properly
https://bugs.webkit.org/show_bug.cgi?id=115104
Source/WebCore:
When attempting a cross-origin request towards a non-HTTP URL, an early verification
of the protocol scheme will cause didFailAccessControlCheck to be called synchronously
before the loader has even finished being created. This special case was not handled
properly, since we tried to cancel a non-existing loader, which resulted in a crash.
In addition to checking whether a request is in flight before trying to cancel it,
this change also schedules the initial creation of the loader to happen asynchronously
when an EventSource is constructed, so that a script can register for the error event
before it is dispatched (as a result of passing a non-HTTP URL to the constructor).
Patch by Per-Erik Brodin <[email protected]> on 2013-04-25
Reviewed by Alexey Proskuryakov.
Test: http/tests/eventsource/eventsource-cors-non-http.html
* page/EventSource.cpp:
(WebCore::EventSource::EventSource):
(WebCore::EventSource::create):
(WebCore::EventSource::scheduleInitialConnect):
(WebCore):
(WebCore::EventSource::scheduleReconnect):
(WebCore::EventSource::connectTimerFired):
(WebCore::EventSource::close):
(WebCore::EventSource::abortConnectionAttempt):
* page/EventSource.h:
(EventSource):
LayoutTests:
Patch by Per-Erik Brodin <[email protected]> on 2013-04-25
Reviewed by Alexey Proskuryakov.
* http/tests/eventsource/eventsource-cors-non-http-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-non-http.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (149097 => 149098)
--- trunk/LayoutTests/ChangeLog 2013-04-25 09:43:31 UTC (rev 149097)
+++ trunk/LayoutTests/ChangeLog 2013-04-25 09:51:36 UTC (rev 149098)
@@ -1,3 +1,13 @@
+2013-04-25 Per-Erik Brodin <[email protected]>
+
+ EventSource: Synchronous loader callback not handled properly
+ https://bugs.webkit.org/show_bug.cgi?id=115104
+
+ Reviewed by Alexey Proskuryakov.
+
+ * http/tests/eventsource/eventsource-cors-non-http-expected.txt: Added.
+ * http/tests/eventsource/eventsource-cors-non-http.html: Added.
+
2013-04-25 Ádám Kallai <[email protected]>
[Qt] Unreviewed gardening. Added platform specific expected files after r148987.
Added: trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http-expected.txt (0 => 149098)
--- trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http-expected.txt 2013-04-25 09:51:36 UTC (rev 149098)
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: EventSource cannot load ftp://127.0.0.1. Cross origin requests are only supported for HTTP.
+CONSOLE MESSAGE: EventSource cannot load motd. Cross origin requests are only supported for HTTP.
+CONSOLE MESSAGE: EventSource cannot load localhost:8080/. Cross origin requests are only supported for HTTP.
+CONSOLE MESSAGE: EventSource cannot load tel:1234. Cross origin requests are only supported for HTTP.
+Test EventSource with non-HTTP protocol schemes in the URL. Should print a series of PASS messages followed by DONE.
+
+PASS: got error event and readyState is CLOSED
+PASS: got error event and readyState is CLOSED
+PASS: got error event and readyState is CLOSED
+PASS: got error event and readyState is CLOSED
+DONE
+
Added: trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http.html (0 => 149098)
--- trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http.html (rev 0)
+++ trunk/LayoutTests/http/tests/eventsource/eventsource-cors-non-http.html 2013-04-25 09:51:36 UTC (rev 149098)
@@ -0,0 +1,37 @@
+<html>
+<body>
+<p>Test EventSource with non-HTTP protocol schemes in the URL. Should print a series of PASS messages followed by DONE.</p>
+<script>
+function log(msg) {
+ document.body.innerHTML += msg + "<br>";
+}
+
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+}
+
+var count = 0;
+new EventSource("ftp://127.0.0.1")._onerror_ =
+new EventSource("file:///etc/motd")._onerror_ =
+new EventSource("localhost:8080/")._onerror_ =
+new EventSource("tel:1234")._onerror_ = function () {
+ if (this.readyState == EventSource.CLOSED) {
+ log("PASS: got error event and readyState is CLOSED");
+ } else {
+ log("FAIL: got error event but readyState is not CLOSED");
+ this.close();
+ }
+ if (count++ == 3) {
+ log("DONE");
+ end();
+ }
+};
+
+function end() {
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (149097 => 149098)
--- trunk/Source/WebCore/ChangeLog 2013-04-25 09:43:31 UTC (rev 149097)
+++ trunk/Source/WebCore/ChangeLog 2013-04-25 09:51:36 UTC (rev 149098)
@@ -1,3 +1,33 @@
+2013-04-25 Per-Erik Brodin <[email protected]>
+
+ EventSource: Synchronous loader callback not handled properly
+ https://bugs.webkit.org/show_bug.cgi?id=115104
+
+ When attempting a cross-origin request towards a non-HTTP URL, an early verification
+ of the protocol scheme will cause didFailAccessControlCheck to be called synchronously
+ before the loader has even finished being created. This special case was not handled
+ properly, since we tried to cancel a non-existing loader, which resulted in a crash.
+ In addition to checking whether a request is in flight before trying to cancel it,
+ this change also schedules the initial creation of the loader to happen asynchronously
+ when an EventSource is constructed, so that a script can register for the error event
+ before it is dispatched (as a result of passing a non-HTTP URL to the constructor).
+
+ Reviewed by Alexey Proskuryakov.
+
+ Test: http/tests/eventsource/eventsource-cors-non-http.html
+
+ * page/EventSource.cpp:
+ (WebCore::EventSource::EventSource):
+ (WebCore::EventSource::create):
+ (WebCore::EventSource::scheduleInitialConnect):
+ (WebCore):
+ (WebCore::EventSource::scheduleReconnect):
+ (WebCore::EventSource::connectTimerFired):
+ (WebCore::EventSource::close):
+ (WebCore::EventSource::abortConnectionAttempt):
+ * page/EventSource.h:
+ (EventSource):
+
2013-04-25 Patrick Gansterer <[email protected]>
Unreviewed WinCE build fix after r148545.
Modified: trunk/Source/WebCore/page/EventSource.cpp (149097 => 149098)
--- trunk/Source/WebCore/page/EventSource.cpp 2013-04-25 09:43:31 UTC (rev 149097)
+++ trunk/Source/WebCore/page/EventSource.cpp 2013-04-25 09:51:36 UTC (rev 149098)
@@ -65,7 +65,7 @@
, m_withCredentials(false)
, m_state(CONNECTING)
, m_decoder(TextResourceDecoder::create("text/plain", "UTF-8"))
- , m_reconnectTimer(this, &EventSource::reconnectTimerFired)
+ , m_connectTimer(this, &EventSource::connectTimerFired)
, m_discardTrailingNewline(false)
, m_requestInFlight(false)
, m_reconnectDelay(defaultReconnectDelay)
@@ -101,7 +101,7 @@
RefPtr<EventSource> source = adoptRef(new EventSource(context, fullURL, eventSourceInit));
source->setPendingActivity(source.get());
- source->connect();
+ source->scheduleInitialConnect();
source->suspendIfNeeded();
return source.release();
@@ -155,14 +155,22 @@
unsetPendingActivity(this);
}
+void EventSource::scheduleInitialConnect()
+{
+ ASSERT(m_state == CONNECTING);
+ ASSERT(!m_requestInFlight);
+
+ m_connectTimer.startOneShot(0);
+}
+
void EventSource::scheduleReconnect()
{
m_state = CONNECTING;
- m_reconnectTimer.startOneShot(m_reconnectDelay / 1000);
+ m_connectTimer.startOneShot(m_reconnectDelay / 1000);
dispatchEvent(Event::create(eventNames().errorEvent, false, false));
}
-void EventSource::reconnectTimerFired(Timer<EventSource>*)
+void EventSource::connectTimerFired(Timer<EventSource>*)
{
connect();
}
@@ -189,16 +197,16 @@
return;
}
- // Stop trying to reconnect if EventSource was explicitly closed or if ActiveDOMObject::stop() was called.
- if (m_reconnectTimer.isActive()) {
- m_reconnectTimer.stop();
- unsetPendingActivity(this);
- }
+ // Stop trying to connect/reconnect if EventSource was explicitly closed or if ActiveDOMObject::stop() was called.
+ if (m_connectTimer.isActive())
+ m_connectTimer.stop();
if (m_requestInFlight)
m_loader->cancel();
-
- m_state = CLOSED;
+ else {
+ m_state = CLOSED;
+ unsetPendingActivity(this);
+ }
}
const AtomicString& EventSource::interfaceName() const
@@ -305,9 +313,13 @@
void EventSource::abortConnectionAttempt()
{
ASSERT(m_state == CONNECTING);
- ASSERT(m_requestInFlight);
- m_loader->cancel();
+ if (m_requestInFlight)
+ m_loader->cancel();
+ else {
+ m_state = CLOSED;
+ unsetPendingActivity(this);
+ }
ASSERT(m_state == CLOSED);
dispatchEvent(Event::create(eventNames().errorEvent, false, false));
Modified: trunk/Source/WebCore/page/EventSource.h (149097 => 149098)
--- trunk/Source/WebCore/page/EventSource.h 2013-04-25 09:43:31 UTC (rev 149097)
+++ trunk/Source/WebCore/page/EventSource.h 2013-04-25 09:51:36 UTC (rev 149098)
@@ -97,8 +97,9 @@
void connect();
void networkRequestEnded();
+ void scheduleInitialConnect();
void scheduleReconnect();
- void reconnectTimerFired(Timer<EventSource>*);
+ void connectTimerFired(Timer<EventSource>*);
void abortConnectionAttempt();
void parseEventStream();
void parseEventStreamLine(unsigned pos, int fieldLength, int lineLength);
@@ -110,7 +111,7 @@
RefPtr<TextResourceDecoder> m_decoder;
RefPtr<ThreadableLoader> m_loader;
- Timer<EventSource> m_reconnectTimer;
+ Timer<EventSource> m_connectTimer;
Vector<UChar> m_receiveBuf;
bool m_discardTrailingNewline;
bool m_requestInFlight;