b=572522; add experimental mozArrayBuffer to XHR; r=jst, a=bsmedberg
authorVladimir Vukicevic <vladimir@pobox.com>
Sat, 14 Aug 2010 10:52:19 -0700
changeset 50604 b0a91fbddbff33e29e0c2e9448b64239433dcbce
parent 50603 2e12374d22853c3b6017b50fc01193f78633d633
child 50605 7b9c03096aa1071c027fa02101cf541d41f303dc
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst, bsmedberg
bugs572522
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=572522; add experimental mozArrayBuffer to XHR; r=jst, a=bsmedberg
content/base/public/nsIXMLHttpRequest.idl
content/base/src/nsXMLHttpRequest.cpp
content/base/test/Makefile.in
content/base/test/file_XHR_binary1.bin
content/base/test/file_XHR_binary1.bin^headers^
content/base/test/test_XHR.html
dom/src/threads/nsDOMWorkerXHR.cpp
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -42,16 +42,21 @@ interface nsIDOMDocument;
 interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
 interface nsIURI;
 interface nsIVariant;
 interface nsPIDOMWindow;
 interface nsIInputStream;
 
+%{C++
+// for jsval
+#include "jsapi.h"
+%}
+
 [scriptable, uuid(6ce0a193-b033-4c3d-b748-f851b09261f5)]
 interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
   // event handler attributes
   attribute nsIDOMEventListener onabort;
   attribute nsIDOMEventListener onerror;
   attribute nsIDOMEventListener onload;
   attribute nsIDOMEventListener onloadstart;
   attribute nsIDOMEventListener onprogress;
@@ -129,16 +134,22 @@ interface nsIXMLHttpRequest : nsISupport
 
   /**
    * The response to the request as text.
    * NULL if the request is unsuccessful or
    * has not yet been sent.
    */
   readonly attribute AString responseText;
 
