Bug 1359087 - Use IPCBlob in FileHandle - part 3 - Changes in IndexedDB StreamWrapper, r=janv
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 09 May 2017 22:35:42 +0200
changeset 357435 f4a5a1808b5f3b55362559c63cd135bb29a202fe
parent 357434 66fafc2b84cf145190468eee4e08de99e5934ad6
child 357436 c41c78005666c97303ef9fba04c34325f6452871
push id31792
push usercbook@mozilla.com
push dateWed, 10 May 2017 13:07:59 +0000
treeherdermozilla-central@ebbcdaa5b580 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanv
bugs1359087
milestone55.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 1359087 - Use IPCBlob in FileHandle - part 3 - Changes in IndexedDB StreamWrapper, r=janv
dom/indexedDB/FileSnapshot.cpp
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -3,37 +3,44 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FileSnapshot.h"
 
 #include "IDBFileHandle.h"
 #include "mozilla/Assertions.h"
+#include "nsIAsyncInputStream.h"
+#include "nsICloneableInputStream.h"
 #include "nsIIPCSerializableInputStream.h"
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 using namespace mozilla::ipc;
 
 namespace {
 
 class StreamWrapper final
-  : public nsIInputStream
+  : public nsIAsyncInputStream
+  , public nsIInputStreamCallback
+  , public nsICloneableInputStream
   , public nsIIPCSerializableInputStream
 {
   class CloseRunnable;
 
   nsCOMPtr<nsIEventTarget> mOwningThread;
   nsCOMPtr<nsIInputStream> mInputStream;
   RefPtr<IDBFileHandle> mFileHandle;
   bool mFinished;
 
+  // This is needed to call OnInputStreamReady() with the correct inputStream.
+  nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
+
 public:
   StreamWrapper(nsIInputStream* aInputStream,
                 IDBFileHandle* aFileHandle)
     : mOwningThread(aFileHandle->GetMutableFile()->Database()->EventTarget())
     , mInputStream(aInputStream)
     , mFileHandle(aFileHandle)
     , mFinished(false)
   {
@@ -90,18 +97,44 @@ private:
       NewNonOwningRunnableMethod("StreamWrapper::Destroy",
                                  this,
                                  &StreamWrapper::Destroy);
 
     MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(destroyRunnable,
                                                 NS_DISPATCH_NORMAL));
   }
 
+  bool
+  IsCloneableInputStream() const
+  {
+    nsCOMPtr<nsICloneableInputStream> stream =
+      do_QueryInterface(mInputStream);
+    return !!stream;
+  }
+
+  bool
+  IsIPCSerializableInputStream() const
+  {
+    nsCOMPtr<nsIIPCSerializableInputStream> stream =
+      do_QueryInterface(mInputStream);
+    return !!stream;
+  }
+
+  bool
+  IsAsyncInputStream() const
+  {
+    nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
+    return !!stream;
+  }
+
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
+  NS_DECL_NSIASYNCINPUTSTREAM
+  NS_DECL_NSIINPUTSTREAMCALLBACK
+  NS_DECL_NSICLONEABLEINPUTSTREAM
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
 };
 
 class StreamWrapper::CloseRunnable final
   : public Runnable
 {
   friend class StreamWrapper;
 
@@ -206,55 +239,57 @@ StreamWrapper::~StreamWrapper()
 {
   AssertIsOnOwningThread();
 
   Finish();
 }
 
 NS_IMPL_ADDREF(StreamWrapper)
 NS_IMPL_RELEASE_WITH_DESTROY(StreamWrapper, Destroy())
-NS_IMPL_QUERY_INTERFACE(StreamWrapper,
-                        nsIInputStream,
-                        nsIIPCSerializableInputStream)
+
+NS_INTERFACE_MAP_BEGIN(StreamWrapper)
+  NS_INTERFACE_MAP_ENTRY(nsIInputStream)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
+                                     IsAsyncInputStream())
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
+                                     IsAsyncInputStream())
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
+                                     IsCloneableInputStream())
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
+                                     IsIPCSerializableInputStream())
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
+NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
 StreamWrapper::Close()
 {
-  MOZ_ASSERT(!IsOnOwningThread());
-
   RefPtr<CloseRunnable> closeRunnable = new CloseRunnable(this);
 
   MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(closeRunnable,
                                               NS_DISPATCH_NORMAL));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 StreamWrapper::Available(uint64_t* _retval)
 {
-  // Can't assert here, this method is sometimes called on the owning thread
-  // (nsInputStreamChannel::OpenContentStream calls Available before setting
-  // the content length property).
-
   return mInputStream->Available(_retval);
 }
 
 NS_IMETHODIMP
 StreamWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
 {
-  MOZ_ASSERT(!IsOnOwningThread());
   return mInputStream->Read(aBuf, aCount, _retval);
 }
 
 NS_IMETHODIMP
 StreamWrapper::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
                             uint32_t aCount, uint32_t* _retval)
 {
-  MOZ_ASSERT(!IsOnOwningThread());
   return mInputStream->ReadSegments(aWriter, aClosure, aCount, _retval);
 }
 
 NS_IMETHODIMP
 StreamWrapper::IsNonBlocking(bool* _retval)
 {
   return mInputStream->IsNonBlocking(_retval);
 }
