Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/cache2/CacheStorageService.h
Line
Count
Source (jump to first uncovered line)
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 CacheStorageService__h__
6
#define CacheStorageService__h__
7
8
#include "nsICacheStorageService.h"
9
#include "nsIMemoryReporter.h"
10
#include "nsINamed.h"
11
#include "nsITimer.h"
12
#include "nsICacheTesting.h"
13
14
#include "nsClassHashtable.h"
15
#include "nsDataHashtable.h"
16
#include "nsString.h"
17
#include "nsThreadUtils.h"
18
#include "nsProxyRelease.h"
19
#include "mozilla/Monitor.h"
20
#include "mozilla/Mutex.h"
21
#include "mozilla/Atomics.h"
22
#include "mozilla/TimeStamp.h"
23
#include "nsTArray.h"
24
25
class nsIURI;
26
class nsICacheEntryDoomCallback;
27
class nsICacheStorageVisitor;
28
class nsIRunnable;
29
class nsIThread;
30
class nsIEventTarget;
31
32
namespace mozilla {
33
34
class OriginAttributes;
35
36
namespace net {
37
38
class CacheStorageService;
39
class CacheStorage;
40
class CacheEntry;
41
class CacheEntryHandle;
42
43
class CacheMemoryConsumer
44
{
45
private:
46
  friend class CacheStorageService;
47
  uint32_t mReportedMemoryConsumption : 30;
48
  uint32_t mFlags : 2;
49
50
private:
51
  CacheMemoryConsumer() = delete;
52
53
protected:
54
  enum {
55
    // No special treatment, reports always to the disk-entries pool.
56
    NORMAL = 0,
57
    // This consumer is belonging to a memory-only cache entry, used to decide
58
    // which of the two disk and memory pools count this consumption at.
59
    MEMORY_ONLY = 1 << 0,
60
    // Prevent reports of this consumer at all, used for disk data chunks since
61
    // we throw them away as soon as the entry is not used by any consumer and
62
    // don't want to make them wipe the whole pool out during their short life.
63
    DONT_REPORT = 1 << 1
64
  };
65
66
  explicit CacheMemoryConsumer(uint32_t aFlags);
67
0
  ~CacheMemoryConsumer() { DoMemoryReport(0); }
68
  void DoMemoryReport(uint32_t aCurrentSize);
69
};
70
71
class CacheStorageService final : public nsICacheStorageService
72
                                , public nsIMemoryReporter
73
                                , public nsITimerCallback
74
                                , public nsICacheTesting
75
                                , public nsINamed
76
{
77
public:
78
  NS_DECL_THREADSAFE_ISUPPORTS
79
  NS_DECL_NSICACHESTORAGESERVICE
80
  NS_DECL_NSIMEMORYREPORTER
81
  NS_DECL_NSITIMERCALLBACK
82
  NS_DECL_NSICACHETESTING
83
  NS_DECL_NSINAMED
84
85
  CacheStorageService();
86
87
  void Shutdown();
88
  void DropPrivateBrowsingEntries();
89
90
  // Takes care of deleting any pending trashes for both cache1 and cache2
91
  // as well as old cache directory.
92
  static void CleaupCacheDirectories();
93
94
0
  static CacheStorageService* Self() { return sSelf; }
95
0
  static nsISupports* SelfISupports() { return static_cast<nsICacheStorageService*>(Self()); }
96
  nsresult Dispatch(nsIRunnable* aEvent);
97
0
  static bool IsRunning() { return sSelf && !sSelf->mShutdown; }
98
  static bool IsOnManagementThread();
99
  already_AddRefed<nsIEventTarget> Thread() const;
100
0
  mozilla::Mutex& Lock() { return mLock; }
101
102
  // Tracks entries that may be forced valid in a pruned hashtable.
103
  nsDataHashtable<nsCStringHashKey, TimeStamp> mForcedValidEntries;
104
  void ForcedValidEntriesPrune(TimeStamp &now);
105
106
  // Helper thread-safe interface to pass entry info, only difference from
107
  // nsICacheStorageVisitor is that instead of nsIURI only the uri spec is
108
  // passed.
109
  class EntryInfoCallback {
110
  public:
111
    virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance,
112
                             int64_t aDataSize, int32_t aFetchCount,
113
                             uint32_t aLastModifiedTime, uint32_t aExpirationTime,
114
                             bool aPinned, nsILoadContextInfo* aInfo) = 0;
115
  };
116
117
  // Invokes OnEntryInfo for the given aEntry, synchronously.
118
  static void GetCacheEntryInfo(CacheEntry* aEntry, EntryInfoCallback *aVisitor);
119
120
  nsresult GetCacheIndexEntryAttrs(CacheStorage const* aStorage,
121
                                   const nsACString &aURI,
122
                                   const nsACString &aIdExtension,
123
                                   bool *aHasAltData,
124
                                   uint32_t *aFileSizeKb);
125
126
  static uint32_t CacheQueueSize(bool highPriority);
127
128
  // Memory reporting
129
  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
130
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
131
  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
132
133
private:
134
  virtual ~CacheStorageService();
135
  void ShutdownBackground();
136
137
private:
138
  // The following methods may only be called on the management
139
  // thread.
140
  friend class CacheEntry;
141
142
  /**
143
   * Registers the entry in management ordered arrays, a mechanism
144
   * helping with weighted purge of entries.
145
   * Management arrays keep hard reference to the entry.  Entry is
146
   * responsible to remove it self or the service is responsible to
147
   * remove the entry when it's no longer needed.
148
   */
149
  void RegisterEntry(CacheEntry* aEntry);
150
151
  /**
152
   * Deregisters the entry from management arrays.  References are
153
   * then released.
154
   */
155
  void UnregisterEntry(CacheEntry* aEntry);
156
157
  /**
158
   * Removes the entry from the related entry hash table, if still present.
159
   */
160
  bool RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced = false);
161
162
  /**
163
   * Tells the storage service whether this entry is only to be stored in
164
   * memory.
165
   */
166
  void RecordMemoryOnlyEntry(CacheEntry* aEntry,
167
                             bool aOnlyInMemory,
168
                             bool aOverwrite);
169
170
  /**
171
   * Sets a cache entry valid (overrides the default loading behavior by loading
172
   * directly from cache) for the given number of seconds
173
   * See nsICacheEntry.idl for more details
174
   */
175
  void ForceEntryValidFor(nsACString const &aContextKey,
176
                          nsACString const &aEntryKey,
177
                          uint32_t aSecondsToTheFuture);
178
179
  /**
180
   * Remove the validity info
181
   */
182
  void RemoveEntryForceValid(nsACString const &aContextKey,
183
                             nsACString const &aEntryKey);
184
185
  /**
186
   * Retrieves the status of the cache entry to see if it has been forced valid
187
   * (so it will loaded directly from cache without further validation)
188
   */
189
  bool IsForcedValidEntry(nsACString const &aContextKey,
190
                          nsACString const &aEntryKey);
191
192
private:
193
  friend class CacheIndex;
194
195
  /**
196
   * CacheIndex uses this to prevent a cache entry from being prememptively
197
   * thrown away when forced valid
198
   * See nsICacheEntry.idl for more details
199
   */
200
  bool IsForcedValidEntry(nsACString const &aEntryKeyWithContext);
201
202
private:
203
  // These are helpers for telemetry monitoring of the memory pools.
204
  void TelemetryPrune(TimeStamp &now);
205
  void TelemetryRecordEntryCreation(CacheEntry const* entry);
206
  void TelemetryRecordEntryRemoval(CacheEntry const* entry);
207
208
private:
209
  // Following methods are thread safe to call.
210
  friend class CacheStorage;
211
212
  /**
213
   * Get, or create when not existing and demanded, an entry for the storage
214
   * and uri+id extension.
215
   */
216
  nsresult AddStorageEntry(CacheStorage const* aStorage,
217
                           const nsACString & aURI,
218
                           const nsACString & aIdExtension,
219
                           bool aReplace,
220
                           CacheEntryHandle** aResult);
221
222
  /**
223
   * Check existance of an entry.  This may throw NS_ERROR_NOT_AVAILABLE
224
   * when the information cannot be obtained synchronously w/o blocking.
225
   */
226
  nsresult CheckStorageEntry(CacheStorage const* aStorage,
227
                             const nsACString & aURI,
228
                             const nsACString & aIdExtension,
229
                             bool* aResult);
230
231
  /**
232
   * Removes the entry from the related entry hash table, if still present
233
   * and returns it.
234
   */
235
  nsresult DoomStorageEntry(CacheStorage const* aStorage,
236
                            const nsACString & aURI,
237
                            const nsACString & aIdExtension,
238
                            nsICacheEntryDoomCallback* aCallback);
239
240
  /**
241
   * Removes and returns entry table for the storage.
242
   */
243
  nsresult DoomStorageEntries(CacheStorage const* aStorage,
244
                              nsICacheEntryDoomCallback* aCallback);
245
246
  /**
247
   * Walk all entiries beloging to the storage.
248
   */
249
  nsresult WalkStorageEntries(CacheStorage const* aStorage,
250
                              bool aVisitEntries,
251
                              nsICacheStorageVisitor* aVisitor);
252
253
private:
254
  friend class CacheFileIOManager;
255
256
  /**
257
   * CacheFileIOManager uses this method to notify CacheStorageService that
258
   * an active entry was removed. This method is called even if the entry
259
   * removal was originated by CacheStorageService.
260
   */
261
  void CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
262
                       const nsACString & aIdExtension,
263
                       const nsACString & aURISpec);
