• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/stl_util.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread.h"
10 #include "content/browser/appcache/mock_appcache_service.h"
11 #include "net/base/net_errors.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/url_request/url_request_error_job.h"
14 #include "net/url_request/url_request_job_factory_impl.h"
15 #include "net/url_request/url_request_test_job.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webkit/browser/appcache/appcache_group.h"
19 #include "webkit/browser/appcache/appcache_host.h"
20 #include "webkit/browser/appcache/appcache_response.h"
21 #include "webkit/browser/appcache/appcache_update_job.h"
22 
23 using appcache::AppCache;
24 using appcache::AppCacheEntry;
25 using appcache::AppCacheFrontend;
26 using appcache::AppCacheHost;
27 using appcache::AppCacheGroup;
28 using appcache::AppCacheResponseInfo;
29 using appcache::AppCacheUpdateJob;
30 using appcache::AppCacheResponseWriter;
31 using appcache::APPCACHE_CACHED_EVENT;
32 using appcache::APPCACHE_CHECKING_EVENT;
33 using appcache::APPCACHE_DOWNLOADING_EVENT;
34 using appcache::APPCACHE_ERROR_EVENT;
35 using appcache::AppCacheEventID;
36 using appcache::APPCACHE_FALLBACK_NAMESPACE;
37 using appcache::HttpResponseInfoIOBuffer;
38 using appcache::kAppCacheNoCacheId;
39 using appcache::kAppCacheNoResponseId;
40 using appcache::Namespace;
41 using appcache::APPCACHE_NETWORK_NAMESPACE;
42 using appcache::APPCACHE_NO_UPDATE_EVENT;
43 using appcache::APPCACHE_OBSOLETE_EVENT;
44 using appcache::APPCACHE_PROGRESS_EVENT;
45 using appcache::APPCACHE_UPDATE_READY_EVENT;
46 using appcache::AppCacheStatus;
47 
48 namespace content {
49 class AppCacheUpdateJobTest;
50 
51 namespace {
52 
53 const char kManifest1Contents[] =
54     "CACHE MANIFEST\n"
55     "explicit1\n"
56     "FALLBACK:\n"
57     "fallback1 fallback1a\n"
58     "NETWORK:\n"
59     "*\n";
60 
61 // There are a handful of http accessible resources that we need to conduct
62 // these tests. Instead of running a seperate server to host these resources,
63 // we mock them up.
64 class MockHttpServer {
65  public:
GetMockUrl(const std::string & path)66   static GURL GetMockUrl(const std::string& path) {
67     return GURL("http://mockhost/" + path);
68   }
69 
GetMockHttpsUrl(const std::string & path)70   static GURL GetMockHttpsUrl(const std::string& path) {
71     return GURL("https://mockhost/" + path);
72   }
73 
GetMockCrossOriginHttpsUrl(const std::string & path)74   static GURL GetMockCrossOriginHttpsUrl(const std::string& path) {
75     return GURL("https://cross_origin_host/" + path);
76   }
77 
JobFactory(net::URLRequest * request,net::NetworkDelegate * network_delegate)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:
GetMockResponse(const std::string & path,std::string * headers,std::string * body)91   static void GetMockResponse(const std::string& path,
92                               std::string* headers,
93                               std::string* body) {
94     const char ok_headers[] =
95         "HTTP/1.1 200 OK\0"
96         "\0";
97     const char error_headers[] =
98         "HTTP/1.1 500 BOO HOO\0"
99         "\0";
100     const char manifest_headers[] =
101         "HTTP/1.1 200 OK\0"
102         "Content-type: text/cache-manifest\0"
103         "\0";
104     const char not_modified_headers[] =
105         "HTTP/1.1 304 NOT MODIFIED\0"
106         "\0";
107     const char gone_headers[] =
108         "HTTP/1.1 410 GONE\0"
109         "\0";
110     const char not_found_headers[] =
111         "HTTP/1.1 404 NOT FOUND\0"
112         "\0";
113     const char no_store_headers[] =
114         "HTTP/1.1 200 OK\0"
115         "Cache-Control: no-store\0"
116         "\0";
117 
118     if (path == "/files/missing-mime-manifest") {
119       (*headers) = std::string(ok_headers, arraysize(ok_headers));
120       (*body) = "CACHE MANIFEST\n";
121     } else if (path == "/files/bad-manifest") {
122       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
123       (*body) = "BAD CACHE MANIFEST";
124     } else if (path == "/files/empty1") {
125       (*headers) = std::string(ok_headers, arraysize(ok_headers));
126       (*body) = "";
127     } else if (path == "/files/empty-file-manifest") {
128       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
129       (*body) = "CACHE MANIFEST\n"
130                 "empty1\n";
131     } else if (path == "/files/empty-manifest") {
132       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
133       (*body) = "CACHE MANIFEST\n";
134     } else if (path == "/files/explicit1") {
135       (*headers) = std::string(ok_headers, arraysize(ok_headers));
136       (*body) = "explicit1";
137     } else if (path == "/files/explicit2") {
138       (*headers) = std::string(ok_headers, arraysize(ok_headers));
139       (*body) = "explicit2";
140     } else if (path == "/files/fallback1a") {
141       (*headers) = std::string(ok_headers, arraysize(ok_headers));
142       (*body) = "fallback1a";
143     } else if (path == "/files/intercept1a") {
144       (*headers) = std::string(ok_headers, arraysize(ok_headers));
145       (*body) = "intercept1a";
146     } else if (path == "/files/gone") {
147       (*headers) = std::string(gone_headers, arraysize(gone_headers));
148       (*body) = "";
149     } else if (path == "/files/manifest1") {
150       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
151       (*body) = kManifest1Contents;
152     } else if (path == "/files/manifest1-with-notmodified") {
153       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
154       (*body) = kManifest1Contents;
155       (*body).append("CACHE:\n"
156                      "notmodified\n");
157     } else if (path == "/files/manifest-fb-404") {
158       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
159       (*body) = "CACHE MANIFEST\n"
160                 "explicit1\n"
161                 "FALLBACK:\n"
162                 "fallback1 fallback1a\n"
163                 "fallback404 fallback-404\n"
164                 "NETWORK:\n"
165                 "online1\n";
166     } else if (path == "/files/manifest-merged-types") {
167       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
168       (*body) = "CACHE MANIFEST\n"
169                 "explicit1\n"
170                 "# manifest is also an explicit entry\n"
171                 "manifest-merged-types\n"
172                 "FALLBACK:\n"
173                 "# fallback is also explicit entry\n"
174                 "fallback1 explicit1\n"
175                 "NETWORK:\n"
176                 "online1\n";
177     } else if (path == "/files/manifest-with-404") {
178       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
179       (*body) = "CACHE MANIFEST\n"
180                 "explicit-404\n"
181                 "explicit1\n"
182                 "explicit2\n"
183                 "explicit3\n"
184                 "FALLBACK:\n"
185                 "fallback1 fallback1a\n"
186                 "NETWORK:\n"
187                 "online1\n";
188     } else if (path == "/files/manifest-with-intercept") {
189       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
190       (*body) = "CACHE MANIFEST\n"
191                 "CHROMIUM-INTERCEPT:\n"
192                 "intercept1 return intercept1a\n";
193     } else if (path == "/files/notmodified") {
194       (*headers) = std::string(not_modified_headers,
195                                arraysize(not_modified_headers));
196       (*body) = "";
197     } else if (path == "/files/servererror") {
198       (*headers) = std::string(error_headers,
199                                arraysize(error_headers));
200       (*body) = "error";
201     } else if (path == "/files/valid_cross_origin_https_manifest") {
202       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
203       (*body) = "CACHE MANIFEST\n"
204                 "https://cross_origin_host/files/explicit1\n";
205     } else if (path == "/files/invalid_cross_origin_https_manifest") {
206       (*headers) = std::string(manifest_headers, arraysize(manifest_headers));
207       (*body) = "CACHE MANIFEST\n"
208                 "https://cross_origin_host/files/no-store-headers\n";
209     } else if (path == "/files/no-store-headers") {
210       (*headers) = std::string(no_store_headers, arraysize(no_store_headers));
211       (*body) = "no-store";
212     } else {
213       (*headers) = std::string(not_found_headers,
214                                arraysize(not_found_headers));
215       (*body) = "";
216     }
217   }
218 };
219 
220 class MockHttpServerJobFactory
221     : public net::URLRequestJobFactory::ProtocolHandler {
222  public:
MaybeCreateJob(net::URLRequest * request,net::NetworkDelegate * network_delegate) const223   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 
operator ==(const Namespace & lhs,const Namespace & rhs)230 inline bool operator==(const Namespace& lhs, const Namespace& rhs) {
231   return lhs.type == rhs.type &&
232          lhs.namespace_url == rhs.namespace_url &&
233          lhs.target_url == rhs.target_url;
234 }
235 
236 }  // namespace
237 
238 class MockFrontend : public AppCacheFrontend {
239  public:
MockFrontend()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 
OnCacheSelected(int host_id,const appcache::AppCacheInfo & info)246   virtual void OnCacheSelected(
247       int host_id, const appcache::AppCacheInfo& info) OVERRIDE {
248   }
249 
OnStatusChanged(const std::vector<int> & host_ids,AppCacheStatus status)250   virtual void OnStatusChanged(const std::vector<int>& host_ids,
251                                AppCacheStatus status) OVERRIDE {
252   }
253 
OnEventRaised(const std::vector<int> & host_ids,AppCacheEventID event_id)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 
OnErrorEventRaised(const std::vector<int> & host_ids,const appcache::AppCacheErrorDetails & details)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 
OnProgressEventRaised(const std::vector<int> & host_ids,const GURL & url,int num_total,int num_complete)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 
OnLogMessage(int host_id,appcache::AppCacheLogLevel log_level,const std::string & message)308   virtual void OnLogMessage(int host_id,
309                             appcache::AppCacheLogLevel log_level,
310                             const std::string& message) OVERRIDE {
311   }
312 
OnContentBlocked(int host_id,const GURL & manifest_url)313   virtual void OnContentBlocked(int host_id,
314                                 const GURL& manifest_url) OVERRIDE {
315   }
316 
AddExpectedEvent(const std::vector<int> & host_ids,AppCacheEventID event_id)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 
SetIgnoreProgressEvents(bool ignore)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 
SetVerifyProgressEvents(bool verify)333   void SetVerifyProgressEvents(bool verify) {
334     verify_progress_events_ = verify;
335   }
336 
TriggerAdditionalUpdates(AppCacheEventID trigger_event,AppCacheUpdateJob * update)337   void TriggerAdditionalUpdates(AppCacheEventID trigger_event,
338                                 AppCacheUpdateJob* update) {
339     start_update_trigger_ = trigger_event;
340     update_ = update;
341   }
342 
AdditionalUpdateHost(AppCacheHost * host)343   void AdditionalUpdateHost(AppCacheHost* host) {
344     update_hosts_.push_back(host);
345   }
346 
347   typedef std::vector<int> HostIds;
348   typedef std::pair<HostIds, AppCacheEventID> RaisedEvent;
349   typedef std::vector<RaisedEvent> RaisedEvents;
350   RaisedEvents raised_events_;
351   std::string error_message_;
352 
353   // Set the expected events if verification needs to happen asynchronously.
354   RaisedEvents expected_events_;
355   std::string expected_error_message_;
356 
357   bool ignore_progress_events_;
358 
359   bool verify_progress_events_;
360   int last_progress_total_;
361   int last_progress_complete_;
362 
363   // Add ability for frontend to add master entries to an inprogress update.
364   AppCacheEventID start_update_trigger_;
365   AppCacheUpdateJob* update_;
366   std::vector<AppCacheHost*> update_hosts_;
367 };
368 
369 // Helper factories to simulate redirected URL responses for tests.
370 class RedirectFactory : public net::URLRequestJobFactory::ProtocolHandler {
371  public:
MaybeCreateJob(net::URLRequest * request,net::NetworkDelegate * network_delegate) const372   virtual net::URLRequestJob* MaybeCreateJob(
373       net::URLRequest* request,
374       net::NetworkDelegate* network_delegate) const OVERRIDE {
375     return new net::URLRequestTestJob(
376         request,
377         network_delegate,
378         net::URLRequestTestJob::test_redirect_headers(),
379         net::URLRequestTestJob::test_data_1(),
380         true);
381   }
382 };
383 
384 // Helper class to simulate a URL that returns retry or success.
385 class RetryRequestTestJob : public net::URLRequestTestJob {
386  public:
387   enum RetryHeader {
388     NO_RETRY_AFTER,
389     NONZERO_RETRY_AFTER,
390     RETRY_AFTER_0,
391   };
392 
393   static const GURL kRetryUrl;
394 
395   // Call this at the start of each retry test.
Initialize(int num_retry_responses,RetryHeader header,int expected_requests)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.
Verify()405   static void Verify() {
406     EXPECT_EQ(expected_requests_, num_requests_);
407     num_requests_ = 0;
408     expected_requests_ = 0;
409   }
410 
RetryFactory(net::URLRequest * request,net::NetworkDelegate * network_delegate)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 
GetResponseCode() const426   virtual int GetResponseCode() const OVERRIDE { return response_code_; }
427 
428  private:
~RetryRequestTestJob()429   virtual ~RetryRequestTestJob() {}
430 
retry_headers()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 
manifest_headers()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 
data()463   static std::string data() {
464     return std::string("CACHE MANIFEST\r"
465         "http://retry\r");  // must be same as kRetryUrl
466   }
467 
RetryRequestTestJob(net::URLRequest * request,net::NetworkDelegate * network_delegate,const std::string & headers,int response_code)468   RetryRequestTestJob(net::URLRequest* request,
469                       net::NetworkDelegate* network_delegate,
470                       const std::string& headers,
471                       int response_code)
472       : net::URLRequestTestJob(
473             request, network_delegate, headers, data(), true),
474         response_code_(response_code) {
475   }
476 
477   int response_code_;
478 
479   static int num_requests_;
480   static int num_retries_;
481   static RetryHeader retry_after_;
482   static int expected_requests_;
483 };
484 
485 class RetryRequestTestJobFactory
486     : public net::URLRequestJobFactory::ProtocolHandler {
487  public:
MaybeCreateJob(net::URLRequest * request,net::NetworkDelegate * network_delegate) const488   virtual net::URLRequestJob* MaybeCreateJob(
489       net::URLRequest* request,
490       net::NetworkDelegate* network_delegate) const OVERRIDE {
491     return RetryRequestTestJob::RetryFactory(request, network_delegate);
492   }
493 };
494 
495 // static
496 const GURL RetryRequestTestJob::kRetryUrl("http://retry");
497 int RetryRequestTestJob::num_requests_ = 0;
498 int RetryRequestTestJob::num_retries_;
499 RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
500 int RetryRequestTestJob::expected_requests_ = 0;
501 
502 // Helper class to check for certain HTTP headers.
503 class HttpHeadersRequestTestJob : public net::URLRequestTestJob {
504  public:
505   // Call this at the start of each HTTP header-related test.
Initialize(const std::string & expect_if_modified_since,const std::string & expect_if_none_match)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.
Verify()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 
IfModifiedSinceFactory(net::URLRequest * request,net::NetworkDelegate * network_delegate)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:
~HttpHeadersRequestTestJob()548   virtual ~HttpHeadersRequestTestJob() {}
549 
550  private:
551   static std::string expect_if_modified_since_;
552   static bool saw_if_modified_since_;
553   static std::string expect_if_none_match_;
554   static bool saw_if_none_match_;
555   static bool already_checked_;
556 };
557 
558 // static
559 std::string HttpHeadersRequestTestJob::expect_if_modified_since_;
560 bool HttpHeadersRequestTestJob::saw_if_modified_since_ = false;
561 std::string HttpHeadersRequestTestJob::expect_if_none_match_;
562 bool HttpHeadersRequestTestJob::saw_if_none_match_ = false;
563 bool HttpHeadersRequestTestJob::already_checked_ = false;
564 
565 class IfModifiedSinceJobFactory
566     : public net::URLRequestJobFactory::ProtocolHandler {
567  public:
MaybeCreateJob(net::URLRequest * request,net::NetworkDelegate * network_delegate) const568   virtual net::URLRequestJob* MaybeCreateJob(
569       net::URLRequest* request,
570       net::NetworkDelegate* network_delegate) const OVERRIDE {
571     return HttpHeadersRequestTestJob::IfModifiedSinceFactory(
572         request, network_delegate);
573   }
574 };
575 
576 class IOThread : public base::Thread {
577  public:
IOThread(const char * name)578   explicit IOThread(const char* name)
579       : base::Thread(name) {
580   }
581 
~IOThread()582   virtual ~IOThread() {
583     Stop();
584   }
585 
request_context()586   net::URLRequestContext* request_context() {
587     return request_context_.get();
588   }
589 
SetNewJobFactory(net::URLRequestJobFactory * job_factory)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 
Init()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 
CleanUp()606   virtual void CleanUp() OVERRIDE {
607     request_context_.reset();
608     job_factory_.reset();
609   }
610 
611  private:
612   scoped_ptr<net::URLRequestJobFactory> job_factory_;
613   scoped_ptr<net::URLRequestContext> request_context_;
614 };
615 
616 class AppCacheUpdateJobTest : public testing::Test,
617                               public AppCacheGroup::UpdateObserver {
618  public:
AppCacheUpdateJobTest()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>
RunTestOnIOThread(Method 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 
StartCacheAttemptTest()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 
StartUpgradeAttemptTest()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 
CacheAttemptFetchManifestFailTest()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 
UpgradeFetchManifestFailTest()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 
ManifestRedirectTest()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 
ManifestMissingMimeTypeTest()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 
ManifestNotFoundTest()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 
ManifestGoneTest()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 
CacheAttemptNotModifiedTest()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 
UpgradeNotModifiedTest()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 
UpgradeManifestDataUnchangedTest()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
Bug95101Test()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 
StartUpdateAfterSeedingStorageData(int result)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 
BasicCacheAttemptSuccessTest()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 
DownloadInterceptEntriesTest()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 
BasicUpgradeSuccessTest()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 
UpgradeLoadFromNewestCacheTest()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 
UpgradeNoLoadFromNewestCacheTest()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 
UpgradeLoadFromNewestCacheVaryHeaderTest()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 
UpgradeSuccessMergedTypesTest()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 
CacheAttemptFailUrlFetchTest()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 
UpgradeFailUrlFetchTest()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 
UpgradeFailMasterUrlFetchTest()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 
EmptyManifestTest()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 
EmptyFileTest()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 
RetryRequestTest()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 
RetryNoRetryAfterTest()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 
RetryNonzeroRetryAfterTest()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 
RetrySuccessTest()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 
RetryUrlTest()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 
FailStoreNewestCacheTest()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 
UpgradeFailStoreNewestCacheTest()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 
MasterEntryFailStoreNewestCacheTest()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 
UpgradeFailMakeGroupObsoleteTest()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 
MasterEntryFetchManifestFailTest()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 
MasterEntryBadManifestTest()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 
MasterEntryManifestNotFoundTest()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 
MasterEntryFailUrlFetchTest()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 
MasterEntryAllFailTest()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 
UpgradeMasterEntryAllFailTest()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 
MasterEntrySomeFailTest()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 
UpgradeMasterEntrySomeFailTest()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 
MasterEntryNoUpdateTest()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 
StartUpdateMidCacheAttemptTest()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 
StartUpdateMidNoUpdateTest()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 
StartUpdateMidDownloadTest()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 
QueueMasterEntryTest()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 
IfModifiedSinceTest()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 
IfModifiedSinceUpgradeTest()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 
IfNoneMatchUpgradeTest()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 
IfNoneMatchRefetchTest()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 
MultipleHeadersRefetchTest()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 
CrossOriginHttpsSuccessTest()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 
CrossOriginHttpsDeniedTest()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 
WaitForUpdateToFinish()3037   void WaitForUpdateToFinish() {
3038     if (group_->update_status() == AppCacheGroup::IDLE)
3039       UpdateFinished();
3040     else
3041       group_->AddUpdateObserver(this);
3042   }
3043 
OnUpdateComplete(AppCacheGroup * group)3044   virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE {
3045     ASSERT_EQ(group_, group);
3046     protect_newest_cache_ = group->newest_complete_cache();
3047     UpdateFinished();
3048   }
3049 
UpdateFinished()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 
UpdateFinishedUnwound()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 
MakeService()3076   void MakeService() {
3077     service_.reset(new MockAppCacheService());
3078     service_->set_request_context(io_thread_->request_context());
3079   }
3080 
MakeCacheForGroup(int64 cache_id,int64 manifest_response_id)3081   AppCache* MakeCacheForGroup(int64 cache_id, int64 manifest_response_id) {
3082     return MakeCacheForGroup(cache_id, group_->manifest_url(),
3083                              manifest_response_id);
3084   }
3085 
MakeCacheForGroup(int64 cache_id,const GURL & manifest_entry_url,int64 manifest_response_id)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 
MakeHost(int host_id,AppCacheFrontend * frontend)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 
MakeAppCacheResponseInfo(const GURL & manifest_url,int64 response_id,const std::string & raw_headers)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 
MakeMockFrontend()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.
VerifyExpectations()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 
VerifyManifest1(AppCache * cache)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 
VerifyManifestMergedTypes(AppCache * cache)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 
VerifyEmptyManifest(AppCache * cache)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 
VerifyEmptyFileManifest(AppCache * cache)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 
VerifyMasterEntryNoUpdate(AppCache * cache)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 
VerifyManifestWithIntercept(AppCache * cache)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 
TEST_F(AppCacheUpdateJobTest,AlreadyChecking)3444 TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
3445   MockAppCacheService service;
3446   scoped_refptr<AppCacheGroup> group(
3447       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
3448                         service.storage()->NewGroupId()));
3449 
3450   AppCacheUpdateJob update(&service, group.get());
3451 
3452   // Pretend group is in checking state.
3453   group->update_job_ = &update;
3454   group->update_status_ = AppCacheGroup::CHECKING;
3455 
3456   update.StartUpdate(NULL, GURL());
3457   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
3458 
3459   MockFrontend mock_frontend;
3460   AppCacheHost host(1, &mock_frontend, &service);
3461   update.StartUpdate(&host, GURL());
3462 
3463   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
3464   size_t expected = 1;
3465   EXPECT_EQ(expected, events.size());
3466   EXPECT_EQ(expected, events[0].first.size());
3467   EXPECT_EQ(host.host_id(), events[0].first[0]);
3468   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
3469   EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
3470 }
3471 
TEST_F(AppCacheUpdateJobTest,AlreadyDownloading)3472 TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
3473   MockAppCacheService service;
3474   scoped_refptr<AppCacheGroup> group(
3475       new AppCacheGroup(service.storage(), GURL("http://manifesturl.com"),
3476                         service.storage()->NewGroupId()));
3477 
3478   AppCacheUpdateJob update(&service, group.get());
3479 
3480   // Pretend group is in downloading state.
3481   group->update_job_ = &update;
3482   group->update_status_ = AppCacheGroup::DOWNLOADING;
3483 
3484   update.StartUpdate(NULL, GURL());
3485   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
3486 
3487   MockFrontend mock_frontend;
3488   AppCacheHost host(1, &mock_frontend, &service);
3489   update.StartUpdate(&host, GURL());
3490 
3491   MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
3492   size_t expected = 2;
3493   EXPECT_EQ(expected, events.size());
3494   expected = 1;
3495   EXPECT_EQ(expected, events[0].first.size());
3496   EXPECT_EQ(host.host_id(), events[0].first[0]);
3497   EXPECT_EQ(APPCACHE_CHECKING_EVENT, events[0].second);
3498 
3499   EXPECT_EQ(expected, events[1].first.size());
3500   EXPECT_EQ(host.host_id(), events[1].first[0]);
3501   EXPECT_EQ(appcache::APPCACHE_DOWNLOADING_EVENT, events[1].second);
3502 
3503   EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
3504 }
3505 
TEST_F(AppCacheUpdateJobTest,StartCacheAttempt)3506 TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
3507   RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
3508 }
3509 
TEST_F(AppCacheUpdateJobTest,StartUpgradeAttempt)3510 TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
3511   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
3512 }
3513 
TEST_F(AppCacheUpdateJobTest,CacheAttemptFetchManifestFail)3514 TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
3515   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
3516 }
3517 
TEST_F(AppCacheUpdateJobTest,UpgradeFetchManifestFail)3518 TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
3519   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
3520 }
3521 
TEST_F(AppCacheUpdateJobTest,ManifestRedirect)3522 TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
3523   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
3524 }
3525 
TEST_F(AppCacheUpdateJobTest,ManifestMissingMimeTypeTest)3526 TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
3527   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
3528 }
3529 
TEST_F(AppCacheUpdateJobTest,ManifestNotFound)3530 TEST_F(AppCacheUpdateJobTest, ManifestNotFound) {
3531   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
3532 }
3533 
TEST_F(AppCacheUpdateJobTest,ManifestGone)3534 TEST_F(AppCacheUpdateJobTest, ManifestGone) {
3535   RunTestOnIOThread(&AppCacheUpdateJobTest::ManifestGoneTest);
3536 }
3537 
TEST_F(AppCacheUpdateJobTest,CacheAttemptNotModified)3538 TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
3539   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
3540 }
3541 
TEST_F(AppCacheUpdateJobTest,UpgradeNotModified)3542 TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
3543   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
3544 }
3545 
TEST_F(AppCacheUpdateJobTest,UpgradeManifestDataUnchanged)3546 TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchanged) {
3547   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeManifestDataUnchangedTest);
3548 }
3549 
TEST_F(AppCacheUpdateJobTest,Bug95101Test)3550 TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
3551   RunTestOnIOThread(&AppCacheUpdateJobTest::Bug95101Test);
3552 }
3553 
TEST_F(AppCacheUpdateJobTest,BasicCacheAttemptSuccess)3554 TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
3555   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
3556 }
3557 
TEST_F(AppCacheUpdateJobTest,DownloadInterceptEntriesTest)3558 TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
3559   RunTestOnIOThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
3560 }
3561 
TEST_F(AppCacheUpdateJobTest,BasicUpgradeSuccess)3562 TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
3563   RunTestOnIOThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
3564 }
3565 
TEST_F(AppCacheUpdateJobTest,UpgradeLoadFromNewestCache)3566 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
3567   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
3568 }
3569 
TEST_F(AppCacheUpdateJobTest,UpgradeNoLoadFromNewestCache)3570 TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
3571   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
3572 }
3573 
TEST_F(AppCacheUpdateJobTest,UpgradeLoadFromNewestCacheVaryHeader)3574 TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
3575   RunTestOnIOThread(
3576       &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
3577 }
3578 
TEST_F(AppCacheUpdateJobTest,UpgradeSuccessMergedTypes)3579 TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
3580   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
3581 }
3582 
TEST_F(AppCacheUpdateJobTest,CacheAttemptFailUrlFetch)3583 TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
3584   RunTestOnIOThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
3585 }
3586 
TEST_F(AppCacheUpdateJobTest,UpgradeFailUrlFetch)3587 TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
3588   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
3589 }
3590 
TEST_F(AppCacheUpdateJobTest,UpgradeFailMasterUrlFetch)3591 TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
3592   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
3593 }
3594 
TEST_F(AppCacheUpdateJobTest,EmptyManifest)3595 TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
3596   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyManifestTest);
3597 }
3598 
TEST_F(AppCacheUpdateJobTest,EmptyFile)3599 TEST_F(AppCacheUpdateJobTest, EmptyFile) {
3600   RunTestOnIOThread(&AppCacheUpdateJobTest::EmptyFileTest);
3601 }
3602 
TEST_F(AppCacheUpdateJobTest,RetryRequest)3603 TEST_F(AppCacheUpdateJobTest, RetryRequest) {
3604   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryRequestTest);
3605 }
3606 
TEST_F(AppCacheUpdateJobTest,RetryNoRetryAfter)3607 TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
3608   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
3609 }
3610 
TEST_F(AppCacheUpdateJobTest,RetryNonzeroRetryAfter)3611 TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
3612   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
3613 }
3614 
TEST_F(AppCacheUpdateJobTest,RetrySuccess)3615 TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
3616   RunTestOnIOThread(&AppCacheUpdateJobTest::RetrySuccessTest);
3617 }
3618 
TEST_F(AppCacheUpdateJobTest,RetryUrl)3619 TEST_F(AppCacheUpdateJobTest, RetryUrl) {
3620   RunTestOnIOThread(&AppCacheUpdateJobTest::RetryUrlTest);
3621 }
3622 
TEST_F(AppCacheUpdateJobTest,FailStoreNewestCache)3623 TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
3624   RunTestOnIOThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
3625 }
3626 
TEST_F(AppCacheUpdateJobTest,MasterEntryFailStoreNewestCacheTest)3627 TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
3628   RunTestOnIOThread(
3629       &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
3630 }
3631 
TEST_F(AppCacheUpdateJobTest,UpgradeFailStoreNewestCache)3632 TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
3633   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
3634 }
3635 
TEST_F(AppCacheUpdateJobTest,UpgradeFailMakeGroupObsolete)3636 TEST_F(AppCacheUpdateJobTest, UpgradeFailMakeGroupObsolete) {
3637   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
3638 }
3639 
TEST_F(AppCacheUpdateJobTest,MasterEntryFetchManifestFail)3640 TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
3641   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
3642 }
3643 
TEST_F(AppCacheUpdateJobTest,MasterEntryBadManifest)3644 TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
3645   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
3646 }
3647 
TEST_F(AppCacheUpdateJobTest,MasterEntryManifestNotFound)3648 TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
3649   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
3650 }
3651 
TEST_F(AppCacheUpdateJobTest,MasterEntryFailUrlFetch)3652 TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
3653   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
3654 }
3655 
TEST_F(AppCacheUpdateJobTest,MasterEntryAllFail)3656 TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
3657   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
3658 }
3659 
TEST_F(AppCacheUpdateJobTest,UpgradeMasterEntryAllFail)3660 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
3661   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
3662 }
3663 
TEST_F(AppCacheUpdateJobTest,MasterEntrySomeFail)3664 TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
3665   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
3666 }
3667 
TEST_F(AppCacheUpdateJobTest,UpgradeMasterEntrySomeFail)3668 TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
3669   RunTestOnIOThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
3670 }
3671 
TEST_F(AppCacheUpdateJobTest,MasterEntryNoUpdate)3672 TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
3673   RunTestOnIOThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
3674 }
3675 
TEST_F(AppCacheUpdateJobTest,StartUpdateMidCacheAttempt)3676 TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
3677   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
3678 }
3679 
TEST_F(AppCacheUpdateJobTest,StartUpdateMidNoUpdate)3680 TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
3681   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
3682 }
3683 
TEST_F(AppCacheUpdateJobTest,StartUpdateMidDownload)3684 TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
3685   RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
3686 }
3687 
TEST_F(AppCacheUpdateJobTest,QueueMasterEntry)3688 TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
3689   RunTestOnIOThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
3690 }
3691 
TEST_F(AppCacheUpdateJobTest,IfModifiedSince)3692 TEST_F(AppCacheUpdateJobTest, IfModifiedSince) {
3693   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceTest);
3694 }
3695 
TEST_F(AppCacheUpdateJobTest,IfModifiedSinceUpgrade)3696 TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgrade) {
3697   RunTestOnIOThread(&AppCacheUpdateJobTest::IfModifiedSinceUpgradeTest);
3698 }
3699 
TEST_F(AppCacheUpdateJobTest,IfNoneMatchUpgrade)3700 TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgrade) {
3701   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchUpgradeTest);
3702 }
3703 
TEST_F(AppCacheUpdateJobTest,IfNoneMatchRefetch)3704 TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
3705   RunTestOnIOThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
3706 }
3707 
TEST_F(AppCacheUpdateJobTest,MultipleHeadersRefetch)3708 TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
3709   RunTestOnIOThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
3710 }
3711 
TEST_F(AppCacheUpdateJobTest,CrossOriginHttpsSuccess)3712 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
3713   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
3714 }
3715 
TEST_F(AppCacheUpdateJobTest,CrossOriginHttpsDenied)3716 TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
3717   RunTestOnIOThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
3718 }
3719 
3720 }  // namespace content
3721