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