264
265
  /**
266
   * Tries to find an existing entry in the hashtables and synchronously call
267
   * OnCacheEntryInfo of the aVisitor callback when found.
268
   * @retuns
269
   *   true, when the entry has been found that also implies the callbacks has
270
   *        beem invoked
271
   *   false, when an entry has not been found
272
   */
273
  bool GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
274
                         const nsACString & aIdExtension,
275
                         const nsACString & aURISpec,
276
                         EntryInfoCallback *aCallback);
277
278
private:
279
  friend class CacheMemoryConsumer;
280
281
  /**
282
   * When memory consumption of this entry radically changes, this method
283
   * is called to reflect the size of allocated memory.  This call may purge
284
   * unspecified number of entries from memory (but not from disk).
285
   */
286
  void OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
287
                                 uint32_t aCurrentMemoryConsumption);
288
289
  /**
290
   * If not already pending, it schedules mPurgeTimer that fires after 1 second
291
   * and dispatches PurgeOverMemoryLimit().
292
   */
293
  void SchedulePurgeOverMemoryLimit();
294
295
  /**
296
   * Called on the management thread, removes all expired and then least used
297
   * entries from the memory, first from the disk pool and then from the memory
298
   * pool.
299
   */
300
  void PurgeOverMemoryLimit();
