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 : #include "CacheObserver.h"
6 :
7 : #include "CacheStorageService.h"
8 : #include "CacheFileIOManager.h"
9 : #include "LoadContextInfo.h"
10 : #include "nsICacheStorage.h"
11 : #include "nsIObserverService.h"
12 : #include "mozilla/Services.h"
13 : #include "mozilla/Preferences.h"
14 : #include "mozilla/TimeStamp.h"
15 : #include "nsServiceManagerUtils.h"
16 : #include "mozilla/net/NeckoCommon.h"
17 : #include "prsystem.h"
18 : #include <time.h>
19 : #include <math.h>
20 :
21 : namespace mozilla {
22 : namespace net {
23 :
24 : CacheObserver* CacheObserver::sSelf = nullptr;
25 :
26 : static uint32_t const kDefaultUseNewCache = 1; // Use the new cache by default
27 : uint32_t CacheObserver::sUseNewCache = kDefaultUseNewCache;
28 :
29 : static bool sUseNewCacheTemp = false; // Temp trigger to not lose early adopters
30 :
31 : static int32_t const kAutoDeleteCacheVersion = -1; // Auto-delete off by default
32 : static int32_t sAutoDeleteCacheVersion = kAutoDeleteCacheVersion;
33 :
34 : static int32_t const kDefaultHalfLifeExperiment = -1; // Disabled
35 : int32_t CacheObserver::sHalfLifeExperiment = kDefaultHalfLifeExperiment;
36 :
37 : static float const kDefaultHalfLifeHours = 1.0F; // 1 hour
38 : float CacheObserver::sHalfLifeHours = kDefaultHalfLifeHours;
39 :
40 : static bool const kDefaultUseDiskCache = true;
41 : bool CacheObserver::sUseDiskCache = kDefaultUseDiskCache;
42 :
43 : static bool const kDefaultUseMemoryCache = true;
44 : bool CacheObserver::sUseMemoryCache = kDefaultUseMemoryCache;
45 :
46 : static uint32_t const kDefaultMetadataMemoryLimit = 250; // 0.25 MB
47 : uint32_t CacheObserver::sMetadataMemoryLimit = kDefaultMetadataMemoryLimit;
48 :
49 : static int32_t const kDefaultMemoryCacheCapacity = -1; // autodetect
50 : int32_t CacheObserver::sMemoryCacheCapacity = kDefaultMemoryCacheCapacity;
51 : // Cache of the calculated memory capacity based on the system memory size
52 : int32_t CacheObserver::sAutoMemoryCacheCapacity = -1;
53 :
54 : static uint32_t const kDefaultDiskCacheCapacity = 250 * 1024; // 250 MB
55 : Atomic<uint32_t,Relaxed> CacheObserver::sDiskCacheCapacity
56 : (kDefaultDiskCacheCapacity);
57 :
58 : static uint32_t const kDefaultDiskFreeSpaceSoftLimit = 5 * 1024; // 5MB
59 : uint32_t CacheObserver::sDiskFreeSpaceSoftLimit = kDefaultDiskFreeSpaceSoftLimit;
60 :
61 : static uint32_t const kDefaultDiskFreeSpaceHardLimit = 1024; // 1MB
62 : uint32_t CacheObserver::sDiskFreeSpaceHardLimit = kDefaultDiskFreeSpaceHardLimit;
63 :
64 : static bool const kDefaultSmartCacheSizeEnabled = false;
65 : bool CacheObserver::sSmartCacheSizeEnabled = kDefaultSmartCacheSizeEnabled;
66 :
67 : static uint32_t const kDefaultPreloadChunkCount = 4;
68 : uint32_t CacheObserver::sPreloadChunkCount = kDefaultPreloadChunkCount;
69 :
70 : static int32_t const kDefaultMaxMemoryEntrySize = 4 * 1024; // 4 MB
71 : int32_t CacheObserver::sMaxMemoryEntrySize = kDefaultMaxMemoryEntrySize;
72 :
73 : static int32_t const kDefaultMaxDiskEntrySize = 50 * 1024; // 50 MB
74 : int32_t CacheObserver::sMaxDiskEntrySize = kDefaultMaxDiskEntrySize;
75 :
76 : static uint32_t const kDefaultMaxDiskChunksMemoryUsage = 10 * 1024; // 10MB
77 : uint32_t CacheObserver::sMaxDiskChunksMemoryUsage = kDefaultMaxDiskChunksMemoryUsage;
78 :
79 : static uint32_t const kDefaultMaxDiskPriorityChunksMemoryUsage = 10 * 1024; // 10MB
80 : uint32_t CacheObserver::sMaxDiskPriorityChunksMemoryUsage = kDefaultMaxDiskPriorityChunksMemoryUsage;
81 :
82 : static uint32_t const kDefaultCompressionLevel = 1;
83 : uint32_t CacheObserver::sCompressionLevel = kDefaultCompressionLevel;
84 :
85 : static bool kDefaultSanitizeOnShutdown = false;
86 3 : bool CacheObserver::sSanitizeOnShutdown = kDefaultSanitizeOnShutdown;
87 :
88 : static bool kDefaultClearCacheOnShutdown = false;
89 3 : bool CacheObserver::sClearCacheOnShutdown = kDefaultClearCacheOnShutdown;
90 :
91 : static bool kDefaultCacheFSReported = false;
92 3 : bool CacheObserver::sCacheFSReported = kDefaultCacheFSReported;
93 :
94 : static bool kDefaultHashStatsReported = false;
95 3 : bool CacheObserver::sHashStatsReported = kDefaultHashStatsReported;
96 :
97 : static uint32_t const kDefaultMaxShutdownIOLag = 2; // seconds
98 : Atomic<uint32_t, Relaxed> CacheObserver::sMaxShutdownIOLag(kDefaultMaxShutdownIOLag);
99 :
100 : Atomic<PRIntervalTime> CacheObserver::sShutdownDemandedTime(PR_INTERVAL_NO_TIMEOUT);
101 :
102 43 : NS_IMPL_ISUPPORTS(CacheObserver,
103 : nsIObserver,
104 : nsISupportsWeakReference)
105 :
106 : // static
107 : nsresult
108 3 : CacheObserver::Init()
109 : {
110 3 : if (IsNeckoChild()) {
111 2 : return NS_OK;
112 : }
113 :
114 1 : if (sSelf) {
115 0 : return NS_OK;
116 : }
117 :
118 2 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
119 1 : if (!obs) {
120 0 : return NS_ERROR_UNEXPECTED;
121 : }
122 :
123 1 : sSelf = new CacheObserver();
124 1 : NS_ADDREF(sSelf);
125 :
126 1 : obs->AddObserver(sSelf, "prefservice:after-app-defaults", true);
127 1 : obs->AddObserver(sSelf, "profile-do-change", true);
128 1 : obs->AddObserver(sSelf, "browser-delayed-startup-finished", true);
129 1 : obs->AddObserver(sSelf, "profile-before-change", true);
130 1 : obs->AddObserver(sSelf, "xpcom-shutdown", true);
131 1 : obs->AddObserver(sSelf, "last-pb-context-exited", true);
132 1 : obs->AddObserver(sSelf, "clear-origin-attributes-data", true);
133 1 : obs->AddObserver(sSelf, "memory-pressure", true);
134 :
135 1 : return NS_OK;
136 : }
137 :
138 : // static
139 : nsresult
140 0 : CacheObserver::Shutdown()
141 : {
142 0 : if (!sSelf) {
143 0 : return NS_ERROR_NOT_INITIALIZED;
144 : }
145 :
146 0 : NS_RELEASE(sSelf);
147 0 : return NS_OK;
148 : }
149 :
150 : void
151 1 : CacheObserver::AttachToPreferences()
152 : {
153 1 : sAutoDeleteCacheVersion = mozilla::Preferences::GetInt(
154 : "browser.cache.auto_delete_cache_version", kAutoDeleteCacheVersion);
155 :
156 : mozilla::Preferences::AddUintVarCache(
157 1 : &sUseNewCache, "browser.cache.use_new_backend", kDefaultUseNewCache);
158 : mozilla::Preferences::AddBoolVarCache(
159 1 : &sUseNewCacheTemp, "browser.cache.use_new_backend_temp", false);
160 :
161 : mozilla::Preferences::AddBoolVarCache(
162 1 : &sUseDiskCache, "browser.cache.disk.enable", kDefaultUseDiskCache);
163 : mozilla::Preferences::AddBoolVarCache(
164 1 : &sUseMemoryCache, "browser.cache.memory.enable", kDefaultUseMemoryCache);
165 :
166 : mozilla::Preferences::AddUintVarCache(
167 1 : &sMetadataMemoryLimit, "browser.cache.disk.metadata_memory_limit", kDefaultMetadataMemoryLimit);
168 :
169 : mozilla::Preferences::AddAtomicUintVarCache(
170 1 : &sDiskCacheCapacity, "browser.cache.disk.capacity", kDefaultDiskCacheCapacity);
171 : mozilla::Preferences::AddBoolVarCache(
172 1 : &sSmartCacheSizeEnabled, "browser.cache.disk.smart_size.enabled", kDefaultSmartCacheSizeEnabled);
173 : mozilla::Preferences::AddIntVarCache(
174 1 : &sMemoryCacheCapacity, "browser.cache.memory.capacity", kDefaultMemoryCacheCapacity);
175 :
176 : mozilla::Preferences::AddUintVarCache(
177 1 : &sDiskFreeSpaceSoftLimit, "browser.cache.disk.free_space_soft_limit", kDefaultDiskFreeSpaceSoftLimit);
178 : mozilla::Preferences::AddUintVarCache(
179 1 : &sDiskFreeSpaceHardLimit, "browser.cache.disk.free_space_hard_limit", kDefaultDiskFreeSpaceHardLimit);
180 :
181 : mozilla::Preferences::AddUintVarCache(
182 1 : &sPreloadChunkCount, "browser.cache.disk.preload_chunk_count", kDefaultPreloadChunkCount);
183 :
184 : mozilla::Preferences::AddIntVarCache(
185 1 : &sMaxDiskEntrySize, "browser.cache.disk.max_entry_size", kDefaultMaxDiskEntrySize);
186 : mozilla::Preferences::AddIntVarCache(
187 1 : &sMaxMemoryEntrySize, "browser.cache.memory.max_entry_size", kDefaultMaxMemoryEntrySize);
188 :
189 : mozilla::Preferences::AddUintVarCache(
190 1 : &sMaxDiskChunksMemoryUsage, "browser.cache.disk.max_chunks_memory_usage", kDefaultMaxDiskChunksMemoryUsage);
191 : mozilla::Preferences::AddUintVarCache(
192 1 : &sMaxDiskPriorityChunksMemoryUsage, "browser.cache.disk.max_priority_chunks_memory_usage", kDefaultMaxDiskPriorityChunksMemoryUsage);
193 :
194 : // http://mxr.mozilla.org/mozilla-central/source/netwerk/cache/nsCacheEntryDescriptor.cpp#367
195 : mozilla::Preferences::AddUintVarCache(
196 1 : &sCompressionLevel, "browser.cache.compression_level", kDefaultCompressionLevel);
197 :
198 1 : mozilla::Preferences::GetComplex(
199 : "browser.cache.disk.parent_directory", NS_GET_IID(nsIFile),
200 2 : getter_AddRefs(mCacheParentDirectoryOverride));
201 :
202 : // First check the default value. If it is at -1, the experient
203 : // is turned off. If it is at 0, then use the user pref value
204 : // instead.
205 1 : sHalfLifeExperiment = mozilla::Preferences::GetDefaultInt(
206 : "browser.cache.frecency_experiment", kDefaultHalfLifeExperiment);
207 :
208 1 : if (sHalfLifeExperiment == 0) {
209 : // Default preferences indicate we want to run the experiment,
210 : // hence read the user value.
211 1 : sHalfLifeExperiment = mozilla::Preferences::GetInt(
212 : "browser.cache.frecency_experiment", sHalfLifeExperiment);
213 : }
214 :
215 1 : if (sHalfLifeExperiment == 0) {
216 : // The experiment has not yet been initialized but is engaged, do
217 : // the initialization now.
218 0 : srand(time(NULL));
219 0 : sHalfLifeExperiment = (rand() % 4) + 1;
220 : // Store the experiemnt value, since we need it not to change between
221 : // browser sessions.
222 : mozilla::Preferences::SetInt(
223 0 : "browser.cache.frecency_experiment", sHalfLifeExperiment);
224 : }
225 :
226 1 : switch (sHalfLifeExperiment) {
227 : case 1: // The experiment is engaged
228 0 : sHalfLifeHours = 0.083F; // ~5 mintues
229 0 : break;
230 : case 2:
231 1 : sHalfLifeHours = 0.25F; // 15 mintues
232 1 : break;
233 : case 3:
234 0 : sHalfLifeHours = 1.0F;
235 0 : break;
236 : case 4:
237 0 : sHalfLifeHours = 6.0F;
238 0 : break;
239 :
240 : case -1:
241 : default: // The experiment is off or broken
242 0 : sHalfLifeExperiment = -1;
243 0 : sHalfLifeHours = std::max(0.01F, std::min(1440.0F, mozilla::Preferences::GetFloat(
244 0 : "browser.cache.frecency_half_life_hours", kDefaultHalfLifeHours)));
245 0 : break;
246 : }
247 :
248 1 : mozilla::Preferences::AddBoolVarCache(
249 1 : &sSanitizeOnShutdown, "privacy.sanitize.sanitizeOnShutdown", kDefaultSanitizeOnShutdown);
250 1 : mozilla::Preferences::AddBoolVarCache(
251 1 : &sClearCacheOnShutdown, "privacy.clearOnShutdown.cache", kDefaultClearCacheOnShutdown);
252 :
253 : mozilla::Preferences::AddAtomicUintVarCache(
254 1 : &sMaxShutdownIOLag, "browser.cache.max_shutdown_io_lag", kDefaultMaxShutdownIOLag);
255 1 : }
256 :
257 : // static
258 0 : uint32_t CacheObserver::MemoryCacheCapacity()
259 : {
260 0 : if (sMemoryCacheCapacity >= 0)
261 0 : return sMemoryCacheCapacity << 10;
262 :
263 0 : if (sAutoMemoryCacheCapacity != -1)
264 0 : return sAutoMemoryCacheCapacity;
265 :
266 0 : static uint64_t bytes = PR_GetPhysicalMemorySize();
267 : // If getting the physical memory failed, arbitrarily assume
268 : // 32 MB of RAM. We use a low default to have a reasonable
269 : // size on all the devices we support.
270 0 : if (bytes == 0)
271 0 : bytes = 32 * 1024 * 1024;
272 :
273 : // Conversion from unsigned int64_t to double doesn't work on all platforms.
274 : // We need to truncate the value at INT64_MAX to make sure we don't
275 : // overflow.
276 0 : if (bytes > INT64_MAX)
277 0 : bytes = INT64_MAX;
278 :
279 0 : uint64_t kbytes = bytes >> 10;
280 0 : double kBytesD = double(kbytes);
281 0 : double x = log(kBytesD)/log(2.0) - 14;
282 :
283 0 : int32_t capacity = 0;
284 0 : if (x > 0) {
285 0 : capacity = (int32_t)(x * x / 3.0 + x + 2.0 / 3 + 0.1); // 0.1 for rounding
286 0 : if (capacity > 32)
287 0 : capacity = 32;
288 0 : capacity <<= 20;
289 : }
290 :
291 : // Result is in bytes.
292 0 : return sAutoMemoryCacheCapacity = capacity;
293 : }
294 :
295 : // static
296 28 : bool CacheObserver::UseNewCache()
297 : {
298 28 : uint32_t useNewCache = sUseNewCache;
299 :
300 28 : if (sUseNewCacheTemp)
301 20 : useNewCache = 1;
302 :
303 28 : switch (useNewCache) {
304 : case 0: // use the old cache backend
305 0 : return false;
306 :
307 : case 1: // use the new cache backend
308 28 : return true;
309 : }
310 :
311 0 : return true;
312 : }
313 :
314 : // static
315 : void
316 0 : CacheObserver::SetDiskCacheCapacity(uint32_t aCapacity)
317 : {
318 0 : sDiskCacheCapacity = aCapacity >> 10;
319 :
320 0 : if (!sSelf) {
321 0 : return;
322 : }
323 :
324 0 : if (NS_IsMainThread()) {
325 0 : sSelf->StoreDiskCacheCapacity();
326 : } else {
327 : nsCOMPtr<nsIRunnable> event =
328 0 : NewRunnableMethod("net::CacheObserver::StoreDiskCacheCapacity",
329 : sSelf,
330 0 : &CacheObserver::StoreDiskCacheCapacity);
331 0 : NS_DispatchToMainThread(event);
332 : }
333 : }
334 :
335 : void
336 0 : CacheObserver::StoreDiskCacheCapacity()
337 : {
338 0 : mozilla::Preferences::SetInt("browser.cache.disk.capacity",
339 0 : sDiskCacheCapacity);
340 0 : }
341 :
342 : // static
343 : void
344 1 : CacheObserver::SetCacheFSReported()
345 : {
346 1 : sCacheFSReported = true;
347 :
348 1 : if (!sSelf) {
349 0 : return;
350 : }
351 :
352 1 : if (NS_IsMainThread()) {
353 0 : sSelf->StoreCacheFSReported();
354 : } else {
355 : nsCOMPtr<nsIRunnable> event =
356 2 : NewRunnableMethod("net::CacheObserver::StoreCacheFSReported",
357 : sSelf,
358 2 : &CacheObserver::StoreCacheFSReported);
359 1 : NS_DispatchToMainThread(event);
360 : }
361 : }
362 :
363 : void
364 1 : CacheObserver::StoreCacheFSReported()
365 : {
366 1 : mozilla::Preferences::SetInt("browser.cache.disk.filesystem_reported",
367 1 : sCacheFSReported);
368 1 : }
369 :
370 : // static
371 : void
372 0 : CacheObserver::SetHashStatsReported()
373 : {
374 0 : sHashStatsReported = true;
375 :
376 0 : if (!sSelf) {
377 0 : return;
378 : }
379 :
380 0 : if (NS_IsMainThread()) {
381 0 : sSelf->StoreHashStatsReported();
382 : } else {
383 : nsCOMPtr<nsIRunnable> event =
384 0 : NewRunnableMethod("net::CacheObserver::StoreHashStatsReported",
385 : sSelf,
386 0 : &CacheObserver::StoreHashStatsReported);
387 0 : NS_DispatchToMainThread(event);
388 : }
389 : }
390 :
391 : void
392 0 : CacheObserver::StoreHashStatsReported()
393 : {
394 0 : mozilla::Preferences::SetInt("browser.cache.disk.hashstats_reported",
395 0 : sHashStatsReported);
396 0 : }
397 :
398 : // static
399 1 : void CacheObserver::ParentDirOverride(nsIFile** aDir)
400 : {
401 1 : if (NS_WARN_IF(!aDir))
402 0 : return;
403 :
404 1 : *aDir = nullptr;
405 :
406 1 : if (!sSelf)
407 0 : return;
408 1 : if (!sSelf->mCacheParentDirectoryOverride)
409 1 : return;
410 :
411 0 : sSelf->mCacheParentDirectoryOverride->Clone(aDir);
412 : }
413 :
414 : namespace {
415 : namespace CacheStorageEvictHelper {
416 :
417 0 : nsresult ClearStorage(bool const aPrivate,
418 : bool const aAnonymous,
419 : OriginAttributes &aOa)
420 : {
421 : nsresult rv;
422 :
423 0 : aOa.SyncAttributesWithPrivateBrowsing(aPrivate);
424 0 : RefPtr<LoadContextInfo> info = GetLoadContextInfo(aAnonymous, aOa);
425 :
426 0 : nsCOMPtr<nsICacheStorage> storage;
427 0 : RefPtr<CacheStorageService> service = CacheStorageService::Self();
428 0 : NS_ENSURE_TRUE(service, NS_ERROR_FAILURE);
429 :
430 : // Clear disk storage
431 0 : rv = service->DiskCacheStorage(info, false, getter_AddRefs(storage));
432 0 : NS_ENSURE_SUCCESS(rv, rv);
433 0 : rv = storage->AsyncEvictStorage(nullptr);
434 0 : NS_ENSURE_SUCCESS(rv, rv);
435 :
436 : // Clear memory storage
437 0 : rv = service->MemoryCacheStorage(info, getter_AddRefs(storage));
438 0 : NS_ENSURE_SUCCESS(rv, rv);
439 0 : rv = storage->AsyncEvictStorage(nullptr);
440 0 : NS_ENSURE_SUCCESS(rv, rv);
441 :
442 0 : return NS_OK;
443 : }
444 :
445 0 : nsresult Run(OriginAttributes &aOa)
446 : {
447 : nsresult rv;
448 :
449 : // Clear all [private X anonymous] combinations
450 0 : rv = ClearStorage(false, false, aOa);
451 0 : NS_ENSURE_SUCCESS(rv, rv);
452 0 : rv = ClearStorage(false, true, aOa);
453 0 : NS_ENSURE_SUCCESS(rv, rv);
454 0 : rv = ClearStorage(true, false, aOa);
455 0 : NS_ENSURE_SUCCESS(rv, rv);
456 0 : rv = ClearStorage(true, true, aOa);
457 0 : NS_ENSURE_SUCCESS(rv, rv);
458 :
459 0 : return NS_OK;
460 : }
461 :
462 : } // CacheStorageEvictHelper
463 : } // anon
464 :
465 : // static
466 7 : bool CacheObserver::EntryIsTooBig(int64_t aSize, bool aUsingDisk)
467 : {
468 : // If custom limit is set, check it.
469 7 : int64_t preferredLimit = aUsingDisk ? sMaxDiskEntrySize : sMaxMemoryEntrySize;
470 :
471 : // do not convert to bytes when the limit is -1, which means no limit
472 7 : if (preferredLimit > 0) {
473 7 : preferredLimit <<= 10;
474 : }
475 :
476 7 : if (preferredLimit != -1 && aSize > preferredLimit)
477 0 : return true;
478 :
479 : // Otherwise (or when in the custom limit), check limit based on the global
480 : // limit. It's 1/8 (>> 3) of the respective capacity.
481 : int64_t derivedLimit = aUsingDisk
482 7 : ? (static_cast<int64_t>(DiskCacheCapacity() >> 3))
483 7 : : (static_cast<int64_t>(MemoryCacheCapacity() >> 3));
484 :
485 7 : if (aSize > derivedLimit)
486 0 : return true;
487 :
488 7 : return false;
489 : }
490 :
491 : // static
492 10 : bool CacheObserver::IsPastShutdownIOLag()
493 : {
494 : #ifdef DEBUG
495 10 : return false;
496 : #endif
497 :
498 : if (sShutdownDemandedTime == PR_INTERVAL_NO_TIMEOUT ||
499 : sMaxShutdownIOLag == UINT32_MAX) {
500 : return false;
501 : }
502 :
503 : static const PRIntervalTime kMaxShutdownIOLag =
504 : PR_SecondsToInterval(sMaxShutdownIOLag);
505 :
506 : if ((PR_IntervalNow() - sShutdownDemandedTime) > kMaxShutdownIOLag) {
507 : return true;
508 : }
509 :
510 : return false;
511 : }
512 :
513 : NS_IMETHODIMP
514 2 : CacheObserver::Observe(nsISupports* aSubject,
515 : const char* aTopic,
516 : const char16_t* aData)
517 : {
518 2 : if (!strcmp(aTopic, "prefservice:after-app-defaults")) {
519 0 : CacheFileIOManager::Init();
520 0 : return NS_OK;
521 : }
522 :
523 2 : if (!strcmp(aTopic, "profile-do-change")) {
524 1 : AttachToPreferences();
525 1 : CacheFileIOManager::Init();
526 1 : CacheFileIOManager::OnProfile();
527 1 : return NS_OK;
528 : }
529 :
530 1 : if (!strcmp(aTopic, "browser-delayed-startup-finished")) {
531 1 : uint32_t activeVersion = UseNewCache() ? 1 : 0;
532 1 : CacheStorageService::CleaupCacheDirectories(sAutoDeleteCacheVersion, activeVersion);
533 1 : return NS_OK;
534 : }
535 :
536 0 : if (!strcmp(aTopic, "profile-change-net-teardown") ||
537 0 : !strcmp(aTopic, "profile-before-change") ||
538 0 : !strcmp(aTopic, "xpcom-shutdown")) {
539 0 : if (sShutdownDemandedTime == PR_INTERVAL_NO_TIMEOUT) {
540 0 : sShutdownDemandedTime = PR_IntervalNow();
541 : }
542 :
543 0 : RefPtr<CacheStorageService> service = CacheStorageService::Self();
544 0 : if (service) {
545 0 : service->Shutdown();
546 : }
547 :
548 0 : CacheFileIOManager::Shutdown();
549 0 : return NS_OK;
550 : }
551 :
552 0 : if (!strcmp(aTopic, "last-pb-context-exited")) {
553 0 : RefPtr<CacheStorageService> service = CacheStorageService::Self();
554 0 : if (service) {
555 0 : service->DropPrivateBrowsingEntries();
556 : }
557 :
558 0 : return NS_OK;
559 : }
560 :
561 0 : if (!strcmp(aTopic, "clear-origin-attributes-data")) {
562 0 : OriginAttributes oa;
563 0 : if (!oa.Init(nsDependentString(aData))) {
564 0 : NS_ERROR("Could not parse OriginAttributes JSON in clear-origin-attributes-data notification");
565 0 : return NS_OK;
566 : }
567 :
568 0 : nsresult rv = CacheStorageEvictHelper::Run(oa);
569 0 : NS_ENSURE_SUCCESS(rv, rv);
570 :
571 0 : return NS_OK;
572 : }
573 :
574 0 : if (!strcmp(aTopic, "memory-pressure")) {
575 0 : RefPtr<CacheStorageService> service = CacheStorageService::Self();
576 0 : if (service)
577 0 : service->PurgeFromMemory(nsICacheStorageService::PURGE_EVERYTHING);
578 :
579 0 : return NS_OK;
580 : }
581 :
582 0 : MOZ_ASSERT(false, "Missing observer handler");
583 : return NS_OK;
584 : }
585 :
586 : } // namespace net
587 9 : } // namespace mozilla
|