LCOV - code coverage report
Current view: top level - dom/indexedDB - FileSnapshot.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 164 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 43 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "FileSnapshot.h"
       8             : 
       9             : #include "IDBDatabase.h"
      10             : #include "IDBFileHandle.h"
      11             : #include "IDBMutableFile.h"
      12             : #include "mozilla/Assertions.h"
      13             : #include "nsIAsyncInputStream.h"
      14             : #include "nsICloneableInputStream.h"
      15             : #include "nsIIPCSerializableInputStream.h"
      16             : 
      17             : namespace mozilla {
      18             : namespace dom {
      19             : namespace indexedDB {
      20             : 
      21             : using namespace mozilla::ipc;
      22             : 
      23             : namespace {
      24             : 
      25             : class StreamWrapper final
      26             :   : public nsIAsyncInputStream
      27             :   , public nsIInputStreamCallback
      28             :   , public nsICloneableInputStream
      29             :   , public nsIIPCSerializableInputStream
      30             : {
      31             :   class CloseRunnable;
      32             : 
      33             :   nsCOMPtr<nsIEventTarget> mOwningThread;
      34             :   nsCOMPtr<nsIInputStream> mInputStream;
      35             :   RefPtr<IDBFileHandle> mFileHandle;
      36             :   bool mFinished;
      37             : 
      38             :   // This is needed to call OnInputStreamReady() with the correct inputStream.
      39             :   nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
      40             : 
      41             : public:
      42           0 :   StreamWrapper(nsIInputStream* aInputStream,
      43             :                 IDBFileHandle* aFileHandle)
      44           0 :     : mOwningThread(aFileHandle->GetMutableFile()->Database()->EventTarget())
      45             :     , mInputStream(aInputStream)
      46             :     , mFileHandle(aFileHandle)
      47           0 :     , mFinished(false)
      48             :   {
      49           0 :     AssertIsOnOwningThread();
      50           0 :     MOZ_ASSERT(aInputStream);
      51           0 :     MOZ_ASSERT(aFileHandle);
      52           0 :     aFileHandle->AssertIsOnOwningThread();
      53             : 
      54           0 :     mFileHandle->OnNewRequest();
      55           0 :   }
      56             : 
      57             : private:
      58             :   virtual ~StreamWrapper();
      59             : 
      60             :   bool
      61           0 :   IsOnOwningThread() const
      62             :   {
      63           0 :     MOZ_ASSERT(mOwningThread);
      64             : 
      65             :     bool current;
      66           0 :     return NS_SUCCEEDED(mOwningThread->
      67           0 :                         IsOnCurrentThread(&current)) && current;
      68             :   }
      69             : 
      70             :   void
      71           0 :   AssertIsOnOwningThread() const
      72             :   {
      73           0 :     MOZ_ASSERT(IsOnOwningThread());
      74           0 :   }
      75             : 
      76             :   void
      77           0 :   Finish()
      78             :   {
      79           0 :     AssertIsOnOwningThread();
      80             : 
      81           0 :     if (mFinished) {
      82           0 :       return;
      83             :     }
      84             : 
      85           0 :     mFinished = true;
      86             : 
      87           0 :     mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
      88             :   }
      89             : 
      90             :   void
      91           0 :   Destroy()
      92             :   {
      93           0 :     if (IsOnOwningThread()) {
      94           0 :       delete this;
      95           0 :       return;
      96             :     }
      97             : 
      98             :     RefPtr<Runnable> destroyRunnable =
      99           0 :       NewNonOwningRunnableMethod("StreamWrapper::Destroy",
     100             :                                  this,
     101           0 :                                  &StreamWrapper::Destroy);
     102             : 
     103           0 :     MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(destroyRunnable,
     104             :                                                 NS_DISPATCH_NORMAL));
     105             :   }
     106             : 
     107             :   bool
     108           0 :   IsCloneableInputStream() const
     109             :   {
     110             :     nsCOMPtr<nsICloneableInputStream> stream =
     111           0 :       do_QueryInterface(mInputStream);
     112           0 :     return !!stream;
     113             :   }
     114             : 
     115             :   bool
     116           0 :   IsIPCSerializableInputStream() const
     117             :   {
     118             :     nsCOMPtr<nsIIPCSerializableInputStream> stream =
     119           0 :       do_QueryInterface(mInputStream);
     120           0 :     return !!stream;
     121             :   }
     122             : 
     123             :   bool
     124           0 :   IsAsyncInputStream() const
     125             :   {
     126           0 :     nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
     127           0 :     return !!stream;
     128             :   }
     129             : 
     130             :   NS_DECL_THREADSAFE_ISUPPORTS
     131             :   NS_DECL_NSIINPUTSTREAM
     132             :   NS_DECL_NSIASYNCINPUTSTREAM
     133             :   NS_DECL_NSIINPUTSTREAMCALLBACK
     134             :   NS_DECL_NSICLONEABLEINPUTSTREAM
     135             :   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
     136             : };
     137             : 
     138             : class StreamWrapper::CloseRunnable final
     139             :   : public Runnable
     140             : {
     141             :   friend class StreamWrapper;
     142             : 
     143             :   RefPtr<StreamWrapper> mStreamWrapper;
     144             : 
     145             : public:
     146             :   NS_DECL_ISUPPORTS_INHERITED
     147             : 
     148             : private:
     149             :   explicit
     150           0 :   CloseRunnable(StreamWrapper* aStreamWrapper)
     151           0 :     : Runnable("StreamWrapper::CloseRunnable")
     152           0 :     , mStreamWrapper(aStreamWrapper)
     153           0 :   { }
     154             : 
     155           0 :   ~CloseRunnable()
     156           0 :   { }
     157             : 
     158             :   NS_IMETHOD
     159             :   Run() override;
     160             : };
     161             : 
     162             : } // anonymous namespace
     163             : 
     164           0 : BlobImplSnapshot::BlobImplSnapshot(BlobImpl* aFileImpl,
     165           0 :                                    IDBFileHandle* aFileHandle)
     166           0 :   : mBlobImpl(aFileImpl)
     167             : {
     168           0 :   MOZ_ASSERT(aFileImpl);
     169           0 :   MOZ_ASSERT(aFileHandle);
     170             : 
     171             :   mFileHandle =
     172           0 :     do_GetWeakReference(NS_ISUPPORTS_CAST(EventTarget*, aFileHandle));
     173           0 : }
     174             : 
     175           0 : BlobImplSnapshot::BlobImplSnapshot(BlobImpl* aFileImpl,
     176           0 :                                    nsIWeakReference* aFileHandle)
     177             :   : mBlobImpl(aFileImpl)
     178           0 :   , mFileHandle(aFileHandle)
     179             : {
     180           0 :   MOZ_ASSERT(aFileImpl);
     181           0 :   MOZ_ASSERT(aFileHandle);
     182           0 : }
     183             : 
     184           0 : BlobImplSnapshot::~BlobImplSnapshot()
     185             : {
     186           0 : }
     187             : 
     188           0 : NS_IMPL_ISUPPORTS_INHERITED(BlobImplSnapshot, BlobImpl, PIBlobImplSnapshot)
     189             : 
     190             : already_AddRefed<BlobImpl>
     191           0 : BlobImplSnapshot::CreateSlice(uint64_t aStart,
     192             :                               uint64_t aLength,
     193             :                               const nsAString& aContentType,
     194             :                               ErrorResult& aRv)
     195             : {
     196             :   RefPtr<BlobImpl> blobImpl =
     197           0 :     mBlobImpl->CreateSlice(aStart, aLength, aContentType, aRv);
     198             : 
     199           0 :   if (NS_WARN_IF(aRv.Failed())) {
     200           0 :     return nullptr;
     201             :   }
     202             : 
     203           0 :   blobImpl = new BlobImplSnapshot(blobImpl, mFileHandle);
     204           0 :   return blobImpl.forget();
     205             : }
     206             : 
     207             : void
     208           0 : BlobImplSnapshot::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
     209             : {
     210           0 :   nsCOMPtr<EventTarget> et = do_QueryReferent(mFileHandle);
     211           0 :   RefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
     212           0 :   if (!fileHandle || !fileHandle->IsOpen()) {
     213           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_INACTIVE_ERR);
     214           0 :     return;
     215             :   }
     216             : 
     217           0 :   nsCOMPtr<nsIInputStream> stream;
     218           0 :   mBlobImpl->GetInternalStream(getter_AddRefs(stream), aRv);
     219           0 :   if (NS_WARN_IF(aRv.Failed())) {
     220           0 :     return;
     221             :   }
     222             : 
     223           0 :   RefPtr<StreamWrapper> wrapper = new StreamWrapper(stream, fileHandle);
     224             : 
     225           0 :   wrapper.forget(aStream);
     226             : }
     227             : 
     228             : BlobImpl*
     229           0 : BlobImplSnapshot::GetBlobImpl() const
     230             : {
     231           0 :   nsCOMPtr<EventTarget> et = do_QueryReferent(mFileHandle);
     232           0 :   RefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
     233           0 :   if (!fileHandle || !fileHandle->IsOpen()) {
     234           0 :     return nullptr;
     235             :   }
     236             : 
     237           0 :   return mBlobImpl;
     238             : }
     239             : 
     240           0 : StreamWrapper::~StreamWrapper()
     241             : {
     242           0 :   AssertIsOnOwningThread();
     243             : 
     244           0 :   Finish();
     245           0 : }
     246             : 
     247           0 : NS_IMPL_ADDREF(StreamWrapper)
     248           0 : NS_IMPL_RELEASE_WITH_DESTROY(StreamWrapper, Destroy())
     249             : 
     250           0 : NS_INTERFACE_MAP_BEGIN(StreamWrapper)
     251           0 :   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
     252           0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
     253             :                                      IsAsyncInputStream())
     254           0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
     255             :                                      IsAsyncInputStream())
     256           0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream,
     257             :                                      IsCloneableInputStream())
     258           0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
     259             :                                      IsIPCSerializableInputStream())
     260           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
     261           0 : NS_INTERFACE_MAP_END
     262             : 
     263             : NS_IMETHODIMP
     264           0 : StreamWrapper::Close()
     265             : {
     266           0 :   RefPtr<CloseRunnable> closeRunnable = new CloseRunnable(this);
     267             : 
     268           0 :   MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(closeRunnable,
     269             :                                               NS_DISPATCH_NORMAL));
     270             : 
     271           0 :   return NS_OK;
     272             : }
     273             : 
     274             : NS_IMETHODIMP
     275           0 : StreamWrapper::Available(uint64_t* _retval)
     276             : {
     277           0 :   return mInputStream->Available(_retval);
     278             : }
     279             : 
     280             : NS_IMETHODIMP
     281           0 : StreamWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
     282             : {
     283           0 :   return mInputStream->Read(aBuf, aCount, _retval);
     284             : }
     285             : 
     286             : NS_IMETHODIMP
     287           0 : StreamWrapper::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
     288             :                             uint32_t aCount, uint32_t* _retval)
     289             : {
     290           0 :   return mInputStream->ReadSegments(aWriter, aClosure, aCount, _retval);
     291             : }
     292             : 
     293             : NS_IMETHODIMP
     294           0 : StreamWrapper::IsNonBlocking(bool* _retval)
     295             : {
     296           0 :   return mInputStream->IsNonBlocking(_retval);
     297             : }
     298             : 
     299             : void
     300           0 : StreamWrapper::Serialize(InputStreamParams& aParams,
     301             :                          FileDescriptorArray& aFileDescriptors)
     302             : {
     303             :   nsCOMPtr<nsIIPCSerializableInputStream> stream =
     304           0 :     do_QueryInterface(mInputStream);
     305             : 
     306           0 :   if (stream) {
     307           0 :     stream->Serialize(aParams, aFileDescriptors);
     308             :   }
     309           0 : }
     310             : 
     311             : bool
     312           0 : StreamWrapper::Deserialize(const InputStreamParams& aParams,
     313             :                            const FileDescriptorArray& aFileDescriptors)
     314             : {
     315           0 :   MOZ_CRASH("This method should never be called");
     316             :   return false;
     317             : }
     318             : 
     319             : Maybe<uint64_t>
     320           0 : StreamWrapper::ExpectedSerializedLength()
     321             : {
     322             :   nsCOMPtr<nsIIPCSerializableInputStream> stream =
     323           0 :     do_QueryInterface(mInputStream);
     324             : 
     325           0 :   if (stream) {
     326           0 :     return stream->ExpectedSerializedLength();
     327             :   }
     328           0 :   return Nothing();
     329             : }
     330             : 
     331             : NS_IMETHODIMP
     332           0 : StreamWrapper::CloseWithStatus(nsresult aStatus)
     333             : {
     334           0 :   nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
     335           0 :   if (!stream) {
     336           0 :     return NS_ERROR_NO_INTERFACE;
     337             :   }
     338             : 
     339           0 :   nsresult rv = stream->CloseWithStatus(aStatus);
     340           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     341           0 :     return rv;
     342             :   }
     343             : 
     344           0 :   return Close();
     345             : }
     346             : 
     347             : NS_IMETHODIMP
     348           0 : StreamWrapper::AsyncWait(nsIInputStreamCallback* aCallback,
     349             :                          uint32_t aFlags,
     350             :                          uint32_t aRequestedCount,
     351             :                          nsIEventTarget* aEventTarget)
     352             : {
     353           0 :   nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
     354           0 :   if (!stream) {
     355           0 :     return NS_ERROR_NO_INTERFACE;
     356             :   }
     357             : 
     358           0 :   if (mAsyncWaitCallback && aCallback) {
     359           0 :     return NS_ERROR_FAILURE;
     360             :   }
     361             : 
     362           0 :   mAsyncWaitCallback = aCallback;
     363             : 
     364           0 :   if (!mAsyncWaitCallback) {
     365           0 :     return NS_OK;
     366             :   }
     367             : 
     368           0 :   return stream->AsyncWait(this, aFlags, aRequestedCount, aEventTarget);
     369             : }
     370             : 
     371             : // nsIInputStreamCallback
     372             : 
     373             : NS_IMETHODIMP
     374           0 : StreamWrapper::OnInputStreamReady(nsIAsyncInputStream* aStream)
     375             : {
     376           0 :   nsCOMPtr<nsIAsyncInputStream> stream = do_QueryInterface(mInputStream);
     377           0 :   if (!stream) {
     378           0 :     return NS_ERROR_NO_INTERFACE;
     379             :   }
     380             : 
     381             :   // We have been canceled in the meanwhile.
     382           0 :   if (!mAsyncWaitCallback) {
     383           0 :     return NS_OK;
     384             :   }
     385             : 
     386           0 :   nsCOMPtr<nsIInputStreamCallback> callback;
     387           0 :   callback.swap(mAsyncWaitCallback);
     388             : 
     389           0 :   return callback->OnInputStreamReady(this);
     390             : }
     391             : 
     392             : // nsICloneableInputStream
     393             : 
     394             : NS_IMETHODIMP
     395           0 : StreamWrapper::GetCloneable(bool* aCloneable)
     396             : {
     397           0 :   nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mInputStream);
     398           0 :   if (!stream) {
     399           0 :     *aCloneable = false;
     400           0 :     return NS_ERROR_NO_INTERFACE;
     401             :   }
     402             : 
     403           0 :   return stream->GetCloneable(aCloneable);
     404             : }
     405             : 
     406             : NS_IMETHODIMP
     407           0 : StreamWrapper::Clone(nsIInputStream** aResult)
     408             : {
     409           0 :   nsCOMPtr<nsICloneableInputStream> stream = do_QueryInterface(mInputStream);
     410           0 :   if (!stream) {
     411           0 :     return NS_ERROR_NO_INTERFACE;
     412             :   }
     413             : 
     414           0 :   return stream->Clone(aResult);
     415             : }
     416             : 
     417           0 : NS_IMPL_ISUPPORTS_INHERITED0(StreamWrapper::CloseRunnable,
     418             :                              Runnable)
     419             : 
     420             : NS_IMETHODIMP
     421           0 : StreamWrapper::
     422             : CloseRunnable::Run()
     423             : {
     424           0 :   mStreamWrapper->Finish();
     425             : 
     426           0 :   return NS_OK;
     427             : }
     428             : 
     429             : } // namespace indexedDB
     430             : } // namespace dom
     431             : } // namespace mozilla

Generated by: LCOV version 1.13