Bug 1043843 - Avoid accessing nsIDOMBlob from worker thread. r=dhylands, a=sledru
authorYuan Xulei <xyuan@mozilla.com>
Mon, 18 Aug 2014 12:00:06 +0800
changeset 217551 51b0a8fb8153502eb4989c739bb62af74199b0d6
parent 217550 83f0220caa1250e97cbb8cd9776ccc7777df680a
child 217552 952d3e6b4b610411c6ef39390e3af3d5ec8742ee
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdhylands, sledru
bugs1043843
milestone33.0a2
Bug 1043843 - Avoid accessing nsIDOMBlob from worker thread. r=dhylands, a=sledru
dom/filesystem/CreateFileTask.cpp
dom/filesystem/CreateFileTask.h
--- a/dom/filesystem/CreateFileTask.cpp
+++ b/dom/filesystem/CreateFileTask.cpp
@@ -26,25 +26,28 @@ uint32_t CreateFileTask::sOutputBufferSi
 CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
                                const nsAString& aPath,
                                nsIDOMBlob* aBlobData,
                                InfallibleTArray<uint8_t>& aArrayData,
                                bool replace,
                                ErrorResult& aRv)
   : FileSystemTaskBase(aFileSystem)
   , mTargetRealPath(aPath)
-  , mBlobData(aBlobData)
   , mReplace(replace)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   MOZ_ASSERT(aFileSystem);
   GetOutputBufferSize();
-  if (mBlobData) {
-    nsresult rv = mBlobData->GetInternalStream(getter_AddRefs(mBlobStream));
-    NS_WARN_IF(NS_FAILED(rv));
+  if (aBlobData) {
+    if (FileSystemUtils::IsParentProcess()) {
+      nsresult rv = aBlobData->GetInternalStream(getter_AddRefs(mBlobStream));
+      NS_WARN_IF(NS_FAILED(rv));
+    } else {
+      mBlobData = aBlobData;
+    }
   }
   mArrayData.SwapElements(aArrayData);
   nsCOMPtr<nsIGlobalObject> globalObject =
     do_QueryInterface(aFileSystem->GetWindow());
   if (!globalObject) {
     return;
   }
   mPromise = Promise::Create(globalObject, aRv);
@@ -69,26 +72,27 @@ CreateFileTask::CreateFileTask(FileSyste
   auto& data = aParam.data();
 
   if (data.type() == FileSystemFileDataValue::TArrayOfuint8_t) {
     mArrayData = data;
     return;
   }
 
   BlobParent* bp = static_cast<BlobParent*>(static_cast<PBlobParent*>(data));
-  mBlobData = bp->GetBlob();
-  MOZ_ASSERT(mBlobData, "mBlobData should not be null.");
-  nsresult rv = mBlobData->GetInternalStream(getter_AddRefs(mBlobStream));
+  nsCOMPtr<nsIDOMBlob> blobData = bp->GetBlob();
+  MOZ_ASSERT(blobData, "blobData should not be null.");
+  nsresult rv = blobData->GetInternalStream(getter_AddRefs(mBlobStream));
   NS_WARN_IF(NS_FAILED(rv));
 }
 
 CreateFileTask::~CreateFileTask()
 {
-  MOZ_ASSERT(!mPromise || NS_IsMainThread(),
-             "mPromise should be released on main thread!");
+  MOZ_ASSERT((!mPromise && !mBlobData) || NS_IsMainThread(),
+             "mPromise and mBlobData should be released on main thread!");
+
   if (mBlobStream) {
     mBlobStream->Close();
   }
 }
 
 already_AddRefed<Promise>
 CreateFileTask::GetPromise()
 {
@@ -278,30 +282,33 @@ CreateFileTask::Work()
 }
 
 void
 CreateFileTask::HandlerCallback()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
   if (mFileSystem->IsShutdown()) {
     mPromise = nullptr;
+    mBlobData = nullptr;
     return;
   }
 
   if (HasError()) {
     nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
       mErrorValue);
     mPromise->MaybeRejectBrokenly(domError);
     mPromise = nullptr;
+    mBlobData = nullptr;
     return;
   }
 
   nsCOMPtr<nsIDOMFile> file = new DOMFile(mTargetFileImpl);
   mPromise->MaybeResolve(file);
   mPromise = nullptr;
+  mBlobData = nullptr;
 }
 
 void
 CreateFileTask::GetPermissionAccessType(nsCString& aAccess) const
 {
   if (mReplace) {
     aAccess.AssignLiteral("write");
     return;
--- a/dom/filesystem/CreateFileTask.h
+++ b/dom/filesystem/CreateFileTask.h
@@ -61,17 +61,20 @@ protected:
 
 private:
   void
   GetOutputBufferSize() const;
 
   static uint32_t sOutputBufferSize;
   nsRefPtr<Promise> mPromise;
   nsString mTargetRealPath;
+
+  // Not thread-safe and should be released on main thread.
   nsCOMPtr<nsIDOMBlob> mBlobData;
+
   nsCOMPtr<nsIInputStream> mBlobStream;
   InfallibleTArray<uint8_t> mArrayData;
   bool mReplace;
 
   // This cannot be a DOMFile because this object is created on a different
   // thread and DOMFile is not thread-safe. Let's use the DOMFileImpl instead.
   nsRefPtr<DOMFileImpl> mTargetFileImpl;
 };