301
302
private:
303
  nsresult DoomStorageEntries(const nsACString& aContextKey,
304
                              nsILoadContextInfo* aContext,
305
                              bool aDiskStorage,
306
                              bool aPin,
307
                              nsICacheEntryDoomCallback* aCallback);
308
  nsresult AddStorageEntry(const nsACString& aContextKey,
309
                           const nsACString & aURI,
310
                           const nsACString & aIdExtension,
311
                           bool aWriteToDisk,
312
                           bool aSkipSizeCheck,
313
                           bool aPin,
314
                           bool aReplace,
315
                           CacheEntryHandle** aResult);
316
317
  nsresult ClearOriginInternal(const nsAString& aOrigin,
318
                               const mozilla::OriginAttributes& aOriginAttributes,
319
                               bool aAnonymous);
320
321
  static CacheStorageService* sSelf;
322
323
  mozilla::Mutex mLock;
324
  mozilla::Mutex mForcedValidEntriesLock;
325
326
  bool mShutdown;
327
328
  // Accessible only on the service thread
329
  class MemoryPool
330
  {
331
  public:
332
    enum EType
333
    {
334
      DISK,
335
      MEMORY,
336
    } mType;
337
338
    explicit MemoryPool(EType aType);
339
    ~MemoryPool();
340
341
    nsTArray<RefPtr<CacheEntry> > mFrecencyArray;
342
    nsTArray<RefPtr<CacheEntry> > mExpirationArray;
343
    Atomic<uint32_t, Relaxed> mMemorySize;
344
345
    bool OnMemoryConsumptionChange(uint32_t aSavedMemorySize,
346
                                   uint32_t aCurrentMemoryConsumption);
347
    /**
348
     * Purges entries from memory based on the frecency ordered array.
349
     */
350
    void PurgeOverMemoryLimit();
351
    void PurgeExpired();
352
    void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat);
353
    void PurgeAll(uint32_t aWhat);
354
355
  private:
356
    uint32_t Limit() const;
357
    MemoryPool() = delete;
358
  };
