1 /* -*- Mode: C++; tab-width: 2; 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 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsBufferedStreams_h__ 7 #define nsBufferedStreams_h__ 8 9 #include "nsIBufferedStreams.h" 10 #include "nsIInputStream.h" 11 #include "nsIOutputStream.h" 12 #include "nsISafeOutputStream.h" 13 #include "nsISeekableStream.h" 14 #include "nsIStreamBufferAccess.h" 15 #include "nsCOMPtr.h" 16 #include "nsIIPCSerializableInputStream.h" 17 #include "nsIAsyncInputStream.h" 18 #include "nsICloneableInputStream.h" 19 #include "nsIInputStreamLength.h" 20 #include "mozilla/Mutex.h" 21 22 //////////////////////////////////////////////////////////////////////////////// 23 24 class nsBufferedStream : public nsISeekableStream { 25 public: 26 NS_DECL_THREADSAFE_ISUPPORTS 27 NS_DECL_NSISEEKABLESTREAM 28 NS_DECL_NSITELLABLESTREAM 29 30 nsBufferedStream() = default; 31 32 void Close(); 33 34 protected: 35 virtual ~nsBufferedStream(); 36 37 nsresult Init(nsISupports* stream, uint32_t bufferSize); 38 nsresult GetData(nsISupports** aResult); 39 NS_IMETHOD Fill() = 0; 40 NS_IMETHOD Flush() = 0; 41 42 uint32_t mBufferSize{0}; 43 char* mBuffer{nullptr}; 44 45 // mBufferStartOffset is the offset relative to the start of mStream. 46 int64_t mBufferStartOffset{0}; 47 48 // mCursor is the read cursor for input streams, or write cursor for 49 // output streams, and is relative to mBufferStartOffset. 50 uint32_t mCursor{0}; 51 52 // mFillPoint is the amount available in the buffer for input streams, 53 // or the high watermark of bytes written into the buffer, and therefore 54 // is relative to mBufferStartOffset. 55 uint32_t mFillPoint{0}; 56 57 nsCOMPtr<nsISupports> mStream; // cast to appropriate subclass 58 59 bool mBufferDisabled{false}; 60 bool mEOF{false}; // True if mStream is at EOF 61 uint8_t mGetBufferCount{0}; 62 }; 63 64 //////////////////////////////////////////////////////////////////////////////// 65 66 class nsBufferedInputStream final : public nsBufferedStream, 67 public nsIBufferedInputStream, 68 public nsIStreamBufferAccess, 69 public nsIIPCSerializableInputStream, 70 public nsIAsyncInputStream, 71 public nsIInputStreamCallback, 72 public nsICloneableInputStream, 73 public nsIInputStreamLength, 74 public nsIAsyncInputStreamLength, 75 public nsIInputStreamLengthCallback { 76 public: 77 NS_DECL_ISUPPORTS_INHERITED 78 NS_DECL_NSIINPUTSTREAM 79 NS_DECL_NSIBUFFEREDINPUTSTREAM 80 NS_DECL_NSISTREAMBUFFERACCESS 81 NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM 82 NS_DECL_NSIASYNCINPUTSTREAM 83 NS_DECL_NSIINPUTSTREAMCALLBACK 84 NS_DECL_NSICLONEABLEINPUTSTREAM 85 NS_DECL_NSIINPUTSTREAMLENGTH 86 NS_DECL_NSIASYNCINPUTSTREAMLENGTH 87 NS_DECL_NSIINPUTSTREAMLENGTHCALLBACK 88 nsBufferedInputStream()89 nsBufferedInputStream() : nsBufferedStream() {} 90 91 static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); 92 Source()93 nsIInputStream* Source() { return (nsIInputStream*)mStream.get(); } 94 95 /** 96 * If there's a reference/pointer to an nsBufferedInputStream BEFORE calling 97 * Init() AND the intent is to ultimately convert/assign that 98 * reference/pointer to an nsIInputStream, DO NOT use that initial 99 * reference/pointer. Instead, use the value of QueryInterface-ing to an 100 * nsIInputStream (and, again, the QueryInterface must be performed after 101 * Init()). This is because nsBufferedInputStream has multiple underlying 102 * nsIInputStreams (one from nsIBufferedInputStream and one from 103 * nsIAsyncInputStream), and the correct base nsIInputStream to use will be 104 * unknown until the final value of mIsAsyncInputStream is set in Init(). 105 * 106 * This method, however, does just that but also hides the QI details and 107 * will assert if called before Init(). 108 */ 109 already_AddRefed<nsIInputStream> GetInputStream(); 110 111 protected: 112 virtual ~nsBufferedInputStream() = default; 113 114 template <typename M> 115 void SerializeInternal(mozilla::ipc::InputStreamParams& aParams, 116 FileDescriptorArray& aFileDescriptors, 117 bool aDelayedStart, uint32_t aMaxSize, 118 uint32_t* aSizeUsed, M* aManager); 119 120 NS_IMETHOD Fill() override; Flush()121 NS_IMETHOD Flush() override { return NS_OK; } // no-op for input streams 122 123 mozilla::Mutex mMutex{"nsBufferedInputStream::mMutex"}; 124 125 // This value is protected by mutex. 126 nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback; 127 128 // This value is protected by mutex. 129 nsCOMPtr<nsIInputStreamLengthCallback> mAsyncInputStreamLengthCallback; 130 131 bool mIsIPCSerializable{true}; 132 bool mIsAsyncInputStream{false}; 133 bool mIsCloneableInputStream{false}; 134 bool mIsInputStreamLength{false}; 135 bool mIsAsyncInputStreamLength{false}; 136 }; 137 138 //////////////////////////////////////////////////////////////////////////////// 139 140 class nsBufferedOutputStream : public nsBufferedStream, 141 public nsISafeOutputStream, 142 public nsIBufferedOutputStream, 143 public nsIStreamBufferAccess { 144 public: 145 NS_DECL_ISUPPORTS_INHERITED 146 NS_DECL_NSIOUTPUTSTREAM 147 NS_DECL_NSISAFEOUTPUTSTREAM 148 NS_DECL_NSIBUFFEREDOUTPUTSTREAM 149 NS_DECL_NSISTREAMBUFFERACCESS 150 nsBufferedOutputStream()151 nsBufferedOutputStream() : nsBufferedStream() {} 152 153 static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); 154 Sink()155 nsIOutputStream* Sink() { return (nsIOutputStream*)mStream.get(); } 156 157 protected: ~nsBufferedOutputStream()158 virtual ~nsBufferedOutputStream() { nsBufferedOutputStream::Close(); } 159 Fill()160 NS_IMETHOD Fill() override { return NS_OK; } // no-op for output streams 161 162 nsCOMPtr<nsISafeOutputStream> mSafeStream; // QI'd from mStream 163 }; 164 165 //////////////////////////////////////////////////////////////////////////////// 166 167 #endif // nsBufferedStreams_h__ 168