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 "base/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/stl_util.h"
      8 #include "base/synchronization/waitable_event.h"
      9 #include "base/threading/thread.h"
     10 #include "content/browser/appcache/mock_appcache_service.h"
     11 #include "net/base/net_errors.h"
     12 #include "net/http/http_response_headers.h"
     13 #include "net/url_request/url_request_error_job.h"
     14 #include "net/url_request/url_request_job_factory_impl.h"
     15 #include "net/url_request/url_request_test_job.h"
     16 #include "net/url_request/url_request_test_util.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "webkit/browser/appcache/appcache_group.h"
     19 #include "webkit/browser/appcache/appcache_host.h"
     20 #include "webkit/browser/appcache/appcache_response.h"
     21 #include "webkit/browser/appcache/appcache_update_job.h"
     22 
     23 using appcache::AppCache;
     24 using appcache::AppCacheEntry;
     25 using appcache::AppCacheFrontend;
     26 using appcache::AppCacheHost;
     27 using appcache::AppCacheGroup;
     28 using appcache::AppCacheResponseInfo;
     29 using appcache::AppCacheUpdateJob;
     30 using appcache::AppCacheResponseWriter;
     31 using appcache::APPCACHE_CACHED_EVENT;
     32 using appcache::APPCACHE_CHECKING_EVENT;
     33 using appcache::APPCACHE_DOWNLOADING_EVENT;
     34 using appcache::APPCACHE_ERROR_EVENT;
     35 using appcache::AppCacheEventID;
     36 using appcache::APPCACHE_FALLBACK_NAMESPACE;
     37 using appcache::HttpResponseInfoIOBuffer;
     38 using appcache::kAppCacheNoCacheId;
     39 using appcache::kAppCacheNoResponseId;
     40 using appcache::Namespace;
     41 using appcache::APPCACHE_NETWORK_NAMESPACE;
     42 using appcache::APPCACHE_NO_UPDATE_EVENT;
     43 using appcache::APPCACHE_OBSOLETE_EVENT;
     44 using appcache::APPCACHE_PROGRESS_EVENT;
     45 using appcache::APPCACHE_UPDATE_READY_EVENT;
     46 using appcache::AppCacheStatus;
     47 
     48 namespace content {
     49 class AppCacheUpdateJobTest;
     50 
     51 namespace {
     52 
     53 const char kManifest1Contents[] =
     54     "CACHE MANIFEST\n"
     55     "explicit1\n"
     56     "FALLBACK:\n"
     57     "fallback1 fallback1a\n"
     58     "NETWORK:\n"
     59     "*\n";
     60 
     61 // There are a handful of http accessible resources that we need to conduct
     62 // these tests. Instead of running a seperate server to host these resources,
     63 // we mock them up.
     64 class MockHttpServer {
     65  public:
     66   static GURL GetMockUrl(const std::string& path) {
     67     return GURL("http://mockhost/" + path);
     68   }
     69 
     70   static GURL GetMockHttpsUrl(const std::string& path) {
     71     return GURL("https://mockhost/" + path);
     72   }
     73 
     74   static GURL GetMockCrossOriginHttpsUrl(const std::string& path) {
     75     return GURL("https://cross_origin_host/" + path);
     76   }
     77 
     78   static net::URLRequestJob* JobFactory(
     79       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
     80     if (request->url().host() != "mockhost" &&
     81         request->url().host() != "cross_origin_host")
     82       return new net::URLRequestErrorJob(request, network_delegate, -100);
     83 
     84     std::string headers, body;
     85     GetMockResponse(request->url().path(), &headers, &body);
     86     return new net::URLRequestTestJob(
     87         request, network_delegate, headers, body, true);
     88   }
     89 
     90  private:
     91   static void GetMockResponse(const std::string& path,
     92                               std::string* headers,
     93                               std::string* body) {
     94     const char ok_headers[] =
     95         "HTTP/1.1 200 OK\0"
     96         "\0";
     97     const char error_headers[] =
     98         "HTTP/1.1 500 BOO HOO\0"
     99         "\0";
    100     const char manifest_headers[] =
    101         "HTTP/1.1 200 OK\0"
    102         "Content-type: text/cache-manifest\0"
    103         "\0";
    104     const char not_modified_headers[] =
    105         "HTTP/1.1 304 NOT MODIFIED\0"
    106         "\0";
    107     const char gone_headers[] =
    108         "HTTP/1.1 410 GONE\0"
    109         "\0";
    110     const char not_found_headers[] =
    111         "HTTP/1.1 404 NOT FOUND\0"
    112         "\0";
    113     const char no_store_headers[] =
    114         "HTTP/1.1 200 OK\0"
    115         "Cache-Control: no-store\0"
    116         "\0";
    117 
    118     if (path == "/files/missing-mime-manifest") {
    119       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    120       (*body) = "CACHE MANIFEST\n";
    121     } else if (path == "/files/bad-manifest") {
    122       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    123       (*body) = "BAD CACHE MANIFEST";
    124     } else if (path == "/files/empty1") {
    125       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    126       (*body) = "";
    127     } else if (path == "/files/empty-file-manifest") {
    128       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    129       (*body) = "CACHE MANIFEST\n"
    130                 "empty1\n";
    131     } else if (path == "/files/empty-manifest") {
    132       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    133       (*body) = "CACHE MANIFEST\n";
    134     } else if (path == "/files/explicit1") {
    135       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    136       (*body) = "explicit1";
    137     } else if (path == "/files/explicit2") {
    138       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    139       (*body) = "explicit2";
    140     } else if (path == "/files/fallback1a") {
    141       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    142       (*body) = "fallback1a";
    143     } else if (path == "/files/intercept1a") {
    144       (*headers) = std::string(ok_headers, arraysize(ok_headers));
    145       (*body) = "intercept1a";
    146     } else if (path == "/files/gone") {
    147       (*headers) = std::string(gone_headers, arraysize(gone_headers));
    148       (*body) = "";
    149     } else if (path == "/files/manifest1") {
    150       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    151       (*body) = kManifest1Contents;
    152     } else if (path == "/files/manifest1-with-notmodified") {
    153       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    154       (*body) = kManifest1Contents;
    155       (*body).append("CACHE:\n"
    156                      "notmodified\n");
    157     } else if (path == "/files/manifest-fb-404") {
    158       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    159       (*body) = "CACHE MANIFEST\n"
    160                 "explicit1\n"
    161                 "FALLBACK:\n"
    162                 "fallback1 fallback1a\n"
    163                 "fallback404 fallback-404\n"
    164                 "NETWORK:\n"
    165                 "online1\n";
    166     } else if (path == "/files/manifest-merged-types") {
    167       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    168       (*body) = "CACHE MANIFEST\n"
    169                 "explicit1\n"
    170                 "# manifest is also an explicit entry\n"
    171                 "manifest-merged-types\n"
    172                 "FALLBACK:\n"
    173                 "# fallback is also explicit entry\n"
    174                 "fallback1 explicit1\n"
    175                 "NETWORK:\n"
    176                 "online1\n";
    177     } else if (path == "/files/manifest-with-404") {
    178       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    179       (*body) = "CACHE MANIFEST\n"
    180                 "explicit-404\n"
    181                 "explicit1\n"
    182                 "explicit2\n"
    183                 "explicit3\n"
    184                 "FALLBACK:\n"
    185                 "fallback1 fallback1a\n"
    186                 "NETWORK:\n"
    187                 "online1\n";
    188     } else if (path == "/files/manifest-with-intercept") {
    189       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    190       (*body) = "CACHE MANIFEST\n"
    191                 "CHROMIUM-INTERCEPT:\n"
    192                 "intercept1 return intercept1a\n";
    193     } else if (path == "/files/notmodified") {
    194       (*headers) = std::string(not_modified_headers,
    195                                arraysize(not_modified_headers));
    196       (*body) = "";
    197     } else if (path == "/files/servererror") {
    198       (*headers) = std::string(error_headers,
    199                                arraysize(error_headers));
    200       (*body) = "error";
    201     } else if (path == "/files/valid_cross_origin_https_manifest") {
    202       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    203       (*body) = "CACHE MANIFEST\n"
    204                 "https://cross_origin_host/files/explicit1\n";
    205     } else if (path == "/files/invalid_cross_origin_https_manifest") {
    206       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
    207       (*body) = "CACHE MANIFEST\n"
    208                 "https://cross_origin_host/files/no-store-headers\n";
    209     } else if (path == "/files/no-store-headers") {
    210       (*headers) = std::string(no_store_headers, arraysize(no_store_headers));
    211       (*body) = "no-store";
    212     } else {
    213       (*headers) = std::string(not_found_headers,
    214                                arraysize(not_found_headers));
    215       (*body) = "";
    216     }
    217   }
    218 };
    219 
    220 class MockHttpServerJobFactory
    221     : public net::URLRequestJobFactory::ProtocolHandler {
    222  public:
    223   virtual net::URLRequestJob* MaybeCreateJob(
    224       net::URLRequest* request,
    225       net::NetworkDelegate* network_delegate) const OVERRIDE {
    226     return MockHttpServer::JobFactory(request, network_delegate);
    227   }
    228 };
    229 
    230 inline bool operator==(const Namespace& lhs, const Namespace& rhs) {
    231   return lhs.type == rhs.type &&
    232          lhs.namespace_url == rhs.namespace_url &&
    233          lhs.target_url == rhs.target_url;
    234 }
    235 
    236 }  // namespace
    237 
    238 class MockFrontend : public AppCacheFrontend {
    239  public:
    240   MockFrontend()
    241       : ignore_progress_events_(false), verify_progress_events_(false),
    242         last_progress_total_(-1), last_progress_complete_(-1),
    243         start_update_trigger_(APPCACHE_CHECKING_EVENT), update_(NULL) {
    244   }
    245 
    246   virtual void OnCacheSelected(
    247       int host_id, const appcache::AppCacheInfo& info) OVERRIDE {
    248   }
    249 
    250   virtual void OnStatusChanged(const std::vector<int>& host_ids,
    251                                AppCacheStatus status) OVERRIDE {
    252   }
    253 
    254   virtual void OnEventRaised(const std::vector<int>& host_ids,
    255                              AppCacheEventID event_id) OVERRIDE {
    256     raised_events_.push_back(RaisedEvent(host_ids, event_id));
    257 
    258     // Trigger additional updates if requested.
    259     if (event_id == start_update_trigger_ && update_) {
    260       for (std::vector<AppCacheHost*>::iterator it = update_hosts_.begin();
    261            it != update_hosts_.end(); ++it) {
    262         AppCacheHost* host = *it;
    263         update_->StartUpdate(host,
    264             (host ? host->pending_master_entry_url() : GURL()));
    265       }
    266       update_hosts_.clear();  // only trigger once
    267     }
    268   }
    269 
    270   virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
    271                                   const appcache::AppCacheErrorDetails& details)
    272       OVERRIDE {
    273     error_message_ = details.message;
    274     OnEventRaised(host_ids, APPCACHE_ERROR_EVENT);
    275   }
    276 
    277   virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
    278                                      const GURL& url,
    279                                      int num_total,
    280                                      int num_complete) OVERRIDE {
    281     if (!ignore_progress_events_)
    282       OnEventRaised(host_ids, APPCACHE_PROGRESS_EVENT);
    283 
    284     if (verify_progress_events_) {
    285       EXPECT_GE(num_total, num_complete);
    286       EXPECT_GE(num_complete, 0);
    287 
    288       if (last_progress_total_ == -1) {
    289         // Should start at zero.
    290         EXPECT_EQ(0, num_complete);
    291       } else {
    292         // Total should be stable and complete should bump up by one at a time.
    293         EXPECT_EQ(last_progress_total_, num_total);
    294         EXPECT_EQ(last_progress_complete_ + 1, num_complete);
    295       }
    296 
    297       // Url should be valid for all except the 'final' event.
    298       if (num_total == num_complete)
    299         EXPECT_TRUE(url.is_empty());
    300       else
    301         EXPECT_TRUE(url.is_valid());
    302 
    303       last_progress_total_ = num_total;
    304       last_progress_complete_ = num_complete;
    305     }
    306   }
    307 
    308   virtual void OnLogMessage(int host_id,
    309                             appcache::AppCacheLogLevel log_level,
    310                             const std::string& message) OVERRIDE {
    311   }
    312 
    313   virtual void OnContentBlocked(int host_id,
    314                                 const GURL& manifest_url) OVERRIDE {
    315   }
    316 
    317   void AddExpectedEvent(const std::vector<int>& host_ids,
    318       AppCacheEventID event_id) {
    319     DCHECK(!ignore_progress_events_ || event_id != APPCACHE_PROGRESS_EVENT);
    320     expected_events_.push_back(RaisedEvent(host_ids, event_id));
    321   }
    322 
    323   void SetIgnoreProgressEvents(bool ignore) {
    324     // Some tests involve joining new hosts to an already running update job
    325     // or intentionally failing. The timing and sequencing of the progress
    326     // events generated by an update job are dependent on the behavior of
    327     // an external HTTP server. For jobs that do not run fully till completion,
    328     // due to either joining late or early exit, we skip monitoring the
    329     // progress events to avoid flakiness.
    330     ignore_progress_events_ = ignore;
    331   }
    332 
    333   void SetVerifyProgressEvents(bool verify) {
    334     verify_progress_events_ = verify;
    335   }
    336 
    337   void TriggerAdditionalUpdates(AppCacheEventID trigger_event,
    338                                 AppCacheUpdateJob* update) {
    339     start_update_trigger_ = trigger_event;
    340     update_ = update;
    341   }
    342 
    343   void AdditionalUpdateHost(AppCacheHost* host) {
    344     update_hosts_.push_back(host);
    345   }
    346 
    347   typedef std::vector<int> HostIds;
    348   typedef std::pair<HostIds, AppCacheEventID> RaisedEvent;
    349   typedef std::vector<RaisedEvent> RaisedEvents;
    350   RaisedEvents raised_events_;
    351   std::string error_message_;
    352 
    353   // Set the expected events if verification needs to happen asynchronously.
    354   RaisedEvents expected_events_;
    355   std::string expected_error_message_;
    356 
    357   bool ignore_progress_events_;
    358 
    359   bool verify_progress_events_;
    360   int last_progress_total_;
    361   int last_progress_complete_;
    362 
    363   // Add ability for frontend to add master entries to an inprogress update.
    364   AppCacheEventID start_update_trigger_;
    365   AppCacheUpdateJob* update_;
    366   std::vector<AppCacheHost*> update_hosts_;
    367 };
    368 
    369 // Helper factories to simulate redirected URL responses for tests.
    370 class RedirectFactory : public net::URLRequestJobFactory::ProtocolHandler {
    371  public:
    372   virtual net::URLRequestJob* MaybeCreateJob(
    373       net::URLRequest* request,
    374       net::NetworkDelegate* network_delegate) const OVERRIDE {
    375     return new net::URLRequestTestJob(
    376         request,
    377         network_delegate,
    378         net::URLRequestTestJob::test_redirect_headers(),
    379         net::URLRequestTestJob::test_data_1(),
    380         true);
    381   }
    382 };
    383 
    384 // Helper class to simulate a URL that returns retry or success.
    385 class RetryRequestTestJob : public net::URLRequestTestJob {
    386  public:
    387   enum RetryHeader {
    388     NO_RETRY_AFTER,
    389     NONZERO_RETRY_AFTER,
    390     RETRY_AFTER_0,
    391   };
    392 
    393   static const GURL kRetryUrl;
    394 
    395   // Call this at the start of each retry test.
    396   static void Initialize(int num_retry_responses, RetryHeader header,
    397       int expected_requests) {
    398     num_requests_ = 0;
    399     num_retries_ = num_retry_responses;
    400     retry_after_ = header;
    401     expected_requests_ = expected_requests;
    402   }
    403 
    404   // Verifies results at end of test and resets counters.
    405   static void Verify() {
    406     EXPECT_EQ(expected_requests_, num_requests_);
    407     num_requests_ = 0;
    408     expected_requests_ = 0;
    409   }
    410 
    411   static net::URLRequestJob* RetryFactory(
    412       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
    413     ++num_requests_;
    414     if (num_retries_ > 0 && request->original_url() == kRetryUrl) {
    415       --num_retries_;
    416       return new RetryRequestTestJob(
    417           request, network_delegate, RetryRequestTestJob::retry_headers(), 503);
    418     } else {
    419       return new RetryRequestTestJob(
    420           request,
    421           network_delegate,
    422           RetryRequestTestJob::manifest_headers(), 200);
    423     }
    424   }
    425 
    426   virtual int GetResponseCode() const OVERRIDE { return response_code_; }
    427 
    428  private:
    429   virtual ~RetryRequestTestJob() {}
    430 
    431   static std::string retry_headers() {
    432     const char no_retry_after[] =
    433         "HTTP/1.1 503 BOO HOO\0"
    434         "\0";
    435     const char nonzero[] =
    436         "HTTP/1.1 503 BOO HOO\0"
    437         "Retry-After: 60\0"
    438         "\0";
    439     const char retry_after_0[] =
    440         "HTTP/1.1 503 BOO HOO\0"
    441         "Retry-After: 0\0"
    442         "\0";
    443 
    444     switch (retry_after_) {
    445       case NO_RETRY_AFTER:
    446         return std::string(no_retry_after, arraysize(no_retry_after));
    447       case NONZERO_RETRY_AFTER:
    448         return std::string(nonzero, arraysize(nonzero));
    449       case RETRY_AFTER_0:
    450       default:
    451         return std::string(retry_after_0, arraysize(retry_after_0));
    452     }
    453   }
    454 
    455   static std::string manifest_headers() {
    456     const char headers[] =
    457         "HTTP/1.1 200 OK\0"
    458         "Content-type: text/cache-manifest\0"
    459         "\0";
    460     return std::string(headers, arraysize(headers));
    461   }
    462 
    463   static std::string data() {
    464     return std::string("CACHE MANIFEST\r"
    465         "http://retry\r");  // must be same as kRetryUrl
    466   }
    467 
    468   RetryRequestTestJob(net::URLRequest* request,
    469                       net::NetworkDelegate* network_delegate,
    470                       const std::string& headers,
    471                       int response_code)
    472       : net::URLRequestTestJob(
    473             request, network_delegate, headers, data(), true),
    474         response_code_(response_code) {
    475   }
    476 
    477   int response_code_;
    478 
    479   static int num_requests_;
    480   static int num_retries_;
    481   static RetryHeader retry_after_;
    482   static int expected_requests_;
    483 };
    484 
    485 class RetryRequestTestJobFactory
    486     : public net::URLRequestJobFactory::ProtocolHandler {
    487  public:
    488   virtual net::URLRequestJob* MaybeCreateJob(
    489       net::URLRequest* request,
    490       net::NetworkDelegate* network_delegate) const OVERRIDE {
    491     return RetryRequestTestJob::RetryFactory(request, network_delegate);
    492   }
    493 };
    494 
    495 // static
    496 const GURL RetryRequestTestJob::kRetryUrl("http://retry");
    497 int RetryRequestTestJob::num_requests_ = 0;
    498 int RetryRequestTestJob::num_retries_;
    499 RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
    500 int RetryRequestTestJob::expected_requests_ = 0;
    501 
    502 // Helper class to check for certain HTTP headers.
    503 class HttpHeadersRequestTestJob : public net::URLRequestTestJob {
    504  public:
    505   // Call this at the start of each HTTP header-related test.
    506   static void Initialize(const std::string& expect_if_modified_since,
    507                          const std::string& expect_if_none_match) {
    508     expect_if_modified_since_ = expect_if_modified_since;
    509     expect_if_none_match_ = expect_if_none_match;
    510   }
    511 
    512   // Verifies results at end of test and resets class.
    513   static void Verify() {
    514     if (!expect_if_modified_since_.empty())
    515       EXPECT_TRUE(saw_if_modified_since_);
    516     if (!expect_if_none_match_.empty())
    517       EXPECT_TRUE(saw_if_none_match_);
    518 
    519     // Reset.
    520     expect_if_modified_since_.clear();
    521     saw_if_modified_since_ = false;
    522     expect_if_none_match_.clear();
    523     saw_if_none_match_ = false;
    524     already_checked_ = false;
    525   }
    526 
    527   static net::URLRequestJob* IfModifiedSinceFactory(
    528       net::URLRequest* request, net::NetworkDelegate* network_delegate) {
    529     if (!already_checked_) {
    530       already_checked_ = true;  // only check once for a test
    531       const net::HttpRequestHeaders& extra_headers =
    532           request->extra_request_headers();
    533       std::string header_value;
    534       saw_if_modified_since_ =
    535           extra_headers.GetHeader(
    536               net::HttpRequestHeaders::kIfModifiedSince, &header_value) &&
    537           header_value == expect_if_modified_since_;
    538 
    539       saw_if_none_match_ =
    540           extra_headers.GetHeader(
    541               net::HttpRequestHeaders::kIfNoneMatch, &header_value) &&
    542           header_value == expect_if_none_match_;
    543     }
    544     return MockHttpServer::JobFactory(request, network_delegate);
    545   }
    546 
    547  protected:
    548   virtual ~HttpHeadersRequestTestJob() {}
    549 
    550  private:
    551   static std::string expect_if_modified_since_;
    552   static bool saw_if_modified_since_;
    553   static std::string expect_if_none_match_;
    554   static bool saw_if_none_match_;
    555   static bool already_checked_;
    556 };
    557 
    558 // static
    559 std::string HttpHeadersRequestTestJob::expect_if_modified_since_;
    560 bool HttpHeadersRequestTestJob::saw_if_modified_since_ = false;
    561 std::string HttpHeadersRequestTestJob::expect_if_none_match_;
    562 bool HttpHeadersRequestTestJob::saw_if_none_match_ = false;
    563 bool HttpHeadersRequestTestJob::already_checked_ = false;
    564 
    565 class IfModifiedSinceJobFactory
    566     : public net::URLRequestJobFactory::ProtocolHandler {
    567  public:
    568   virtual net::URLRequestJob* MaybeCreateJob(
    569       net::URLRequest* request,
    570       net::NetworkDelegate* network_delegate) const OVERRIDE {
    571     return HttpHeadersRequestTestJob::IfModifiedSinceFactory(
    572         request, network_delegate);
    573   }
    574 };
    575 
    576 class IOThread : public base::Thread {
    577  public:
    578   explicit IOThread(const char* name)
    579       : base::Thread(name) {
    580   }
    581 
    582   virtual ~IOThread() {
    583     Stop();
    584   }
    585 
    586   net::URLRequestContext* request_context() {
    587     return request_context_.get();
    588   }
    589 
    590   void SetNewJobFactory(net::URLRequestJobFactory* job_factory) {
    591     DCHECK(job_factory);
    592     job_factory_.reset(job_factory);
    593     request_context_->set_job_factory(job_factory_.get());
    594   }
    595 
    596   virtual void Init() OVERRIDE {
    597     scoped_ptr<net::URLRequestJobFactoryImpl> factory(
    598         new net::URLRequestJobFactoryImpl());
    599     factory->SetProtocolHandler("http", new MockHttpServerJobFactory);
    600     factory->SetProtocolHandler("https", new MockHttpServerJobFactory);
    601     job_factory_ = factory.Pass();
    602     request_context_.reset(new net::TestURLRequestContext());
    603     request_context_->set_job_factory(job_factory_.get());
    604   }
    605 
    606   virtual void CleanUp() OVERRIDE {
    607     request_context_.reset();
    608     job_factory_.reset();
    609   }
    610 
    611  private:
    612   scoped_ptr<net::URLRequestJobFactory> job_factory_;
    613   scoped_ptr<net::URLRequestContext> request_context_;
    614 };
    615 
    616 class AppCacheUpdateJobTest : public testing::Test,
    617                               public AppCacheGroup::UpdateObserver {
    618  public:
    619   AppCacheUpdateJobTest()
    620       : do_checks_after_update_finished_(false),
    621         expect_group_obsolete_(false),
    622         expect_group_has_cache_(false),
    623         expect_group_is_being_deleted_(false),
    624         expect_old_cache_(NULL),
    625         expect_newest_cache_(NULL),
    626         expect_non_null_update_time_(false),
    627         tested_manifest_(NONE),
    628         tested_manifest_path_override_(NULL) {
    629     io_thread_.reset(new IOThread("AppCacheUpdateJob IO test thread"));
    630     base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
    631     io_thread_->StartWithOptions(options);
    632   }
    633 
    634   // Use a separate IO thread to run a test. Thread will be destroyed
    635   // when it goes out of scope.
    636   template <class Method>
    637   void RunTestOnIOThread(Method method) {
    638     event_.reset(new base::WaitableEvent(false, false));
    639     io_thread_->message_loop()->PostTask(
    640         FROM_HERE, base::Bind(method, base::Unretained(this)));
    641 
    642     // Wait until task is done before exiting the test.
    643     event_->Wait();
    644   }
    645 
    646   void StartCacheAttemptTest() {
    647     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    648 
    649     MakeService();
    650     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
    651                                service_->storage()->NewGroupId());
    652 
    653     AppCacheUpdateJob* update =
    654         new AppCacheUpdateJob(service_.get(), group_.get());
    655     group_->update_job_ = update;
    656 
    657     MockFrontend mock_frontend;
    658     AppCacheHost host(1, &mock_frontend, service_.get());
    659 
    660     update->StartUpdate(&host, GURL());
    661 
    662     // Verify state.
    663     EXPECT_EQ(AppCacheUpdateJob::CACHE_ATTEMPT, update->update_type_);
    664     EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_);
    665     EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
    666 
    667     // Verify notifications.
    668     MockFrontend::RaisedEvents& events = mock_frontend.raised_events_;
    669     size_t expected = 1;
    670     EXPECT_EQ(expected, events.size());
    671     EXPECT_EQ(expected, events[0].first.size());
    672     EXPECT_EQ(host.host_id(), events[0].first[0]);
    673     EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
    674 
    675     // Abort as we're not testing actual URL fetches in this test.
    676     delete update;
    677     UpdateFinished();
    678   }
    679 
    680   void StartUpgradeAttemptTest() {
    681     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    682 
    683     {
    684       MakeService();
    685       group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
    686                                  service_->storage()->NewGroupId());
    687 
    688       // Give the group some existing caches.
    689       AppCache* cache1 = MakeCacheForGroup(1, 111);
    690       AppCache* cache2 = MakeCacheForGroup(2, 222);
    691 
    692       // Associate some hosts with caches in the group.
    693       MockFrontend mock_frontend1;
    694       MockFrontend mock_frontend2;
    695       MockFrontend mock_frontend3;
    696 
    697       AppCacheHost host1(1, &mock_frontend1, service_.get());
    698       host1.AssociateCompleteCache(cache1);
    699 
    700       AppCacheHost host2(2, &mock_frontend2, service_.get());
    701       host2.AssociateCompleteCache(cache2);
    702 
    703       AppCacheHost host3(3, &mock_frontend1, service_.get());
    704       host3.AssociateCompleteCache(cache1);
    705 
    706       AppCacheHost host4(4, &mock_frontend3, service_.get());
    707 
    708       AppCacheUpdateJob* update =
    709           new AppCacheUpdateJob(service_.get(), group_.get());
    710       group_->update_job_ = update;
    711       update->StartUpdate(&host4, GURL());
    712 
    713       // Verify state after starting an update.
    714       EXPECT_EQ(AppCacheUpdateJob::UPGRADE_ATTEMPT, update->update_type_);
    715       EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_);
    716       EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
    717 
    718       // Verify notifications.
    719       MockFrontend::RaisedEvents& events = mock_frontend1.raised_events_;
    720       size_t expected = 1;
    721       EXPECT_EQ(expected, events.size());
    722       expected = 2;  // 2 hosts using frontend1
    723       EXPECT_EQ(expected, events[0].first.size());
    724       MockFrontend::HostIds& host_ids = events[0].first;
    725       EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host1.host_id())
    726           != host_ids.end());
    727       EXPECT_TRUE(std::find(host_ids.begin(), host_ids.end(), host3.host_id())
    728           != host_ids.end());
    729       EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
    730 
    731       events = mock_frontend2.raised_events_;
    732       expected = 1;
    733       EXPECT_EQ(expected, events.size());
    734       EXPECT_EQ(expected, events[0].first.size());  // 1 host using frontend2
    735       EXPECT_EQ(host2.host_id(), events[0].first[0]);
    736       EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
    737 
    738       events = mock_frontend3.raised_events_;
    739       EXPECT_TRUE(events.empty());
    740 
    741       // Abort as we're not testing actual URL fetches in this test.
    742       delete update;
    743     }
    744     UpdateFinished();
    745   }
    746 
    747   void CacheAttemptFetchManifestFailTest() {
    748     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    749 
    750     MakeService();
    751     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
    752                                service_->storage()->NewGroupId());
    753     AppCacheUpdateJob* update =
    754         new AppCacheUpdateJob(service_.get(), group_.get());
    755     group_->update_job_ = update;
    756 
    757     MockFrontend* frontend = MakeMockFrontend();
    758     AppCacheHost* host = MakeHost(1, frontend);
    759     update->StartUpdate(host, GURL());
    760     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    761 
    762     update->manifest_fetcher_->request()->CancelWithError(-100);
    763 
    764     // Set up checks for when update job finishes.
    765     do_checks_after_update_finished_ = true;
    766     expect_group_obsolete_ = false;
    767     expect_group_has_cache_ = false;
    768     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
    769                                APPCACHE_CHECKING_EVENT);
    770 
    771     WaitForUpdateToFinish();
    772   }
    773 
    774   void UpgradeFetchManifestFailTest() {
    775     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    776 
    777     MakeService();
    778     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"),
    779                                service_->storage()->NewGroupId());
    780     AppCacheUpdateJob* update =
    781         new AppCacheUpdateJob(service_.get(), group_.get());
    782     group_->update_job_ = update;
    783 
    784     AppCache* cache = MakeCacheForGroup(1, 111);
    785     MockFrontend* frontend1 = MakeMockFrontend();
    786     MockFrontend* frontend2 = MakeMockFrontend();
    787     AppCacheHost* host1 = MakeHost(1, frontend1);
    788     AppCacheHost* host2 = MakeHost(2, frontend2);
    789     host1->AssociateCompleteCache(cache);
    790     host2->AssociateCompleteCache(cache);
    791 
    792     update->StartUpdate(NULL, GURL());
    793     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    794 
    795     update->manifest_fetcher_->request()->CancelWithError(-100);
    796 
    797     // Set up checks for when update job finishes.
    798     do_checks_after_update_finished_ = true;
    799     expect_group_obsolete_ = false;
    800     expect_group_has_cache_ = true;
    801     expect_newest_cache_ = cache;  // newest cache unaffected by update
    802     MockFrontend::HostIds ids1(1, host1->host_id());
    803     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
    804     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
    805     MockFrontend::HostIds ids2(1, host2->host_id());
    806     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
    807     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
    808 
    809     WaitForUpdateToFinish();
    810   }
    811 
    812   void ManifestRedirectTest() {
    813     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    814 
    815     net::URLRequestJobFactoryImpl* new_factory(
    816         new net::URLRequestJobFactoryImpl);
    817     new_factory->SetProtocolHandler("http", new RedirectFactory);
    818     io_thread_->SetNewJobFactory(new_factory);
    819 
    820     MakeService();
    821     group_ = new AppCacheGroup(service_->storage(), GURL("http://testme"),
    822                                service_->storage()->NewGroupId());
    823     AppCacheUpdateJob* update =
    824         new AppCacheUpdateJob(service_.get(), group_.get());
    825     group_->update_job_ = update;
    826 
    827     MockFrontend* frontend = MakeMockFrontend();
    828     AppCacheHost* host = MakeHost(1, frontend);
    829     update->StartUpdate(host, GURL());
    830     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    831 
    832     // Set up checks for when update job finishes.
    833     do_checks_after_update_finished_ = true;
    834     expect_group_obsolete_ = false;
    835     expect_group_has_cache_ = false;  // redirect is like a failed request
    836     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
    837                                APPCACHE_CHECKING_EVENT);
    838 
    839     WaitForUpdateToFinish();
    840   }
    841 
    842   void ManifestMissingMimeTypeTest() {
    843     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    844 
    845     MakeService();
    846     group_ = new AppCacheGroup(
    847         service_->storage(),
    848         MockHttpServer::GetMockUrl("files/missing-mime-manifest"),
    849         service_->storage()->NewGroupId());
    850     AppCacheUpdateJob* update =
    851         new AppCacheUpdateJob(service_.get(), group_.get());
    852     group_->update_job_ = update;
    853 
    854     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
    855     MockFrontend* frontend = MakeMockFrontend();
    856     AppCacheHost* host = MakeHost(1, frontend);
    857     host->AssociateCompleteCache(cache);
    858 
    859     frontend->SetVerifyProgressEvents(true);
    860 
    861     update->StartUpdate(NULL, GURL());
    862     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    863 
    864     // Set up checks for when update job finishes.
    865     do_checks_after_update_finished_ = true;
    866     expect_group_obsolete_ = false;
    867     expect_group_has_cache_ = true;
    868     expect_old_cache_ = cache;
    869     tested_manifest_ = EMPTY_MANIFEST;
    870     tested_manifest_path_override_ = "files/missing-mime-manifest";
    871     MockFrontend::HostIds ids(1, host->host_id());
    872     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
    873     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
    874     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
    875     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
    876 
    877     WaitForUpdateToFinish();
    878   }
    879 
    880   void ManifestNotFoundTest() {
    881     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    882 
    883     MakeService();
    884     group_ = new AppCacheGroup(
    885         service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
    886         service_->storage()->NewGroupId());
    887     AppCacheUpdateJob* update =
    888         new AppCacheUpdateJob(service_.get(), group_.get());
    889     group_->update_job_ = update;
    890 
    891     AppCache* cache = MakeCacheForGroup(1, 111);
    892     MockFrontend* frontend1 = MakeMockFrontend();
    893     MockFrontend* frontend2 = MakeMockFrontend();
    894     AppCacheHost* host1 = MakeHost(1, frontend1);
    895     AppCacheHost* host2 = MakeHost(2, frontend2);
    896     host1->AssociateCompleteCache(cache);
    897     host2->AssociateCompleteCache(cache);
    898 
    899     update->StartUpdate(NULL, GURL());
    900     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    901 
    902     // Set up checks for when update job finishes.
    903     do_checks_after_update_finished_ = true;
    904     expect_group_obsolete_ = true;
    905     expect_group_has_cache_ = true;
    906     expect_newest_cache_ = cache;  // newest cache unaffected by update
    907     MockFrontend::HostIds ids1(1, host1->host_id());
    908     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
    909     frontend1->AddExpectedEvent(ids1, APPCACHE_OBSOLETE_EVENT);
    910     MockFrontend::HostIds ids2(1, host2->host_id());
    911     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
    912     frontend2->AddExpectedEvent(ids2, APPCACHE_OBSOLETE_EVENT);
    913 
    914     WaitForUpdateToFinish();
    915   }
    916 
    917   void ManifestGoneTest() {
    918     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    919 
    920     MakeService();
    921     group_ = new AppCacheGroup(
    922         service_->storage(), MockHttpServer::GetMockUrl("files/gone"),
    923         service_->storage()->NewGroupId());
    924     AppCacheUpdateJob* update =
    925         new AppCacheUpdateJob(service_.get(), group_.get());
    926     group_->update_job_ = update;
    927 
    928     MockFrontend* frontend = MakeMockFrontend();
    929     AppCacheHost* host = MakeHost(1, frontend);
    930     update->StartUpdate(host, GURL());
    931     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    932 
    933     // Set up checks for when update job finishes.
    934     do_checks_after_update_finished_ = true;
    935     expect_group_obsolete_ = false;
    936     expect_group_has_cache_ = false;
    937     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
    938                                APPCACHE_CHECKING_EVENT);
    939 
    940     WaitForUpdateToFinish();
    941   }
    942 
    943   void CacheAttemptNotModifiedTest() {
    944     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    945 
    946     MakeService();
    947     group_ = new AppCacheGroup(
    948         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
    949         service_->storage()->NewGroupId());
    950     AppCacheUpdateJob* update =
    951         new AppCacheUpdateJob(service_.get(), group_.get());
    952     group_->update_job_ = update;
    953 
    954     MockFrontend* frontend = MakeMockFrontend();
    955     AppCacheHost* host = MakeHost(1, frontend);
    956     update->StartUpdate(host, GURL());
    957     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    958 
    959     // Set up checks for when update job finishes.
    960     do_checks_after_update_finished_ = true;
    961     expect_group_obsolete_ = false;
    962     expect_group_has_cache_ = false;  // treated like cache failure
    963     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
    964                                APPCACHE_CHECKING_EVENT);
    965 
    966     WaitForUpdateToFinish();
    967   }
    968 
    969   void UpgradeNotModifiedTest() {
    970     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
    971 
    972     MakeService();
    973     group_ = new AppCacheGroup(
    974         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
    975         service_->storage()->NewGroupId());
    976     AppCacheUpdateJob* update =
    977         new AppCacheUpdateJob(service_.get(), group_.get());
    978     group_->update_job_ = update;
    979 
    980     AppCache* cache = MakeCacheForGroup(1, 111);
    981     MockFrontend* frontend1 = MakeMockFrontend();
    982     MockFrontend* frontend2 = MakeMockFrontend();
    983     AppCacheHost* host1 = MakeHost(1, frontend1);
    984     AppCacheHost* host2 = MakeHost(2, frontend2);
    985     host1->AssociateCompleteCache(cache);
    986     host2->AssociateCompleteCache(cache);
    987 
    988     update->StartUpdate(NULL, GURL());
    989     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
    990 
    991     // Set up checks for when update job finishes.
    992     do_checks_after_update_finished_ = true;
    993     expect_group_obsolete_ = false;
    994     expect_group_has_cache_ = true;
    995     expect_newest_cache_ = cache;  // newest cache unaffected by update
    996     MockFrontend::HostIds ids1(1, host1->host_id());
    997     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
    998     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
    999     MockFrontend::HostIds ids2(1, host2->host_id());
   1000     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1001     frontend2->AddExpectedEvent(ids2, APPCACHE_NO_UPDATE_EVENT);
   1002 
   1003     WaitForUpdateToFinish();
   1004   }
   1005 
   1006   void UpgradeManifestDataUnchangedTest() {
   1007     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1008 
   1009     MakeService();
   1010     group_ = new AppCacheGroup(
   1011         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1012         service_->storage()->NewGroupId());
   1013     AppCacheUpdateJob* update =
   1014         new AppCacheUpdateJob(service_.get(), group_.get());
   1015     group_->update_job_ = update;
   1016 
   1017     // Create response writer to get a response id.
   1018     response_writer_.reset(
   1019         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   1020                                                   group_->group_id()));
   1021 
   1022     AppCache* cache = MakeCacheForGroup(1, response_writer_->response_id());
   1023     MockFrontend* frontend1 = MakeMockFrontend();
   1024     MockFrontend* frontend2 = MakeMockFrontend();
   1025     AppCacheHost* host1 = MakeHost(1, frontend1);
   1026     AppCacheHost* host2 = MakeHost(2, frontend2);
   1027     host1->AssociateCompleteCache(cache);
   1028     host2->AssociateCompleteCache(cache);
   1029 
   1030     // Set up checks for when update job finishes.
   1031     do_checks_after_update_finished_ = true;
   1032     expect_group_obsolete_ = false;
   1033     expect_group_has_cache_ = true;
   1034     expect_newest_cache_ = cache;  // newest cache unaffected by update
   1035     MockFrontend::HostIds ids1(1, host1->host_id());
   1036     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1037     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
   1038     MockFrontend::HostIds ids2(1, host2->host_id());
   1039     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1040     frontend2->AddExpectedEvent(ids2, APPCACHE_NO_UPDATE_EVENT);
   1041 
   1042     // Seed storage with expected manifest data.
   1043     const std::string seed_data(kManifest1Contents);
   1044     scoped_refptr<net::StringIOBuffer> io_buffer(
   1045         new net::StringIOBuffer(seed_data));
   1046     response_writer_->WriteData(
   1047         io_buffer.get(),
   1048         seed_data.length(),
   1049         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   1050                    base::Unretained(this)));
   1051 
   1052     // Start update after data write completes asynchronously.
   1053   }
   1054 
   1055   // See http://code.google.com/p/chromium/issues/detail?id=95101
   1056   void Bug95101Test() {
   1057     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1058 
   1059     MakeService();
   1060     group_ = new AppCacheGroup(
   1061         service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
   1062         service_->storage()->NewGroupId());
   1063     AppCacheUpdateJob* update =
   1064         new AppCacheUpdateJob(service_.get(), group_.get());
   1065     group_->update_job_ = update;
   1066 
   1067     // Create a malformed cache with a missing manifest entry.
   1068     GURL wrong_manifest_url =
   1069         MockHttpServer::GetMockUrl("files/missing-mime-manifest");
   1070     AppCache* cache = MakeCacheForGroup(1, wrong_manifest_url, 111);
   1071     MockFrontend* frontend = MakeMockFrontend();
   1072     AppCacheHost* host = MakeHost(1, frontend);
   1073     host->AssociateCompleteCache(cache);
   1074 
   1075     update->StartUpdate(NULL, GURL());
   1076     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1077 
   1078     // Set up checks for when update job finishes.
   1079     do_checks_after_update_finished_ = true;
   1080     expect_group_is_being_deleted_ = true;
   1081     expect_group_has_cache_ = true;
   1082     expect_newest_cache_ = cache;  // newest cache unaffected by update
   1083     MockFrontend::HostIds id(1, host->host_id());
   1084     frontend->AddExpectedEvent(id, APPCACHE_CHECKING_EVENT);
   1085     frontend->AddExpectedEvent(id, APPCACHE_ERROR_EVENT);
   1086     frontend->expected_error_message_ =
   1087         "Manifest entry not found in existing cache";
   1088     WaitForUpdateToFinish();
   1089   }
   1090 
   1091   void StartUpdateAfterSeedingStorageData(int result) {
   1092     ASSERT_GT(result, 0);
   1093     response_writer_.reset();
   1094 
   1095     AppCacheUpdateJob* update = group_->update_job_;
   1096     update->StartUpdate(NULL, GURL());
   1097     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1098 
   1099     WaitForUpdateToFinish();
   1100   }
   1101 
   1102   void BasicCacheAttemptSuccessTest() {
   1103     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1104 
   1105     GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1");
   1106 
   1107     MakeService();
   1108     group_ = new AppCacheGroup(
   1109         service_->storage(), manifest_url,
   1110         service_->storage()->NewGroupId());
   1111     AppCacheUpdateJob* update =
   1112         new AppCacheUpdateJob(service_.get(), group_.get());
   1113     group_->update_job_ = update;
   1114 
   1115     MockFrontend* frontend = MakeMockFrontend();
   1116     AppCacheHost* host = MakeHost(1, frontend);
   1117     update->StartUpdate(host, GURL());
   1118 
   1119     // Set up checks for when update job finishes.
   1120     do_checks_after_update_finished_ = true;
   1121     expect_group_obsolete_ = false;
   1122     expect_group_has_cache_ = true;
   1123     tested_manifest_ = MANIFEST1;
   1124     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1125                                APPCACHE_CHECKING_EVENT);
   1126 
   1127     WaitForUpdateToFinish();
   1128   }
   1129 
   1130   void DownloadInterceptEntriesTest() {
   1131     // Ensures we download intercept entries too.
   1132     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1133     GURL manifest_url =
   1134         MockHttpServer::GetMockUrl("files/manifest-with-intercept");
   1135     MakeService();
   1136     group_ = new AppCacheGroup(
   1137         service_->storage(), manifest_url,
   1138         service_->storage()->NewGroupId());
   1139     AppCacheUpdateJob* update =
   1140         new AppCacheUpdateJob(service_.get(), group_.get());
   1141     group_->update_job_ = update;
   1142 
   1143     MockFrontend* frontend = MakeMockFrontend();
   1144     AppCacheHost* host = MakeHost(1, frontend);
   1145     update->StartUpdate(host, GURL());
   1146 
   1147     // Set up checks for when update job finishes.
   1148     do_checks_after_update_finished_ = true;
   1149     expect_group_obsolete_ = false;
   1150     expect_group_has_cache_ = true;
   1151     tested_manifest_ = MANIFEST_WITH_INTERCEPT;
   1152     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1153                                APPCACHE_CHECKING_EVENT);
   1154 
   1155     WaitForUpdateToFinish();
   1156   }
   1157 
   1158   void BasicUpgradeSuccessTest() {
   1159     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1160 
   1161     MakeService();
   1162     group_ = new AppCacheGroup(
   1163         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1164         service_->storage()->NewGroupId());
   1165     AppCacheUpdateJob* update =
   1166         new AppCacheUpdateJob(service_.get(), group_.get());
   1167     group_->update_job_ = update;
   1168 
   1169     // Create a response writer to get a response id.
   1170     response_writer_.reset(
   1171         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   1172                                                   group_->group_id()));
   1173 
   1174     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
   1175                                         response_writer_->response_id());
   1176     MockFrontend* frontend1 = MakeMockFrontend();
   1177     MockFrontend* frontend2 = MakeMockFrontend();
   1178     AppCacheHost* host1 = MakeHost(1, frontend1);
   1179     AppCacheHost* host2 = MakeHost(2, frontend2);
   1180     host1->AssociateCompleteCache(cache);
   1181     host2->AssociateCompleteCache(cache);
   1182     frontend1->SetVerifyProgressEvents(true);
   1183     frontend2->SetVerifyProgressEvents(true);
   1184 
   1185     // Set up checks for when update job finishes.
   1186     do_checks_after_update_finished_ = true;
   1187     expect_group_obsolete_ = false;
   1188     expect_group_has_cache_ = true;
   1189     expect_old_cache_ = cache;
   1190     tested_manifest_ = MANIFEST1;
   1191     MockFrontend::HostIds ids1(1, host1->host_id());
   1192     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1193     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1194     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   1195     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   1196     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   1197     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   1198     MockFrontend::HostIds ids2(1, host2->host_id());
   1199     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1200     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1201     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1202     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1203     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   1204     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
   1205 
   1206     // Seed storage with expected manifest data different from manifest1.
   1207     const std::string seed_data("different");
   1208     scoped_refptr<net::StringIOBuffer> io_buffer(
   1209         new net::StringIOBuffer(seed_data));
   1210     response_writer_->WriteData(
   1211         io_buffer.get(),
   1212         seed_data.length(),
   1213         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   1214                    base::Unretained(this)));
   1215 
   1216     // Start update after data write completes asynchronously.
   1217   }
   1218 
   1219   void UpgradeLoadFromNewestCacheTest() {
   1220     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1221 
   1222     MakeService();
   1223     group_ = new AppCacheGroup(
   1224         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1225         service_->storage()->NewGroupId());
   1226     AppCacheUpdateJob* update =
   1227         new AppCacheUpdateJob(service_.get(), group_.get());
   1228     group_->update_job_ = update;
   1229 
   1230     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   1231     MockFrontend* frontend = MakeMockFrontend();
   1232     AppCacheHost* host = MakeHost(1, frontend);
   1233     host->AssociateCompleteCache(cache);
   1234 
   1235     // Give the newest cache an entry that is in storage.
   1236     response_writer_.reset(
   1237         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   1238                                                   group_->group_id()));
   1239     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
   1240                     AppCacheEntry(AppCacheEntry::EXPLICIT,
   1241                                   response_writer_->response_id()));
   1242 
   1243     // Set up checks for when update job finishes.
   1244     do_checks_after_update_finished_ = true;
   1245     expect_group_obsolete_ = false;
   1246     expect_group_has_cache_ = true;
   1247     expect_old_cache_ = cache;
   1248     expect_response_ids_.insert(
   1249         std::map<GURL, int64>::value_type(
   1250             MockHttpServer::GetMockUrl("files/explicit1"),
   1251             response_writer_->response_id()));
   1252     tested_manifest_ = MANIFEST1;
   1253     MockFrontend::HostIds ids(1, host->host_id());
   1254     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
   1255     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
   1256     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1257     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1258     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
   1259     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
   1260 
   1261     // Seed storage with expected http response info for entry. Allow reuse.
   1262     const char data[] =
   1263         "HTTP/1.1 200 OK\0"
   1264         "Cache-Control: max-age=8675309\0"
   1265         "\0";
   1266     net::HttpResponseHeaders* headers =
   1267         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   1268     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   1269     response_info->request_time = base::Time::Now();
   1270     response_info->response_time = base::Time::Now();
   1271     response_info->headers = headers;  // adds ref to headers
   1272     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
   1273         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
   1274     response_writer_->WriteInfo(
   1275         io_buffer.get(),
   1276         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   1277                    base::Unretained(this)));
   1278 
   1279     // Start update after data write completes asynchronously.
   1280   }
   1281 
   1282   void UpgradeNoLoadFromNewestCacheTest() {
   1283     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1284 
   1285     MakeService();
   1286     group_ = new AppCacheGroup(
   1287         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1288         service_->storage()->NewGroupId());
   1289     AppCacheUpdateJob* update =
   1290         new AppCacheUpdateJob(service_.get(), group_.get());
   1291     group_->update_job_ = update;
   1292 
   1293     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   1294     MockFrontend* frontend = MakeMockFrontend();
   1295     AppCacheHost* host = MakeHost(1, frontend);
   1296     host->AssociateCompleteCache(cache);
   1297 
   1298     // Give the newest cache an entry that is in storage.
   1299     response_writer_.reset(
   1300         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   1301                                                   group_->group_id()));
   1302     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
   1303                     AppCacheEntry(AppCacheEntry::EXPLICIT,
   1304                                   response_writer_->response_id()));
   1305 
   1306     // Set up checks for when update job finishes.
   1307     do_checks_after_update_finished_ = true;
   1308     expect_group_obsolete_ = false;
   1309     expect_group_has_cache_ = true;
   1310     expect_old_cache_ = cache;
   1311     tested_manifest_ = MANIFEST1;
   1312     MockFrontend::HostIds ids(1, host->host_id());
   1313     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
   1314     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
   1315     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1316     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1317     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
   1318     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
   1319 
   1320     // Seed storage with expected http response info for entry. Do NOT
   1321     // allow reuse by setting an expires header in the past.
   1322     const char data[] =
   1323         "HTTP/1.1 200 OK\0"
   1324         "Expires: Thu, 01 Dec 1994 16:00:00 GMT\0"
   1325         "\0";
   1326     net::HttpResponseHeaders* headers =
   1327         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   1328     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   1329     response_info->request_time = base::Time::Now();
   1330     response_info->response_time = base::Time::Now();
   1331     response_info->headers = headers;  // adds ref to headers
   1332     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
   1333         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
   1334     response_writer_->WriteInfo(
   1335         io_buffer.get(),
   1336         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   1337                    base::Unretained(this)));
   1338 
   1339     // Start update after data write completes asynchronously.
   1340   }
   1341 
   1342   void UpgradeLoadFromNewestCacheVaryHeaderTest() {
   1343     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1344 
   1345     MakeService();
   1346     group_ = new AppCacheGroup(
   1347         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1348         service_->storage()->NewGroupId());
   1349     AppCacheUpdateJob* update =
   1350         new AppCacheUpdateJob(service_.get(), group_.get());
   1351     group_->update_job_ = update;
   1352 
   1353     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   1354     MockFrontend* frontend = MakeMockFrontend();
   1355     AppCacheHost* host = MakeHost(1, frontend);
   1356     host->AssociateCompleteCache(cache);
   1357 
   1358     // Give the newest cache an entry that is in storage.
   1359     response_writer_.reset(
   1360         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   1361                                                   group_->group_id()));
   1362     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
   1363                     AppCacheEntry(AppCacheEntry::EXPLICIT,
   1364                                   response_writer_->response_id()));
   1365 
   1366     // Set up checks for when update job finishes.
   1367     do_checks_after_update_finished_ = true;
   1368     expect_group_obsolete_ = false;
   1369     expect_group_has_cache_ = true;
   1370     expect_old_cache_ = cache;
   1371     tested_manifest_ = MANIFEST1;
   1372     MockFrontend::HostIds ids(1, host->host_id());
   1373     frontend->AddExpectedEvent(ids, APPCACHE_CHECKING_EVENT);
   1374     frontend->AddExpectedEvent(ids, APPCACHE_DOWNLOADING_EVENT);
   1375     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1376     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);
   1377     frontend->AddExpectedEvent(ids, APPCACHE_PROGRESS_EVENT);  // final
   1378     frontend->AddExpectedEvent(ids, APPCACHE_UPDATE_READY_EVENT);
   1379 
   1380     // Seed storage with expected http response info for entry: a vary header.
   1381     const char data[] =
   1382         "HTTP/1.1 200 OK\0"
   1383         "Cache-Control: max-age=8675309\0"
   1384         "Vary: blah\0"
   1385         "\0";
   1386     net::HttpResponseHeaders* headers =
   1387         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   1388     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   1389     response_info->request_time = base::Time::Now();
   1390     response_info->response_time = base::Time::Now();
   1391     response_info->headers = headers;  // adds ref to headers
   1392     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
   1393         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
   1394     response_writer_->WriteInfo(
   1395         io_buffer.get(),
   1396         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   1397                    base::Unretained(this)));
   1398 
   1399     // Start update after data write completes asynchronously.
   1400   }
   1401 
   1402   void UpgradeSuccessMergedTypesTest() {
   1403     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1404 
   1405     MakeService();
   1406     group_ = new AppCacheGroup(service_->storage(),
   1407         MockHttpServer::GetMockUrl("files/manifest-merged-types"),
   1408         service_->storage()->NewGroupId());
   1409     AppCacheUpdateJob* update =
   1410         new AppCacheUpdateJob(service_.get(), group_.get());
   1411     group_->update_job_ = update;
   1412 
   1413     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   1414     MockFrontend* frontend1 = MakeMockFrontend();
   1415     MockFrontend* frontend2 = MakeMockFrontend();
   1416     AppCacheHost* host1 = MakeHost(1, frontend1);
   1417     AppCacheHost* host2 = MakeHost(2, frontend2);
   1418     host1->AssociateCompleteCache(cache);
   1419     host2->AssociateCompleteCache(cache);
   1420 
   1421     // Give the newest cache a master entry that is also one of the explicit
   1422     // entries in the manifest.
   1423     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
   1424                     AppCacheEntry(AppCacheEntry::MASTER, 111));
   1425 
   1426     update->StartUpdate(NULL, GURL());
   1427     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1428 
   1429     // Set up checks for when update job finishes.
   1430     do_checks_after_update_finished_ = true;
   1431     expect_group_obsolete_ = false;
   1432     expect_group_has_cache_ = true;
   1433     expect_old_cache_ = cache;
   1434     tested_manifest_ = MANIFEST_MERGED_TYPES;
   1435     MockFrontend::HostIds ids1(1, host1->host_id());
   1436     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1437     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1438     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit1
   1439     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // manifest
   1440     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   1441     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   1442     MockFrontend::HostIds ids2(1, host2->host_id());
   1443     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1444     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1445     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1446     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1447     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   1448     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
   1449 
   1450     WaitForUpdateToFinish();
   1451   }
   1452 
   1453   void CacheAttemptFailUrlFetchTest() {
   1454     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1455 
   1456     MakeService();
   1457     group_ = new AppCacheGroup(service_->storage(),
   1458         MockHttpServer::GetMockUrl("files/manifest-with-404"),
   1459         service_->storage()->NewGroupId());
   1460     AppCacheUpdateJob* update =
   1461         new AppCacheUpdateJob(service_.get(), group_.get());
   1462     group_->update_job_ = update;
   1463 
   1464     MockFrontend* frontend = MakeMockFrontend();
   1465     AppCacheHost* host = MakeHost(1, frontend);
   1466     update->StartUpdate(host, GURL());
   1467     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1468 
   1469     // Set up checks for when update job finishes.
   1470     do_checks_after_update_finished_ = true;
   1471     expect_group_obsolete_ = false;
   1472     expect_group_has_cache_ = false;  // 404 explicit url is cache failure
   1473     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1474                                APPCACHE_CHECKING_EVENT);
   1475 
   1476     WaitForUpdateToFinish();
   1477   }
   1478 
   1479   void UpgradeFailUrlFetchTest() {
   1480     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1481 
   1482     MakeService();
   1483     group_ = new AppCacheGroup(service_->storage(),
   1484         MockHttpServer::GetMockUrl("files/manifest-fb-404"),
   1485         service_->storage()->NewGroupId());
   1486     AppCacheUpdateJob* update =
   1487         new AppCacheUpdateJob(service_.get(), group_.get());
   1488     group_->update_job_ = update;
   1489 
   1490     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 99);
   1491     MockFrontend* frontend1 = MakeMockFrontend();
   1492     MockFrontend* frontend2 = MakeMockFrontend();
   1493     frontend1->SetIgnoreProgressEvents(true);
   1494     frontend2->SetIgnoreProgressEvents(true);
   1495     AppCacheHost* host1 = MakeHost(1, frontend1);
   1496     AppCacheHost* host2 = MakeHost(2, frontend2);
   1497     host1->AssociateCompleteCache(cache);
   1498     host2->AssociateCompleteCache(cache);
   1499 
   1500     update->StartUpdate(NULL, GURL());
   1501     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1502 
   1503     // Set up checks for when update job finishes.
   1504     do_checks_after_update_finished_ = true;
   1505     expect_group_obsolete_ = false;
   1506     expect_group_has_cache_ = true;
   1507     expect_newest_cache_ = cache;  // newest cache unaffectd by failed update
   1508     MockFrontend::HostIds ids1(1, host1->host_id());
   1509     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1510     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1511     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   1512     MockFrontend::HostIds ids2(1, host2->host_id());
   1513     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1514     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1515     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   1516 
   1517     WaitForUpdateToFinish();
   1518   }
   1519 
   1520   void UpgradeFailMasterUrlFetchTest() {
   1521     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1522 
   1523     tested_manifest_path_override_ = "files/manifest1-with-notmodified";
   1524 
   1525     MakeService();
   1526     const GURL kManifestUrl =
   1527         MockHttpServer::GetMockUrl(tested_manifest_path_override_);
   1528     group_ = new AppCacheGroup(
   1529         service_->storage(), kManifestUrl,
   1530         service_->storage()->NewGroupId());
   1531     AppCacheUpdateJob* update =
   1532         new AppCacheUpdateJob(service_.get(), group_.get());
   1533     group_->update_job_ = update;
   1534 
   1535     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 25);
   1536     MockFrontend* frontend1 = MakeMockFrontend();
   1537     MockFrontend* frontend2 = MakeMockFrontend();
   1538     AppCacheHost* host1 = MakeHost(1, frontend1);
   1539     AppCacheHost* host2 = MakeHost(2, frontend2);
   1540     host1->AssociateCompleteCache(cache);
   1541     host2->AssociateCompleteCache(cache);
   1542 
   1543     // Give the newest cache some existing entries; one will fail with a 404.
   1544     cache->AddEntry(
   1545         MockHttpServer::GetMockUrl("files/notfound"),
   1546         AppCacheEntry(AppCacheEntry::MASTER, 222));
   1547     cache->AddEntry(
   1548         MockHttpServer::GetMockUrl("files/explicit2"),
   1549         AppCacheEntry(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, 333));
   1550     cache->AddEntry(
   1551         MockHttpServer::GetMockUrl("files/servererror"),
   1552         AppCacheEntry(AppCacheEntry::MASTER, 444));
   1553     cache->AddEntry(
   1554         MockHttpServer::GetMockUrl("files/notmodified"),
   1555         AppCacheEntry(AppCacheEntry::EXPLICIT, 555));
   1556 
   1557     // Seed the response_info working set with canned data for
   1558     // files/servererror and for files/notmodified to test that the
   1559     // existing entries for those resource are reused by the update job.
   1560     const char kData[] =
   1561         "HTTP/1.1 200 OK\0"
   1562         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
   1563         "\0";
   1564     const std::string kRawHeaders(kData, arraysize(kData));
   1565     MakeAppCacheResponseInfo(kManifestUrl, 444, kRawHeaders);
   1566     MakeAppCacheResponseInfo(kManifestUrl, 555, kRawHeaders);
   1567 
   1568     update->StartUpdate(NULL, GURL());
   1569     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1570 
   1571     // Set up checks for when update job finishes.
   1572     do_checks_after_update_finished_ = true;
   1573     expect_group_obsolete_ = false;
   1574     expect_group_has_cache_ = true;
   1575     expect_old_cache_ = cache;
   1576     tested_manifest_ = MANIFEST1;
   1577     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   1578         MockHttpServer::GetMockUrl("files/explicit2"),
   1579         AppCacheEntry(AppCacheEntry::MASTER)));  // foreign flag is dropped
   1580     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   1581         MockHttpServer::GetMockUrl("files/servererror"),
   1582         AppCacheEntry(AppCacheEntry::MASTER)));
   1583     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   1584         MockHttpServer::GetMockUrl("files/notmodified"),
   1585         AppCacheEntry(AppCacheEntry::EXPLICIT)));
   1586     expect_response_ids_.insert(std::map<GURL, int64>::value_type(
   1587         MockHttpServer::GetMockUrl("files/servererror"), 444));  // copied
   1588     expect_response_ids_.insert(std::map<GURL, int64>::value_type(
   1589         MockHttpServer::GetMockUrl("files/notmodified"), 555));  // copied
   1590     MockFrontend::HostIds ids1(1, host1->host_id());
   1591     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1592     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1593     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit1
   1594     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // fallback1a
   1595     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // notfound
   1596     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // explicit2
   1597     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // servererror
   1598     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // notmodified
   1599     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   1600     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   1601     MockFrontend::HostIds ids2(1, host2->host_id());
   1602     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1603     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1604     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // explicit1
   1605     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // fallback1a
   1606     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // notfound
   1607     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // explicit2
   1608     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // servererror
   1609     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // notmodified
   1610     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   1611     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
   1612 
   1613     WaitForUpdateToFinish();
   1614   }
   1615 
   1616   void EmptyManifestTest() {
   1617     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1618 
   1619     MakeService();
   1620     group_ = new AppCacheGroup(
   1621         service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
   1622         service_->storage()->NewGroupId());
   1623     AppCacheUpdateJob* update =
   1624         new AppCacheUpdateJob(service_.get(), group_.get());
   1625     group_->update_job_ = update;
   1626 
   1627     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
   1628     MockFrontend* frontend1 = MakeMockFrontend();
   1629     MockFrontend* frontend2 = MakeMockFrontend();
   1630     AppCacheHost* host1 = MakeHost(1, frontend1);
   1631     AppCacheHost* host2 = MakeHost(2, frontend2);
   1632     host1->AssociateCompleteCache(cache);
   1633     host2->AssociateCompleteCache(cache);
   1634 
   1635     frontend1->SetVerifyProgressEvents(true);
   1636 
   1637     update->StartUpdate(NULL, GURL());
   1638     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1639 
   1640     // Set up checks for when update job finishes.
   1641     do_checks_after_update_finished_ = true;
   1642     expect_group_obsolete_ = false;
   1643     expect_group_has_cache_ = true;
   1644     expect_old_cache_ = cache;
   1645     tested_manifest_ = EMPTY_MANIFEST;
   1646     MockFrontend::HostIds ids1(1, host1->host_id());
   1647     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1648     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1649     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   1650     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   1651     MockFrontend::HostIds ids2(1, host2->host_id());
   1652     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1653     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1654     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   1655     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
   1656 
   1657     WaitForUpdateToFinish();
   1658   }
   1659 
   1660   void EmptyFileTest() {
   1661     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1662 
   1663     MakeService();
   1664     group_ = new AppCacheGroup(service_->storage(),
   1665         MockHttpServer::GetMockUrl("files/empty-file-manifest"),
   1666         service_->storage()->NewGroupId());
   1667     AppCacheUpdateJob* update =
   1668         new AppCacheUpdateJob(service_.get(), group_.get());
   1669     group_->update_job_ = update;
   1670 
   1671     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 22);
   1672     MockFrontend* frontend = MakeMockFrontend();
   1673     AppCacheHost* host = MakeHost(1, frontend);
   1674     host->AssociateCompleteCache(cache);
   1675     frontend->SetVerifyProgressEvents(true);
   1676 
   1677     update->StartUpdate(host, GURL());
   1678     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1679 
   1680     // Set up checks for when update job finishes.
   1681     do_checks_after_update_finished_ = true;
   1682     expect_group_obsolete_ = false;
   1683     expect_group_has_cache_ = true;
   1684     tested_manifest_ = EMPTY_FILE_MANIFEST;
   1685     MockFrontend::HostIds ids1(1, host->host_id());
   1686     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1687     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1688     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   1689     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   1690     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   1691 
   1692     WaitForUpdateToFinish();
   1693   }
   1694 
   1695   void RetryRequestTest() {
   1696     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1697 
   1698     // Set some large number of times to return retry.
   1699     // Expect 1 manifest fetch and 3 retries.
   1700     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
   1701     net::URLRequestJobFactoryImpl* new_factory(
   1702         new net::URLRequestJobFactoryImpl);
   1703     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
   1704     io_thread_->SetNewJobFactory(new_factory);
   1705 
   1706     MakeService();
   1707     group_ = new AppCacheGroup(service_->storage(),
   1708                                RetryRequestTestJob::kRetryUrl,
   1709                                service_->storage()->NewGroupId());
   1710     AppCacheUpdateJob* update =
   1711         new AppCacheUpdateJob(service_.get(), group_.get());
   1712     group_->update_job_ = update;
   1713 
   1714     MockFrontend* frontend = MakeMockFrontend();
   1715     AppCacheHost* host = MakeHost(1, frontend);
   1716     update->StartUpdate(host, GURL());
   1717     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1718 
   1719     // Set up checks for when update job finishes.
   1720     do_checks_after_update_finished_ = true;
   1721     expect_group_obsolete_ = false;
   1722     expect_group_has_cache_ = false;
   1723     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1724                                APPCACHE_CHECKING_EVENT);
   1725 
   1726     WaitForUpdateToFinish();
   1727   }
   1728 
   1729   void RetryNoRetryAfterTest() {
   1730     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1731 
   1732     // Set some large number of times to return retry.
   1733     // Expect 1 manifest fetch and 0 retries.
   1734     RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
   1735     net::URLRequestJobFactoryImpl* new_factory(
   1736         new net::URLRequestJobFactoryImpl);
   1737     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
   1738     io_thread_->SetNewJobFactory(new_factory);
   1739 
   1740     MakeService();
   1741     group_ = new AppCacheGroup(service_->storage(),
   1742                                RetryRequestTestJob::kRetryUrl,
   1743                                service_->storage()->NewGroupId());
   1744     AppCacheUpdateJob* update =
   1745         new AppCacheUpdateJob(service_.get(), group_.get());
   1746     group_->update_job_ = update;
   1747 
   1748     MockFrontend* frontend = MakeMockFrontend();
   1749     AppCacheHost* host = MakeHost(1, frontend);
   1750     update->StartUpdate(host, GURL());
   1751     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1752 
   1753     // Set up checks for when update job finishes.
   1754     do_checks_after_update_finished_ = true;
   1755     expect_group_obsolete_ = false;
   1756     expect_group_has_cache_ = false;
   1757     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1758                                APPCACHE_CHECKING_EVENT);
   1759 
   1760     WaitForUpdateToFinish();
   1761   }
   1762 
   1763   void RetryNonzeroRetryAfterTest() {
   1764     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1765 
   1766     // Set some large number of times to return retry.
   1767     // Expect 1 request and 0 retry attempts.
   1768     RetryRequestTestJob::Initialize(
   1769         5, RetryRequestTestJob::NONZERO_RETRY_AFTER, 1);
   1770     net::URLRequestJobFactoryImpl* new_factory(
   1771         new net::URLRequestJobFactoryImpl);
   1772     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
   1773     io_thread_->SetNewJobFactory(new_factory);
   1774 
   1775     MakeService();
   1776     group_ = new AppCacheGroup(service_->storage(),
   1777                                RetryRequestTestJob::kRetryUrl,
   1778                                service_->storage()->NewGroupId());
   1779     AppCacheUpdateJob* update =
   1780         new AppCacheUpdateJob(service_.get(), group_.get());
   1781     group_->update_job_ = update;
   1782 
   1783     MockFrontend* frontend = MakeMockFrontend();
   1784     AppCacheHost* host = MakeHost(1, frontend);
   1785     update->StartUpdate(host, GURL());
   1786     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1787 
   1788     // Set up checks for when update job finishes.
   1789     do_checks_after_update_finished_ = true;
   1790     expect_group_obsolete_ = false;
   1791     expect_group_has_cache_ = false;
   1792     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1793                                APPCACHE_CHECKING_EVENT);
   1794 
   1795     WaitForUpdateToFinish();
   1796   }
   1797 
   1798   void RetrySuccessTest() {
   1799     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1800 
   1801     // Set 2 as the retry limit (does not exceed the max).
   1802     // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
   1803     RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
   1804     net::URLRequestJobFactoryImpl* new_factory(
   1805         new net::URLRequestJobFactoryImpl);
   1806     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
   1807     io_thread_->SetNewJobFactory(new_factory);
   1808 
   1809     MakeService();
   1810     group_ = new AppCacheGroup(service_->storage(),
   1811                                RetryRequestTestJob::kRetryUrl,
   1812                                service_->storage()->NewGroupId());
   1813     AppCacheUpdateJob* update =
   1814         new AppCacheUpdateJob(service_.get(), group_.get());
   1815     group_->update_job_ = update;
   1816 
   1817     MockFrontend* frontend = MakeMockFrontend();
   1818     AppCacheHost* host = MakeHost(1, frontend);
   1819     update->StartUpdate(host, GURL());
   1820     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1821 
   1822     // Set up checks for when update job finishes.
   1823     do_checks_after_update_finished_ = true;
   1824     expect_group_obsolete_ = false;
   1825     expect_group_has_cache_ = true;
   1826     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1827                                APPCACHE_CHECKING_EVENT);
   1828 
   1829     WaitForUpdateToFinish();
   1830   }
   1831 
   1832   void RetryUrlTest() {
   1833     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1834 
   1835     // Set 1 as the retry limit (does not exceed the max).
   1836     // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
   1837     RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
   1838     net::URLRequestJobFactoryImpl* new_factory(
   1839         new net::URLRequestJobFactoryImpl);
   1840     new_factory->SetProtocolHandler("http", new RetryRequestTestJobFactory);
   1841     io_thread_->SetNewJobFactory(new_factory);
   1842 
   1843     MakeService();
   1844     group_ = new AppCacheGroup(service_->storage(), GURL("http://retryurl"),
   1845                                service_->storage()->NewGroupId());
   1846     AppCacheUpdateJob* update =
   1847         new AppCacheUpdateJob(service_.get(), group_.get());
   1848     group_->update_job_ = update;
   1849 
   1850     MockFrontend* frontend = MakeMockFrontend();
   1851     AppCacheHost* host = MakeHost(1, frontend);
   1852     update->StartUpdate(host, GURL());
   1853     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   1854 
   1855     // Set up checks for when update job finishes.
   1856     do_checks_after_update_finished_ = true;
   1857     expect_group_obsolete_ = false;
   1858     expect_group_has_cache_ = true;
   1859     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1860                                APPCACHE_CHECKING_EVENT);
   1861 
   1862     WaitForUpdateToFinish();
   1863   }
   1864 
   1865   void FailStoreNewestCacheTest() {
   1866     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1867 
   1868     MakeService();
   1869     MockAppCacheStorage* storage =
   1870         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
   1871     storage->SimulateStoreGroupAndNewestCacheFailure();
   1872 
   1873     group_ = new AppCacheGroup(
   1874         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1875         service_->storage()->NewGroupId());
   1876     AppCacheUpdateJob* update =
   1877         new AppCacheUpdateJob(service_.get(), group_.get());
   1878     group_->update_job_ = update;
   1879 
   1880     MockFrontend* frontend = MakeMockFrontend();
   1881     AppCacheHost* host = MakeHost(1, frontend);
   1882     update->StartUpdate(host, GURL());
   1883 
   1884     // Set up checks for when update job finishes.
   1885     do_checks_after_update_finished_ = true;
   1886     expect_group_obsolete_ = false;
   1887     expect_group_has_cache_ = false;  // storage failed
   1888     frontend->AddExpectedEvent(MockFrontend::HostIds(1, host->host_id()),
   1889                                APPCACHE_CHECKING_EVENT);
   1890 
   1891     WaitForUpdateToFinish();
   1892   }
   1893 
   1894   void UpgradeFailStoreNewestCacheTest() {
   1895     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1896 
   1897     MakeService();
   1898     MockAppCacheStorage* storage =
   1899         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
   1900     storage->SimulateStoreGroupAndNewestCacheFailure();
   1901 
   1902     group_ = new AppCacheGroup(
   1903         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   1904         service_->storage()->NewGroupId());
   1905     AppCacheUpdateJob* update =
   1906         new AppCacheUpdateJob(service_.get(), group_.get());
   1907     group_->update_job_ = update;
   1908 
   1909     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 11);
   1910     MockFrontend* frontend1 = MakeMockFrontend();
   1911     MockFrontend* frontend2 = MakeMockFrontend();
   1912     AppCacheHost* host1 = MakeHost(1, frontend1);
   1913     AppCacheHost* host2 = MakeHost(2, frontend2);
   1914     host1->AssociateCompleteCache(cache);
   1915     host2->AssociateCompleteCache(cache);
   1916 
   1917     update->StartUpdate(NULL, GURL());
   1918 
   1919     // Set up checks for when update job finishes.
   1920     do_checks_after_update_finished_ = true;
   1921     expect_group_obsolete_ = false;
   1922     expect_group_has_cache_ = true;
   1923     expect_newest_cache_ = cache;  // unchanged
   1924     MockFrontend::HostIds ids1(1, host1->host_id());
   1925     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   1926     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   1927     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   1928     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   1929     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   1930     MockFrontend::HostIds ids2(1, host2->host_id());
   1931     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   1932     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   1933     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1934     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   1935     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   1936 
   1937     WaitForUpdateToFinish();
   1938   }
   1939 
   1940   void MasterEntryFailStoreNewestCacheTest() {
   1941     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1942 
   1943     MakeService();
   1944     MockAppCacheStorage* storage =
   1945         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
   1946     storage->SimulateStoreGroupAndNewestCacheFailure();
   1947 
   1948     const GURL kManifestUrl = MockHttpServer::GetMockUrl("files/notmodified");
   1949     const int64 kManifestResponseId = 11;
   1950 
   1951     // Seed the response_info working set with canned data for
   1952     // files/servererror and for files/notmodified to test that the
   1953     // existing entries for those resource are reused by the update job.
   1954     const char kData[] =
   1955         "HTTP/1.1 200 OK\0"
   1956         "Content-type: text/cache-manifest\0"
   1957         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
   1958         "\0";
   1959     const std::string kRawHeaders(kData, arraysize(kData));
   1960     MakeAppCacheResponseInfo(kManifestUrl, kManifestResponseId, kRawHeaders);
   1961 
   1962     group_ = new AppCacheGroup(
   1963         service_->storage(), kManifestUrl,
   1964         service_->storage()->NewGroupId());
   1965     scoped_refptr<AppCache> cache(
   1966         MakeCacheForGroup(service_->storage()->NewCacheId(),
   1967                           kManifestResponseId));
   1968 
   1969     MockFrontend* frontend = MakeMockFrontend();
   1970     AppCacheHost* host = MakeHost(1, frontend);
   1971     host->first_party_url_ = kManifestUrl;
   1972     host->SelectCache(MockHttpServer::GetMockUrl("files/empty1"),
   1973                       kAppCacheNoCacheId, kManifestUrl);
   1974 
   1975     // Set up checks for when update job finishes.
   1976     do_checks_after_update_finished_ = true;
   1977     tested_manifest_ = EMPTY_MANIFEST;
   1978     tested_manifest_path_override_ = "files/notmodified";
   1979     expect_group_obsolete_ = false;
   1980     expect_group_has_cache_ = true;
   1981     expect_newest_cache_ = cache.get();  // unchanged
   1982     MockFrontend::HostIds ids1(1, host->host_id());
   1983     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   1984     frontend->expected_error_message_ =
   1985         "Failed to commit new cache to storage";
   1986 
   1987     WaitForUpdateToFinish();
   1988   }
   1989 
   1990   void UpgradeFailMakeGroupObsoleteTest() {
   1991     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   1992 
   1993     MakeService();
   1994     MockAppCacheStorage* storage =
   1995         reinterpret_cast<MockAppCacheStorage*>(service_->storage());
   1996     storage->SimulateMakeGroupObsoleteFailure();
   1997 
   1998     group_ = new AppCacheGroup(
   1999         service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
   2000         service_->storage()->NewGroupId());
   2001     AppCacheUpdateJob* update =
   2002         new AppCacheUpdateJob(service_.get(), group_.get());
   2003     group_->update_job_ = update;
   2004 
   2005     AppCache* cache = MakeCacheForGroup(1, 111);
   2006     MockFrontend* frontend1 = MakeMockFrontend();
   2007     MockFrontend* frontend2 = MakeMockFrontend();
   2008     AppCacheHost* host1 = MakeHost(1, frontend1);
   2009     AppCacheHost* host2 = MakeHost(2, frontend2);
   2010     host1->AssociateCompleteCache(cache);
   2011     host2->AssociateCompleteCache(cache);
   2012 
   2013     update->StartUpdate(NULL, GURL());
   2014     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2015 
   2016     // Set up checks for when update job finishes.
   2017     do_checks_after_update_finished_ = true;
   2018     expect_group_obsolete_ = false;
   2019     expect_group_has_cache_ = true;
   2020     expect_newest_cache_ = cache;  // newest cache unaffected by update
   2021     MockFrontend::HostIds ids1(1, host1->host_id());
   2022     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2023     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2024     MockFrontend::HostIds ids2(1, host2->host_id());
   2025     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   2026     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2027 
   2028     WaitForUpdateToFinish();
   2029   }
   2030 
   2031   void MasterEntryFetchManifestFailTest() {
   2032     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2033 
   2034     MakeService();
   2035     group_ = new AppCacheGroup(service_->storage(), GURL("http://failme"), 111);
   2036     AppCacheUpdateJob* update =
   2037         new AppCacheUpdateJob(service_.get(), group_.get());
   2038     group_->update_job_ = update;
   2039 
   2040     MockFrontend* frontend = MakeMockFrontend();
   2041     AppCacheHost* host = MakeHost(1, frontend);
   2042     host->new_master_entry_url_ = GURL("http://failme/blah");
   2043     update->StartUpdate(host, host->new_master_entry_url_);
   2044     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2045 
   2046     update->manifest_fetcher_->request()->CancelWithError(-100);
   2047 
   2048     // Set up checks for when update job finishes.
   2049     do_checks_after_update_finished_ = true;
   2050     expect_group_obsolete_ = false;
   2051     expect_group_has_cache_ = false;
   2052     MockFrontend::HostIds ids1(1, host->host_id());
   2053     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2054     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2055 
   2056     WaitForUpdateToFinish();
   2057   }
   2058 
   2059   void MasterEntryBadManifestTest() {
   2060     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2061 
   2062     MakeService();
   2063     group_ = new AppCacheGroup(service_->storage(),
   2064         MockHttpServer::GetMockUrl("files/bad-manifest"), 111);
   2065     AppCacheUpdateJob* update =
   2066         new AppCacheUpdateJob(service_.get(), group_.get());
   2067     group_->update_job_ = update;
   2068 
   2069     MockFrontend* frontend = MakeMockFrontend();
   2070     AppCacheHost* host = MakeHost(1, frontend);
   2071     host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
   2072     update->StartUpdate(host, host->new_master_entry_url_);
   2073     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2074 
   2075     // Set up checks for when update job finishes.
   2076     do_checks_after_update_finished_ = true;
   2077     expect_group_obsolete_ = false;
   2078     expect_group_has_cache_ = false;
   2079     MockFrontend::HostIds ids1(1, host->host_id());
   2080     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2081     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2082 
   2083     WaitForUpdateToFinish();
   2084   }
   2085 
   2086   void MasterEntryManifestNotFoundTest() {
   2087     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2088 
   2089     MakeService();
   2090     group_ = new AppCacheGroup(
   2091         service_->storage(),
   2092         MockHttpServer::GetMockUrl("files/nosuchfile"),
   2093         111);
   2094     AppCacheUpdateJob* update =
   2095         new AppCacheUpdateJob(service_.get(), group_.get());
   2096     group_->update_job_ = update;
   2097 
   2098     MockFrontend* frontend = MakeMockFrontend();
   2099     AppCacheHost* host = MakeHost(1, frontend);
   2100     host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
   2101 
   2102     update->StartUpdate(host, host->new_master_entry_url_);
   2103     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2104 
   2105     // Set up checks for when update job finishes.
   2106     do_checks_after_update_finished_ = true;
   2107     expect_group_obsolete_ = false;
   2108     expect_group_has_cache_ = false;
   2109     MockFrontend::HostIds ids1(1, host->host_id());
   2110     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2111     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2112 
   2113     WaitForUpdateToFinish();
   2114   }
   2115 
   2116   void MasterEntryFailUrlFetchTest() {
   2117     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2118 
   2119     MakeService();
   2120     group_ = new AppCacheGroup(service_->storage(),
   2121         MockHttpServer::GetMockUrl("files/manifest-fb-404"), 111);
   2122     AppCacheUpdateJob* update =
   2123         new AppCacheUpdateJob(service_.get(), group_.get());
   2124     group_->update_job_ = update;
   2125 
   2126     MockFrontend* frontend = MakeMockFrontend();
   2127     frontend->SetIgnoreProgressEvents(true);
   2128     AppCacheHost* host = MakeHost(1, frontend);
   2129     host->new_master_entry_url_ =
   2130         MockHttpServer::GetMockUrl("files/explicit1");
   2131 
   2132     update->StartUpdate(host, host->new_master_entry_url_);
   2133     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2134 
   2135     // Set up checks for when update job finishes.
   2136     do_checks_after_update_finished_ = true;
   2137     expect_group_obsolete_ = false;
   2138     expect_group_has_cache_ = false;  // 404 fallback url is cache failure
   2139     MockFrontend::HostIds ids1(1, host->host_id());
   2140     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2141     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2142     frontend->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2143 
   2144     WaitForUpdateToFinish();
   2145   }
   2146 
   2147   void MasterEntryAllFailTest() {
   2148     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2149 
   2150     MakeService();
   2151     group_ = new AppCacheGroup(
   2152         service_->storage(),
   2153         MockHttpServer::GetMockUrl("files/manifest1"),
   2154         111);
   2155     AppCacheUpdateJob* update =
   2156         new AppCacheUpdateJob(service_.get(), group_.get());
   2157     group_->update_job_ = update;
   2158 
   2159     MockFrontend* frontend1 = MakeMockFrontend();
   2160     frontend1->SetIgnoreProgressEvents(true);
   2161     AppCacheHost* host1 = MakeHost(1, frontend1);
   2162     host1->new_master_entry_url_ =
   2163         MockHttpServer::GetMockUrl("files/nosuchfile");
   2164     update->StartUpdate(host1, host1->new_master_entry_url_);
   2165 
   2166     MockFrontend* frontend2 = MakeMockFrontend();
   2167     frontend2->SetIgnoreProgressEvents(true);
   2168     AppCacheHost* host2 = MakeHost(2, frontend2);
   2169     host2->new_master_entry_url_ =
   2170         MockHttpServer::GetMockUrl("files/servererror");
   2171     update->StartUpdate(host2, host2->new_master_entry_url_);
   2172 
   2173     // Set up checks for when update job finishes.
   2174     do_checks_after_update_finished_ = true;
   2175     expect_group_obsolete_ = false;
   2176     expect_group_has_cache_ = false;  // all pending masters failed
   2177     MockFrontend::HostIds ids1(1, host1->host_id());
   2178     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2179     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2180     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2181     MockFrontend::HostIds ids2(1, host2->host_id());
   2182     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   2183     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2184     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2185 
   2186     WaitForUpdateToFinish();
   2187   }
   2188 
   2189   void UpgradeMasterEntryAllFailTest() {
   2190     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2191 
   2192     MakeService();
   2193     group_ = new AppCacheGroup(
   2194         service_->storage(),
   2195         MockHttpServer::GetMockUrl("files/manifest1"),
   2196         111);
   2197     AppCacheUpdateJob* update =
   2198         new AppCacheUpdateJob(service_.get(), group_.get());
   2199     group_->update_job_ = update;
   2200 
   2201     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   2202     MockFrontend* frontend1 = MakeMockFrontend();
   2203     AppCacheHost* host1 = MakeHost(1, frontend1);
   2204     host1->AssociateCompleteCache(cache);
   2205 
   2206     MockFrontend* frontend2 = MakeMockFrontend();
   2207     frontend2->SetIgnoreProgressEvents(true);
   2208     AppCacheHost* host2 = MakeHost(2, frontend2);
   2209     host2->new_master_entry_url_ =
   2210         MockHttpServer::GetMockUrl("files/nosuchfile");
   2211     update->StartUpdate(host2, host2->new_master_entry_url_);
   2212 
   2213     MockFrontend* frontend3 = MakeMockFrontend();
   2214     frontend3->SetIgnoreProgressEvents(true);
   2215     AppCacheHost* host3 = MakeHost(3, frontend3);
   2216     host3->new_master_entry_url_ =
   2217         MockHttpServer::GetMockUrl("files/servererror");
   2218     update->StartUpdate(host3, host3->new_master_entry_url_);
   2219 
   2220     // Set up checks for when update job finishes.
   2221     do_checks_after_update_finished_ = true;
   2222     expect_group_obsolete_ = false;
   2223     expect_group_has_cache_ = true;
   2224     expect_old_cache_ = cache;
   2225     tested_manifest_ = MANIFEST1;
   2226     MockFrontend::HostIds ids1(1, host1->host_id());
   2227     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2228     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2229     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2230     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2231     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2232     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   2233     MockFrontend::HostIds ids2(1, host2->host_id());
   2234     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2235     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2236     MockFrontend::HostIds ids3(1, host3->host_id());
   2237     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2238     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
   2239     frontend3->AddExpectedEvent(ids3, APPCACHE_ERROR_EVENT);
   2240 
   2241     WaitForUpdateToFinish();
   2242   }
   2243 
   2244   void MasterEntrySomeFailTest() {
   2245     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2246 
   2247     MakeService();
   2248     group_ = new AppCacheGroup(
   2249         service_->storage(),
   2250         MockHttpServer::GetMockUrl("files/manifest1"),
   2251         111);
   2252     AppCacheUpdateJob* update =
   2253         new AppCacheUpdateJob(service_.get(), group_.get());
   2254     group_->update_job_ = update;
   2255 
   2256     MockFrontend* frontend1 = MakeMockFrontend();
   2257     frontend1->SetIgnoreProgressEvents(true);
   2258     AppCacheHost* host1 = MakeHost(1, frontend1);
   2259     host1->new_master_entry_url_ =
   2260         MockHttpServer::GetMockUrl("files/nosuchfile");
   2261     update->StartUpdate(host1, host1->new_master_entry_url_);
   2262 
   2263     MockFrontend* frontend2 = MakeMockFrontend();
   2264     AppCacheHost* host2 = MakeHost(2, frontend2);
   2265     host2->new_master_entry_url_ =
   2266         MockHttpServer::GetMockUrl("files/explicit2");
   2267     update->StartUpdate(host2, host2->new_master_entry_url_);
   2268 
   2269     // Set up checks for when update job finishes.
   2270     do_checks_after_update_finished_ = true;
   2271     expect_group_obsolete_ = false;
   2272     expect_group_has_cache_ = true;  // as long as one pending master succeeds
   2273     tested_manifest_ = MANIFEST1;
   2274     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   2275         MockHttpServer::GetMockUrl("files/explicit2"),
   2276         AppCacheEntry(AppCacheEntry::MASTER)));
   2277     MockFrontend::HostIds ids1(1, host1->host_id());
   2278     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2279     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2280     frontend1->AddExpectedEvent(ids1, APPCACHE_ERROR_EVENT);
   2281     MockFrontend::HostIds ids2(1, host2->host_id());
   2282     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   2283     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2284     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   2285     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   2286     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   2287     frontend2->AddExpectedEvent(ids2, APPCACHE_CACHED_EVENT);
   2288 
   2289     WaitForUpdateToFinish();
   2290   }
   2291 
   2292   void UpgradeMasterEntrySomeFailTest() {
   2293     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2294 
   2295     MakeService();
   2296     group_ = new AppCacheGroup(
   2297         service_->storage(),
   2298         MockHttpServer::GetMockUrl("files/manifest1"),
   2299         111);
   2300     AppCacheUpdateJob* update =
   2301         new AppCacheUpdateJob(service_.get(), group_.get());
   2302     group_->update_job_ = update;
   2303 
   2304     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   2305     MockFrontend* frontend1 = MakeMockFrontend();
   2306     AppCacheHost* host1 = MakeHost(1, frontend1);
   2307     host1->AssociateCompleteCache(cache);
   2308 
   2309     MockFrontend* frontend2 = MakeMockFrontend();
   2310     frontend2->SetIgnoreProgressEvents(true);
   2311     AppCacheHost* host2 = MakeHost(2, frontend2);
   2312     host2->new_master_entry_url_ =
   2313         MockHttpServer::GetMockUrl("files/nosuchfile");
   2314     update->StartUpdate(host2, host2->new_master_entry_url_);
   2315 
   2316     MockFrontend* frontend3 = MakeMockFrontend();
   2317     AppCacheHost* host3 = MakeHost(3, frontend3);
   2318     host3->new_master_entry_url_ =
   2319         MockHttpServer::GetMockUrl("files/explicit2");
   2320     update->StartUpdate(host3, host3->new_master_entry_url_);
   2321 
   2322     // Set up checks for when update job finishes.
   2323     do_checks_after_update_finished_ = true;
   2324     expect_group_obsolete_ = false;
   2325     expect_group_has_cache_ = true;
   2326     expect_old_cache_ = cache;
   2327     tested_manifest_ = MANIFEST1;
   2328     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   2329         MockHttpServer::GetMockUrl("files/explicit2"),
   2330         AppCacheEntry(AppCacheEntry::MASTER)));
   2331     MockFrontend::HostIds ids1(1, host1->host_id());
   2332     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2333     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2334     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2335     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2336     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2337     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   2338     MockFrontend::HostIds ids2(1, host2->host_id());
   2339     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2340     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2341     MockFrontend::HostIds ids3(1, host3->host_id());
   2342     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2343     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
   2344     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
   2345     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
   2346     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
   2347     frontend3->AddExpectedEvent(ids3, APPCACHE_UPDATE_READY_EVENT);
   2348 
   2349     WaitForUpdateToFinish();
   2350   }
   2351 
   2352   void MasterEntryNoUpdateTest() {
   2353     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2354 
   2355     MakeService();
   2356     group_ = new AppCacheGroup(service_->storage(),
   2357         MockHttpServer::GetMockUrl("files/notmodified"), 111);
   2358     AppCacheUpdateJob* update =
   2359         new AppCacheUpdateJob(service_.get(), group_.get());
   2360     group_->update_job_ = update;
   2361 
   2362     AppCache* cache = MakeCacheForGroup(1, 111);
   2363     MockFrontend* frontend1 = MakeMockFrontend();
   2364     AppCacheHost* host1 = MakeHost(1, frontend1);
   2365     host1->AssociateCompleteCache(cache);
   2366 
   2367     // Give cache an existing entry that can also be fetched.
   2368     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
   2369                     AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
   2370 
   2371     // Reset the update time to null so we can verify it gets
   2372     // modified in this test case by the UpdateJob.
   2373     cache->set_update_time(base::Time());
   2374 
   2375     MockFrontend* frontend2 = MakeMockFrontend();
   2376     AppCacheHost* host2 = MakeHost(2, frontend2);
   2377     host2->new_master_entry_url_ =
   2378         MockHttpServer::GetMockUrl("files/explicit1");
   2379     update->StartUpdate(host2, host2->new_master_entry_url_);
   2380 
   2381     AppCacheHost* host3 = MakeHost(3, frontend2);  // same frontend as host2
   2382     host3->new_master_entry_url_ =
   2383         MockHttpServer::GetMockUrl("files/explicit2");
   2384     update->StartUpdate(host3, host3->new_master_entry_url_);
   2385 
   2386     // Set up checks for when update job finishes.
   2387     do_checks_after_update_finished_ = true;
   2388     expect_group_obsolete_ = false;
   2389     expect_group_has_cache_ = true;
   2390     expect_newest_cache_ = cache;  // newest cache still the same cache
   2391     expect_non_null_update_time_ = true;
   2392     tested_manifest_ = PENDING_MASTER_NO_UPDATE;
   2393     MockFrontend::HostIds ids1(1, host1->host_id());
   2394     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2395     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
   2396     MockFrontend::HostIds ids3(1, host3->host_id());
   2397     frontend2->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2398     MockFrontend::HostIds ids2and3;
   2399     ids2and3.push_back(host2->host_id());
   2400     ids2and3.push_back(host3->host_id());
   2401     frontend2->AddExpectedEvent(ids2and3, APPCACHE_NO_UPDATE_EVENT);
   2402 
   2403     WaitForUpdateToFinish();
   2404   }
   2405 
   2406   void StartUpdateMidCacheAttemptTest() {
   2407     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2408 
   2409     MakeService();
   2410     group_ = new AppCacheGroup(
   2411         service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
   2412         service_->storage()->NewGroupId());
   2413     AppCacheUpdateJob* update =
   2414         new AppCacheUpdateJob(service_.get(), group_.get());
   2415     group_->update_job_ = update;
   2416 
   2417     MockFrontend* frontend1 = MakeMockFrontend();
   2418     AppCacheHost* host1 = MakeHost(1, frontend1);
   2419     host1->new_master_entry_url_ =
   2420         MockHttpServer::GetMockUrl("files/explicit2");
   2421     update->StartUpdate(host1, host1->new_master_entry_url_);
   2422     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2423 
   2424     // Set up additional updates to be started while update is in progress.
   2425     MockFrontend* frontend2 = MakeMockFrontend();
   2426     frontend2->SetIgnoreProgressEvents(true);
   2427     AppCacheHost* host2 = MakeHost(2, frontend2);
   2428     host2->new_master_entry_url_ =
   2429         MockHttpServer::GetMockUrl("files/nosuchfile");
   2430 
   2431     MockFrontend* frontend3 = MakeMockFrontend();
   2432     AppCacheHost* host3 = MakeHost(3, frontend3);
   2433     host3->new_master_entry_url_ =
   2434         MockHttpServer::GetMockUrl("files/explicit1");
   2435 
   2436     MockFrontend* frontend4 = MakeMockFrontend();
   2437     AppCacheHost* host4 = MakeHost(4, frontend4);
   2438     host4->new_master_entry_url_ =
   2439         MockHttpServer::GetMockUrl("files/explicit2");
   2440 
   2441     MockFrontend* frontend5 = MakeMockFrontend();
   2442     AppCacheHost* host5 = MakeHost(5, frontend5);  // no master entry url
   2443 
   2444     frontend1->TriggerAdditionalUpdates(APPCACHE_DOWNLOADING_EVENT, update);
   2445     frontend1->AdditionalUpdateHost(host2);  // fetch will fail
   2446     frontend1->AdditionalUpdateHost(host3);  // same as an explicit entry
   2447     frontend1->AdditionalUpdateHost(host4);  // same as another master entry
   2448     frontend1->AdditionalUpdateHost(NULL);   // no host
   2449     frontend1->AdditionalUpdateHost(host5);  // no master entry url
   2450 
   2451     // Set up checks for when update job finishes.
   2452     do_checks_after_update_finished_ = true;
   2453     expect_group_obsolete_ = false;
   2454     expect_group_has_cache_ = true;
   2455     tested_manifest_ = MANIFEST1;
   2456     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   2457         MockHttpServer::GetMockUrl("files/explicit2"),
   2458         AppCacheEntry(AppCacheEntry::MASTER)));
   2459     MockFrontend::HostIds ids1(1, host1->host_id());
   2460     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2461     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2462     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2463     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2464     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2465     frontend1->AddExpectedEvent(ids1, APPCACHE_CACHED_EVENT);
   2466     MockFrontend::HostIds ids2(1, host2->host_id());
   2467     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   2468     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2469     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2470     MockFrontend::HostIds ids3(1, host3->host_id());
   2471     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2472     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
   2473     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
   2474     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
   2475     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
   2476     frontend3->AddExpectedEvent(ids3, APPCACHE_CACHED_EVENT);
   2477     MockFrontend::HostIds ids4(1, host4->host_id());
   2478     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
   2479     frontend4->AddExpectedEvent(ids4, APPCACHE_DOWNLOADING_EVENT);
   2480     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);
   2481     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);
   2482     frontend4->AddExpectedEvent(ids4, APPCACHE_PROGRESS_EVENT);  // final
   2483     frontend4->AddExpectedEvent(ids4, APPCACHE_CACHED_EVENT);
   2484 
   2485     // Host 5 is not associated with cache so no progress/cached events.
   2486     MockFrontend::HostIds ids5(1, host5->host_id());
   2487     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
   2488     frontend5->AddExpectedEvent(ids5, APPCACHE_DOWNLOADING_EVENT);
   2489 
   2490     WaitForUpdateToFinish();
   2491   }
   2492 
   2493   void StartUpdateMidNoUpdateTest() {
   2494     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2495 
   2496     MakeService();
   2497     group_ = new AppCacheGroup(
   2498         service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
   2499         service_->storage()->NewGroupId());
   2500     AppCacheUpdateJob* update =
   2501         new AppCacheUpdateJob(service_.get(), group_.get());
   2502     group_->update_job_ = update;
   2503 
   2504     AppCache* cache = MakeCacheForGroup(1, 111);
   2505     MockFrontend* frontend1 = MakeMockFrontend();
   2506     AppCacheHost* host1 = MakeHost(1, frontend1);
   2507     host1->AssociateCompleteCache(cache);
   2508 
   2509     // Give cache an existing entry.
   2510     cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
   2511                     AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
   2512 
   2513     // Start update with a pending master entry that will fail to give us an
   2514     // event to trigger other updates.
   2515     MockFrontend* frontend2 = MakeMockFrontend();
   2516     AppCacheHost* host2 = MakeHost(2, frontend2);
   2517     host2->new_master_entry_url_ =
   2518         MockHttpServer::GetMockUrl("files/nosuchfile");
   2519     update->StartUpdate(host2, host2->new_master_entry_url_);
   2520     EXPECT_TRUE(update->manifest_fetcher_ != NULL);
   2521 
   2522     // Set up additional updates to be started while update is in progress.
   2523     MockFrontend* frontend3 = MakeMockFrontend();
   2524     AppCacheHost* host3 = MakeHost(3, frontend3);
   2525     host3->new_master_entry_url_ =
   2526         MockHttpServer::GetMockUrl("files/explicit1");
   2527 
   2528     MockFrontend* frontend4 = MakeMockFrontend();
   2529     AppCacheHost* host4 = MakeHost(4, frontend4);  // no master entry url
   2530 
   2531     MockFrontend* frontend5 = MakeMockFrontend();
   2532     AppCacheHost* host5 = MakeHost(5, frontend5);
   2533     host5->new_master_entry_url_ =
   2534         MockHttpServer::GetMockUrl("files/explicit2");  // existing entry
   2535 
   2536     MockFrontend* frontend6 = MakeMockFrontend();
   2537     AppCacheHost* host6 = MakeHost(6, frontend6);
   2538     host6->new_master_entry_url_ =
   2539         MockHttpServer::GetMockUrl("files/explicit1");
   2540 
   2541     frontend2->TriggerAdditionalUpdates(APPCACHE_ERROR_EVENT, update);
   2542     frontend2->AdditionalUpdateHost(host3);
   2543     frontend2->AdditionalUpdateHost(NULL);   // no host
   2544     frontend2->AdditionalUpdateHost(host4);  // no master entry url
   2545     frontend2->AdditionalUpdateHost(host5);  // same as existing cache entry
   2546     frontend2->AdditionalUpdateHost(host6);  // same as another master entry
   2547 
   2548     // Set up checks for when update job finishes.
   2549     do_checks_after_update_finished_ = true;
   2550     expect_group_obsolete_ = false;
   2551     expect_group_has_cache_ = true;
   2552     expect_newest_cache_ = cache;  // newest cache unaffected by update
   2553     tested_manifest_ = PENDING_MASTER_NO_UPDATE;
   2554     MockFrontend::HostIds ids1(1, host1->host_id());  // prior associated host
   2555     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2556     frontend1->AddExpectedEvent(ids1, APPCACHE_NO_UPDATE_EVENT);
   2557     MockFrontend::HostIds ids2(1, host2->host_id());
   2558     frontend2->AddExpectedEvent(ids2, APPCACHE_ERROR_EVENT);
   2559     MockFrontend::HostIds ids3(1, host3->host_id());
   2560     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2561     frontend3->AddExpectedEvent(ids3, APPCACHE_NO_UPDATE_EVENT);
   2562     MockFrontend::HostIds ids4(1, host4->host_id());  // unassociated w/cache
   2563     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
   2564     MockFrontend::HostIds ids5(1, host5->host_id());
   2565     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
   2566     frontend5->AddExpectedEvent(ids5, APPCACHE_NO_UPDATE_EVENT);
   2567     MockFrontend::HostIds ids6(1, host6->host_id());
   2568     frontend6->AddExpectedEvent(ids6, APPCACHE_CHECKING_EVENT);
   2569     frontend6->AddExpectedEvent(ids6, APPCACHE_NO_UPDATE_EVENT);
   2570 
   2571     WaitForUpdateToFinish();
   2572   }
   2573 
   2574   void StartUpdateMidDownloadTest() {
   2575     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2576 
   2577     MakeService();
   2578     group_ = new AppCacheGroup(
   2579         service_->storage(),
   2580         MockHttpServer::GetMockUrl("files/manifest1"),
   2581         111);
   2582     AppCacheUpdateJob* update =
   2583         new AppCacheUpdateJob(service_.get(), group_.get());
   2584     group_->update_job_ = update;
   2585 
   2586     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
   2587     MockFrontend* frontend1 = MakeMockFrontend();
   2588     AppCacheHost* host1 = MakeHost(1, frontend1);
   2589     host1->AssociateCompleteCache(cache);
   2590 
   2591     update->StartUpdate(NULL, GURL());
   2592 
   2593     // Set up additional updates to be started while update is in progress.
   2594     MockFrontend* frontend2 = MakeMockFrontend();
   2595     AppCacheHost* host2 = MakeHost(2, frontend2);
   2596     host2->new_master_entry_url_ =
   2597         MockHttpServer::GetMockUrl("files/explicit1");
   2598 
   2599     MockFrontend* frontend3 = MakeMockFrontend();
   2600     AppCacheHost* host3 = MakeHost(3, frontend3);
   2601     host3->new_master_entry_url_ =
   2602         MockHttpServer::GetMockUrl("files/explicit2");
   2603 
   2604     MockFrontend* frontend4 = MakeMockFrontend();
   2605     AppCacheHost* host4 = MakeHost(4, frontend4);  // no master entry url
   2606 
   2607     MockFrontend* frontend5 = MakeMockFrontend();
   2608     AppCacheHost* host5 = MakeHost(5, frontend5);
   2609     host5->new_master_entry_url_ =
   2610         MockHttpServer::GetMockUrl("files/explicit2");
   2611 
   2612     frontend1->TriggerAdditionalUpdates(APPCACHE_PROGRESS_EVENT, update);
   2613     frontend1->AdditionalUpdateHost(host2);  // same as entry in manifest
   2614     frontend1->AdditionalUpdateHost(NULL);   // no host
   2615     frontend1->AdditionalUpdateHost(host3);  // new master entry
   2616     frontend1->AdditionalUpdateHost(host4);  // no master entry url
   2617     frontend1->AdditionalUpdateHost(host5);  // same as another master entry
   2618 
   2619     // Set up checks for when update job finishes.
   2620     do_checks_after_update_finished_ = true;
   2621     expect_group_obsolete_ = false;
   2622     expect_group_has_cache_ = true;
   2623     tested_manifest_ = MANIFEST1;
   2624     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   2625         MockHttpServer::GetMockUrl("files/explicit2"),
   2626         AppCacheEntry(AppCacheEntry::MASTER)));
   2627     MockFrontend::HostIds ids1(1, host1->host_id());  // prior associated host
   2628     frontend1->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2629     frontend1->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2630     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2631     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2632     frontend1->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2633     frontend1->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   2634     MockFrontend::HostIds ids2(1, host2->host_id());
   2635     frontend2->AddExpectedEvent(ids2, APPCACHE_CHECKING_EVENT);
   2636     frontend2->AddExpectedEvent(ids2, APPCACHE_DOWNLOADING_EVENT);
   2637     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);
   2638     frontend2->AddExpectedEvent(ids2, APPCACHE_PROGRESS_EVENT);  // final
   2639     frontend2->AddExpectedEvent(ids2, APPCACHE_UPDATE_READY_EVENT);
   2640     MockFrontend::HostIds ids3(1, host3->host_id());
   2641     frontend3->AddExpectedEvent(ids3, APPCACHE_CHECKING_EVENT);
   2642     frontend3->AddExpectedEvent(ids3, APPCACHE_DOWNLOADING_EVENT);
   2643     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);
   2644     frontend3->AddExpectedEvent(ids3, APPCACHE_PROGRESS_EVENT);  // final
   2645     frontend3->AddExpectedEvent(ids3, APPCACHE_UPDATE_READY_EVENT);
   2646     MockFrontend::HostIds ids4(1, host4->host_id());  // unassociated w/cache
   2647     frontend4->AddExpectedEvent(ids4, APPCACHE_CHECKING_EVENT);
   2648     frontend4->AddExpectedEvent(ids4, APPCACHE_DOWNLOADING_EVENT);
   2649     MockFrontend::HostIds ids5(1, host5->host_id());
   2650     frontend5->AddExpectedEvent(ids5, APPCACHE_CHECKING_EVENT);
   2651     frontend5->AddExpectedEvent(ids5, APPCACHE_DOWNLOADING_EVENT);
   2652     frontend5->AddExpectedEvent(ids5, APPCACHE_PROGRESS_EVENT);
   2653     frontend5->AddExpectedEvent(ids5, APPCACHE_PROGRESS_EVENT);  // final
   2654     frontend5->AddExpectedEvent(ids5, APPCACHE_UPDATE_READY_EVENT);
   2655 
   2656     WaitForUpdateToFinish();
   2657   }
   2658 
   2659   void QueueMasterEntryTest() {
   2660     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2661 
   2662     MakeService();
   2663     group_ = new AppCacheGroup(
   2664         service_->storage(),
   2665         MockHttpServer::GetMockUrl("files/manifest1"),
   2666         111);
   2667     AppCacheUpdateJob* update =
   2668         new AppCacheUpdateJob(service_.get(), group_.get());
   2669     group_->update_job_ = update;
   2670 
   2671     // Pretend update job has been running and is about to terminate.
   2672     group_->update_status_ = AppCacheGroup::DOWNLOADING;
   2673     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
   2674     EXPECT_TRUE(update->IsTerminating());
   2675 
   2676     // Start an update. Should be queued.
   2677     MockFrontend* frontend = MakeMockFrontend();
   2678     AppCacheHost* host = MakeHost(1, frontend);
   2679     host->new_master_entry_url_ =
   2680         MockHttpServer::GetMockUrl("files/explicit2");
   2681     update->StartUpdate(host, host->new_master_entry_url_);
   2682     EXPECT_TRUE(update->pending_master_entries_.empty());
   2683     EXPECT_FALSE(group_->queued_updates_.empty());
   2684 
   2685     // Delete update, causing it to finish, which should trigger a new update
   2686     // for the queued host and master entry after a delay.
   2687     delete update;
   2688     EXPECT_FALSE(group_->restart_update_task_.IsCancelled());
   2689 
   2690     // Set up checks for when queued update job finishes.
   2691     do_checks_after_update_finished_ = true;
   2692     expect_group_obsolete_ = false;
   2693     expect_group_has_cache_ = true;
   2694     tested_manifest_ = MANIFEST1;
   2695     expect_extra_entries_.insert(AppCache::EntryMap::value_type(
   2696         host->new_master_entry_url_, AppCacheEntry(AppCacheEntry::MASTER)));
   2697     MockFrontend::HostIds ids1(1, host->host_id());
   2698     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2699     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2700     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2701     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2702     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2703     frontend->AddExpectedEvent(ids1, APPCACHE_CACHED_EVENT);
   2704 
   2705     // Group status will be APPCACHE_STATUS_IDLE so cannot call
   2706     // WaitForUpdateToFinish.
   2707     group_->AddUpdateObserver(this);
   2708   }
   2709 
   2710   void IfModifiedSinceTest() {
   2711     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2712 
   2713     net::URLRequestJobFactoryImpl* new_factory(
   2714         new net::URLRequestJobFactoryImpl);
   2715     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
   2716     io_thread_->SetNewJobFactory(new_factory);
   2717 
   2718     MakeService();
   2719     group_ = new AppCacheGroup(
   2720         service_->storage(), GURL("http://headertest"), 111);
   2721     AppCacheUpdateJob* update =
   2722         new AppCacheUpdateJob(service_.get(), group_.get());
   2723     group_->update_job_ = update;
   2724 
   2725     // First test against a cache attempt. Will start manifest fetch
   2726     // synchronously.
   2727     HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
   2728     MockFrontend mock_frontend;
   2729     AppCacheHost host(1, &mock_frontend, service_.get());
   2730     update->StartUpdate(&host, GURL());
   2731     HttpHeadersRequestTestJob::Verify();
   2732     delete update;
   2733 
   2734     // Now simulate a refetch manifest request. Will start fetch request
   2735     // synchronously.
   2736     const char data[] =
   2737         "HTTP/1.1 200 OK\0"
   2738         "\0";
   2739     net::HttpResponseHeaders* headers =
   2740         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   2741     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   2742     response_info->headers = headers;  // adds ref to headers
   2743 
   2744     HttpHeadersRequestTestJob::Initialize(std::string(), std::string());
   2745     update = new AppCacheUpdateJob(service_.get(), group_.get());
   2746     group_->update_job_ = update;
   2747     group_->update_status_ = AppCacheGroup::DOWNLOADING;
   2748     update->manifest_response_info_.reset(response_info);
   2749     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
   2750     update->FetchManifest(false);  // not first request
   2751     HttpHeadersRequestTestJob::Verify();
   2752     delete update;
   2753 
   2754     // Change the headers to include a Last-Modified header. Manifest refetch
   2755     // should include If-Modified-Since header.
   2756     const char data2[] =
   2757         "HTTP/1.1 200 OK\0"
   2758         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
   2759         "\0";
   2760     net::HttpResponseHeaders* headers2 =
   2761         new net::HttpResponseHeaders(std::string(data2, arraysize(data2)));
   2762     response_info = new net::HttpResponseInfo();
   2763     response_info->headers = headers2;
   2764 
   2765     HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
   2766                                           std::string());
   2767     update = new AppCacheUpdateJob(service_.get(), group_.get());
   2768     group_->update_job_ = update;
   2769     group_->update_status_ = AppCacheGroup::DOWNLOADING;
   2770     update->manifest_response_info_.reset(response_info);
   2771     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
   2772     update->FetchManifest(false);  // not first request
   2773     HttpHeadersRequestTestJob::Verify();
   2774     delete update;
   2775 
   2776     UpdateFinished();
   2777   }
   2778 
   2779   void IfModifiedSinceUpgradeTest() {
   2780     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2781 
   2782     HttpHeadersRequestTestJob::Initialize("Sat, 29 Oct 1994 19:43:31 GMT",
   2783                                           std::string());
   2784     net::URLRequestJobFactoryImpl* new_factory(
   2785         new net::URLRequestJobFactoryImpl);
   2786     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
   2787     io_thread_->SetNewJobFactory(new_factory);
   2788 
   2789     MakeService();
   2790     group_ =new AppCacheGroup(
   2791         service_->storage(),
   2792         MockHttpServer::GetMockUrl("files/manifest1"),
   2793         111);
   2794     AppCacheUpdateJob* update =
   2795         new AppCacheUpdateJob(service_.get(), group_.get());
   2796     group_->update_job_ = update;
   2797 
   2798     // Give the newest cache a manifest enry that is in storage.
   2799     response_writer_.reset(
   2800         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   2801                                                   group_->group_id()));
   2802 
   2803     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
   2804                                         response_writer_->response_id());
   2805     MockFrontend* frontend = MakeMockFrontend();
   2806     AppCacheHost* host = MakeHost(1, frontend);
   2807     host->AssociateCompleteCache(cache);
   2808 
   2809     // Set up checks for when update job finishes.
   2810     do_checks_after_update_finished_ = true;
   2811     expect_group_obsolete_ = false;
   2812     expect_group_has_cache_ = true;
   2813     expect_old_cache_ = cache;
   2814     tested_manifest_ = MANIFEST1;
   2815     MockFrontend::HostIds ids1(1, host->host_id());
   2816     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2817     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2818     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2819     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2820     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2821     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   2822 
   2823     // Seed storage with expected manifest response info that will cause
   2824     // an If-Modified-Since header to be put in the manifest fetch request.
   2825     const char data[] =
   2826         "HTTP/1.1 200 OK\0"
   2827         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
   2828         "\0";
   2829     net::HttpResponseHeaders* headers =
   2830         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   2831     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   2832     response_info->headers = headers;  // adds ref to headers
   2833     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
   2834         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
   2835     response_writer_->WriteInfo(
   2836         io_buffer.get(),
   2837         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   2838                    base::Unretained(this)));
   2839 
   2840     // Start update after data write completes asynchronously.
   2841   }
   2842 
   2843   void IfNoneMatchUpgradeTest() {
   2844     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2845 
   2846     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
   2847     net::URLRequestJobFactoryImpl* new_factory(
   2848         new net::URLRequestJobFactoryImpl);
   2849     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
   2850     io_thread_->SetNewJobFactory(new_factory);
   2851 
   2852     MakeService();
   2853     group_ = new AppCacheGroup(
   2854         service_->storage(),
   2855         MockHttpServer::GetMockUrl("files/manifest1"),
   2856         111);
   2857     AppCacheUpdateJob* update =
   2858         new AppCacheUpdateJob(service_.get(), group_.get());
   2859     group_->update_job_ = update;
   2860 
   2861     // Give the newest cache a manifest enry that is in storage.
   2862     response_writer_.reset(
   2863         service_->storage()->CreateResponseWriter(group_->manifest_url(),
   2864                                                   group_->group_id()));
   2865 
   2866     AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
   2867                                         response_writer_->response_id());
   2868     MockFrontend* frontend = MakeMockFrontend();
   2869     AppCacheHost* host = MakeHost(1, frontend);
   2870     host->AssociateCompleteCache(cache);
   2871 
   2872     // Set up checks for when update job finishes.
   2873     do_checks_after_update_finished_ = true;
   2874     expect_group_obsolete_ = false;
   2875     expect_group_has_cache_ = true;
   2876     expect_old_cache_ = cache;
   2877     tested_manifest_ = MANIFEST1;
   2878     MockFrontend::HostIds ids1(1, host->host_id());
   2879     frontend->AddExpectedEvent(ids1, APPCACHE_CHECKING_EVENT);
   2880     frontend->AddExpectedEvent(ids1, APPCACHE_DOWNLOADING_EVENT);
   2881     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2882     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);
   2883     frontend->AddExpectedEvent(ids1, APPCACHE_PROGRESS_EVENT);  // final
   2884     frontend->AddExpectedEvent(ids1, APPCACHE_UPDATE_READY_EVENT);
   2885 
   2886     // Seed storage with expected manifest response info that will cause
   2887     // an If-None-Match header to be put in the manifest fetch request.
   2888     const char data[] =
   2889         "HTTP/1.1 200 OK\0"
   2890         "ETag: \"LadeDade\"\0"
   2891         "\0";
   2892     net::HttpResponseHeaders* headers =
   2893         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   2894     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   2895     response_info->headers = headers;  // adds ref to headers
   2896     scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
   2897         new HttpResponseInfoIOBuffer(response_info));  // adds ref to info
   2898     response_writer_->WriteInfo(
   2899         io_buffer.get(),
   2900         base::Bind(&AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
   2901                    base::Unretained(this)));
   2902 
   2903     // Start update after data write completes asynchronously.
   2904   }
   2905 
   2906   void IfNoneMatchRefetchTest() {
   2907     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2908 
   2909     HttpHeadersRequestTestJob::Initialize(std::string(), "\"LadeDade\"");
   2910     net::URLRequestJobFactoryImpl* new_factory(
   2911         new net::URLRequestJobFactoryImpl);
   2912     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
   2913     io_thread_->SetNewJobFactory(new_factory);
   2914 
   2915     MakeService();
   2916     group_ = new AppCacheGroup(
   2917         service_->storage(), GURL("http://headertest"), 111);
   2918     AppCacheUpdateJob* update =
   2919         new AppCacheUpdateJob(service_.get(), group_.get());
   2920     group_->update_job_ = update;
   2921 
   2922     // Simulate a refetch manifest request that uses an ETag header.
   2923     const char data[] =
   2924         "HTTP/1.1 200 OK\0"
   2925         "ETag: \"LadeDade\"\0"
   2926         "\0";
   2927     net::HttpResponseHeaders* headers =
   2928         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   2929     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   2930     response_info->headers = headers;  // adds ref to headers
   2931 
   2932     group_->update_status_ = AppCacheGroup::DOWNLOADING;
   2933     update->manifest_response_info_.reset(response_info);
   2934     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
   2935     update->FetchManifest(false);  // not first request
   2936     HttpHeadersRequestTestJob::Verify();
   2937     delete update;
   2938 
   2939     UpdateFinished();
   2940   }
   2941 
   2942   void MultipleHeadersRefetchTest() {
   2943     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2944 
   2945     // Verify that code is correct when building multiple extra headers.
   2946     HttpHeadersRequestTestJob::Initialize(
   2947         "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\"");
   2948     net::URLRequestJobFactoryImpl* new_factory(
   2949         new net::URLRequestJobFactoryImpl);
   2950     new_factory->SetProtocolHandler("http", new IfModifiedSinceJobFactory);
   2951     io_thread_->SetNewJobFactory(new_factory);
   2952 
   2953     MakeService();
   2954     group_ = new AppCacheGroup(
   2955         service_->storage(), GURL("http://headertest"), 111);
   2956     AppCacheUpdateJob* update =
   2957         new AppCacheUpdateJob(service_.get(), group_.get());
   2958     group_->update_job_ = update;
   2959 
   2960     // Simulate a refetch manifest request that uses an ETag header.
   2961     const char data[] =
   2962         "HTTP/1.1 200 OK\0"
   2963         "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
   2964         "ETag: \"LadeDade\"\0"
   2965         "\0";
   2966     net::HttpResponseHeaders* headers =
   2967         new net::HttpResponseHeaders(std::string(data, arraysize(data)));
   2968     net::HttpResponseInfo* response_info = new net::HttpResponseInfo();
   2969     response_info->headers = headers;  // adds ref to headers
   2970 
   2971     group_->update_status_ = AppCacheGroup::DOWNLOADING;
   2972     update->manifest_response_info_.reset(response_info);
   2973     update->internal_state_ = AppCacheUpdateJob::REFETCH_MANIFEST;
   2974     update->FetchManifest(false);  // not first request
   2975     HttpHeadersRequestTestJob::Verify();
   2976     delete update;
   2977 
   2978     UpdateFinished();
   2979   }
   2980 
   2981   void CrossOriginHttpsSuccessTest() {
   2982     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   2983 
   2984     GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
   2985         "files/valid_cross_origin_https_manifest");
   2986 
   2987     MakeService();
   2988     group_ = new AppCacheGroup(
   2989         service_->storage(), manifest_url, service_->storage()->NewGroupId());
   2990     AppCacheUpdateJob* update =
   2991         new AppCacheUpdateJob(service_.get(), group_.get());
   2992     group_->update_job_ = update;
   2993 
   2994     MockFrontend* frontend = MakeMockFrontend();
   2995     AppCacheHost* host = MakeHost(1, frontend);
   2996     update->StartUpdate(host, GURL());
   2997 
   2998     // Set up checks for when update job finishes.
   2999     do_checks_after_update_finished_ = true;
   3000     expect_group_obsolete_ = false;
   3001     expect_group_has_cache_ = true;
   3002     tested_manifest_ = NONE;
   3003     MockFrontend::HostIds host_ids(1, host->host_id());
   3004     frontend->AddExpectedEvent(host_ids, APPCACHE_CHECKING_EVENT);
   3005 
   3006     WaitForUpdateToFinish();
   3007   }
   3008 
   3009   void CrossOriginHttpsDeniedTest() {
   3010     ASSERT_TRUE(base::MessageLoopForIO::IsCurrent());
   3011 
   3012     GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
   3013         "files/invalid_cross_origin_https_manifest");
   3014 
   3015     MakeService();
   3016     group_ = new AppCacheGroup(
   3017         service_->storage(), manifest_url, service_->storage()->NewGroupId());
   3018     AppCacheUpdateJob* update =
   3019         new AppCacheUpdateJob(service_.get(), group_.get());
   3020     group_->update_job_ = update;
   3021 
   3022     MockFrontend* frontend = MakeMockFrontend();
   3023     AppCacheHost* host = MakeHost(1, frontend);
   3024     update->StartUpdate(host, GURL());
   3025 
   3026     // Set up checks for when update job finishes.
   3027     do_checks_after_update_finished_ = true;
   3028     expect_group_obsolete_ = false;
   3029     expect_group_has_cache_ = false;
   3030     tested_manifest_ = NONE;
   3031     MockFrontend::HostIds host_ids(1, host->host_id());
   3032     frontend->AddExpectedEvent(host_ids, APPCACHE_CHECKING_EVENT);
   3033 
   3034     WaitForUpdateToFinish();
   3035   }
   3036 
   3037   void WaitForUpdateToFinish() {
   3038     if (group_->update_status() == AppCacheGroup::IDLE)
   3039       UpdateFinished();
   3040     else
   3041       group_->AddUpdateObserver(this);
   3042   }
   3043 
   3044   virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE {
   3045     ASSERT_EQ(group_, group);
   3046     protect_newest_cache_ = group->newest_complete_cache();
   3047     UpdateFinished();
   3048   }
   3049 
   3050   void UpdateFinished() {
   3051     // We unwind the stack prior to finishing up to let stack-based objects
   3052     // get deleted.
   3053     base::MessageLoop::current()->PostTask(
   3054         FROM_HERE,
   3055         base::Bind(&AppCacheUpdateJobTest::UpdateFinishedUnwound,
   3056                    base::Unretained(this)));
   3057   }
   3058 
   3059   void UpdateFinishedUnwound() {
   3060     EXPECT_EQ(AppCacheGroup::IDLE, group_->update_status());
   3061     EXPECT_TRUE(group_->update_job() == NULL);
   3062     if (do_checks_after_update_finished_)
   3063       VerifyExpectations();
   3064 
   3065     // Clean up everything that was created on the IO thread.
   3066     protect_newest_cache_ = NULL;
   3067     group_ = NULL;
   3068     STLDeleteContainerPointers(hosts_.begin(), hosts_.end());
   3069     STLDeleteContainerPointers(frontends_.begin(), frontends_.end());
   3070     response_infos_.clear();
   3071     service_.reset(NULL);
   3072 
   3073     event_->Signal();
   3074   }
   3075 
   3076   void MakeService() {
   3077     service_.reset(new MockAppCacheService());
   3078     service_->set_request_context(io_thread_->request_context());
   3079   }
   3080 
   3081   AppCache* MakeCacheForGroup(int64 cache_id, int64 manifest_response_id) {
   3082     return MakeCacheForGroup(cache_id, group_->manifest_url(),
   3083                              manifest_response_id);
   3084   }
   3085 
   3086   AppCache* MakeCacheForGroup(int64 cache_id, const GURL& manifest_entry_url,
   3087                               int64 manifest_response_id) {
   3088     AppCache* cache = new AppCache(service_->storage(), cache_id);
   3089     cache->set_complete(true);
   3090     cache->set_update_time(base::Time::Now());
   3091     group_->AddCache(cache);
   3092 
   3093     // Add manifest entry to cache.
   3094     cache->AddEntry(manifest_entry_url,
   3095         AppCacheEntry(AppCacheEntry::MANIFEST, manifest_response_id));
   3096 
   3097     return cache;
   3098   }
   3099 
   3100   AppCacheHost* MakeHost(int host_id, AppCacheFrontend* frontend) {
   3101     AppCacheHost* host = new AppCacheHost(host_id, frontend, service_.get());
   3102     hosts_.push_back(host);
   3103     return host;
   3104   }
   3105 
   3106   AppCacheResponseInfo* MakeAppCacheResponseInfo(
   3107       const GURL& manifest_url, int64 response_id,
   3108       const std::string& raw_headers) {
   3109     net::HttpResponseInfo* http_info = new net::HttpResponseInfo();
   3110     http_info->headers = new net::HttpResponseHeaders(raw_headers);
   3111     scoped_refptr<AppCacheResponseInfo> info(
   3112         new AppCacheResponseInfo(service_->storage(), manifest_url,
   3113                                  response_id, http_info, 0));
   3114     response_infos_.push_back(info);
   3115     return info.get();
   3116   }
   3117 
   3118   MockFrontend* MakeMockFrontend() {
   3119     MockFrontend* frontend = new MockFrontend();
   3120     frontends_.push_back(frontend);
   3121     return frontend;
   3122   }
   3123 
   3124   // Verifies conditions about the group and notifications after an update
   3125   // has finished. Cannot verify update job internals as update is deleted.
   3126   void VerifyExpectations() {
   3127     RetryRequestTestJob::Verify();
   3128     HttpHeadersRequestTestJob::Verify();
   3129 
   3130     EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete());
   3131     EXPECT_EQ(expect_group_is_being_deleted_, group_->is_being_deleted());
   3132 
   3133     if (expect_group_has_cache_) {
   3134       EXPECT_TRUE(group_->newest_complete_cache() != NULL);
   3135 
   3136       if (expect_non_null_update_time_)
   3137         EXPECT_TRUE(!group_->newest_complete_cache()->update_time().is_null());
   3138 
   3139       if (expect_old_cache_) {
   3140         EXPECT_NE(expect_old_cache_, group_->newest_complete_cache());
   3141         EXPECT_TRUE(group_->old_caches().end() !=
   3142             std::find(group_->old_caches().begin(),
   3143                       group_->old_caches().end(), expect_old_cache_));
   3144       }
   3145       if (expect_newest_cache_) {
   3146         EXPECT_EQ(expect_newest_cache_, group_->newest_complete_cache());
   3147         EXPECT_TRUE(group_->old_caches().end() ==
   3148             std::find(group_->old_caches().begin(),
   3149                       group_->old_caches().end(), expect_newest_cache_));
   3150       } else {
   3151         // Tests that don't know which newest cache to expect contain updates
   3152         // that succeed (because the update creates a new cache whose pointer
   3153         // is unknown to the test). Check group and newest cache were stored
   3154         // when update succeeds.
   3155         MockAppCacheStorage* storage =
   3156             reinterpret_cast<MockAppCacheStorage*>(service_->storage());
   3157         EXPECT_TRUE(storage->IsGroupStored(group_.get()));
   3158         EXPECT_TRUE(storage->IsCacheStored(group_->newest_complete_cache()));
   3159 
   3160         // Check that all entries in the newest cache were stored.
   3161         const AppCache::EntryMap& entries =
   3162             group_->newest_complete_cache()->entries();
   3163         for (AppCache::EntryMap::const_iterator it = entries.begin();
   3164              it != entries.end(); ++it) {
   3165           EXPECT_NE(kAppCacheNoResponseId, it->second.response_id());
   3166 
   3167           // Check that any copied entries have the expected response id
   3168           // and that entries that are not copied have a different response id.
   3169           std::map<GURL, int64>::iterator found =
   3170               expect_response_ids_.find(it->first);
   3171           if (found != expect_response_ids_.end()) {
   3172             EXPECT_EQ(found->second, it->second.response_id());
   3173           } else if (expect_old_cache_) {
   3174             AppCacheEntry* old_entry = expect_old_cache_->GetEntry(it->first);
   3175             if (old_entry)
   3176               EXPECT_NE(old_entry->response_id(), it->second.response_id());
   3177           }
   3178         }
   3179       }
   3180     } else {
   3181       EXPECT_TRUE(group_->newest_complete_cache() == NULL);
   3182     }
   3183 
   3184     // Check expected events.
   3185     for (size_t i = 0; i < frontends_.size(); ++i) {
   3186       MockFrontend* frontend = frontends_[i];
   3187 
   3188       MockFrontend::RaisedEvents& expected_events = frontend->expected_events_;
   3189       MockFrontend::RaisedEvents& actual_events = frontend->raised_events_;
   3190       EXPECT_EQ(expected_events.size(), actual_events.size());
   3191 
   3192       // Check each expected event.
   3193       for (size_t j = 0;
   3194            j < expected_events.size() && j < actual_events.size(); ++j) {
   3195         EXPECT_EQ(expected_events[j].second, actual_events[j].second);
   3196 
   3197         MockFrontend::HostIds& expected_ids = expected_events[j].first;
   3198         MockFrontend::HostIds& actual_ids = actual_events[j].first;
   3199         EXPECT_EQ(expected_ids.size(), actual_ids.size());
   3200 
   3201         for (size_t k = 0; k < expected_ids.size(); ++k) {
   3202           int id = expected_ids[k];
   3203           EXPECT_TRUE(std::find(actual_ids.begin(), actual_ids.end(), id) !=
   3204               actual_ids.end());
   3205         }
   3206       }
   3207 
   3208       if (!frontend->expected_error_message_.empty()) {
   3209         EXPECT_EQ(frontend->expected_error_message_,
   3210                   frontend->error_message_);
   3211       }
   3212     }
   3213 
   3214     // Verify expected cache contents last as some checks are asserts
   3215     // and will abort the test if they fail.
   3216     if (tested_manifest_) {
   3217       AppCache* cache = group_->newest_complete_cache();
   3218       ASSERT_TRUE(cache != NULL);
   3219       EXPECT_EQ(group_, cache->owning_group());
   3220       EXPECT_TRUE(cache->is_complete());
   3221 
   3222       switch (tested_manifest_) {
   3223         case MANIFEST1:
   3224           VerifyManifest1(cache);
   3225           break;
   3226         case MANIFEST_MERGED_TYPES:
   3227           VerifyManifestMergedTypes(cache);
   3228           break;
   3229         case EMPTY_MANIFEST:
   3230           VerifyEmptyManifest(cache);
   3231           break;
   3232         case EMPTY_FILE_MANIFEST:
   3233           VerifyEmptyFileManifest(cache);
   3234           break;
   3235         case PENDING_MASTER_NO_UPDATE:
   3236           VerifyMasterEntryNoUpdate(cache);
   3237           break;
   3238         case MANIFEST_WITH_INTERCEPT:
   3239           VerifyManifestWithIntercept(cache);
   3240           break;
   3241         case NONE:
   3242         default:
   3243           break;
   3244       }
   3245     }
   3246   }
   3247 
   3248   void VerifyManifest1(AppCache* cache) {
   3249     size_t expected = 3 + expect_extra_entries_.size();
   3250     EXPECT_EQ(expected, cache->entries().size());
   3251     const char* kManifestPath = tested_manifest_path_override_ ?
   3252         tested_manifest_path_override_ :
   3253         "files/manifest1";
   3254     AppCacheEntry* entry =
   3255         cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
   3256     ASSERT_TRUE(entry);
   3257     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
   3258     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
   3259     ASSERT_TRUE(entry);
   3260     EXPECT_TRUE(entry->IsExplicit());
   3261     entry = cache->GetEntry(
   3262         MockHttpServer::GetMockUrl("files/fallback1a"));
   3263     ASSERT_TRUE(entry);
   3264     EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types());
   3265 
   3266     for (AppCache::EntryMap::iterator i = expect_extra_entries_.begin();
   3267          i != expect_extra_entries_.end(); ++i) {
   3268       entry = cache->GetEntry(i->first);
   3269       ASSERT_TRUE(entry);
   3270       EXPECT_EQ(i->second.types(), entry->types());
   3271     }
   3272 
   3273     expected = 1;
   3274     ASSERT_EQ(expected, cache->fallback_namespaces_.size());
   3275     EXPECT_TRUE(cache->fallback_namespaces_[0] ==
   3276                     Namespace(
   3277                         APPCACHE_FALLBACK_NAMESPACE,
   3278                         MockHttpServer::GetMockUrl("files/fallback1"),
   3279                         MockHttpServer::GetMockUrl("files/fallback1a"),
   3280                         false));
   3281 
   3282     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
   3283     EXPECT_TRUE(cache->online_whitelist_all_);
   3284 
   3285     EXPECT_TRUE(cache->update_time_ > base::Time());
   3286   }
   3287 
   3288   void VerifyManifestMergedTypes(AppCache* cache) {
   3289     size_t expected = 2;
   3290     EXPECT_EQ(expected, cache->entries().size());
   3291     AppCacheEntry* entry = cache->GetEntry(
   3292         MockHttpServer::GetMockUrl("files/manifest-merged-types"));
   3293     ASSERT_TRUE(entry);
   3294     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MANIFEST,
   3295               entry->types());
   3296     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
   3297     ASSERT_TRUE(entry);
   3298     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FALLBACK |
   3299         AppCacheEntry::MASTER, entry->types());
   3300 
   3301     expected = 1;
   3302     ASSERT_EQ(expected, cache->fallback_namespaces_.size());
   3303     EXPECT_TRUE(cache->fallback_namespaces_[0] ==
   3304                     Namespace(
   3305                         APPCACHE_FALLBACK_NAMESPACE,
   3306                         MockHttpServer::GetMockUrl("files/fallback1"),
   3307                         MockHttpServer::GetMockUrl("files/explicit1"),
   3308                         false));
   3309 
   3310     EXPECT_EQ(expected, cache->online_whitelist_namespaces_.size());
   3311     EXPECT_TRUE(cache->online_whitelist_namespaces_[0] ==
   3312                     Namespace(
   3313                         APPCACHE_NETWORK_NAMESPACE,
   3314                         MockHttpServer::GetMockUrl("files/online1"),
   3315                         GURL(), false));
   3316     EXPECT_FALSE(cache->online_whitelist_all_);
   3317 
   3318     EXPECT_TRUE(cache->update_time_ > base::Time());
   3319   }
   3320 
   3321   void VerifyEmptyManifest(AppCache* cache) {
   3322     const char* kManifestPath = tested_manifest_path_override_ ?
   3323         tested_manifest_path_override_ :
   3324         "files/empty-manifest";
   3325     size_t expected = 1;
   3326     EXPECT_EQ(expected, cache->entries().size());
   3327     AppCacheEntry* entry = cache->GetEntry(
   3328         MockHttpServer::GetMockUrl(kManifestPath));
   3329     ASSERT_TRUE(entry);
   3330     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
   3331 
   3332     EXPECT_TRUE(cache->fallback_namespaces_.empty());
   3333     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
   3334     EXPECT_FALSE(cache->online_whitelist_all_);
   3335 
   3336     EXPECT_TRUE(cache->update_time_ > base::Time());
   3337   }
   3338 
   3339   void VerifyEmptyFileManifest(AppCache* cache) {
   3340     EXPECT_EQ(size_t(2), cache->entries().size());
   3341     AppCacheEntry* entry = cache->GetEntry(
   3342         MockHttpServer::GetMockUrl("files/empty-file-manifest"));
   3343     ASSERT_TRUE(entry);
   3344     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
   3345 
   3346     entry = cache->GetEntry(
   3347         MockHttpServer::GetMockUrl("files/empty1"));
   3348     ASSERT_TRUE(entry);
   3349     EXPECT_EQ(AppCacheEntry::EXPLICIT, entry->types());
   3350     EXPECT_TRUE(entry->has_response_id());
   3351 
   3352     EXPECT_TRUE(cache->fallback_namespaces_.empty());
   3353     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
   3354     EXPECT_FALSE(cache->online_whitelist_all_);
   3355 
   3356     EXPECT_TRUE(cache->update_time_ > base::Time());
   3357   }
   3358 
   3359   void VerifyMasterEntryNoUpdate(AppCache* cache) {
   3360     EXPECT_EQ(size_t(3), cache->entries().size());
   3361     AppCacheEntry* entry = cache->GetEntry(
   3362         MockHttpServer::GetMockUrl("files/notmodified"));
   3363     ASSERT_TRUE(entry);
   3364     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
   3365 
   3366     entry = cache->GetEntry(
   3367         MockHttpServer::GetMockUrl("files/explicit1"));
   3368     ASSERT_TRUE(entry);
   3369     EXPECT_EQ(AppCacheEntry::MASTER, entry->types());
   3370     EXPECT_TRUE(entry->has_response_id());
   3371 
   3372     entry = cache->GetEntry(
   3373         MockHttpServer::GetMockUrl("files/explicit2"));
   3374     ASSERT_TRUE(entry);
   3375     EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MASTER, entry->types());
   3376     EXPECT_TRUE(entry->has_response_id());
   3377 
   3378     EXPECT_TRUE(cache->fallback_namespaces_.empty());
   3379     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
   3380     EXPECT_FALSE(cache->online_whitelist_all_);
   3381 
   3382     EXPECT_TRUE(cache->update_time_ > base::Time());
   3383   }
   3384 
   3385   void VerifyManifestWithIntercept(AppCache* cache) {
   3386     EXPECT_EQ(2u, cache->entries().size());
   3387     const char* kManifestPath = "files/manifest-with-intercept";
   3388     AppCacheEntry* entry =
   3389         cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
   3390     ASSERT_TRUE(entry);
   3391     EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
   3392     entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a"));
   3393     ASSERT_TRUE(entry);
   3394     EXPECT_TRUE(entry->IsIntercept());
   3395     EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
   3396     EXPECT_FALSE(cache->online_whitelist_all_);
   3397     EXPECT_TRUE(cache->update_time_ > base::Time());
   3398   }
   3399 
   3400  private:
   3401   // Various manifest files used in this test.
   3402   enum TestedManifest {
   3403     NONE,
   3404     MANIFEST1,
   3405     MANIFEST_MERGED_TYPES,
   3406     EMPTY_MANIFEST,
   3407     EMPTY_FILE_MANIFEST,
   3408     PENDING_MASTER_NO_UPDATE,
   3409     MANIFEST_WITH_INTERCEPT
   3410   };
   3411 
   3412   scoped_ptr<IOThread> io_thread_;
   3413 
   3414   scoped_ptr<MockAppCacheService> service_;
   3415   scoped_refptr<AppCacheGroup> group_;
   3416   scoped_refptr<AppCache> protect_newest_cache_;
   3417   scoped_ptr<base::WaitableEvent> event_;
   3418 
   3419   scoped_ptr<AppCacheResponseWriter> response_writer_;
   3420 
   3421   // Hosts used by an async test that need to live until update job finishes.
   3422   // Otherwise, test can put host on the stack instead of here.
   3423   std::vector<AppCacheHost*> hosts_;
   3424 
   3425   // Response infos used by an async test that need to live until update job
   3426   // finishes.
   3427   std::vector<scoped_refptr<AppCacheResponseInfo> > response_infos_;
   3428 
   3429   // Flag indicating if test cares to verify the update after update finishes.
   3430   bool do_checks_after_update_finished_;
   3431   bool expect_group_obsolete_;
   3432   bool expect_group_has_cache_;
   3433   bool expect_group_is_being_deleted_;
   3434   AppCache* expect_old_cache_;
   3435   AppCache* expect_newest_cache_;
   3436   bool expect_non_null_update_time_;
   3437   std::vector<MockFrontend*> frontends_;  // to check expected events
   3438   TestedManifest tested_manifest_;
   3439   const char* tested_manifest_path_override_;
   3440   AppCache::EntryMap expect_extra_entries_;
   3441   std::map<GURL, int64> expect_response_ids_;
   3442 };
   3443 
   3444 TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
   3445   MockAppCacheService service;
   3446   scoped_refptr<AppCacheGroup> group(
   3447       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
   3448                         service.storage()->NewGroupId()));
   3449 
   3450   AppCacheUpdateJob update(&service, group.get());
   3451 
   3452   // Pretend group is in checking state.
   3453   group->update_job_ = &update;
   3454   group->update_status_ = AppCacheGroup::CHECKING;
   3455 
   3456   update.StartUpdate(NULL, GURL());
   3457   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
   3458 
   3459   MockFrontend mock_frontend;
   3460   AppCacheHost host(1, &mock_frontend, &service);
   3461   update.StartUpdate(&host, GURL());
   3462 
   3463   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
   3464   size_t expected = 1;
   3465   EXPECT_EQ(expected, events.size());
   3466   EXPECT_EQ(expected, events[0].first.size());
   3467   EXPECT_EQ(host.host_id(), events[0].first[0]);
   3468   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
   3469   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
   3470 }
   3471 
   3472 TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
   3473   MockAppCacheService service;
   3474   scoped_refptr<AppCacheGroup> group(
   3475       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
   3476                         service.storage()->NewGroupId()));
   3477 
   3478   AppCacheUpdateJob update(&service, group.get());
   3479 
   3480   // Pretend group is in downloading state.
   3481   group->update_job_ = &update;
   3482   group->update_status_ = AppCacheGroup::DOWNLOADING;
   3483 
   3484   update.StartUpdate(NULL, GURL());
   3485   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
   3486 
   3487   MockFrontend mock_frontend;
   3488   AppCacheHost host(1, &mock_frontend, &service);
   3489   update.StartUpdate(&host, GURL());
   3490 
   3491   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
   3492   size_t expected = 2;
   3493   EXPECT_EQ(expected, events.size());
   3494   expected = 1;
   3495   EXPECT_EQ(expected, events[0].first.size());
   3496   EXPECT_EQ(host.host_id(), events[0].first[0]);
   3497   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
   3498 
   3499   EXPECT_EQ(expected, events[1].first.size());
   3500   EXPECT_EQ(host.host_id(), events[1].first[0]);
   3501   EXPECT_EQ(appcache::APPCACHE_DOWNLOADING_EVENT, events[1].second);
   3502 
   3503   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
   3504 }
   3505 
   3506 TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
   3507   RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
   3508 }
   3509 
   3510 TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
   3511   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
   3512 }
   3513 
   3514 TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
   3515   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
   3516 }
   3517 
   3518 TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
   3519   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
   3520 }
   3521 
   3522 TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
   3523   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
   3524 }
   3525 
   3526 TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
   3527   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
   3528 }
   3529 
   3530 TEST_F(AppCacheUpdateJobTest, ManifestNotFound) {
   3531   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
   3532 }
   3533 
   3534 TEST_F(AppCacheUpdateJobTest, ManifestGone) {
   3535   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest);
   3536 }
   3537 
   3538 TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
   3539   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
   3540 }
   3541 
   3542 TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
   3543   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
   3544 }
   3545 
   3546 TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
   3547   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest);
   3548 }
   3549 
   3550 TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
   3551   RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test);
   3552 }
   3553 
   3554 TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
   3555   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
   3556 }
   3557 
   3558 TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
   3559   RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
   3560 }
   3561 
   3562 TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
   3563   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
   3564 }
   3565 
   3566 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
   3567   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
   3568 }
   3569 
   3570 TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
   3571   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
   3572 }
   3573 
   3574 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
   3575   RunTestOnIOThread(
   3576       &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
   3577 }
   3578 
   3579 TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
   3580   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
   3581 }
   3582 
   3583 TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
   3584   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
   3585 }
   3586 
   3587 TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
   3588   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
   3589 }
   3590 
   3591 TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
   3592   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
   3593 }
   3594 
   3595 TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
   3596   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
   3597 }
   3598 
   3599 TEST_F(AppCacheUpdateJobTest, EmptyFile) {
   3600   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest);
   3601 }
   3602 
   3603 TEST_F(AppCacheUpdateJobTest, RetryRequest) {
   3604   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
   3605 }
   3606 
   3607 TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
   3608   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
   3609 }
   3610 
   3611 TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
   3612   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
   3613 }
   3614 
   3615 TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
   3616   RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
   3617 }
   3618 
   3619 TEST_F(AppCacheUpdateJobTest, RetryUrl) {
   3620   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
   3621 }
   3622 
   3623 TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
   3624   RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
   3625 }
   3626 
   3627 TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
   3628   RunTestOnIOThread(
   3629       &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
   3630 }
   3631 
   3632 TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
   3633   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
   3634 }
   3635 
   3636 TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
   3637   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
   3638 }
   3639 
   3640 TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
   3641   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
   3642 }
   3643 
   3644 TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
   3645   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
   3646 }
   3647 
   3648 TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
   3649   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
   3650 }
   3651 
   3652 TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
   3653   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
   3654 }
   3655 
   3656 TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
   3657   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
   3658 }
   3659 
   3660 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
   3661   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
   3662 }
   3663 
   3664 TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
   3665   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
   3666 }
   3667 
   3668 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
   3669   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
   3670 }
   3671 
   3672 TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
   3673   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
   3674 }
   3675 
   3676 TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
   3677   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
   3678 }
   3679 
   3680 TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
   3681   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
   3682 }
   3683 
   3684 TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
   3685   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
   3686 }
   3687 
   3688 TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
   3689   RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
   3690 }
   3691 
   3692 TEST_F(AppCacheUpdateJobTest, IfModifiedSince) {
   3693   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest);
   3694 }
   3695 
   3696 TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
   3697   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
   3698 }
   3699 
   3700 TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
   3701   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
   3702 }
   3703 
   3704 TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
   3705   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
   3706 }
   3707 
   3708 TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
   3709   RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
   3710 }
   3711 
   3712 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
   3713   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
   3714 }
   3715 
   3716 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
   3717   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
   3718 }
   3719 
   3720 }  // namespace content
   3721