359
360
  MemoryPool mDiskPool;
361
  MemoryPool mMemoryPool;
362
  TimeStamp mLastPurgeTime;
363
  MemoryPool& Pool(bool aUsingDisk)
364
0
  {
365
0
    return aUsingDisk ? mDiskPool : mMemoryPool;
366
0
  }
367
  MemoryPool const& Pool(bool aUsingDisk) const
368
0
  {
369
0
    return aUsingDisk ? mDiskPool : mMemoryPool;
370
0
  }
371
372
  nsCOMPtr<nsITimer> mPurgeTimer;
373
374
  class PurgeFromMemoryRunnable : public Runnable
375
  {
376
  public:
377
    PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat)
378
      : Runnable("net::CacheStorageService::PurgeFromMemoryRunnable")
379
      , mService(aService)
380
      , mWhat(aWhat)
381
0
    {
382
0
    }
383
384
  private:
385
0
    virtual ~PurgeFromMemoryRunnable() = default;
386
387
    NS_IMETHOD Run() override;
388
389
    RefPtr<CacheStorageService> mService;
390
    uint32_t mWhat;
391
  };
392
393
  // Used just for telemetry purposes, accessed only on the management thread.
394
  // Note: not included in the memory reporter, this is not expected to be huge
395
  // and also would be complicated to report since reporting happens on the main
396
  // thread but this table is manipulated on the management thread.
397
  nsDataHashtable<nsCStringHashKey, mozilla::TimeStamp> mPurgeTimeStamps;
398
399
  // nsICacheTesting
400
  class IOThreadSuspender : public Runnable
401
  {
402
  public:
403
    IOThreadSuspender()
404
      : Runnable("net::CacheStorageService::IOThreadSuspender")
405
      , mMon("IOThreadSuspender")
406
      , mSignaled(false)
407
0
    {
408
0
    }
409
    void Notify();
410
  private:
411
0
    virtual ~IOThreadSuspender() = default;
412
    NS_IMETHOD Run() override;
413
414
    Monitor mMon;
415
    bool mSignaled;
416
  };
417
418
  RefPtr<IOThreadSuspender> mActiveIOSuspender;
419
};
420
421
template<class T>
422
void ProxyRelease(const char* aName, nsCOMPtr<T> &object, nsIEventTarget* target)
423
0
{
424
0
  NS_ProxyRelease(aName, target, object.forget());
425
0
}
Unexecuted instantiation: void mozilla::net::ProxyRelease<nsIApplicationCache>(char const*, nsCOMPtr<nsIApplicationCache>&, nsIEventTarget*)
Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheEntryOpenCallback>(char const*, nsCOMPtr<nsICacheEntryOpenCallback>&, nsIEventTarget*)
Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheStorageVisitor>(char const*, nsCOMPtr<nsICacheStorageVisitor>&, nsIEventTarget*)
Unexecuted instantiation: void mozilla::net::ProxyRelease<nsICacheEntryDoomCallback>(char const*, nsCOMPtr<nsICacheEntryDoomCallback>&, nsIEventTarget*)
426
427
template<class T>
428
void ProxyReleaseMainThread(const char* aName, nsCOMPtr<T> &object)
429
0
{
430
0
  ProxyRelease(aName, object, GetMainThreadEventTarget());
431
0
}
Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsIApplicationCache>(char const*, nsCOMPtr<nsIApplicationCache>&)
Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsICacheStorageVisitor>(char const*, nsCOMPtr<nsICacheStorageVisitor>&)
Unexecuted instantiation: void mozilla::net::ProxyReleaseMainThread<nsICacheEntryDoomCallback>(char const*, nsCOMPtr<nsICacheEntryDoomCallback>&)
432
433
} // namespace net
434
} // namespace mozilla
435
436
#define NS_CACHE_STORAGE_SERVICE_CID \
437
  { 0xea70b098, 0x5014, 0x4e21, \
438
  { 0xae, 0xe1, 0x75, 0xe6, 0xb2, 0xc4, 0xb8, 0xe0 } } \
439
440
#define NS_CACHE_STORAGE_SERVICE_CONTRACTID \
441
  "@mozilla.org/netwerk/cache-storage-service;1"
442
443
#define NS_CACHE_STORAGE_SERVICE_CONTRACTID2 \
444
  "@mozilla.org/network/cache-storage-service;1"
445
446
#endif