1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef _nsCacheEntryDescriptor_h_ 8 #define _nsCacheEntryDescriptor_h_ 9 10 #include "nsICacheEntryDescriptor.h" 11 #include "nsCacheEntry.h" 12 #include "nsIInputStream.h" 13 #include "nsIOutputStream.h" 14 #include "nsCacheService.h" 15 #include "zlib.h" 16 #include "mozilla/Mutex.h" 17 18 /****************************************************************************** 19 * nsCacheEntryDescriptor 20 *******************************************************************************/ 21 class nsCacheEntryDescriptor final : public PRCList, 22 public nsICacheEntryDescriptor { 23 public: 24 NS_DECL_THREADSAFE_ISUPPORTS 25 NS_DECL_NSICACHEENTRYDESCRIPTOR 26 NS_DECL_NSICACHEENTRYINFO 27 28 friend class nsAsyncDoomEvent; 29 friend class nsCacheService; 30 31 nsCacheEntryDescriptor(nsCacheEntry* entry, nsCacheAccessMode mode); 32 33 /** 34 * utility method to attempt changing data size of associated entry 35 */ 36 nsresult RequestDataSizeChange(int32_t deltaSize); 37 38 /** 39 * methods callbacks for nsCacheService 40 */ CacheEntry(void)41 nsCacheEntry* CacheEntry(void) { return mCacheEntry; } ClearCacheEntry(void)42 bool ClearCacheEntry(void) { 43 NS_ASSERTION(mInputWrappers.IsEmpty(), "Bad state"); 44 NS_ASSERTION(!mOutputWrapper, "Bad state"); 45 46 bool doomEntry = false; 47 bool asyncDoomPending; 48 { 49 mozilla::MutexAutoLock lock(mLock); 50 asyncDoomPending = mAsyncDoomPending; 51 } 52 53 if (asyncDoomPending && mCacheEntry) { 54 doomEntry = true; 55 mDoomedOnClose = true; 56 } 57 mCacheEntry = nullptr; 58 59 return doomEntry; 60 } 61 62 private: 63 virtual ~nsCacheEntryDescriptor(); 64 65 /************************************************************************* 66 * input stream wrapper class - 67 * 68 * The input stream wrapper references the descriptor, but the descriptor 69 * doesn't need any references to the stream wrapper. 70 *************************************************************************/ 71 class nsInputStreamWrapper : public nsIInputStream { 72 friend class nsCacheEntryDescriptor; 73 74 private: 75 nsCacheEntryDescriptor* mDescriptor; 76 nsCOMPtr<nsIInputStream> mInput; 77 uint32_t mStartOffset; 78 bool mInitialized; 79 mozilla::Mutex mLock; 80 81 public: 82 NS_DECL_THREADSAFE_ISUPPORTS 83 NS_DECL_NSIINPUTSTREAM 84 nsInputStreamWrapper(nsCacheEntryDescriptor * desc,uint32_t off)85 nsInputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off) 86 : mDescriptor(desc), 87 mStartOffset(off), 88 mInitialized(false), 89 mLock("nsInputStreamWrapper.mLock") { 90 NS_ADDREF(mDescriptor); 91 } 92 93 private: ~nsInputStreamWrapper()94 virtual ~nsInputStreamWrapper() { NS_IF_RELEASE(mDescriptor); } 95 96 nsresult LazyInit(); 97 nsresult EnsureInit(); 98 nsresult Read_Locked(char* buf, uint32_t count, uint32_t* countRead); 99 nsresult Close_Locked(); 100 void CloseInternal(); 101 }; 102 103 class nsDecompressInputStreamWrapper : public nsInputStreamWrapper { 104 private: 105 unsigned char* mReadBuffer; 106 uint32_t mReadBufferLen; 107 z_stream mZstream; 108 bool mStreamInitialized; 109 bool mStreamEnded; 110 111 public: 112 NS_DECL_ISUPPORTS_INHERITED 113 nsDecompressInputStreamWrapper(nsCacheEntryDescriptor * desc,uint32_t off)114 nsDecompressInputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off) 115 : nsInputStreamWrapper(desc, off), 116 mReadBuffer(nullptr), 117 mReadBufferLen(0), 118 mZstream{}, 119 mStreamInitialized(false), 120 mStreamEnded(false) {} 121 NS_IMETHOD Read(char* buf, uint32_t count, uint32_t* result) override; 122 NS_IMETHOD Close() override; 123 124 private: ~nsDecompressInputStreamWrapper()125 virtual ~nsDecompressInputStreamWrapper() { Close(); } 126 nsresult InitZstream(); 127 nsresult EndZstream(); 128 }; 129 130 /************************************************************************* 131 * output stream wrapper class - 132 * 133 * The output stream wrapper references the descriptor, but the descriptor 134 * doesn't need any references to the stream wrapper. 135 *************************************************************************/ 136 class nsOutputStreamWrapper : public nsIOutputStream { 137 friend class nsCacheEntryDescriptor; 138 139 protected: 140 nsCacheEntryDescriptor* mDescriptor; 141 nsCOMPtr<nsIOutputStream> mOutput; 142 uint32_t mStartOffset; 143 bool mInitialized; 144 mozilla::Mutex mLock; 145 146 public: 147 NS_DECL_THREADSAFE_ISUPPORTS 148 NS_DECL_NSIOUTPUTSTREAM 149 nsOutputStreamWrapper(nsCacheEntryDescriptor * desc,uint32_t off)150 nsOutputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off) 151 : mDescriptor(desc), 152 mStartOffset(off), 153 mInitialized(false), 154 mLock("nsOutputStreamWrapper.mLock") { 155 NS_ADDREF(mDescriptor); // owning ref 156 } 157 158 private: ~nsOutputStreamWrapper()159 virtual ~nsOutputStreamWrapper() { 160 Close(); 161 162 NS_ASSERTION(!mOutput, "Bad state"); 163 NS_ASSERTION(!mDescriptor, "Bad state"); 164 } 165 166 nsresult LazyInit(); 167 nsresult EnsureInit(); 168 nsresult OnWrite(uint32_t count); 169 nsresult Write_Locked(const char* buf, uint32_t count, uint32_t* result); 170 nsresult Close_Locked(); 171 void CloseInternal(); 172 }; 173 174 class nsCompressOutputStreamWrapper : public nsOutputStreamWrapper { 175 private: 176 unsigned char* mWriteBuffer; 177 uint32_t mWriteBufferLen; 178 z_stream mZstream; 179 bool mStreamInitialized; 180 bool mStreamEnded; 181 uint32_t mUncompressedCount; 182 183 public: 184 NS_DECL_ISUPPORTS_INHERITED 185 nsCompressOutputStreamWrapper(nsCacheEntryDescriptor * desc,uint32_t off)186 nsCompressOutputStreamWrapper(nsCacheEntryDescriptor* desc, uint32_t off) 187 : nsOutputStreamWrapper(desc, off), 188 mWriteBuffer(nullptr), 189 mWriteBufferLen(0), 190 mZstream{}, 191 mStreamInitialized(false), 192 mStreamEnded(false), 193 mUncompressedCount(0) {} 194 NS_IMETHOD Write(const char* buf, uint32_t count, 195 uint32_t* result) override; 196 NS_IMETHOD Close() override; 197 198 private: ~nsCompressOutputStreamWrapper()199 virtual ~nsCompressOutputStreamWrapper() { Close(); } 200 nsresult InitZstream(); 201 nsresult WriteBuffer(); 202 }; 203 204 private: 205 /** 206 * nsCacheEntryDescriptor data members 207 */ 208 209 nsCOMPtr<nsICacheServiceInternal> mCacheService; 210 nsCacheEntry* mCacheEntry; // we are a child of the entry 211 nsCacheAccessMode mAccessGranted; 212 nsTArray<nsInputStreamWrapper*> mInputWrappers; 213 nsOutputStreamWrapper* mOutputWrapper; 214 mozilla::Mutex mLock; 215 bool mAsyncDoomPending; 216 bool mDoomedOnClose; 217 bool mClosingDescriptor; 218 }; 219 220 #endif // _nsCacheEntryDescriptor_h_ 221