Bug 736686 - Part 2: Implement Blob constructor in Worker. r=jonas, bent
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Sat, 24 Mar 2012 12:33:59 +0100
changeset 94003 6009d836249f540739c89417a50922648a870f53
parent 94002 120e179a4af7ffae3c7d5df25f95ad0dacbe52fe
child 94004 2342271b2be16c50307a6b4f0257310fe010faa3
push id160
push userlsblakk@mozilla.com
push dateFri, 13 Jul 2012 18:18:57 +0000
treeherdermozilla-release@228ba1a111fc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonas, bent
bugs736686
milestone14.0a1
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
Bug 736686 - Part 2: Implement Blob constructor in Worker. r=jonas, bent
content/base/src/nsDOMBlobBuilder.cpp
content/base/src/nsDOMBlobBuilder.h
dom/workers/File.cpp
dom/workers/test/Makefile.in
dom/workers/test/test_blobConstructor.html
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -174,23 +174,39 @@ nsDOMMultipartFile::CreateSlice(PRUint64
 /* static */ nsresult
 nsDOMMultipartFile::NewBlob(nsISupports* *aNewObject)
 {
   nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMMultipartFile());
   file.forget(aNewObject);
   return NS_OK;
 }
 
+static nsIDOMBlob*
+GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
+  nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
+    nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
+  return blob;
+}
+
 NS_IMETHODIMP
 nsDOMMultipartFile::Initialize(nsISupports* aOwner,
                                JSContext* aCx,
                                JSObject* aObj,
                                PRUint32 aArgc,
                                jsval* aArgv)
 {
+  return InitInternal(aCx, aArgc, aArgv, GetXPConnectNative);
+}
+
+nsresult
+nsDOMMultipartFile::InitInternal(JSContext* aCx,
+                                 PRUint32 aArgc,
+                                 jsval* aArgv,
+                                 UnwrapFuncPtr aUnwrapFunc)
+{
   bool nativeEOL = false;
   if (aArgc > 1) {
     mozilla::dom::BlobPropertyBag d;
     nsresult rv = d.Init(aCx, &aArgv[1]);
     NS_ENSURE_SUCCESS(rv, rv);
     mContentType = d.type;
     if (d.endings.EqualsLiteral("native")) {
       nativeEOL = true;
@@ -216,18 +232,17 @@ nsDOMMultipartFile::Initialize(nsISuppor
     JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, &obj, &length));
     for (uint32_t i = 0; i < length; ++i) {
       jsval element;
       if (!JS_GetElement(aCx, &obj, i, &element))
         return NS_ERROR_INVALID_ARG;
 
       if (element.isObject()) {
         JSObject& obj = element.toObject();
-        nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
-          nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &obj));
+        nsCOMPtr<nsIDOMBlob> blob = aUnwrapFunc(aCx, &obj);
         if (blob) {
           // Flatten so that multipart blobs will never nest
           nsDOMFileBase* file = static_cast<nsDOMFileBase*>(
               static_cast<nsIDOMBlob*>(blob));
           const nsTArray<nsCOMPtr<nsIDOMBlob> >*
               subBlobs = file->GetSubBlobs();
           if (subBlobs) {
             blobSet.AppendBlobs(*subBlobs);
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -76,16 +76,22 @@ public:
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner,
                         JSContext* aCx,
                         JSObject* aObj,
                         PRUint32 aArgc,
                         jsval* aArgv);
 
+  typedef nsIDOMBlob* (*UnwrapFuncPtr)(JSContext*, JSObject*);
+  nsresult InitInternal(JSContext* aCx,
+                        PRUint32 aArgc,
+                        jsval* aArgv,
+                        UnwrapFuncPtr aUnwrapFunc);
+
   already_AddRefed<nsIDOMBlob>
   CreateSlice(PRUint64 aStart, PRUint64 aLength, const nsAString& aContentType);
 
   NS_IMETHOD GetSize(PRUint64*);
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
   // DOMClassInfo constructor (for Blob([b1, "foo"], { type: "image/png" }))
   static nsresult
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -35,16 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "File.h"
 
 #include "nsIDOMFile.h"
+#include "nsDOMBlobBuilder.h"
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsfriendapi.h"
 #include "nsCOMPtr.h"
 #include "nsJSUtils.h"
 #include "nsStringGlue.h"
 
@@ -52,16 +53,17 @@
 #include "WorkerInlines.h"
 #include "WorkerPrivate.h"
 
 #define PROPERTY_FLAGS \
   (JSPROP_ENUMERATE | JSPROP_SHARED)
 
 USING_WORKERS_NAMESPACE
 
+using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
 using mozilla::dom::workers::exceptions::ThrowFileExceptionForCode;
 
 namespace {
 
 class Blob
 {
   // Blob should never be instantiated.
   Blob();
@@ -105,22 +107,42 @@ private:
     }
 
     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          JS_GetClass(aObj)->name);
     return NULL;
   }
 
+  static nsIDOMBlob*
+  Unwrap(JSContext* aCx, JSObject* aObj)
+  {
+    return GetPrivate(aObj);
+  }
+
   static JSBool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
-    return false;
+    nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
+    nsresult rv = file->InitInternal(aCx, aArgc, JS_ARGV(aCx, aVp),
+                                     Unwrap);
+    if (NS_FAILED(rv)) {
+      ThrowDOMExceptionForCode(aCx,
+        NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM ?
+          NS_ERROR_GET_CODE(rv) : UNKNOWN_ERR);
+      return false;
+    }
+
+    JSObject* obj = file::CreateBlob(aCx, file);
+    if (!obj) {
+      return false;
+    }
+
+    JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(obj));
+    return true;
   }
 
   static void
   Finalize(JSContext* aCx, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMBlob* blob = GetPrivate(aObj);
--- a/dom/workers/test/Makefile.in
+++ b/dom/workers/test/Makefile.in
@@ -118,16 +118,17 @@ include $(topsrcdir)/config/rules.mk
   newError_worker.js \
   test_chromeWorker.html \
   WorkerTest_badworker.js \
   test_workersDisabled.html \
   workersDisabled_worker.js \
   test_xhr_implicit_cancel.html \
   xhr_implicit_cancel_worker.js \
   test_xhr_timeout.html \
+  test_blobConstructor.html \
   $(NULL)
 
 _SUBDIR_TEST_FILES = \
   relativeLoad_sub_worker.js \
   relativeLoad_sub_worker2.js \
   relativeLoad_sub_import.js \
   $(NULL)
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_blobConstructor.html
@@ -0,0 +1,59 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<!--
+Tests of DOM Worker Blob constructor
+-->
+<head>
+  <title>Test for DOM Worker Blob constructor</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+(function() {
+  onerror = function(e) {
+    ok(false, "Main Thread had an error: " + event.data);
+    SimpleTest.finish();
+  };
+  function f() {
+    onmessage = function(e) {
+      var b = new Blob([e.data, "World"],{});
+      var fr = new FileReaderSync();
+      postMessage(fr.readAsText(b));
+    };
+  }
+  var b = new Blob([f.toString(),"f();"]);
+  var u = URL.createObjectURL(b);
+  var w = new Worker(u);
+  w.onmessage = function(e) {
+    URL.revokeObjectURL(u);
+    is(e.data, fr.result);
+    SimpleTest.finish();
+  };
+  w.onerror = function(e) {
+    is(e.target, w);
+    ok(false, "Worker had an error: " + e.data);
+    SimpleTest.finish();
+  };
+
+  b = new Blob(["Hello, "]);
+  var fr = new FileReader();
+  fr.readAsText(new Blob([b, "World"],{}));
+  fr.onload = function() {
+    w.postMessage(b);
+  };
+  SimpleTest.waitForExplicitFinish();
+})();
+</script>
+</pre>
+</body>
+</html>