forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			155 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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
 | 
