1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_H_
#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
#include "content/browser/cache_storage/blob_storage_context_wrapper.h"
#include "content/browser/cache_storage/cache_storage_cache.h"
#include "content/browser/cache_storage/cache_storage_cache_observer.h"
#include "content/browser/cache_storage/cache_storage_handle.h"
#include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/cache_storage/cache_storage_scheduler_types.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "storage/browser/quota/quota_manager.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/application_status_listener.h"
#endif
namespace base {
class SequencedTaskRunner;
}
namespace content {
class CacheStorageIndex;
class CacheStorageScheduler;
class CacheStorageManager;
namespace cache_storage_manager_unittest {
class CacheStorageManagerTest;
FORWARD_DECLARE_TEST(CacheStorageManagerTest, PersistedCacheKeyUsed);
FORWARD_DECLARE_TEST(CacheStorageManagerTest, PutResponseWithExistingFileTest);
FORWARD_DECLARE_TEST(CacheStorageManagerTest, TestErrorInitializingCache);
} // namespace cache_storage_manager_unittest
// TODO(jkarlin): Constrain the total bytes used per storage key.
// CacheStorage holds the set of caches for a given BucketLocator. It is
// owned by the CacheStorageManager. This class expects to be run
// on the IO thread. The asynchronous methods are executed serially.
class CONTENT_EXPORT CacheStorage : public CacheStorageCacheObserver {
public:
constexpr static int64_t kSizeUnknown = -1;
using SizeCallback = base::OnceCallback<void(int64_t)>;
using BoolAndErrorCallback =
base::OnceCallback<void(bool, blink::mojom::CacheStorageError)>;
using ErrorCallback =
base::OnceCallback<void(blink::mojom::CacheStorageError)>;
using CacheAndErrorCallback =
base::OnceCallback<void(CacheStorageCacheHandle,
blink::mojom::CacheStorageError)>;
using EnumerateCachesCallback =
base::OnceCallback<void(std::vector<std::u16string> cache_names)>;
static const char kIndexFileName[];
CacheStorage(const base::FilePath& origin_path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
CacheStorageManager* cache_storage_manager,
const storage::BucketLocator& bucket_locator,
storage::mojom::CacheStorageOwner owner);
CacheStorage(const CacheStorage&) = delete;
CacheStorage& operator=(const CacheStorage&) = delete;
// Any unfinished asynchronous operations may not complete or call their
// callbacks.
virtual ~CacheStorage();
// Creates a new handle to this CacheStorage instance. Each handle represents
// a signal that the CacheStorage is in active use and should avoid cleaning
// up resources, if possible. However, there are some cases, such as a
// user-initiated storage wipe, that will forcibly delete the CacheStorage
// instance. Therefore the handle should be treated as a weak pointer that
// needs to be tested for existence before use.
CacheStorageHandle CreateHandle();
// These methods are called by the CacheStorageHandle to track the number
// of outstanding references.
void AddHandleRef();
void DropHandleRef();
void AssertUnreferenced() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!handle_ref_count_);
}
// Explicitly begin initialization if it has not already been triggered.
void Init();
// Get the cache for the given key. If the cache is not found it is
// created. The CacheStorgeCacheHandle in the callback prolongs the lifetime
// of the cache. Once all handles to a cache are deleted the cache is deleted.
// The cache will also be deleted in the CacheStorage's destructor so be sure
// to check the handle's value before using it.
void OpenCache(const std::u16string& cache_name,
int64_t trace_id,
CacheAndErrorCallback callback);
// Calls the callback with whether or not the cache exists.
void HasCache(const std::u16string& cache_name,
int64_t trace_id,
BoolAndErrorCallback callback);
// Deletes the cache if it exists. If it doesn't exist,
// blink::mojom::CacheStorageError::kErrorNotFound is returned. Any
// existing CacheStorageCacheHandle(s) to the cache will remain valid but
// future CacheStorage operations won't be able to access the cache. The cache
// isn't actually erased from disk until the last handle is dropped.
void DoomCache(const std::u16string& cache_name,
int64_t trace_id,
ErrorCallback callback);
// Calls the callback with the existing cache names.
void EnumerateCaches(int64_t trace_id, EnumerateCachesCallback callback);
// Calls match on the cache with the given |cache_name|.
void MatchCache(const std::u16string& cache_name,
blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
CacheStorageSchedulerPriority priority,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback);
// Calls match on all of the caches in parallel, calling |callback| with the
// response from the first cache (in order of cache creation) to have the
// entry. If no response is found then |callback| is called with
// blink::mojom::CacheStorageError::kErrorNotFound.
void MatchAllCaches(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
CacheStorageSchedulerPriority priority,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback);
// Puts the request/response pair in the cache.
void WriteToCache(const std::u16string& cache_name,
blink::mojom::FetchAPIRequestPtr request,
blink::mojom::FetchAPIResponsePtr response,
int64_t trace_id,
ErrorCallback callback);
// Sums the sizes of each cache and closes them. Runs |callback| with the
// size. The sizes include any doomed caches and will also force close all
// caches even if there are existing handles to them.
void GetSizeThenCloseAllCaches(SizeCallback callback);
// The size of all of the storage key's contents. This value should be used as
// an estimate only since the cache may be modified at any time.
void Size(SizeCallback callback);
// The functions below are for tests to verify that the operations run
// serially.
CacheStorageSchedulerId StartAsyncOperationForTesting();
void CompleteAsyncOperationForTesting(CacheStorageSchedulerId id);
// Removes the manager reference. Called before this storage is deleted by the
// manager, since it is removed from manager's storage map before deleting.
void ResetManager();
// CacheStorageCacheObserver:
void CacheSizeUpdated(const CacheStorageCache* cache) override;
// Destroy any CacheStorageCache instances that are not currently referenced
// by a CacheStorageCacheHandle.
void ReleaseUnreferencedCaches();
static CacheStorage* From(const CacheStorageHandle& handle) {
return static_cast<CacheStorage*>(handle.value());
}
static std::u16string ConvertUTF16BytesStringToU16String(
const std::string& utf16_bytes,
bool correct_encoding);
protected:
// Virtual for testing
virtual void CacheUnreferenced(CacheStorageCache* cache);
private:
friend class CacheStorageCache;
friend class cache_storage_manager_unittest::CacheStorageManagerTest;
FRIEND_TEST_ALL_PREFIXES(
cache_storage_manager_unittest::CacheStorageManagerTest,
PersistedCacheKeyUsed);
FRIEND_TEST_ALL_PREFIXES(
cache_storage_manager_unittest::CacheStorageManagerTest,
PutResponseWithExistingFileTest);
FRIEND_TEST_ALL_PREFIXES(
cache_storage_manager_unittest::CacheStorageManagerTest,
TestErrorInitializingCache);
class CacheLoader;
class MemoryLoader;
class SimpleCacheLoader;
struct CacheMatchResponse;
typedef std::map<std::u16string, std::unique_ptr<CacheStorageCache>> CacheMap;
// Generate a new padding key. For testing only and *not thread safe*.
static void GenerateNewKeyForTesting();
// Returns a CacheStorageCacheHandle for the given name if the name is known.
// If the CacheStorageCache has been deleted, creates a new one.
CacheStorageCacheHandle GetLoadedCache(const std::u16string& cache_name);
// Initializer and its callback are below.
void LazyInit();
void LazyInitImpl();
void LazyInitDidLoadIndex(std::unique_ptr<CacheStorageIndex> index);
// The Open and CreateCache callbacks are below.
void OpenCacheImpl(const std::u16string& cache_name,
int64_t trace_id,
CacheAndErrorCallback callback);
void CreateCacheDidCreateCache(const std::u16string& cache_name,
int64_t trace_id,
CacheAndErrorCallback callback,
std::unique_ptr<CacheStorageCache> cache,
blink::mojom::CacheStorageError status);
void CreateCacheDidWriteIndex(CacheAndErrorCallback callback,
CacheStorageCacheHandle cache_handle,
int64_t trace_id,
bool success);
// The HasCache callbacks are below.
void HasCacheImpl(const std::u16string& cache_name,
int64_t trace_id,
BoolAndErrorCallback callback);
// The DeleteCache callbacks are below.
void DoomCacheImpl(const std::u16string& cache_name,
int64_t trace_id,
ErrorCallback callback);
void DeleteCacheDidWriteIndex(CacheStorageCacheHandle cache_handle,
ErrorCallback callback,
int64_t trace_id,
bool success);
void DeleteCacheFinalize(CacheStorageCache* doomed_cache);
void DeleteCacheDidGetSize(CacheStorageCache* doomed_cache,
int64_t cache_size);
void DeleteCacheDidCleanUp(bool success);
// The EnumerateCache callbacks are below.
void EnumerateCachesImpl(int64_t trace_id, EnumerateCachesCallback callback);
// The MatchCache callbacks are below.
void MatchCacheImpl(const std::u16string& cache_name,
blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
CacheStorageSchedulerPriority priority,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback);
void MatchCacheDidMatch(CacheStorageCacheHandle cache_handle,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback,
blink::mojom::CacheStorageError error,
blink::mojom::FetchAPIResponsePtr response);
// The MatchAllCaches callbacks are below.
void MatchAllCachesImpl(blink::mojom::FetchAPIRequestPtr request,
blink::mojom::CacheQueryOptionsPtr match_options,
CacheStorageSchedulerPriority priority,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback);
void MatchAllCachesDidMatch(CacheStorageCacheHandle cache_handle,
CacheMatchResponse* out_match_response,
const base::RepeatingClosure& barrier_closure,
int64_t trace_id,
blink::mojom::CacheStorageError error,
blink::mojom::FetchAPIResponsePtr response);
void MatchAllCachesDidMatchAll(
std::unique_ptr<std::vector<CacheMatchResponse>> match_responses,
int64_t trace_id,
CacheStorageCache::ResponseCallback callback);
// WriteToCache callbacks.
void WriteToCacheImpl(const std::u16string& cache_name,
blink::mojom::FetchAPIRequestPtr request,
blink::mojom::FetchAPIResponsePtr response,
int64_t trace_id,
ErrorCallback callback);
void GetSizeThenCloseAllCachesImpl(SizeCallback callback);
void SizeImpl(SizeCallback callback);
void SizeRetrievedFromCache(CacheStorageCacheHandle cache_handle,
base::OnceClosure closure,
int64_t* accumulator,
int64_t size);
void NotifyCacheContentChanged(const std::u16string& cache_name);
void ScheduleWriteIndex();
void WriteIndex(base::OnceCallback<void(bool)> callback);
void WriteIndexImpl(base::OnceCallback<void(bool)> callback);
bool index_write_pending() const { return !index_write_task_.IsCancelled(); }
// Start a scheduled index write immediately. Returns true if a write was
// scheduled, or false if not.
bool InitiateScheduledIndexWriteForTest(
base::OnceCallback<void(bool)> callback);
void FlushIndexIfDirty();
#if BUILDFLAG(IS_ANDROID)
void OnApplicationStateChange(base::android::ApplicationState state);
#endif
// The `BucketLocator` that this CacheStorage is associated with.
const storage::BucketLocator bucket_locator_;
// Whether or not we've loaded the list of cache names into memory.
bool initialized_ = false;
bool initializing_ = false;
// True if the backend is supposed to reside in memory only.
const bool memory_only_;
// The pending operation scheduler.
std::unique_ptr<CacheStorageScheduler> scheduler_;
// The map of cache names to CacheStorageCache objects.
CacheMap cache_map_;
// Caches that have been deleted but must still be held onto until all handles
// have been released.
std::map<CacheStorageCache*, std::unique_ptr<CacheStorageCache>>
doomed_caches_;
// The cache index data.
std::unique_ptr<CacheStorageIndex> cache_index_;
// The file path for this CacheStorage.
base::FilePath directory_path_;
// The TaskRunner to run file IO on.
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
size_t handle_ref_count_ = 0;
// Performs backend specific operations (memory vs disk).
std::unique_ptr<CacheLoader> cache_loader_;
// The quota manager.
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
// An IO thread bound wrapper for storage.mojom.BlobStorageContext.
scoped_refptr<BlobStorageContextWrapper> blob_storage_context_;
// The owner that this CacheStorage is associated with.
const storage::mojom::CacheStorageOwner owner_;
CacheStorageSchedulerId init_id_ = -1;
// The manager that owns this cache storage. Only set to null by
// RemoveManager() when this cache storage is being deleted.
raw_ptr<CacheStorageManager> cache_storage_manager_;
base::CancelableOnceClosure index_write_task_;
#if BUILDFLAG(IS_ANDROID)
std::unique_ptr<base::android::ApplicationStatusListener>
app_status_listener_;
#endif
// True if running on android and the app is in the background.
bool app_on_background_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CacheStorage> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_H_
|