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