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