summaryrefslogtreecommitdiffstats
path: root/dom/file/ipc/RemoteLazyInputStream.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/file/ipc/RemoteLazyInputStream.h')
-rw-r--r--dom/file/ipc/RemoteLazyInputStream.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/dom/file/ipc/RemoteLazyInputStream.h b/dom/file/ipc/RemoteLazyInputStream.h
new file mode 100644
index 0000000000..08bb168e27
--- /dev/null
+++ b/dom/file/ipc/RemoteLazyInputStream.h
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_RemoteLazyInputStream_h
+#define mozilla_RemoteLazyInputStream_h
+
+#include "chrome/common/ipc_message_utils.h"
+#include "mozilla/Mutex.h"
+#include "mozIRemoteLazyInputStream.h"
+#include "nsIAsyncInputStream.h"
+#include "nsICloneableInputStream.h"
+#include "nsIFileStreams.h"
+#include "nsIIPCSerializableInputStream.h"
+#include "nsIInputStreamLength.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+
+class RemoteLazyInputStreamChild;
+
+class RemoteLazyInputStream final : public nsIAsyncInputStream,
+ public nsIInputStreamCallback,
+ public nsICloneableInputStreamWithRange,
+ public nsIIPCSerializableInputStream,
+ public nsIAsyncFileMetadata,
+ public nsIInputStreamLength,
+ public nsIAsyncInputStreamLength,
+ public mozIRemoteLazyInputStream {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIASYNCINPUTSTREAM
+ NS_DECL_NSIINPUTSTREAMCALLBACK
+ NS_DECL_NSICLONEABLEINPUTSTREAM
+ NS_DECL_NSICLONEABLEINPUTSTREAMWITHRANGE
+ NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
+ NS_DECL_NSIFILEMETADATA
+ NS_DECL_NSIASYNCFILEMETADATA
+ NS_DECL_NSIINPUTSTREAMLENGTH
+ NS_DECL_NSIASYNCINPUTSTREAMLENGTH
+
+ // Create a new lazy RemoteLazyInputStream, and move the provided aInputStream
+ // into storage as referenced by it. May only be called in processes with
+ // RemoteLazyInputStreamStorage.
+ static already_AddRefed<RemoteLazyInputStream> WrapStream(
+ nsIInputStream* aInputStream);
+
+ // mozIRemoteLazyInputStream
+ NS_IMETHOD TakeInternalStream(nsIInputStream** aStream) override;
+ NS_IMETHOD GetInternalStreamID(nsID& aID) override;
+
+ private:
+ friend struct IPC::ParamTraits<mozilla::RemoteLazyInputStream*>;
+
+ // Constructor for an already-closed RemoteLazyInputStream.
+ RemoteLazyInputStream() = default;
+
+ explicit RemoteLazyInputStream(RemoteLazyInputStreamChild* aActor,
+ uint64_t aStart = 0,
+ uint64_t aLength = UINT64_MAX);
+
+ explicit RemoteLazyInputStream(nsIInputStream* aStream);
+
+ ~RemoteLazyInputStream();
+
+ void StreamNeeded() MOZ_REQUIRES(mMutex);
+
+ // Upon receiving the stream from our actor, we will not wrap it into an async
+ // stream until needed. This allows callers to get access to the underlying
+ // potentially-sync stream using `TakeInternalStream` before reading.
+ nsresult EnsureAsyncRemoteStream() MOZ_REQUIRES(mMutex);
+
+ // Note that data has been read from our input stream, and disconnect from our
+ // remote actor.
+ void MarkConsumed();
+
+ void IPCWrite(IPC::MessageWriter* aWriter);
+ static already_AddRefed<RemoteLazyInputStream> IPCRead(
+ IPC::MessageReader* aReader);
+
+ // Helper method to generate a description of a stream for use in loggging.
+ nsCString Describe() MOZ_REQUIRES(mMutex);
+
+ // Start and length of the slice to apply on this RemoteLazyInputStream when
+ // fetching the underlying stream with `SendStreamNeeded`.
+ const uint64_t mStart = 0;
+ const uint64_t mLength = UINT64_MAX;
+
+ // Any non-const member of this class is protected by mutex because it is
+ // touched on multiple threads.
+ Mutex mMutex{"RemoteLazyInputStream::mMutex"};
+
+ // This is the list of possible states.
+ enum {
+ // The initial state. Only ::Available() can be used without receiving an
+ // error. The available size is known by the actor.
+ eInit,
+
+ // AsyncWait() has been called for the first time. SendStreamNeeded() has
+ // been called and we are waiting for the 'real' inputStream.
+ ePending,
+
+ // When the child receives the stream from the parent, we move to this
+ // state. The received stream is stored in mInnerStream. From now on, any
+ // method call will be forwared to mInnerStream or mAsyncInnerStream.
+ eRunning,
+
+ // If Close() or CloseWithStatus() is called, we move to this state.
+ // mInnerStream is released and any method will return
+ // NS_BASE_STREAM_CLOSED.
+ eClosed,
+ } mState MOZ_GUARDED_BY(mMutex) = eClosed;
+
+ // The actor which will be used to provide the underlying stream or length
+ // information when needed, as well as to efficiently allow transferring the
+ // stream over IPC.
+ //
+ // The connection to our actor will be cleared once the stream has been closed
+ // or has started reading, at which point this stream will be serialized and
+ // cloned as-if it was the underlying stream.
+ RefPtr<RemoteLazyInputStreamChild> mActor MOZ_GUARDED_BY(mMutex);
+
+ nsCOMPtr<nsIInputStream> mInnerStream MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsIAsyncInputStream> mAsyncInnerStream MOZ_GUARDED_BY(mMutex);
+
+ // These 2 values are set only if mState is ePending or eRunning.
+ // RefPtr is used instead of nsCOMPtr to avoid invoking QueryInterface when
+ // assigning in debug builds, as `mInputStreamCallback` may not be threadsafe.
+ RefPtr<nsIInputStreamCallback> mInputStreamCallback MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget
+ MOZ_GUARDED_BY(mMutex);
+ uint32_t mInputStreamCallbackFlags MOZ_GUARDED_BY(mMutex) = 0;
+ uint32_t mInputStreamCallbackRequestedCount MOZ_GUARDED_BY(mMutex) = 0;
+
+ // These 2 values are set only if mState is ePending.
+ nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback
+ MOZ_GUARDED_BY(mMutex);
+ nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget
+ MOZ_GUARDED_BY(mMutex);
+};
+
+} // namespace mozilla
+
+template <>
+struct IPC::ParamTraits<mozilla::RemoteLazyInputStream*> {
+ static void Write(IPC::MessageWriter* aWriter,
+ mozilla::RemoteLazyInputStream* aParam);
+ static bool Read(IPC::MessageReader* aReader,
+ RefPtr<mozilla::RemoteLazyInputStream>* aResult);
+};
+
+#endif // mozilla_RemoteLazyInputStream_h