FileSnapshot.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "FileSnapshot.h"
  6. #include "IDBFileHandle.h"
  7. #include "mozilla/Assertions.h"
  8. #include "nsIIPCSerializableInputStream.h"
  9. namespace mozilla {
  10. namespace dom {
  11. namespace indexedDB {
  12. using namespace mozilla::ipc;
  13. namespace {
  14. class StreamWrapper final
  15. : public nsIInputStream
  16. , public nsIIPCSerializableInputStream
  17. {
  18. class CloseRunnable;
  19. nsCOMPtr<nsIEventTarget> mOwningThread;
  20. nsCOMPtr<nsIInputStream> mInputStream;
  21. RefPtr<IDBFileHandle> mFileHandle;
  22. bool mFinished;
  23. public:
  24. StreamWrapper(nsIInputStream* aInputStream,
  25. IDBFileHandle* aFileHandle)
  26. : mOwningThread(NS_GetCurrentThread())
  27. , mInputStream(aInputStream)
  28. , mFileHandle(aFileHandle)
  29. , mFinished(false)
  30. {
  31. AssertIsOnOwningThread();
  32. MOZ_ASSERT(aInputStream);
  33. MOZ_ASSERT(aFileHandle);
  34. aFileHandle->AssertIsOnOwningThread();
  35. mFileHandle->OnNewRequest();
  36. }
  37. private:
  38. virtual ~StreamWrapper();
  39. bool
  40. IsOnOwningThread() const
  41. {
  42. MOZ_ASSERT(mOwningThread);
  43. bool current;
  44. return NS_SUCCEEDED(mOwningThread->
  45. IsOnCurrentThread(&current)) && current;
  46. }
  47. void
  48. AssertIsOnOwningThread() const
  49. {
  50. MOZ_ASSERT(IsOnOwningThread());
  51. }
  52. void
  53. Finish()
  54. {
  55. AssertIsOnOwningThread();
  56. if (mFinished) {
  57. return;
  58. }
  59. mFinished = true;
  60. mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
  61. }
  62. void
  63. Destroy()
  64. {
  65. if (IsOnOwningThread()) {
  66. delete this;
  67. return;
  68. }
  69. nsCOMPtr<nsIRunnable> destroyRunnable =
  70. NewNonOwningRunnableMethod(this, &StreamWrapper::Destroy);
  71. MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(destroyRunnable,
  72. NS_DISPATCH_NORMAL));
  73. }
  74. NS_DECL_THREADSAFE_ISUPPORTS
  75. NS_DECL_NSIINPUTSTREAM
  76. NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
  77. };
  78. class StreamWrapper::CloseRunnable final
  79. : public Runnable
  80. {
  81. friend class StreamWrapper;
  82. RefPtr<StreamWrapper> mStreamWrapper;
  83. public:
  84. NS_DECL_ISUPPORTS_INHERITED
  85. private:
  86. explicit
  87. CloseRunnable(StreamWrapper* aStreamWrapper)
  88. : mStreamWrapper(aStreamWrapper)
  89. { }
  90. ~CloseRunnable()
  91. { }
  92. NS_IMETHOD
  93. Run() override;
  94. };
  95. } // anonymous namespace
  96. BlobImplSnapshot::BlobImplSnapshot(BlobImpl* aFileImpl,
  97. IDBFileHandle* aFileHandle)
  98. : mBlobImpl(aFileImpl)
  99. {
  100. MOZ_ASSERT(aFileImpl);
  101. MOZ_ASSERT(aFileHandle);
  102. mFileHandle =
  103. do_GetWeakReference(NS_ISUPPORTS_CAST(EventTarget*, aFileHandle));
  104. }
  105. BlobImplSnapshot::BlobImplSnapshot(BlobImpl* aFileImpl,
  106. nsIWeakReference* aFileHandle)
  107. : mBlobImpl(aFileImpl)
  108. , mFileHandle(aFileHandle)
  109. {
  110. MOZ_ASSERT(aFileImpl);
  111. MOZ_ASSERT(aFileHandle);
  112. }
  113. BlobImplSnapshot::~BlobImplSnapshot()
  114. {
  115. }
  116. NS_IMPL_ISUPPORTS_INHERITED(BlobImplSnapshot, BlobImpl, PIBlobImplSnapshot)
  117. already_AddRefed<BlobImpl>
  118. BlobImplSnapshot::CreateSlice(uint64_t aStart,
  119. uint64_t aLength,
  120. const nsAString& aContentType,
  121. ErrorResult& aRv)
  122. {
  123. RefPtr<BlobImpl> blobImpl =
  124. mBlobImpl->CreateSlice(aStart, aLength, aContentType, aRv);
  125. if (NS_WARN_IF(aRv.Failed())) {
  126. return nullptr;
  127. }
  128. blobImpl = new BlobImplSnapshot(blobImpl, mFileHandle);
  129. return blobImpl.forget();
  130. }
  131. void
  132. BlobImplSnapshot::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
  133. {
  134. nsCOMPtr<EventTarget> et = do_QueryReferent(mFileHandle);
  135. RefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
  136. if (!fileHandle || !fileHandle->IsOpen()) {
  137. aRv.Throw(NS_ERROR_DOM_FILEHANDLE_INACTIVE_ERR);
  138. return;
  139. }
  140. nsCOMPtr<nsIInputStream> stream;
  141. mBlobImpl->GetInternalStream(getter_AddRefs(stream), aRv);
  142. if (NS_WARN_IF(aRv.Failed())) {
  143. return;
  144. }
  145. RefPtr<StreamWrapper> wrapper = new StreamWrapper(stream, fileHandle);
  146. wrapper.forget(aStream);
  147. }
  148. BlobImpl*
  149. BlobImplSnapshot::GetBlobImpl() const
  150. {
  151. nsCOMPtr<EventTarget> et = do_QueryReferent(mFileHandle);
  152. RefPtr<IDBFileHandle> fileHandle = static_cast<IDBFileHandle*>(et.get());
  153. if (!fileHandle || !fileHandle->IsOpen()) {
  154. return nullptr;
  155. }
  156. return mBlobImpl;
  157. }
  158. StreamWrapper::~StreamWrapper()
  159. {
  160. AssertIsOnOwningThread();
  161. Finish();
  162. }
  163. NS_IMPL_ADDREF(StreamWrapper)
  164. NS_IMPL_RELEASE_WITH_DESTROY(StreamWrapper, Destroy())
  165. NS_IMPL_QUERY_INTERFACE(StreamWrapper,
  166. nsIInputStream,
  167. nsIIPCSerializableInputStream)
  168. NS_IMETHODIMP
  169. StreamWrapper::Close()
  170. {
  171. MOZ_ASSERT(!IsOnOwningThread());
  172. RefPtr<CloseRunnable> closeRunnable = new CloseRunnable(this);
  173. MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(closeRunnable,
  174. NS_DISPATCH_NORMAL));
  175. return NS_OK;
  176. }
  177. NS_IMETHODIMP
  178. StreamWrapper::Available(uint64_t* _retval)
  179. {
  180. // Can't assert here, this method is sometimes called on the owning thread
  181. // (nsInputStreamChannel::OpenContentStream calls Available before setting
  182. // the content length property).
  183. return mInputStream->Available(_retval);
  184. }
  185. NS_IMETHODIMP
  186. StreamWrapper::Read(char* aBuf, uint32_t aCount, uint32_t* _retval)
  187. {
  188. MOZ_ASSERT(!IsOnOwningThread());
  189. return mInputStream->Read(aBuf, aCount, _retval);
  190. }
  191. NS_IMETHODIMP
  192. StreamWrapper::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
  193. uint32_t aCount, uint32_t* _retval)
  194. {
  195. MOZ_ASSERT(!IsOnOwningThread());
  196. return mInputStream->ReadSegments(aWriter, aClosure, aCount, _retval);
  197. }
  198. NS_IMETHODIMP
  199. StreamWrapper::IsNonBlocking(bool* _retval)
  200. {
  201. return mInputStream->IsNonBlocking(_retval);
  202. }
  203. void
  204. StreamWrapper::Serialize(InputStreamParams& aParams,
  205. FileDescriptorArray& aFileDescriptors)
  206. {
  207. nsCOMPtr<nsIIPCSerializableInputStream> stream =
  208. do_QueryInterface(mInputStream);
  209. if (stream) {
  210. stream->Serialize(aParams, aFileDescriptors);
  211. }
  212. }
  213. bool
  214. StreamWrapper::Deserialize(const InputStreamParams& aParams,
  215. const FileDescriptorArray& aFileDescriptors)
  216. {
  217. nsCOMPtr<nsIIPCSerializableInputStream> stream =
  218. do_QueryInterface(mInputStream);
  219. if (stream) {
  220. return stream->Deserialize(aParams, aFileDescriptors);
  221. }
  222. return false;
  223. }
  224. Maybe<uint64_t>
  225. StreamWrapper::ExpectedSerializedLength()
  226. {
  227. nsCOMPtr<nsIIPCSerializableInputStream> stream =
  228. do_QueryInterface(mInputStream);
  229. if (stream) {
  230. return stream->ExpectedSerializedLength();
  231. }
  232. return Nothing();
  233. }
  234. NS_IMPL_ISUPPORTS_INHERITED0(StreamWrapper::CloseRunnable,
  235. Runnable)
  236. NS_IMETHODIMP
  237. StreamWrapper::
  238. CloseRunnable::Run()
  239. {
  240. mStreamWrapper->Finish();
  241. return NS_OK;
  242. }
  243. } // namespace indexedDB
  244. } // namespace dom
  245. } // namespace mozilla