Bug 1317725 -Correct creation of Sliced Remote Blob actorss when used in FormData in workers, r=smaug, a=gchang
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 16 Nov 2016 15:04:23 +0100
changeset 352621 5cac2e6569d00933d7bf9046cbf9f2a57203ab52
parent 352620 84bb1123f7774f00d63e01735894fcdfae07930d
child 352622 7f611a717df6bf178b2cab2da4ef8c005f80da8a
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, gchang
bugs1317725
milestone52.0a2
Bug 1317725 -Correct creation of Sliced Remote Blob actorss when used in FormData in workers, r=smaug, a=gchang
dom/base/StructuredCloneHolder.cpp
dom/ipc/Blob.cpp
dom/workers/test/mochitest.ini
dom/workers/test/script_bug1301094.js
dom/workers/test/script_createFile.js
dom/workers/test/test_bug1301094.html
dom/workers/test/test_bug1317725.html
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -858,21 +858,29 @@ ReadFormData(JSContext* aCx,
       }
 
       if (tag == SCTAG_DOM_BLOB) {
         MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length());
 
         RefPtr<BlobImpl> blobImpl =
           aHolder->BlobImpls()[indexOrLengthOfString];
 
+        ErrorResult rv;
+        blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          rv.SuppressException();
+          return nullptr;
+        }
+
+        MOZ_ASSERT(blobImpl);
+
         RefPtr<Blob> blob =
           Blob::Create(aHolder->ParentDuringRead(), blobImpl);
         MOZ_ASSERT(blob);
 
