Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/cache/nsCacheService.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef _nsCacheService_h_
8
#define _nsCacheService_h_
9
10
#include "nsICacheService.h"
11
#include "nsCacheSession.h"
12
#include "nsCacheDevice.h"
13
#include "nsCacheEntry.h"
14
#include "nsThreadUtils.h"
15
#include "nsICacheListener.h"
16
#include "nsIMemoryReporter.h"
17
18
#include "prthread.h"
19
#include "nsIObserver.h"
20
#include "nsString.h"
21
#include "nsTArray.h"
22
#include "nsRefPtrHashtable.h"
23
#include "mozilla/CondVar.h"
24
#include "mozilla/Mutex.h"
25
#include "mozilla/Telemetry.h"
26
27
class nsCacheRequest;
28
class nsCacheProfilePrefObserver;
29
class nsDiskCacheDevice;
30
class nsMemoryCacheDevice;
31
class nsOfflineCacheDevice;
32
class nsCacheServiceAutoLock;
33
class nsITimer;
34
class mozIStorageService;
35
36
37
/******************************************************************************
38
 * nsNotifyDoomListener
39
 *****************************************************************************/
40
41
class nsNotifyDoomListener : public mozilla::Runnable {
42
public:
43
  nsNotifyDoomListener(nsICacheListener* listener, nsresult status)
44
    : mozilla::Runnable("nsNotifyDoomListener")
45
    , mListener(listener) // transfers reference
46
    , mStatus(status)
47
0
  {
48
0
  }
49
50
  NS_IMETHOD Run() override
51
0
  {
52
0
    mListener->OnCacheEntryDoomed(mStatus);
53
0
    NS_RELEASE(mListener);
54
0
    return NS_OK;
55
0
    }
56
57
private:
58
    nsICacheListener *mListener;
59
    nsresult          mStatus;
60
};
61
62
/******************************************************************************
63
 *  nsCacheService
64
 ******************************************************************************/
65
66
class nsCacheService final : public nsICacheServiceInternal,
67
                             public nsIMemoryReporter
68
{
69
    virtual ~nsCacheService();
70
71
public:
72
    NS_DECL_THREADSAFE_ISUPPORTS
73
    NS_DECL_NSICACHESERVICE
74
    NS_DECL_NSICACHESERVICEINTERNAL
75
    NS_DECL_NSIMEMORYREPORTER
76
77
    nsCacheService();
78
79
    // Define a Create method to be used with a factory:
80
    static nsresult
81
    Create(nsISupports* outer, const nsIID& iid, void* *result);
82
83
84
    /**
85
     * Methods called by nsCacheSession
86
     */
87
    static nsresult  OpenCacheEntry(nsCacheSession *           session,
88
                                    const nsACString &         key,
89
                                    nsCacheAccessMode          accessRequested,
90
                                    bool                       blockingMode,
91
                                    nsICacheListener *         listener,
92
                                    nsICacheEntryDescriptor ** result);
93
94
    static nsresult  EvictEntriesForSession(nsCacheSession *   session);
95
96
    static nsresult  IsStorageEnabledForPolicy(nsCacheStoragePolicy  storagePolicy,
97
                                               bool *              result);
98
99
    static nsresult  DoomEntry(nsCacheSession   *session,
100
                               const nsACString &key,
101
                               nsICacheListener *listener);
102
103
    /**
104
     * Methods called by nsCacheEntryDescriptor
105
     */
106
107
    static void      CloseDescriptor(nsCacheEntryDescriptor * descriptor);
108
109
    static nsresult  GetFileForEntry(nsCacheEntry *         entry,
110
                                     nsIFile **             result);
111
112
    static nsresult  OpenInputStreamForEntry(nsCacheEntry *     entry,
113
                                             nsCacheAccessMode  mode,
114
                                             uint32_t           offset,
115
                                             nsIInputStream **  result);
116
117
    static nsresult  OpenOutputStreamForEntry(nsCacheEntry *     entry,
118
                                              nsCacheAccessMode  mode,
119
                                              uint32_t           offset,
120
                                              nsIOutputStream ** result);
121
122
    static nsresult  OnDataSizeChange(nsCacheEntry * entry, int32_t deltaSize);
123
124
    static nsresult  SetCacheElement(nsCacheEntry * entry, nsISupports * element);
125
126
    static nsresult  ValidateEntry(nsCacheEntry * entry);
127
128
    static int32_t   CacheCompressionLevel();
129
130
    static bool      GetClearingEntries();
131
132
    static void      GetCacheBaseDirectoty(nsIFile ** result);
133
    static void      GetDiskCacheDirectory(nsIFile ** result);
134
    static void      GetAppCacheDirectory(nsIFile ** result);
135
136
    /**
137
     * Methods called by any cache classes
138
     */
139
140
    static
141
0
    nsCacheService * GlobalInstance()   { return gService; }
142
143
    static nsresult  DoomEntry(nsCacheEntry * entry);
144
145
    static bool      IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy);
