EventSource should support CORS

https://bugs.webkit.org/show_bug.cgi?id=61862

Patch by Per-Erik Brodin <per-erik.brodin@ericsson.com> on 2012-12-18
Reviewed by Alexey Proskuryakov.

Source/WebCore:

Enabled CORS in EventSource with optional constructor argument to
indicate whether credentials should be included or not, as per the spec.
Added didFailAccessControlCheck to ThreadableLoaderClient to be able to
properly distinguish CORS failures from other errors.

Tests: http/tests/eventsource/eventsource-cors-basic.html
       http/tests/eventsource/eventsource-cors-no-server.html
       http/tests/eventsource/eventsource-cors-with-credentials.html

* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest):
(WebCore::DocumentThreadableLoader::didReceiveResponse):
(WebCore::DocumentThreadableLoader::preflightFailure):
* loader/ThreadableLoaderClient.h:
(WebCore::ThreadableLoaderClient::didFailAccessControlCheck):
* loader/ThreadableLoaderClientWrapper.h:
(WebCore::ThreadableLoaderClientWrapper::didFailAccessControlCheck):
(ThreadableLoaderClientWrapper):
* loader/WorkerThreadableLoader.cpp:
(WebCore::workerContextDidFailAccessControlCheck):
(WebCore):
(WebCore::WorkerThreadableLoader::MainThreadBridge::didFailAccessControlCheck):
* loader/WorkerThreadableLoader.h:
(MainThreadBridge):
* page/EventSource.cpp:
(WebCore::EventSource::EventSource):
(WebCore::EventSource::create):
(WebCore::EventSource::connect):
(WebCore::EventSource::withCredentials):
(WebCore):
(WebCore::EventSource::didReceiveResponse):
(WebCore::EventSource::didFailAccessControlCheck):
(WebCore::EventSource::didFailRedirectCheck):
(WebCore::EventSource::abortConnectionAttempt):
(WebCore::EventSource::parseEventStreamLine):
(WebCore::EventSource::createMessageEvent):
* page/EventSource.h:
(WebCore):
(EventSource):
(WebCore::EventSource::refEventTarget):
(WebCore::EventSource::derefEventTarget):
* page/EventSource.idl:

LayoutTests:

Added new CORS tests for EventSource. Modified existing test to verify
that the new constructor argument can be passed to the constructor.