-        ErrorResult rv;
         formData->Append(name, *blob, thirdArg, rv);
         if (NS_WARN_IF(rv.Failed())) {
           rv.SuppressException();
           return nullptr;
         }
 
       } else if (tag == SCTAG_DOM_DIRECTORY) {
         RefPtr<Directory> directory =
@@ -955,17 +963,25 @@ WriteFormData(JSStructuredCloneWriter* a
           void* aClosure)
     {
       Closure* closure = static_cast<Closure*>(aClosure);
       if (!WriteString(closure->mWriter, aName)) {
         return false;
       }
 
       if (aValue.IsBlob()) {
-        BlobImpl* blobImpl = aValue.GetAsBlob()->Impl();
+        ErrorResult rv;
+        RefPtr<BlobImpl> blobImpl =
+          EnsureBlobForBackgroundManager(aValue.GetAsBlob()->Impl(), nullptr,
+                                         rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          rv.SuppressException();
+          return false;
+        }
+
         if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB,
                                 closure->mHolder->BlobImpls().Length())) {
           return false;
         }
 
         closure->mHolder->BlobImpls().AppendElement(blobImpl);
         return true;
       }
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -2247,17 +2247,16 @@ RemoteBlobImpl::RemoteBlobImpl(const nsA
 }
 
 void
 BlobChild::
 RemoteBlobImpl::CommonInit(BlobChild* aActor)
 {
   MOZ_ASSERT(aActor);
   aActor->AssertIsOnOwningThread();
-  MOZ_ASSERT(!mIsSlice);
 
   mActor = aActor;
   mActorTarget = aActor->EventTarget();
 
   if (!NS_IsMainThread()) {
     mWorkerPrivate = GetCurrentThreadWorkerPrivate();
     // We must comunicate via IPC in the owning thread, so, if this BlobImpl has
     // been created on a Workerr and then it's sent to a different thread (for
@@ -2747,22 +2746,26 @@ RemoteBlobSliceImpl::EnsureActorWasCreat
   ParentBlobConstructorParams params(
     SlicedBlobConstructorParams(nullptr /* sourceParent */,
                                 baseActor /* sourceChild */,
                                 id /* id */,
                                 mStart /* begin */,
                                 mStart + mLength /* end */,
                                 mContentType /* contentType */));
 
+  BlobChild* actor;
+
   if (nsIContentChild* contentManager = baseActor->GetContentManager()) {
-    mActor = SendSliceConstructor(contentManager, this, params);
+    actor = SendSliceConstructor(contentManager, this, params);
   } else {
-    mActor =
+    actor =
       SendSliceConstructor(baseActor->GetBackgroundManager(), this, params);
   }
+
+  CommonInit(actor);
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(BlobChild::RemoteBlobSliceImpl,
                              BlobChild::RemoteBlobImpl)
 
 BlobChild*
 BlobChild::
 RemoteBlobSliceImpl::GetBlobChild()
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -99,17 +99,17 @@ support-files =
   websocket_https.html
   websocket_https_worker.js
   worker_fileReader.js
   fileapi_chromeScript.js
   importScripts_3rdParty_worker.js
   worker_bug1278777.js
   worker_setTimeoutWith0.js
   worker_bug1301094.js
-  script_bug1301094.js
+  script_createFile.js
   worker_suspended.js
   window_suspended.html
   !/dom/base/test/file_websocket_basic_wsh.py
   !/dom/base/test/file_websocket_hello_wsh.py
   !/dom/base/test/file_websocket_http_resource.txt
   !/dom/base/test/file_websocket_permessage_deflate_disabled_wsh.py
   !/dom/base/test/file_websocket_permessage_deflate_params_wsh.py
   !/dom/base/test/file_websocket_permessage_deflate_rejected_wsh.py
@@ -218,8 +218,9 @@ skip-if = toolkit == 'android' #bug 9828
 [test_sharedWorker_ports.html]
 [test_sharedWorker_lifetime.html]
 [test_fileReader.html]
 [test_navigator_workers_hardwareConcurrency.html]
 [test_bug1278777.html]
 [test_setTimeoutWith0.html]
 [test_bug1301094.html]
 [test_subworkers_suspended.html]
+[test_bug1317725.html]
rename from dom/workers/test/script_bug1301094.js
rename to dom/workers/test/script_createFile.js
--- a/dom/workers/test/test_bug1301094.html
+++ b/dom/workers/test/test_bug1301094.html
@@ -11,17 +11,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301094">Mozilla Bug 1301094</a>
   <input id="file" type="file"></input>
   <script type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
-var url = SimpleTest.getTestFileURL("script_bug1301094.js");
+var url = SimpleTest.getTestFileURL("script_createFile.js");
 script = SpecialPowers.loadChromeScript(url);
 
 var mainThreadOk, workerOk;
 
 function maybeFinish() {
   if (mainThreadOk & workerOk) {
     SimpleTest.finish();
   }
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_bug1317725.html
@@ -0,0 +1,62 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for bug 1317725</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<input type="file" id="file" />
+
+<script type="text/js-worker" id="worker-src">
+onmessage = function(e) {
+  var data = new FormData();
+  data.append('Filedata', e.data.slice(0, 127), encodeURI(e.data.name));
+  var xhr = new XMLHttpRequest();
+  xhr.open('POST', location.href, false);
+  xhr.send(data);
+  postMessage("No crash \\o/");
+}
+</script>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var url = SimpleTest.getTestFileURL("script_createFile.js");
+script = SpecialPowers.loadChromeScript(url);
+
+function onOpened(message) {
+  var input = document.getElementById('file');
+  SpecialPowers.wrap(input).mozSetFileArray([message.data]);
+
+  var blob = new Blob([ document.getElementById("worker-src").textContent ],
+                      { type: "text/javascript" });
+  var worker = new Worker(URL.createObjectURL(blob));
+  worker.onerror = function(e) {
+    ok(false, "We should not see any error.");
+    SimpleTest.finish();
+  }
+
+  worker.onmessage = function(e) {
+    ok(e.data, "Everything seems OK on the worker-side.");
+    SimpleTest.finish();
+  }
+
+  is(input.files.length, 1, "We have something");
+  ok(input.files[0] instanceof Blob, "We have one Blob");
+  worker.postMessage(input.files[0]);
+}
+
+script.addMessageListener("file.opened", onOpened);
+script.sendAsyncMessage("file.open");
+
+</script>
+</pre>
+</body>
+</html>