tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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