Bug 1373222 - MutableBlobStorage always returns a temporary-file Blob if the size of data is greater than 1mb. r=smaug, a=jcristau
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 20 Jun 2017 13:27:59 +0200
changeset 414052 b54b431ba47cea6c7cdde680b410fbe3e2215983
parent 414051 bd2df31d88f07e468c460beee82397ba0d0256cb
child 414053 9dd0df149c5220a1808373954d6e03dee9a92b08
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, jcristau
bugs1373222
milestone55.0
Bug 1373222 - MutableBlobStorage always returns a temporary-file Blob if the size of data is greater than 1mb. r=smaug, a=jcristau
dom/file/MutableBlobStorage.cpp
dom/file/MutableBlobStorage.h
--- a/dom/file/MutableBlobStorage.cpp
+++ b/dom/file/MutableBlobStorage.cpp
@@ -418,16 +418,24 @@ MutableBlobStorage::GetBlobWhenReady(nsI
     // this is to go to the I/O thread and then we come back: the runnables are
     // executed in order and this LastRunnable will be... the last one.
     RefPtr<Runnable> runnable =
       new LastRunnable(this, aParent, aContentType, aCallback);
     DispatchToIOThread(runnable.forget());
     return mDataLen;
   }
 
+  // If we are waiting for the temporary file, it's better to wait...
+  if (previousState == eWaitingForTemporaryFile) {
+    mPendingParent = aParent;
+    mPendingContentType = aContentType;
+    mPendingCallback = aCallback;
+    return mDataLen;
+  }
+
   RefPtr<BlobImpl> blobImpl;
 
   if (mData) {
     blobImpl = new MemoryBlobImpl(mData, mDataLen,
                                   NS_ConvertUTF8toUTF16(aContentType));
 
     mData = nullptr; // The MemoryBlobImpl takes ownership of the buffer
     mDataLen = 0;
@@ -569,33 +577,59 @@ MutableBlobStorage::MaybeCreateTemporary
 }
 
 void
 MutableBlobStorage::TemporaryFileCreated(PRFileDesc* aFD)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mStorageState == eWaitingForTemporaryFile ||
              mStorageState == eClosed);
+  MOZ_ASSERT_IF(mPendingCallback, mStorageState == eClosed);
 
-  if (mStorageState == eClosed) {
+  // If the object has been already closed and we don't need to execute a
+  // callback, we need just to close the file descriptor in the correct thread.
+  if (mStorageState == eClosed && !mPendingCallback) {
     RefPtr<Runnable> runnable = new CloseFileRunnable(aFD);
     DispatchToIOThread(runnable.forget());
     return;
   }
 
-  mStorageState = eInTemporaryFile;
+  // If we still receiving data, we can proceed in temporary-file mode.
+  if (mStorageState == eWaitingForTemporaryFile) {
+    mStorageState = eInTemporaryFile;
+  }
+
   mFD = aFD;
 
+  // This runnable takes the ownership of mData and it will write this buffer
+  // into the temporary file.
   RefPtr<WriteRunnable> runnable =
     WriteRunnable::AdoptBuffer(this, mFD, mData, mDataLen);
   MOZ_ASSERT(runnable);
 
   mData = nullptr;
 
   DispatchToIOThread(runnable.forget());
+
+  // If we are closed, it means that GetBlobWhenReady() has been called when we
+  // were already waiting for a temporary file-descriptor. Finally we are here,
+  // AdoptBuffer runnable is going to write the current buffer into this file.
+  // After that, there is nothing else to write, and we dispatch LastRunnable
+  // which ends up calling mPendingCallback via CreateBlobRunnable.
+  if (mStorageState == eClosed) {
+    MOZ_ASSERT(mPendingCallback);
+
+    RefPtr<Runnable> runnable =
+      new LastRunnable(this, mPendingParent, mPendingContentType,
+                       mPendingCallback);
+    DispatchToIOThread(runnable.forget());
+
+    mPendingParent = nullptr;
+    mPendingCallback = nullptr;
+  }
 }
 
 void
 MutableBlobStorage::CreateBlobAndRespond(already_AddRefed<nsISupports> aParent,
                                          const nsACString& aContentType,
                                          already_AddRefed<MutableBlobStorageCallback> aCallback)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/file/MutableBlobStorage.h
+++ b/dom/file/MutableBlobStorage.h
@@ -98,14 +98,18 @@ private:
   StorageState mStorageState;
 
   PRFileDesc* mFD;
 
   nsresult mErrorResult;
 
   RefPtr<TaskQueue> mTaskQueue;
   nsCOMPtr<nsIEventTarget> mEventTarget;
+
+  nsCOMPtr<nsISupports> mPendingParent;
+  nsCString mPendingContentType;
+  RefPtr<MutableBlobStorageCallback> mPendingCallback;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_MutableBlobStorage_h