/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * 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 _nsCacheEntryDescriptor_h_ #define _nsCacheEntryDescriptor_h_ #include "nsICacheEntryDescriptor.h" #include "nsCacheEntry.h" #include "nsIInputStream.h" #include "nsIOutputStream.h" #include "nsCacheService.h" #include "zlib.h" #include "mozilla/Mutex.h" /****************************************************************************** * nsCacheEntryDescriptor *******************************************************************************/ class nsCacheEntryDescriptor final : public PRCList, public nsICacheEntryDescriptor { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSICACHEENTRYDESCRIPTOR NS_DECL_NSICACHEENTRYINFO friend class nsAsyncDoomEvent; friend class nsCacheService; nsCacheEntryDescriptor(nsCacheEntry * entry, nsCacheAccessMode mode); /** * utility method to attempt changing data size of associated entry */ nsresult RequestDataSizeChange(int32_t deltaSize); /** * methods callbacks for nsCacheService */ nsCacheEntry * CacheEntry(void) { return mCacheEntry; } bool ClearCacheEntry(void) { NS_ASSERTION(mInputWrappers.IsEmpty(), "Bad state"); NS_ASSERTION(!mOutputWrapper, "Bad state"); bool doomEntry = false; bool asyncDoomPending; { mozilla::MutexAutoLock lock(mLock); asyncDoomPending = mAsyncDoomPending; } if (asyncDoomPending && mCacheEntry) { doomEntry = true; mDoomedOnClose = true; } mCacheEntry = nullptr; return doomEntry; } private: virtual ~nsCacheEntryDescriptor(); /************************************************************************* * input stream wrapper class - * * The input stream wrapper references the descriptor, but the descriptor * doesn't need any references to the stream wrapper. *************************************************************************/ class nsInputStreamWrapper : public nsIInputStream { friend class nsCacheEntryDescriptor; private: nsCacheEntryDescriptor * mDescriptor; nsCOMPtr mInput; uint32_t mStartOffset; bool mInitialized; mozilla::Mutex mLock; public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIINPUTSTREAM nsInputStreamWrapper(nsCacheEntryDescriptor * desc, uint32_t off) : mDescriptor(desc) , mStartOffset(off) , mInitialized(false) , mLock("nsInputStreamWrapper.mLock") { NS_ADDREF(mDescriptor); } private: virtual ~nsInputStreamWrapper() { NS_IF_RELEASE(mDescriptor); } nsresult LazyInit(); nsresult EnsureInit(); nsresult Read_Locked(char *buf, uint32_t count, uint32_t *countRead); nsresult Close_Locked(); void CloseInternal(); }; class nsDecompressInputStreamWrapper : public nsInputStreamWrapper { private: unsigned char* mReadBuffer; uint32_t mReadBufferLen; z_stream mZstream; bool mStreamInitialized; bool mStreamEnded; public: NS_DECL_ISUPPORTS_INHERITED nsDecompressInputStreamWrapper(nsCacheEntryDescriptor * desc, uint32_t off) : nsInputStreamWrapper(desc, off) , mReadBuffer(0) , mReadBufferLen(0) , mStreamInitialized(false) , mStreamEnded(false) { } NS_IMETHOD Read(char* buf, uint32_t count, uint32_t * result) override; NS_IMETHOD Close() override; private: virtual ~nsDecompressInputStreamWrapper() { Close(); } nsresult InitZstream(); nsresult EndZstream(); }; /************************************************************************* * output stream wrapper class - * * The output stream wrapper references the descriptor, but the descriptor * doesn't need any references to the stream wrapper. *************************************************************************/ class nsOutputStreamWrapper : public nsIOutputStream { friend class nsCacheEntryDescriptor; protected: nsCacheEntryDescriptor * mDescriptor; nsCOMPtr mOutput; uint32_t mStartOffset; bool mInitialized; mozilla::Mutex mLock; public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOUTPUTSTREAM nsOutputStreamWrapper(nsCacheEntryDescriptor * desc, uint32_t off) : mDescriptor(desc) , mStartOffset(off) , mInitialized(false) , mLock("nsOutputStreamWrapper.mLock") { NS_ADDREF(mDescriptor); // owning ref } private: virtual ~nsOutputStreamWrapper() { Close(); NS_ASSERTION(!mOutput, "Bad state"); NS_ASSERTION(!mDescriptor, "Bad state"); } nsresult LazyInit(); nsresult EnsureInit(); nsresult OnWrite(uint32_t count); nsresult Write_Locked(const char * buf, uint32_t count, uint32_t * result); nsresult Close_Locked(); void CloseInternal(); }; class nsCompressOutputStreamWrapper : public nsOutputStreamWrapper { private: unsigned char* mWriteBuffer; uint32_t mWriteBufferLen; z_stream mZstream; bool mStreamInitialized; bool mStreamEnded; uint32_t mUncompressedCount; public: NS_DECL_ISUPPORTS_INHERITED nsCompressOutputStreamWrapper(nsCacheEntryDescriptor * desc, uint32_t off) : nsOutputStreamWrapper(desc, off) , mWriteBuffer(0) , mWriteBufferLen(0) , mStreamInitialized(false) , mStreamEnded(false) , mUncompressedCount(0) { } NS_IMETHOD Write(const char* buf, uint32_t count, uint32_t * result) override; NS_IMETHOD Close() override; private: virtual ~nsCompressOutputStreamWrapper() { Close(); } nsresult InitZstream(); nsresult WriteBuffer(); }; private: /** * nsCacheEntryDescriptor data members */ nsCacheEntry * mCacheEntry; // we are a child of the entry nsCacheAccessMode mAccessGranted; nsTArray mInputWrappers; nsOutputStreamWrapper * mOutputWrapper; mozilla::Mutex mLock; bool mAsyncDoomPending; bool mDoomedOnClose; bool mClosingDescriptor; }; #endif // _nsCacheEntryDescriptor_h_