146
147
    /**
148
     * Called by disk cache to notify us to use the new max smart size
149
     */
150
    static void      MarkStartingFresh();
151
152
    /**
153
     * Methods called by nsApplicationCacheService
154
     */
155
156
    nsresult GetOfflineDevice(nsOfflineCacheDevice ** aDevice);
157
158
    /**
159
     * Creates an offline cache device that works over a specific profile directory.
160
     * A tool to preload offline cache for profiles different from the current
161
     * application's profile directory.
162
     */
163
    nsresult GetCustomOfflineDevice(nsIFile *aProfileDir,
164
                                    int32_t aQuota,
165
                                    nsOfflineCacheDevice **aDevice);
166
167
    // This method may be called to release an object while the cache service
168
    // lock is being held.  If a non-null target is specified and the target
169
    // does not correspond to the current thread, then the release will be
170
    // proxied to the specified target.  Otherwise, the object will be added to
171
    // the list of objects to be released when the cache service is unlocked.
172
    static void      ReleaseObject_Locked(nsISupports *    object,
173
                                          nsIEventTarget * target = nullptr);
174
175
    static nsresult DispatchToCacheIOThread(nsIRunnable* event);
176
177
    // Calling this method will block the calling thread until all pending
178
    // events on the cache-io thread has finished. The calling thread must
179
    // hold the cache-lock
180
    static nsresult SyncWithCacheIOThread();
181
182
183
    /**
184
     * Methods called by nsCacheProfilePrefObserver
185
     */
186
    static void      OnProfileShutdown();
187
    static void      OnProfileChanged();
188
189
    static void      SetDiskCacheEnabled(bool    enabled);
190
    // Sets the disk cache capacity (in kilobytes)
191
    static void      SetDiskCacheCapacity(int32_t  capacity);
192
    // Set max size for a disk-cache entry (in KB). -1 disables limit up to
193
    // 1/8th of disk cache size
194
    static void      SetDiskCacheMaxEntrySize(int32_t  maxSize);
195
    // Set max size for a memory-cache entry (in kilobytes). -1 disables
196
    // limit up to 90% of memory cache size
197
    static void      SetMemoryCacheMaxEntrySize(int32_t  maxSize);
198
199
    static void      SetOfflineCacheEnabled(bool    enabled);
200
    // Sets the offline cache capacity (in kilobytes)
201
    static void      SetOfflineCacheCapacity(int32_t  capacity);
202
203
    static void      SetMemoryCache();
204
205
    static void      SetCacheCompressionLevel(int32_t level);
206
207
    // Starts smart cache size computation if disk device is available
208
    static nsresult  SetDiskSmartSize();
209
210
    static void      MoveOrRemoveDiskCache(nsIFile *aOldCacheDir,
211
                                           nsIFile *aNewCacheDir,
212
                                           const char *aCacheSubdir);
213
214
    nsresult         Init();
215
    void             Shutdown();
216
217
    static bool      IsInitialized()
218
0
    {
219
0
      if (!gService) {
220
0
          return false;
221
0
      }
222
0
      return gService->mInitialized;
223
0
    }
224
225
    static void      AssertOwnsLock()
226
0
    { gService->mLock.AssertCurrentThreadOwns(); }
227
228
    static void      LeavePrivateBrowsing();
229
    bool             IsDoomListEmpty();
230
231
    typedef bool (*DoomCheckFn)(nsCacheEntry* entry);
232
233
    // Accessors to the disabled functionality
234
    nsresult CreateSessionInternal(const char *          clientID,
235
                                   nsCacheStoragePolicy  storagePolicy,
236
                                   bool                  streamBased,
237
                                   nsICacheSession     **result);
238
    nsresult VisitEntriesInternal(nsICacheVisitor *visitor);
239
    nsresult EvictEntriesInternal(nsCacheStoragePolicy storagePolicy);
240
241
private:
242
    friend class nsCacheServiceAutoLock;
243
    friend class nsOfflineCacheDevice;
244
    friend class nsProcessRequestEvent;
245
    friend class nsSetSmartSizeEvent;
246
    friend class nsBlockOnCacheThreadEvent;
247
    friend class nsSetDiskSmartSizeCallback;
248
    friend class nsDoomEvent;
249
    friend class nsDisableOldMaxSmartSizePrefEvent;
250
    friend class nsDiskCacheMap;
251
    friend class nsAsyncDoomEvent;
252
    friend class nsCacheEntryDescriptor;
253
254
    /**
255
     * Internal Methods
256
     */
257
258
    static void      Lock();
259
    static void      Lock(::mozilla::Telemetry::HistogramID mainThreadLockerID);
260
    static void      Unlock();
261
    void             LockAcquired();
262
    void             LockReleased();
263
264
    nsresult         CreateDiskDevice();
265
    nsresult         CreateOfflineDevice();
266
    nsresult         CreateCustomOfflineDevice(nsIFile *aProfileDir,
267
                                               int32_t aQuota,
268
                                               nsOfflineCacheDevice **aDevice);
