[go: nahoru, domu]

blob: f6785665d02164cb2d8bd956dc46639f8fb33cfa [file] [log] [blame]
Avi Drissman4e1b7bc2022-09-15 14:03:501// Copyright 2014 The Chromium Authors
jkarlin@chromium.org10e9d5d2014-08-09 05:35:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
jsbell279efb42015-03-31 17:02:465#include "content/browser/cache_storage/cache_storage_manager.h"
jkarlin@chromium.org10e9d5d2014-08-09 05:35:176
Evan Stadef3a6c0c2022-04-06 23:57:357#include <stdint.h>
8
9#include <map>
10#include <numeric>
Arthur Sonzognic686e8f2024-01-11 08:36:3711#include <optional>
Evan Stadef3a6c0c2022-04-06 23:57:3512#include <set>
Andrew Williams9eaa2a052022-08-17 02:43:1013#include <tuple>
Evan Stadef3a6c0c2022-04-06 23:57:3514#include <utility>
Andrew Williams97fa8532022-11-29 21:16:2515#include <vector>
Evan Stadef3a6c0c2022-04-06 23:57:3516
Andrew Williams9eaa2a052022-08-17 02:43:1017#include "base/barrier_callback.h"
Evan Stadef3a6c0c2022-04-06 23:57:3518#include "base/containers/id_map.h"
19#include "base/files/file_enumerator.h"
20#include "base/files/file_util.h"
Avi Drissmanadac21992023-01-11 23:46:3921#include "base/functional/bind.h"
22#include "base/functional/callback_helpers.h"
Evan Stadef3a6c0c2022-04-06 23:57:3523#include "base/hash/sha1.h"
24#include "base/memory/ptr_util.h"
Andrew Williams9eaa2a052022-08-17 02:43:1025#include "base/memory/scoped_refptr.h"
26#include "base/memory/weak_ptr.h"
Evan Stadef3a6c0c2022-04-06 23:57:3527#include "base/metrics/histogram_functions.h"
Andrew Williams9eaa2a052022-08-17 02:43:1028#include "base/notreached.h"
29#include "base/sequence_checker.h"
Evan Stadef3a6c0c2022-04-06 23:57:3530#include "base/strings/string_number_conversions.h"
31#include "base/strings/string_util.h"
32#include "base/task/sequenced_task_runner.h"
Evan Stadef3a6c0c2022-04-06 23:57:3533#include "base/time/time.h"
Pei Zhangcc4549e2022-05-07 02:51:1334#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
Evan Stadef3a6c0c2022-04-06 23:57:3535#include "components/services/storage/public/cpp/constants.h"
Andrew Williams9eaa2a052022-08-17 02:43:1036#include "components/services/storage/public/mojom/storage_usage_info.mojom-forward.h"
Evan Stadef3a6c0c2022-04-06 23:57:3537#include "content/browser/cache_storage/cache_storage.h"
38#include "content/browser/cache_storage/cache_storage.pb.h"
39#include "content/browser/cache_storage/cache_storage_quota_client.h"
40#include "storage/browser/quota/quota_manager_proxy.h"
Andrew Williams691aceb2022-07-18 17:44:1041#include "storage/browser/quota/storage_directory_util.h"
Evan Stadef3a6c0c2022-04-06 23:57:3542#include "storage/common/database/database_identifier.h"
Antonio Sartoricd09590d2021-06-02 08:51:0643#include "third_party/blink/public/common/storage_key/storage_key.h"
Evan Stadef3a6c0c2022-04-06 23:57:3544#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
45#include "url/gurl.h"
46#include "url/origin.h"
jkarlin@chromium.org10e9d5d2014-08-09 05:35:1747
jkarlind2d1b62f2014-10-21 01:41:5248namespace content {
49
Evan Stadef3a6c0c2022-04-06 23:57:3550namespace {
51
52bool DeleteDir(const base::FilePath& path) {
53 return base::DeletePathRecursively(path);
54}
55
Andrew Williams9eaa2a052022-08-17 02:43:1056void DeleteBucketDidDeleteDir(
Evan Stadef3a6c0c2022-04-06 23:57:3557 storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
58 bool rv) {
59 // On scheduler sequence.
Sean Maher52fa5a72022-11-14 15:53:2560 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Evan Stadef3a6c0c2022-04-06 23:57:3561 FROM_HERE,
62 base::BindOnce(std::move(callback),
63 rv ? blink::mojom::QuotaStatusCode::kOk
64 : blink::mojom::QuotaStatusCode::kErrorAbort));
65}
66
Andrew Williams9eaa2a052022-08-17 02:43:1067void DeleteStorageKeyDidDeleteAllData(
68 storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
69 std::vector<blink::mojom::QuotaStatusCode> results) {
70 // On scheduler sequence.
71 for (auto result : results) {
72 if (result != blink::mojom::QuotaStatusCode::kOk) {
Sean Maher52fa5a72022-11-14 15:53:2573 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Andrew Williams9eaa2a052022-08-17 02:43:1074 FROM_HERE, base::BindOnce(std::move(callback), result));
75 return;
76 }
77 }
Sean Maher52fa5a72022-11-14 15:53:2578 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Andrew Williams9eaa2a052022-08-17 02:43:1079 FROM_HERE,
80 base::BindOnce(std::move(callback), blink::mojom::QuotaStatusCode::kOk));
81}
82
Evan Stadef3a6c0c2022-04-06 23:57:3583// Calculate the sum of all cache sizes in this store, but only if all sizes are
84// known. If one or more sizes are not known then return kSizeUnknown.
85int64_t GetCacheStorageSize(const base::FilePath& base_path,
86 const base::Time& index_time,
87 const proto::CacheStorageIndex& index) {
88 // Note, do not use the base path time modified to invalidate the index file.
89 // On some platforms the directory modified time will be slightly later than
90 // the last modified time of a file within it. This means any write to the
91 // index file will also update the directory modify time slightly after
92 // immediately invalidating it. To avoid this we only look at the cache
93 // directories and not the base directory containing the index itself.
94 int64_t storage_size = 0;
95 for (int i = 0, max = index.cache_size(); i < max; ++i) {
96 const proto::CacheStorageIndex::Cache& cache = index.cache(i);
97 if (!cache.has_cache_dir() || !cache.has_size() ||
98 cache.size() == CacheStorage::kSizeUnknown || !cache.has_padding() ||
99 cache.padding() == CacheStorage::kSizeUnknown) {
100 return CacheStorage::kSizeUnknown;
101 }
102
103 // Check the modified time on each cache directory. If one of the
104 // directories has the same or newer modified time as the index file, then
105 // its size is most likely not accounted for in the index file. The
106 // cache can have a newer time here in spite of our base path time check
107 // above since simple disk_cache writes to these directories from a
108 // different thread.
109 base::FilePath path = base_path.AppendASCII(cache.cache_dir());
110 base::File::Info file_info;
111 if (!base::GetFileInfo(path, &file_info) ||
112 file_info.last_modified >= index_time) {
113 return CacheStorage::kSizeUnknown;
114 }
115
116 storage_size += (cache.size() + cache.padding());
117 }
118
119 return storage_size;
120}
121
122// These values are persisted to logs. Entries should not be renumbered and
123// numeric values should never be reused.
124enum class IndexResult {
125 kOk = 0,
126 kFailedToParse = 1,
127 kMissingOrigin = 2,
128 kEmptyOriginUrl = 3,
129 kPathMismatch = 4,
130 kPathFileInfoFailed = 5,
Andrew Williams480a3a12022-06-14 18:10:56131 kInvalidStorageKey = 6,
Evan Stadef3a6c0c2022-04-06 23:57:35132 // Add new enums above
Andrew Williams480a3a12022-06-14 18:10:56133 kMaxValue = kInvalidStorageKey,
Evan Stadef3a6c0c2022-04-06 23:57:35134};
135
136IndexResult ValidateIndex(proto::CacheStorageIndex index) {
Nathan Memmottcd1426b2023-05-20 01:51:23137 if (!index.has_origin()) {
Evan Stadef3a6c0c2022-04-06 23:57:35138 return IndexResult::kMissingOrigin;
Nathan Memmottcd1426b2023-05-20 01:51:23139 }
Evan Stadef3a6c0c2022-04-06 23:57:35140
141 GURL url(index.origin());
Nathan Memmottcd1426b2023-05-20 01:51:23142 if (url.is_empty()) {
Evan Stadef3a6c0c2022-04-06 23:57:35143 return IndexResult::kEmptyOriginUrl;
Nathan Memmottcd1426b2023-05-20 01:51:23144 }
Evan Stadef3a6c0c2022-04-06 23:57:35145
Andrew Williams480a3a12022-06-14 18:10:56146 // TODO(https://crbug.com/1199077): Consider adding a
147 // 'index.has_storage_key()' check here once we've ensured that a
148 // sufficient number of CacheStorage instances have been migrated (or
149 // verified that `ValidateIndex` won't be passed an unmigrated `index`).
Evan Stadef3a6c0c2022-04-06 23:57:35150 return IndexResult::kOk;
151}
152
153void RecordIndexValidationResult(IndexResult value) {
154 base::UmaHistogramEnumeration("ServiceWorkerCache.ListOriginsIndexValidity",
155 value);
156}
157
Andrew Williams691aceb2022-07-18 17:44:10158base::FilePath ConstructOriginPath(const base::FilePath& profile_path,
159 const url::Origin& origin,
160 storage::mojom::CacheStorageOwner owner) {
161 base::FilePath first_party_default_root_path =
162 CacheStorageManager::ConstructFirstPartyDefaultRootPath(profile_path);
Evan Stadef3a6c0c2022-04-06 23:57:35163
Andrew Williams691aceb2022-07-18 17:44:10164 std::string identifier = storage::GetIdentifierFromOrigin(origin);
165 if (owner != storage::mojom::CacheStorageOwner::kCacheAPI) {
166 identifier += "-" + base::NumberToString(static_cast<int>(owner));
Evan Stadef3a6c0c2022-04-06 23:57:35167 }
Tom Sepez70317a12023-11-15 19:55:58168 const std::string origin_hash_hex = base::ToLowerASCII(base::HexEncode(
169 base::SHA1HashSpan(base::as_bytes(base::make_span(identifier)))));
Andrew Williams691aceb2022-07-18 17:44:10170 return first_party_default_root_path.AppendASCII(origin_hash_hex);
Evan Stadef3a6c0c2022-04-06 23:57:35171}
172
Andrew Williams691aceb2022-07-18 17:44:10173void ValidateAndAddUsageFromPath(
174 const base::FilePath& index_file_directory_path,
175 storage::mojom::CacheStorageOwner owner,
176 const base::FilePath& profile_path,
Andrew Williams9eaa2a052022-08-17 02:43:10177 std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29178 storage::mojom::StorageUsageInfoPtr>>& usage_tuples,
Andrew Williams9eaa2a052022-08-17 02:43:10179 bool is_origin_path = false) {
Andrew Williams691aceb2022-07-18 17:44:10180 if (!base::PathExists(index_file_directory_path)) {
181 return;
182 }
183 base::FilePath index_path =
184 index_file_directory_path.AppendASCII(CacheStorage::kIndexFileName);
185 base::File::Info file_info;
186 base::Time index_last_modified;
Nathan Memmottcd1426b2023-05-20 01:51:23187 if (GetFileInfo(index_path, &file_info)) {
Andrew Williams691aceb2022-07-18 17:44:10188 index_last_modified = file_info.last_modified;
Nathan Memmottcd1426b2023-05-20 01:51:23189 }
Andrew Williams691aceb2022-07-18 17:44:10190 std::string protobuf;
191 base::ReadFileToString(index_path, &protobuf);
Evan Stadef3a6c0c2022-04-06 23:57:35192
Andrew Williams691aceb2022-07-18 17:44:10193 proto::CacheStorageIndex index;
194 if (!index.ParseFromString(protobuf)) {
195 RecordIndexValidationResult(IndexResult::kFailedToParse);
196 return;
197 }
Evan Stadef3a6c0c2022-04-06 23:57:35198
Andrew Williams691aceb2022-07-18 17:44:10199 IndexResult rv = ValidateIndex(index);
200 if (rv != IndexResult::kOk) {
201 RecordIndexValidationResult(rv);
202 return;
203 }
204
205 blink::StorageKey storage_key;
206 if (index.has_storage_key()) {
Arthur Sonzognic686e8f2024-01-11 08:36:37207 std::optional<blink::StorageKey> result =
Andrew Williams691aceb2022-07-18 17:44:10208 blink::StorageKey::Deserialize(index.storage_key());
209 if (!result) {
210 RecordIndexValidationResult(IndexResult::kInvalidStorageKey);
211 return;
212 }
213 storage_key = result.value();
214 } else {
215 // TODO(https://crbug.com/1199077): Since index file migrations happen
216 // lazily, it's plausible that the index file we are reading doesn't have
217 // a storage key yet. For now, fall back to creating the storage key
218 // from the origin. Once enough time has passed it should be safe to treat
219 // this case as an index validation error.
Ari Chivukulac81e13e2023-02-15 20:44:57220 storage_key = blink::StorageKey::CreateFirstParty(
221 url::Origin::Create(GURL(index.origin())));
Andrew Williams691aceb2022-07-18 17:44:10222 }
223 DCHECK(!storage_key.origin().GetURL().is_empty());
224
Andrew Williams9eaa2a052022-08-17 02:43:10225 storage::BucketLocator bucket_locator{};
226
227 if (index.has_bucket_id() && index.has_bucket_is_default()) {
Andrew Williamsa4cfe132022-09-28 14:26:23228 // We'll populate the bucket locator using the information from the index
229 // file, but it's not guaranteed that this will be valid.
Andrew Williams9eaa2a052022-08-17 02:43:10230 bucket_locator = storage::BucketLocator(
231 storage::BucketId(index.bucket_id()), storage_key,
232 blink::mojom::StorageType::kTemporary, index.bucket_is_default());
Andrew Williams9eaa2a052022-08-17 02:43:10233 } else {
234 // If the index file has no bucket information then it's from before we
235 // had non-default buckets and third-party storage partitioning
236 // implemented. That means these index files will always use the
237 // origin-based path format. Populate our BucketLocator with enough
238 // data to construct the appropriate path from it below.
Evan Staded55e8652022-10-07 19:30:56239 bucket_locator = storage::BucketLocator::ForDefaultBucket(storage_key);
Andrew Williams9eaa2a052022-08-17 02:43:10240 // TODO(https://crbug.com/1218097): Once enough time has passed it should be
241 // safe to treat this case as an index validation error.
242 }
243
244 auto bucket_path = CacheStorageManager::ConstructBucketPath(
245 profile_path, bucket_locator, owner);
246 if (index_file_directory_path != bucket_path) {
247 if (is_origin_path) {
248 // For paths corresponding to the legacy Cache Storage directory structure
249 // (where the bucket ID is not in the path),
250 // `ValidateAndAddUsageFromPath()` can get called with an
251 // `index_file_directory_path` that corresponds to a Cache Storage
252 // instance from a different `owner`. That is valid and expected because
253 // the directory entries from different owners are stored alongside each
254 // other and are not easily distinguishable (the directory name is a
255 // hash of the origin + the owner), so it's easiest to just compute the
256 // two possible origin paths here and compare. If the path doesn't match
257 // the calculated path for either `owner` then it is invalid. With the new
258 // directory structure for non-default buckets and third-party contexts,
259 // we only call `ValidateAndAddUsageFromPath()` with Cache Storage
260 // instances for the appropriate owner, so this check isn't needed in that
261 // case. We return early if this instance corresponds to another owner to
262 // avoid recording an index validation error and polluting the metrics
263 // derived from them.
264 storage::mojom::CacheStorageOwner other_owner =
265 owner == storage::mojom::CacheStorageOwner::kCacheAPI
266 ? storage::mojom::CacheStorageOwner::kBackgroundFetch
267 : storage::mojom::CacheStorageOwner::kCacheAPI;
268 auto other_owner_path = CacheStorageManager::ConstructBucketPath(
269 profile_path, bucket_locator, other_owner);
Nathan Memmottcd1426b2023-05-20 01:51:23270 if (index_file_directory_path == other_owner_path) {
Andrew Williams9eaa2a052022-08-17 02:43:10271 return;
Nathan Memmottcd1426b2023-05-20 01:51:23272 }
Andrew Williams9eaa2a052022-08-17 02:43:10273 }
274 RecordIndexValidationResult(IndexResult::kPathMismatch);
Andrew Williams691aceb2022-07-18 17:44:10275 return;
276 }
277
278 int64_t storage_size = GetCacheStorageSize(index_file_directory_path,
279 index_last_modified, index);
280
Andrew Williams9eaa2a052022-08-17 02:43:10281 usage_tuples.emplace_back(
Ari Chivukulac29c1b82022-09-30 20:49:29282 bucket_locator, storage::mojom::StorageUsageInfo::New(
Ari Chivukula6b6f0452022-09-27 16:01:55283 storage_key, storage_size, file_info.last_modified));
Andrew Williams691aceb2022-07-18 17:44:10284 RecordIndexValidationResult(IndexResult::kOk);
285}
286
Andrew Williams9eaa2a052022-08-17 02:43:10287void GetStorageKeyAndLastModifiedGotBucket(
Ari Chivukulac29c1b82022-09-30 20:49:29288 storage::mojom::StorageUsageInfoPtr info,
Andrew Williams9eaa2a052022-08-17 02:43:10289 base::OnceCallback<void(std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29290 storage::mojom::StorageUsageInfoPtr>)>
Andrew Williams9eaa2a052022-08-17 02:43:10291 callback,
292 storage::QuotaErrorOr<storage::BucketInfo> result) {
293 storage::BucketLocator bucket_locator{};
Claudio DeSouza708aede82023-02-24 19:32:58294 if (result.has_value()) {
Andrew Williams9eaa2a052022-08-17 02:43:10295 bucket_locator = result->ToBucketLocator();
Evan Stade6dea467a2022-10-18 20:01:36296 DCHECK_EQ(info->storage_key, result->storage_key);
Andrew Williams9eaa2a052022-08-17 02:43:10297 }
Sean Maher52fa5a72022-11-14 15:53:25298 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Andrew Williams9eaa2a052022-08-17 02:43:10299 FROM_HERE,
Ari Chivukula6b6f0452022-09-27 16:01:55300 base::BindOnce(
301 std::move(callback),
302 std::make_tuple(bucket_locator,
Ari Chivukulac29c1b82022-09-30 20:49:29303 storage::mojom::StorageUsageInfo::New(
Ari Chivukula6b6f0452022-09-27 16:01:55304 info->storage_key, info->total_size_bytes,
305 info->last_modified))));
Andrew Williams9eaa2a052022-08-17 02:43:10306}
307
308// Open the various cache directories' index files and extract their bucket
309// locators, sizes (if current), and last modified times.
Andrew Williams691aceb2022-07-18 17:44:10310void GetStorageKeysAndLastModifiedOnTaskRunner(
Andrew Williams9eaa2a052022-08-17 02:43:10311 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
Andrew Williams691aceb2022-07-18 17:44:10312 scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
Andrew Williams9eaa2a052022-08-17 02:43:10313 std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29314 storage::mojom::StorageUsageInfoPtr>> usage_tuples,
Andrew Williams9eaa2a052022-08-17 02:43:10315
Andrew Williams691aceb2022-07-18 17:44:10316 base::FilePath profile_path,
317 storage::mojom::CacheStorageOwner owner,
Andrew Williams9eaa2a052022-08-17 02:43:10318 base::OnceCallback<
319 void(std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29320 storage::mojom::StorageUsageInfoPtr>>)>
Andrew Williams691aceb2022-07-18 17:44:10321 callback) {
Andrew Williams9eaa2a052022-08-17 02:43:10322 // Add entries to `usage_tuples` from the directory for default buckets
323 // corresponding to first-party contexts.
Andrew Williams691aceb2022-07-18 17:44:10324 {
325 base::FilePath first_party_default_buckets_root_path =
326 CacheStorageManager::ConstructFirstPartyDefaultRootPath(profile_path);
327
328 base::FileEnumerator file_enum(first_party_default_buckets_root_path,
329 false /* recursive */,
330 base::FileEnumerator::DIRECTORIES);
331
332 base::FilePath path;
333 while (!(path = file_enum.Next()).empty()) {
Andrew Williams9eaa2a052022-08-17 02:43:10334 ValidateAndAddUsageFromPath(path, owner, profile_path, usage_tuples,
335 true /* is_origin_path */);
Andrew Williams691aceb2022-07-18 17:44:10336 }
337 }
338
Andrew Williams9eaa2a052022-08-17 02:43:10339 // Add entries to `usage_tuples` from the directory for non-default
340 // buckets and for buckets corresponding to third-party contexts.
341 base::FilePath third_party_and_non_default_root_path =
342 CacheStorageManager::ConstructThirdPartyAndNonDefaultRootPath(
343 profile_path);
344 {
345 base::FileEnumerator file_enum(third_party_and_non_default_root_path,
346 false /* recursive */,
347 base::FileEnumerator::DIRECTORIES);
348 base::FilePath path;
349 while (!(path = file_enum.Next()).empty()) {
350 base::FilePath cache_storage_path =
351 owner == storage::mojom::CacheStorageOwner::kCacheAPI
352 ? path.Append(storage::kCacheStorageDirectory)
353 : path.Append(storage::kBackgroundFetchDirectory);
354 if (!base::PathExists(cache_storage_path)) {
355 continue;
356 }
357 ValidateAndAddUsageFromPath(cache_storage_path, owner, profile_path,
358 usage_tuples);
359 }
360 }
361
362 if (usage_tuples.empty()) {
363 scheduler_task_runner->PostTask(
364 FROM_HERE,
365 base::BindOnce(std::move(callback), std::move(usage_tuples)));
366 return;
367 }
368
369 if (!quota_manager_proxy) {
370 // If we don't have a `QuotaManagerProxy` then don't attempt to resolve
371 // any missing bucket IDs.
372 scheduler_task_runner->PostTask(
373 FROM_HERE,
374 base::BindOnce(std::move(callback), std::move(usage_tuples)));
375 return;
376 }
377
Andrew Williamsa4cfe132022-09-28 14:26:23378 // If the quota manager proxy is available, query it for the correct
379 // bucket information regardless of whether the index file has bucket
380 // information. If we recreate a stale bucket locator here, a side effect is
381 // that our CacheStorageCache instance map could get populated with entries
382 // that map to the same file path (for instances where the bucket ID isn't a
383 // part of the directory path), triggering an infinite hang.
Ari Chivukulac29c1b82022-09-30 20:49:29384 const auto barrier_callback = base::BarrierCallback<
385 std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>(
386 usage_tuples.size(), std::move(callback));
Andrew Williams9eaa2a052022-08-17 02:43:10387
388 for (const auto& usage_tuple : usage_tuples) {
389 const storage::BucketLocator& bucket_locator = std::get<0>(usage_tuple);
Ari Chivukulac29c1b82022-09-30 20:49:29390 const storage::mojom::StorageUsageInfoPtr& info = std::get<1>(usage_tuple);
Evan Stade6dea467a2022-10-18 20:01:36391 if (bucket_locator.is_default) {
392 quota_manager_proxy->UpdateOrCreateBucket(
393 storage::BucketInitParams::ForDefaultBucket(
394 bucket_locator.storage_key),
395 scheduler_task_runner,
396 base::BindOnce(&GetStorageKeyAndLastModifiedGotBucket,
397 storage::mojom::StorageUsageInfo::New(
398 info->storage_key, info->total_size_bytes,
399 info->last_modified),
400 barrier_callback));
401 } else {
402 quota_manager_proxy->GetBucketById(
403 bucket_locator.id, scheduler_task_runner,
404 base::BindOnce(&GetStorageKeyAndLastModifiedGotBucket,
405 storage::mojom::StorageUsageInfo::New(
406 info->storage_key, info->total_size_bytes,
407 info->last_modified),
408 barrier_callback));
409 }
Andrew Williams9eaa2a052022-08-17 02:43:10410 }
Evan Stadef3a6c0c2022-04-06 23:57:35411}
412
Ari Chivukula6b6f0452022-09-27 16:01:55413void AllStorageKeySizesReported(
Andrew Williams9eaa2a052022-08-17 02:43:10414 storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback,
Ari Chivukulac29c1b82022-09-30 20:49:29415 std::vector<storage::mojom::StorageUsageInfoPtr> usages) {
Ari Chivukula6b6f0452022-09-27 16:01:55416 // We should return only one entry per StorageKey, so condense down all
417 // results before passing them to the callback. We condense by adding total
418 // size bytes and using the latest last_modified value.
419 std::map<blink::StorageKey, int64_t> storage_key_to_total_size_bytes;
420 std::map<blink::StorageKey, base::Time> storage_key_to_last_modified;
Andrew Williams9eaa2a052022-08-17 02:43:10421 for (const auto& usage : usages) {
Ari Chivukula6b6f0452022-09-27 16:01:55422 storage_key_to_total_size_bytes[usage->storage_key] +=
423 usage->total_size_bytes;
Andrew Williams9eaa2a052022-08-17 02:43:10424 // Save off the most recent valid last modified time.
Ari Chivukula6b6f0452022-09-27 16:01:55425 if (storage_key_to_last_modified.count(usage->storage_key) == 0 ||
Andrew Williams9eaa2a052022-08-17 02:43:10426 (!usage->last_modified.is_null() &&
Ari Chivukula6b6f0452022-09-27 16:01:55427 (storage_key_to_last_modified[usage->storage_key].is_null() ||
428 usage->last_modified >
429 storage_key_to_last_modified[usage->storage_key]))) {
430 storage_key_to_last_modified[usage->storage_key] = usage->last_modified;
Andrew Williams9eaa2a052022-08-17 02:43:10431 }
432 }
433
Ari Chivukulac29c1b82022-09-30 20:49:29434 std::vector<storage::mojom::StorageUsageInfoPtr> new_usages;
Ari Chivukula6b6f0452022-09-27 16:01:55435 new_usages.reserve(storage_key_to_total_size_bytes.size());
Andrew Williams9eaa2a052022-08-17 02:43:10436
Ari Chivukula6b6f0452022-09-27 16:01:55437 for (const auto& storage_key_usage_info : storage_key_to_total_size_bytes) {
Ari Chivukulac29c1b82022-09-30 20:49:29438 new_usages.emplace_back(storage::mojom::StorageUsageInfo::New(
Ari Chivukula6b6f0452022-09-27 16:01:55439 storage_key_usage_info.first, storage_key_usage_info.second,
440 storage_key_to_last_modified[storage_key_usage_info.first]));
Andrew Williams9eaa2a052022-08-17 02:43:10441 }
442
Evan Stadef3a6c0c2022-04-06 23:57:35443 // On scheduler sequence.
Sean Maher52fa5a72022-11-14 15:53:25444 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Andrew Williams9eaa2a052022-08-17 02:43:10445 FROM_HERE, base::BindOnce(std::move(callback), std::move(new_usages)));
Evan Stadef3a6c0c2022-04-06 23:57:35446}
447
Ari Chivukula6b6f0452022-09-27 16:01:55448void OneStorageKeySizeReported(
Ari Chivukulac29c1b82022-09-30 20:49:29449 base::OnceCallback<void(storage::mojom::StorageUsageInfoPtr)> callback,
Ari Chivukula6b6f0452022-09-27 16:01:55450 const blink::StorageKey storage_key,
Andrew Williams9eaa2a052022-08-17 02:43:10451 const base::Time last_modified,
452 int64_t size) {
Evan Stadef3a6c0c2022-04-06 23:57:35453 // On scheduler sequence.
454 DCHECK_NE(size, CacheStorage::kSizeUnknown);
Sean Maher52fa5a72022-11-14 15:53:25455 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
Ari Chivukula6b6f0452022-09-27 16:01:55456 FROM_HERE, base::BindOnce(std::move(callback),
Ari Chivukulac29c1b82022-09-30 20:49:29457 storage::mojom::StorageUsageInfo::New(
Ari Chivukula6b6f0452022-09-27 16:01:55458 storage_key, size, last_modified)));
Evan Stadef3a6c0c2022-04-06 23:57:35459}
460
Dustin J. Mitchell65a9d662023-03-17 20:20:40461// Match a bucket for deletion if its storage key matches any of the given
462// storage keys.
463//
Dustin J. Mitchell1984ccab2023-03-17 20:55:33464// This function considers a bucket to match a storage key if either the
465// bucket's key's origin matches the storage key's origin or the bucket's key is
466// third-party and its top-level site matches the origin.
Debadree Chatterjee799d39692023-03-28 19:02:09467bool BucketMatchesOriginsForDeletion(
Dustin J. Mitchell65a9d662023-03-17 20:20:40468 const storage::BucketLocator& bucket_locator,
Debadree Chatterjee799d39692023-03-28 19:02:09469 const std::set<url::Origin>& origins) {
Dustin J. Mitchell65a9d662023-03-17 20:20:40470 auto& bucket_key = bucket_locator.storage_key;
471
Debadree Chatterjee799d39692023-03-28 19:02:09472 for (auto& requested_origin : origins) {
Dustin J. Mitchell65a9d662023-03-17 20:20:40473 if (bucket_key.origin() == requested_origin ||
474 (bucket_key.IsThirdPartyContext() &&
475 bucket_key.top_level_site() == net::SchemefulSite(requested_origin))) {
476 return true;
477 }
478 }
479
480 return false;
481}
482
Evan Stadef3a6c0c2022-04-06 23:57:35483} // namespace
484
485// static
486scoped_refptr<CacheStorageManager> CacheStorageManager::Create(
Andrew Williams691aceb2022-07-18 17:44:10487 const base::FilePath& profile_path,
Evan Stadef3a6c0c2022-04-06 23:57:35488 scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
489 scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
490 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
Andrew Williams9eaa2a052022-08-17 02:43:10491 scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
492 base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host) {
Evan Stadef3a6c0c2022-04-06 23:57:35493 DCHECK(cache_task_runner);
494 DCHECK(scheduler_task_runner);
495 DCHECK(quota_manager_proxy);
496 DCHECK(blob_storage_context);
497
Evan Stadef3a6c0c2022-04-06 23:57:35498 return base::WrapRefCounted(new CacheStorageManager(
Andrew Williams691aceb2022-07-18 17:44:10499 profile_path, std::move(cache_task_runner),
500 std::move(scheduler_task_runner), std::move(quota_manager_proxy),
Andrew Williams9eaa2a052022-08-17 02:43:10501 std::move(blob_storage_context),
502 std::move(cache_storage_dispatcher_host)));
Evan Stadef3a6c0c2022-04-06 23:57:35503}
504
505// static
506scoped_refptr<CacheStorageManager> CacheStorageManager::CreateForTesting(
507 CacheStorageManager* old_manager) {
508 scoped_refptr<CacheStorageManager> manager(new CacheStorageManager(
Andrew Williams691aceb2022-07-18 17:44:10509 old_manager->profile_path(), old_manager->cache_task_runner(),
Evan Stadef3a6c0c2022-04-06 23:57:35510 old_manager->scheduler_task_runner(), old_manager->quota_manager_proxy_,
Andrew Williams9eaa2a052022-08-17 02:43:10511 old_manager->blob_storage_context_,
512 old_manager->cache_storage_dispatcher_host_));
Evan Stadef3a6c0c2022-04-06 23:57:35513 return manager;
514}
515
516CacheStorageManager::~CacheStorageManager() {
517 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
518}
519
Andrew Williams9eaa2a052022-08-17 02:43:10520#if DCHECK_IS_ON()
521bool CacheStorageManager::CacheStoragePathIsUnique(const base::FilePath& path) {
522 for (const auto& bucket_info : cache_storage_map_) {
523 const auto& bucket_locator = bucket_info.first.first;
524 const auto owner = bucket_info.first.second;
525 if (path == CacheStorageManager::ConstructBucketPath(
526 profile_path_, bucket_locator, owner)) {
527 return false;
528 }
529 }
530 return true;
531}
532#endif
533
Andrew Williamsdca3b312022-10-03 18:55:57534// Like `CacheStorageManager::CacheStoragePathIsUnique()`, this checks whether
535// there's an existing entry in `cache_storage_map_` that would share the same
536// directory path for the given `owner` and `bucket_locator`.
537bool CacheStorageManager::ConflictingInstanceExistsInMap(
538 storage::mojom::CacheStorageOwner owner,
539 const storage::BucketLocator& bucket_locator) {
540 DCHECK(bucket_locator.type == blink::mojom::StorageType::kTemporary);
541
542 if (IsMemoryBacked() || !bucket_locator.is_default ||
543 !bucket_locator.storage_key.IsFirstPartyContext()) {
544 return false;
545 }
546 CacheStorageMap::const_iterator it =
547 cache_storage_map_.find({bucket_locator, owner});
548 if (it != cache_storage_map_.end()) {
549 // If there's an entry in the map for a given BucketLocator then assume
550 // there are no conflicts.
551 return false;
552 }
553 // Note: since the number of CacheStorage instances is usually small, just
554 // search for any `storage::BucketLocator` keys with a matching
555 // `blink::StorageKey`.
556 for (const auto& key_value : cache_storage_map_) {
557 if (key_value.first.second != owner) {
558 continue;
559 }
560 if (!key_value.first.first.is_default ||
561 key_value.first.first.storage_key != bucket_locator.storage_key) {
562 continue;
563 }
564 DCHECK(key_value.first.first.type == blink::mojom::StorageType::kTemporary);
565
566 // An existing entry has a different bucket ID and/or type, which means
567 // these entries will use the same directory path.
568 return true;
569 }
570 return false;
571}
572
Evan Stadef3a6c0c2022-04-06 23:57:35573CacheStorageHandle CacheStorageManager::OpenCacheStorage(
Pei Zhangcc4549e2022-05-07 02:51:13574 const storage::BucketLocator& bucket_locator,
575 storage::mojom::CacheStorageOwner owner) {
Evan Stadef3a6c0c2022-04-06 23:57:35576 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
577
578 // Wait to create the MemoryPressureListener until the first CacheStorage
579 // object is needed. This ensures we create the listener on the correct
580 // thread.
581 if (!memory_pressure_listener_) {
582 memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
583 FROM_HERE, base::BindRepeating(&CacheStorageManager::OnMemoryPressure,
584 base::Unretained(this)));
585 }
586
587 CacheStorageMap::const_iterator it =
Andrew Williams9eaa2a052022-08-17 02:43:10588 cache_storage_map_.find({bucket_locator, owner});
Evan Stadef3a6c0c2022-04-06 23:57:35589 if (it == cache_storage_map_.end()) {
Andrew Williams9eaa2a052022-08-17 02:43:10590 const auto bucket_path = CacheStorageManager::ConstructBucketPath(
591 profile_path_, bucket_locator, owner);
592#if DCHECK_IS_ON()
593 // Each CacheStorage instance expects to exclusively own it's corresponding
594 // origin / bucket path, and if it doesn't then the underlying scheduler for
595 // that instance will block, maybe indefinitely, if an existing instance
596 // using that directory is alive. The effects of a stalled scheduler can
597 // manifest in peculiar ways, so to make debugging easier emit a warning
598 // here if we observe that there will be path conflicts. One case where this
599 // can happen is when a bucket was deleted very recently and a CacheStorage
600 // instance is created using a new bucket id (for the same storage key /
601 // default bucket). If we haven't yet deleted the existing CacheStorage
602 // instance via `DeleteBucketData()` then we will temporarily hit this
603 // condition. This should be fine, though, because once the original
604 // CacheStorage instance is deleted the scheduler of the second instance
605 // will no longer be blocked.
606 DLOG_IF(WARNING, !CacheStoragePathIsUnique(bucket_path))
607 << "Multiple CacheStorage instances using the same directory detected";
608#endif
Evan Stadef3a6c0c2022-04-06 23:57:35609 CacheStorage* cache_storage = new CacheStorage(
Andrew Williams9eaa2a052022-08-17 02:43:10610 bucket_path, IsMemoryBacked(), cache_task_runner_.get(),
611 scheduler_task_runner_, quota_manager_proxy_, blob_storage_context_,
612 this, bucket_locator, owner);
613 cache_storage_map_[{bucket_locator, owner}] =
614 base::WrapUnique(cache_storage);
Evan Stadef3a6c0c2022-04-06 23:57:35615 return cache_storage->CreateHandle();
616 }
617 return it->second.get()->CreateHandle();
618}
619
620void CacheStorageManager::NotifyCacheListChanged(
Andrew Williams9eaa2a052022-08-17 02:43:10621 const storage::BucketLocator& bucket_locator) {
Evan Stadef3a6c0c2022-04-06 23:57:35622 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Nathan Memmottcd1426b2023-05-20 01:51:23623 for (const auto& observer : observers_) {
624 observer->OnCacheListChanged(bucket_locator);
625 }
Evan Stadef3a6c0c2022-04-06 23:57:35626}
627
628void CacheStorageManager::NotifyCacheContentChanged(
Andrew Williams9eaa2a052022-08-17 02:43:10629 const storage::BucketLocator& bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:35630 const std::string& name) {
631 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Nathan Memmottcd1426b2023-05-20 01:51:23632 for (const auto& observer : observers_) {
633 observer->OnCacheContentChanged(bucket_locator, name);
634 }
Evan Stadef3a6c0c2022-04-06 23:57:35635}
636
637void CacheStorageManager::CacheStorageUnreferenced(
638 CacheStorage* cache_storage,
Andrew Williams9eaa2a052022-08-17 02:43:10639 const storage::BucketLocator& bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:35640 storage::mojom::CacheStorageOwner owner) {
641 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
642 DCHECK(cache_storage);
643 cache_storage->AssertUnreferenced();
Andrew Williams9eaa2a052022-08-17 02:43:10644 auto it = cache_storage_map_.find({bucket_locator, owner});
Evan Stadef3a6c0c2022-04-06 23:57:35645 DCHECK(it != cache_storage_map_.end());
646 DCHECK(it->second.get() == cache_storage);
647
648 // Currently we don't do anything when a CacheStorage instance becomes
649 // unreferenced. In the future we will deallocate some or all of the
650 // CacheStorage's state.
651}
652
653void CacheStorageManager::GetAllStorageKeysUsage(
654 storage::mojom::CacheStorageOwner owner,
655 storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback
656 callback) {
657 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
658
Andrew Williams9eaa2a052022-08-17 02:43:10659 std::vector<
Ari Chivukulac29c1b82022-09-30 20:49:29660 std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>
Andrew Williams9eaa2a052022-08-17 02:43:10661 usages;
Evan Stadef3a6c0c2022-04-06 23:57:35662
663 if (IsMemoryBacked()) {
Andrew Williams9eaa2a052022-08-17 02:43:10664 for (const auto& bucket_details : cache_storage_map_) {
Nathan Memmottcd1426b2023-05-20 01:51:23665 if (bucket_details.first.second != owner) {
Evan Stadef3a6c0c2022-04-06 23:57:35666 continue;
Nathan Memmottcd1426b2023-05-20 01:51:23667 }
Andrew Williams9eaa2a052022-08-17 02:43:10668 const storage::BucketLocator& bucket_locator = bucket_details.first.first;
Ari Chivukulac29c1b82022-09-30 20:49:29669 usages.emplace_back(bucket_locator, storage::mojom::StorageUsageInfo::New(
670 bucket_locator.storage_key,
671 /*total_size_bytes=*/0,
672 /*last_modified=*/base::Time()));
Evan Stadef3a6c0c2022-04-06 23:57:35673 }
Andrew Williams00db1be2022-07-20 20:48:57674 GetAllStorageKeysUsageGetSizes(owner, std::move(callback),
675 std::move(usages));
Evan Stadef3a6c0c2022-04-06 23:57:35676 return;
677 }
678
Andrew Williams691aceb2022-07-18 17:44:10679 cache_task_runner_->PostTask(
Evan Stadef3a6c0c2022-04-06 23:57:35680 FROM_HERE,
Andrew Williams691aceb2022-07-18 17:44:10681 base::BindOnce(
682 &GetStorageKeysAndLastModifiedOnTaskRunner,
Andrew Williams9eaa2a052022-08-17 02:43:10683 base::WrapRefCounted(quota_manager_proxy_.get()),
Andrew Williams691aceb2022-07-18 17:44:10684 base::WrapRefCounted(scheduler_task_runner_.get()), std::move(usages),
685 profile_path_, owner,
686 base::BindOnce(&CacheStorageManager::GetAllStorageKeysUsageGetSizes,
Andrew Williams9eaa2a052022-08-17 02:43:10687 weak_ptr_factory_.GetWeakPtr(), owner,
Andrew Williams00db1be2022-07-20 20:48:57688 std::move(callback))));
Evan Stadef3a6c0c2022-04-06 23:57:35689}
690
691void CacheStorageManager::GetAllStorageKeysUsageGetSizes(
Andrew Williams00db1be2022-07-20 20:48:57692 storage::mojom::CacheStorageOwner owner,
Evan Stadef3a6c0c2022-04-06 23:57:35693 storage::mojom::CacheStorageControl::GetAllStorageKeysInfoCallback callback,
Andrew Williams9eaa2a052022-08-17 02:43:10694 std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29695 storage::mojom::StorageUsageInfoPtr>> usage_tuples) {
Evan Stadef3a6c0c2022-04-06 23:57:35696 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
697
698 // The origin GURL and last modified times are set in |usages| but not the
699 // size in bytes. Call each CacheStorage's Size() function to fill that out.
Ari Chivukulac29c1b82022-09-30 20:49:29700 std::vector<storage::mojom::StorageUsageInfoPtr> usages;
Andrew Williams9eaa2a052022-08-17 02:43:10701 if (usage_tuples.empty()) {
Evan Stadef3a6c0c2022-04-06 23:57:35702 scheduler_task_runner_->PostTask(
703 FROM_HERE, base::BindOnce(std::move(callback), std::move(usages)));
704 return;
705 }
706
Andrew Williams97fa8532022-11-29 21:16:25707 // If we weren't able to lookup a bucket ID that corresponds to this
708 // CacheStorage instance, skip reporting usage information about it.
709 int non_null_count = std::count_if(
710 usage_tuples.begin(), usage_tuples.end(),
711 [](const std::tuple<storage::BucketLocator,
712 storage::mojom::StorageUsageInfoPtr>& usage_tuple) {
713 const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
714 return !bucket_locator.is_null();
715 });
716
Andrew Williams9eaa2a052022-08-17 02:43:10717 const auto barrier_callback =
Ari Chivukulac29c1b82022-09-30 20:49:29718 base::BarrierCallback<storage::mojom::StorageUsageInfoPtr>(
Andrew Williams97fa8532022-11-29 21:16:25719 non_null_count,
Ari Chivukula6b6f0452022-09-27 16:01:55720 base::BindOnce(&AllStorageKeySizesReported, std::move(callback)));
Evan Stadef3a6c0c2022-04-06 23:57:35721
Andrew Williams9eaa2a052022-08-17 02:43:10722 for (const auto& usage_tuple : usage_tuples) {
723 const storage::BucketLocator& bucket_locator = std::get<0>(usage_tuple);
Ari Chivukulac29c1b82022-09-30 20:49:29724 const storage::mojom::StorageUsageInfoPtr& info = std::get<1>(usage_tuple);
Andrew Williams97fa8532022-11-29 21:16:25725 if (bucket_locator.is_null()) {
726 continue;
727 }
Andrew Williams9eaa2a052022-08-17 02:43:10728 if (info->total_size_bytes != CacheStorage::kSizeUnknown ||
729 !IsValidQuotaStorageKey(bucket_locator.storage_key)) {
730 scheduler_task_runner_->PostTask(
Ari Chivukula6b6f0452022-09-27 16:01:55731 FROM_HERE,
732 base::BindOnce(barrier_callback,
Ari Chivukulac29c1b82022-09-30 20:49:29733 storage::mojom::StorageUsageInfo::New(
Ari Chivukula6b6f0452022-09-27 16:01:55734 info->storage_key, info->total_size_bytes,
735 info->last_modified)));
Evan Stadef3a6c0c2022-04-06 23:57:35736 continue;
737 }
Andrew Williams9eaa2a052022-08-17 02:43:10738 CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner);
Evan Stadef3a6c0c2022-04-06 23:57:35739 CacheStorage::From(cache_storage)
Ari Chivukula6b6f0452022-09-27 16:01:55740 ->Size(base::BindOnce(&OneStorageKeySizeReported, barrier_callback,
741 info->storage_key, info->last_modified));
Evan Stadef3a6c0c2022-04-06 23:57:35742 }
743}
744
Andrew Williams9eaa2a052022-08-17 02:43:10745void CacheStorageManager::GetBucketUsage(
746 const storage::BucketLocator& bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:35747 storage::mojom::CacheStorageOwner owner,
748 storage::mojom::QuotaClient::GetBucketUsageCallback callback) {
749 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
750
751 if (IsMemoryBacked()) {
Andrew Williams9eaa2a052022-08-17 02:43:10752 auto it = cache_storage_map_.find({bucket_locator, owner});
Evan Stadef3a6c0c2022-04-06 23:57:35753 if (it == cache_storage_map_.end()) {
754 scheduler_task_runner_->PostTask(FROM_HERE,
755 base::BindOnce(std::move(callback),
756 /*usage=*/0));
757 return;
758 }
Andrew Williams9eaa2a052022-08-17 02:43:10759 CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner);
Evan Stadef3a6c0c2022-04-06 23:57:35760 CacheStorage::From(cache_storage)->Size(std::move(callback));
761 return;
762 }
763 cache_task_runner_->PostTaskAndReplyWithResult(
764 FROM_HERE,
Andrew Williams9eaa2a052022-08-17 02:43:10765 base::BindOnce(&base::PathExists,
766 CacheStorageManager::ConstructBucketPath(
767 profile_path_, bucket_locator, owner)),
768 base::BindOnce(&CacheStorageManager::GetBucketUsageDidGetExists,
769 weak_ptr_factory_.GetWeakPtr(), bucket_locator, owner,
Evan Stadef3a6c0c2022-04-06 23:57:35770 std::move(callback)));
771}
772
Andrew Williams9eaa2a052022-08-17 02:43:10773void CacheStorageManager::GetBucketUsageDidGetExists(
774 const storage::BucketLocator& bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:35775 storage::mojom::CacheStorageOwner owner,
776 storage::mojom::QuotaClient::GetBucketUsageCallback callback,
777 bool exists) {
778 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Andrew Williamsdca3b312022-10-03 18:55:57779 if (!exists || ConflictingInstanceExistsInMap(owner, bucket_locator)) {
Evan Stadef3a6c0c2022-04-06 23:57:35780 scheduler_task_runner_->PostTask(
781 FROM_HERE, base::BindOnce(std::move(callback), /*usage=*/0));
782 return;
783 }
Andrew Williamsdca3b312022-10-03 18:55:57784
Andrew Williams9eaa2a052022-08-17 02:43:10785 CacheStorageHandle cache_storage = OpenCacheStorage(bucket_locator, owner);
Evan Stadef3a6c0c2022-04-06 23:57:35786 CacheStorage::From(cache_storage)->Size(std::move(callback));
787}
788
Andrew Williams9eaa2a052022-08-17 02:43:10789// Used by QuotaClient which only wants the storage keys that have data in the
790// default bucket.
Evan Stadef3a6c0c2022-04-06 23:57:35791void CacheStorageManager::GetStorageKeys(
792 storage::mojom::CacheStorageOwner owner,
793 storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback) {
794 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
795
796 if (IsMemoryBacked()) {
797 std::vector<blink::StorageKey> storage_keys;
Andrew Williams9eaa2a052022-08-17 02:43:10798 for (const auto& key_value : cache_storage_map_) {
Nathan Memmottcd1426b2023-05-20 01:51:23799 if (key_value.first.second != owner) {
Andrew Williams9eaa2a052022-08-17 02:43:10800 continue;
Nathan Memmottcd1426b2023-05-20 01:51:23801 }
Andrew Williams9eaa2a052022-08-17 02:43:10802
803 const storage::BucketLocator& bucket_locator = key_value.first.first;
Nathan Memmottcd1426b2023-05-20 01:51:23804 if (!bucket_locator.is_default) {
Andrew Williams9eaa2a052022-08-17 02:43:10805 continue;
Nathan Memmottcd1426b2023-05-20 01:51:23806 }
Andrew Williams9eaa2a052022-08-17 02:43:10807
Andrew Williams6c893b02022-09-29 19:16:25808 storage_keys.push_back(bucket_locator.storage_key);
Andrew Williams9eaa2a052022-08-17 02:43:10809 }
Evan Stadef3a6c0c2022-04-06 23:57:35810
811 scheduler_task_runner_->PostTask(
812 FROM_HERE,
813 base::BindOnce(std::move(callback), std::move(storage_keys)));
814 return;
815 }
816
Andrew Williams9eaa2a052022-08-17 02:43:10817 std::vector<
Ari Chivukulac29c1b82022-09-30 20:49:29818 std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>
Andrew Williams9eaa2a052022-08-17 02:43:10819 usage_tuples;
Andrew Williams691aceb2022-07-18 17:44:10820
Andrew Williams8bf996a2022-10-05 04:47:23821 // Note that we don't want `GetStorageKeysAndLastModifiedOnTaskRunner()` to
Andrew Williams7dcef202022-10-06 17:49:13822 // call `QuotaManagerProxy::UpdateOrCreateBucket()` because doing so creates
823 // a deadlock. Specifically, `GetStorageKeys()` would wait for the bucket
824 // information to be returned and the QuotaManager won't respond with
825 // bucket information until the `GetStorageKeys()` call finishes (as part of
826 // the QuotaDatabase bootstrapping process). We don't need the bucket ID to
827 // build a list of StorageKeys anyway.
Andrew Williams691aceb2022-07-18 17:44:10828 cache_task_runner_->PostTask(
829 FROM_HERE,
830 base::BindOnce(
Andrew Williams8bf996a2022-10-05 04:47:23831 &GetStorageKeysAndLastModifiedOnTaskRunner, nullptr,
Andrew Williams9eaa2a052022-08-17 02:43:10832 base::WrapRefCounted(scheduler_task_runner_.get()),
833 std::move(usage_tuples), profile_path_, owner,
Andrew Williams691aceb2022-07-18 17:44:10834 base::BindOnce(&CacheStorageManager::ListStorageKeysOnTaskRunner,
Andrew Williams9eaa2a052022-08-17 02:43:10835 weak_ptr_factory_.GetWeakPtr(), std::move(callback))));
Evan Stadef3a6c0c2022-04-06 23:57:35836}
837
Debadree Chatterjee799d39692023-03-28 19:02:09838void CacheStorageManager::DeleteOriginsDataGotAllBucketInfo(
839 const std::set<url::Origin>& origins,
Andrew Williams9eaa2a052022-08-17 02:43:10840 storage::mojom::CacheStorageOwner owner,
841 base::OnceCallback<void(std::vector<blink::mojom::QuotaStatusCode>)>
842 callback,
843 std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29844 storage::mojom::StorageUsageInfoPtr>> usage_tuples) {
Andrew Williams9eaa2a052022-08-17 02:43:10845 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
846 if (usage_tuples.empty()) {
847 std::vector<blink::mojom::QuotaStatusCode> results{
848 blink::mojom::QuotaStatusCode::kOk};
849 scheduler_task_runner_->PostTask(
850 FROM_HERE, base::BindOnce(std::move(callback), std::move(results)));
851 return;
852 }
853
854 int instance_count = 0;
855 for (const std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29856 storage::mojom::StorageUsageInfoPtr>& usage_tuple :
Andrew Williams9eaa2a052022-08-17 02:43:10857 usage_tuples) {
858 const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
Debadree Chatterjee799d39692023-03-28 19:02:09859 if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
Andrew Williams9eaa2a052022-08-17 02:43:10860 continue;
861 }
862 instance_count += 1;
863 }
864
865 const auto barrier_callback =
866 base::BarrierCallback<blink::mojom::QuotaStatusCode>(instance_count,
867 std::move(callback));
868
869 for (const std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:29870 storage::mojom::StorageUsageInfoPtr>& usage_tuple :
Andrew Williams9eaa2a052022-08-17 02:43:10871 usage_tuples) {
872 const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
Debadree Chatterjee799d39692023-03-28 19:02:09873 if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
Andrew Williams9eaa2a052022-08-17 02:43:10874 continue;
875 }
Andrew Williams97fa8532022-11-29 21:16:25876 if (!bucket_locator.is_null()) {
Andrew Williams9eaa2a052022-08-17 02:43:10877 // The bucket locator is fully formed, so use the same steps to delete as
878 // `DeleteBucketData()`.
879 DeleteBucketDataDidGetExists(owner, barrier_callback, bucket_locator,
880 /*exists=*/true);
881 } else {
882 // This must be for an unmigrated cache storage instance using an origin
883 // path, so just directly delete the directory.
Sean Maheracb01c42022-12-01 18:22:23884 cache_task_runner_->PostTaskAndReplyWithResult(
885 FROM_HERE,
Andrew Williams9eaa2a052022-08-17 02:43:10886 base::BindOnce(&DeleteDir, CacheStorageManager::ConstructBucketPath(
887 profile_path_, bucket_locator, owner)),
888 base::BindOnce(&DeleteBucketDidDeleteDir, barrier_callback));
889 }
890 }
891}
892
Evan Stadef3a6c0c2022-04-06 23:57:35893void CacheStorageManager::DeleteStorageKeyData(
894 const blink::StorageKey& storage_key,
Dustin J. Mitchell65a9d662023-03-17 20:20:40895 storage::mojom::CacheStorageOwner owner) {
896 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
897 DeleteStorageKeyData(storage_key, owner, base::DoNothing());
898}
899
900void CacheStorageManager::DeleteStorageKeyData(
901 const blink::StorageKey& storage_key,
Evan Stadef3a6c0c2022-04-06 23:57:35902 storage::mojom::CacheStorageOwner owner,
903 storage::mojom::QuotaClient::DeleteBucketDataCallback callback) {
904 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
905
Debadree Chatterjee799d39692023-03-28 19:02:09906 // TODO(https://crbug.com/1376071#c12): This function isn't
907 // actually deleting data for a single key, but rather for
908 // the origin of the key.
909
910 std::set<url::Origin> origin_set{storage_key.origin()};
911 DeleteOriginData(origin_set, owner, std::move(callback));
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03912}
913
Debadree Chatterjee799d39692023-03-28 19:02:09914void CacheStorageManager::DeleteOriginData(
915 const std::set<url::Origin>& origins,
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03916 storage::mojom::CacheStorageOwner owner,
917 storage::mojom::QuotaClient::DeleteBucketDataCallback callback) {
918 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
919
Debadree Chatterjee799d39692023-03-28 19:02:09920 if (origins.empty()) {
Andrew Williamse238e1cc2023-03-21 21:36:55921 scheduler_task_runner_->PostTask(
922 FROM_HERE, base::BindOnce(std::move(callback),
923 blink::mojom::QuotaStatusCode::kOk));
924 return;
925 }
926
Evan Stadef3a6c0c2022-04-06 23:57:35927 if (IsMemoryBacked()) {
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03928 std::vector<
929 std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>
930 to_delete;
Debadree Chatterjee799d39692023-03-28 19:02:09931 to_delete.reserve(origins.size());
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03932
Andrew Williams9eaa2a052022-08-17 02:43:10933 // Note: since the number of CacheStorage instances is usually small, just
Dustin J. Mitchell65a9d662023-03-17 20:20:40934 // search for the corresponding `storage::BucketLocator` keys, given a
Andrew Williams9eaa2a052022-08-17 02:43:10935 // `blink::StorageKey`.
936 for (const auto& key_value : cache_storage_map_) {
Nathan Memmottcd1426b2023-05-20 01:51:23937 if (key_value.first.second != owner) {
Andrew Williams9eaa2a052022-08-17 02:43:10938 continue;
Nathan Memmottcd1426b2023-05-20 01:51:23939 }
Andrew Williams9eaa2a052022-08-17 02:43:10940 const storage::BucketLocator& bucket_locator = key_value.first.first;
Debadree Chatterjee799d39692023-03-28 19:02:09941 if (!BucketMatchesOriginsForDeletion(bucket_locator, origins)) {
Andrew Williams9eaa2a052022-08-17 02:43:10942 continue;
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03943 }
944 to_delete.emplace_back(bucket_locator,
945 storage::mojom::StorageUsageInfo::New(
946 bucket_locator.storage_key, 0, base::Time()));
Andrew Williams9eaa2a052022-08-17 02:43:10947 }
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03948
Debadree Chatterjee799d39692023-03-28 19:02:09949 DeleteOriginsDataGotAllBucketInfo(
950 origins, owner,
Ahmed Elwasefi1ffdc6072023-03-14 16:33:03951 base::BindOnce(&DeleteStorageKeyDidDeleteAllData, std::move(callback)),
952 std::move(to_delete));
Andrew Williams9eaa2a052022-08-17 02:43:10953 return;
954 }
955 // Note that we can't call `QuotaManagerProxy::GetBucket()` and then use the
956 // same steps as `DeleteBucketData()` here because this method is called
957 // during shutdown and the quota code might be at various stages of shutting
958 // down as well. Instead, build a list of cache storage instances from disk
959 // and either use the bucket locators from index files or directly delete any
960 // unmigrated cache storage origin paths.
961 std::vector<
Ari Chivukulac29c1b82022-09-30 20:49:29962 std::tuple<storage::BucketLocator, storage::mojom::StorageUsageInfoPtr>>
Andrew Williams9eaa2a052022-08-17 02:43:10963 usage_tuples;
964 cache_task_runner_->PostTask(
965 FROM_HERE,
966 base::BindOnce(
967 &GetStorageKeysAndLastModifiedOnTaskRunner, nullptr,
968 base::WrapRefCounted(scheduler_task_runner_.get()),
969 std::move(usage_tuples), profile_path_, owner,
970 base::BindOnce(
Debadree Chatterjee799d39692023-03-28 19:02:09971 &CacheStorageManager::DeleteOriginsDataGotAllBucketInfo,
972 weak_ptr_factory_.GetWeakPtr(), origins, owner,
Andrew Williams9eaa2a052022-08-17 02:43:10973 base::BindOnce(&DeleteStorageKeyDidDeleteAllData,
974 std::move(callback)))));
975}
976
977void CacheStorageManager::DeleteBucketData(
978 const storage::BucketLocator& bucket_locator,
979 storage::mojom::CacheStorageOwner owner,
980 storage::mojom::QuotaClient::DeleteBucketDataCallback callback) {
981 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
982
983 // `DeleteBucketData()` is called when the bucket corresponding to
984 // `bucket_locator` has been destroyed, which means we should notify
985 // `cache_storage_dispatcher_host_` that any `CacheStorageImpl` objects with a
986 // cached version of this `BucketLocator` should invalidate the copy they
987 // have.
988 if (cache_storage_dispatcher_host_) {
989 cache_storage_dispatcher_host_->NotifyBucketDataDeleted(bucket_locator);
990 }
991
992 if (IsMemoryBacked()) {
993 auto it = cache_storage_map_.find({bucket_locator, owner});
Evan Stadef3a6c0c2022-04-06 23:57:35994 if (it == cache_storage_map_.end()) {
995 scheduler_task_runner_->PostTask(
996 FROM_HERE, base::BindOnce(std::move(callback),
997 blink::mojom::QuotaStatusCode::kOk));
998 return;
999 }
Andrew Williams9eaa2a052022-08-17 02:43:101000 DeleteBucketDataDidGetExists(owner, std::move(callback), bucket_locator,
1001 /*exists=*/true);
Evan Stadef3a6c0c2022-04-06 23:57:351002 return;
1003 }
1004
1005 cache_task_runner_->PostTaskAndReplyWithResult(
1006 FROM_HERE,
Andrew Williams9eaa2a052022-08-17 02:43:101007 base::BindOnce(&base::PathExists,
1008 CacheStorageManager::ConstructBucketPath(
1009 profile_path_, bucket_locator, owner)),
1010 base::BindOnce(&CacheStorageManager::DeleteBucketDataDidGetExists,
1011 weak_ptr_factory_.GetWeakPtr(), owner, std::move(callback),
1012 bucket_locator));
Evan Stadef3a6c0c2022-04-06 23:57:351013}
1014
Andrew Williams9eaa2a052022-08-17 02:43:101015void CacheStorageManager::DeleteBucketDataDidGetExists(
Evan Stadef3a6c0c2022-04-06 23:57:351016 storage::mojom::CacheStorageOwner owner,
1017 storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
Andrew Williams9eaa2a052022-08-17 02:43:101018 storage::BucketLocator bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:351019 bool exists) {
1020 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1021
Andrew Williamsdca3b312022-10-03 18:55:571022 if (!exists || ConflictingInstanceExistsInMap(owner, bucket_locator)) {
Evan Stadef3a6c0c2022-04-06 23:57:351023 scheduler_task_runner_->PostTask(
1024 FROM_HERE, base::BindOnce(std::move(callback),
1025 blink::mojom::QuotaStatusCode::kOk));
1026 return;
1027 }
1028
Andrew Williams9eaa2a052022-08-17 02:43:101029 // Create the CacheStorage for the bucket if it hasn't been loaded yet.
1030 CacheStorageHandle handle = OpenCacheStorage(bucket_locator, owner);
Evan Stadef3a6c0c2022-04-06 23:57:351031
Andrew Williams9eaa2a052022-08-17 02:43:101032 auto it = cache_storage_map_.find({bucket_locator, owner});
Evan Stadef3a6c0c2022-04-06 23:57:351033 DCHECK(it != cache_storage_map_.end());
1034
1035 CacheStorage* cache_storage = it->second.release();
1036 cache_storage->ResetManager();
Andrew Williams9eaa2a052022-08-17 02:43:101037 cache_storage_map_.erase({bucket_locator, owner});
1038
Evan Stadef3a6c0c2022-04-06 23:57:351039 cache_storage->GetSizeThenCloseAllCaches(
Andrew Williams9eaa2a052022-08-17 02:43:101040 base::BindOnce(&CacheStorageManager::DeleteBucketDidClose,
1041 weak_ptr_factory_.GetWeakPtr(), bucket_locator, owner,
Evan Stadef3a6c0c2022-04-06 23:57:351042 std::move(callback), base::WrapUnique(cache_storage)));
1043}
1044
Evan Stadef3a6c0c2022-04-06 23:57:351045void CacheStorageManager::AddObserver(
1046 mojo::PendingRemote<storage::mojom::CacheStorageObserver> observer) {
1047 observers_.Add(std::move(observer));
1048}
1049
Andrew Williams9eaa2a052022-08-17 02:43:101050void CacheStorageManager::DeleteBucketDidClose(
1051 const storage::BucketLocator& bucket_locator,
Evan Stadef3a6c0c2022-04-06 23:57:351052 storage::mojom::CacheStorageOwner owner,
1053 storage::mojom::QuotaClient::DeleteBucketDataCallback callback,
1054 std::unique_ptr<CacheStorage> cache_storage,
Ari Chivukula6b6f0452022-09-27 16:01:551055 int64_t bucket_size) {
Evan Stadef3a6c0c2022-04-06 23:57:351056 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1057 // TODO(jkarlin): Deleting the storage leaves any unfinished operations
1058 // hanging, resulting in unresolved promises. Fix this by returning early from
1059 // CacheStorage operations posted after GetSizeThenCloseAllCaches is called.
1060 cache_storage.reset();
1061
Andrew Williams9eaa2a052022-08-17 02:43:101062 quota_manager_proxy_->NotifyBucketModified(
Evan Stadedda5c552022-12-04 23:34:111063 CacheStorageQuotaClient::GetClientTypeFromOwner(owner), bucket_locator,
Sean Maher52fa5a72022-11-14 15:53:251064 -bucket_size, base::Time::Now(),
1065 base::SequencedTaskRunner::GetCurrentDefault(), base::DoNothing());
Evan Stadef3a6c0c2022-04-06 23:57:351066
Nathan Memmottcd1426b2023-05-20 01:51:231067 if (owner == storage::mojom::CacheStorageOwner::kCacheAPI) {
Andrew Williams9eaa2a052022-08-17 02:43:101068 NotifyCacheListChanged(bucket_locator);
Nathan Memmottcd1426b2023-05-20 01:51:231069 }
Evan Stadef3a6c0c2022-04-06 23:57:351070
1071 if (IsMemoryBacked()) {
1072 scheduler_task_runner_->PostTask(
1073 FROM_HERE, base::BindOnce(std::move(callback),
1074 blink::mojom::QuotaStatusCode::kOk));
1075 return;
1076 }
1077
Sean Maheracb01c42022-12-01 18:22:231078 cache_task_runner_->PostTaskAndReplyWithResult(
1079 FROM_HERE,
Andrew Williams9eaa2a052022-08-17 02:43:101080 base::BindOnce(&DeleteDir, CacheStorageManager::ConstructBucketPath(
1081 profile_path_, bucket_locator, owner)),
1082 base::BindOnce(&DeleteBucketDidDeleteDir, std::move(callback)));
Evan Stadef3a6c0c2022-04-06 23:57:351083}
1084
1085CacheStorageManager::CacheStorageManager(
Andrew Williams691aceb2022-07-18 17:44:101086 const base::FilePath& profile_path,
Evan Stadef3a6c0c2022-04-06 23:57:351087 scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
1088 scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
1089 scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
Andrew Williams9eaa2a052022-08-17 02:43:101090 scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
1091 base::WeakPtr<CacheStorageDispatcherHost> cache_storage_dispatcher_host)
Andrew Williams691aceb2022-07-18 17:44:101092 : profile_path_(profile_path),
Evan Stadef3a6c0c2022-04-06 23:57:351093 cache_task_runner_(std::move(cache_task_runner)),
1094 scheduler_task_runner_(std::move(scheduler_task_runner)),
1095 quota_manager_proxy_(std::move(quota_manager_proxy)),
Andrew Williams9eaa2a052022-08-17 02:43:101096 blob_storage_context_(std::move(blob_storage_context)),
1097 cache_storage_dispatcher_host_(std::move(cache_storage_dispatcher_host)) {
Evan Stadef3a6c0c2022-04-06 23:57:351098 DCHECK(cache_task_runner_);
1099 DCHECK(scheduler_task_runner_);
1100 DCHECK(quota_manager_proxy_);
1101 DCHECK(blob_storage_context_);
1102}
1103
Pei Zhangcc4549e2022-05-07 02:51:131104base::FilePath CacheStorageManager::ConstructBucketPath(
Andrew Williams691aceb2022-07-18 17:44:101105 const base::FilePath& profile_path,
Pei Zhangcc4549e2022-05-07 02:51:131106 const storage::BucketLocator& bucket_locator,
1107 storage::mojom::CacheStorageOwner owner) {
1108 if (bucket_locator.is_default &&
1109 bucket_locator.storage_key.IsFirstPartyContext()) {
1110 // Default-bucket & first-party partition:
1111 // {{storage_partition_path}}/Service Worker/CacheStorage/{origin_hash}/...
Andrew Williams691aceb2022-07-18 17:44:101112 return ConstructOriginPath(profile_path,
1113 bucket_locator.storage_key.origin(), owner);
Pei Zhangcc4549e2022-05-07 02:51:131114 }
1115 // Non-default bucket & first/third-party partition:
Andrew Williams85f0925c2022-07-19 17:54:461116 // {{storage_partition_path}}/WebStorage/{{bucket_id}}/CacheStorage/... and
1117 // {{storage_partition_path}}/WebStorage/{{bucket_id}}/BackgroundFetch/...
Evan Stadef92ca432023-04-04 14:51:111118 // TODO(estade): this ought to use
1119 // `quota_manager_proxy_->GetClientBucketPath()`
Andrew Williams85f0925c2022-07-19 17:54:461120 switch (owner) {
1121 case storage::mojom::CacheStorageOwner::kCacheAPI:
1122 return storage::CreateClientBucketPath(
1123 profile_path, bucket_locator,
1124 storage::QuotaClientType::kServiceWorkerCache);
1125 case storage::mojom::CacheStorageOwner::kBackgroundFetch:
1126 return storage::CreateClientBucketPath(
1127 profile_path, bucket_locator,
1128 storage::QuotaClientType::kBackgroundFetch);
1129 default:
1130 NOTREACHED();
1131 }
Pei Zhangcc4549e2022-05-07 02:51:131132}
1133
Ben Kelly4695ea232019-03-08 21:36:021134// static
Antonio Sartoricd09590d2021-06-02 08:51:061135bool CacheStorageManager::IsValidQuotaStorageKey(
1136 const blink::StorageKey& storage_key) {
1137 // Disallow opaque storage keys at the quota boundary because we DCHECK that
1138 // we don't get an opaque key in lower code layers.
Steven Bingler38c03032021-06-09 21:15:271139 return !storage_key.origin().opaque();
Ben Kelly4695ea232019-03-08 21:36:021140}
1141
Evan Stadef3a6c0c2022-04-06 23:57:351142void CacheStorageManager::OnMemoryPressure(
1143 base::MemoryPressureListener::MemoryPressureLevel level) {
1144 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Nathan Memmottcd1426b2023-05-20 01:51:231145 if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
Evan Stadef3a6c0c2022-04-06 23:57:351146 return;
Nathan Memmottcd1426b2023-05-20 01:51:231147 }
Evan Stadef3a6c0c2022-04-06 23:57:351148
1149 for (auto& entry : cache_storage_map_) {
1150 entry.second->ReleaseUnreferencedCaches();
1151 }
1152}
1153
Andrew Williams691aceb2022-07-18 17:44:101154// static
1155base::FilePath CacheStorageManager::ConstructFirstPartyDefaultRootPath(
1156 const base::FilePath& profile_path) {
1157 return profile_path.Append(storage::kServiceWorkerDirectory)
Andrew Williams9eaa2a052022-08-17 02:43:101158 .Append(storage::kCacheStorageDirectory);
1159}
1160
1161// static
1162base::FilePath CacheStorageManager::ConstructThirdPartyAndNonDefaultRootPath(
1163 const base::FilePath& profile_path) {
1164 return profile_path.Append(storage::kWebStorageDirectory);
Andrew Williams691aceb2022-07-18 17:44:101165}
1166
1167// Used by QuotaClient which only wants the storage keys that have data in the
1168// default bucket. Keep this function to return a vector of StorageKeys, instead
1169// of buckets.
1170void CacheStorageManager::ListStorageKeysOnTaskRunner(
1171 storage::mojom::QuotaClient::GetStorageKeysForTypeCallback callback,
Andrew Williams9eaa2a052022-08-17 02:43:101172 std::vector<std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:291173 storage::mojom::StorageUsageInfoPtr>> usage_tuples) {
Andrew Williams8bf996a2022-10-05 04:47:231174 // Note that bucket IDs will not be populated in the `usage_tuples` entries.
Andrew Williams691aceb2022-07-18 17:44:101175 std::vector<blink::StorageKey> out_storage_keys;
Andrew Williams9eaa2a052022-08-17 02:43:101176 for (const std::tuple<storage::BucketLocator,
Ari Chivukulac29c1b82022-09-30 20:49:291177 storage::mojom::StorageUsageInfoPtr>& usage_tuple :
Andrew Williams9eaa2a052022-08-17 02:43:101178 usage_tuples) {
1179 const storage::BucketLocator bucket_locator = std::get<0>(usage_tuple);
Andrew Williams8bf996a2022-10-05 04:47:231180 if (!bucket_locator.is_default) {
Andrew Williams9eaa2a052022-08-17 02:43:101181 continue;
1182 }
1183 out_storage_keys.emplace_back(bucket_locator.storage_key);
1184 }
Andrew Williams691aceb2022-07-18 17:44:101185
1186 scheduler_task_runner_->PostTask(
1187 FROM_HERE,
1188 base::BindOnce(std::move(callback), std::move(out_storage_keys)));
1189}
jkarlin@chromium.org10e9d5d2014-08-09 05:35:171190} // namespace content