* fast/eventsource/eventsource-constructor-expected.txt:
* fast/eventsource/eventsource-constructor.html:
* fast/js/constructor-length.html:
* http/tests/eventsource/eventsource-cors-basic-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-basic.html: Added.
* http/tests/eventsource/eventsource-cors-no-server-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-no-server.html: Added.
* http/tests/eventsource/eventsource-cors-with-credentials-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-with-credentials.html: Added.
* http/tests/eventsource/resources/es-cors-basic.php: Added.
* http/tests/eventsource/resources/es-cors-credentials.php: Added.
* platform/blackberry/fast/js/constructor-length-expected.txt:
* platform/chromium/fast/js/constructor-length-expected.txt:
* platform/gtk/fast/js/constructor-length-expected.txt:
* platform/mac/fast/js/constructor-length-expected.txt:
* platform/qt/fast/js/constructor-length-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@138083 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 561d3c1c
2012-12-18 Per-Erik Brodin <per-erik.brodin@ericsson.com>
EventSource should support CORS
https://bugs.webkit.org/show_bug.cgi?id=61862
Reviewed by Alexey Proskuryakov.
Added new CORS tests for EventSource. Modified existing test to verify
that the new constructor argument can be passed to the constructor.
* fast/eventsource/eventsource-constructor-expected.txt:
* fast/eventsource/eventsource-constructor.html:
* fast/js/constructor-length.html:
* http/tests/eventsource/eventsource-cors-basic-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-basic.html: Added.
* http/tests/eventsource/eventsource-cors-no-server-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-no-server.html: Added.
* http/tests/eventsource/eventsource-cors-with-credentials-expected.txt: Added.
* http/tests/eventsource/eventsource-cors-with-credentials.html: Added.
* http/tests/eventsource/resources/es-cors-basic.php: Added.
* http/tests/eventsource/resources/es-cors-credentials.php: Added.
* platform/blackberry/fast/js/constructor-length-expected.txt:
* platform/chromium/fast/js/constructor-length-expected.txt:
* platform/gtk/fast/js/constructor-length-expected.txt:
* platform/mac/fast/js/constructor-length-expected.txt:
* platform/qt/fast/js/constructor-length-expected.txt:
2012-12-18 Yuki Sekiguchi <yuki.sekiguchi@access-company.com>
Cannot click an element at 2nd line or more inside inline-block in vertical writing mode.
......@@ -3,5 +3,6 @@ Test EventSource constructor functionality. Should print a series of PASS messag
PASS: missing argument to EventSource constructor resulted in an exception (TypeError: Not enough arguments)
PASS: passing an empty string to the EventSource constructor resulted in an exception (Error: SyntaxError: DOM Exception 12)
PASS: passing an invalid URL to the EventSource constructor resulted in an exception (Error: SyntaxError: DOM Exception 12)
PASS: no exception when passing a second argument to the EventSource constructor
DONE
......@@ -34,7 +34,19 @@ try {
}
catch (ex) {
log("PASS: passing an invalid URL to the EventSource constructor resulted in an exception (" + ex + ")");
log("DONE");
}
try {
var es = new EventSource("http://127.0.0.1/", {"withCredentials": false});
es.close();
if (!es.withCredentials) {
log("PASS: no exception when passing a second argument to the EventSource constructor");
log("DONE");
} else
log("FAIL: the 'withCredentials' property is unexpectedly true");
}
catch (ex) {
log("FAIL: passing a second argument to the EventSource constructor resulted in an exception (" + ex + ")");
}
if (window.testRunner)
......
......@@ -18,7 +18,7 @@ shouldBe('DOMParser.length', '0');
shouldBe('DataView.length', '3');
shouldBe('ErrorEvent.length', '2');
shouldBe('Event.length', '2');
shouldBe('EventSource.length', '1');
shouldBe('EventSource.length', '2');
shouldBe('Float32Array.length', '1');
shouldBe('Float64Array.length', '1');
shouldBe('FileReader.length', '0');
......
CONSOLE MESSAGE: EventSource cannot load http://localhost:8000/eventsource/resources/es-cors-basic.php?count=1. Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
CONSOLE MESSAGE: EventSource cannot load http://localhost:8000/eventsource/resources/es-cors-basic.php?count=2. Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
Test that basic EventSource cross-origin requests fail until they are allowed by the Access-Control-Allow-Origin header. 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 cross-origin message event with data "DATA1" and lastEventId "77"
PASS: got cross-origin message event with data "DATA2"
DONE
<html>
<body>
<p>Test that basic EventSource cross-origin requests fail until they are allowed by the Access-Control-Allow-Origin header. Should print a series of PASS messages followed by DONE.</p>
<div id="result"></div>
<script>
function log(msg) {
document.getElementById("result").innerHTML += msg + "<br>";
}
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function end() {
if (window.testRunner)
testRunner.notifyDone();
}
var count = 1;
var base_url = location.href.substr(0, location.href.lastIndexOf('/')).replace("127.0.0.1", "localhost");
function create_es() {
try {
var es = new EventSource(base_url + "/resources/es-cors-basic.php?count=" + count);
}
catch (ex) {
log("FAIL: EventSource constructor threw exception: " + ex);
end();
return;
}
if (es.withCredentials) {
log("FAIL: withCredentials is true");
es.close();
end();
}
es.onerror = function () {
if (es.readyState == es.CLOSED) {
if (count != 3 && count != 4) {
log("PASS: got error event and readyState is CLOSED");
count++;
setTimeout(create_es);
}
else {
log("FAIL: got unexpected error event");
end();
}
}
else if (count != 4) {
log("FAIL: got error event but readyState is not CLOSED");
es.close();
end();
}
};
es.onmessage = function (evt) {
if (evt.origin != location.origin && !evt.origin.indexOf("http://localhost")) {
if (count == 3 && evt.data == "DATA1" && evt.lastEventId == "77") {
log("PASS: got cross-origin message event with data \"DATA1\" and lastEventId \"77\"");
count++;
return;
}
if (count == 4 && evt.data == "DATA2") {
log("PASS: got cross-origin message event with data \"DATA2\"");
log("DONE");
}
else
log("FAIL: got unexpected cross-origin message event");
}
else
log("FAIL: got message event from same or unexpected origin");
es.close();
end();
};
}
create_es();
</script>
</body>
</html>
Test that EventSource tries to reconnect if there's no server response when making cross-origin requests. Should print a series of PASS messages followed by DONE.
PASS: got error event and readyState is CONNECTING
<html>
<body>
<p>Test that EventSource tries to reconnect if there's no server response when making cross-origin requests. Should print a series of PASS messages followed by DONE.</p>
<div id="result"></div>
<script>
function log(msg) {
document.getElementById("result").innerHTML += msg + "<br>";
}
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function end() {
if (window.testRunner)
testRunner.notifyDone();
}
var count = 0;
var hosts = ["http://127.0.0.1:12345/event-stream", "http://localhost:54321/event-stream"];
function create_es() {
try {
var es = new EventSource(hosts[count]);
}
catch (ex) {
log("FAIL: EventSource constructor threw exception: " + ex);
end();
return;
}
es.onerror = function () {
if (es.readyState == es.CONNECTING) {
log("PASS: got error event and readyState is CONNECTING");
es.close();
end();
return;
}
if (es.readyState == es.CLOSED)
log("FAIL: got error event but readyState is CLOSED");
if (++count == hosts.length) {
log("DONE");
end();
}
else
setTimeout(create_es);
};
}
create_es();
</script>
</body>
</html>
CONSOLE MESSAGE: EventSource cannot load http://localhost:8000/eventsource/resources/es-cors-credentials.php?count=1. Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.
CONSOLE MESSAGE: EventSource cannot load http://localhost:8000/eventsource/resources/es-cors-credentials.php?count=2. Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.
CONSOLE MESSAGE: EventSource cannot load http://localhost:8000/eventsource/resources/es-cors-credentials.php?count=3. Credentials flag is true, but Access-Control-Allow-Credentials is not "true".
Test that EventSource cross-origin requests with credentials fail until the correct CORS headers are sent. 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 cross-origin message event with data "DATA1" and lastEventId "77"
PASS: got cross-origin message event with data "DATA2"
DONE
<html>
<body>
<p>Test that EventSource cross-origin requests with credentials fail until the correct CORS headers are sent. Should print a series of PASS messages followed by DONE.</p>
<div id="result"></div>
<script>
function log(msg) {
document.getElementById("result").innerHTML += msg + "<br>";
}
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
function end() {
if (window.testRunner)
testRunner.notifyDone();
}
var count = 1;
var base_url = location.href.substr(0, location.href.lastIndexOf('/')).replace("127.0.0.1", "localhost");
function create_es() {
try {
var es = new EventSource(base_url + "/resources/es-cors-credentials.php?count=" + count, {"withCredentials": true});
}
catch (ex) {
log("FAIL: EventSource constructor threw exception: " + ex);
end();
return;
}
if (!es.withCredentials) {
log("FAIL: withCredentials is false");
es.close();
end();
}
es.onerror = function () {
if (es.readyState == es.CLOSED) {
if (count != 4 && count != 5) {
log("PASS: got error event and readyState is CLOSED");
count++;
setTimeout(create_es);
}
else {
log("FAIL: got unexpected error event");
end();
}
}
else if (count != 5) {
log("FAIL: got error event but readyState is not CLOSED");
es.close();
end();
}
};
es.onmessage = function (evt) {
if (evt.origin != location.origin && !evt.origin.indexOf("http://localhost")) {
if (count == 4 && evt.data == "DATA1" && evt.lastEventId == "77") {
log("PASS: got cross-origin message event with data \"DATA1\" and lastEventId \"77\"");
count++;
return;
}
if (count == 5 && evt.data == "DATA2") {
log("PASS: got cross-origin message event with data \"DATA2\"");
log("DONE");
}
else
log("FAIL: got unexpected cross-origin message event");
}
else
log("FAIL: got message event from same or unexpected origin");
es.close();
end();
};
}
create_es();
</script>
</body>
</html>
<?php
if ($_SERVER["REQUEST_METHOD"] == "OPTIONS")
die("Got unexpected preflight request");
header("Content-Type: text/event-stream");
$count = intval($_GET["count"]);
if ($count == 2)
header("Access-Control-Allow-Origin: http://some.other.origin:80");
else if ($count == 3)
header("Access-Control-Allow-Origin: *");
else if ($count > 3)
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
if ($_SERVER["HTTP_LAST_EVENT_ID"] != "77")
echo "id: 77\ndata: DATA1\nretry: 0\n\n";
else
echo "data: DATA2\n\n";
?>
<?php
if ($_SERVER["REQUEST_METHOD"] == "OPTIONS")
die("Got unexpected preflight request");
header("Content-Type: text/event-stream");
$count = intval($_GET["count"]);
if ($count == 1 || $count == 2)
header("Access-Control-Allow-Origin: *");
else if ($count > 2)
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
if ($count == 2 || $count > 3)
header("Access-Control-Allow-Credentials: true");
if ($_SERVER["HTTP_LAST_EVENT_ID"] != "77")
echo "id: 77\ndata: DATA1\nretry: 0\n\n";
else
echo "data: DATA2\n\n";
?>
......@@ -14,7 +14,7 @@ PASS DOMParser.length is 0
PASS DataView.length is 3
PASS ErrorEvent.length is 2
PASS Event.length is 2
PASS EventSource.length is 1
PASS EventSource.length is 2
PASS Float32Array.length is 1
PASS Float64Array.length is 1
PASS FileReader.length is 0
......
......@@ -14,7 +14,7 @@ PASS DOMParser.length is 0
FAIL DataView.length should be 3. Was 0.
FAIL ErrorEvent.length should be 2. Was 0.
FAIL Event.length should be 2. Was 0.
FAIL EventSource.length should be 1. Was 0.
FAIL EventSource.length should be 2. Was 0.
FAIL Float32Array.length should be 1. Was 0.
FAIL Float64Array.length should be 1. Was 0.
PASS FileReader.length is 0
......
......@@ -14,7 +14,7 @@ PASS DOMParser.length is 0
PASS DataView.length is 3
PASS ErrorEvent.length is 2
PASS Event.length is 2
PASS EventSource.length is 1
PASS EventSource.length is 2
PASS Float32Array.length is 1
PASS Float64Array.length is 1
PASS FileReader.length is 0
......
......@@ -14,7 +14,7 @@ PASS DOMParser.length is 0
PASS DataView.length is 3
PASS ErrorEvent.length is 2
PASS Event.length is 2
PASS EventSource.length is 1
PASS EventSource.length is 2
PASS Float32Array.length is 1
PASS Float64Array.length is 1
PASS FileReader.length is 0
......
......@@ -14,7 +14,7 @@ PASS DOMParser.length is 0
PASS DataView.length is 3
PASS ErrorEvent.length is 2
PASS Event.length is 2
PASS EventSource.length is 1
PASS EventSource.length is 2
PASS Float32Array.length is 1
PASS Float64Array.length is 1
PASS FileReader.length is 0
......
2012-12-18 Per-Erik Brodin <per-erik.brodin@ericsson.com>
EventSource should support CORS
https://bugs.webkit.org/show_bug.cgi?id=61862
Reviewed by Alexey Proskuryakov.
Enabled CORS in EventSource with optional constructor argument to
indicate whether credentials should be included or not, as per the spec.
Added didFailAccessControlCheck to ThreadableLoaderClient to be able to
properly distinguish CORS failures from other errors.
Tests: http/tests/eventsource/eventsource-cors-basic.html
http/tests/eventsource/eventsource-cors-no-server.html
http/tests/eventsource/eventsource-cors-with-credentials.html
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest):
(WebCore::DocumentThreadableLoader::didReceiveResponse):
(WebCore::DocumentThreadableLoader::preflightFailure):
* loader/ThreadableLoaderClient.h:
(WebCore::ThreadableLoaderClient::didFailAccessControlCheck):
* loader/ThreadableLoaderClientWrapper.h:
(WebCore::ThreadableLoaderClientWrapper::didFailAccessControlCheck):
(ThreadableLoaderClientWrapper):
* loader/WorkerThreadableLoader.cpp:
(WebCore::workerContextDidFailAccessControlCheck):
(WebCore):
(WebCore::WorkerThreadableLoader::MainThreadBridge::didFailAccessControlCheck):
* loader/WorkerThreadableLoader.h:
(MainThreadBridge):
* page/EventSource.cpp:
(WebCore::EventSource::EventSource):
(WebCore::EventSource::create):
(WebCore::EventSource::connect):
(WebCore::EventSource::withCredentials):
(WebCore):
(WebCore::EventSource::didReceiveResponse):
(WebCore::EventSource::didFailAccessControlCheck):
(WebCore::EventSource::didFailRedirectCheck):
(WebCore::EventSource::abortConnectionAttempt):
(WebCore::EventSource::parseEventStreamLine):
(WebCore::EventSource::createMessageEvent):
* page/EventSource.h:
(WebCore):
(EventSource):
(WebCore::EventSource::refEventTarget):
(WebCore::EventSource::derefEventTarget):
* page/EventSource.idl:
2012-12-18 Michael Pruett <michael@68k.org>
IndexedDB: Implement custom bindings for parsing options
......@@ -127,7 +127,7 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource
// Cross-origin requests are only allowed for HTTP and registered schemes. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) {
m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are only supported for HTTP."));
m_client->didFailAccessControlCheck(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are only supported for HTTP."));
return;
}
......@@ -274,7 +274,7 @@ void DocumentThreadableLoader::didReceiveResponse(unsigned long identifier, cons
} else {
if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
if (!passesAccessControlCheck(response, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)) {
m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, response.url().string(), accessControlErrorDescription));
m_client->didFailAccessControlCheck(ResourceError(errorDomainWebKitInternal, 0, response.url().string(), accessControlErrorDescription));
return;
}
}
......@@ -352,7 +352,7 @@ void DocumentThreadableLoader::preflightSuccess()
void DocumentThreadableLoader::preflightFailure(const String& url, const String& errorDescription)
{
m_actualRequest = nullptr; // Prevent didFinishLoading() from bypassing access check.
m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, url, errorDescription));
m_client->didFailAccessControlCheck(ResourceError(errorDomainWebKitInternal, 0, url, errorDescription));
}
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck)
......
......@@ -47,6 +47,7 @@ namespace WebCore {
virtual void didReceiveCachedMetadata(const char*, int /*dataLength*/) { }
virtual void didFinishLoading(unsigned long /*identifier*/, double /*finishTime*/) { }
virtual void didFail(const ResourceError&) { }
virtual void didFailAccessControlCheck(const ResourceError& error) { didFail(error); }
virtual void didFailRedirectCheck() { }
virtual bool isDocumentThreadableLoaderClient() { return false; }
......
......@@ -94,6 +94,13 @@ public:
m_client->didFail(error);
}
void didFailAccessControlCheck(const ResourceError& error)
{
m_done = true;
if (m_client)
m_client->didFailAccessControlCheck(error);
}
void didFailRedirectCheck()
{
m_done = true;
......
......@@ -238,6 +238,17 @@ void WorkerThreadableLoader::MainThreadBridge::didFail(const ResourceError& erro
m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFail, m_workerClientWrapper, error), m_taskMode);
}
static void workerContextDidFailAccessControlCheck(ScriptExecutionContext* context, PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, const ResourceError& error)
{
ASSERT_UNUSED(context, context->isWorkerContext());
workerClientWrapper->didFailAccessControlCheck(error);
}
void WorkerThreadableLoader::MainThreadBridge::didFailAccessControlCheck(const ResourceError& error)
{
m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFailAccessControlCheck, m_workerClientWrapper, error), m_taskMode);
}
static void workerContextDidFailRedirectCheck(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper)
{
ASSERT_UNUSED(context, context->isWorkerContext());
......
......@@ -118,6 +118,7 @@ namespace WebCore {
virtual void didReceiveCachedMetadata(const char*, int dataLength);
virtual void didFinishLoading(unsigned long identifier, double finishTime);
virtual void didFail(const ResourceError&);
virtual void didFailAccessControlCheck(const ResourceError&);
virtual void didFailRedirectCheck();
// Only to be used on the main thread.
......
/*
* Copyright (C) 2009 Ericsson AB
* All rights reserved.
* Copyright (C) 2009, 2012 Ericsson AB. All rights reserved.
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Copyright (C) 2011, Code Aurora Forum. All rights reserved.
*
......@@ -36,6 +35,7 @@
#include "ContentSecurityPolicy.h"
#include "DOMWindow.h"
#include "Dictionary.h"
#include "Event.h"
#include "EventException.h"
#include "ExceptionCode.h"
......@@ -56,20 +56,21 @@ namespace WebCore {
const unsigned long long EventSource::defaultReconnectDelay = 3000;
inline EventSource::EventSource(const KURL& url, ScriptExecutionContext* context)
inline EventSource::EventSource(ScriptExecutionContext* context, const KURL& url, const Dictionary& eventSourceInit)
: ActiveDOMObject(context, this)
, m_url(url)
, m_withCredentials(false)
, m_state(CONNECTING)
, m_decoder(TextResourceDecoder::create("text/plain", "UTF-8"))
, m_reconnectTimer(this, &EventSource::reconnectTimerFired)
, m_discardTrailingNewline(false)
, m_requestInFlight(false)
, m_reconnectDelay(defaultReconnectDelay)
, m_origin(context->securityOrigin()->toString())
{
eventSourceInit.get("withCredentials", m_withCredentials);
}
PassRefPtr<EventSource> EventSource::create(ScriptExecutionContext* context, const String& url, ExceptionCode& ec)
PassRefPtr<EventSource> EventSource::create(ScriptExecutionContext* context, const String& url, const Dictionary& eventSourceInit, ExceptionCode& ec)
{
if (url.isEmpty()) {
ec = SYNTAX_ERR;
......@@ -82,19 +83,13 @@ PassRefPtr<EventSource> EventSource::create(ScriptExecutionContext* context, con
return 0;
}
// FIXME: Should support at least some cross-origin requests.
if (!context->securityOrigin()->canRequest(fullURL)) {
ec = SECURITY_ERR;
return 0;
}
if (!context->contentSecurityPolicy()->allowConnectToSource(fullURL)) {
// FIXME: Should this be throwing an exception?
ec = SECURITY_ERR;
return 0;
}
RefPtr<EventSource> source = adoptRef(new EventSource(fullURL, context));
RefPtr<EventSource> source = adoptRef(new EventSource(context, fullURL, eventSourceInit));
source->setPendingActivity(source.get());
source->connect();
......@@ -121,11 +116,16 @@ void EventSource::connect()
if (!m_lastEventId.isEmpty())
request.setHTTPHeaderField("Last-Event-ID", m_lastEventId);