Home | History | Annotate | Download | only in appcache
      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 <stack>
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/callback.h"
     10 #include "base/files/file_util.h"
     11 #include "base/files/scoped_temp_dir.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "base/synchronization/waitable_event.h"
     15 #include "base/threading/thread.h"
     16 #include "content/browser/appcache/appcache.h"
     17 #include "content/browser/appcache/appcache_backend_impl.h"
     18 #include "content/browser/appcache/appcache_database.h"
     19 #include "content/browser/appcache/appcache_entry.h"
     20 #include "content/browser/appcache/appcache_group.h"
     21 #include "content/browser/appcache/appcache_host.h"
     22 #include "content/browser/appcache/appcache_interceptor.h"
     23 #include "content/browser/appcache/appcache_request_handler.h"
     24 #include "content/browser/appcache/appcache_service_impl.h"
     25 #include "content/browser/appcache/appcache_storage_impl.h"
     26 #include "net/base/net_errors.h"
     27 #include "net/base/request_priority.h"
     28 #include "net/http/http_response_headers.h"
     29 #include "net/url_request/url_request_error_job.h"
     30 #include "net/url_request/url_request_job_factory_impl.h"
     31 #include "net/url_request/url_request_test_job.h"
     32 #include "net/url_request/url_request_test_util.h"
     33 #include "sql/test/test_helpers.h"
     34 #include "storage/browser/quota/quota_manager.h"
     35 #include "testing/gtest/include/gtest/gtest.h"
     36 
     37 namespace content {
     38 
     39 namespace {
     40 
     41 const base::Time kZeroTime;
     42 const GURL kManifestUrl("http://blah/manifest");
     43 const GURL kManifestUrl2("http://blah/manifest2");
     44 const GURL kManifestUrl3("http://blah/manifest3");
     45 const GURL kEntryUrl("http://blah/entry");
     46 const GURL kEntryUrl2("http://blah/entry2");
     47 const GURL kFallbackNamespace("http://blah/fallback_namespace/");
     48 const GURL kFallbackNamespace2("http://blah/fallback_namespace/longer");
     49 const GURL kFallbackTestUrl("http://blah/fallback_namespace/longer/test");
     50 const GURL kOnlineNamespace("http://blah/online_namespace");
     51 const GURL kOnlineNamespaceWithinFallback(
     52     "http://blah/fallback_namespace/online/");
     53 const GURL kInterceptNamespace("http://blah/intercept_namespace/");
     54 const GURL kInterceptNamespace2("http://blah/intercept_namespace/longer/");
     55 const GURL kInterceptTestUrl("http://blah/intercept_namespace/longer/test");
     56 const GURL kInterceptPatternNamespace("http://blah/intercept_pattern/*/bar");
     57 const GURL kInterceptPatternTestPositiveUrl(
     58     "http://blah/intercept_pattern/foo/bar");
     59 const GURL kInterceptPatternTestNegativeUrl(
     60     "http://blah/intercept_pattern/foo/not_bar");
     61 const GURL kFallbackPatternNamespace("http://blah/fallback_pattern/*/bar");
     62 const GURL kFallbackPatternTestPositiveUrl(
     63     "http://blah/fallback_pattern/foo/bar");
     64 const GURL kFallbackPatternTestNegativeUrl(
     65     "http://blah/fallback_pattern/foo/not_bar");
     66 const GURL kOrigin(kManifestUrl.GetOrigin());
     67 
     68 const int kManifestEntryIdOffset = 100;
     69 const int kFallbackEntryIdOffset = 1000;
     70 
     71 const GURL kDefaultEntryUrl("http://blah/makecacheandgroup_default_entry");
     72 const int kDefaultEntrySize = 10;
     73 const int kDefaultEntryIdOffset = 12345;
     74 
     75 const int kMockQuota = 5000;
     76 
     77 // The Reinitialize test needs some http accessible resources to run,
     78 // we mock stuff inprocess for that.
     79 class MockHttpServer {
     80  public:
     81   static GURL GetMockUrl(const std::string& path) {
     82     return GURL("http://mockhost/" + path);
     83   }
     84 
     85   static net::URLRequestJob* CreateJob(
     86       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
     87     if (request->url().host() != "mockhost")
     88       return new net::URLRequestErrorJob(request, network_delegate, -100);
     89 
     90     std::string headers, body;
     91     GetMockResponse(request->url().path(), &headers, &body);
     92     return new net::URLRequestTestJob(
     93         request, network_delegate, headers, body, true);
     94   }
     95 
     96  private:
     97   static void GetMockResponse(const std::string& path,
     98                               std::string* headers,
     99                               std::string* body) {
    100     const char manifest_headers[] =
    101         "HTTP/1.1 200 OK\0"
    102         "Content-type: text/cache-manifest\0"
    103         "\0";
    104     const char page_headers[] =
    105         "HTTP/1.1 200 OK\0"
    106         "Content-type: text/html\0"
    107         "\0";
    108     const char not_found_headers[] =
    109         "HTTP/1.1 404 NOT FOUND\0"
    110         "\0";
    111 
    112     if (path == "/manifest") {
    113       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    114       (*body) = "CACHE MANIFEST\n";
    115     } else if (path == "/empty.html") {
    116       (*headers) = std::string(page_headers, arraysize(page_headers));
    117       (*body) = "";
    118     } else {
    119       (*headers) = std::string(not_found_headers,
    120                                arraysize(not_found_headers));
    121       (*body) = "";
    122     }
    123   }
    124 };
    125 
    126 class MockHttpServerJobFactory
    127     : public net::URLRequestJobFactory::ProtocolHandler {
    128  public:
    129   virtual net::URLRequestJob* MaybeCreateJob(
    130       net::URLRequest* request,
    131       net::NetworkDelegate* network_delegate) const OVERRIDE {
    132     return MockHttpServer::CreateJob(request, network_delegate);
    133   }
    134 };
    135 
    136 class IOThread : public base::Thread {
    137  public:
    138   explicit IOThread(const char* name)
    139       : base::Thread(name) {
    140   }
    141 
    142   virtual ~IOThread() {
    143     Stop();
    144   }
    145 
    146   net::URLRequestContext* request_context() {
    147     return request_context_.get();
    148   }
    149 
    150   virtual void Init() OVERRIDE {
    151     scoped_ptr<net::URLRequestJobFactoryImpl> factory(
    152         new net::URLRequestJobFactoryImpl());
    153     factory->SetProtocolHandler("http", new MockHttpServerJobFactory);
    154     job_factory_ = factory.Pass();
    155     request_context_.reset(new net::TestURLRequestContext());
    156     request_context_->set_job_factory(job_factory_.get());
    157     AppCacheInterceptor::EnsureRegistered();
    158   }
    159 
    160   virtual void CleanUp() OVERRIDE {
    161     request_context_.reset();
    162     job_factory_.reset();
    163   }
    164 
    165  private:
    166   scoped_ptr<net::URLRequestJobFactory> job_factory_;
    167   scoped_ptr<net::URLRequestContext> request_context_;
    168 };
    169 
    170 scoped_ptr<IOThread> io_thread;
    171 scoped_ptr<base::Thread> db_thread;
    172 
    173 }  // namespace
    174 
    175 class AppCacheStorageImplTest : public testing::Test {
    176  public:
    177   class MockStorageDelegate : public AppCacheStorage::Delegate {
    178    public:
    179     explicit MockStorageDelegate(AppCacheStorageImplTest* test)
    180         : loaded_cache_id_(0), stored_group_success_(false),
    181           would_exceed_quota_(false), obsoleted_success_(false),
    182           found_cache_id_(kAppCacheNoCacheId), test_(test) {
    183     }
    184 
    185     virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE {
    186       loaded_cache_ = cache;
    187       loaded_cache_id_ = cache_id;
    188       test_->ScheduleNextTask();
    189     }
    190 
    191     virtual void OnGroupLoaded(AppCacheGroup* group,
    192                                const GURL& manifest_url) OVERRIDE {
    193       loaded_group_ = group;
    194       loaded_manifest_url_ = manifest_url;
    195       loaded_groups_newest_cache_ = group ? group->newest_complete_cache()
    196                                           : NULL;
    197       test_->ScheduleNextTask();
    198     }
    199 
    200     virtual void OnGroupAndNewestCacheStored(
    201         AppCacheGroup* group, AppCache* newest_cache, bool success,
    202         bool would_exceed_quota) OVERRIDE {
    203       stored_group_ = group;
    204       stored_group_success_ = success;
    205       would_exceed_quota_ = would_exceed_quota;
    206       test_->ScheduleNextTask();
    207     }
    208 
    209     virtual void OnGroupMadeObsolete(AppCacheGroup* group,
    210                                      bool success,
    211                                      int response_code) OVERRIDE {
    212       obsoleted_group_ = group;
    213       obsoleted_success_ = success;
    214       test_->ScheduleNextTask();
    215     }
    216 
    217     virtual void OnMainResponseFound(const GURL& url,
    218                                      const AppCacheEntry& entry,
    219                                      const GURL& namespace_entry_url,
    220                                      const AppCacheEntry& fallback_entry,
    221                                      int64 cache_id,
    222                                      int64 group_id,
    223                                      const GURL& manifest_url) OVERRIDE {
    224       found_url_ = url;
    225       found_entry_ = entry;
    226       found_namespace_entry_url_ = namespace_entry_url;
    227       found_fallback_entry_ = fallback_entry;
    228       found_cache_id_ = cache_id;
    229       found_group_id_ = group_id;
    230       found_manifest_url_ = manifest_url;
    231       test_->ScheduleNextTask();
    232     }
    233 
    234     scoped_refptr<AppCache> loaded_cache_;
    235     int64 loaded_cache_id_;
    236     scoped_refptr<AppCacheGroup> loaded_group_;
    237     GURL loaded_manifest_url_;
    238     scoped_refptr<AppCache> loaded_groups_newest_cache_;
    239     scoped_refptr<AppCacheGroup> stored_group_;
    240     bool stored_group_success_;
    241     bool would_exceed_quota_;
    242     scoped_refptr<AppCacheGroup> obsoleted_group_;
    243     bool obsoleted_success_;
    244     GURL found_url_;
    245     AppCacheEntry found_entry_;
    246     GURL found_namespace_entry_url_;
    247     AppCacheEntry found_fallback_entry_;
    248     int64 found_cache_id_;
    249     int64 found_group_id_;
    250     GURL found_manifest_url_;
    251     AppCacheStorageImplTest* test_;
    252   };
    253 
    254   class MockQuotaManager : public storage::QuotaManager {
    255    public:
    256     MockQuotaManager()
    257         : QuotaManager(true /* is_incognito */,
    258                        base::FilePath(),
    259                        io_thread->message_loop_proxy().get(),
    260                        db_thread->message_loop_proxy().get(),
    261                        NULL),
    262           async_(false) {}
    263 
    264     virtual void GetUsageAndQuota(
    265         const GURL& origin,
    266         storage::StorageType type,
    267         const GetUsageAndQuotaCallback& callback) OVERRIDE {
    268       EXPECT_EQ(storage::kStorageTypeTemporary, type);
    269       if (async_) {
    270         base::MessageLoop::current()->PostTask(
    271             FROM_HERE,
    272             base::Bind(&MockQuotaManager::CallCallback,
    273                        base::Unretained(this),
    274                        callback));
    275         return;
    276       }
    277       CallCallback(callback);
    278     }
    279 
    280     void CallCallback(const GetUsageAndQuotaCallback& callback) {
    281       callback.Run(storage::kQuotaStatusOk, 0, kMockQuota);
    282     }
    283 
    284     bool async_;
    285 
    286    protected:
    287     virtual ~MockQuotaManager() {}
    288   };
    289 
    290   class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
    291    public:
    292     MockQuotaManagerProxy()
    293         : QuotaManagerProxy(NULL, NULL),
    294           notify_storage_accessed_count_(0),
    295           notify_storage_modified_count_(0),
    296           last_delta_(0),
    297           mock_manager_(new MockQuotaManager) {
    298       manager_ = mock_manager_.get();
    299     }
    300 
    301     virtual void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
    302                                        const GURL& origin,
    303                                        storage::StorageType type) OVERRIDE {
    304       EXPECT_EQ(storage::QuotaClient::kAppcache, client_id);
    305       EXPECT_EQ(storage::kStorageTypeTemporary, type);
    306       ++notify_storage_accessed_count_;
    307       last_origin_ = origin;
    308     }
    309 
    310     virtual void NotifyStorageModified(storage::QuotaClient::ID client_id,
    311                                        const GURL& origin,
    312                                        storage::StorageType type,
    313                                        int64 delta) OVERRIDE {
    314       EXPECT_EQ(storage::QuotaClient::kAppcache, client_id);
    315       EXPECT_EQ(storage::kStorageTypeTemporary, type);
    316       ++notify_storage_modified_count_;
    317       last_origin_ = origin;
    318       last_delta_ = delta;
    319     }
    320 
    321     // Not needed for our tests.
    322     virtual void RegisterClient(storage::QuotaClient* client) OVERRIDE {}
    323     virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
    324     virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
    325     virtual void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
    326                                       const GURL& origin,
    327                                       storage::StorageType type,
    328                                       bool enabled) OVERRIDE {}
    329     virtual void GetUsageAndQuota(
    330         base::SequencedTaskRunner* original_task_runner,
    331         const GURL& origin,
    332         storage::StorageType type,
    333         const GetUsageAndQuotaCallback& callback) OVERRIDE {}
    334 
    335     int notify_storage_accessed_count_;
    336     int notify_storage_modified_count_;
    337     GURL last_origin_;
    338     int last_delta_;
    339     scoped_refptr<MockQuotaManager> mock_manager_;
    340 
    341    protected:
    342     virtual ~MockQuotaManagerProxy() {}
    343   };
    344 
    345   template <class Method>
    346   void RunMethod(Method method) {
    347     (this->*method)();
    348   }
    349 
    350   // Helper callback to run a test on our io_thread. The io_thread is spun up
    351   // once and reused for all tests.
    352   template <class Method>
    353   void MethodWrapper(Method method) {
    354     SetUpTest();
    355 
    356     // Ensure InitTask execution prior to conducting a test.
    357     FlushDbThreadTasks();
    358 
    359     // We also have to wait for InitTask completion call to be performed
    360     // on the IO thread prior to running the test. Its guaranteed to be
    361     // queued by this time.
    362     base::MessageLoop::current()->PostTask(
    363         FROM_HERE,
    364         base::Bind(&AppCacheStorageImplTest::RunMethod<Method>,
    365                    base::Unretained(this),
    366                    method));
    367   }
    368 
    369   static void SetUpTestCase() {
    370     // We start both threads as TYPE_IO because we also use the db_thead
    371     // for the disk_cache which needs to be of TYPE_IO.
    372     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
    373     io_thread.reset(new IOThread("AppCacheTest.IOThread"));
    374     ASSERT_TRUE(io_thread->StartWithOptions(options));
    375     db_thread.reset(new base::Thread("AppCacheTest::DBThread"));
    376     ASSERT_TRUE(db_thread->StartWithOptions(options));
    377   }
    378 
    379   static void TearDownTestCase() {
    380     io_thread.reset(NULL);
    381     db_thread.reset(NULL);
    382   }
    383 
    384   // Test harness --------------------------------------------------
    385 
    386   AppCacheStorageImplTest() {
    387   }
    388 
    389   template <class Method>
    390   void RunTestOnIOThread(Method method) {
    391     test_finished_event_ .reset(new base::WaitableEvent(false, false));
    392     io_thread->message_loop()->PostTask(
    393         FROM_HERE, base::Bind(&AppCacheStorageImplTest::MethodWrapper<Method>,
    394                               base::Unretained(this), method));
    395     test_finished_event_->Wait();
    396   }
    397 
    398   void SetUpTest() {
    399     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    400     service_.reset(new AppCacheServiceImpl(NULL));
    401     service_->Initialize(base::FilePath(), db_thread->task_runner(), NULL);
    402     mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
    403     service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
    404     delegate_.reset(new MockStorageDelegate(this));
    405   }
    406 
    407   void TearDownTest() {
    408     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    409     storage()->CancelDelegateCallbacks(delegate());
    410     group_ = NULL;
    411     cache_ = NULL;
    412     cache2_ = NULL;
    413     mock_quota_manager_proxy_ = NULL;
    414     delegate_.reset();
    415     service_.reset();
    416     FlushDbThreadTasks();
    417   }
    418 
    419   void TestFinished() {
    420     // We unwind the stack prior to finishing up to let stack
    421     // based objects get deleted.
    422     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    423     base::MessageLoop::current()->PostTask(
    424         FROM_HERE,
    425         base::Bind(&AppCacheStorageImplTest::TestFinishedUnwound,
    426                    base::Unretained(this)));
    427   }
    428 
    429   void TestFinishedUnwound() {
    430     TearDownTest();
    431     test_finished_event_->Signal();
    432   }
    433 
    434   void PushNextTask(const base::Closure& task) {
    435     task_stack_.push(task);
    436   }
    437 
    438   void ScheduleNextTask() {
    439     DCHECK(base::MessageLoop::current() == io_thread->message_loop());
    440     if (task_stack_.empty()) {
    441       return;
    442     }
    443     base::MessageLoop::current()->PostTask(FROM_HERE, task_stack_.top());
    444     task_stack_.pop();
    445   }
    446 
    447   static void SignalEvent(base::WaitableEvent* event) {
    448     event->Signal();
    449   }
    450 
    451   void FlushDbThreadTasks() {
    452     // We pump a task thru the db thread to ensure any tasks previously
    453     // scheduled on that thread have been performed prior to return.
    454     base::WaitableEvent event(false, false);
    455     db_thread->message_loop()->PostTask(
    456         FROM_HERE, base::Bind(&AppCacheStorageImplTest::SignalEvent, &event));
    457     event.Wait();
    458   }
    459 
    460   // LoadCache_Miss ----------------------------------------------------
    461 
    462   void LoadCache_Miss() {
    463     // Attempt to load a cache that doesn't exist. Should
    464     // complete asynchronously.
    465     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Miss,
    466                             base::Unretained(this)));
    467 
    468     storage()->LoadCache(111, delegate());
    469     EXPECT_NE(111, delegate()->loaded_cache_id_);
    470   }
    471 
    472   void Verify_LoadCache_Miss() {
    473     EXPECT_EQ(111, delegate()->loaded_cache_id_);
    474     EXPECT_FALSE(delegate()->loaded_cache_.get());
    475     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    476     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    477     TestFinished();
    478   }
    479 
    480   // LoadCache_NearHit -------------------------------------------------
    481 
    482   void LoadCache_NearHit() {
    483     // Attempt to load a cache that is currently in use
    484     // and does not require loading from storage. This
    485     // load should complete syncly.
    486 
    487     // Setup some preconditions. Make an 'unstored' cache for
    488     // us to load. The ctor should put it in the working set.
    489     int64 cache_id = storage()->NewCacheId();
    490     scoped_refptr<AppCache> cache(new AppCache(storage(), cache_id));
    491 
    492     // Conduct the test.
    493     storage()->LoadCache(cache_id, delegate());
    494     EXPECT_EQ(cache_id, delegate()->loaded_cache_id_);
    495     EXPECT_EQ(cache.get(), delegate()->loaded_cache_.get());
    496     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    497     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    498     TestFinished();
    499   }
    500 
    501   // CreateGroup  --------------------------------------------
    502 
    503   void CreateGroupInEmptyOrigin() {
    504     // Attempt to load a group that doesn't exist, one should
    505     // be created for us, but not stored.
    506 
    507     // Since the origin has no groups, the storage class will respond
    508     // syncly.
    509     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    510     Verify_CreateGroup();
    511   }
    512 
    513   void CreateGroupInPopulatedOrigin() {
    514     // Attempt to load a group that doesn't exist, one should
    515     // be created for us, but not stored.
    516     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_CreateGroup,
    517                             base::Unretained(this)));
    518 
    519     // Since the origin has groups, storage class will have to
    520     // consult the database and completion will be async.
    521     storage()->usage_map_[kOrigin] = kDefaultEntrySize;
    522 
    523     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    524     EXPECT_FALSE(delegate()->loaded_group_.get());
    525   }
    526 
    527   void Verify_CreateGroup() {
    528     EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
    529     EXPECT_TRUE(delegate()->loaded_group_.get());
    530     EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
    531     EXPECT_FALSE(delegate()->loaded_group_->newest_complete_cache());
    532 
    533     // Should not have been stored in the database.
    534     AppCacheDatabase::GroupRecord record;
    535     EXPECT_FALSE(database()->FindGroup(
    536         delegate()->loaded_group_->group_id(), &record));
    537 
    538     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    539     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    540 
    541     TestFinished();
    542   }
    543 
    544   // LoadGroupAndCache_FarHit  --------------------------------------
    545 
    546   void LoadGroupAndCache_FarHit() {
    547     // Attempt to load a cache that is not currently in use
    548     // and does require loading from disk. This
    549     // load should complete asynchronously.
    550     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadCache_Far_Hit,
    551                             base::Unretained(this)));
    552 
    553     // Setup some preconditions. Create a group and newest cache that
    554     // appear to be "stored" and "not currently in use".
    555     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    556     group_ = NULL;
    557     cache_ = NULL;
    558 
    559     // Conduct the cache load test, completes async
    560     storage()->LoadCache(1, delegate());
    561   }
    562 
    563   void Verify_LoadCache_Far_Hit() {
    564     EXPECT_TRUE(delegate()->loaded_cache_.get());
    565     EXPECT_TRUE(delegate()->loaded_cache_->HasOneRef());
    566     EXPECT_EQ(1, delegate()->loaded_cache_id_);
    567 
    568     // The group should also have been loaded.
    569     EXPECT_TRUE(delegate()->loaded_cache_->owning_group());
    570     EXPECT_TRUE(delegate()->loaded_cache_->owning_group()->HasOneRef());
    571     EXPECT_EQ(1, delegate()->loaded_cache_->owning_group()->group_id());
    572 
    573     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    574     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    575 
    576     // Drop things from the working set.
    577     delegate()->loaded_cache_ = NULL;
    578     EXPECT_FALSE(delegate()->loaded_group_.get());
    579 
    580     // Conduct the group load test, also complete asynchronously.
    581     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_LoadGroup_Far_Hit,
    582                             base::Unretained(this)));
    583 
    584     storage()->LoadOrCreateGroup(kManifestUrl, delegate());
    585   }
    586 
    587   void Verify_LoadGroup_Far_Hit() {
    588     EXPECT_TRUE(delegate()->loaded_group_.get());
    589     EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
    590     EXPECT_TRUE(delegate()->loaded_group_->newest_complete_cache());
    591     delegate()->loaded_groups_newest_cache_ = NULL;
    592     EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
    593     EXPECT_EQ(2, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    594     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    595     TestFinished();
    596   }
    597 
    598   // StoreNewGroup  --------------------------------------
    599 
    600   void StoreNewGroup() {
    601     // Store a group and its newest cache. Should complete asynchronously.
    602     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreNewGroup,
    603                             base::Unretained(this)));
    604 
    605     // Setup some preconditions. Create a group and newest cache that
    606     // appear to be "unstored".
    607     group_ = new AppCacheGroup(
    608         storage(), kManifestUrl, storage()->NewGroupId());
    609     cache_ = new AppCache(storage(), storage()->NewCacheId());
    610     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1,
    611                                               kDefaultEntrySize));
    612     // Hold a ref to the cache simulate the UpdateJob holding that ref,
    613     // and hold a ref to the group to simulate the CacheHost holding that ref.
    614 
    615     // Have the quota manager retrun asynchronously for this test.
    616     mock_quota_manager_proxy_->mock_manager_->async_ = true;
    617 
    618     // Conduct the store test.
    619     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    620     EXPECT_FALSE(delegate()->stored_group_success_);
    621   }
    622 
    623   void Verify_StoreNewGroup() {
    624     EXPECT_TRUE(delegate()->stored_group_success_);
    625     EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
    626     EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
    627     EXPECT_TRUE(cache_->is_complete());
    628 
    629     // Should have been stored in the database.
    630     AppCacheDatabase::GroupRecord group_record;
    631     AppCacheDatabase::CacheRecord cache_record;
    632     EXPECT_TRUE(database()->FindGroup(group_->group_id(), &group_record));
    633     EXPECT_TRUE(database()->FindCache(cache_->cache_id(), &cache_record));
    634 
    635     // Verify quota bookkeeping
    636     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    637     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    638     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    639     EXPECT_EQ(kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
    640 
    641     TestFinished();
    642   }
    643 
    644   // StoreExistingGroup  --------------------------------------
    645 
    646   void StoreExistingGroup() {
    647     // Store a group and its newest cache. Should complete asynchronously.
    648     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_StoreExistingGroup,
    649                             base::Unretained(this)));
    650 
    651     // Setup some preconditions. Create a group and old complete cache
    652     // that appear to be "stored"
    653     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    654     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    655 
    656     // And a newest unstored complete cache.
    657     cache2_ = new AppCache(storage(), 2);
    658     cache2_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1,
    659                                                kDefaultEntrySize + 100));
    660 
    661     // Conduct the test.
    662     storage()->StoreGroupAndNewestCache(
    663         group_.get(), cache2_.get(), delegate());
    664     EXPECT_FALSE(delegate()->stored_group_success_);
    665   }
    666 
    667   void Verify_StoreExistingGroup() {
    668     EXPECT_TRUE(delegate()->stored_group_success_);
    669     EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
    670     EXPECT_EQ(cache2_.get(), group_->newest_complete_cache());
    671     EXPECT_TRUE(cache2_->is_complete());
    672 
    673     // The new cache should have been stored in the database.
    674     AppCacheDatabase::GroupRecord group_record;
    675     AppCacheDatabase::CacheRecord cache_record;
    676     EXPECT_TRUE(database()->FindGroup(1, &group_record));
    677     EXPECT_TRUE(database()->FindCache(2, &cache_record));
    678 
    679     // The old cache should have been deleted
    680     EXPECT_FALSE(database()->FindCache(1, &cache_record));
    681 
    682     // Verify quota bookkeeping
    683     EXPECT_EQ(kDefaultEntrySize + 100, storage()->usage_map_[kOrigin]);
    684     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    685     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    686     EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
    687 
    688     TestFinished();
    689   }
    690 
    691   // StoreExistingGroupExistingCache  -------------------------------
    692 
    693   void StoreExistingGroupExistingCache() {
    694     // Store a group with updates to its existing newest complete cache.
    695     // Setup some preconditions. Create a group and a complete cache that
    696     // appear to be "stored".
    697 
    698     // Setup some preconditions. Create a group and old complete cache
    699     // that appear to be "stored"
    700     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    701     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    702 
    703     // Change the cache.
    704     base::Time now = base::Time::Now();
    705     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::MASTER, 1, 100));
    706     cache_->set_update_time(now);
    707 
    708     PushNextTask(base::Bind(
    709         &AppCacheStorageImplTest::Verify_StoreExistingGroupExistingCache,
    710         base::Unretained(this), now));
    711 
    712     // Conduct the test.
    713     EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
    714     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    715     EXPECT_FALSE(delegate()->stored_group_success_);
    716   }
    717 
    718   void Verify_StoreExistingGroupExistingCache(
    719       base::Time expected_update_time) {
    720     EXPECT_TRUE(delegate()->stored_group_success_);
    721     EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
    722 
    723     AppCacheDatabase::CacheRecord cache_record;
    724     EXPECT_TRUE(database()->FindCache(1, &cache_record));
    725     EXPECT_EQ(1, cache_record.cache_id);
    726     EXPECT_EQ(1, cache_record.group_id);
    727     EXPECT_FALSE(cache_record.online_wildcard);
    728     EXPECT_TRUE(expected_update_time == cache_record.update_time);
    729     EXPECT_EQ(100 + kDefaultEntrySize, cache_record.cache_size);
    730 
    731     std::vector<AppCacheDatabase::EntryRecord> entry_records;
    732     EXPECT_TRUE(database()->FindEntriesForCache(1, &entry_records));
    733     EXPECT_EQ(2U, entry_records.size());
    734     if (entry_records[0].url == kDefaultEntryUrl)
    735       entry_records.erase(entry_records.begin());
    736     EXPECT_EQ(1 , entry_records[0].cache_id);
    737     EXPECT_EQ(kEntryUrl, entry_records[0].url);
    738     EXPECT_EQ(AppCacheEntry::MASTER, entry_records[0].flags);
    739     EXPECT_EQ(1, entry_records[0].response_id);
    740     EXPECT_EQ(100, entry_records[0].response_size);
    741 
    742     // Verify quota bookkeeping
    743     EXPECT_EQ(100 + kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    744     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    745     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    746     EXPECT_EQ(100, mock_quota_manager_proxy_->last_delta_);
    747 
    748     TestFinished();
    749   }
    750 
    751   // FailStoreGroup  --------------------------------------
    752 
    753   void FailStoreGroup() {
    754     // Store a group and its newest cache. Should complete asynchronously.
    755     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FailStoreGroup,
    756                             base::Unretained(this)));
    757 
    758     // Setup some preconditions. Create a group and newest cache that
    759     // appear to be "unstored" and big enough to exceed the 5M limit.
    760     const int64 kTooBig = 10 * 1024 * 1024;  // 10M
    761     group_ = new AppCacheGroup(
    762         storage(), kManifestUrl, storage()->NewGroupId());
    763     cache_ = new AppCache(storage(), storage()->NewCacheId());
    764     cache_->AddEntry(kManifestUrl,
    765                      AppCacheEntry(AppCacheEntry::MANIFEST, 1, kTooBig));
    766     // Hold a ref to the cache simulate the UpdateJob holding that ref,
    767     // and hold a ref to the group to simulate the CacheHost holding that ref.
    768 
    769     // Conduct the store test.
    770     storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
    771     EXPECT_FALSE(delegate()->stored_group_success_);  // Expected to be async.
    772   }
    773 
    774   void Verify_FailStoreGroup() {
    775     EXPECT_FALSE(delegate()->stored_group_success_);
    776     EXPECT_TRUE(delegate()->would_exceed_quota_);
    777 
    778     // Should not have been stored in the database.
    779     AppCacheDatabase::GroupRecord group_record;
    780     AppCacheDatabase::CacheRecord cache_record;
    781     EXPECT_FALSE(database()->FindGroup(group_->group_id(), &group_record));
    782     EXPECT_FALSE(database()->FindCache(cache_->cache_id(), &cache_record));
    783 
    784     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
    785     EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
    786 
    787     TestFinished();
    788   }
    789 
    790   // MakeGroupObsolete  -------------------------------
    791 
    792   void MakeGroupObsolete() {
    793     // Make a group obsolete, should complete asynchronously.
    794     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_MakeGroupObsolete,
    795                             base::Unretained(this)));
    796 
    797     // Setup some preconditions. Create a group and newest cache that
    798     // appears to be "stored" and "currently in use".
    799     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    800     EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
    801 
    802     // Also insert some related records.
    803     AppCacheDatabase::EntryRecord entry_record;
    804     entry_record.cache_id = 1;
    805     entry_record.flags = AppCacheEntry::FALLBACK;
    806     entry_record.response_id = 1;
    807     entry_record.url = kEntryUrl;
    808     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    809 
    810     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
    811     fallback_namespace_record.cache_id = 1;
    812     fallback_namespace_record.namespace_.target_url = kEntryUrl;
    813     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
    814     fallback_namespace_record.origin = kManifestUrl.GetOrigin();
    815     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
    816 
    817     AppCacheDatabase::OnlineWhiteListRecord online_whitelist_record;
    818     online_whitelist_record.cache_id = 1;
    819     online_whitelist_record.namespace_url = kOnlineNamespace;
    820     EXPECT_TRUE(database()->InsertOnlineWhiteList(&online_whitelist_record));
    821 
    822     // Conduct the test.
    823     storage()->MakeGroupObsolete(group_.get(), delegate(), 0);
    824     EXPECT_FALSE(group_->is_obsolete());
    825   }
    826 
    827   void Verify_MakeGroupObsolete() {
    828     EXPECT_TRUE(delegate()->obsoleted_success_);
    829     EXPECT_EQ(group_.get(), delegate()->obsoleted_group_.get());
    830     EXPECT_TRUE(group_->is_obsolete());
    831     EXPECT_TRUE(storage()->usage_map_.empty());
    832 
    833     // The cache and group have been deleted from the database.
    834     AppCacheDatabase::GroupRecord group_record;
    835     AppCacheDatabase::CacheRecord cache_record;
    836     EXPECT_FALSE(database()->FindGroup(1, &group_record));
    837     EXPECT_FALSE(database()->FindCache(1, &cache_record));
    838 
    839     // The related records should have been deleted too.
    840     std::vector<AppCacheDatabase::EntryRecord> entry_records;
    841     database()->FindEntriesForCache(1, &entry_records);
    842     EXPECT_TRUE(entry_records.empty());
    843     std::vector<AppCacheDatabase::NamespaceRecord> intercept_records;
    844     std::vector<AppCacheDatabase::NamespaceRecord> fallback_records;
    845     database()->FindNamespacesForCache(
    846         1, &intercept_records, &fallback_records);
    847     EXPECT_TRUE(fallback_records.empty());
    848     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelist_records;
    849     database()->FindOnlineWhiteListForCache(1, &whitelist_records);
    850     EXPECT_TRUE(whitelist_records.empty());
    851 
    852     // Verify quota bookkeeping
    853     EXPECT_TRUE(storage()->usage_map_.empty());
    854     EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
    855     EXPECT_EQ(kOrigin, mock_quota_manager_proxy_->last_origin_);
    856     EXPECT_EQ(-kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
    857 
    858     TestFinished();
    859   }
    860 
    861   // MarkEntryAsForeign  -------------------------------
    862 
    863   void MarkEntryAsForeign() {
    864     // Setup some preconditions. Create a cache with an entry
    865     // in storage and in the working set.
    866     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    867     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
    868     AppCacheDatabase::EntryRecord entry_record;
    869     entry_record.cache_id = 1;
    870     entry_record.url = kEntryUrl;
    871     entry_record.flags = AppCacheEntry::EXPLICIT;
    872     entry_record.response_id = 0;
    873     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    874     EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
    875 
    876     // Conduct the test.
    877     storage()->MarkEntryAsForeign(kEntryUrl, 1);
    878 
    879     // The entry in the working set should have been updated syncly.
    880     EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsForeign());
    881     EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsExplicit());
    882 
    883     // And the entry in storage should also be updated, but that
    884     // happens asynchronously on the db thread.
    885     FlushDbThreadTasks();
    886     AppCacheDatabase::EntryRecord entry_record2;
    887     EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record2));
    888     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
    889               entry_record2.flags);
    890     TestFinished();
    891   }
    892 
    893   // MarkEntryAsForeignWithLoadInProgress  -------------------------------
    894 
    895   void MarkEntryAsForeignWithLoadInProgress() {
    896     PushNextTask(base::Bind(
    897        &AppCacheStorageImplTest::Verify_MarkEntryAsForeignWithLoadInProgress,
    898        base::Unretained(this)));
    899 
    900     // Setup some preconditions. Create a cache with an entry
    901     // in storage, but not in the working set.
    902     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
    903     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
    904     AppCacheDatabase::EntryRecord entry_record;
    905     entry_record.cache_id = 1;
    906     entry_record.url = kEntryUrl;
    907     entry_record.flags = AppCacheEntry::EXPLICIT;
    908     entry_record.response_id = 0;
    909     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    910     EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
    911     EXPECT_TRUE(cache_->HasOneRef());
    912     cache_ = NULL;
    913     group_ = NULL;
    914 
    915     // Conduct the test, start a cache load, and prior to completion
    916     // of that load, mark the entry as foreign.
    917     storage()->LoadCache(1, delegate());
    918     storage()->MarkEntryAsForeign(kEntryUrl, 1);
    919   }
    920 
    921   void Verify_MarkEntryAsForeignWithLoadInProgress() {
    922     EXPECT_EQ(1, delegate()->loaded_cache_id_);
    923     EXPECT_TRUE(delegate()->loaded_cache_.get());
    924 
    925     // The entry in the working set should have been updated upon load.
    926     EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsForeign());
    927     EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsExplicit());
    928 
    929     // And the entry in storage should also be updated.
    930     FlushDbThreadTasks();
    931     AppCacheDatabase::EntryRecord entry_record;
    932     EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record));
    933     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
    934               entry_record.flags);
    935     TestFinished();
    936   }
    937 
    938   // FindNoMainResponse  -------------------------------
    939 
    940   void FindNoMainResponse() {
    941     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
    942                             base::Unretained(this)));
    943 
    944     // Conduct the test.
    945     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
    946     EXPECT_NE(kEntryUrl, delegate()->found_url_);
    947   }
    948 
    949   void Verify_FindNoMainResponse() {
    950     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
    951     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
    952     EXPECT_EQ(kAppCacheNoCacheId, delegate()->found_cache_id_);
    953     EXPECT_EQ(kAppCacheNoResponseId, delegate()->found_entry_.response_id());
    954     EXPECT_EQ(kAppCacheNoResponseId,
    955         delegate()->found_fallback_entry_.response_id());
    956     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
    957     EXPECT_EQ(0, delegate()->found_entry_.types());
    958     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
    959     TestFinished();
    960   }
    961 
    962   // BasicFindMainResponse  -------------------------------
    963 
    964   void BasicFindMainResponseInDatabase() {
    965     BasicFindMainResponse(true);
    966   }
    967 
    968   void BasicFindMainResponseInWorkingSet() {
    969     BasicFindMainResponse(false);
    970   }
    971 
    972   void BasicFindMainResponse(bool drop_from_working_set) {
    973     PushNextTask(base::Bind(
    974         &AppCacheStorageImplTest::Verify_BasicFindMainResponse,
    975         base::Unretained(this)));
    976 
    977     // Setup some preconditions. Create a complete cache with an entry
    978     // in storage.
    979     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
    980     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1));
    981     AppCacheDatabase::EntryRecord entry_record;
    982     entry_record.cache_id = 1;
    983     entry_record.url = kEntryUrl;
    984     entry_record.flags = AppCacheEntry::EXPLICIT;
    985     entry_record.response_id = 1;
    986     EXPECT_TRUE(database()->InsertEntry(&entry_record));
    987 
    988     // Optionally drop the cache/group pair from the working set.
    989     if (drop_from_working_set) {
    990       EXPECT_TRUE(cache_->HasOneRef());
    991       cache_ = NULL;
    992       EXPECT_TRUE(group_->HasOneRef());
    993       group_ = NULL;
    994     }
    995 
    996     // Conduct the test.
    997     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
    998     EXPECT_NE(kEntryUrl,  delegate()->found_url_);
    999   }
   1000 
   1001   void Verify_BasicFindMainResponse() {
   1002     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1003     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1004     EXPECT_EQ(1, delegate()->found_cache_id_);
   1005     EXPECT_EQ(2, delegate()->found_group_id_);
   1006     EXPECT_EQ(1, delegate()->found_entry_.response_id());
   1007     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1008     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1009     TestFinished();
   1010   }
   1011 
   1012   // BasicFindMainFallbackResponse  -------------------------------
   1013 
   1014   void BasicFindMainFallbackResponseInDatabase() {
   1015     BasicFindMainFallbackResponse(true);
   1016   }
   1017 
   1018   void BasicFindMainFallbackResponseInWorkingSet() {
   1019     BasicFindMainFallbackResponse(false);
   1020   }
   1021 
   1022   void BasicFindMainFallbackResponse(bool drop_from_working_set) {
   1023     PushNextTask(base::Bind(
   1024         &AppCacheStorageImplTest::Verify_BasicFindMainFallbackResponse,
   1025         base::Unretained(this)));
   1026 
   1027     // Setup some preconditions. Create a complete cache with a
   1028     // fallback namespace and entry.
   1029     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1030     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
   1031     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
   1032     cache_->fallback_namespaces_.push_back(
   1033         AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
   1034                   kFallbackNamespace2,
   1035                   kEntryUrl2,
   1036                   false));
   1037     cache_->fallback_namespaces_.push_back(
   1038         AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
   1039                   kFallbackNamespace,
   1040                   kEntryUrl,
   1041                   false));
   1042     AppCacheDatabase::CacheRecord cache_record;
   1043     std::vector<AppCacheDatabase::EntryRecord> entries;
   1044     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1045     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1046     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1047     cache_->ToDatabaseRecords(group_.get(),
   1048                               &cache_record,
   1049                               &entries,
   1050                               &intercepts,
   1051                               &fallbacks,
   1052                               &whitelists);
   1053 
   1054     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1055         entries.begin();
   1056     while (iter != entries.end()) {
   1057       // MakeCacheAndGroup has inserted the default entry record already.
   1058       if (iter->url != kDefaultEntryUrl)
   1059         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1060       ++iter;
   1061     }
   1062 
   1063     EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
   1064     EXPECT_TRUE(database()->InsertOnlineWhiteListRecords(whitelists));
   1065     if (drop_from_working_set) {
   1066       EXPECT_TRUE(cache_->HasOneRef());
   1067       cache_ = NULL;
   1068       EXPECT_TRUE(group_->HasOneRef());
   1069       group_ = NULL;
   1070     }
   1071 
   1072     // Conduct the test. The test url is in both fallback namespace urls,
   1073     // but should match the longer of the two.
   1074     storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
   1075     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
   1076   }
   1077 
   1078   void Verify_BasicFindMainFallbackResponse() {
   1079     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
   1080     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1081     EXPECT_EQ(1, delegate()->found_cache_id_);
   1082     EXPECT_EQ(2, delegate()->found_group_id_);
   1083     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1084     EXPECT_EQ(2, delegate()->found_fallback_entry_.response_id());
   1085     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1086     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1087     TestFinished();
   1088   }
   1089 
   1090   // BasicFindMainInterceptResponse  -------------------------------
   1091 
   1092   void BasicFindMainInterceptResponseInDatabase() {
   1093     BasicFindMainInterceptResponse(true);
   1094   }
   1095 
   1096   void BasicFindMainInterceptResponseInWorkingSet() {
   1097     BasicFindMainInterceptResponse(false);
   1098   }
   1099 
   1100   void BasicFindMainInterceptResponse(bool drop_from_working_set) {
   1101     PushNextTask(base::Bind(
   1102         &AppCacheStorageImplTest::Verify_BasicFindMainInterceptResponse,
   1103         base::Unretained(this)));
   1104 
   1105     // Setup some preconditions. Create a complete cache with an
   1106     // intercept namespace and entry.
   1107     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1108     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
   1109     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::INTERCEPT, 2));
   1110     cache_->intercept_namespaces_.push_back(
   1111         AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace2,
   1112                   kEntryUrl2, false));
   1113     cache_->intercept_namespaces_.push_back(
   1114         AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
   1115                   kEntryUrl, false));
   1116     AppCacheDatabase::CacheRecord cache_record;
   1117     std::vector<AppCacheDatabase::EntryRecord> entries;
   1118     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1119     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1120     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1121     cache_->ToDatabaseRecords(group_.get(),
   1122                               &cache_record,
   1123                               &entries,
   1124                               &intercepts,
   1125                               &fallbacks,
   1126                               &whitelists);
   1127 
   1128     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1129         entries.begin();
   1130     while (iter != entries.end()) {
   1131       // MakeCacheAndGroup has inserted  the default entry record already
   1132       if (iter->url != kDefaultEntryUrl)
   1133         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1134       ++iter;
   1135     }
   1136 
   1137     EXPECT_TRUE(database()->InsertNamespaceRecords(intercepts));
   1138     EXPECT_TRUE(database()->InsertOnlineWhiteListRecords(whitelists));
   1139     if (drop_from_working_set) {
   1140       EXPECT_TRUE(cache_->HasOneRef());
   1141       cache_ = NULL;
   1142       EXPECT_TRUE(group_->HasOneRef());
   1143       group_ = NULL;
   1144     }
   1145 
   1146     // Conduct the test. The test url is in both intercept namespaces,
   1147     // but should match the longer of the two.
   1148     storage()->FindResponseForMainRequest(
   1149         kInterceptTestUrl, GURL(), delegate());
   1150     EXPECT_NE(kInterceptTestUrl, delegate()->found_url_);
   1151   }
   1152 
   1153   void Verify_BasicFindMainInterceptResponse() {
   1154     EXPECT_EQ(kInterceptTestUrl, delegate()->found_url_);
   1155     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1156     EXPECT_EQ(1, delegate()->found_cache_id_);
   1157     EXPECT_EQ(2, delegate()->found_group_id_);
   1158     EXPECT_EQ(2, delegate()->found_entry_.response_id());
   1159     EXPECT_TRUE(delegate()->found_entry_.IsIntercept());
   1160     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1161     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1162     TestFinished();
   1163   }
   1164 
   1165   // FindInterceptPatternMatch ----------------------------------------
   1166 
   1167   void FindInterceptPatternMatchInDatabase() {
   1168     FindInterceptPatternMatch(true);
   1169   }
   1170 
   1171   void FindInterceptPatternMatchInWorkingSet() {
   1172     FindInterceptPatternMatch(false);
   1173   }
   1174 
   1175   void FindInterceptPatternMatch(bool drop_from_working_set) {
   1176     // Setup some preconditions. Create a complete cache with an
   1177     // pattern matching intercept namespace and entry.
   1178     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1179     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
   1180     cache_->intercept_namespaces_.push_back(
   1181         AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
   1182             kInterceptPatternNamespace, kEntryUrl, true));
   1183     AppCacheDatabase::CacheRecord cache_record;
   1184     std::vector<AppCacheDatabase::EntryRecord> entries;
   1185     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1186     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1187     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1188     cache_->ToDatabaseRecords(group_.get(),
   1189                               &cache_record,
   1190                               &entries,
   1191                               &intercepts,
   1192                               &fallbacks,
   1193                               &whitelists);
   1194 
   1195     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1196         entries.begin();
   1197     while (iter != entries.end()) {
   1198       // MakeCacheAndGroup has inserted  the default entry record already
   1199       if (iter->url != kDefaultEntryUrl)
   1200         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1201       ++iter;
   1202     }
   1203 
   1204     EXPECT_TRUE(database()->InsertNamespaceRecords(intercepts));
   1205     if (drop_from_working_set) {
   1206       EXPECT_TRUE(cache_->HasOneRef());
   1207       cache_ = NULL;
   1208       EXPECT_TRUE(group_->HasOneRef());
   1209       group_ = NULL;
   1210     }
   1211 
   1212     // First test something that does not match the pattern.
   1213     PushNextTask(base::Bind(
   1214         &AppCacheStorageImplTest::Verify_FindInterceptPatternMatchNegative,
   1215         base::Unretained(this)));
   1216     storage()->FindResponseForMainRequest(
   1217         kInterceptPatternTestNegativeUrl, GURL(), delegate());
   1218     EXPECT_EQ(GURL(), delegate()->found_url_);  // Is always async.
   1219   }
   1220 
   1221   void Verify_FindInterceptPatternMatchNegative() {
   1222     EXPECT_EQ(kInterceptPatternTestNegativeUrl, delegate()->found_url_);
   1223     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1224     EXPECT_EQ(kAppCacheNoCacheId, delegate()->found_cache_id_);
   1225     EXPECT_EQ(kAppCacheNoResponseId, delegate()->found_entry_.response_id());
   1226     EXPECT_EQ(kAppCacheNoResponseId,
   1227         delegate()->found_fallback_entry_.response_id());
   1228     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1229     EXPECT_EQ(0, delegate()->found_entry_.types());
   1230     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1231 
   1232     // Then test something that matches.
   1233     PushNextTask(base::Bind(
   1234         &AppCacheStorageImplTest::Verify_FindInterceptPatternMatchPositive,
   1235         base::Unretained(this)));
   1236     storage()->FindResponseForMainRequest(
   1237         kInterceptPatternTestPositiveUrl, GURL(), delegate());
   1238   }
   1239 
   1240   void Verify_FindInterceptPatternMatchPositive() {
   1241     EXPECT_EQ(kInterceptPatternTestPositiveUrl, delegate()->found_url_);
   1242     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1243     EXPECT_EQ(1, delegate()->found_cache_id_);
   1244     EXPECT_EQ(2, delegate()->found_group_id_);
   1245     EXPECT_EQ(1, delegate()->found_entry_.response_id());
   1246     EXPECT_TRUE(delegate()->found_entry_.IsIntercept());
   1247     EXPECT_EQ(kEntryUrl, delegate()->found_namespace_entry_url_);
   1248     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1249     TestFinished();
   1250   }
   1251 
   1252   // FindFallbackPatternMatch  -------------------------------
   1253 
   1254   void FindFallbackPatternMatchInDatabase() {
   1255     FindFallbackPatternMatch(true);
   1256   }
   1257 
   1258   void FindFallbackPatternMatchInWorkingSet() {
   1259     FindFallbackPatternMatch(false);
   1260   }
   1261 
   1262   void FindFallbackPatternMatch(bool drop_from_working_set) {
   1263     // Setup some preconditions. Create a complete cache with a
   1264     // pattern matching fallback namespace and entry.
   1265     MakeCacheAndGroup(kManifestUrl, 2, 1, true);
   1266     cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
   1267     cache_->fallback_namespaces_.push_back(
   1268         AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
   1269             kFallbackPatternNamespace, kEntryUrl, true));
   1270     AppCacheDatabase::CacheRecord cache_record;
   1271     std::vector<AppCacheDatabase::EntryRecord> entries;
   1272     std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
   1273     std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
   1274     std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists;
   1275     cache_->ToDatabaseRecords(group_.get(),
   1276                               &cache_record,
   1277                               &entries,
   1278                               &intercepts,
   1279                               &fallbacks,
   1280                               &whitelists);
   1281 
   1282     std::vector<AppCacheDatabase::EntryRecord>::const_iterator iter =
   1283         entries.begin();
   1284     while (iter != entries.end()) {
   1285       // MakeCacheAndGroup has inserted the default entry record already.
   1286       if (iter->url != kDefaultEntryUrl)
   1287         EXPECT_TRUE(database()->InsertEntry(&(*iter)));
   1288       ++iter;
   1289     }
   1290 
   1291     EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
   1292     if (drop_from_working_set) {
   1293       EXPECT_TRUE(cache_->HasOneRef());
   1294       cache_ = NULL;
   1295       EXPECT_TRUE(group_->HasOneRef());
   1296       group_ = NULL;
   1297     }
   1298 
   1299     // First test something that does not match the pattern.
   1300     PushNextTask(base::Bind(
   1301         &AppCacheStorageImplTest::Verify_FindFallbackPatternMatchNegative,
   1302         base::Unretained(this)));
   1303     storage()->FindResponseForMainRequest(
   1304         kFallbackPatternTestNegativeUrl, GURL(), delegate());
   1305     EXPECT_EQ(GURL(), delegate()->found_url_);  // Is always async.
   1306   }
   1307 
   1308   void Verify_FindFallbackPatternMatchNegative() {
   1309     EXPECT_EQ(kFallbackPatternTestNegativeUrl, delegate()->found_url_);
   1310       EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1311       EXPECT_EQ(kAppCacheNoCacheId, delegate()->found_cache_id_);
   1312       EXPECT_EQ(kAppCacheNoResponseId, delegate()->found_entry_.response_id());
   1313       EXPECT_EQ(kAppCacheNoResponseId,
   1314           delegate()->found_fallback_entry_.response_id());
   1315       EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1316       EXPECT_EQ(0, delegate()->found_entry_.types());
   1317       EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1318 
   1319       // Then test something that matches.
   1320       PushNextTask(base::Bind(
   1321           &AppCacheStorageImplTest::Verify_FindFallbackPatternMatchPositive,
   1322           base::Unretained(this)));
   1323       storage()->FindResponseForMainRequest(
   1324           kFallbackPatternTestPositiveUrl, GURL(), delegate());
   1325   }
   1326 
   1327   void Verify_FindFallbackPatternMatchPositive() {
   1328     EXPECT_EQ(kFallbackPatternTestPositiveUrl, delegate()->found_url_);
   1329     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1330     EXPECT_EQ(1, delegate()->found_cache_id_);
   1331     EXPECT_EQ(2, delegate()->found_group_id_);
   1332     EXPECT_EQ(1, delegate()->found_fallback_entry_.response_id());
   1333     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1334     EXPECT_EQ(kEntryUrl, delegate()->found_namespace_entry_url_);
   1335     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1336     TestFinished();
   1337   }
   1338 
   1339   // FindMainResponseWithMultipleHits  -------------------------------
   1340 
   1341   void FindMainResponseWithMultipleHits() {
   1342     PushNextTask(base::Bind(
   1343         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits,
   1344         base::Unretained(this)));
   1345 
   1346     // Setup some preconditions, create a few caches with an identical set
   1347     // of entries and fallback namespaces. Only the last one remains in
   1348     // the working set to simulate appearing as "in use".
   1349     MakeMultipleHitCacheAndGroup(kManifestUrl, 1);
   1350     MakeMultipleHitCacheAndGroup(kManifestUrl2, 2);
   1351     MakeMultipleHitCacheAndGroup(kManifestUrl3, 3);
   1352 
   1353     // Conduct the test, we should find the response from the last cache
   1354     // since it's "in use".
   1355     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
   1356     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1357   }
   1358 
   1359   void MakeMultipleHitCacheAndGroup(const GURL& manifest_url, int id) {
   1360     MakeCacheAndGroup(manifest_url, id, id, true);
   1361     AppCacheDatabase::EntryRecord entry_record;
   1362 
   1363     // Add an entry for kEntryUrl
   1364     entry_record.cache_id = id;
   1365     entry_record.url = kEntryUrl;
   1366     entry_record.flags = AppCacheEntry::EXPLICIT;
   1367     entry_record.response_id = id;
   1368     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1369     cache_->AddEntry(
   1370         entry_record.url,
   1371         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1372 
   1373     // Add an entry for the manifestUrl
   1374     entry_record.cache_id = id;
   1375     entry_record.url = manifest_url;
   1376     entry_record.flags = AppCacheEntry::MANIFEST;
   1377     entry_record.response_id = id + kManifestEntryIdOffset;
   1378     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1379     cache_->AddEntry(
   1380         entry_record.url,
   1381         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1382 
   1383     // Add a fallback entry and namespace
   1384     entry_record.cache_id = id;
   1385     entry_record.url = kEntryUrl2;
   1386     entry_record.flags = AppCacheEntry::FALLBACK;
   1387     entry_record.response_id = id + kFallbackEntryIdOffset;
   1388     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1389     cache_->AddEntry(
   1390         entry_record.url,
   1391         AppCacheEntry(entry_record.flags, entry_record.response_id));
   1392     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
   1393     fallback_namespace_record.cache_id = id;
   1394     fallback_namespace_record.namespace_.target_url = entry_record.url;
   1395     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
   1396     fallback_namespace_record.origin = manifest_url.GetOrigin();
   1397     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
   1398     cache_->fallback_namespaces_.push_back(
   1399         AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
   1400                   kFallbackNamespace,
   1401                   kEntryUrl2,
   1402                   false));
   1403   }
   1404 
   1405   void Verify_FindMainResponseWithMultipleHits() {
   1406     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1407     EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
   1408     EXPECT_EQ(3, delegate()->found_cache_id_);
   1409     EXPECT_EQ(3, delegate()->found_group_id_);
   1410     EXPECT_EQ(3, delegate()->found_entry_.response_id());
   1411     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1412     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1413 
   1414     // Conduct another test preferring kManifestUrl
   1415     delegate_.reset(new MockStorageDelegate(this));
   1416     PushNextTask(base::Bind(
   1417         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2,
   1418         base::Unretained(this)));
   1419     storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl, delegate());
   1420     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1421   }
   1422 
   1423   void Verify_FindMainResponseWithMultipleHits2() {
   1424     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1425     EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
   1426     EXPECT_EQ(1, delegate()->found_cache_id_);
   1427     EXPECT_EQ(1, delegate()->found_group_id_);
   1428     EXPECT_EQ(1, delegate()->found_entry_.response_id());
   1429     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1430     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1431 
   1432     // Conduct the another test preferring kManifestUrl2
   1433     delegate_.reset(new MockStorageDelegate(this));
   1434     PushNextTask(base::Bind(
   1435         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3,
   1436         base::Unretained(this)));
   1437     storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl2, delegate());
   1438     EXPECT_NE(kEntryUrl, delegate()->found_url_);
   1439   }
   1440 
   1441   void Verify_FindMainResponseWithMultipleHits3() {
   1442     EXPECT_EQ(kEntryUrl, delegate()->found_url_);
   1443     EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
   1444     EXPECT_EQ(2, delegate()->found_cache_id_);
   1445     EXPECT_EQ(2, delegate()->found_group_id_);
   1446     EXPECT_EQ(2, delegate()->found_entry_.response_id());
   1447     EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
   1448     EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
   1449 
   1450     // Conduct another test with no preferred manifest that hits the fallback.
   1451     delegate_.reset(new MockStorageDelegate(this));
   1452     PushNextTask(base::Bind(
   1453         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits4,
   1454         base::Unretained(this)));
   1455     storage()->FindResponseForMainRequest(
   1456         kFallbackTestUrl, GURL(), delegate());
   1457     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
   1458   }
   1459 
   1460   void Verify_FindMainResponseWithMultipleHits4() {
   1461     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
   1462     EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
   1463     EXPECT_EQ(3, delegate()->found_cache_id_);
   1464     EXPECT_EQ(3, delegate()->found_group_id_);
   1465     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1466     EXPECT_EQ(3 + kFallbackEntryIdOffset,
   1467               delegate()->found_fallback_entry_.response_id());
   1468     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1469     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1470 
   1471     // Conduct another test preferring kManifestUrl2 that hits the fallback.
   1472     delegate_.reset(new MockStorageDelegate(this));
   1473     PushNextTask(base::Bind(
   1474         &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits5,
   1475         base::Unretained(this)));
   1476     storage()->FindResponseForMainRequest(
   1477         kFallbackTestUrl, kManifestUrl2, delegate());
   1478     EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
   1479   }
   1480 
   1481   void Verify_FindMainResponseWithMultipleHits5() {
   1482     EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
   1483     EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
   1484     EXPECT_EQ(2, delegate()->found_cache_id_);
   1485     EXPECT_EQ(2, delegate()->found_group_id_);
   1486     EXPECT_FALSE(delegate()->found_entry_.has_response_id());
   1487     EXPECT_EQ(2 + kFallbackEntryIdOffset,
   1488               delegate()->found_fallback_entry_.response_id());
   1489     EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
   1490     EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
   1491 
   1492     TestFinished();
   1493   }
   1494 
   1495   // FindMainResponseExclusions  -------------------------------
   1496 
   1497   void FindMainResponseExclusionsInDatabase() {
   1498     FindMainResponseExclusions(true);
   1499   }
   1500 
   1501   void FindMainResponseExclusionsInWorkingSet() {
   1502     FindMainResponseExclusions(false);
   1503   }
   1504 
   1505   void FindMainResponseExclusions(bool drop_from_working_set) {
   1506     // Setup some preconditions. Create a complete cache with a
   1507     // foreign entry, an online namespace, and a second online
   1508     // namespace nested within a fallback namespace.
   1509     MakeCacheAndGroup(kManifestUrl, 1, 1, true);
   1510     cache_->AddEntry(kEntryUrl,
   1511         AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 1));
   1512     cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
   1513     cache_->fallback_namespaces_.push_back(
   1514         AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
   1515                   kFallbackNamespace,
   1516                   kEntryUrl2,
   1517                   false));
   1518     cache_->online_whitelist_namespaces_.push_back(
   1519         AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespace,
   1520                   GURL(), false));
   1521     cache_->online_whitelist_namespaces_.push_back(
   1522         AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
   1523             kOnlineNamespaceWithinFallback, GURL(), false));
   1524 
   1525     AppCacheDatabase::EntryRecord entry_record;
   1526     entry_record.cache_id = 1;
   1527     entry_record.url = kEntryUrl;
   1528     entry_record.flags = AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN;
   1529     entry_record.response_id = 1;
   1530     EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1531     AppCacheDatabase::OnlineWhiteListRecord whitelist_record;
   1532     whitelist_record.cache_id = 1;
   1533     whitelist_record.namespace_url = kOnlineNamespace;
   1534     EXPECT_TRUE(database()->InsertOnlineWhiteList(&whitelist_record));
   1535     AppCacheDatabase::NamespaceRecord fallback_namespace_record;
   1536     fallback_namespace_record.cache_id = 1;
   1537     fallback_namespace_record.namespace_.target_url = kEntryUrl2;
   1538     fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
   1539     fallback_namespace_record.origin = kManifestUrl.GetOrigin();
   1540     EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
   1541     whitelist_record.cache_id = 1;
   1542     whitelist_record.namespace_url = kOnlineNamespaceWithinFallback;
   1543     EXPECT_TRUE(database()->InsertOnlineWhiteList(&whitelist_record));
   1544     if (drop_from_working_set) {
   1545       cache_ = NULL;
   1546       group_ = NULL;
   1547     }
   1548 
   1549     // We should not find anything for the foreign entry.
   1550     PushNextTask(base::Bind(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1551                             base::Unretained(this), kEntryUrl, 1));
   1552     storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
   1553   }
   1554 
   1555   void Verify_ExclusionNotFound(GURL expected_url, int phase) {
   1556     EXPECT_EQ(expected_url, delegate()->found_url_);
   1557     EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
   1558     EXPECT_EQ(kAppCacheNoCacheId, delegate()->found_cache_id_);
   1559     EXPECT_EQ(0, delegate()->found_group_id_);
   1560     EXPECT_EQ(kAppCacheNoResponseId, delegate()->found_entry_.response_id());
   1561     EXPECT_EQ(kAppCacheNoResponseId,
   1562         delegate()->found_fallback_entry_.response_id());
   1563     EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
   1564     EXPECT_EQ(0, delegate()->found_entry_.types());
   1565     EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
   1566 
   1567     if (phase == 1) {
   1568       // We should not find anything for the online namespace.
   1569       PushNextTask(
   1570           base::Bind(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1571                      base::Unretained(this), kOnlineNamespace, 2));
   1572       storage()->FindResponseForMainRequest(
   1573           kOnlineNamespace, GURL(), delegate());
   1574       return;
   1575     }
   1576     if (phase == 2) {
   1577       // We should not find anything for the online namespace nested within
   1578       // the fallback namespace.
   1579       PushNextTask(base::Bind(
   1580           &AppCacheStorageImplTest::Verify_ExclusionNotFound,
   1581           base::Unretained(this), kOnlineNamespaceWithinFallback, 3));
   1582       storage()->FindResponseForMainRequest(
   1583           kOnlineNamespaceWithinFallback, GURL(), delegate());
   1584       return;
   1585     }
   1586 
   1587     TestFinished();
   1588   }
   1589 
   1590   // Reinitialize -------------------------------
   1591   // These tests are somewhat of a system integration test.
   1592   // They rely on running a mock http server on our IO thread,
   1593   // and involves other appcache classes to get some code
   1594   // coverage thruout when Reinitialize happens.
   1595 
   1596   class MockServiceObserver : public AppCacheServiceImpl::Observer {
   1597    public:
   1598     explicit MockServiceObserver(AppCacheStorageImplTest* test)
   1599         : test_(test) {}
   1600 
   1601     virtual void OnServiceReinitialized(
   1602         AppCacheStorageReference* old_storage_ref) OVERRIDE {
   1603       observed_old_storage_ = old_storage_ref;
   1604       test_->ScheduleNextTask();
   1605     }
   1606 
   1607     scoped_refptr<AppCacheStorageReference> observed_old_storage_;
   1608     AppCacheStorageImplTest* test_;
   1609   };
   1610 
   1611   class MockAppCacheFrontend : public AppCacheFrontend {
   1612    public:
   1613     MockAppCacheFrontend() : error_event_was_raised_(false) {}
   1614 
   1615     virtual void OnCacheSelected(
   1616         int host_id, const AppCacheInfo& info) OVERRIDE {}
   1617     virtual void OnStatusChanged(const std::vector<int>& host_ids,
   1618                                  AppCacheStatus status) OVERRIDE {}
   1619     virtual void OnEventRaised(const std::vector<int>& host_ids,
   1620                                AppCacheEventID event_id) OVERRIDE {}
   1621     virtual void OnProgressEventRaised(
   1622         const std::vector<int>& host_ids,
   1623         const GURL& url,
   1624         int num_total, int num_complete) OVERRIDE {}
   1625     virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
   1626                                     const AppCacheErrorDetails& details)
   1627         OVERRIDE {
   1628       error_event_was_raised_ = true;
   1629     }
   1630     virtual void OnLogMessage(int host_id, AppCacheLogLevel log_level,
   1631                               const std::string& message) OVERRIDE {}
   1632     virtual void OnContentBlocked(
   1633         int host_id, const GURL& manifest_url) OVERRIDE {}
   1634 
   1635     bool error_event_was_raised_;
   1636   };
   1637 
   1638   enum ReinitTestCase {
   1639      CORRUPT_CACHE_ON_INSTALL,
   1640      CORRUPT_CACHE_ON_LOAD_EXISTING,
   1641      CORRUPT_SQL_ON_INSTALL
   1642   };
   1643 
   1644   void Reinitialize1() {
   1645     // Recover from a corrupt disk cache discovered while
   1646     // installing a new appcache.
   1647     Reinitialize(CORRUPT_CACHE_ON_INSTALL);
   1648   }
   1649 
   1650   void Reinitialize2() {
   1651     // Recover from a corrupt disk cache discovered while
   1652     // trying to load a resource from an existing appcache.
   1653     Reinitialize(CORRUPT_CACHE_ON_LOAD_EXISTING);
   1654   }
   1655 
   1656   void Reinitialize3() {
   1657     // Recover from a corrupt sql database discovered while
   1658     // installing a new appcache.
   1659     Reinitialize(CORRUPT_SQL_ON_INSTALL);
   1660   }
   1661 
   1662   void Reinitialize(ReinitTestCase test_case) {
   1663     // Unlike all of the other tests, this one actually read/write files.
   1664     ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
   1665 
   1666     AppCacheDatabase db(temp_directory_.path().AppendASCII("Index"));
   1667     EXPECT_TRUE(db.LazyOpen(true));
   1668 
   1669     if (test_case == CORRUPT_CACHE_ON_INSTALL ||
   1670         test_case == CORRUPT_CACHE_ON_LOAD_EXISTING) {
   1671       // Create a corrupt/unopenable disk_cache index file.
   1672       const std::string kCorruptData("deadbeef");
   1673       base::FilePath disk_cache_directory =
   1674           temp_directory_.path().AppendASCII("Cache");
   1675       ASSERT_TRUE(base::CreateDirectory(disk_cache_directory));
   1676       base::FilePath index_file = disk_cache_directory.AppendASCII("index");
   1677       EXPECT_EQ(static_cast<int>(kCorruptData.length()),
   1678                 base::WriteFile(
   1679                     index_file, kCorruptData.data(), kCorruptData.length()));
   1680     }
   1681 
   1682     // Create records for a degenerate cached manifest that only contains
   1683     // one entry for the manifest file resource.
   1684     if (test_case == CORRUPT_CACHE_ON_LOAD_EXISTING) {
   1685       AppCacheDatabase db(temp_directory_.path().AppendASCII("Index"));
   1686       GURL manifest_url = MockHttpServer::GetMockUrl("manifest");
   1687 
   1688       AppCacheDatabase::GroupRecord group_record;
   1689       group_record.group_id = 1;
   1690       group_record.manifest_url = manifest_url;
   1691       group_record.origin = manifest_url.GetOrigin();
   1692       EXPECT_TRUE(db.InsertGroup(&group_record));
   1693       AppCacheDatabase::CacheRecord cache_record;
   1694       cache_record.cache_id = 1;
   1695       cache_record.group_id = 1;
   1696       cache_record.online_wildcard = false;
   1697       cache_record.update_time = kZeroTime;
   1698       cache_record.cache_size = kDefaultEntrySize;
   1699       EXPECT_TRUE(db.InsertCache(&cache_record));
   1700       AppCacheDatabase::EntryRecord entry_record;
   1701       entry_record.cache_id = 1;
   1702       entry_record.url = manifest_url;
   1703       entry_record.flags = AppCacheEntry::MANIFEST;
   1704       entry_record.response_id = 1;
   1705       entry_record.response_size = kDefaultEntrySize;
   1706       EXPECT_TRUE(db.InsertEntry(&entry_record));
   1707     }
   1708 
   1709     // Recreate the service to point at the db and corruption on disk.
   1710     service_.reset(new AppCacheServiceImpl(NULL));
   1711     service_->set_request_context(io_thread->request_context());
   1712     service_->Initialize(temp_directory_.path(),
   1713                          db_thread->task_runner(),
   1714                          db_thread->task_runner());
   1715     mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
   1716     service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
   1717     delegate_.reset(new MockStorageDelegate(this));
   1718 
   1719     // Additional setup to observe reinitailize happens.
   1720     observer_.reset(new MockServiceObserver(this));
   1721     service_->AddObserver(observer_.get());
   1722 
   1723     // We continue after the init task is complete including the callback
   1724     // on the current thread.
   1725     FlushDbThreadTasks();
   1726     base::MessageLoop::current()->PostTask(
   1727         FROM_HERE,
   1728         base::Bind(&AppCacheStorageImplTest::Continue_Reinitialize,
   1729                    base::Unretained(this),
   1730                    test_case));
   1731   }
   1732 
   1733   void Continue_Reinitialize(ReinitTestCase test_case) {
   1734     const int kMockProcessId = 1;
   1735     backend_.reset(new AppCacheBackendImpl);
   1736     backend_->Initialize(service_.get(), &frontend_, kMockProcessId);
   1737 
   1738     if (test_case == CORRUPT_SQL_ON_INSTALL) {
   1739       // Break the db file
   1740       EXPECT_FALSE(database()->was_corruption_detected());
   1741       ASSERT_TRUE(sql::test::CorruptSizeInHeader(
   1742           temp_directory_.path().AppendASCII("Index")));
   1743     }
   1744 
   1745     if (test_case == CORRUPT_CACHE_ON_INSTALL  ||
   1746         test_case == CORRUPT_SQL_ON_INSTALL) {
   1747       // Try to create a new appcache, the resulting update job will
   1748       // eventually fail when it gets to disk cache initialization.
   1749       backend_->RegisterHost(1);
   1750       AppCacheHost* host1 = backend_->GetHost(1);
   1751       const GURL kEmptyPageUrl(MockHttpServer::GetMockUrl("empty.html"));
   1752       host1->first_party_url_ = kEmptyPageUrl;
   1753       host1->SelectCache(kEmptyPageUrl,
   1754                          kAppCacheNoCacheId,
   1755                          MockHttpServer::GetMockUrl("manifest"));
   1756     } else {
   1757       ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
   1758       // Try to access the existing cache manifest.
   1759       // The URLRequestJob  will eventually fail when it gets to disk
   1760       // cache initialization.
   1761       backend_->RegisterHost(2);
   1762       AppCacheHost* host2 = backend_->GetHost(2);
   1763       GURL manifest_url = MockHttpServer::GetMockUrl("manifest");
   1764       request_ = service()->request_context()->CreateRequest(
   1765           manifest_url, net::DEFAULT_PRIORITY, NULL, NULL);
   1766       AppCacheInterceptor::SetExtraRequestInfo(
   1767           request_.get(), service_.get(),
   1768           backend_->process_id(), host2->host_id(),
   1769           RESOURCE_TYPE_MAIN_FRAME);
   1770       request_->Start();
   1771     }
   1772 
   1773     PushNextTask(base::Bind(
   1774         &AppCacheStorageImplTest::Verify_Reinitialized,
   1775         base::Unretained(this),
   1776         test_case));
   1777   }
   1778 
   1779   void Verify_Reinitialized(ReinitTestCase test_case) {
   1780     // Verify we got notified of reinit and a new storage instance is created,
   1781     // and that the old data has been deleted.
   1782     EXPECT_TRUE(observer_->observed_old_storage_.get());
   1783     EXPECT_TRUE(observer_->observed_old_storage_->storage() != storage());
   1784     EXPECT_FALSE(PathExists(
   1785         temp_directory_.path().AppendASCII("Cache").AppendASCII("index")));
   1786     EXPECT_FALSE(PathExists(
   1787         temp_directory_.path().AppendASCII("Index")));
   1788 
   1789     if (test_case == CORRUPT_SQL_ON_INSTALL) {
   1790       AppCacheStorageImpl* storage = static_cast<AppCacheStorageImpl*>(
   1791           observer_->observed_old_storage_->storage());
   1792       EXPECT_TRUE(storage->database_->was_corruption_detected());
   1793     }
   1794 
   1795     // Verify that the hosts saw appropriate events.
   1796     if (test_case == CORRUPT_CACHE_ON_INSTALL ||
   1797         test_case == CORRUPT_SQL_ON_INSTALL) {
   1798       EXPECT_TRUE(frontend_.error_event_was_raised_);
   1799       AppCacheHost* host1 = backend_->GetHost(1);
   1800       EXPECT_FALSE(host1->associated_cache());
   1801       EXPECT_FALSE(host1->group_being_updated_.get());
   1802       EXPECT_TRUE(host1->disabled_storage_reference_.get());
   1803     } else {
   1804       ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
   1805       AppCacheHost* host2 = backend_->GetHost(2);
   1806       EXPECT_EQ(1, host2->main_resource_cache_->cache_id());
   1807       EXPECT_TRUE(host2->disabled_storage_reference_.get());
   1808     }
   1809 
   1810     // Cleanup and claim victory.
   1811     service_->RemoveObserver(observer_.get());
   1812     request_.reset();
   1813     backend_.reset();
   1814     observer_.reset();
   1815     TestFinished();
   1816   }
   1817 
   1818   // Test case helpers --------------------------------------------------
   1819 
   1820   AppCacheServiceImpl* service() {
   1821     return service_.get();
   1822   }
   1823 
   1824   AppCacheStorageImpl* storage() {
   1825     return static_cast<AppCacheStorageImpl*>(service()->storage());
   1826   }
   1827 
   1828   AppCacheDatabase* database() {
   1829     return storage()->database_;
   1830   }
   1831 
   1832   MockStorageDelegate* delegate() {
   1833     return delegate_.get();
   1834   }
   1835 
   1836   void MakeCacheAndGroup(
   1837       const GURL& manifest_url, int64 group_id, int64 cache_id,
   1838       bool add_to_database) {
   1839     AppCacheEntry default_entry(
   1840         AppCacheEntry::EXPLICIT, cache_id + kDefaultEntryIdOffset,
   1841         kDefaultEntrySize);
   1842     group_ = new AppCacheGroup(storage(), manifest_url, group_id);
   1843     cache_ = new AppCache(storage(), cache_id);
   1844     cache_->AddEntry(kDefaultEntryUrl, default_entry);
   1845     cache_->set_complete(true);
   1846     group_->AddCache(cache_.get());
   1847     if (add_to_database) {
   1848       AppCacheDatabase::GroupRecord group_record;
   1849       group_record.group_id = group_id;
   1850       group_record.manifest_url = manifest_url;
   1851       group_record.origin = manifest_url.GetOrigin();
   1852       EXPECT_TRUE(database()->InsertGroup(&group_record));
   1853       AppCacheDatabase::CacheRecord cache_record;
   1854       cache_record.cache_id = cache_id;
   1855       cache_record.group_id = group_id;
   1856       cache_record.online_wildcard = false;
   1857       cache_record.update_time = kZeroTime;
   1858       cache_record.cache_size = kDefaultEntrySize;
   1859       EXPECT_TRUE(database()->InsertCache(&cache_record));
   1860       AppCacheDatabase::EntryRecord entry_record;
   1861       entry_record.cache_id = cache_id;
   1862       entry_record.url = kDefaultEntryUrl;
   1863       entry_record.flags = default_entry.types();
   1864       entry_record.response_id = default_entry.response_id();
   1865       entry_record.response_size = default_entry.response_size();
   1866       EXPECT_TRUE(database()->InsertEntry(&entry_record));
   1867 
   1868       storage()->usage_map_[manifest_url.GetOrigin()] =
   1869           default_entry.response_size();
   1870     }
   1871   }
   1872 
   1873   // Data members --------------------------------------------------
   1874 
   1875   scoped_ptr<base::WaitableEvent> test_finished_event_;
   1876   std::stack<base::Closure> task_stack_;
   1877   scoped_ptr<AppCacheServiceImpl> service_;
   1878   scoped_ptr<MockStorageDelegate> delegate_;
   1879   scoped_refptr<MockQuotaManagerProxy> mock_quota_manager_proxy_;
   1880   scoped_refptr<AppCacheGroup> group_;
   1881   scoped_refptr<AppCache> cache_;
   1882   scoped_refptr<AppCache> cache2_;
   1883 
   1884   // Specifically for the Reinitalize test.
   1885   base::ScopedTempDir temp_directory_;
   1886   scoped_ptr<MockServiceObserver> observer_;
   1887   MockAppCacheFrontend frontend_;
   1888   scoped_ptr<AppCacheBackendImpl> backend_;
   1889   scoped_ptr<net::URLRequest> request_;
   1890 };
   1891 
   1892 
   1893 TEST_F(AppCacheStorageImplTest, LoadCache_Miss) {
   1894   RunTestOnIOThread(&AppCacheStorageImplTest::LoadCache_Miss);
   1895 }
   1896 
   1897 TEST_F(AppCacheStorageImplTest, LoadCache_NearHit) {
   1898   RunTestOnIOThread(&AppCacheStorageImplTest::LoadCache_NearHit);
   1899 }
   1900 
   1901 TEST_F(AppCacheStorageImplTest, CreateGroupInEmptyOrigin) {
   1902   RunTestOnIOThread(&AppCacheStorageImplTest::CreateGroupInEmptyOrigin);
   1903 }
   1904 
   1905 TEST_F(AppCacheStorageImplTest, CreateGroupInPopulatedOrigin) {
   1906   RunTestOnIOThread(&AppCacheStorageImplTest::CreateGroupInPopulatedOrigin);
   1907 }
   1908 
   1909 TEST_F(AppCacheStorageImplTest, LoadGroupAndCache_FarHit) {
   1910   RunTestOnIOThread(&AppCacheStorageImplTest::LoadGroupAndCache_FarHit);
   1911 }
   1912 
   1913 TEST_F(AppCacheStorageImplTest, StoreNewGroup) {
   1914   RunTestOnIOThread(&AppCacheStorageImplTest::StoreNewGroup);
   1915 }
   1916 
   1917 TEST_F(AppCacheStorageImplTest, StoreExistingGroup) {
   1918   RunTestOnIOThread(&AppCacheStorageImplTest::StoreExistingGroup);
   1919 }
   1920 
   1921 TEST_F(AppCacheStorageImplTest, StoreExistingGroupExistingCache) {
   1922   RunTestOnIOThread(&AppCacheStorageImplTest::StoreExistingGroupExistingCache);
   1923 }
   1924 
   1925 TEST_F(AppCacheStorageImplTest, FailStoreGroup) {
   1926   RunTestOnIOThread(&AppCacheStorageImplTest::FailStoreGroup);
   1927 }
   1928 
   1929 TEST_F(AppCacheStorageImplTest, MakeGroupObsolete) {
   1930   RunTestOnIOThread(&AppCacheStorageImplTest::MakeGroupObsolete);
   1931 }
   1932 
   1933 TEST_F(AppCacheStorageImplTest, MarkEntryAsForeign) {
   1934   RunTestOnIOThread(&AppCacheStorageImplTest::MarkEntryAsForeign);
   1935 }
   1936 
   1937 TEST_F(AppCacheStorageImplTest, MarkEntryAsForeignWithLoadInProgress) {
   1938   RunTestOnIOThread(
   1939       &AppCacheStorageImplTest::MarkEntryAsForeignWithLoadInProgress);
   1940 }
   1941 
   1942 TEST_F(AppCacheStorageImplTest, FindNoMainResponse) {
   1943   RunTestOnIOThread(&AppCacheStorageImplTest::FindNoMainResponse);
   1944 }
   1945 
   1946 TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInDatabase) {
   1947   RunTestOnIOThread(
   1948       &AppCacheStorageImplTest::BasicFindMainResponseInDatabase);
   1949 }
   1950 
   1951 TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInWorkingSet) {
   1952   RunTestOnIOThread(
   1953       &AppCacheStorageImplTest::BasicFindMainResponseInWorkingSet);
   1954 }
   1955 
   1956 TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInDatabase) {
   1957   RunTestOnIOThread(
   1958       &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase);
   1959 }
   1960 
   1961 TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInWorkingSet) {
   1962   RunTestOnIOThread(
   1963       &AppCacheStorageImplTest::BasicFindMainFallbackResponseInWorkingSet);
   1964 }
   1965 
   1966 TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInDatabase) {
   1967   RunTestOnIOThread(
   1968       &AppCacheStorageImplTest::BasicFindMainInterceptResponseInDatabase);
   1969 }
   1970 
   1971 TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInWorkingSet) {
   1972   RunTestOnIOThread(
   1973       &AppCacheStorageImplTest::BasicFindMainInterceptResponseInWorkingSet);
   1974 }
   1975 
   1976 TEST_F(AppCacheStorageImplTest, FindMainResponseWithMultipleHits) {
   1977   RunTestOnIOThread(
   1978       &AppCacheStorageImplTest::FindMainResponseWithMultipleHits);
   1979 }
   1980 
   1981 TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInDatabase) {
   1982   RunTestOnIOThread(
   1983       &AppCacheStorageImplTest::FindMainResponseExclusionsInDatabase);
   1984 }
   1985 
   1986 TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInWorkingSet) {
   1987   RunTestOnIOThread(
   1988       &AppCacheStorageImplTest::FindMainResponseExclusionsInWorkingSet);
   1989 }
   1990 
   1991 TEST_F(AppCacheStorageImplTest, FindInterceptPatternMatchInWorkingSet) {
   1992   RunTestOnIOThread(
   1993       &AppCacheStorageImplTest::FindInterceptPatternMatchInWorkingSet);
   1994 }
   1995 
   1996 TEST_F(AppCacheStorageImplTest, FindInterceptPatternMatchInDatabase) {
   1997   RunTestOnIOThread(
   1998       &AppCacheStorageImplTest::FindInterceptPatternMatchInDatabase);
   1999 }
   2000 
   2001 TEST_F(AppCacheStorageImplTest, FindFallbackPatternMatchInWorkingSet) {
   2002   RunTestOnIOThread(
   2003       &AppCacheStorageImplTest::FindFallbackPatternMatchInWorkingSet);
   2004 }
   2005 
   2006 TEST_F(AppCacheStorageImplTest, FindFallbackPatternMatchInDatabase) {
   2007   RunTestOnIOThread(
   2008       &AppCacheStorageImplTest::FindFallbackPatternMatchInDatabase);
   2009 }
   2010 
   2011 TEST_F(AppCacheStorageImplTest, Reinitialize1) {
   2012   RunTestOnIOThread(&AppCacheStorageImplTest::Reinitialize1);
   2013 }
   2014 
   2015 TEST_F(AppCacheStorageImplTest, Reinitialize2) {
   2016   RunTestOnIOThread(&AppCacheStorageImplTest::Reinitialize2);
   2017 }
   2018 
   2019 TEST_F(AppCacheStorageImplTest, Reinitialize3) {
   2020   RunTestOnIOThread(&AppCacheStorageImplTest::Reinitialize3);
   2021 }
   2022 
   2023 // That's all folks!
   2024 
   2025 }  // namespace content
   2026