1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <list>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/containers/flat_map.h"
14 #include "base/files/file_enumerator.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/guid.h"
19 #include "base/macros.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/memory/scoped_refptr.h"
22 #include "base/run_loop.h"
23 #include "base/stl_util.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/test/bind.h"
26 #include "base/test/metrics/histogram_tester.h"
27 #include "base/threading/thread_task_runner_handle.h"
28 #include "build/build_config.h"
29 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
30 #include "content/browser/cache_storage/cache_storage.pb.h"
31 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
32 #include "content/browser/cache_storage/cache_storage_context_impl.h"
33 #include "content/browser/cache_storage/cache_storage_quota_client.h"
34 #include "content/browser/cache_storage/cache_storage_scheduler.h"
35 #include "content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.h"
36 #include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
37 #include "content/browser/cache_storage/legacy/legacy_cache_storage_manager.h"
38 #include "content/common/background_fetch/background_fetch_types.h"
39 #include "content/public/browser/browser_thread.h"
40 #include "content/public/browser/storage_usage_info.h"
41 #include "content/public/test/browser_task_environment.h"
42 #include "content/public/test/test_browser_context.h"
43 #include "content/public/test/test_utils.h"
44 #include "mojo/public/cpp/bindings/pending_remote.h"
45 #include "mojo/public/cpp/bindings/receiver.h"
46 #include "mojo/public/cpp/bindings/remote.h"
47 #include "net/disk_cache/disk_cache.h"
48 #include "services/network/public/mojom/fetch_api.mojom.h"
49 #include "storage/browser/blob/blob_storage_context.h"
50 #include "storage/browser/quota/padding_key.h"
51 #include "storage/browser/quota/quota_client_type.h"
52 #include "storage/browser/quota/quota_manager_proxy.h"
53 #include "storage/browser/test/fake_blob.h"
54 #include "storage/browser/test/mock_quota_manager_proxy.h"
55 #include "storage/browser/test/mock_special_storage_policy.h"
56 #include "testing/gmock/include/gmock/gmock-matchers.h"
57 #include "testing/gtest/include/gtest/gtest.h"
58 #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
59 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
60 #include "url/gurl.h"
61 #include "url/origin.h"
62
63 using blink::mojom::CacheStorageError;
64 using blink::mojom::CacheStorageVerboseErrorPtr;
65 using network::mojom::FetchResponseType;
66
67 namespace content {
68 namespace cache_storage_manager_unittest {
69
70 enum class TestManager {
71 kLegacy,
72 kCrossSequence,
73 };
74
75 enum class TestStorage {
76 kDisk,
77 kMemory,
78 };
79
80 struct Param {
Paramcontent::cache_storage_manager_unittest::Param81 Param(TestManager manager, TestStorage storage)
82 : manager_(manager), storage_(storage) {}
83
84 TestManager manager_;
85 TestStorage storage_;
86 };
87
88 using blink::mojom::StorageType;
89 using ResponseHeaderMap = base::flat_map<std::string, std::string>;
90
91 class DelayedBlob : public storage::FakeBlob {
92 public:
DelayedBlob(mojo::PendingReceiver<blink::mojom::Blob> receiver,std::string data,base::OnceClosure read_closure)93 DelayedBlob(mojo::PendingReceiver<blink::mojom::Blob> receiver,
94 std::string data,
95 base::OnceClosure read_closure)
96 : FakeBlob("foo"),
97 receiver_(this, std::move(receiver)),
98 data_(std::move(data)),
99 read_closure_(std::move(read_closure)) {}
100
Resume()101 void Resume() {
102 paused_ = false;
103 MaybeComplete();
104 }
105
ReadAll(mojo::ScopedDataPipeProducerHandle producer_handle,mojo::PendingRemote<blink::mojom::BlobReaderClient> client)106 void ReadAll(
107 mojo::ScopedDataPipeProducerHandle producer_handle,
108 mojo::PendingRemote<blink::mojom::BlobReaderClient> client) override {
109 client_.Bind(std::move(client));
110 producer_handle_ = std::move(producer_handle);
111
112 client_->OnCalculatedSize(data_.length(), data_.length());
113
114 // This should always succeed immediately because we size the pipe to
115 // hold the entire blob for tiny data lengths.
116 uint32_t num_bytes = data_.length();
117 producer_handle_->WriteData(data_.data(), &num_bytes,
118 MOJO_WRITE_DATA_FLAG_NONE);
119 ASSERT_EQ(data_.length(), num_bytes);
120
121 // Signal that ReadAll() was called.
122 std::move(read_closure_).Run();
123
124 MaybeComplete();
125 }
126
127 private:
MaybeComplete()128 void MaybeComplete() {
129 if (paused_ || !client_)
130 return;
131 client_->OnComplete(net::OK, data_.length());
132 client_.reset();
133 producer_handle_.reset();
134 }
135
136 mojo::Receiver<blink::mojom::Blob> receiver_;
137 std::string data_;
138 base::OnceClosure read_closure_;
139 mojo::Remote<blink::mojom::BlobReaderClient> client_;
140 mojo::ScopedDataPipeProducerHandle producer_handle_;
141 bool paused_ = true;
142 };
143
144 // Scheduler implementation that will invoke a callback after the
145 // next operation has been started.
146 class CallbackScheduler : public CacheStorageScheduler {
147 public:
CallbackScheduler(base::OnceClosure callback)148 explicit CallbackScheduler(base::OnceClosure callback)
149 : CacheStorageScheduler(CacheStorageSchedulerClient::kCache,
150 base::ThreadTaskRunnerHandle::Get()),
151 callback_(std::move(callback)) {}
152
153 protected:
DispatchOperationTask(base::OnceClosure task)154 void DispatchOperationTask(base::OnceClosure task) override {
155 auto wrapped = base::BindOnce(&CallbackScheduler::ExecuteTask,
156 base::Unretained(this), std::move(task));
157 CacheStorageScheduler::DispatchOperationTask(std::move(wrapped));
158 }
159
160 private:
ExecuteTask(base::OnceClosure task)161 void ExecuteTask(base::OnceClosure task) {
162 std::move(task).Run();
163 if (callback_)
164 std::move(callback_).Run();
165 }
166
167 base::OnceClosure callback_;
168 };
169
170 class MockCacheStorageQuotaManagerProxy
171 : public storage::MockQuotaManagerProxy {
172 public:
MockCacheStorageQuotaManagerProxy(storage::MockQuotaManager * quota_manager,base::SingleThreadTaskRunner * task_runner)173 MockCacheStorageQuotaManagerProxy(storage::MockQuotaManager* quota_manager,
174 base::SingleThreadTaskRunner* task_runner)
175 : MockQuotaManagerProxy(quota_manager, task_runner) {}
176
RegisterClient(scoped_refptr<storage::QuotaClient> client,storage::QuotaClientType client_type,const std::vector<blink::mojom::StorageType> & storage_types)177 void RegisterClient(
178 scoped_refptr<storage::QuotaClient> client,
179 storage::QuotaClientType client_type,
180 const std::vector<blink::mojom::StorageType>& storage_types) override {
181 registered_clients_.push_back(std::move(client));
182 }
183
SimulateQuotaManagerDestroyed()184 void SimulateQuotaManagerDestroyed() override {
185 for (const auto& client : registered_clients_) {
186 client->OnQuotaManagerDestroyed();
187 }
188 registered_clients_.clear();
189 }
190
191 private:
~MockCacheStorageQuotaManagerProxy()192 ~MockCacheStorageQuotaManagerProxy() override {
193 DCHECK(registered_clients_.empty());
194 }
195
196 std::vector<scoped_refptr<storage::QuotaClient>> registered_clients_;
197 };
198
IsIndexFileCurrent(const base::FilePath & cache_dir)199 bool IsIndexFileCurrent(const base::FilePath& cache_dir) {
200 base::File::Info info;
201 const base::FilePath index_path =
202 cache_dir.AppendASCII(LegacyCacheStorage::kIndexFileName);
203 if (!GetFileInfo(index_path, &info))
204 return false;
205 base::Time index_last_modified = info.last_modified;
206
207 base::FileEnumerator enumerator(cache_dir, false,
208 base::FileEnumerator::DIRECTORIES);
209 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
210 file_path = enumerator.Next()) {
211 if (!GetFileInfo(file_path, &info))
212 return false;
213 if (index_last_modified < info.last_modified)
214 return false;
215 }
216
217 return true;
218 }
219
220 class TestCacheStorageObserver : public CacheStorageContextImpl::Observer {
221 public:
TestCacheStorageObserver()222 TestCacheStorageObserver() : loop_(std::make_unique<base::RunLoop>()) {}
223
OnCacheListChanged(const url::Origin & origin)224 void OnCacheListChanged(const url::Origin& origin) override {
225 ++notify_list_changed_count;
226 loop_->Quit();
227 }
228
OnCacheContentChanged(const url::Origin & origin,const std::string & cache_name)229 void OnCacheContentChanged(const url::Origin& origin,
230 const std::string& cache_name) override {
231 ++notify_content_changed_count;
232 loop_->Quit();
233 }
234
Wait()235 void Wait() {
236 loop_->Run();
237 loop_ = std::make_unique<base::RunLoop>();
238 }
239
240 base::OnceClosure callback;
241 int notify_list_changed_count = 0;
242 int notify_content_changed_count = 0;
243
244 std::unique_ptr<base::RunLoop> loop_;
245 };
246
247 class TestCacheStorageContext : public CacheStorageContextWithManager {
248 public:
TestCacheStorageContext(scoped_refptr<CacheStorageManager> manager)249 explicit TestCacheStorageContext(scoped_refptr<CacheStorageManager> manager)
250 : manager_(std::move(manager)) {}
251
CacheManager()252 scoped_refptr<CacheStorageManager> CacheManager() override {
253 return manager_;
254 }
255
GetAllOriginsInfo(GetUsageInfoCallback callback)256 void GetAllOriginsInfo(GetUsageInfoCallback callback) override {
257 NOTREACHED();
258 }
259
DeleteForOrigin(const url::Origin & origin)260 void DeleteForOrigin(const url::Origin& origin) override { NOTREACHED(); }
261
262 private:
263 ~TestCacheStorageContext() override = default;
264 scoped_refptr<CacheStorageManager> manager_;
265 };
266
267 class CacheStorageManagerTest : public testing::Test {
268 public:
CacheStorageManagerTest()269 CacheStorageManagerTest()
270 : task_environment_(BrowserTaskEnvironment::IO_MAINLOOP),
271 blob_storage_context_(nullptr),
272 observers_(
273 base::MakeRefCounted<CacheStorageContextImpl::ObserverList>()),
274 origin1_(url::Origin::Create(GURL("http://example1.com"))),
275 origin2_(url::Origin::Create(GURL("http://example2.com"))) {}
276
SetUp()277 void SetUp() override {
278 base::FilePath temp_dir_path;
279 if (!MemoryOnly())
280 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
281
282 CreateStorageManager();
283 }
284
TearDown()285 void TearDown() override {
286 DestroyStorageManager();
287 disk_cache::FlushCacheThreadForTesting();
288 content::RunAllTasksUntilIdle();
289 }
290
MemoryOnly()291 virtual bool MemoryOnly() { return false; }
ManagerType()292 virtual TestManager ManagerType() { return TestManager::kLegacy; }
293
BoolCallback(base::RunLoop * run_loop,bool value)294 void BoolCallback(base::RunLoop* run_loop, bool value) {
295 callback_bool_ = value;
296 run_loop->Quit();
297 }
298
ErrorCallback(base::RunLoop * run_loop,CacheStorageError error)299 void ErrorCallback(base::RunLoop* run_loop, CacheStorageError error) {
300 callback_error_ = error;
301 callback_bool_ = error == CacheStorageError::kSuccess;
302 run_loop->Quit();
303 }
304
BoolAndErrorCallback(base::RunLoop * run_loop,bool value,CacheStorageError error)305 void BoolAndErrorCallback(base::RunLoop* run_loop,
306 bool value,
307 CacheStorageError error) {
308 callback_bool_ = value;
309 callback_error_ = error;
310 run_loop->Quit();
311 }
312
CacheAndErrorCallback(base::RunLoop * run_loop,CacheStorageCacheHandle cache_handle,CacheStorageError error)313 void CacheAndErrorCallback(base::RunLoop* run_loop,
314 CacheStorageCacheHandle cache_handle,
315 CacheStorageError error) {
316 callback_cache_handle_ = std::move(cache_handle);
317 callback_error_ = error;
318 run_loop->Quit();
319 }
320
CacheMetadataCallback(base::RunLoop * run_loop,std::vector<std::string> cache_names)321 void CacheMetadataCallback(base::RunLoop* run_loop,
322 std::vector<std::string> cache_names) {
323 cache_names_ = std::move(cache_names);
324 run_loop->Quit();
325 }
326
GetFirstIndexName() const327 const std::string& GetFirstIndexName() const { return cache_names_.front(); }
328
GetIndexNames() const329 std::vector<std::string> GetIndexNames() const { return cache_names_; }
330
CachePutCallback(base::RunLoop * run_loop,CacheStorageVerboseErrorPtr error)331 void CachePutCallback(base::RunLoop* run_loop,
332 CacheStorageVerboseErrorPtr error) {
333 callback_error_ = error->value;
334 run_loop->Quit();
335 }
336
CacheDeleteCallback(base::RunLoop * run_loop,CacheStorageVerboseErrorPtr error)337 void CacheDeleteCallback(base::RunLoop* run_loop,
338 CacheStorageVerboseErrorPtr error) {
339 callback_error_ = error->value;
340 run_loop->Quit();
341 }
342
CacheMatchCallback(base::RunLoop * run_loop,CacheStorageError error,blink::mojom::FetchAPIResponsePtr response)343 void CacheMatchCallback(base::RunLoop* run_loop,
344 CacheStorageError error,
345 blink::mojom::FetchAPIResponsePtr response) {
346 callback_error_ = error;
347 callback_cache_handle_response_ = std::move(response);
348 run_loop->Quit();
349 }
350
CacheMatchAllCallback(base::RunLoop * run_loop,CacheStorageError error,std::vector<blink::mojom::FetchAPIResponsePtr>)351 void CacheMatchAllCallback(base::RunLoop* run_loop,
352 CacheStorageError error,
353 std::vector<blink::mojom::FetchAPIResponsePtr>) {
354 callback_error_ = error;
355 run_loop->Quit();
356 }
357
CreateStorageManager()358 void CreateStorageManager() {
359 ChromeBlobStorageContext* blob_storage_context(
360 ChromeBlobStorageContext::GetFor(&browser_context_));
361 // Wait for ChromeBlobStorageContext to finish initializing.
362 base::RunLoop().RunUntilIdle();
363
364 mojo::PendingRemote<storage::mojom::BlobStorageContext> remote;
365 blob_storage_context->BindMojoContext(
366 remote.InitWithNewPipeAndPassReceiver());
367 blob_storage_context_ =
368 base::MakeRefCounted<BlobStorageContextWrapper>(std::move(remote));
369
370 base::FilePath temp_dir_path;
371 if (!MemoryOnly())
372 temp_dir_path = temp_dir_.GetPath();
373
374 quota_policy_ = base::MakeRefCounted<storage::MockSpecialStoragePolicy>();
375 mock_quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>(
376 MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
377 quota_policy_.get());
378 mock_quota_manager_->SetQuota(origin1_, StorageType::kTemporary,
379 1024 * 1024 * 100);
380 mock_quota_manager_->SetQuota(origin2_, StorageType::kTemporary,
381 1024 * 1024 * 100);
382
383 quota_manager_proxy_ =
384 base::MakeRefCounted<MockCacheStorageQuotaManagerProxy>(
385 mock_quota_manager_.get(),
386 base::ThreadTaskRunnerHandle::Get().get());
387
388 auto legacy_manager = LegacyCacheStorageManager::Create(
389 temp_dir_path, base::ThreadTaskRunnerHandle::Get(),
390 base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_, observers_);
391 legacy_manager->SetBlobParametersForCache(blob_storage_context_);
392
393 switch (ManagerType()) {
394 case TestManager::kLegacy:
395 cache_manager_ = std::move(legacy_manager);
396 break;
397 case TestManager::kCrossSequence:
398 auto context = base::MakeRefCounted<TestCacheStorageContext>(
399 std::move(legacy_manager));
400 cache_manager_ = base::MakeRefCounted<CrossSequenceCacheStorageManager>(
401 base::ThreadTaskRunnerHandle::Get(), std::move(context));
402 break;
403 }
404 }
405
RecreateStorageManager()406 void RecreateStorageManager() {
407 DCHECK(cache_manager_);
408 auto* legacy_manager =
409 static_cast<LegacyCacheStorageManager*>(cache_manager_.get());
410 cache_manager_ =
411 LegacyCacheStorageManager::CreateForTesting(legacy_manager);
412 }
413
FlushCacheStorageIndex(const url::Origin & origin)414 bool FlushCacheStorageIndex(const url::Origin& origin) {
415 DCHECK(ManagerType() == TestManager::kLegacy);
416 callback_bool_ = false;
417 base::RunLoop loop;
418 auto* impl = LegacyCacheStorage::From(CacheStorageForOrigin(origin));
419 bool write_was_scheduled = impl->InitiateScheduledIndexWriteForTest(
420 base::BindOnce(&CacheStorageManagerTest::BoolCallback,
421 base::Unretained(this), &loop));
422 loop.Run();
423 DCHECK(callback_bool_);
424 return write_was_scheduled;
425 }
426
DestroyStorageManager()427 void DestroyStorageManager() {
428 if (quota_manager_proxy_)
429 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
430
431 callback_cache_handle_ = CacheStorageCacheHandle();
432 callback_bool_ = false;
433 callback_cache_handle_response_ = nullptr;
434 cache_names_.clear();
435 callback_all_origins_usage_.clear();
436
437 base::RunLoop().RunUntilIdle();
438 quota_manager_proxy_ = nullptr;
439
440 blob_storage_context_ = nullptr;
441
442 quota_policy_ = nullptr;
443 mock_quota_manager_ = nullptr;
444
445 cache_manager_ = nullptr;
446 }
447
CheckOpHistograms(base::HistogramTester & histogram_tester,const char * op_name)448 void CheckOpHistograms(base::HistogramTester& histogram_tester,
449 const char* op_name) {
450 std::string base("ServiceWorkerCache.CacheStorage.Scheduler.");
451 histogram_tester.ExpectTotalCount(base + "OperationDuration2." + op_name,
452 1);
453 histogram_tester.ExpectTotalCount(base + "QueueDuration2." + op_name, 1);
454 histogram_tester.ExpectTotalCount(base + "QueueLength." + op_name, 1);
455 }
456
Open(const url::Origin & origin,const std::string & cache_name,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)457 bool Open(const url::Origin& origin,
458 const std::string& cache_name,
459 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
460 base::HistogramTester histogram_tester;
461 base::RunLoop loop;
462 CacheStorageHandle cache_storage =
463 cache_manager_->OpenCacheStorage(origin, owner);
464 cache_storage.value()->OpenCache(
465 cache_name, /* trace_id = */ 0,
466 base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
467 base::Unretained(this), base::Unretained(&loop)));
468 loop.Run();
469
470 bool error = callback_error_ != CacheStorageError::kSuccess;
471 if (error) {
472 EXPECT_FALSE(callback_cache_handle_.value());
473 } else {
474 EXPECT_TRUE(callback_cache_handle_.value());
475 CheckOpHistograms(histogram_tester, "Open");
476 }
477 return !error;
478 }
479
Has(const url::Origin & origin,const std::string & cache_name,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)480 bool Has(const url::Origin& origin,
481 const std::string& cache_name,
482 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
483 base::HistogramTester histogram_tester;
484 base::RunLoop loop;
485 CacheStorageHandle cache_storage =
486 cache_manager_->OpenCacheStorage(origin, owner);
487 cache_storage.value()->HasCache(
488 cache_name, /* trace_id = */ 0,
489 base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback,
490 base::Unretained(this), base::Unretained(&loop)));
491 loop.Run();
492 CheckOpHistograms(histogram_tester, "Has");
493 return callback_bool_;
494 }
495
Delete(const url::Origin & origin,const std::string & cache_name,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)496 bool Delete(const url::Origin& origin,
497 const std::string& cache_name,
498 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
499 base::HistogramTester histogram_tester;
500 base::RunLoop loop;
501 CacheStorageHandle cache_storage =
502 cache_manager_->OpenCacheStorage(origin, owner);
503 cache_storage.value()->DoomCache(
504 cache_name, /* trace_id = */ 0,
505 base::BindOnce(&CacheStorageManagerTest::ErrorCallback,
506 base::Unretained(this), base::Unretained(&loop)));
507 loop.Run();
508 CheckOpHistograms(histogram_tester, "Delete");
509 return callback_bool_;
510 }
511
Keys(const url::Origin & origin,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)512 size_t Keys(const url::Origin& origin,
513 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
514 base::HistogramTester histogram_tester;
515 base::RunLoop loop;
516 CacheStorageHandle cache_storage =
517 cache_manager_->OpenCacheStorage(origin, owner);
518 cache_storage.value()->EnumerateCaches(
519 /* trace_id = */ 0,
520 base::BindOnce(&CacheStorageManagerTest::CacheMetadataCallback,
521 base::Unretained(this), base::Unretained(&loop)));
522 loop.Run();
523 CheckOpHistograms(histogram_tester, "Keys");
524 return cache_names_.size();
525 }
526
StorageMatch(const url::Origin & origin,const std::string & cache_name,const GURL & url,blink::mojom::CacheQueryOptionsPtr match_options=nullptr,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)527 bool StorageMatch(const url::Origin& origin,
528 const std::string& cache_name,
529 const GURL& url,
530 blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
531 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
532 auto request = blink::mojom::FetchAPIRequest::New();
533 request->url = url;
534 return StorageMatchWithRequest(origin, cache_name, std::move(request),
535 std::move(match_options), owner);
536 }
537
StorageMatchWithRequest(const url::Origin & origin,const std::string & cache_name,blink::mojom::FetchAPIRequestPtr request,blink::mojom::CacheQueryOptionsPtr match_options=nullptr,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)538 bool StorageMatchWithRequest(
539 const url::Origin& origin,
540 const std::string& cache_name,
541 blink::mojom::FetchAPIRequestPtr request,
542 blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
543 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
544 base::HistogramTester histogram_tester;
545 base::RunLoop loop;
546 CacheStorageHandle cache_storage =
547 cache_manager_->OpenCacheStorage(origin, owner);
548 cache_storage.value()->MatchCache(
549 cache_name, std::move(request), std::move(match_options),
550 CacheStorageSchedulerPriority::kNormal, /* trace_id = */ 0,
551 base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
552 base::Unretained(this), base::Unretained(&loop)));
553 loop.Run();
554 if (callback_error_ == CacheStorageError::kSuccess)
555 CheckOpHistograms(histogram_tester, "Match");
556 return callback_error_ == CacheStorageError::kSuccess;
557 }
558
StorageMatchAll(const url::Origin & origin,const GURL & url,blink::mojom::CacheQueryOptionsPtr match_options=nullptr)559 bool StorageMatchAll(
560 const url::Origin& origin,
561 const GURL& url,
562 blink::mojom::CacheQueryOptionsPtr match_options = nullptr) {
563 auto request = blink::mojom::FetchAPIRequest::New();
564 request->url = url;
565 return StorageMatchAllWithRequest(origin, std::move(request),
566 std::move(match_options));
567 }
568
StorageMatchAllWithRequest(const url::Origin & origin,blink::mojom::FetchAPIRequestPtr request,blink::mojom::CacheQueryOptionsPtr match_options=nullptr,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)569 bool StorageMatchAllWithRequest(
570 const url::Origin& origin,
571 blink::mojom::FetchAPIRequestPtr request,
572 blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
573 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
574 base::HistogramTester histogram_tester;
575 base::RunLoop loop;
576 CacheStorageHandle cache_storage =
577 cache_manager_->OpenCacheStorage(origin, owner);
578 cache_storage.value()->MatchAllCaches(
579 std::move(request), std::move(match_options),
580 CacheStorageSchedulerPriority::kNormal, /* trace_id = */ 0,
581 base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
582 base::Unretained(this), base::Unretained(&loop)));
583 loop.Run();
584 if (callback_error_ == CacheStorageError::kSuccess)
585 CheckOpHistograms(histogram_tester, "MatchAll");
586 return callback_error_ == CacheStorageError::kSuccess;
587 }
588
Write(const url::Origin & origin,CacheStorageOwner owner,const std::string & cache_name,const std::string & request_url)589 bool Write(const url::Origin& origin,
590 CacheStorageOwner owner,
591 const std::string& cache_name,
592 const std::string& request_url) {
593 auto request = blink::mojom::FetchAPIRequest::New();
594 request->url = GURL(request_url);
595
596 base::RunLoop loop;
597 CacheStorageHandle cache_storage =
598 cache_manager_->OpenCacheStorage(origin, owner);
599 cache_storage.value()->WriteToCache(
600 cache_name, std::move(request), blink::mojom::FetchAPIResponse::New(),
601 /* trace_id = */ 0,
602 base::BindOnce(&CacheStorageManagerTest::ErrorCallback,
603 base::Unretained(this), base::Unretained(&loop)));
604 loop.Run();
605 return callback_bool_;
606 }
607
CachePut(CacheStorageCache * cache,const GURL & url,FetchResponseType response_type=FetchResponseType::kDefault)608 bool CachePut(CacheStorageCache* cache,
609 const GURL& url,
610 FetchResponseType response_type = FetchResponseType::kDefault) {
611 auto request = blink::mojom::FetchAPIRequest::New();
612 request->url = url;
613
614 return CachePutWithStatusCode(cache, std::move(request), 200,
615 response_type);
616 }
617
CachePutWithRequestAndHeaders(CacheStorageCache * cache,blink::mojom::FetchAPIRequestPtr request,ResponseHeaderMap response_headers,FetchResponseType response_type=FetchResponseType::kDefault)618 bool CachePutWithRequestAndHeaders(
619 CacheStorageCache* cache,
620 blink::mojom::FetchAPIRequestPtr request,
621 ResponseHeaderMap response_headers,
622 FetchResponseType response_type = FetchResponseType::kDefault) {
623 return CachePutWithStatusCode(cache, std::move(request), 200, response_type,
624 std::move(response_headers));
625 }
626
CachePutWithStatusCode(CacheStorageCache * cache,blink::mojom::FetchAPIRequestPtr request,int status_code,FetchResponseType response_type=FetchResponseType::kDefault,ResponseHeaderMap response_headers=ResponseHeaderMap ())627 bool CachePutWithStatusCode(
628 CacheStorageCache* cache,
629 blink::mojom::FetchAPIRequestPtr request,
630 int status_code,
631 FetchResponseType response_type = FetchResponseType::kDefault,
632 ResponseHeaderMap response_headers = ResponseHeaderMap()) {
633 std::string blob_uuid = base::GenerateGUID();
634
635 auto blob = blink::mojom::SerializedBlob::New();
636 blob->uuid = blob_uuid;
637 blob->size = request->url.spec().size();
638 auto& str = request->url.spec();
639 blob_storage_context_->context()->RegisterFromMemory(
640 blob->blob.InitWithNewPipeAndPassReceiver(), blob_uuid,
641 std::vector<uint8_t>(str.begin(), str.end()));
642
643 base::RunLoop loop;
644 CachePutWithStatusCodeAndBlobInternal(cache, std::move(request),
645 status_code, std::move(blob), &loop,
646 response_type, response_headers);
647 loop.Run();
648
649 return callback_error_ == CacheStorageError::kSuccess;
650 }
651
CachePutWithStatusCodeAndBlobInternal(CacheStorageCache * cache,blink::mojom::FetchAPIRequestPtr request,int status_code,blink::mojom::SerializedBlobPtr blob,base::RunLoop * loop,FetchResponseType response_type=FetchResponseType::kDefault,ResponseHeaderMap response_headers=ResponseHeaderMap ())652 void CachePutWithStatusCodeAndBlobInternal(
653 CacheStorageCache* cache,
654 blink::mojom::FetchAPIRequestPtr request,
655 int status_code,
656 blink::mojom::SerializedBlobPtr blob,
657 base::RunLoop* loop,
658 FetchResponseType response_type = FetchResponseType::kDefault,
659 ResponseHeaderMap response_headers = ResponseHeaderMap()) {
660 auto response = blink::mojom::FetchAPIResponse::New(
661 std::vector<GURL>({request->url}), status_code, "OK", response_type,
662 network::mojom::FetchResponseSource::kUnspecified, response_headers,
663 base::nullopt /* mime_type */, net::HttpRequestHeaders::kGetMethod,
664 std::move(blob), blink::mojom::ServiceWorkerResponseError::kUnknown,
665 base::Time(), std::string() /* cache_storage_cache_name */,
666 std::vector<std::string>() /* cors_exposed_header_names */,
667 nullptr /* side_data_blob */,
668 nullptr /* side_data_blob_for_cache_put */,
669 network::mojom::ParsedHeaders::New(),
670 net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
671 "unknown" /* alpn_negotiated_protocol */,
672 false /* loaded_with_credentials */, false /* was_fetched_via_spdy */,
673 false /* has_range_requested */);
674
675 blink::mojom::BatchOperationPtr operation =
676 blink::mojom::BatchOperation::New();
677 operation->operation_type = blink::mojom::OperationType::kPut;
678 operation->request = std::move(request);
679 operation->response = std::move(response);
680
681 std::vector<blink::mojom::BatchOperationPtr> operations;
682 operations.emplace_back(std::move(operation));
683 cache->BatchOperation(
684 std::move(operations), /* trace_id = */ 0,
685 base::BindOnce(&CacheStorageManagerTest::CachePutCallback,
686 base::Unretained(this), base::Unretained(loop)),
687 CacheStorageCache::BadMessageCallback());
688 }
689
CacheDelete(CacheStorageCache * cache,const GURL & url)690 bool CacheDelete(CacheStorageCache* cache, const GURL& url) {
691 auto request = blink::mojom::FetchAPIRequest::New();
692 request->url = url;
693
694 blink::mojom::BatchOperationPtr operation =
695 blink::mojom::BatchOperation::New();
696 operation->operation_type = blink::mojom::OperationType::kDelete;
697 operation->request = std::move(request);
698 operation->response = blink::mojom::FetchAPIResponse::New();
699
700 std::vector<blink::mojom::BatchOperationPtr> operations;
701 operations.emplace_back(std::move(operation));
702 base::RunLoop loop;
703 cache->BatchOperation(
704 std::move(operations), /* trace_id = */ 0,
705 base::BindOnce(&CacheStorageManagerTest::CacheDeleteCallback,
706 base::Unretained(this), base::Unretained(&loop)),
707 CacheStorageCache::BadMessageCallback());
708 loop.Run();
709
710 return callback_error_ == CacheStorageError::kSuccess;
711 }
712
CacheMatch(CacheStorageCache * cache,const GURL & url)713 bool CacheMatch(CacheStorageCache* cache, const GURL& url) {
714 auto request = blink::mojom::FetchAPIRequest::New();
715 request->url = url;
716 base::RunLoop loop;
717 cache->Match(
718 std::move(request), nullptr, CacheStorageSchedulerPriority::kNormal,
719 /* trace_id = */ 0,
720 base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback,
721 base::Unretained(this), base::Unretained(&loop)));
722 loop.Run();
723
724 return callback_error_ == CacheStorageError::kSuccess;
725 }
726
CacheStorageForOrigin(const url::Origin & origin)727 CacheStorageHandle CacheStorageForOrigin(const url::Origin& origin) {
728 return cache_manager_->OpenCacheStorage(origin,
729 CacheStorageOwner::kCacheAPI);
730 }
731
GetOriginUsage(const url::Origin & origin,CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)732 int64_t GetOriginUsage(
733 const url::Origin& origin,
734 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
735 base::RunLoop loop;
736 cache_manager_->GetOriginUsage(
737 origin, owner,
738 base::BindOnce(&CacheStorageManagerTest::UsageCallback,
739 base::Unretained(this), base::Unretained(&loop)));
740 loop.Run();
741 return callback_usage_;
742 }
743
UsageCallback(base::RunLoop * run_loop,int64_t usage)744 void UsageCallback(base::RunLoop* run_loop, int64_t usage) {
745 callback_usage_ = usage;
746 run_loop->Quit();
747 }
748
GetAllOriginsUsage(CacheStorageOwner owner=CacheStorageOwner::kCacheAPI)749 std::vector<StorageUsageInfo> GetAllOriginsUsage(
750 CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
751 base::RunLoop loop;
752 cache_manager_->GetAllOriginsUsage(
753 owner, base::BindLambdaForTesting(
754 [&](const std::vector<StorageUsageInfo>& usage) {
755 callback_all_origins_usage_ = usage;
756 loop.Quit();
757 }));
758 loop.Run();
759 return callback_all_origins_usage_;
760 }
761
GetSizeThenCloseAllCaches(const url::Origin & origin)762 int64_t GetSizeThenCloseAllCaches(const url::Origin& origin) {
763 DCHECK(ManagerType() == TestManager::kLegacy);
764 base::RunLoop loop;
765 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin);
766 LegacyCacheStorage::From(cache_storage)
767 ->GetSizeThenCloseAllCaches(
768 base::BindOnce(&CacheStorageManagerTest::UsageCallback,
769 base::Unretained(this), &loop));
770 loop.Run();
771 return callback_usage_;
772 }
773
Size(const url::Origin & origin)774 int64_t Size(const url::Origin& origin) {
775 DCHECK(ManagerType() == TestManager::kLegacy);
776 base::RunLoop loop;
777 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin);
778 LegacyCacheStorage::From(cache_storage)
779 ->Size(base::BindOnce(&CacheStorageManagerTest::UsageCallback,
780 base::Unretained(this), &loop));
781 loop.Run();
782 return callback_usage_;
783 }
784
GetQuotaOriginUsage(const url::Origin & origin)785 int64_t GetQuotaOriginUsage(const url::Origin& origin) {
786 int64_t usage(CacheStorage::kSizeUnknown);
787 base::RunLoop loop;
788 quota_manager_proxy_->GetUsageAndQuota(
789 base::ThreadTaskRunnerHandle::Get().get(), origin,
790 StorageType::kTemporary,
791 base::BindOnce(&CacheStorageManagerTest::DidGetQuotaOriginUsage,
792 base::Unretained(this), base::Unretained(&usage),
793 &loop));
794 loop.Run();
795 return usage;
796 }
797
DidGetQuotaOriginUsage(int64_t * out_usage,base::RunLoop * run_loop,blink::mojom::QuotaStatusCode status_code,int64_t usage,int64_t quota)798 void DidGetQuotaOriginUsage(int64_t* out_usage,
799 base::RunLoop* run_loop,
800 blink::mojom::QuotaStatusCode status_code,
801 int64_t usage,
802 int64_t quota) {
803 if (status_code == blink::mojom::QuotaStatusCode::kOk)
804 *out_usage = usage;
805 run_loop->Quit();
806 }
807
808 protected:
809 // Temporary directory must be allocated first so as to be destroyed last.
810 base::ScopedTempDir temp_dir_;
811
812 BrowserTaskEnvironment task_environment_;
813 TestBrowserContext browser_context_;
814 scoped_refptr<BlobStorageContextWrapper> blob_storage_context_;
815
816 scoped_refptr<storage::MockSpecialStoragePolicy> quota_policy_;
817 scoped_refptr<storage::MockQuotaManager> mock_quota_manager_;
818 scoped_refptr<MockCacheStorageQuotaManagerProxy> quota_manager_proxy_;
819 scoped_refptr<CacheStorageContextImpl::ObserverList> observers_;
820 scoped_refptr<CacheStorageManager> cache_manager_;
821
822 CacheStorageCacheHandle callback_cache_handle_;
823 int callback_bool_ = false;
824 CacheStorageError callback_error_ = CacheStorageError::kSuccess;
825 blink::mojom::FetchAPIResponsePtr callback_cache_handle_response_;
826 std::vector<std::string> cache_names_;
827
828 const url::Origin origin1_;
829 const url::Origin origin2_;
830
831 int64_t callback_usage_;
832 std::vector<StorageUsageInfo> callback_all_origins_usage_;
833
834 private:
835 DISALLOW_COPY_AND_ASSIGN(CacheStorageManagerTest);
836 };
837
838 class CacheStorageManagerMemoryOnlyTest : public CacheStorageManagerTest {
839 public:
MemoryOnly()840 bool MemoryOnly() override { return true; }
841 };
842
843 class CacheStorageManagerTestP : public CacheStorageManagerTest,
844 public testing::WithParamInterface<Param> {
845 public:
MemoryOnly()846 bool MemoryOnly() override {
847 return GetParam().storage_ == TestStorage::kMemory;
848 }
ManagerType()849 TestManager ManagerType() override { return GetParam().manager_; }
850 };
851
852 // Some tests must be run on the LegacyCacheStorageManager. This could
853 // be for a number of reasons:
854 // * The test needs to use internal APIs on the legacy manager.
855 // * The test is checking behavior that is only true for "real" manager's
856 // like that Open() will return the exact same c++ pointer for the
857 // underlying cache. This assumption is not truee for the cross-sequence
858 // wrapper.
859 class CacheStorageManagerLegacyOnlyTestP
860 : public CacheStorageManagerTest,
861 public testing::WithParamInterface<TestStorage> {
MemoryOnly()862 bool MemoryOnly() override { return GetParam() == TestStorage::kMemory; }
863 };
864
TEST_F(CacheStorageManagerTest,TestsRunOnIOThread)865 TEST_F(CacheStorageManagerTest, TestsRunOnIOThread) {
866 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
867 }
868
TEST_P(CacheStorageManagerTestP,OpenCache)869 TEST_P(CacheStorageManagerTestP, OpenCache) {
870 EXPECT_TRUE(Open(origin1_, "foo"));
871 }
872
TEST_P(CacheStorageManagerTestP,OpenTwoCaches)873 TEST_P(CacheStorageManagerTestP, OpenTwoCaches) {
874 EXPECT_TRUE(Open(origin1_, "foo"));
875 EXPECT_TRUE(Open(origin1_, "bar"));
876 }
877
TEST_P(CacheStorageManagerTestP,OpenSameCacheDifferentOwners)878 TEST_P(CacheStorageManagerTestP, OpenSameCacheDifferentOwners) {
879 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
880 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
881 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
882 EXPECT_NE(callback_cache_handle_.value(), cache_handle.value());
883 }
884
TEST_P(CacheStorageManagerTestP,CachePointersDiffer)885 TEST_P(CacheStorageManagerTestP, CachePointersDiffer) {
886 EXPECT_TRUE(Open(origin1_, "foo"));
887 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
888 EXPECT_TRUE(Open(origin1_, "bar"));
889 EXPECT_NE(callback_cache_handle_.value(), cache_handle.value());
890 }
891
TEST_P(CacheStorageManagerTestP,Open2CachesSameNameDiffOrigins)892 TEST_P(CacheStorageManagerTestP, Open2CachesSameNameDiffOrigins) {
893 EXPECT_TRUE(Open(origin1_, "foo"));
894 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
895 EXPECT_TRUE(Open(origin2_, "foo"));
896 EXPECT_NE(cache_handle.value(), callback_cache_handle_.value());
897 }
898
TEST_P(CacheStorageManagerLegacyOnlyTestP,OpenExistingCache)899 TEST_P(CacheStorageManagerLegacyOnlyTestP, OpenExistingCache) {
900 EXPECT_TRUE(Open(origin1_, "foo"));
901 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
902 EXPECT_TRUE(Open(origin1_, "foo"));
903 EXPECT_EQ(callback_cache_handle_.value(), cache_handle.value());
904 }
905
TEST_P(CacheStorageManagerTestP,HasCache)906 TEST_P(CacheStorageManagerTestP, HasCache) {
907 EXPECT_TRUE(Open(origin1_, "foo"));
908 EXPECT_TRUE(Has(origin1_, "foo"));
909 EXPECT_TRUE(callback_bool_);
910 }
911
TEST_P(CacheStorageManagerTestP,HasCacheDifferentOwners)912 TEST_P(CacheStorageManagerTestP, HasCacheDifferentOwners) {
913 EXPECT_TRUE(Open(origin1_, "public", CacheStorageOwner::kCacheAPI));
914 EXPECT_TRUE(Open(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
915
916 EXPECT_TRUE(Has(origin1_, "public", CacheStorageOwner::kCacheAPI));
917 EXPECT_TRUE(callback_bool_);
918 EXPECT_FALSE(Has(origin1_, "bgf", CacheStorageOwner::kCacheAPI));
919 EXPECT_FALSE(callback_bool_);
920
921 EXPECT_TRUE(Has(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
922 EXPECT_TRUE(callback_bool_);
923 EXPECT_FALSE(Has(origin1_, "public", CacheStorageOwner::kBackgroundFetch));
924 EXPECT_FALSE(callback_bool_);
925 }
926
TEST_P(CacheStorageManagerTestP,HasNonExistent)927 TEST_P(CacheStorageManagerTestP, HasNonExistent) {
928 EXPECT_FALSE(Has(origin1_, "foo"));
929 }
930
TEST_P(CacheStorageManagerTestP,DeleteCache)931 TEST_P(CacheStorageManagerTestP, DeleteCache) {
932 EXPECT_TRUE(Open(origin1_, "foo"));
933 EXPECT_TRUE(Delete(origin1_, "foo"));
934 EXPECT_FALSE(Has(origin1_, "foo"));
935 }
936
TEST_P(CacheStorageManagerTestP,DeleteTwice)937 TEST_P(CacheStorageManagerTestP, DeleteTwice) {
938 EXPECT_TRUE(Open(origin1_, "foo"));
939 EXPECT_TRUE(Delete(origin1_, "foo"));
940 EXPECT_FALSE(Delete(origin1_, "foo"));
941 EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
942 }
943
TEST_P(CacheStorageManagerTestP,DeleteCacheReducesOriginSize)944 TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) {
945 EXPECT_TRUE(Open(origin1_, "foo"));
946 EXPECT_TRUE(
947 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
948 // The quota manager gets updated after the put operation runs its callback so
949 // run the event loop.
950 base::RunLoop().RunUntilIdle();
951 int64_t put_delta = quota_manager_proxy_->last_notified_delta();
952 EXPECT_LT(0, put_delta);
953 EXPECT_TRUE(Delete(origin1_, "foo"));
954
955 // Drop the cache handle so that the cache can be erased from disk.
956 callback_cache_handle_ = CacheStorageCacheHandle();
957 base::RunLoop().RunUntilIdle();
958
959 EXPECT_EQ(-1 * quota_manager_proxy_->last_notified_delta(), put_delta);
960 }
961
TEST_P(CacheStorageManagerTestP,EmptyKeys)962 TEST_P(CacheStorageManagerTestP, EmptyKeys) {
963 EXPECT_EQ(0u, Keys(origin1_));
964 }
965
TEST_P(CacheStorageManagerTestP,SomeKeys)966 TEST_P(CacheStorageManagerTestP, SomeKeys) {
967 EXPECT_TRUE(Open(origin1_, "foo"));
968 EXPECT_TRUE(Open(origin1_, "bar"));
969 EXPECT_TRUE(Open(origin2_, "baz"));
970 EXPECT_EQ(2u, Keys(origin1_));
971 std::vector<std::string> expected_keys;
972 expected_keys.push_back("foo");
973 expected_keys.push_back("bar");
974 EXPECT_EQ(expected_keys, GetIndexNames());
975 EXPECT_EQ(1u, Keys(origin2_));
976 EXPECT_STREQ("baz", GetFirstIndexName().c_str());
977 }
978
TEST_P(CacheStorageManagerTestP,DeletedKeysGone)979 TEST_P(CacheStorageManagerTestP, DeletedKeysGone) {
980 EXPECT_TRUE(Open(origin1_, "foo"));
981 EXPECT_TRUE(Open(origin1_, "bar"));
982 EXPECT_TRUE(Open(origin2_, "baz"));
983 EXPECT_TRUE(Delete(origin1_, "bar"));
984 EXPECT_EQ(1u, Keys(origin1_));
985 EXPECT_STREQ("foo", GetFirstIndexName().c_str());
986 }
987
TEST_P(CacheStorageManagerTestP,StorageMatchEntryExists)988 TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) {
989 EXPECT_TRUE(Open(origin1_, "foo"));
990 EXPECT_TRUE(
991 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
992 EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
993 }
994
TEST_P(CacheStorageManagerTestP,StorageMatchNoEntry)995 TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) {
996 EXPECT_TRUE(Open(origin1_, "foo"));
997 EXPECT_TRUE(
998 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
999 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar")));
1000 EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
1001 }
1002
TEST_P(CacheStorageManagerTestP,StorageMatchNoCache)1003 TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) {
1004 EXPECT_TRUE(Open(origin1_, "foo"));
1005 EXPECT_TRUE(
1006 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1007 EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo")));
1008 EXPECT_EQ(CacheStorageError::kErrorCacheNameNotFound, callback_error_);
1009 }
1010
TEST_P(CacheStorageManagerTestP,StorageMatchAllEntryExists)1011 TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) {
1012 EXPECT_TRUE(Open(origin1_, "foo"));
1013 EXPECT_TRUE(
1014 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1015 EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
1016 }
1017
TEST_P(CacheStorageManagerTestP,StorageMatchAllNoEntry)1018 TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) {
1019 EXPECT_TRUE(Open(origin1_, "foo"));
1020 EXPECT_TRUE(
1021 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1022 EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/bar")));
1023 EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
1024 }
1025
TEST_P(CacheStorageManagerTestP,StorageMatchAllNoCaches)1026 TEST_P(CacheStorageManagerTestP, StorageMatchAllNoCaches) {
1027 EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
1028 EXPECT_EQ(CacheStorageError::kErrorNotFound, callback_error_);
1029 }
1030
TEST_P(CacheStorageManagerTestP,StorageMatchDifferentOwners)1031 TEST_P(CacheStorageManagerTestP, StorageMatchDifferentOwners) {
1032 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
1033 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
1034 GURL("http://example.com/public")));
1035 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
1036 EXPECT_TRUE(
1037 CachePut(callback_cache_handle_.value(), GURL("http://example.com/bgf")));
1038
1039 // Check the public cache.
1040 EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
1041 nullptr, CacheStorageOwner::kCacheAPI));
1042 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
1043 nullptr, CacheStorageOwner::kCacheAPI));
1044
1045 // Check the internal cache.
1046 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
1047 nullptr, CacheStorageOwner::kBackgroundFetch));
1048 EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
1049 nullptr, CacheStorageOwner::kBackgroundFetch));
1050 }
1051
TEST_F(CacheStorageManagerTest,StorageReuseCacheName)1052 TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
1053 // Deleting a cache and creating one with the same name and adding an entry
1054 // with the same URL should work. (see crbug.com/542668)
1055 const GURL kTestURL = GURL("http://example.com/foo");
1056 EXPECT_TRUE(Open(origin1_, "foo"));
1057 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL));
1058 EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kTestURL));
1059
1060 EXPECT_TRUE(Delete(origin1_, "foo"));
1061 // The cache is deleted but the handle to one of its entries is still
1062 // open. Creating a new cache in the same directory would fail on Windows.
1063 EXPECT_TRUE(Open(origin1_, "foo"));
1064 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL));
1065 }
1066
TEST_P(CacheStorageManagerTestP,DropRefAfterNewCacheWithSameNameCreated)1067 TEST_P(CacheStorageManagerTestP, DropRefAfterNewCacheWithSameNameCreated) {
1068 // Make sure that dropping the final cache handle to a doomed cache doesn't
1069 // affect newer caches with the same name. (see crbug.com/631467)
1070
1071 // 1. Create cache A and hang onto the handle
1072 const GURL kTestURL = GURL("http://example.com/foo");
1073 EXPECT_TRUE(Open(origin1_, "foo"));
1074 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1075
1076 // 2. Doom the cache
1077 EXPECT_TRUE(Delete(origin1_, "foo"));
1078
1079 // 3. Create cache B (with the same name)
1080 EXPECT_TRUE(Open(origin1_, "foo"));
1081
1082 // 4. Drop handle to A
1083 cache_handle = CacheStorageCacheHandle();
1084
1085 // 5. Verify that B still works
1086 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kTestURL));
1087 }
1088
TEST_P(CacheStorageManagerTestP,DeleteCorrectDirectory)1089 TEST_P(CacheStorageManagerTestP, DeleteCorrectDirectory) {
1090 // This test reproduces crbug.com/630036.
1091 // 1. Cache A with name "foo" is created
1092 const GURL kTestURL = GURL("http://example.com/foo");
1093 EXPECT_TRUE(Open(origin1_, "foo"));
1094 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1095
1096 // 2. Cache A is doomed, but js hangs onto the handle.
1097 EXPECT_TRUE(Delete(origin1_, "foo"));
1098
1099 // 3. Cache B with name "foo" is created
1100 EXPECT_TRUE(Open(origin1_, "foo"));
1101
1102 // 4. Cache B is doomed, and both handles are reset.
1103 EXPECT_TRUE(Delete(origin1_, "foo"));
1104 cache_handle = CacheStorageCacheHandle();
1105
1106 // Do some busy work on a different cache to move the cache pool threads
1107 // along and trigger the bug.
1108 EXPECT_TRUE(Open(origin1_, "bar"));
1109 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kTestURL));
1110 EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kTestURL));
1111 }
1112
TEST_P(CacheStorageManagerTestP,StorageMatchAllEntryExistsTwice)1113 TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) {
1114 EXPECT_TRUE(Open(origin1_, "foo"));
1115 // |request_1| and |request_2| has the same url.
1116 auto request_1 = blink::mojom::FetchAPIRequest::New();
1117 request_1->url = GURL("http://example.com/foo");
1118 auto request_2 = BackgroundFetchSettledFetch::CloneRequest(request_1);
1119 EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_.value(),
1120 std::move(request_1), 200));
1121 EXPECT_TRUE(Open(origin1_, "bar"));
1122 EXPECT_TRUE(CachePutWithStatusCode(callback_cache_handle_.value(),
1123 std::move(request_2), 201));
1124
1125 EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
1126
1127 // The caches need to be searched in order of creation, so verify that the
1128 // response came from the first cache.
1129 EXPECT_EQ(200, callback_cache_handle_response_->status_code);
1130 }
1131
TEST_P(CacheStorageManagerTestP,StorageMatchInOneOfMany)1132 TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) {
1133 EXPECT_TRUE(Open(origin1_, "foo"));
1134 EXPECT_TRUE(Open(origin1_, "bar"));
1135 EXPECT_TRUE(
1136 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1137 EXPECT_TRUE(Open(origin1_, "baz"));
1138
1139 EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
1140 }
1141
TEST_P(CacheStorageManagerLegacyOnlyTestP,Chinese)1142 TEST_P(CacheStorageManagerLegacyOnlyTestP, Chinese) {
1143 EXPECT_TRUE(Open(origin1_, "你好"));
1144 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1145 EXPECT_TRUE(Open(origin1_, "你好"));
1146 EXPECT_EQ(callback_cache_handle_.value(), cache_handle.value());
1147 EXPECT_EQ(1u, Keys(origin1_));
1148 EXPECT_STREQ("你好", GetFirstIndexName().c_str());
1149 }
1150
TEST_F(CacheStorageManagerTest,EmptyKey)1151 TEST_F(CacheStorageManagerTest, EmptyKey) {
1152 EXPECT_TRUE(Open(origin1_, ""));
1153 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1154 EXPECT_TRUE(Open(origin1_, ""));
1155 EXPECT_EQ(cache_handle.value(), callback_cache_handle_.value());
1156 EXPECT_EQ(1u, Keys(origin1_));
1157 EXPECT_STREQ("", GetFirstIndexName().c_str());
1158 EXPECT_TRUE(Has(origin1_, ""));
1159 EXPECT_TRUE(Delete(origin1_, ""));
1160 EXPECT_EQ(0u, Keys(origin1_));
1161 }
1162
TEST_F(CacheStorageManagerTest,DataPersists)1163 TEST_F(CacheStorageManagerTest, DataPersists) {
1164 EXPECT_TRUE(Open(origin1_, "foo"));
1165 EXPECT_TRUE(Open(origin1_, "bar"));
1166 EXPECT_TRUE(Open(origin1_, "baz"));
1167 EXPECT_TRUE(Open(origin2_, "raz"));
1168 EXPECT_TRUE(Delete(origin1_, "bar"));
1169 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1170 RecreateStorageManager();
1171 EXPECT_EQ(2u, Keys(origin1_));
1172 std::vector<std::string> expected_keys;
1173 expected_keys.push_back("foo");
1174 expected_keys.push_back("baz");
1175 EXPECT_EQ(expected_keys, GetIndexNames());
1176 }
1177
TEST_F(CacheStorageManagerMemoryOnlyTest,DataLostWhenMemoryOnly)1178 TEST_F(CacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
1179 EXPECT_TRUE(Open(origin1_, "foo"));
1180 EXPECT_TRUE(Open(origin2_, "baz"));
1181 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1182 RecreateStorageManager();
1183 EXPECT_EQ(0u, Keys(origin1_));
1184 }
1185
TEST_F(CacheStorageManagerTest,BadCacheName)1186 TEST_F(CacheStorageManagerTest, BadCacheName) {
1187 // Since the implementation writes cache names to disk, ensure that we don't
1188 // escape the directory.
1189 const std::string bad_name = "../../../../../../../../../../../../../../foo";
1190 EXPECT_TRUE(Open(origin1_, bad_name));
1191 EXPECT_EQ(1u, Keys(origin1_));
1192 EXPECT_STREQ(bad_name.c_str(), GetFirstIndexName().c_str());
1193 }
1194
TEST_F(CacheStorageManagerTest,BadOriginName)1195 TEST_F(CacheStorageManagerTest, BadOriginName) {
1196 // Since the implementation writes origin names to disk, ensure that we don't
1197 // escape the directory.
1198 url::Origin bad_origin(url::Origin::Create(
1199 GURL("http://../../../../../../../../../../../../../../foo")));
1200 EXPECT_TRUE(Open(bad_origin, "foo"));
1201 EXPECT_EQ(1u, Keys(bad_origin));
1202 EXPECT_STREQ("foo", GetFirstIndexName().c_str());
1203 }
1204
1205 // Dropping a reference to a cache should not immediately destroy it. These
1206 // warm cache objects are kept alive to optimize the next open.
TEST_F(CacheStorageManagerTest,DropReference)1207 TEST_F(CacheStorageManagerTest, DropReference) {
1208 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
1209
1210 EXPECT_TRUE(Open(origin1_, "foo"));
1211 base::WeakPtr<LegacyCacheStorageCache> cache =
1212 LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
1213 // Run a cache operation to ensure that the cache has finished initializing so
1214 // that when the handle is dropped it could possibly close immediately.
1215 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(),
1216 GURL("http://example.com/foo")));
1217
1218 callback_cache_handle_ = CacheStorageCacheHandle();
1219 EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning "
1220 "CacheStorage is still referenced";
1221
1222 cache_storage = CacheStorageHandle();
1223 EXPECT_FALSE(cache) << "unreferenced cache not destroyed after last "
1224 "CacheStorage reference removed";
1225 }
1226
1227 // Deleting a cache should remove any warmed caches that been kept alive
1228 // without a reference.
TEST_F(CacheStorageManagerTest,DropReferenceAndDelete)1229 TEST_F(CacheStorageManagerTest, DropReferenceAndDelete) {
1230 // Hold a reference to the CacheStorage to permit the warmed
1231 // CacheStorageCache to be kept alive.
1232 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
1233
1234 EXPECT_TRUE(Open(origin1_, "foo"));
1235 base::WeakPtr<LegacyCacheStorageCache> cache =
1236 LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
1237 // Run a cache operation to ensure that the cache has finished initializing so
1238 // that when the handle is dropped it could possibly close immediately.
1239 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(),
1240 GURL("http://example.com/foo")));
1241
1242 callback_cache_handle_ = CacheStorageCacheHandle();
1243 EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning "
1244 "CacheStorage is still referenced";
1245
1246 // Delete() should trigger its destruction, however.
1247 EXPECT_TRUE(Delete(origin1_, "foo"));
1248 base::RunLoop().RunUntilIdle();
1249
1250 EXPECT_FALSE(cache)
1251 << "deleted cache not destroyed after last reference removed";
1252 }
1253
1254 // Critical memory pressure should remove any warmed caches that been kept
1255 // alive without a reference.
TEST_F(CacheStorageManagerTest,DropReferenceAndMemoryPressure)1256 TEST_F(CacheStorageManagerTest, DropReferenceAndMemoryPressure) {
1257 // Hold a reference to the CacheStorage to permit the warmed
1258 // CacheStorageCache to be kept alive.
1259 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
1260
1261 EXPECT_TRUE(Open(origin1_, "foo"));
1262 base::WeakPtr<LegacyCacheStorageCache> cache =
1263 LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
1264 // Run a cache operation to ensure that the cache has finished initializing so
1265 // that when the handle is dropped it could possibly close immediately.
1266 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(),
1267 GURL("http://example.com/foo")));
1268
1269 callback_cache_handle_ = CacheStorageCacheHandle();
1270 EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning "
1271 "CacheStorage is still referenced";
1272
1273 // Moderate memory pressure should not destroy unreferenced cache objects
1274 // since reading data back in from disk can be expensive.
1275 base::MemoryPressureListener::NotifyMemoryPressure(
1276 base::MemoryPressureListener::MemoryPressureLevel::
1277 MEMORY_PRESSURE_LEVEL_MODERATE);
1278 base::RunLoop().RunUntilIdle();
1279 EXPECT_TRUE(cache);
1280
1281 // Critical memory pressure should destroy unreferenced cache objects.
1282 base::MemoryPressureListener::NotifyMemoryPressure(
1283 base::MemoryPressureListener::MemoryPressureLevel::
1284 MEMORY_PRESSURE_LEVEL_CRITICAL);
1285 base::RunLoop().RunUntilIdle();
1286
1287 EXPECT_FALSE(cache)
1288 << "unreferenced cache not destroyed on critical memory pressure";
1289 }
1290
TEST_F(CacheStorageManagerTest,DropReferenceDuringQuery)1291 TEST_F(CacheStorageManagerTest, DropReferenceDuringQuery) {
1292 // Setup the cache and execute an operation to make sure all initialization
1293 // is complete.
1294 EXPECT_TRUE(Open(origin1_, "foo"));
1295 base::WeakPtr<LegacyCacheStorageCache> cache =
1296 LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
1297 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(),
1298 GURL("http://example.com/foo")));
1299
1300 // Override the cache scheduler so that we can take an action below
1301 // after the query operation begins.
1302 base::RunLoop scheduler_loop;
1303 auto scheduler =
1304 std::make_unique<CallbackScheduler>(scheduler_loop.QuitClosure());
1305 cache->SetSchedulerForTesting(std::move(scheduler));
1306
1307 // Perform a MatchAll() operation to trigger a full query of the cache
1308 // that does not hit the fast path optimization.
1309 base::RunLoop match_loop;
1310 cache->MatchAll(
1311 nullptr, nullptr, /* trace_id = */ 0,
1312 base::BindOnce(&CacheStorageManagerTest::CacheMatchAllCallback,
1313 base::Unretained(this), base::Unretained(&match_loop)));
1314
1315 // Wait for the MatchAll operation to begin.
1316 scheduler_loop.Run();
1317
1318 // Clear the external cache handle.
1319 callback_cache_handle_ = CacheStorageCacheHandle();
1320
1321 // Wait for the MatchAll operation to complete as expected.
1322 match_loop.Run();
1323 EXPECT_EQ(CacheStorageError::kSuccess, callback_error_);
1324 }
1325 // A cache continues to work so long as there is a handle to it. Only after the
1326 // last cache handle is deleted can the cache be freed.
TEST_P(CacheStorageManagerTestP,CacheWorksAfterDelete)1327 TEST_P(CacheStorageManagerTestP, CacheWorksAfterDelete) {
1328 const GURL kFooURL("http://example.com/foo");
1329 const GURL kBarURL("http://example.com/bar");
1330 const GURL kBazURL("http://example.com/baz");
1331 EXPECT_TRUE(Open(origin1_, "foo"));
1332 CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_);
1333 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1334 EXPECT_TRUE(Delete(origin1_, "foo"));
1335
1336 // Verify that the existing cache handle still works.
1337 EXPECT_TRUE(CacheMatch(original_handle.value(), kFooURL));
1338 EXPECT_TRUE(CachePut(original_handle.value(), kBarURL));
1339 EXPECT_TRUE(CacheMatch(original_handle.value(), kBarURL));
1340
1341 // The cache shouldn't be visible to subsequent storage operations.
1342 EXPECT_EQ(0u, Keys(origin1_));
1343
1344 // Open a new cache with the same name, it should create a new cache, but not
1345 // interfere with the original cache.
1346 EXPECT_TRUE(Open(origin1_, "foo"));
1347 CacheStorageCacheHandle new_handle = std::move(callback_cache_handle_);
1348 EXPECT_TRUE(CachePut(new_handle.value(), kBazURL));
1349
1350 EXPECT_FALSE(CacheMatch(new_handle.value(), kFooURL));
1351 EXPECT_FALSE(CacheMatch(new_handle.value(), kBarURL));
1352 EXPECT_TRUE(CacheMatch(new_handle.value(), kBazURL));
1353
1354 EXPECT_TRUE(CacheMatch(original_handle.value(), kFooURL));
1355 EXPECT_TRUE(CacheMatch(original_handle.value(), kBarURL));
1356 EXPECT_FALSE(CacheMatch(original_handle.value(), kBazURL));
1357 }
1358
1359 // Deleted caches can still be modified, but all changes will eventually be
1360 // thrown away when all references are released.
TEST_F(CacheStorageManagerTest,DeletedCacheIgnoredInIndex)1361 TEST_F(CacheStorageManagerTest, DeletedCacheIgnoredInIndex) {
1362 const GURL kFooURL("http://example.com/foo");
1363 const GURL kBarURL("http://example.com/bar");
1364 const GURL kBazURL("http://example.com/baz");
1365 const std::string kCacheName = "foo";
1366
1367 EXPECT_TRUE(Open(origin1_, kCacheName));
1368 auto original_handle = std::move(callback_cache_handle_);
1369 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1370 EXPECT_TRUE(Delete(origin1_, kCacheName));
1371
1372 // Now a second cache using the same name, but with different data.
1373 EXPECT_TRUE(Open(origin1_, kCacheName));
1374 auto new_handle = std::move(callback_cache_handle_);
1375 EXPECT_TRUE(CachePut(new_handle.value(), kFooURL));
1376 EXPECT_TRUE(CachePut(new_handle.value(), kBarURL));
1377 EXPECT_TRUE(CachePut(new_handle.value(), kBazURL));
1378 auto new_cache_size = Size(origin1_);
1379
1380 // Now modify the first cache.
1381 EXPECT_TRUE(CachePut(original_handle.value(), kBarURL));
1382
1383 // Now deref both caches, and recreate the storage manager.
1384 original_handle = CacheStorageCacheHandle();
1385 new_handle = CacheStorageCacheHandle();
1386 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1387 DestroyStorageManager();
1388 CreateStorageManager();
1389
1390 EXPECT_TRUE(Open(origin1_, kCacheName));
1391 EXPECT_EQ(new_cache_size, Size(origin1_));
1392 }
1393
TEST_F(CacheStorageManagerTest,TestErrorInitializingCache)1394 TEST_F(CacheStorageManagerTest, TestErrorInitializingCache) {
1395 if (MemoryOnly())
1396 return;
1397 const GURL kFooURL("http://example.com/foo");
1398 const std::string kCacheName = "foo";
1399
1400 EXPECT_TRUE(Open(origin1_, kCacheName));
1401 auto original_handle = std::move(callback_cache_handle_);
1402 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1403 auto size_before_close = Size(origin1_);
1404 EXPECT_GT(size_before_close, 0);
1405
1406 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
1407 auto cache_handle =
1408 LegacyCacheStorage::From(cache_storage)->GetLoadedCache(kCacheName);
1409 base::FilePath cache_path =
1410 LegacyCacheStorageCache::From(cache_handle)->path();
1411 base::FilePath storage_path = cache_path.DirName();
1412 base::FilePath index_path = cache_path.AppendASCII("index");
1413 cache_handle = CacheStorageCacheHandle();
1414
1415 // Do our best to flush any pending cache_storage index file writes to disk
1416 // before proceeding. This does not guarantee the simple disk_cache index
1417 // is written, though.
1418 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1419 EXPECT_FALSE(FlushCacheStorageIndex(origin1_));
1420
1421 DestroyStorageManager();
1422
1423 // Truncate the SimpleCache index to force an error when next opened.
1424 ASSERT_FALSE(index_path.empty());
1425 ASSERT_TRUE(base::WriteFile(index_path, "hello"));
1426
1427 // The cache_storage index and simple disk_cache index files are written from
1428 // background threads. They may be written in unexpected orders due to timing
1429 // differences. We need to ensure the cache directory to have a newer time
1430 // stamp, though, in order for the Size() method to actually try calculating
1431 // the size from the corrupted simple disk_cache. Therefore we force the
1432 // cache_storage index to have a much older time to ensure that it is not used
1433 // in the following Size() call.
1434 base::FilePath cache_index_path =
1435 storage_path.AppendASCII(LegacyCacheStorage::kIndexFileName);
1436 base::Time t = base::Time::Now() + base::TimeDelta::FromHours(-1);
1437 EXPECT_TRUE(base::TouchFile(cache_index_path, t, t));
1438 EXPECT_FALSE(IsIndexFileCurrent(storage_path));
1439
1440 CreateStorageManager();
1441
1442 EXPECT_TRUE(Open(origin1_, kCacheName));
1443 EXPECT_EQ(0, Size(origin1_));
1444 }
1445
TEST_F(CacheStorageManagerTest,CacheSizeCorrectAfterReopen)1446 TEST_F(CacheStorageManagerTest, CacheSizeCorrectAfterReopen) {
1447 const GURL kFooURL("http://example.com/foo");
1448 const std::string kCacheName = "foo";
1449
1450 EXPECT_TRUE(Open(origin1_, kCacheName));
1451 auto original_handle = std::move(callback_cache_handle_);
1452 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1453 auto size_before_close = Size(origin1_);
1454 EXPECT_GT(size_before_close, 0);
1455
1456 DestroyStorageManager();
1457 CreateStorageManager();
1458
1459 EXPECT_TRUE(Open(origin1_, kCacheName));
1460 EXPECT_EQ(size_before_close, Size(origin1_));
1461 }
1462
TEST_F(CacheStorageManagerTest,CacheSizePaddedAfterReopen)1463 TEST_F(CacheStorageManagerTest, CacheSizePaddedAfterReopen) {
1464 const GURL kFooURL = origin1_.GetURL().Resolve("foo");
1465 const std::string kCacheName = "foo";
1466
1467 int64_t put_delta = quota_manager_proxy_->last_notified_delta();
1468 EXPECT_EQ(0, put_delta);
1469 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
1470
1471 EXPECT_TRUE(Open(origin1_, kCacheName));
1472 CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_);
1473
1474 base::RunLoop().RunUntilIdle();
1475 put_delta += quota_manager_proxy_->last_notified_delta();
1476 EXPECT_EQ(0, put_delta);
1477 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
1478
1479 EXPECT_TRUE(
1480 CachePut(original_handle.value(), kFooURL, FetchResponseType::kOpaque));
1481 int64_t cache_size_before_close = Size(origin1_);
1482 base::FilePath storage_dir =
1483 LegacyCacheStorageCache::From(original_handle)->path().DirName();
1484 original_handle = CacheStorageCacheHandle();
1485 EXPECT_GT(cache_size_before_close, 0);
1486
1487 base::RunLoop().RunUntilIdle();
1488 EXPECT_EQ(cache_size_before_close, GetQuotaOriginUsage(origin1_));
1489
1490 base::RunLoop().RunUntilIdle();
1491 put_delta = quota_manager_proxy_->last_notified_delta();
1492 EXPECT_GT(put_delta, 0);
1493 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
1494
1495 EXPECT_EQ(GetQuotaOriginUsage(origin1_), put_delta);
1496
1497 // Close the caches and cache manager.
1498 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1499 DestroyStorageManager();
1500
1501 // Create a new CacheStorageManager that hasn't yet loaded the origin.
1502 CreateStorageManager();
1503 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1504 RecreateStorageManager();
1505 EXPECT_TRUE(Open(origin1_, kCacheName));
1506
1507 base::RunLoop().RunUntilIdle();
1508 put_delta = quota_manager_proxy_->last_notified_delta();
1509 EXPECT_EQ(0, put_delta);
1510 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
1511
1512 EXPECT_EQ(cache_size_before_close, Size(origin1_));
1513 }
1514
TEST_F(CacheStorageManagerTest,QuotaCorrectAfterReopen)1515 TEST_F(CacheStorageManagerTest, QuotaCorrectAfterReopen) {
1516 const std::string kCacheName = "foo";
1517
1518 // Choose a response type that will not be padded so that the expected
1519 // cache size can be calculated.
1520 const FetchResponseType response_type = FetchResponseType::kCors;
1521
1522 // Create a new cache.
1523 int64_t cache_size;
1524 {
1525 EXPECT_TRUE(Open(origin1_, kCacheName));
1526 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1527 base::RunLoop().RunUntilIdle();
1528
1529 const GURL kFooURL = origin1_.GetURL().Resolve("foo");
1530 EXPECT_TRUE(CachePut(cache_handle.value(), kFooURL, response_type));
1531 cache_size = Size(origin1_);
1532
1533 EXPECT_EQ(cache_size, GetQuotaOriginUsage(origin1_));
1534 }
1535
1536 // Wait for the dereferenced cache to be closed.
1537 base::RunLoop().RunUntilIdle();
1538
1539 // Now reopen the cache.
1540 EXPECT_TRUE(Open(origin1_, kCacheName));
1541 CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
1542 base::RunLoop().RunUntilIdle();
1543 EXPECT_EQ(cache_size, GetQuotaOriginUsage(origin1_));
1544
1545 // And write a second equally sized value and verify size is doubled.
1546 const GURL kBarURL = origin1_.GetURL().Resolve("bar");
1547 EXPECT_TRUE(CachePut(cache_handle.value(), kBarURL, response_type));
1548
1549 EXPECT_EQ(2 * cache_size, GetQuotaOriginUsage(origin1_));
1550 }
1551
TEST_F(CacheStorageManagerTest,PersistedCacheKeyUsed)1552 TEST_F(CacheStorageManagerTest, PersistedCacheKeyUsed) {
1553 const GURL kFooURL = origin1_.GetURL().Resolve("foo");
1554 const std::string kCacheName = "foo";
1555
1556 EXPECT_TRUE(Open(origin1_, kCacheName));
1557 CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_);
1558
1559 EXPECT_TRUE(
1560 CachePut(original_handle.value(), kFooURL, FetchResponseType::kOpaque));
1561
1562 int64_t cache_size_after_put = Size(origin1_);
1563 EXPECT_LT(0, cache_size_after_put);
1564
1565 // Close the caches and cache manager.
1566 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1567 DestroyStorageManager();
1568
1569 // ResetPaddingKeyForTesting isn't thread safe so
1570 base::RunLoop().RunUntilIdle();
1571 storage::ResetPaddingKeyForTesting();
1572
1573 // Create a new CacheStorageManager that hasn't yet loaded the origin.
1574 CreateStorageManager();
1575 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1576 RecreateStorageManager();
1577
1578 // Reopening the origin/cache creates a new CacheStorage instance with a new
1579 // random key.
1580 EXPECT_TRUE(Open(origin1_, kCacheName));
1581
1582 // Size (before any change) should be the same as before it was closed.
1583 EXPECT_EQ(cache_size_after_put, Size(origin1_));
1584
1585 // Delete the value. If the new padding key was used to deduct the padded size
1586 // then after deletion we would expect to see a non-zero cache size.
1587 EXPECT_TRUE(Delete(origin1_, "foo"));
1588 EXPECT_EQ(0, Size(origin1_));
1589
1590 // Now put the exact same resource back into the cache. This time we expect to
1591 // see a different size as the padding is calculated with a different key.
1592 CacheStorageCacheHandle new_handle = std::move(callback_cache_handle_);
1593 EXPECT_TRUE(
1594 CachePut(new_handle.value(), kFooURL, FetchResponseType::kOpaque));
1595
1596 EXPECT_NE(cache_size_after_put, Size(origin1_));
1597 }
1598
1599 // With a memory cache the cache can't be freed from memory until the client
1600 // calls delete.
TEST_F(CacheStorageManagerMemoryOnlyTest,MemoryLosesReferenceOnlyAfterDelete)1601 TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryLosesReferenceOnlyAfterDelete) {
1602 EXPECT_TRUE(Open(origin1_, "foo"));
1603 base::WeakPtr<LegacyCacheStorageCache> cache =
1604 LegacyCacheStorageCache::From(callback_cache_handle_)->AsWeakPtr();
1605 callback_cache_handle_ = CacheStorageCacheHandle();
1606 EXPECT_TRUE(cache);
1607 EXPECT_TRUE(Delete(origin1_, "foo"));
1608 base::RunLoop().RunUntilIdle();
1609 EXPECT_FALSE(cache);
1610 }
1611
TEST_P(CacheStorageManagerTestP,DeleteBeforeRelease)1612 TEST_P(CacheStorageManagerTestP, DeleteBeforeRelease) {
1613 EXPECT_TRUE(Open(origin1_, "foo"));
1614 EXPECT_TRUE(Delete(origin1_, "foo"));
1615 EXPECT_TRUE(callback_cache_handle_.value());
1616 }
1617
TEST_P(CacheStorageManagerLegacyOnlyTestP,OpenRunsSerially)1618 TEST_P(CacheStorageManagerLegacyOnlyTestP, OpenRunsSerially) {
1619 EXPECT_FALSE(Delete(origin1_, "tmp")); // Init storage.
1620 CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_);
1621 auto* impl = LegacyCacheStorage::From(cache_storage);
1622 auto id = impl->StartAsyncOperationForTesting();
1623
1624 base::RunLoop open_loop;
1625 cache_storage.value()->OpenCache(
1626 "foo", /* trace_id = */ 0,
1627 base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback,
1628 base::Unretained(this), base::Unretained(&open_loop)));
1629
1630 base::RunLoop().RunUntilIdle();
1631 EXPECT_FALSE(callback_cache_handle_.value());
1632
1633 impl->CompleteAsyncOperationForTesting(id);
1634 open_loop.Run();
1635 EXPECT_TRUE(callback_cache_handle_.value());
1636 }
1637
TEST_P(CacheStorageManagerTestP,GetOriginUsage)1638 TEST_P(CacheStorageManagerTestP, GetOriginUsage) {
1639 EXPECT_EQ(0, GetOriginUsage(origin1_));
1640 EXPECT_TRUE(Open(origin1_, "foo"));
1641 EXPECT_EQ(0, GetOriginUsage(origin1_));
1642 EXPECT_TRUE(
1643 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1644 int64_t foo_size = GetOriginUsage(origin1_);
1645 EXPECT_LT(0, GetOriginUsage(origin1_));
1646 EXPECT_EQ(0, GetOriginUsage(origin2_));
1647
1648 // Add the same entry into a second cache, the size should double.
1649 EXPECT_TRUE(Open(origin1_, "bar"));
1650 EXPECT_TRUE(
1651 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1652 EXPECT_EQ(2 * foo_size, GetOriginUsage(origin1_));
1653 }
1654
TEST_P(CacheStorageManagerTestP,GetAllOriginsUsage)1655 TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
1656 EXPECT_EQ(0ULL, GetAllOriginsUsage().size());
1657 // Put one entry in a cache on origin 1.
1658 EXPECT_TRUE(Open(origin1_, "foo"));
1659 EXPECT_TRUE(
1660 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1661
1662 // Put two entries (of identical size) in a cache on origin 2.
1663 EXPECT_TRUE(Open(origin2_, "foo"));
1664 EXPECT_TRUE(
1665 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1666 EXPECT_TRUE(
1667 CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar")));
1668
1669 std::vector<StorageUsageInfo> usage = GetAllOriginsUsage();
1670 EXPECT_EQ(2ULL, usage.size());
1671
1672 int origin1_index = usage[0].origin == origin1_ ? 0 : 1;
1673 int origin2_index = usage[1].origin == origin2_ ? 1 : 0;
1674 EXPECT_NE(origin1_index, origin2_index);
1675
1676 int64_t origin1_size = usage[origin1_index].total_size_bytes;
1677 int64_t origin2_size = usage[origin2_index].total_size_bytes;
1678 EXPECT_EQ(2 * origin1_size, origin2_size);
1679
1680 if (MemoryOnly()) {
1681 EXPECT_TRUE(usage[origin1_index].last_modified.is_null());
1682 EXPECT_TRUE(usage[origin2_index].last_modified.is_null());
1683 } else {
1684 EXPECT_FALSE(usage[origin1_index].last_modified.is_null());
1685 EXPECT_FALSE(usage[origin2_index].last_modified.is_null());
1686 }
1687 }
1688
TEST_P(CacheStorageManagerTestP,GetAllOriginsUsageDifferentOwners)1689 TEST_P(CacheStorageManagerTestP, GetAllOriginsUsageDifferentOwners) {
1690 EXPECT_EQ(0ULL, GetAllOriginsUsage(CacheStorageOwner::kCacheAPI).size());
1691 EXPECT_EQ(0ULL,
1692 GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch).size());
1693
1694 // Put one entry in a cache of owner 1.
1695 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
1696 EXPECT_TRUE(
1697 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1698
1699 // Put two entries (of identical size) in two origins in a cache of owner 2.
1700 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
1701 EXPECT_TRUE(
1702 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1703 EXPECT_TRUE(Open(origin2_, "foo", CacheStorageOwner::kBackgroundFetch));
1704 EXPECT_TRUE(
1705 CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar")));
1706
1707 std::vector<StorageUsageInfo> usage_cache =
1708 GetAllOriginsUsage(CacheStorageOwner::kCacheAPI);
1709 EXPECT_EQ(1ULL, usage_cache.size());
1710 std::vector<StorageUsageInfo> usage_bgf =
1711 GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch);
1712 EXPECT_EQ(2ULL, usage_bgf.size());
1713
1714 int origin1_index = usage_bgf[0].origin == origin1_ ? 0 : 1;
1715 int origin2_index = usage_bgf[1].origin == origin2_ ? 1 : 0;
1716 EXPECT_NE(origin1_index, origin2_index);
1717
1718 EXPECT_EQ(usage_cache[0].origin, origin1_);
1719 EXPECT_EQ(usage_bgf[origin1_index].origin, origin1_);
1720 EXPECT_EQ(usage_bgf[origin2_index].origin, origin2_);
1721
1722 EXPECT_EQ(usage_cache[0].total_size_bytes,
1723 usage_bgf[origin1_index].total_size_bytes);
1724
1725 if (MemoryOnly()) {
1726 EXPECT_TRUE(usage_cache[0].last_modified.is_null());
1727 EXPECT_TRUE(usage_bgf[origin1_index].last_modified.is_null());
1728 EXPECT_TRUE(usage_bgf[origin2_index].last_modified.is_null());
1729 } else {
1730 EXPECT_FALSE(usage_cache[0].last_modified.is_null());
1731 EXPECT_FALSE(usage_bgf[origin1_index].last_modified.is_null());
1732 EXPECT_FALSE(usage_bgf[origin2_index].last_modified.is_null());
1733 }
1734 }
1735
1736 // TODO(crbug.com/760687): Flaky on Fuchsia.
1737 #if defined(OS_FUCHSIA)
1738 #define MAYBE_GetAllOriginsUsageWithOldIndex DISABLED_GetAllOriginsUsageWithOldIndex
1739 #else
1740 #define MAYBE_GetAllOriginsUsageWithOldIndex GetAllOriginsUsageWithOldIndex
1741 #endif
TEST_F(CacheStorageManagerTest,MAYBE_GetAllOriginsUsageWithOldIndex)1742 TEST_F(CacheStorageManagerTest, MAYBE_GetAllOriginsUsageWithOldIndex) {
1743 // Write a single value (V1) to the cache.
1744 const GURL kFooURL = origin1_.GetURL().Resolve("foo");
1745 const std::string kCacheName = "foo";
1746 EXPECT_TRUE(Open(origin1_, kCacheName));
1747 CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_);
1748
1749 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1750 int64_t cache_size_v1 = Size(origin1_);
1751 base::FilePath storage_dir =
1752 LegacyCacheStorageCache::From(original_handle)->path().DirName();
1753 original_handle = CacheStorageCacheHandle();
1754 EXPECT_GE(cache_size_v1, 0);
1755
1756 // Close the caches and cache manager.
1757 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1758 DestroyStorageManager();
1759
1760 // Save a copy of the V1 index.
1761 EXPECT_TRUE(IsIndexFileCurrent(storage_dir));
1762 base::FilePath index_path = storage_dir.AppendASCII("index.txt");
1763 EXPECT_TRUE(base::PathExists(index_path));
1764 base::FilePath backup_index_path = storage_dir.AppendASCII("index.txt.bak");
1765 EXPECT_TRUE(base::CopyFile(index_path, backup_index_path));
1766
1767 // Create a new CacheStorageManager that hasn't yet loaded the origin.
1768 CreateStorageManager();
1769 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1770 RecreateStorageManager();
1771
1772 // Create a second value (V2) in the cache.
1773 EXPECT_TRUE(Open(origin1_, kCacheName));
1774 original_handle = std::move(callback_cache_handle_);
1775 const GURL kBarURL = origin1_.GetURL().Resolve("bar");
1776 EXPECT_TRUE(CachePut(original_handle.value(), kBarURL));
1777 original_handle = CacheStorageCacheHandle();
1778
1779 // Capture the size before the index has necessarily flushed to disk.
1780 std::vector<StorageUsageInfo> usage = GetAllOriginsUsage();
1781 ASSERT_EQ(1ULL, usage.size());
1782 int64_t usage_before_close = usage[0].total_size_bytes;
1783 EXPECT_GT(usage_before_close, 0);
1784
1785 // Flush the index to ensure we can read it correctly from the index file.
1786 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1787
1788 // Close the caches and cache manager.
1789 DestroyStorageManager();
1790
1791 CreateStorageManager();
1792 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1793 RecreateStorageManager();
1794
1795 // Read the size from the index file.
1796 CreateStorageManager();
1797 usage = GetAllOriginsUsage();
1798 ASSERT_EQ(1ULL, usage.size());
1799 EXPECT_EQ(usage_before_close, usage[0].total_size_bytes);
1800
1801 DestroyStorageManager();
1802
1803 // Restore the index to the V1 state. Make the access/mod times of index file
1804 // older than the other directories in the store to trigger size
1805 // recalculation.
1806 EXPECT_TRUE(base::CopyFile(backup_index_path, index_path));
1807 base::Time t = base::Time::Now() - base::TimeDelta::FromHours(1);
1808 EXPECT_TRUE(base::TouchFile(index_path, t, t));
1809 EXPECT_FALSE(IsIndexFileCurrent(storage_dir));
1810
1811 // Read the size with the stale index file forcing a recalculation.
1812 CreateStorageManager();
1813 usage = GetAllOriginsUsage();
1814 ASSERT_EQ(1ULL, usage.size());
1815
1816 EXPECT_EQ(usage_before_close, usage[0].total_size_bytes);
1817
1818 EXPECT_FALSE(usage[0].last_modified.is_null());
1819 }
1820
1821 // TODO(crbug.com/760687): Flaky on Fuchsia.
1822 #if defined(OS_FUCHSIA)
1823 #define MAYBE_GetOriginSizeWithOldIndex DISABLED_GetOriginSizeWithOldIndex
1824 #else
1825 #define MAYBE_GetOriginSizeWithOldIndex GetOriginSizeWithOldIndex
1826 #endif
TEST_F(CacheStorageManagerTest,MAYBE_GetOriginSizeWithOldIndex)1827 TEST_F(CacheStorageManagerTest, MAYBE_GetOriginSizeWithOldIndex) {
1828 // Write a single value (V1) to the cache.
1829 const GURL kFooURL = origin1_.GetURL().Resolve("foo");
1830 const std::string kCacheName = "foo";
1831 EXPECT_TRUE(Open(origin1_, kCacheName));
1832 CacheStorageCacheHandle original_handle = std::move(callback_cache_handle_);
1833
1834 EXPECT_TRUE(CachePut(original_handle.value(), kFooURL));
1835 int64_t cache_size_v1 = Size(origin1_);
1836 base::FilePath storage_dir =
1837 LegacyCacheStorageCache::From(original_handle)->path().DirName();
1838 original_handle = CacheStorageCacheHandle();
1839 EXPECT_GE(cache_size_v1, 0);
1840
1841 // Close the caches and cache manager.
1842 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
1843 DestroyStorageManager();
1844
1845 // Save a copy of the V1 index.
1846 EXPECT_TRUE(IsIndexFileCurrent(storage_dir));
1847 base::FilePath index_path = storage_dir.AppendASCII("index.txt");
1848 EXPECT_TRUE(base::PathExists(index_path));
1849 base::FilePath backup_index_path = storage_dir.AppendASCII("index.txt.bak");
1850 EXPECT_TRUE(base::CopyFile(index_path, backup_index_path));
1851
1852 // Create a new CacheStorageManager that hasn't yet loaded the origin.
1853 CreateStorageManager();
1854 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1855 RecreateStorageManager();
1856
1857 // Reopen the cache and write a second value (V2).
1858 EXPECT_TRUE(Open(origin1_, kCacheName));
1859 original_handle = std::move(callback_cache_handle_);
1860 const GURL kBarURL = origin1_.GetURL().Resolve("bar");
1861 EXPECT_TRUE(CachePut(original_handle.value(), kBarURL));
1862 original_handle = CacheStorageCacheHandle();
1863 int64_t cache_size_v2 = Size(origin1_);
1864 EXPECT_GE(cache_size_v2, 0);
1865
1866 // Close the caches and cache manager.
1867 DestroyStorageManager();
1868
1869 // Restore the index to the V1 state.
1870 EXPECT_TRUE(base::CopyFile(backup_index_path, index_path));
1871
1872 // Make the access/mod times of index file older than the other files in the
1873 // cache to trigger size recalculation.
1874 base::Time t = base::Time::Now() - base::TimeDelta::FromHours(1);
1875 EXPECT_TRUE(base::TouchFile(index_path, t, t));
1876 EXPECT_FALSE(IsIndexFileCurrent(storage_dir));
1877
1878 // Reopen the cache and ensure the size is correct for the V2 value.
1879 CreateStorageManager();
1880 EXPECT_TRUE(Open(origin1_, kCacheName));
1881 EXPECT_EQ(cache_size_v2, Size(origin1_));
1882 }
1883
TEST_P(CacheStorageManagerLegacyOnlyTestP,GetSizeThenCloseAllCaches)1884 TEST_P(CacheStorageManagerLegacyOnlyTestP, GetSizeThenCloseAllCaches) {
1885 EXPECT_TRUE(Open(origin1_, "foo"));
1886 EXPECT_TRUE(
1887 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1888 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
1889 GURL("http://example.com/foo2")));
1890 EXPECT_TRUE(Open(origin1_, "bar"));
1891 EXPECT_TRUE(
1892 CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar")));
1893
1894 int64_t origin_size = GetOriginUsage(origin1_);
1895 EXPECT_LT(0, origin_size);
1896
1897 EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
1898 EXPECT_FALSE(
1899 CachePut(callback_cache_handle_.value(), GURL("http://example.com/baz")));
1900 }
1901
TEST_P(CacheStorageManagerLegacyOnlyTestP,GetSizeThenCloseAllCachesTwoOwners)1902 TEST_P(CacheStorageManagerLegacyOnlyTestP, GetSizeThenCloseAllCachesTwoOwners) {
1903 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
1904 CacheStorageCacheHandle public_handle = std::move(callback_cache_handle_);
1905 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
1906 CacheStorageCacheHandle bgf_handle = std::move(callback_cache_handle_);
1907
1908 EXPECT_TRUE(
1909 CachePut(public_handle.value(), GURL("http://example.com/public")));
1910 EXPECT_TRUE(CachePut(bgf_handle.value(), GURL("http://example.com/bgf")));
1911
1912 int64_t origin_size = GetOriginUsage(origin1_);
1913 EXPECT_LT(0, origin_size);
1914
1915 EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
1916 EXPECT_FALSE(CachePut(public_handle.value(), GURL("http://example.com/baz")));
1917 }
1918
TEST_P(CacheStorageManagerLegacyOnlyTestP,GetSizeThenCloseAllCachesAfterDelete)1919 TEST_P(CacheStorageManagerLegacyOnlyTestP,
1920 GetSizeThenCloseAllCachesAfterDelete) {
1921 // Tests that doomed caches are also deleted by GetSizeThenCloseAllCaches.
1922 EXPECT_TRUE(Open(origin1_, "foo"));
1923 EXPECT_TRUE(
1924 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1925
1926 int64_t size_after_put = GetOriginUsage(origin1_);
1927 EXPECT_LT(0, size_after_put);
1928
1929 // Keep a handle to a (soon-to-be deleted cache).
1930 auto saved_cache_handle = callback_cache_handle_.Clone();
1931
1932 // Delete will only doom the cache because there is still at least one handle
1933 // referencing an open cache.
1934 EXPECT_TRUE(Delete(origin1_, "foo"));
1935
1936 // GetSizeThenCloseAllCaches should close the cache (which is then deleted)
1937 // even though there is still an open handle.
1938 EXPECT_EQ(size_after_put, GetSizeThenCloseAllCaches(origin1_));
1939 EXPECT_EQ(0, GetOriginUsage(origin1_));
1940 }
1941
TEST_F(CacheStorageManagerTest,DeleteUnreferencedCacheDirectories)1942 TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
1943 // Create a referenced cache.
1944 EXPECT_TRUE(Open(origin1_, "foo"));
1945 EXPECT_TRUE(
1946 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
1947
1948 // Create an unreferenced directory next to the referenced one.
1949 auto* legacy_manager =
1950 static_cast<LegacyCacheStorageManager*>(cache_manager_.get());
1951 base::FilePath origin_path = LegacyCacheStorageManager::ConstructOriginPath(
1952 legacy_manager->root_path(), origin1_, CacheStorageOwner::kCacheAPI);
1953 base::FilePath unreferenced_path = origin_path.AppendASCII("bar");
1954 EXPECT_TRUE(CreateDirectory(unreferenced_path));
1955 EXPECT_TRUE(base::DirectoryExists(unreferenced_path));
1956
1957 // Create a new StorageManager so that the next time the cache is opened
1958 // the unreferenced directory can be deleted.
1959 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
1960 RecreateStorageManager();
1961
1962 // Verify that the referenced cache still works.
1963 EXPECT_TRUE(Open(origin1_, "foo"));
1964 EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(),
1965 GURL("http://example.com/foo")));
1966
1967 // Verify that the unreferenced cache is gone.
1968 EXPECT_FALSE(base::DirectoryExists(unreferenced_path));
1969 }
1970
TEST_P(CacheStorageManagerTestP,OpenCacheStorageAccessed)1971 TEST_P(CacheStorageManagerTestP, OpenCacheStorageAccessed) {
1972 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
1973 EXPECT_TRUE(Open(origin1_, "foo"));
1974 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
1975 }
1976
TEST_P(CacheStorageManagerTestP,HasStorageAccessed)1977 TEST_P(CacheStorageManagerTestP, HasStorageAccessed) {
1978 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
1979 EXPECT_FALSE(Has(origin1_, "foo"));
1980 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
1981 }
1982
TEST_P(CacheStorageManagerTestP,DeleteStorageAccessed)1983 TEST_P(CacheStorageManagerTestP, DeleteStorageAccessed) {
1984 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
1985 EXPECT_FALSE(Delete(origin1_, "foo"));
1986 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
1987 }
1988
TEST_P(CacheStorageManagerTestP,KeysStorageAccessed)1989 TEST_P(CacheStorageManagerTestP, KeysStorageAccessed) {
1990 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
1991 EXPECT_EQ(0u, Keys(origin1_));
1992 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
1993 }
1994
TEST_P(CacheStorageManagerTestP,MatchCacheStorageAccessed)1995 TEST_P(CacheStorageManagerTestP, MatchCacheStorageAccessed) {
1996 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
1997 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
1998 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
1999 }
2000
TEST_P(CacheStorageManagerTestP,MatchAllCachesStorageAccessed)2001 TEST_P(CacheStorageManagerTestP, MatchAllCachesStorageAccessed) {
2002 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
2003 EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
2004 EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
2005 }
2006
TEST_P(CacheStorageManagerLegacyOnlyTestP,SizeStorageAccessed)2007 TEST_P(CacheStorageManagerLegacyOnlyTestP, SizeStorageAccessed) {
2008 EXPECT_EQ(0, Size(origin1_));
2009 // Size is not part of the web API and should not notify the quota manager of
2010 // an access.
2011 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
2012 }
2013
TEST_P(CacheStorageManagerLegacyOnlyTestP,SizeThenCloseStorageAccessed)2014 TEST_P(CacheStorageManagerLegacyOnlyTestP, SizeThenCloseStorageAccessed) {
2015 EXPECT_EQ(0, GetSizeThenCloseAllCaches(origin1_));
2016 // GetSizeThenCloseAllCaches is not part of the web API and should not notify
2017 // the quota manager of an access.
2018 EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
2019 }
2020
TEST_P(CacheStorageManagerTestP,NotifyCacheListChanged_Created)2021 TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Created) {
2022 TestCacheStorageObserver observer;
2023 observers_->AddObserver(&observer);
2024
2025 EXPECT_EQ(0, observer.notify_list_changed_count);
2026 EXPECT_TRUE(Open(origin1_, "foo"));
2027 observer.Wait();
2028 EXPECT_EQ(1, observer.notify_list_changed_count);
2029 EXPECT_TRUE(
2030 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2031 observer.Wait();
2032 EXPECT_EQ(1, observer.notify_list_changed_count);
2033 }
2034
TEST_P(CacheStorageManagerTestP,NotifyCacheListChanged_Deleted)2035 TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_Deleted) {
2036 TestCacheStorageObserver observer;
2037 observers_->AddObserver(&observer);
2038
2039 EXPECT_EQ(0, observer.notify_list_changed_count);
2040 EXPECT_FALSE(Delete(origin1_, "foo"));
2041 // Give any unexpected observer tasks a chance to run.
2042 base::RunLoop().RunUntilIdle();
2043 EXPECT_EQ(0, observer.notify_list_changed_count);
2044 EXPECT_TRUE(Open(origin1_, "foo"));
2045 observer.Wait();
2046 EXPECT_EQ(1, observer.notify_list_changed_count);
2047 EXPECT_TRUE(Delete(origin1_, "foo"));
2048 observer.Wait();
2049 EXPECT_EQ(2, observer.notify_list_changed_count);
2050 }
2051
TEST_P(CacheStorageManagerTestP,NotifyCacheListChanged_DeletedThenCreated)2052 TEST_P(CacheStorageManagerTestP, NotifyCacheListChanged_DeletedThenCreated) {
2053 TestCacheStorageObserver observer;
2054 observers_->AddObserver(&observer);
2055
2056 EXPECT_EQ(0, observer.notify_list_changed_count);
2057 EXPECT_TRUE(Open(origin1_, "foo"));
2058 observer.Wait();
2059 EXPECT_EQ(1, observer.notify_list_changed_count);
2060 EXPECT_TRUE(Delete(origin1_, "foo"));
2061 observer.Wait();
2062 EXPECT_EQ(2, observer.notify_list_changed_count);
2063 EXPECT_TRUE(Open(origin2_, "foo2"));
2064 observer.Wait();
2065 EXPECT_EQ(3, observer.notify_list_changed_count);
2066 }
2067
TEST_P(CacheStorageManagerTestP,NotifyCacheContentChanged_PutEntry)2068 TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_PutEntry) {
2069 TestCacheStorageObserver observer;
2070 observers_->AddObserver(&observer);
2071
2072 EXPECT_EQ(0, observer.notify_content_changed_count);
2073 EXPECT_TRUE(Open(origin1_, "foo"));
2074 observer.Wait();
2075 EXPECT_EQ(0, observer.notify_content_changed_count);
2076 EXPECT_TRUE(
2077 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2078 observer.Wait();
2079 EXPECT_EQ(1, observer.notify_content_changed_count);
2080 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
2081 GURL("http://example.com/foo1")));
2082 observer.Wait();
2083 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
2084 GURL("http://example.com/foo2")));
2085 observer.Wait();
2086 EXPECT_EQ(3, observer.notify_content_changed_count);
2087 }
2088
TEST_P(CacheStorageManagerTestP,NotifyCacheContentChanged_DeleteEntry)2089 TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteEntry) {
2090 TestCacheStorageObserver observer;
2091 observers_->AddObserver(&observer);
2092
2093 EXPECT_EQ(0, observer.notify_content_changed_count);
2094 EXPECT_FALSE(Delete(origin1_, "foo"));
2095 base::RunLoop().RunUntilIdle();
2096 EXPECT_EQ(0, observer.notify_content_changed_count);
2097 EXPECT_TRUE(Open(origin1_, "foo"));
2098 observer.Wait();
2099 EXPECT_EQ(0, observer.notify_content_changed_count);
2100 EXPECT_TRUE(
2101 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2102 observer.Wait();
2103 EXPECT_EQ(1, observer.notify_content_changed_count);
2104 EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
2105 GURL("http://example.com/foo")));
2106 observer.Wait();
2107 EXPECT_EQ(2, observer.notify_content_changed_count);
2108 EXPECT_FALSE(CacheDelete(callback_cache_handle_.value(),
2109 GURL("http://example.com/foo")));
2110 // Give any unexpected observer tasks a chance to run.
2111 base::RunLoop().RunUntilIdle();
2112 EXPECT_EQ(2, observer.notify_content_changed_count);
2113 }
2114
TEST_P(CacheStorageManagerTestP,NotifyCacheContentChanged_DeleteThenPutEntry)2115 TEST_P(CacheStorageManagerTestP, NotifyCacheContentChanged_DeleteThenPutEntry) {
2116 TestCacheStorageObserver observer;
2117 observers_->AddObserver(&observer);
2118
2119 EXPECT_EQ(0, observer.notify_content_changed_count);
2120 EXPECT_TRUE(Open(origin1_, "foo"));
2121 observer.Wait();
2122 EXPECT_EQ(0, observer.notify_content_changed_count);
2123 EXPECT_TRUE(
2124 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2125 observer.Wait();
2126 EXPECT_EQ(1, observer.notify_content_changed_count);
2127 EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
2128 GURL("http://example.com/foo")));
2129 observer.Wait();
2130 EXPECT_EQ(2, observer.notify_content_changed_count);
2131 EXPECT_TRUE(
2132 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2133 observer.Wait();
2134 EXPECT_EQ(3, observer.notify_content_changed_count);
2135 EXPECT_TRUE(CacheDelete(callback_cache_handle_.value(),
2136 GURL("http://example.com/foo")));
2137 observer.Wait();
2138 EXPECT_EQ(4, observer.notify_content_changed_count);
2139 }
2140
TEST_P(CacheStorageManagerTestP,StorageMatch_IgnoreSearch)2141 TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreSearch) {
2142 EXPECT_TRUE(Open(origin1_, "foo"));
2143 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
2144 GURL("http://example.com/foo?bar")));
2145
2146 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
2147
2148 blink::mojom::CacheQueryOptionsPtr match_options =
2149 blink::mojom::CacheQueryOptions::New();
2150 match_options->ignore_search = true;
2151 EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
2152 std::move(match_options)));
2153 }
2154
TEST_P(CacheStorageManagerTestP,StorageMatch_IgnoreMethod)2155 TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreMethod) {
2156 GURL url = GURL("http://example.com/foo");
2157 EXPECT_TRUE(Open(origin1_, "foo"));
2158 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), url));
2159
2160 auto post_request = blink::mojom::FetchAPIRequest::New();
2161 post_request->url = url;
2162 post_request->method = "POST";
2163 EXPECT_FALSE(StorageMatchWithRequest(
2164 origin1_, "foo",
2165 BackgroundFetchSettledFetch::CloneRequest(post_request)));
2166
2167 blink::mojom::CacheQueryOptionsPtr match_options =
2168 blink::mojom::CacheQueryOptions::New();
2169 match_options->ignore_method = true;
2170 EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", std::move(post_request),
2171 std::move(match_options)));
2172 }
2173
TEST_P(CacheStorageManagerTestP,StorageMatch_IgnoreVary)2174 TEST_P(CacheStorageManagerTestP, StorageMatch_IgnoreVary) {
2175 GURL url = GURL("http://example.com/foo");
2176 EXPECT_TRUE(Open(origin1_, "foo"));
2177
2178 auto request = blink::mojom::FetchAPIRequest::New();
2179 request->url = url;
2180 request->headers["vary_foo"] = "foo";
2181 // |request_1| and |request_2| has the same url and headers.
2182 auto request_1 = BackgroundFetchSettledFetch::CloneRequest(request);
2183 auto request_2 = BackgroundFetchSettledFetch::CloneRequest(request);
2184
2185 ResponseHeaderMap response_headers;
2186 response_headers["vary"] = "vary_foo";
2187
2188 EXPECT_TRUE(CachePutWithRequestAndHeaders(callback_cache_handle_.value(),
2189 std::move(request_1),
2190 std::move(response_headers)));
2191 EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", std::move(request_2)));
2192
2193 request->headers["vary_foo"] = "bar";
2194 // |request_3| and |request_4| has the same url and headers.
2195 auto request_3 = BackgroundFetchSettledFetch::CloneRequest(request);
2196 auto request_4 = BackgroundFetchSettledFetch::CloneRequest(request);
2197 EXPECT_FALSE(StorageMatchWithRequest(origin1_, "foo", std::move(request_3)));
2198
2199 blink::mojom::CacheQueryOptionsPtr match_options =
2200 blink::mojom::CacheQueryOptions::New();
2201 match_options->ignore_vary = true;
2202 EXPECT_TRUE(StorageMatchWithRequest(origin1_, "foo", std::move(request_4),
2203 std::move(match_options)));
2204 }
2205
TEST_P(CacheStorageManagerTestP,StorageMatchAll_IgnoreSearch)2206 TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreSearch) {
2207 EXPECT_TRUE(Open(origin1_, "foo"));
2208 EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
2209 GURL("http://example.com/foo?bar")));
2210
2211 EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
2212
2213 blink::mojom::CacheQueryOptionsPtr match_options =
2214 blink::mojom::CacheQueryOptions::New();
2215 match_options->ignore_search = true;
2216 EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo"),
2217 std::move(match_options)));
2218 }
2219
TEST_P(CacheStorageManagerTestP,StorageMatchAll_IgnoreMethod)2220 TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreMethod) {
2221 GURL url = GURL("http://example.com/foo");
2222 EXPECT_TRUE(Open(origin1_, "foo"));
2223 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), url));
2224
2225 auto post_request = blink::mojom::FetchAPIRequest::New();
2226 post_request->url = url;
2227 post_request->method = "POST";
2228 EXPECT_FALSE(StorageMatchAllWithRequest(
2229 origin1_, BackgroundFetchSettledFetch::CloneRequest(post_request)));
2230
2231 blink::mojom::CacheQueryOptionsPtr match_options =
2232 blink::mojom::CacheQueryOptions::New();
2233 match_options->ignore_method = true;
2234 EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, std::move(post_request),
2235 std::move(match_options)));
2236 }
2237
TEST_P(CacheStorageManagerTestP,StorageMatchAll_IgnoreVary)2238 TEST_P(CacheStorageManagerTestP, StorageMatchAll_IgnoreVary) {
2239 GURL url = GURL("http://example.com/foo");
2240 EXPECT_TRUE(Open(origin1_, "foo"));
2241
2242 auto request = blink::mojom::FetchAPIRequest::New();
2243 request->url = url;
2244 request->headers["vary_foo"] = "foo";
2245 // |request_1| and |request_2| has the same url and headers.
2246 auto request_1 = BackgroundFetchSettledFetch::CloneRequest(request);
2247 auto request_2 = BackgroundFetchSettledFetch::CloneRequest(request);
2248
2249 ResponseHeaderMap response_headers;
2250 response_headers["vary"] = "vary_foo";
2251
2252 EXPECT_TRUE(CachePutWithRequestAndHeaders(
2253 callback_cache_handle_.value(), std::move(request_1), response_headers));
2254 EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, std::move(request_2)));
2255
2256 request->headers["vary_foo"] = "bar";
2257 // |request_3| and |request_4| has the same url and headers.
2258 auto request_3 = BackgroundFetchSettledFetch::CloneRequest(request);
2259 auto request_4 = BackgroundFetchSettledFetch::CloneRequest(request);
2260 EXPECT_FALSE(StorageMatchAllWithRequest(origin1_, std::move(request_3)));
2261
2262 blink::mojom::CacheQueryOptionsPtr match_options =
2263 blink::mojom::CacheQueryOptions::New();
2264 match_options->ignore_vary = true;
2265 EXPECT_TRUE(StorageMatchAllWithRequest(origin1_, std::move(request_4),
2266 std::move(match_options)));
2267 }
2268
TEST_P(CacheStorageManagerTestP,StorageWriteToCache)2269 TEST_P(CacheStorageManagerTestP, StorageWriteToCache) {
2270 EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
2271
2272 EXPECT_TRUE(Write(origin1_, CacheStorageOwner::kBackgroundFetch, "foo",
2273 "http://example.com/foo"));
2274
2275 // Match request we just wrote.
2276 EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
2277 nullptr, CacheStorageOwner::kBackgroundFetch));
2278
2279 // Don't match with different origin.
2280 EXPECT_FALSE(StorageMatch(origin2_, "foo", GURL("http://example.com/foo"),
2281 nullptr, CacheStorageOwner::kBackgroundFetch));
2282 // Don't match with different cache name.
2283 EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo"),
2284 nullptr, CacheStorageOwner::kBackgroundFetch));
2285 // Don't match with different request.
2286 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar"),
2287 nullptr, CacheStorageOwner::kBackgroundFetch));
2288 // Don't match with different owner.
2289 EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
2290 nullptr, CacheStorageOwner::kCacheAPI));
2291 }
2292
TEST_F(CacheStorageManagerTest,WriteIndexOnlyScheduledWhenValueChanges)2293 TEST_F(CacheStorageManagerTest, WriteIndexOnlyScheduledWhenValueChanges) {
2294 const char* kCacheName = "WriteIndexOnlyScheduledWhenValueChanges";
2295
2296 // In order to make sure operations are flushed through the various scheduler
2297 // queues we match against a non-existant URL. This should always return
2298 // false from Match() and when it completes we know any previous operations
2299 // have completed as well.
2300 const GURL kNonExistant("http://example.com/bar");
2301 const GURL kResource("https://example.com/foo");
2302
2303 // Opening a new cache should require writing the index.
2304 EXPECT_TRUE(Open(origin1_, kCacheName));
2305 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant));
2306 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
2307
2308 // Allow the cache to close.
2309 callback_cache_handle_ = CacheStorageCacheHandle();
2310
2311 // Opening an existing cache should *not* require writing the index.
2312 EXPECT_TRUE(Open(origin1_, kCacheName));
2313 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant));
2314 EXPECT_FALSE(FlushCacheStorageIndex(origin1_));
2315
2316 // Putting a value in the cache should require writing the index.
2317 EXPECT_TRUE(CachePut(callback_cache_handle_.value(), kResource));
2318 EXPECT_TRUE(FlushCacheStorageIndex(origin1_));
2319
2320 // Allow the cache to close.
2321 callback_cache_handle_ = CacheStorageCacheHandle();
2322
2323 // Opening an existing cache after writing a value should *not* require
2324 // writing the index.
2325 EXPECT_TRUE(Open(origin1_, kCacheName));
2326 EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), kNonExistant));
2327 EXPECT_TRUE(CacheMatch(callback_cache_handle_.value(), kResource));
2328 EXPECT_FALSE(FlushCacheStorageIndex(origin1_));
2329 }
2330
TEST_P(CacheStorageManagerTestP,SlowPutCompletesWithoutExternalRef)2331 TEST_P(CacheStorageManagerTestP, SlowPutCompletesWithoutExternalRef) {
2332 EXPECT_TRUE(Open(origin1_, "foo"));
2333
2334 auto request = blink::mojom::FetchAPIRequest::New();
2335 request->url = GURL("http://example.com/foo");
2336
2337 // Start defining a blob for the response body.
2338 std::string body_data("hello world");
2339 auto blob = blink::mojom::SerializedBlob::New();
2340 blob->uuid = "mock blob";
2341 blob->size = body_data.length();
2342
2343 // Provide a fake blob implementation that delays completion. This will
2344 // allow us to pause the writing operation so we can drop the external
2345 // reference.
2346 base::RunLoop blob_loop;
2347 DelayedBlob delayed_blob(blob->blob.InitWithNewPipeAndPassReceiver(),
2348 body_data, blob_loop.QuitClosure());
2349
2350 // Begin the operation to write the blob into the cache.
2351 base::RunLoop cache_loop;
2352 CachePutWithStatusCodeAndBlobInternal(callback_cache_handle_.value(),
2353 std::move(request), 200,
2354 std::move(blob), &cache_loop);
2355
2356 // Wait for blob's ReadAll() method to be called.
2357 blob_loop.Run();
2358
2359 // Drop the external reference to the cache. The operation should hold
2360 // itself alive, but previous versions of the code would destroy the cache
2361 // immediately at this step.
2362 callback_cache_handle_ = CacheStorageCacheHandle();
2363
2364 // Signal the blob to complete reading.
2365 delayed_blob.Resume();
2366
2367 // Wait for the cache write operation to be complete and verify that it
2368 // succeeded.
2369 cache_loop.Run();
2370 EXPECT_EQ(CacheStorageError::kSuccess, callback_error_);
2371 }
2372
2373 class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
2374 protected:
2375 CacheStorageQuotaClientTest() = default;
2376
SetUp()2377 void SetUp() override {
2378 CacheStorageManagerTest::SetUp();
2379 quota_client_ = base::MakeRefCounted<CacheStorageQuotaClient>(
2380 cache_manager_, CacheStorageOwner::kCacheAPI);
2381 }
2382
QuotaUsageCallback(base::RunLoop * run_loop,int64_t usage)2383 void QuotaUsageCallback(base::RunLoop* run_loop, int64_t usage) {
2384 callback_quota_usage_ = usage;
2385 run_loop->Quit();
2386 }
2387
OriginsCallback(base::RunLoop * run_loop,const std::vector<url::Origin> & origins)2388 void OriginsCallback(base::RunLoop* run_loop,
2389 const std::vector<url::Origin>& origins) {
2390 callback_origins_ = origins;
2391 run_loop->Quit();
2392 }
2393
DeleteOriginCallback(base::RunLoop * run_loop,blink::mojom::QuotaStatusCode status)2394 void DeleteOriginCallback(base::RunLoop* run_loop,
2395 blink::mojom::QuotaStatusCode status) {
2396 callback_status_ = status;
2397 run_loop->Quit();
2398 }
2399
QuotaGetOriginUsage(const url::Origin & origin)2400 int64_t QuotaGetOriginUsage(const url::Origin& origin) {
2401 base::RunLoop loop;
2402 quota_client_->GetOriginUsage(
2403 origin, StorageType::kTemporary,
2404 base::BindOnce(&CacheStorageQuotaClientTest::QuotaUsageCallback,
2405 base::Unretained(this), base::Unretained(&loop)));
2406 loop.Run();
2407 return callback_quota_usage_;
2408 }
2409
QuotaGetOriginsForType()2410 size_t QuotaGetOriginsForType() {
2411 base::RunLoop loop;
2412 quota_client_->GetOriginsForType(
2413 StorageType::kTemporary,
2414 base::BindOnce(&CacheStorageQuotaClientTest::OriginsCallback,
2415 base::Unretained(this), base::Unretained(&loop)));
2416 loop.Run();
2417 return callback_origins_.size();
2418 }
2419
QuotaGetOriginsForHost(const std::string & host)2420 size_t QuotaGetOriginsForHost(const std::string& host) {
2421 base::RunLoop loop;
2422 quota_client_->GetOriginsForHost(
2423 StorageType::kTemporary, host,
2424 base::BindOnce(&CacheStorageQuotaClientTest::OriginsCallback,
2425 base::Unretained(this), base::Unretained(&loop)));
2426 loop.Run();
2427 return callback_origins_.size();
2428 }
2429
QuotaDeleteOriginData(const url::Origin & origin)2430 bool QuotaDeleteOriginData(const url::Origin& origin) {
2431 base::RunLoop loop;
2432 quota_client_->DeleteOriginData(
2433 origin, StorageType::kTemporary,
2434 base::BindOnce(&CacheStorageQuotaClientTest::DeleteOriginCallback,
2435 base::Unretained(this), base::Unretained(&loop)));
2436 loop.Run();
2437 return callback_status_ == blink::mojom::QuotaStatusCode::kOk;
2438 }
2439
2440 scoped_refptr<CacheStorageQuotaClient> quota_client_;
2441
2442 blink::mojom::QuotaStatusCode callback_status_;
2443 int64_t callback_quota_usage_ = 0;
2444 std::vector<url::Origin> callback_origins_;
2445
2446 private:
2447 DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClientTest);
2448 };
2449
2450 class CacheStorageQuotaClientDiskOnlyTest : public CacheStorageQuotaClientTest {
2451 public:
MemoryOnly()2452 bool MemoryOnly() override { return false; }
2453 };
2454
2455 class CacheStorageQuotaClientTestP : public CacheStorageQuotaClientTest,
2456 public testing::WithParamInterface<Param> {
MemoryOnly()2457 bool MemoryOnly() override {
2458 return GetParam().storage_ == TestStorage::kMemory;
2459 }
ManagerType()2460 TestManager ManagerType() override { return GetParam().manager_; }
2461 };
2462
TEST_P(CacheStorageQuotaClientTestP,QuotaGetOriginUsage)2463 TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginUsage) {
2464 EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
2465 EXPECT_TRUE(Open(origin1_, "foo"));
2466 EXPECT_TRUE(
2467 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2468 EXPECT_LT(0, QuotaGetOriginUsage(origin1_));
2469 }
2470
TEST_P(CacheStorageQuotaClientTestP,QuotaGetOriginsForType)2471 TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForType) {
2472 EXPECT_EQ(0u, QuotaGetOriginsForType());
2473 EXPECT_TRUE(Open(origin1_, "foo"));
2474 EXPECT_TRUE(Open(origin1_, "bar"));
2475 EXPECT_TRUE(Open(origin2_, "foo"));
2476 EXPECT_EQ(2u, QuotaGetOriginsForType());
2477 }
2478
TEST_P(CacheStorageQuotaClientTestP,QuotaGetOriginsForTypeDifferentOwners)2479 TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForTypeDifferentOwners) {
2480 EXPECT_EQ(0u, QuotaGetOriginsForType());
2481 EXPECT_TRUE(Open(origin1_, "foo"));
2482 // The |quota_client_| is registered for CacheStorageOwner::kCacheAPI, so this
2483 // Open is ignored.
2484 EXPECT_TRUE(Open(origin2_, "bar", CacheStorageOwner::kBackgroundFetch));
2485 EXPECT_EQ(1u, QuotaGetOriginsForType());
2486 }
2487
TEST_P(CacheStorageQuotaClientTestP,QuotaGetOriginsForHost)2488 TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForHost) {
2489 EXPECT_EQ(0u, QuotaGetOriginsForHost("example.com"));
2490 EXPECT_TRUE(
2491 Open(url::Origin::Create(GURL("http://example.com:8080")), "foo"));
2492 EXPECT_TRUE(
2493 Open(url::Origin::Create(GURL("http://example.com:9000")), "foo"));
2494 EXPECT_TRUE(Open(url::Origin::Create(GURL("ftp://example.com")), "foo"));
2495 EXPECT_TRUE(Open(url::Origin::Create(GURL("http://example2.com")), "foo"));
2496 EXPECT_EQ(3u, QuotaGetOriginsForHost("example.com"));
2497 EXPECT_EQ(1u, QuotaGetOriginsForHost("example2.com"));
2498 EXPECT_THAT(
2499 callback_origins_,
2500 testing::Contains(url::Origin::Create(GURL("http://example2.com"))));
2501 EXPECT_EQ(0u, QuotaGetOriginsForHost("unknown.com"));
2502 }
2503
TEST_P(CacheStorageQuotaClientTestP,QuotaDeleteOriginData)2504 TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteOriginData) {
2505 EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
2506 EXPECT_TRUE(Open(origin1_, "foo"));
2507 // Call put to test that initialized caches are properly deleted too.
2508 EXPECT_TRUE(
2509 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2510 EXPECT_TRUE(Open(origin1_, "bar"));
2511 EXPECT_TRUE(Open(origin2_, "baz"));
2512
2513 int64_t origin1_size = QuotaGetOriginUsage(origin1_);
2514 EXPECT_LT(0, origin1_size);
2515
2516 EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
2517
2518 EXPECT_EQ(-1 * origin1_size, quota_manager_proxy_->last_notified_delta());
2519 EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
2520 EXPECT_FALSE(Has(origin1_, "foo"));
2521 EXPECT_FALSE(Has(origin1_, "bar"));
2522 EXPECT_TRUE(Has(origin2_, "baz"));
2523 EXPECT_TRUE(Open(origin1_, "foo"));
2524 }
2525
TEST_P(CacheStorageQuotaClientTestP,QuotaDeleteEmptyOrigin)2526 TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyOrigin) {
2527 EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
2528 }
2529
TEST_F(CacheStorageQuotaClientDiskOnlyTest,QuotaDeleteUnloadedOriginData)2530 TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
2531 EXPECT_TRUE(Open(origin1_, "foo"));
2532 // Call put to test that initialized caches are properly deleted too.
2533 EXPECT_TRUE(
2534 CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
2535
2536 // Close the cache backend so that it writes out its index to disk.
2537 base::RunLoop run_loop;
2538 LegacyCacheStorageCache::From(callback_cache_handle_)
2539 ->Close(run_loop.QuitClosure());
2540 run_loop.Run();
2541
2542 // Create a new CacheStorageManager that hasn't yet loaded the origin.
2543 quota_manager_proxy_->SimulateQuotaManagerDestroyed();
2544 RecreateStorageManager();
2545 quota_client_ = base::MakeRefCounted<CacheStorageQuotaClient>(
2546 cache_manager_, CacheStorageOwner::kCacheAPI);
2547
2548 EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
2549 EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
2550 }
2551
2552 INSTANTIATE_TEST_SUITE_P(
2553 CacheStorageManagerTests,
2554 CacheStorageManagerTestP,
2555 ::testing::Values(Param(TestManager::kLegacy, TestStorage::kMemory),
2556 Param(TestManager::kLegacy, TestStorage::kDisk),
2557 Param(TestManager::kCrossSequence, TestStorage::kMemory),
2558 Param(TestManager::kCrossSequence, TestStorage::kDisk)));
2559
2560 INSTANTIATE_TEST_SUITE_P(CacheStorageManagerTests,
2561 CacheStorageManagerLegacyOnlyTestP,
2562 ::testing::Values(TestStorage::kMemory,
2563 TestStorage::kDisk));
2564
2565 INSTANTIATE_TEST_SUITE_P(
2566 CacheStorageQuotaClientTests,
2567 CacheStorageQuotaClientTestP,
2568 ::testing::Values(Param(TestManager::kLegacy, TestStorage::kMemory),
2569 Param(TestManager::kLegacy, TestStorage::kDisk),
2570 Param(TestManager::kCrossSequence, TestStorage::kMemory),
2571 Param(TestManager::kCrossSequence, TestStorage::kDisk)));
2572
2573 } // namespace cache_storage_manager_unittest
2574 } // namespace content
2575