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.
5 #include "content/browser/service_worker/service_worker_cache_storage_manager.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "content/browser/fileapi/chrome_blob_storage_context.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/test/test_browser_context.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "net/url_request/url_request_context_getter.h"
16 #include "storage/browser/blob/blob_storage_context.h"
17 #include "testing/gtest/include/gtest/gtest.h"
21 class ServiceWorkerCacheStorageManagerTest : public testing::Test {
23 ServiceWorkerCacheStorageManagerTest()
24 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
25 callback_bool_(false),
27 ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR),
28 callback_cache_error_(ServiceWorkerCache::ErrorTypeOK),
29 origin1_("http://example1.com"),
30 origin2_("http://example2.com") {}
32 virtual void SetUp() OVERRIDE {
33 ChromeBlobStorageContext* blob_storage_context(
34 ChromeBlobStorageContext::GetFor(&browser_context_));
35 // Wait for ChromeBlobStorageContext to finish initializing.
36 base::RunLoop().RunUntilIdle();
38 net::URLRequestContext* url_request_context =
39 browser_context_.GetRequestContext()->GetURLRequestContext();
41 cache_manager_ = ServiceWorkerCacheStorageManager::Create(
42 base::FilePath(), base::MessageLoopProxy::current());
44 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
45 cache_manager_ = ServiceWorkerCacheStorageManager::Create(
46 temp_dir_.path(), base::MessageLoopProxy::current());
49 cache_manager_->SetBlobParametersForCache(
50 url_request_context, blob_storage_context->context()->AsWeakPtr());
53 virtual void TearDown() OVERRIDE {
54 base::RunLoop().RunUntilIdle();
57 virtual bool MemoryOnly() { return false; }
59 void BoolAndErrorCallback(
60 base::RunLoop* run_loop,
62 ServiceWorkerCacheStorage::CacheStorageError error) {
63 callback_bool_ = value;
64 callback_error_ = error;
68 void CacheAndErrorCallback(
69 base::RunLoop* run_loop,
70 const scoped_refptr<ServiceWorkerCache>& cache,
71 ServiceWorkerCacheStorage::CacheStorageError error) {
72 callback_cache_ = cache;
73 callback_error_ = error;
77 void StringsAndErrorCallback(
78 base::RunLoop* run_loop,
79 const std::vector<std::string>& strings,
80 ServiceWorkerCacheStorage::CacheStorageError error) {
81 callback_strings_ = strings;
82 callback_error_ = error;
86 void CachePutCallback(base::RunLoop* run_loop,
87 ServiceWorkerCache::ErrorType error) {
88 callback_cache_error_ = error;
92 void CacheMatchCallback(
93 base::RunLoop* run_loop,
94 ServiceWorkerCache::ErrorType error,
95 scoped_ptr<ServiceWorkerResponse> response,
96 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
97 callback_cache_error_ = error;
98 callback_cache_response_ = response.Pass();
99 // Deliberately drop the data handle as only the url is being tested.
103 bool CreateCache(const GURL& origin, const std::string& cache_name) {
104 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
105 cache_manager_->CreateCache(
108 base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheAndErrorCallback,
109 base::Unretained(this),
110 base::Unretained(loop.get())));
113 bool error = callback_error_ !=
114 ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
116 EXPECT_TRUE(!callback_cache_.get());
118 EXPECT_TRUE(callback_cache_.get());
122 bool Get(const GURL& origin, const std::string& cache_name) {
123 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
124 cache_manager_->GetCache(
127 base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheAndErrorCallback,
128 base::Unretained(this),
129 base::Unretained(loop.get())));
132 bool error = callback_error_ !=
133 ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
135 EXPECT_TRUE(!callback_cache_.get());
137 EXPECT_TRUE(callback_cache_.get());
141 bool Has(const GURL& origin, const std::string& cache_name) {
142 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
143 cache_manager_->HasCache(
146 base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
147 base::Unretained(this),
148 base::Unretained(loop.get())));
151 return callback_bool_;
154 bool Delete(const GURL& origin, const std::string& cache_name) {
155 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
156 cache_manager_->DeleteCache(
159 base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
160 base::Unretained(this),
161 base::Unretained(loop.get())));
164 return callback_bool_;
167 bool Keys(const GURL& origin) {
168 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
169 cache_manager_->EnumerateCaches(
172 &ServiceWorkerCacheStorageManagerTest::StringsAndErrorCallback,
173 base::Unretained(this),
174 base::Unretained(loop.get())));
177 bool error = callback_error_ !=
178 ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
182 bool CachePut(const scoped_refptr<ServiceWorkerCache>& cache,
183 const std::string& url) {
184 scoped_ptr<ServiceWorkerFetchRequest> request(
185 new ServiceWorkerFetchRequest());
186 scoped_ptr<ServiceWorkerResponse> response(new ServiceWorkerResponse());
187 request->url = GURL("http://example.com/foo");
188 response->url = GURL("http://example.com/foo");
189 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
193 base::Bind(&ServiceWorkerCacheStorageManagerTest::CachePutCallback,
194 base::Unretained(this),
195 base::Unretained(loop.get())));
198 bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
202 bool CacheMatch(const scoped_refptr<ServiceWorkerCache>& cache,
203 const std::string& url) {
204 scoped_ptr<ServiceWorkerFetchRequest> request(
205 new ServiceWorkerFetchRequest());
206 request->url = GURL("http://example.com/foo");
207 scoped_ptr<base::RunLoop> loop(new base::RunLoop());
210 base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheMatchCallback,
211 base::Unretained(this),
212 base::Unretained(loop.get())));
215 bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
220 TestBrowserContext browser_context_;
221 TestBrowserThreadBundle browser_thread_bundle_;
223 base::ScopedTempDir temp_dir_;
224 scoped_ptr<ServiceWorkerCacheStorageManager> cache_manager_;
226 scoped_refptr<ServiceWorkerCache> callback_cache_;
228 ServiceWorkerCacheStorage::CacheStorageError callback_error_;
229 ServiceWorkerCache::ErrorType callback_cache_error_;
230 scoped_ptr<ServiceWorkerResponse> callback_cache_response_;
231 std::vector<std::string> callback_strings_;
237 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorageManagerTest);
240 class ServiceWorkerCacheStorageManagerMemoryOnlyTest
241 : public ServiceWorkerCacheStorageManagerTest {
242 virtual bool MemoryOnly() OVERRIDE { return true; }
245 class ServiceWorkerCacheStorageManagerTestP
246 : public ServiceWorkerCacheStorageManagerTest,
247 public testing::WithParamInterface<bool> {
248 virtual bool MemoryOnly() OVERRIDE { return !GetParam(); }
251 TEST_F(ServiceWorkerCacheStorageManagerTest, TestsRunOnIOThread) {
252 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
255 TEST_P(ServiceWorkerCacheStorageManagerTestP, CreateCache) {
256 EXPECT_TRUE(CreateCache(origin1_, "foo"));
259 TEST_P(ServiceWorkerCacheStorageManagerTestP, CreateDuplicateCache) {
260 EXPECT_TRUE(CreateCache(origin1_, "foo"));
261 EXPECT_FALSE(CreateCache(origin1_, "foo"));
262 EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_EXISTS,
266 TEST_P(ServiceWorkerCacheStorageManagerTestP, CreateTwoCaches) {
267 EXPECT_TRUE(CreateCache(origin1_, "foo"));
268 EXPECT_TRUE(CreateCache(origin1_, "bar"));
271 TEST_P(ServiceWorkerCacheStorageManagerTestP, CachePointersDiffer) {
272 EXPECT_TRUE(CreateCache(origin1_, "foo"));
273 scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
274 EXPECT_TRUE(CreateCache(origin1_, "bar"));
275 EXPECT_TRUE(cache.get() != callback_cache_.get());
278 TEST_P(ServiceWorkerCacheStorageManagerTestP, Create2CachesSameNameDiffSWs) {
279 EXPECT_TRUE(CreateCache(origin1_, "foo"));
280 EXPECT_TRUE(CreateCache(origin2_, "foo"));
283 TEST_P(ServiceWorkerCacheStorageManagerTestP, GetCache) {
284 EXPECT_TRUE(CreateCache(origin1_, "foo"));
285 scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
286 EXPECT_TRUE(Get(origin1_, "foo"));
287 EXPECT_TRUE(cache.get() == callback_cache_.get());
290 TEST_P(ServiceWorkerCacheStorageManagerTestP, GetNonExistent) {
291 EXPECT_FALSE(Get(origin1_, "foo"));
292 EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND,
296 TEST_P(ServiceWorkerCacheStorageManagerTestP, HasCache) {
297 EXPECT_TRUE(CreateCache(origin1_, "foo"));
298 EXPECT_TRUE(Has(origin1_, "foo"));
299 EXPECT_TRUE(callback_bool_);
302 TEST_P(ServiceWorkerCacheStorageManagerTestP, HasNonExistent) {
303 EXPECT_FALSE(Has(origin1_, "foo"));
306 TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteCache) {
307 EXPECT_TRUE(CreateCache(origin1_, "foo"));
308 EXPECT_TRUE(Delete(origin1_, "foo"));
309 EXPECT_FALSE(Get(origin1_, "foo"));
310 EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND,
314 TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteTwice) {
315 EXPECT_TRUE(CreateCache(origin1_, "foo"));
316 EXPECT_TRUE(Delete(origin1_, "foo"));
317 EXPECT_FALSE(Delete(origin1_, "foo"));
318 EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND,
322 TEST_P(ServiceWorkerCacheStorageManagerTestP, EmptyKeys) {
323 EXPECT_TRUE(Keys(origin1_));
324 EXPECT_TRUE(callback_strings_.empty());
327 TEST_P(ServiceWorkerCacheStorageManagerTestP, SomeKeys) {
328 EXPECT_TRUE(CreateCache(origin1_, "foo"));
329 EXPECT_TRUE(CreateCache(origin1_, "bar"));
330 EXPECT_TRUE(CreateCache(origin2_, "baz"));
331 EXPECT_TRUE(Keys(origin1_));
332 EXPECT_EQ(2u, callback_strings_.size());
333 std::vector<std::string> expected_keys;
334 expected_keys.push_back("foo");
335 expected_keys.push_back("bar");
336 EXPECT_TRUE(expected_keys == callback_strings_);
337 EXPECT_TRUE(Keys(origin2_));
338 EXPECT_EQ(1u, callback_strings_.size());
339 EXPECT_STREQ("baz", callback_strings_[0].c_str());
342 TEST_P(ServiceWorkerCacheStorageManagerTestP, DeletedKeysGone) {
343 EXPECT_TRUE(CreateCache(origin1_, "foo"));
344 EXPECT_TRUE(CreateCache(origin1_, "bar"));
345 EXPECT_TRUE(CreateCache(origin2_, "baz"));
346 EXPECT_TRUE(Delete(origin1_, "bar"));
347 EXPECT_TRUE(Keys(origin1_));
348 EXPECT_EQ(1u, callback_strings_.size());
349 EXPECT_STREQ("foo", callback_strings_[0].c_str());
352 TEST_P(ServiceWorkerCacheStorageManagerTestP, Chinese) {
353 EXPECT_TRUE(CreateCache(origin1_, "你好"));
354 scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
355 EXPECT_TRUE(Get(origin1_, "你好"));
356 EXPECT_TRUE(cache.get() == callback_cache_.get());
357 EXPECT_TRUE(Keys(origin1_));
358 EXPECT_EQ(1u, callback_strings_.size());
359 EXPECT_TRUE("你好" == callback_strings_[0]);
362 TEST_F(ServiceWorkerCacheStorageManagerTest, EmptyKey) {
363 EXPECT_TRUE(CreateCache(origin1_, ""));
364 scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
365 EXPECT_TRUE(Get(origin1_, ""));
366 EXPECT_EQ(cache.get(), callback_cache_.get());
367 EXPECT_TRUE(Keys(origin1_));
368 EXPECT_EQ(1u, callback_strings_.size());
369 EXPECT_TRUE("" == callback_strings_[0]);
370 EXPECT_TRUE(Has(origin1_, ""));
371 EXPECT_TRUE(Delete(origin1_, ""));
372 EXPECT_TRUE(Keys(origin1_));
373 EXPECT_EQ(0u, callback_strings_.size());
376 TEST_F(ServiceWorkerCacheStorageManagerTest, DataPersists) {
377 EXPECT_TRUE(CreateCache(origin1_, "foo"));
378 EXPECT_TRUE(CreateCache(origin1_, "bar"));
379 EXPECT_TRUE(CreateCache(origin1_, "baz"));
380 EXPECT_TRUE(CreateCache(origin2_, "raz"));
381 EXPECT_TRUE(Delete(origin1_, "bar"));
383 ServiceWorkerCacheStorageManager::Create(cache_manager_.get());
384 EXPECT_TRUE(Keys(origin1_));
385 EXPECT_EQ(2u, callback_strings_.size());
386 std::vector<std::string> expected_keys;
387 expected_keys.push_back("foo");
388 expected_keys.push_back("baz");
389 EXPECT_TRUE(expected_keys == callback_strings_);
392 TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
393 EXPECT_TRUE(CreateCache(origin1_, "foo"));
394 EXPECT_TRUE(CreateCache(origin2_, "baz"));
396 ServiceWorkerCacheStorageManager::Create(cache_manager_.get());
397 EXPECT_TRUE(Keys(origin1_));
398 EXPECT_EQ(0u, callback_strings_.size());
401 TEST_F(ServiceWorkerCacheStorageManagerTest, BadCacheName) {
402 // Since the implementation writes cache names to disk, ensure that we don't
403 // escape the directory.
404 const std::string bad_name = "../../../../../../../../../../../../../../foo";
405 EXPECT_TRUE(CreateCache(origin1_, bad_name));
406 EXPECT_TRUE(Keys(origin1_));
407 EXPECT_EQ(1u, callback_strings_.size());
408 EXPECT_STREQ(bad_name.c_str(), callback_strings_[0].c_str());
411 TEST_F(ServiceWorkerCacheStorageManagerTest, BadOriginName) {
412 // Since the implementation writes origin names to disk, ensure that we don't
413 // escape the directory.
414 GURL bad_origin("../../../../../../../../../../../../../../foo");
415 EXPECT_TRUE(CreateCache(bad_origin, "foo"));
416 EXPECT_TRUE(Keys(bad_origin));
417 EXPECT_EQ(1u, callback_strings_.size());
418 EXPECT_STREQ("foo", callback_strings_[0].c_str());
421 // With a persistent cache if the client drops its reference to a
422 // ServiceWorkerCache
423 // it should be deleted.
424 TEST_F(ServiceWorkerCacheStorageManagerTest, DropReference) {
425 EXPECT_TRUE(CreateCache(origin1_, "foo"));
426 base::WeakPtr<ServiceWorkerCache> cache = callback_cache_->AsWeakPtr();
427 callback_cache_ = NULL;
431 // With a memory cache the cache can't be freed from memory until the client
433 TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest,
434 MemoryLosesReferenceOnlyAfterDelete) {
435 EXPECT_TRUE(CreateCache(origin1_, "foo"));
436 base::WeakPtr<ServiceWorkerCache> cache = callback_cache_->AsWeakPtr();
437 callback_cache_ = NULL;
439 EXPECT_TRUE(Delete(origin1_, "foo"));
443 TEST_P(ServiceWorkerCacheStorageManagerTestP, RecreateCacheOnDemand) {
444 EXPECT_TRUE(CreateCache(origin1_, "foo"));
445 EXPECT_TRUE(CachePut(callback_cache_, "bar"));
446 callback_cache_ = NULL;
447 EXPECT_TRUE(Get(origin1_, "foo"));
448 EXPECT_TRUE(CacheMatch(callback_cache_, "bar"));
451 TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteBeforeRelease) {
452 EXPECT_TRUE(CreateCache(origin1_, "foo"));
453 EXPECT_TRUE(Delete(origin1_, "foo"));
454 EXPECT_TRUE(callback_cache_->AsWeakPtr());
457 INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheStorageManagerTests,
458 ServiceWorkerCacheStorageManagerTestP,
459 ::testing::Values(false, true));
461 } // namespace content