@@ -270,38 +305,118 @@ StreamWrapper::Serialize(InputStreamPara
     stream->Serialize(aParams, aFileDescriptors);
   }
 }
 
 bool
 StreamWrapper::Deserialize(const InputStreamParams& aParams,
                            const FileDescriptorArray& aFileDescriptors)
 {
-  nsCOMPtr<nsIIPCSerializableInputStream> stream =
-    do_QueryInterface(mInputStream);
-
-  if (stream) {
-    return stream->Deserialize(aParams, aFileDescriptors);
-  }
-
+  MOZ_CRASH("This method should never be called");
   return false;
 }
 
 Maybe<uint64_t>
 StreamWrapper::ExpectedSerializedLength()
 {
   nsCOMPtr<nsIIPCSerializableInputStream> stream =
     do_QueryInterface(mInputStream);
 
   if (stream) {
     return stream->ExpectedSerializedLength();
   }
   return Nothing();
 }
 
+NS_IMETHODIMP
+StreamWrapper::CloseWithStatus(nsresult aStatus)
+{
+  nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
+  if (!stream) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  nsresult rv = stream->CloseWithStatus(aStatus);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return Close();
+}
+
+NS_IMETHODIMP
+StreamWrapper::AsyncWait(nsIInputStreamCallback* aCallback,
+                         uint32_t aFlags,
+                         uint32_t aRequestedCount,
+                         nsIEventTarget* aEventTarget)
+{
+  nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
+  if (!stream) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  if (mAsyncWaitCallback && aCallback) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mAsyncWaitCallback = aCallback;
+
+  if (!mAsyncWaitCallback) {
+    return NS_OK;
+  }
+
+  return stream->AsyncWait(this, aFlags, aRequestedCount, aEventTarget);
+}
+
+// nsIInputStreamCallback
+
+NS_IMETHODIMP
+StreamWrapper::OnInputStreamReady(nsIAsyncInputStream* aStream)
+{
+  nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
+  if (!stream) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  // We have been canceled in the meanwhile.
+  if (!mAsyncWaitCallback) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIInputStreamCallback> callback;
+  callback.swap(mAsyncWaitCallback);
+
+  return callback->OnInputStreamReady(this);
+}
+
+// nsICloneableInputStream
+
+NS_IMETHODIMP
+StreamWrapper::GetCloneable(bool* aCloneable)
+{
+  nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mInputStream);
+  if (!stream) {
+    *aCloneable = false;
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  return stream->GetCloneable(aCloneable);
+}
+
+NS_IMETHODIMP
+StreamWrapper::Clone(nsIInputStream** aResult)
+{
+  nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mInputStream);
+  if (!stream) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  return stream->Clone(aResult);
+}
+
 NS_IMPL_ISUPPORTS_INHERITED0(StreamWrapper::CloseRunnable,
                              Runnable)
 
 NS_IMETHODIMP
 StreamWrapper::
 CloseRunnable::Run()
 {
   mStreamWrapper->Finish();