Home | History | Annotate | Download | only in service_worker
      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 "content/browser/service_worker/service_worker_cache_storage_manager.h"
      6 
      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"
     18 
     19 namespace content {
     20 
     21 class ServiceWorkerCacheStorageManagerTest : public testing::Test {
     22  protected:
     23   ServiceWorkerCacheStorageManagerTest()
     24       : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
     25         callback_bool_(false),
     26         callback_error_(
     27             ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR),
     28         callback_cache_error_(ServiceWorkerCache::ErrorTypeOK),
     29         origin1_("http://example1.com"),
     30         origin2_("http://example2.com") {}
     31 
     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();
     37 
     38     net::URLRequestContext* url_request_context =
     39         browser_context_.GetRequestContext()->GetURLRequestContext();
     40     if (MemoryOnly()) {
     41       cache_manager_ = ServiceWorkerCacheStorageManager::Create(
     42           base::FilePath(), base::MessageLoopProxy::current());
     43     } else {
     44       ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     45       cache_manager_ = ServiceWorkerCacheStorageManager::Create(
     46           temp_dir_.path(), base::MessageLoopProxy::current());
     47     }
     48 
     49     cache_manager_->SetBlobParametersForCache(
     50         url_request_context, blob_storage_context->context()->AsWeakPtr());
     51   }
     52 
     53   virtual void TearDown() OVERRIDE {
     54     base::RunLoop().RunUntilIdle();
     55   }
     56 
     57   virtual bool MemoryOnly() { return false; }
     58 
     59   void BoolAndErrorCallback(
     60       base::RunLoop* run_loop,
     61       bool value,
     62       ServiceWorkerCacheStorage::CacheStorageError error) {
     63     callback_bool_ = value;
     64     callback_error_ = error;
     65     run_loop->Quit();
     66   }
     67 
     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;
     74     run_loop->Quit();
     75   }
     76 
     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;
     83     run_loop->Quit();
     84   }
     85 
     86   void CachePutCallback(base::RunLoop* run_loop,
     87                         ServiceWorkerCache::ErrorType error) {
     88     callback_cache_error_ = error;
     89     run_loop->Quit();
     90   }
     91 
     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.
    100     run_loop->Quit();
    101   }
    102 
    103   bool CreateCache(const GURL& origin, const std::string& cache_name) {
    104     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
    105     cache_manager_->CreateCache(
    106         origin,
    107         cache_name,
    108         base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheAndErrorCallback,
    109                    base::Unretained(this),
    110                    base::Unretained(loop.get())));
    111     loop->Run();
    112 
    113     bool error = callback_error_ !=
    114                  ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
    115     if (error)
    116       EXPECT_TRUE(!callback_cache_.get());
    117     else
    118       EXPECT_TRUE(callback_cache_.get());
    119     return !error;
    120   }
    121 
    122   bool Get(const GURL& origin, const std::string& cache_name) {
    123     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
    124     cache_manager_->GetCache(
    125         origin,
    126         cache_name,
    127         base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheAndErrorCallback,
    128                    base::Unretained(this),
    129                    base::Unretained(loop.get())));
    130     loop->Run();
    131 
    132     bool error = callback_error_ !=
    133                  ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
    134     if (error)
    135       EXPECT_TRUE(!callback_cache_.get());
    136     else
    137       EXPECT_TRUE(callback_cache_.get());
    138     return !error;
    139   }
    140 
    141   bool Has(const GURL& origin, const std::string& cache_name) {
    142     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
    143     cache_manager_->HasCache(
    144         origin,
    145         cache_name,
    146         base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
    147                    base::Unretained(this),
    148                    base::Unretained(loop.get())));
    149     loop->Run();
    150 
    151     return callback_bool_;
    152   }
    153 
    154   bool Delete(const GURL& origin, const std::string& cache_name) {
    155     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
    156     cache_manager_->DeleteCache(
    157         origin,
    158         cache_name,
    159         base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
    160                    base::Unretained(this),
    161                    base::Unretained(loop.get())));
    162     loop->Run();
    163 
    164     return callback_bool_;
    165   }
    166 
    167   bool Keys(const GURL& origin) {
    168     scoped_ptr<base::RunLoop> loop(new base::RunLoop());
    169     cache_manager_->EnumerateCaches(
    170         origin,
    171         base::Bind(
    172             &ServiceWorkerCacheStorageManagerTest::StringsAndErrorCallback,
    173             base::Unretained(this),
    174             base::Unretained(loop.get())));
    175     loop->Run();
    176 
    177     bool error = callback_error_ !=
    178                  ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
    179     return !error;
    180   }
    181 
    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());
    190     cache->Put(
    191         request.Pass(),
    192         response.Pass(),
    193         base::Bind(&ServiceWorkerCacheStorageManagerTest::CachePutCallback,
    194                    base::Unretained(this),
    195                    base::Unretained(loop.get())));
    196     loop->Run();
    197 
    198     bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
    199     return !error;
    200   }
    201 
    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());
    208     cache->Match(
    209         request.Pass(),
    210         base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheMatchCallback,
    211                    base::Unretained(this),
    212                    base::Unretained(loop.get())));
    213     loop->Run();
    214 
    215     bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
    216     return !error;
    217   }
    218 
    219  protected:
    220   TestBrowserContext browser_context_;
    221   TestBrowserThreadBundle browser_thread_bundle_;
    222 
    223   base::ScopedTempDir temp_dir_;
    224   scoped_ptr<ServiceWorkerCacheStorageManager> cache_manager_;
    225 
    226   scoped_refptr<ServiceWorkerCache> callback_cache_;
    227   int callback_bool_;
    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_;
    232 
    233   const GURL origin1_;
    234   const GURL origin2_;
    235 
    236  private:
    237   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorageManagerTest);
    238 };
    239 
    240 class ServiceWorkerCacheStorageManagerMemoryOnlyTest
    241     : public ServiceWorkerCacheStorageManagerTest {
    242   virtual bool MemoryOnly() OVERRIDE { return true; }
    243 };
    244 
    245 class ServiceWorkerCacheStorageManagerTestP
    246     : public ServiceWorkerCacheStorageManagerTest,
    247       public testing::WithParamInterface<bool> {
    248   virtual bool MemoryOnly() OVERRIDE { return !GetParam(); }
    249 };
    250 
    251 TEST_F(ServiceWorkerCacheStorageManagerTest, TestsRunOnIOThread) {
    252   EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    253 }
    254 
    255 TEST_P(ServiceWorkerCacheStorageManagerTestP, CreateCache) {
    256   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    257 }
    258 
    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,
    263             callback_error_);
    264 }
    265 
    266 TEST_P(ServiceWorkerCacheStorageManagerTestP, CreateTwoCaches) {
    267   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    268   EXPECT_TRUE(CreateCache(origin1_, "bar"));
    269 }
    270 
    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());
    276 }
    277 
    278 TEST_P(ServiceWorkerCacheStorageManagerTestP, Create2CachesSameNameDiffSWs) {
    279   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    280   EXPECT_TRUE(CreateCache(origin2_, "foo"));
    281 }
    282 
    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());
    288 }
    289 
    290 TEST_P(ServiceWorkerCacheStorageManagerTestP, GetNonExistent) {
    291   EXPECT_FALSE(Get(origin1_, "foo"));
    292   EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND,
    293             callback_error_);
    294 }
    295 
    296 TEST_P(ServiceWorkerCacheStorageManagerTestP, HasCache) {
    297   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    298   EXPECT_TRUE(Has(origin1_, "foo"));
    299   EXPECT_TRUE(callback_bool_);
    300 }
    301 
    302 TEST_P(ServiceWorkerCacheStorageManagerTestP, HasNonExistent) {
    303   EXPECT_FALSE(Has(origin1_, "foo"));
    304 }
    305 
    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,
    311             callback_error_);
    312 }
    313 
    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,
    319             callback_error_);
    320 }
    321 
    322 TEST_P(ServiceWorkerCacheStorageManagerTestP, EmptyKeys) {
    323   EXPECT_TRUE(Keys(origin1_));
    324   EXPECT_TRUE(callback_strings_.empty());
    325 }
    326 
    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());
    340 }
    341 
    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());
    350 }
    351 
    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]);
    360 }
    361 
    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());
    374 }
    375 
    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"));
    382   cache_manager_ =
    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_);
    390 }
    391 
    392 TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
    393   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    394   EXPECT_TRUE(CreateCache(origin2_, "baz"));
    395   cache_manager_ =
    396       ServiceWorkerCacheStorageManager::Create(cache_manager_.get());
    397   EXPECT_TRUE(Keys(origin1_));
    398   EXPECT_EQ(0u, callback_strings_.size());
    399 }
    400 
    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());
    409 }
    410 
    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());
    419 }
    420 
    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;
    428   EXPECT_TRUE(!cache);
    429 }
    430 
    431 // With a memory cache the cache can't be freed from memory until the client
    432 // calls delete.
    433 TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest,
    434        MemoryLosesReferenceOnlyAfterDelete) {
    435   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    436   base::WeakPtr<ServiceWorkerCache> cache = callback_cache_->AsWeakPtr();
    437   callback_cache_ = NULL;
    438   EXPECT_TRUE(cache);
    439   EXPECT_TRUE(Delete(origin1_, "foo"));
    440   EXPECT_FALSE(cache);
    441 }
    442 
    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"));
    449 }
    450 
    451 TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteBeforeRelease) {
    452   EXPECT_TRUE(CreateCache(origin1_, "foo"));
    453   EXPECT_TRUE(Delete(origin1_, "foo"));
    454   EXPECT_TRUE(callback_cache_->AsWeakPtr());
    455 }
    456 
    457 INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheStorageManagerTests,
    458                         ServiceWorkerCacheStorageManagerTestP,
    459                         ::testing::Values(false, true));
    460 
    461 }  // namespace content
    462