+  /**
+   * The response to the request as a typed array ArrayBuffer.
+   * NULL if the request is unsuccessful or
+   * has not yet been sent.
+   */
+  readonly attribute jsval /*ArrayBuffer*/ mozResponseArrayBuffer;
 
   /**
    * The status of the response to the request for HTTP requests.
    */
   readonly attribute unsigned long status;
 
   /**
    * The string representing the status of the response for
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -95,16 +95,17 @@
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsAsyncRedirectVerifyHelper.h"
+#include "jstypedarray.h"
 
 #define LOAD_STR "load"
 #define ERROR_STR "error"
 #define ABORT_STR "abort"
 #define LOADSTART_STR "loadstart"
 #define PROGRESS_STR "progress"
 #define UPLOADPROGRESS_STR "uploadprogress"
 #define READYSTATE_STR "readystatechange"
@@ -1229,16 +1230,45 @@ NS_IMETHODIMP nsXMLHttpRequest::GetRespo
   if (mState & (XML_HTTP_REQUEST_COMPLETED |
                 XML_HTTP_REQUEST_INTERACTIVE)) {
     rv = ConvertBodyToText(aResponseText);
   }
 
   return rv;
 }
 
+/* readonly attribute jsval (ArrayBuffer) mozResponseArrayBuffer; */
+NS_IMETHODIMP nsXMLHttpRequest::GetMozResponseArrayBuffer(jsval *aResult)
+{
+  JSContext *cx = nsContentUtils::GetCurrentJSContext();
+  if (!cx)
+    return NS_ERROR_FAILURE;
+
+  if (!(mState & (XML_HTTP_REQUEST_COMPLETED |
+                  XML_HTTP_REQUEST_INTERACTIVE))) {
+    *aResult = JSVAL_NULL;
+    return NS_OK;
+  }
+
+  PRInt32 dataLen = mResponseBody.Length();
+  JSObject *obj = js_CreateArrayBuffer(cx, dataLen);
+  if (!obj)
+    return NS_ERROR_FAILURE;
+
+  *aResult = OBJECT_TO_JSVAL(obj);
+
+  if (dataLen > 0) {
+    js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(obj);
+    NS_ASSERTION(abuf, "What happened?");
+    memcpy(abuf->data, mResponseBody.BeginReading(), dataLen);
+  }
+
+  return NS_OK;
+}
+
 /* readonly attribute unsigned long status; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetStatus(PRUint32 *aStatus)
 {
   *aStatus = 0;
 
   if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
     // Make sure we don't leak status information from denied cross-site
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -205,16 +205,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug429157.html \
 		test_XHR.html \
 		file_XHR_pass1.xml \
 		file_XHR_pass2.txt \
 		file_XHR_pass3.txt \
 		file_XHR_pass3.txt^headers^ \
 		file_XHR_fail1.txt \
 		file_XHR_fail1.txt^headers^ \
+		file_XHR_binary1.bin \
+		file_XHR_binary1.bin^headers^ \
 		test_bug428847.html \
 		file_bug428847-1.xhtml \
 		file_bug428847-2.xhtml \
 		test_bug431701.html \
 		test_bug431833.html \
 		test_bug435425.html \
 		bug435425.sjs \
 		bug435425_redirect.sjs \
new file mode 100644
index 0000000000000000000000000000000000000000..39e527bfc33b57fd176d1f4b75829d44462de848
GIT binary patch
literal 12
Qc${1Hj)D0<5bOp505gpUga7~l
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_XHR_binary1.bin^headers^
@@ -0,0 +1,1 @@
+Content-Type: application/binary
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -54,12 +54,43 @@ for (i = 0; i < failFiles.length; ++i) {
   if (!didthrow) {
     is(xhr.status, 301, "wrong status");
     is(xhr.responseText, "redirect file\n", "wrong response");
   }
   else {
     ok(1, "should have thrown or given incorrect result");
   }
 }
+
+// test mozResponseArrayBuffer
+
+// with a simple text file
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_pass2.txt', false); 
+xhr.send(null);
+is(xhr.status, 200, "wrong status");
+ab = xhr.mozResponseArrayBuffer;
+ok(ab != null, "should have a non-null arraybuffer");
+is(ab.byteLength, "hello pass\n".length, "wrong arraybuffer byteLength");
+
+u8v = new Uint8Array(ab);
+ok(String.fromCharCode([u8v[0], u8v[1], u8v[2], u8v[3], u8v[4]]), "hello", "wrong values");
+
+// with a binary file
+xhr = new XMLHttpRequest();
+xhr.open("GET", 'file_XHR_binary1.bin', false); 
+xhr.send(null)
+is(xhr.status, 200, "wrong status");
+ab = xhr.mozResponseArrayBuffer;
+ok(ab != null, "should have a non-null arraybuffer");
+is(ab.byteLength, 12, "wrong arraybuffer byteLength");
+
+u8v = new Uint8Array(ab);
+i32v = new Int32Array(ab);
+u32v = new Uint32Array(ab, 8);
+ok(u8v[0] == 0xaa && u8v[1] == 0xee && u8v[2] == 0x00 && u8v[3] == 0x03, "wrong initial 4 bytes");
+is(i32v[1], -1, "wrong value, expected -1 (0xffffffff)");
+is(u32v[0], 0xbbbbbbbb, "wrong value, expected 0xbbbbbbbb");
+
 </script>
 </pre>
 </body>
 </html>
--- a/dom/src/threads/nsDOMWorkerXHR.cpp
+++ b/dom/src/threads/nsDOMWorkerXHR.cpp
@@ -884,8 +884,15 @@ nsDOMWorkerXHR::SetWithCredentials(PRBoo
     return NS_ERROR_ABORT;
   }
 
   nsresult rv = mXHRProxy->SetWithCredentials(aWithCredentials);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
+
+/* readonly attribute jsval (ArrayBuffer) mozResponseArrayBuffer; */
+NS_IMETHODIMP
+nsDOMWorkerXHR::GetMozResponseArrayBuffer(jsval *aResult)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}