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