CacheFileMetadata.h (8390B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef CacheFileMetadata__h__ 6 #define CacheFileMetadata__h__ 7 8 #include "CacheFileIOManager.h" 9 #include "CacheStorageService.h" 10 #include "CacheHashUtils.h" 11 #include "CacheObserver.h" 12 #include "mozilla/EndianUtils.h" 13 #include "mozilla/BasePrincipal.h" 14 #include "mozilla/NotNull.h" 15 #include "nsString.h" 16 17 class nsICacheEntryMetaDataVisitor; 18 19 namespace mozilla { 20 namespace net { 21 22 namespace CacheFileUtils { 23 class CacheFileLock; 24 }; 25 26 // Flags stored in CacheFileMetadataHeader.mFlags 27 28 // Whether an entry is a pinned entry (created with 29 // nsICacheStorageService.pinningCacheStorage.) 30 static const uint32_t kCacheEntryIsPinned = 1 << 0; 31 32 // By multiplying with the current half-life we convert the frecency 33 // to time independent of half-life value. The range fits 32bits. 34 // When decay time changes on next run of the browser, we convert 35 // the frecency value to a correct internal representation again. 36 // It might not be 100% accurate, but for the purpose it suffice. 37 #define FRECENCY2INT(aFrecency) \ 38 ((uint32_t)((aFrecency) * CacheObserver::HalfLifeSeconds())) 39 #define INT2FRECENCY(aInt) \ 40 ((double)(aInt) / (double)CacheObserver::HalfLifeSeconds()) 41 42 #define kCacheEntryVersion 3 43 44 #pragma pack(push) 45 #pragma pack(1) 46 47 class CacheFileMetadataHeader { 48 public: 49 uint32_t mVersion; 50 uint32_t mFetchCount; 51 uint32_t mLastFetched; 52 uint32_t mLastModified; 53 uint32_t mFrecency; 54 uint32_t mExpirationTime; 55 uint32_t mKeySize; 56 uint32_t mFlags; 57 58 void WriteToBuf(void* aBuf) { 59 EnsureCorrectClassSize(); 60 61 uint8_t* ptr = static_cast<uint8_t*>(aBuf); 62 MOZ_ASSERT(mVersion == kCacheEntryVersion); 63 NetworkEndian::writeUint32(ptr, mVersion); 64 ptr += sizeof(uint32_t); 65 NetworkEndian::writeUint32(ptr, mFetchCount); 66 ptr += sizeof(uint32_t); 67 NetworkEndian::writeUint32(ptr, mLastFetched); 68 ptr += sizeof(uint32_t); 69 NetworkEndian::writeUint32(ptr, mLastModified); 70 ptr += sizeof(uint32_t); 71 NetworkEndian::writeUint32(ptr, mFrecency); 72 ptr += sizeof(uint32_t); 73 NetworkEndian::writeUint32(ptr, mExpirationTime); 74 ptr += sizeof(uint32_t); 75 NetworkEndian::writeUint32(ptr, mKeySize); 76 ptr += sizeof(uint32_t); 77 NetworkEndian::writeUint32(ptr, mFlags); 78 } 79 80 void ReadFromBuf(const void* aBuf) { 81 EnsureCorrectClassSize(); 82 83 const uint8_t* ptr = static_cast<const uint8_t*>(aBuf); 84 mVersion = BigEndian::readUint32(ptr); 85 ptr += sizeof(uint32_t); 86 mFetchCount = BigEndian::readUint32(ptr); 87 ptr += sizeof(uint32_t); 88 mLastFetched = BigEndian::readUint32(ptr); 89 ptr += sizeof(uint32_t); 90 mLastModified = BigEndian::readUint32(ptr); 91 ptr += sizeof(uint32_t); 92 mFrecency = BigEndian::readUint32(ptr); 93 ptr += sizeof(uint32_t); 94 mExpirationTime = BigEndian::readUint32(ptr); 95 ptr += sizeof(uint32_t); 96 mKeySize = BigEndian::readUint32(ptr); 97 ptr += sizeof(uint32_t); 98 if (mVersion >= 2) { 99 mFlags = BigEndian::readUint32(ptr); 100 } else { 101 mFlags = 0; 102 } 103 } 104 105 inline void EnsureCorrectClassSize() { 106 static_assert( 107 (sizeof(mVersion) + sizeof(mFetchCount) + sizeof(mLastFetched) + 108 sizeof(mLastModified) + sizeof(mFrecency) + sizeof(mExpirationTime) + 109 sizeof(mKeySize)) + 110 sizeof(mFlags) == 111 sizeof(CacheFileMetadataHeader), 112 "Unexpected sizeof(CacheFileMetadataHeader)!"); 113 } 114 }; 115 116 #pragma pack(pop) 117 118 #define CACHEFILEMETADATALISTENER_IID \ 119 {/* a9e36125-3f01-4020-9540-9dafa8d31ba7 */ \ 120 0xa9e36125, \ 121 0x3f01, \ 122 0x4020, \ 123 {0x95, 0x40, 0x9d, 0xaf, 0xa8, 0xd3, 0x1b, 0xa7}} 124 125 class CacheFileMetadataListener : public nsISupports { 126 public: 127 NS_INLINE_DECL_STATIC_IID(CACHEFILEMETADATALISTENER_IID) 128 129 NS_IMETHOD OnMetadataRead(nsresult aResult) = 0; 130 NS_IMETHOD OnMetadataWritten(nsresult aResult) = 0; 131 virtual bool IsKilled() = 0; 132 }; 133 134 class CacheFileMetadata final : public CacheFileIOListener, 135 public CacheMemoryConsumer { 136 public: 137 NS_DECL_THREADSAFE_ISUPPORTS 138 139 CacheFileMetadata(CacheFileHandle* aHandle, const nsACString& aKey, 140 NotNull<CacheFileUtils::CacheFileLock*> aLock); 141 CacheFileMetadata(bool aMemoryOnly, bool aPinned, const nsACString& aKey, 142 NotNull<CacheFileUtils::CacheFileLock*> aLock); 143 CacheFileMetadata(); 144 145 void SetHandle(CacheFileHandle* aHandle); 146 147 const nsACString& GetKey() const { return mKey; } 148 149 void ReadMetadata(CacheFileMetadataListener* aListener); 150 uint32_t CalcMetadataSize(uint32_t aElementsSize, uint32_t aHashCount); 151 nsresult WriteMetadata(uint32_t aOffset, 152 CacheFileMetadataListener* aListener); 153 nsresult SyncReadMetadata(nsIFile* aFile); 154 155 bool IsAnonymous() const { return mAnonymous; } 156 mozilla::OriginAttributes const& OriginAttributes() const { 157 return mOriginAttributes; 158 } 159 bool Pinned() const { return !!(mMetaHdr.mFlags & kCacheEntryIsPinned); } 160 161 const char* GetElement(const char* aKey); 162 void HandleCorruptMetaData() const; 163 nsresult SetElement(const char* aKey, const char* aValue); 164 void Visit(nsICacheEntryMetaDataVisitor* aVisitor); 165 166 CacheHash::Hash16_t GetHash(uint32_t aIndex); 167 nsresult SetHash(uint32_t aIndex, CacheHash::Hash16_t aHash); 168 nsresult RemoveHash(uint32_t aIndex); 169 170 void AddFlags(uint32_t aFlags); 171 void RemoveFlags(uint32_t aFlags); 172 uint32_t GetFlags() const { return mMetaHdr.mFlags; } 173 void SetExpirationTime(uint32_t aExpirationTime); 174 uint32_t GetExpirationTime() const { return mMetaHdr.mExpirationTime; } 175 void SetFrecency(uint32_t aFrecency); 176 uint32_t GetFrecency() const { return mMetaHdr.mFrecency; } 177 uint32_t GetLastModified() const { return mMetaHdr.mLastModified; } 178 uint32_t GetLastFetched() const { return mMetaHdr.mLastFetched; } 179 uint32_t GetFetchCount() const { return mMetaHdr.mFetchCount; } 180 // Called by upper layers to indicate the entry this metadata belongs 181 // with has been fetched, i.e. delivered to the consumer. 182 void OnFetched(); 183 184 int64_t Offset() { return mOffset; } 185 uint32_t ElementsSize() { return mElementsSize; } 186 void MarkDirty(bool aUpdateLastModified = true); 187 bool IsDirty() { return mIsDirty; } 188 uint32_t MemoryUsage() { 189 return sizeof(CacheFileMetadata) + mHashArraySize + mBufSize; 190 } 191 192 NS_IMETHOD OnFileOpened(CacheFileHandle* aHandle, nsresult aResult) override; 193 NS_IMETHOD OnDataWritten(CacheFileHandle* aHandle, const char* aBuf, 194 nsresult aResult) override; 195 NS_IMETHOD OnDataRead(CacheFileHandle* aHandle, char* aBuf, 196 nsresult aResult) override; 197 NS_IMETHOD OnFileDoomed(CacheFileHandle* aHandle, nsresult aResult) override; 198 NS_IMETHOD OnEOFSet(CacheFileHandle* aHandle, nsresult aResult) override; 199 NS_IMETHOD OnFileRenamed(CacheFileHandle* aHandle, nsresult aResult) override; 200 virtual bool IsKilled() override { 201 return mListener && mListener->IsKilled(); 202 } 203 void InitEmptyMetadata(); 204 205 // Memory reporting 206 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 207 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 208 209 private: 210 virtual ~CacheFileMetadata(); 211 212 nsresult ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset, 213 bool aHaveKey); 214 nsresult CheckElements(const char* aBuf, uint32_t aSize); 215 nsresult EnsureBuffer(uint32_t aSize); 216 nsresult ParseKey(const nsACString& aKey); 217 218 RefPtr<CacheFileHandle> mHandle; 219 nsCString mKey; 220 CacheHash::Hash16_t* mHashArray{nullptr}; 221 uint32_t mHashArraySize{0}; 222 uint32_t mHashCount{0}; 223 int64_t mOffset{0}; 224 // used for parsing, then points to elements 225 char* mBuf{nullptr}; 226 uint32_t mBufSize{0}; 227 char* mWriteBuf{nullptr}; 228 CacheFileMetadataHeader mMetaHdr{0}; 229 uint32_t mElementsSize{0}; 230 bool mIsDirty : 1; 231 bool mAnonymous : 1; 232 bool mAllocExactSize : 1; 233 bool mFirstRead : 1; 234 mozilla::OriginAttributes mOriginAttributes; 235 mozilla::TimeStamp mReadStart; 236 nsCOMPtr<CacheFileMetadataListener> mListener; 237 RefPtr<CacheFileUtils::CacheFileLock> mLock; 238 }; 239 240 } // namespace net 241 } // namespace mozilla 242 243 #endif