Diff
Modified: trunk/LayoutTests/ChangeLog (163526 => 163527)
--- trunk/LayoutTests/ChangeLog 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/LayoutTests/ChangeLog 2014-02-06 09:42:26 UTC (rev 163527)
@@ -1,3 +1,25 @@
+2014-02-06 Youenn Fablet <[email protected]>
+
+ [XHR] Ensure response return null when error flag is set for blob and arraybuffer
+ https://bugs.webkit.org/show_bug.cgi?id=127050
+
+ Reviewed by Alexey Proskuryakov.
+
+ Added test cases that check XHR response in case of timeout and abort for arraybuffer, blob, document and json.
+
+ * fast/files/script-tests/xhr-response-blob.js: updated to expect null for blob response in case of XHR requesting a file that does not exist
+ (.xhr.onreadystatechange):
+ (.xhr.onerror):
+ (.xhr.onload):
+ (.xhr.onloadend):
+ (testBlob):
+ * fast/files/xhr-response-blob-expected.txt:
+ * http/tests/resources/load-then-wait.cgi: Added (similar to load-and-stall except that it sends the whole document and then wait for some time before completing the response).
+ * http/tests/xmlhttprequest/onabort-response-getters-expected.txt: Added.
+ * http/tests/xmlhttprequest/onabort-response-getters.html: Added.
+ * http/tests/xmlhttprequest/ontimeout-response-getters-expected.txt: Added.
+ * http/tests/xmlhttprequest/ontimeout-response-getters.html: Added.
+
2014-02-05 Brady Eidson <[email protected]>
IDB: storage/indexeddb/mozilla/autoincrement-indexes.html fails
Modified: trunk/LayoutTests/fast/files/script-tests/xhr-response-blob.js (163526 => 163527)
--- trunk/LayoutTests/fast/files/script-tests/xhr-response-blob.js 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/LayoutTests/fast/files/script-tests/xhr-response-blob.js 2014-02-06 09:42:26 UTC (rev 163527)
@@ -10,12 +10,17 @@
shouldBeEqualToString("xhr.responseType", "blob");
xhr.send();
xhr._onreadystatechange_ = function() {
- if (xhr.readyState != 4) {
+ if (xhr.readyState != xhr.DONE)
shouldBeNull("xhr.response");
- return;
- }
+ }
+ xhr._onerror_ = function() {
+ shouldBeNull("xhr.response");
+ };
+ xhr._onload_ = function() {
shouldBeTrue("xhr.response instanceof Blob");
shouldBeEqualToString("xhr.response.type", blobType);
+ };
+ xhr._onloadend_ = function() {
doneFunction();
}
}
Modified: trunk/LayoutTests/fast/files/xhr-response-blob-expected.txt (163526 => 163527)
--- trunk/LayoutTests/fast/files/xhr-response-blob-expected.txt 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/LayoutTests/fast/files/xhr-response-blob-expected.txt 2014-02-06 09:42:26 UTC (rev 163527)
@@ -12,8 +12,7 @@
PASS xhr.response instanceof Blob is true
PASS xhr.response.type is "text/plain"
PASS xhr.responseType is "blob"
-PASS xhr.response instanceof Blob is true
-PASS xhr.response.type is ""
+PASS xhr.response is null
PASS xhr.responseType is "blob"
PASS xhr.response is null
PASS xhr.response instanceof Blob is true
Added: trunk/LayoutTests/http/tests/resources/load-then-wait.cgi (0 => 163527)
--- trunk/LayoutTests/http/tests/resources/load-then-wait.cgi (rev 0)
+++ trunk/LayoutTests/http/tests/resources/load-then-wait.cgi 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+use CGI;
+use File::stat;
+use Time::HiRes;
+
+$query = new CGI;
+$name = $query->param('name');
+$waitFor = $query->param('waitFor');
+$mimeType = $query->param('mimeType');
+
+my $filesize = stat($name)->size;
+print "Content-type: " . $mimeType . "\n";
+print "Content-Length: " . $filesize . "\n\n";
+
+open FILE, $name or die;
+binmode FILE;
+$total = 0;
+my ($buf, $data, $n);
+while (($n = read FILE, $data, 1024) != 0) {
+ $total += $n;
+ print $data;
+}
+close(FILE);
+if (defined $waitFor) {
+ Time::HiRes::sleep($waitFor)
+}
+
Property changes on: trunk/LayoutTests/http/tests/resources/load-then-wait.cgi
___________________________________________________________________
Added: svn:executable
Added: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt (0 => 163527)
--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters-expected.txt 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,6 @@
+
+PASS getting arraybuffer response within abort event callback
+PASS getting blob response within abort event callback
+PASS getting json response within abort event callback
+PASS getting document response within abort event callback
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html (0 => 163527)
--- trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/onabort-response-getters.html 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,74 @@
+<html>
+ <head>
+ <title>XMLHttpRequest: blob, arraybuffer and document response getters should return null in case of abort</title>
+ <script src=""
+ <script src=""
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function runTest(name, fileName, mimeType, setupClient, checkResponse) {
+ var test = async_test(name)
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ var url = "" + fileName + "&waitFor=1&mimeType=" + mimeType
+ client.open("GET", url, true)
+ setupClient(test, client)
+ client.isAborting = false
+ client.hasAborted = false
+ client.isResponseChecked = false
+
+ client._onprogress_ = test.step_func(function (e) {
+ if (!client.isAborting && e.total == e.loaded) {
+ client.isAborting = true
+ client.abort()
+ }
+ })
+ client._onreadystatechange_ = test.step_func(function() {
+ if (client.readyState == 4) {
+ checkResponse(test, client)
+ client.isResponseChecked = true
+ }
+ })
+
+ client._onabort_ = test.step_func(function () {
+ client.hasAborted = true
+ })
+
+ client._onloadend_ = test.step_func(function () {
+ assert_true(client.hasAborted, "xhr should have aborted")
+ assert_true(client.isResponseChecked, "xhr response should have been checked")
+ test.done()
+ })
+ client.send(null)
+ })
+ }
+
+ runTest("getting arraybuffer response within abort event callback",
+ "onabort-response-getters.html","text/html",
+ function(test, client) {client.responseType = "arraybuffer"},
+ function(test, client) {assert_true(client.response == null, "arraybuffer response must be empty")}
+ )
+
+ runTest("getting blob response within abort event callback",
+ "onabort-response-getters.html","text/html",
+ function(test, client) {client.responseType = "blob"},
+ function(test, client) {assert_true(client.response == null, "blob response must be empty")}
+ )
+
+ runTest("getting json response within abort event callback",
+ "resources/test.json","text/plain",
+ function(test, client) {client.responseType = "json"},
+ function(test, client) {assert_true(client.response == null, "json response must be empty")}
+ )
+
+ runTest("getting document response within abort event callback",
+ "resources/test.xml","text/xml",
+ function(test, client) {client.responseType = "document"},
+ function(test, client) {assert_true(client.response == null, "document response must be empty")}
+ )
+
+ </script>
+ </body>
+</html>
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters-expected.txt (0 => 163527)
--- trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters-expected.txt 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,6 @@
+
+PASS getting arraybuffer response within timeout event callback
+PASS getting blob response within timeout event callback
+PASS getting json response within timeout event callback
+PASS getting document response within timeout event callback
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters.html (0 => 163527)
--- trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters.html (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/ontimeout-response-getters.html 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: blob, arraybuffer and document response getters should return null in case of timeout error</title>
+ <script src=""
+ <script src=""
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function runTest(name, fileName, mimeType, setupClient, checkResponse) {
+ var test = async_test(name)
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.timeout = 10
+ var url = "" + fileName + "&waitFor=0.1&mimeType=" + mimeType
+ client.open("GET", url, true)
+ setupClient(test, client)
+ client.hasTimedout = false;
+ client._ontimeout_ = test.step_func(function () {
+ checkResponse(test, client)
+ client.hasTimedout = true
+ })
+ client._onloadend_ = test.step_func(function () {
+ assert_true(client.hasTimedout, "xhr should have timed out")
+ test.done()
+ })
+ client.send(null)
+ })
+ }
+
+ runTest("getting arraybuffer response within timeout event callback",
+ "ontimeout-response-getters.html","text/html",
+ function(test, client) {client.responseType = "arraybuffer"},
+ function(test, client) {assert_true(client.response == null, "arraybuffer response must be empty")}
+ )
+
+ runTest("getting blob response within timeout event callback",
+ "ontimeout-response-getters.html","text/html",
+ function(test, client) {client.responseType = "blob"},
+ function(test, client) {assert_true(client.response == null, "blob response must be empty")}
+ )
+
+ runTest("getting json response within timeout event callback",
+ "resources/test.json","text/plain",
+ function(test, client) {client.responseType = "json"},
+ function(test, client) {assert_true(client.response == null, "json response must be empty")}
+ )
+
+ runTest("getting document response within timeout event callback",
+ "resources/test.xml","text/xml",
+ function(test, client) {client.responseType = "document"},
+ function(test, client) {assert_true(client.response == null, "document response must be empty")}
+ )
+ </script>
+ </body>
+</html>
+
Added: trunk/LayoutTests/http/tests/xmlhttprequest/resources/test.xml (0 => 163527)
--- trunk/LayoutTests/http/tests/xmlhttprequest/resources/test.xml (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/resources/test.xml 2014-02-06 09:42:26 UTC (rev 163527)
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<test/>
+
Modified: trunk/Source/WebCore/ChangeLog (163526 => 163527)
--- trunk/Source/WebCore/ChangeLog 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/Source/WebCore/ChangeLog 2014-02-06 09:42:26 UTC (rev 163527)
@@ -1,3 +1,27 @@
+2014-02-06 Youenn Fablet <[email protected]>
+
+ [XHR] Ensure response return null when error flag is set for blob and arraybuffer
+ https://bugs.webkit.org/show_bug.cgi?id=127050
+
+ Reviewed by Alexey Proskuryakov.
+
+ Added a check in JSXMLHttpRequest::response to ensure response return null when error flag is set for blob and arraybuffer
+ This check also applies to document and json response types (no change in behavior for those types but code path change)
+ Added assertions in the related XMLHttpRequest blob and array buffer getters
+ Minor code clean-up.
+ The test cases check all four response types in case of timeout and abort
+
+ Tests: http/tests/xmlhttprequest/onabort-response-getters.html
+ http/tests/xmlhttprequest/ontimeout-response-getters.html
+
+ * bindings/js/JSXMLHttpRequestCustom.cpp:
+ (WebCore::JSXMLHttpRequest::response):
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::didCacheResponseJSON):
+ (WebCore::XMLHttpRequest::responseXML):
+ (WebCore::XMLHttpRequest::responseBlob):
+ (WebCore::XMLHttpRequest::responseArrayBuffer):
+
2014-02-05 Gavin Barraclough <[email protected]>
Change Page, FocusController to use ViewState
Modified: trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp (163526 => 163527)
--- trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp 2014-02-06 09:42:26 UTC (rev 163527)
@@ -190,6 +190,13 @@
JSValue JSXMLHttpRequest::response(ExecState* exec) const
{
+ // FIXME: Use CachedAttribute for other types than JSON as well.
+ if (m_response && impl().responseCacheIsValid())
+ return m_response.get();
+
+ if (!impl().doneWithoutErrors() && impl().responseTypeCode() > XMLHttpRequest::ResponseTypeText)
+ return jsNull();
+
switch (impl().responseTypeCode()) {
case XMLHttpRequest::ResponseTypeDefault:
case XMLHttpRequest::ResponseTypeText:
@@ -197,13 +204,6 @@
case XMLHttpRequest::ResponseTypeJSON:
{
- // FIXME: Use CachedAttribute for other types as well.
- if (m_response && impl().responseCacheIsValid())
- return m_response.get();
-
- if (!impl().doneWithoutErrors())
- return jsNull();
-
JSValue value = JSONParse(exec, impl().responseTextIgnoringResponseType());
if (!value)
value = jsNull();
Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (163526 => 163527)
--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp 2014-02-06 09:01:29 UTC (rev 163526)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp 2014-02-06 09:42:26 UTC (rev 163527)
@@ -241,7 +241,8 @@
void XMLHttpRequest::didCacheResponseJSON()
{
- ASSERT(m_responseTypeCode == ResponseTypeJSON && doneWithoutErrors());
+ ASSERT(m_responseTypeCode == ResponseTypeJSON);
+ ASSERT(doneWithoutErrors());
m_responseCacheIsValid = true;
m_responseBuilder.clear();
}
@@ -250,11 +251,11 @@
{
if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
ec = INVALID_STATE_ERR;
- return 0;
+ return nullptr;
}
if (!doneWithoutErrors())
- return 0;
+ return nullptr;
if (!m_createdDocument) {
bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html");
@@ -285,11 +286,8 @@
Blob* XMLHttpRequest::responseBlob()
{
ASSERT(m_responseTypeCode == ResponseTypeBlob);
+ ASSERT(doneWithoutErrors());
- // We always return null before DONE.
- if (m_state != DONE)
- return 0;
-
if (!m_responseBlob) {
// FIXME: This causes two (or more) unnecessary copies of the data.
// Chromium stores blob data in the browser process, so we're pulling the data
@@ -319,10 +317,8 @@
ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
{
ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer);
+ ASSERT(doneWithoutErrors());
- if (m_state != DONE)
- return 0;
-
if (!m_responseArrayBuffer) {
if (m_binaryResponseBuilder)
m_responseArrayBuffer = m_binaryResponseBuilder->createArrayBuffer();