Title: [163527] trunk
Revision
163527
Author
[email protected]
Date
2014-02-06 01:42:26 -0800 (Thu, 06 Feb 2014)

Log Message

[XHR] Ensure response return null when error flag is set for blob and arraybuffer
https://bugs.webkit.org/show_bug.cgi?id=127050

Patch by Youenn Fablet <[email protected]> on 2014-02-06
Reviewed by Alexey Proskuryakov.

Source/WebCore:

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):

LayoutTests:

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.

Modified Paths

Added Paths

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();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to