269
    nsresult         CreateMemoryDevice();
270
271
    nsresult         RemoveCustomOfflineDevice(nsOfflineCacheDevice *aDevice);
272
273
    nsresult         CreateRequest(nsCacheSession *   session,
274
                                   const nsACString & clientKey,
275
                                   nsCacheAccessMode  accessRequested,
276
                                   bool               blockingMode,
277
                                   nsICacheListener * listener,
278
                                   nsCacheRequest **  request);
279
280
    nsresult         DoomEntry_Internal(nsCacheEntry * entry,
281
                                        bool doProcessPendingRequests);
282
283
    nsresult         EvictEntriesForClient(const char *          clientID,
284
                                           nsCacheStoragePolicy  storagePolicy);
285
286
    // Notifies request listener asynchronously on the request's thread, and
287
    // releases the descriptor on the request's thread.  If this method fails,
288
    // the descriptor is not released.
289
    nsresult         NotifyListener(nsCacheRequest *          request,
290
                                    nsICacheEntryDescriptor * descriptor,
291
                                    nsCacheAccessMode         accessGranted,
292
                                    nsresult                  error);
293
294
    nsresult         ActivateEntry(nsCacheRequest * request,
295
                                   nsCacheEntry ** entry,
296
                                   nsCacheEntry ** doomedEntry);
297
298
    nsCacheDevice *  EnsureEntryHasDevice(nsCacheEntry * entry);
299
300
    nsCacheEntry *   SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy, bool *collision);
301
302
    void             DeactivateEntry(nsCacheEntry * entry);
303
304
    nsresult         ProcessRequest(nsCacheRequest *           request,
305
                                    bool                       calledFromOpenCacheEntry,
306
                                    nsICacheEntryDescriptor ** result);
307
308
    nsresult         ProcessPendingRequests(nsCacheEntry * entry);
309
310
    void             ClearDoomList(void);
311
    void             DoomActiveEntries(DoomCheckFn check);
312
    void             CloseAllStreams();
313
    void             FireClearNetworkCacheStoredAnywhereNotification();
314
315
    void LogCacheStatistics();
316
317
    nsresult         SetDiskSmartSize_Locked();
318
319
    /**
320
     *  Data Members
321
     */
322
323
    static nsCacheService *         gService;  // there can be only one...
324
325
    nsCOMPtr<mozIStorageService>    mStorageService;
326
327
    nsCacheProfilePrefObserver *    mObserver;
328
329
    mozilla::Mutex                  mLock;
330
    mozilla::CondVar                mCondVar;
331
    bool                            mNotified;
332
333
    mozilla::Mutex                  mTimeStampLock;
334
    mozilla::TimeStamp              mLockAcquiredTimeStamp;
335
336
    nsCOMPtr<nsIThread>             mCacheIOThread;
337
338
    nsTArray<nsISupports*>          mDoomedObjects;
339
    nsCOMPtr<nsITimer>              mSmartSizeTimer;
340
341
    bool                            mInitialized;
342
    bool                            mClearingEntries;
343
344
    bool                            mEnableMemoryDevice;
345
    bool                            mEnableDiskDevice;
346
    bool                            mEnableOfflineDevice;
347
348
    nsMemoryCacheDevice *           mMemoryDevice;
349
    nsDiskCacheDevice *             mDiskDevice;
350
    nsOfflineCacheDevice *          mOfflineDevice;
351
352
    nsRefPtrHashtable<nsStringHashKey, nsOfflineCacheDevice> mCustomOfflineDevices;
353
354
    nsCacheEntryHashTable           mActiveEntries;
355
    PRCList                         mDoomedEntries;
356
357
    // stats
358
359
    uint32_t                        mTotalEntries;
360
    uint32_t                        mCacheHits;
361
    uint32_t                        mCacheMisses;
362
    uint32_t                        mMaxKeyLength;
363
    uint32_t                        mMaxDataSize;
364
    uint32_t                        mMaxMetaSize;
365
366
    // Unexpected error totals
367
    uint32_t                        mDeactivateFailures;
368
    uint32_t                        mDeactivatedUnboundEntries;
369
};
370
371
/******************************************************************************
372
 *  nsCacheServiceAutoLock
373
 ******************************************************************************/
374
375
#define LOCK_TELEM(x) \
376
0
  (::mozilla::Telemetry::CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_##x)
377
378
// Instantiate this class to acquire the cache service lock for a particular
379
// execution scope.
380
class nsCacheServiceAutoLock {
381
public:
382
0
    nsCacheServiceAutoLock() {
383
0
        nsCacheService::Lock();
384
0
    }
385
0
    explicit nsCacheServiceAutoLock(mozilla::Telemetry::HistogramID mainThreadLockerID) {
386
0
        nsCacheService::Lock(mainThreadLockerID);
387
0
    }
388
0
    ~nsCacheServiceAutoLock() {
389
0
        nsCacheService::Unlock();
390
0
    }
391
};
392
393
#endif // _nsCacheService_h_