Dismiss autofill popup on screen orientation change.
[chromium-blink-merge.git] / webkit / browser / appcache / appcache_request_handler_unittest.cc
blob286fd79c683eb2df9630762c9dbe5dca2c11fd0d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <stack>
6 #include <string>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_error_job.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "webkit/browser/appcache/appcache.h"
22 #include "webkit/browser/appcache/appcache_backend_impl.h"
23 #include "webkit/browser/appcache/appcache_request_handler.h"
24 #include "webkit/browser/appcache/appcache_url_request_job.h"
25 #include "webkit/browser/appcache/mock_appcache_policy.h"
26 #include "webkit/browser/appcache/mock_appcache_service.h"
28 namespace appcache {
30 static const int kMockProcessId = 1;
32 class AppCacheRequestHandlerTest : public testing::Test {
33 public:
34 class MockFrontend : public AppCacheFrontend {
35 public:
36 virtual void OnCacheSelected(
37 int host_id, const appcache::AppCacheInfo& info) OVERRIDE {}
39 virtual void OnStatusChanged(const std::vector<int>& host_ids,
40 appcache::Status status) OVERRIDE {}
42 virtual void OnEventRaised(const std::vector<int>& host_ids,
43 appcache::EventID event_id) OVERRIDE {}
45 virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
46 const std::string& message) OVERRIDE {}
48 virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
49 const GURL& url,
50 int num_total,
51 int num_complete) OVERRIDE {
54 virtual void OnLogMessage(int host_id,
55 appcache::LogLevel log_level,
56 const std::string& message) OVERRIDE {
59 virtual void OnContentBlocked(int host_id,
60 const GURL& manifest_url) OVERRIDE {}
63 // Helper callback to run a test on our io_thread. The io_thread is spun up
64 // once and reused for all tests.
65 template <class Method>
66 void MethodWrapper(Method method) {
67 SetUpTest();
68 (this->*method)();
71 // Subclasses to simulate particular responses so test cases can
72 // exercise fallback code paths.
74 class MockURLRequestDelegate : public net::URLRequest::Delegate {
75 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {}
76 virtual void OnReadCompleted(net::URLRequest* request,
77 int bytes_read) OVERRIDE {
81 class MockURLRequestJob : public net::URLRequestJob {
82 public:
83 MockURLRequestJob(net::URLRequest* request,
84 net::NetworkDelegate* network_delegate,
85 int response_code)
86 : net::URLRequestJob(request, network_delegate),
87 response_code_(response_code),
88 has_response_info_(false) {}
89 MockURLRequestJob(net::URLRequest* request,
90 net::NetworkDelegate* network_delegate,
91 const net::HttpResponseInfo& info)
92 : net::URLRequestJob(request, network_delegate),
93 response_code_(info.headers->response_code()),
94 has_response_info_(true),
95 response_info_(info) {}
97 protected:
98 virtual ~MockURLRequestJob() {}
99 virtual void Start() OVERRIDE {
100 NotifyHeadersComplete();
102 virtual int GetResponseCode() const OVERRIDE {
103 return response_code_;
105 virtual void GetResponseInfo(
106 net::HttpResponseInfo* info) OVERRIDE {
107 if (!has_response_info_)
108 return;
109 *info = response_info_;
112 private:
113 int response_code_;
114 bool has_response_info_;
115 net::HttpResponseInfo response_info_;
118 class MockURLRequest : public net::URLRequest {
119 public:
120 MockURLRequest(
121 const GURL& url,
122 net::URLRequestContext* context,
123 net::NetworkDelegate* network_delegate) :
124 net::URLRequest(url, NULL, context, network_delegate),
125 network_delegate_(network_delegate) {
128 void SimulateResponseCode(int http_response_code) {
129 mock_factory_job_ = new MockURLRequestJob(
130 this, network_delegate_, http_response_code);
131 Start();
132 DCHECK(!mock_factory_job_);
133 // All our simulation needs to satisfy are the following two DCHECKs
134 DCHECK(status().is_success());
135 DCHECK_EQ(http_response_code, GetResponseCode());
138 void SimulateResponseInfo(const net::HttpResponseInfo& info) {
139 mock_factory_job_ = new MockURLRequestJob(
140 this, network_delegate_, info);
141 set_delegate(&delegate_); // needed to get the info back out
142 Start();
143 DCHECK(!mock_factory_job_);
146 MockURLRequestDelegate delegate_;
148 private:
149 net::NetworkDelegate* network_delegate_;
152 static net::URLRequestJob* MockHttpJobFactory(
153 net::URLRequest* request,
154 net::NetworkDelegate* network_delegate,
155 const std::string& scheme) {
156 if (mock_factory_job_) {
157 net::URLRequestJob* temp = mock_factory_job_;
158 mock_factory_job_ = NULL;
159 return temp;
160 } else {
161 // Some of these tests trigger UpdateJobs which start URLRequests.
162 // We short circuit those be returning error jobs.
163 return new net::URLRequestErrorJob(request,
164 network_delegate,
165 net::ERR_INTERNET_DISCONNECTED);
169 static void SetUpTestCase() {
170 io_thread_.reset(new base::Thread("AppCacheRequestHandlerTest Thread"));
171 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
172 io_thread_->StartWithOptions(options);
175 static void TearDownTestCase() {
176 io_thread_.reset(NULL);
179 // Test harness --------------------------------------------------
181 AppCacheRequestHandlerTest()
182 : host_(NULL), empty_network_delegate_(NULL), orig_http_factory_(NULL) {
185 template <class Method>
186 void RunTestOnIOThread(Method method) {
187 test_finished_event_ .reset(new base::WaitableEvent(false, false));
188 io_thread_->message_loop()->PostTask(
189 FROM_HERE,
190 base::Bind(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
191 base::Unretained(this), method));
192 test_finished_event_->Wait();
195 void SetUpTest() {
196 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
197 orig_http_factory_ = net::URLRequest::Deprecated::RegisterProtocolFactory(
198 "http", MockHttpJobFactory);
199 mock_service_.reset(new MockAppCacheService);
200 mock_service_->set_request_context(&empty_context_);
201 mock_policy_.reset(new MockAppCachePolicy);
202 mock_service_->set_appcache_policy(mock_policy_.get());
203 mock_frontend_.reset(new MockFrontend);
204 backend_impl_.reset(new AppCacheBackendImpl);
205 backend_impl_->Initialize(mock_service_.get(), mock_frontend_.get(),
206 kMockProcessId);
207 const int kHostId = 1;
208 backend_impl_->RegisterHost(kHostId);
209 host_ = backend_impl_->GetHost(kHostId);
210 empty_network_delegate_ = NULL;
213 void TearDownTest() {
214 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
215 DCHECK(!mock_factory_job_);
216 net::URLRequest::Deprecated::RegisterProtocolFactory(
217 "http", orig_http_factory_);
218 orig_http_factory_ = NULL;
219 job_ = NULL;
220 handler_.reset();
221 request_.reset();
222 backend_impl_.reset();
223 mock_frontend_.reset();
224 mock_service_.reset();
225 mock_policy_.reset();
226 host_ = NULL;
227 empty_network_delegate_ = NULL;
230 void TestFinished() {
231 // We unwind the stack prior to finishing up to let stack
232 // based objects get deleted.
233 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
234 base::MessageLoop::current()->PostTask(
235 FROM_HERE,
236 base::Bind(&AppCacheRequestHandlerTest::TestFinishedUnwound,
237 base::Unretained(this)));
240 void TestFinishedUnwound() {
241 TearDownTest();
242 test_finished_event_->Signal();
245 void PushNextTask(const base::Closure& task) {
246 task_stack_.push(task);
249 void ScheduleNextTask() {
250 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
251 if (task_stack_.empty()) {
252 TestFinished();
253 return;
255 base::MessageLoop::current()->PostTask(FROM_HERE, task_stack_.top());
256 task_stack_.pop();
259 // MainResource_Miss --------------------------------------------------
261 void MainResource_Miss() {
262 PushNextTask(
263 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
264 base::Unretained(this)));
266 request_.reset(new MockURLRequest(
267 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
268 handler_.reset(host_->CreateRequestHandler(request_.get(),
269 ResourceType::MAIN_FRAME));
270 EXPECT_TRUE(handler_.get());
272 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
273 EXPECT_TRUE(job_.get());
274 EXPECT_TRUE(job_->is_waiting());
276 // We have to wait for completion of storage->FindResponseForMainRequest.
277 ScheduleNextTask();
280 void Verify_MainResource_Miss() {
281 EXPECT_FALSE(job_->is_waiting());
282 EXPECT_TRUE(job_->is_delivering_network_response());
284 int64 cache_id = kNoCacheId;
285 GURL manifest_url;
286 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
287 EXPECT_EQ(kNoCacheId, cache_id);
288 EXPECT_EQ(GURL(), manifest_url);
289 EXPECT_EQ(0, handler_->found_group_id_);
291 AppCacheURLRequestJob* fallback_job;
292 fallback_job = handler_->MaybeLoadFallbackForRedirect(
293 request_.get(),
294 empty_network_delegate_,
295 GURL("http://blah/redirect"));
296 EXPECT_FALSE(fallback_job);
297 fallback_job = handler_->MaybeLoadFallbackForResponse(
298 request_.get(), empty_network_delegate_);
299 EXPECT_FALSE(fallback_job);
301 EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
303 TestFinished();
306 // MainResource_Hit --------------------------------------------------
308 void MainResource_Hit() {
309 PushNextTask(
310 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
311 base::Unretained(this)));
313 request_.reset(new MockURLRequest(
314 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
315 handler_.reset(host_->CreateRequestHandler(request_.get(),
316 ResourceType::MAIN_FRAME));
317 EXPECT_TRUE(handler_.get());
319 mock_storage()->SimulateFindMainResource(
320 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
321 GURL(), AppCacheEntry(),
322 1, 2, GURL("http://blah/manifest/"));
324 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
325 EXPECT_TRUE(job_.get());
326 EXPECT_TRUE(job_->is_waiting());
328 // We have to wait for completion of storage->FindResponseForMainRequest.
329 ScheduleNextTask();
332 void Verify_MainResource_Hit() {
333 EXPECT_FALSE(job_->is_waiting());
334 EXPECT_TRUE(job_->is_delivering_appcache_response());
336 int64 cache_id = kNoCacheId;
337 GURL manifest_url;
338 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
339 EXPECT_EQ(1, cache_id);
340 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
341 EXPECT_EQ(2, handler_->found_group_id_);
343 AppCacheURLRequestJob* fallback_job;
344 fallback_job = handler_->MaybeLoadFallbackForResponse(
345 request_.get(), empty_network_delegate_);
346 EXPECT_FALSE(fallback_job);
348 EXPECT_EQ(GURL("http://blah/manifest/"),
349 host_->preferred_manifest_url());
351 TestFinished();
354 // MainResource_Fallback --------------------------------------------------
356 void MainResource_Fallback() {
357 PushNextTask(
358 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
359 base::Unretained(this)));
361 request_.reset(new MockURLRequest(
362 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
363 handler_.reset(host_->CreateRequestHandler(request_.get(),
364 ResourceType::MAIN_FRAME));
365 EXPECT_TRUE(handler_.get());
367 mock_storage()->SimulateFindMainResource(
368 AppCacheEntry(),
369 GURL("http://blah/fallbackurl"),
370 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
371 1, 2, GURL("http://blah/manifest/"));
373 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
374 EXPECT_TRUE(job_.get());
375 EXPECT_TRUE(job_->is_waiting());
377 // We have to wait for completion of storage->FindResponseForMainRequest.
378 ScheduleNextTask();
381 void Verify_MainResource_Fallback() {
382 EXPECT_FALSE(job_->is_waiting());
383 EXPECT_TRUE(job_->is_delivering_network_response());
385 // When the request is restarted, the existing job is dropped so a
386 // real network job gets created. We expect NULL here which will cause
387 // the net library to create a real job.
388 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
389 EXPECT_FALSE(job_.get());
391 // Simulate an http error of the real network job.
392 request_->SimulateResponseCode(500);
394 job_ = handler_->MaybeLoadFallbackForResponse(
395 request_.get(), empty_network_delegate_);
396 EXPECT_TRUE(job_.get());
397 EXPECT_TRUE(job_->is_delivering_appcache_response());
399 int64 cache_id = kNoCacheId;
400 GURL manifest_url;
401 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
402 EXPECT_EQ(1, cache_id);
403 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
404 EXPECT_TRUE(host_->main_resource_was_namespace_entry_);
405 EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->namespace_entry_url_);
407 EXPECT_EQ(GURL("http://blah/manifest/"),
408 host_->preferred_manifest_url());
410 TestFinished();
413 // MainResource_FallbackOverride --------------------------------------------
415 void MainResource_FallbackOverride() {
416 PushNextTask(base::Bind(
417 &AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
418 base::Unretained(this)));
420 request_.reset(new MockURLRequest(
421 GURL("http://blah/fallback-override"),
422 &empty_context_, empty_network_delegate_));
423 handler_.reset(host_->CreateRequestHandler(request_.get(),
424 ResourceType::MAIN_FRAME));
425 EXPECT_TRUE(handler_.get());
427 mock_storage()->SimulateFindMainResource(
428 AppCacheEntry(),
429 GURL("http://blah/fallbackurl"),
430 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
431 1, 2, GURL("http://blah/manifest/"));
433 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
434 EXPECT_TRUE(job_.get());
435 EXPECT_TRUE(job_->is_waiting());
437 // We have to wait for completion of storage->FindResponseForMainRequest.
438 ScheduleNextTask();
441 void Verify_MainResource_FallbackOverride() {
442 EXPECT_FALSE(job_->is_waiting());
443 EXPECT_TRUE(job_->is_delivering_network_response());
445 // When the request is restarted, the existing job is dropped so a
446 // real network job gets created. We expect NULL here which will cause
447 // the net library to create a real job.
448 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
449 EXPECT_FALSE(job_.get());
451 // Simulate an http error of the real network job, but with custom
452 // headers that override the fallback behavior.
453 const char kOverrideHeaders[] =
454 "HTTP/1.1 404 BOO HOO\0"
455 "x-chromium-appcache-fallback-override: disallow-fallback\0"
456 "\0";
457 net::HttpResponseInfo info;
458 info.headers = new net::HttpResponseHeaders(
459 std::string(kOverrideHeaders, arraysize(kOverrideHeaders)));
460 request_->SimulateResponseInfo(info);
462 job_ = handler_->MaybeLoadFallbackForResponse(
463 request_.get(), empty_network_delegate_);
464 EXPECT_FALSE(job_.get());
466 TestFinished();
469 // SubResource_Miss_WithNoCacheSelected ----------------------------------
471 void SubResource_Miss_WithNoCacheSelected() {
472 request_.reset(new MockURLRequest(
473 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
474 handler_.reset(host_->CreateRequestHandler(request_.get(),
475 ResourceType::SUB_RESOURCE));
477 // We avoid creating handler when possible, sub-resource requests are not
478 // subject to retrieval from an appcache when there's no associated cache.
479 EXPECT_FALSE(handler_.get());
481 TestFinished();
484 // SubResource_Miss_WithCacheSelected ----------------------------------
486 void SubResource_Miss_WithCacheSelected() {
487 // A sub-resource load where the resource is not in an appcache, or
488 // in a network or fallback namespace, should result in a failed request.
489 host_->AssociateCompleteCache(MakeNewCache());
491 request_.reset(new MockURLRequest(
492 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
493 handler_.reset(host_->CreateRequestHandler(request_.get(),
494 ResourceType::SUB_RESOURCE));
495 EXPECT_TRUE(handler_.get());
497 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
498 EXPECT_TRUE(job_.get());
499 EXPECT_TRUE(job_->is_delivering_error_response());
501 AppCacheURLRequestJob* fallback_job;
502 fallback_job = handler_->MaybeLoadFallbackForRedirect(
503 request_.get(), empty_network_delegate_, GURL("http://blah/redirect"));
504 EXPECT_FALSE(fallback_job);
505 fallback_job = handler_->MaybeLoadFallbackForResponse(
506 request_.get(), empty_network_delegate_);
507 EXPECT_FALSE(fallback_job);
509 TestFinished();
512 // SubResource_Miss_WithWaitForCacheSelection -----------------------------
514 void SubResource_Miss_WithWaitForCacheSelection() {
515 // Precondition, the host is waiting on cache selection.
516 scoped_refptr<AppCache> cache(MakeNewCache());
517 host_->pending_selected_cache_id_ = cache->cache_id();
518 host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
520 request_.reset(new MockURLRequest(
521 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
522 handler_.reset(host_->CreateRequestHandler(request_.get(),
523 ResourceType::SUB_RESOURCE));
524 EXPECT_TRUE(handler_.get());
525 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
526 EXPECT_TRUE(job_.get());
527 EXPECT_TRUE(job_->is_waiting());
529 host_->FinishCacheSelection(cache.get(), NULL);
530 EXPECT_FALSE(job_->is_waiting());
531 EXPECT_TRUE(job_->is_delivering_error_response());
533 AppCacheURLRequestJob* fallback_job;
534 fallback_job = handler_->MaybeLoadFallbackForRedirect(
535 request_.get(), empty_network_delegate_, GURL("http://blah/redirect"));
536 EXPECT_FALSE(fallback_job);
537 fallback_job = handler_->MaybeLoadFallbackForResponse(
538 request_.get(), empty_network_delegate_);
539 EXPECT_FALSE(fallback_job);
541 TestFinished();
544 // SubResource_Hit -----------------------------
546 void SubResource_Hit() {
547 host_->AssociateCompleteCache(MakeNewCache());
549 mock_storage()->SimulateFindSubResource(
550 AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
552 request_.reset(new MockURLRequest(
553 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
554 handler_.reset(host_->CreateRequestHandler(request_.get(),
555 ResourceType::SUB_RESOURCE));
556 EXPECT_TRUE(handler_.get());
557 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
558 EXPECT_TRUE(job_.get());
559 EXPECT_TRUE(job_->is_delivering_appcache_response());
561 AppCacheURLRequestJob* fallback_job;
562 fallback_job = handler_->MaybeLoadFallbackForRedirect(
563 request_.get(), empty_network_delegate_, GURL("http://blah/redirect"));
564 EXPECT_FALSE(fallback_job);
565 fallback_job = handler_->MaybeLoadFallbackForResponse(
566 request_.get(), empty_network_delegate_);
567 EXPECT_FALSE(fallback_job);
569 TestFinished();
572 // SubResource_RedirectFallback -----------------------------
574 void SubResource_RedirectFallback() {
575 // Redirects to resources in the a different origin are subject to
576 // fallback namespaces.
577 host_->AssociateCompleteCache(MakeNewCache());
579 mock_storage()->SimulateFindSubResource(
580 AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
582 request_.reset(new MockURLRequest(
583 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
584 handler_.reset(host_->CreateRequestHandler(request_.get(),
585 ResourceType::SUB_RESOURCE));
586 EXPECT_TRUE(handler_.get());
587 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
588 EXPECT_FALSE(job_.get());
590 job_ = handler_->MaybeLoadFallbackForRedirect(
591 request_.get(),
592 empty_network_delegate_,
593 GURL("http://not_blah/redirect"));
594 EXPECT_TRUE(job_.get());
595 EXPECT_TRUE(job_->is_delivering_appcache_response());
597 AppCacheURLRequestJob* fallback_job;
598 fallback_job = handler_->MaybeLoadFallbackForResponse(
599 request_.get(), empty_network_delegate_);
600 EXPECT_FALSE(fallback_job);
602 TestFinished();
605 // SubResource_NoRedirectFallback -----------------------------
607 void SubResource_NoRedirectFallback() {
608 // Redirects to resources in the same-origin are not subject to
609 // fallback namespaces.
610 host_->AssociateCompleteCache(MakeNewCache());
612 mock_storage()->SimulateFindSubResource(
613 AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
615 request_.reset(new MockURLRequest(
616 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
617 handler_.reset(host_->CreateRequestHandler(request_.get(),
618 ResourceType::SUB_RESOURCE));
619 EXPECT_TRUE(handler_.get());
620 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
621 EXPECT_FALSE(job_.get());
623 AppCacheURLRequestJob* fallback_job;
624 fallback_job = handler_->MaybeLoadFallbackForRedirect(
625 request_.get(), empty_network_delegate_, GURL("http://blah/redirect"));
626 EXPECT_FALSE(fallback_job);
628 request_->SimulateResponseCode(200);
629 fallback_job = handler_->MaybeLoadFallbackForResponse(
630 request_.get(), empty_network_delegate_);
631 EXPECT_FALSE(fallback_job);
633 TestFinished();
636 // SubResource_Network -----------------------------
638 void SubResource_Network() {
639 // A sub-resource load where the resource is in a network namespace,
640 // should result in the system using a 'real' job to do the network
641 // retrieval.
642 host_->AssociateCompleteCache(MakeNewCache());
644 mock_storage()->SimulateFindSubResource(
645 AppCacheEntry(), AppCacheEntry(), true);
647 request_.reset(new MockURLRequest(
648 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
649 handler_.reset(host_->CreateRequestHandler(request_.get(),
650 ResourceType::SUB_RESOURCE));
651 EXPECT_TRUE(handler_.get());
652 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
653 EXPECT_FALSE(job_.get());
655 AppCacheURLRequestJob* fallback_job;
656 fallback_job = handler_->MaybeLoadFallbackForRedirect(
657 request_.get(), empty_network_delegate_, GURL("http://blah/redirect"));
658 EXPECT_FALSE(fallback_job);
659 fallback_job = handler_->MaybeLoadFallbackForResponse(
660 request_.get(), empty_network_delegate_);
661 EXPECT_FALSE(fallback_job);
663 TestFinished();
666 // DestroyedHost -----------------------------
668 void DestroyedHost() {
669 host_->AssociateCompleteCache(MakeNewCache());
671 mock_storage()->SimulateFindSubResource(
672 AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
674 request_.reset(new MockURLRequest(
675 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
676 handler_.reset(host_->CreateRequestHandler(request_.get(),
677 ResourceType::SUB_RESOURCE));
678 EXPECT_TRUE(handler_.get());
680 backend_impl_->UnregisterHost(1);
681 host_ = NULL;
683 EXPECT_FALSE(handler_->MaybeLoadResource(
684 request_.get(), empty_network_delegate_));
685 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
686 request_.get(), empty_network_delegate_, GURL("http://blah/redirect")));
687 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
688 request_.get(), empty_network_delegate_));
690 TestFinished();
693 // DestroyedHostWithWaitingJob -----------------------------
695 void DestroyedHostWithWaitingJob() {
696 // Precondition, the host is waiting on cache selection.
697 host_->pending_selected_cache_id_ = 1;
699 request_.reset(new MockURLRequest(
700 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
701 handler_.reset(host_->CreateRequestHandler(request_.get(),
702 ResourceType::SUB_RESOURCE));
703 EXPECT_TRUE(handler_.get());
705 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
706 EXPECT_TRUE(job_.get());
707 EXPECT_TRUE(job_->is_waiting());
709 backend_impl_->UnregisterHost(1);
710 host_ = NULL;
711 EXPECT_TRUE(job_->has_been_killed());
713 EXPECT_FALSE(handler_->MaybeLoadResource(
714 request_.get(), empty_network_delegate_));
715 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
716 request_.get(), empty_network_delegate_, GURL("http://blah/redirect")));
717 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
718 request_.get(), empty_network_delegate_));
720 TestFinished();
723 // UnsupportedScheme -----------------------------
725 void UnsupportedScheme() {
726 // Precondition, the host is waiting on cache selection.
727 host_->pending_selected_cache_id_ = 1;
729 request_.reset(new MockURLRequest(
730 GURL("ftp://blah/"), &empty_context_, empty_network_delegate_));
731 handler_.reset(host_->CreateRequestHandler(request_.get(),
732 ResourceType::SUB_RESOURCE));
733 EXPECT_TRUE(handler_.get()); // we could redirect to http (conceivably)
735 EXPECT_FALSE(handler_->MaybeLoadResource(
736 request_.get(), empty_network_delegate_));
737 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
738 request_.get(), empty_network_delegate_, GURL("ftp://blah/redirect")));
739 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
740 request_.get(), empty_network_delegate_));
742 TestFinished();
745 // CanceledRequest -----------------------------
747 void CanceledRequest() {
748 request_.reset(new MockURLRequest(
749 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
750 handler_.reset(host_->CreateRequestHandler(request_.get(),
751 ResourceType::MAIN_FRAME));
752 EXPECT_TRUE(handler_.get());
754 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
755 EXPECT_TRUE(job_.get());
756 EXPECT_TRUE(job_->is_waiting());
757 EXPECT_FALSE(job_->has_been_started());
759 mock_factory_job_ = job_.get();
760 request_->Start();
761 EXPECT_TRUE(job_->has_been_started());
763 request_->Cancel();
764 EXPECT_TRUE(job_->has_been_killed());
766 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
767 request_.get(), empty_network_delegate_));
769 TestFinished();
772 // WorkerRequest -----------------------------
774 void WorkerRequest() {
775 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
776 ResourceType::MAIN_FRAME));
777 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
778 ResourceType::SUB_FRAME));
779 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
780 ResourceType::SHARED_WORKER));
781 EXPECT_FALSE(AppCacheRequestHandler::IsMainResourceType(
782 ResourceType::WORKER));
784 request_.reset(new MockURLRequest(
785 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
787 const int kParentHostId = host_->host_id();
788 const int kWorkerHostId = 2;
789 const int kAbandonedWorkerHostId = 3;
790 const int kNonExsitingHostId = 700;
792 backend_impl_->RegisterHost(kWorkerHostId);
793 AppCacheHost* worker_host = backend_impl_->GetHost(kWorkerHostId);
794 worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
795 handler_.reset(worker_host->CreateRequestHandler(
796 request_.get(), ResourceType::SHARED_WORKER));
797 EXPECT_TRUE(handler_.get());
798 // Verify that the handler is associated with the parent host.
799 EXPECT_EQ(host_, handler_->host_);
801 // Create a new worker host, but associate it with a parent host that
802 // does not exists to simulate the host having been torn down.
803 backend_impl_->UnregisterHost(kWorkerHostId);
804 backend_impl_->RegisterHost(kAbandonedWorkerHostId);
805 worker_host = backend_impl_->GetHost(kAbandonedWorkerHostId);
806 EXPECT_EQ(NULL, backend_impl_->GetHost(kNonExsitingHostId));
807 worker_host->SelectCacheForWorker(kNonExsitingHostId, kMockProcessId);
808 handler_.reset(worker_host->CreateRequestHandler(
809 request_.get(), ResourceType::SHARED_WORKER));
810 EXPECT_FALSE(handler_.get());
812 TestFinished();
815 // MainResource_Blocked --------------------------------------------------
817 void MainResource_Blocked() {
818 PushNextTask(
819 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
820 base::Unretained(this)));
822 request_.reset(new MockURLRequest(
823 GURL("http://blah/"), &empty_context_, empty_network_delegate_));
824 handler_.reset(host_->CreateRequestHandler(request_.get(),
825 ResourceType::MAIN_FRAME));
826 EXPECT_TRUE(handler_.get());
828 mock_policy_->can_load_return_value_ = false;
829 mock_storage()->SimulateFindMainResource(
830 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
831 GURL(), AppCacheEntry(),
832 1, 2, GURL("http://blah/manifest/"));
834 job_ = handler_->MaybeLoadResource(request_.get(), empty_network_delegate_);
835 EXPECT_TRUE(job_.get());
836 EXPECT_TRUE(job_->is_waiting());
838 // We have to wait for completion of storage->FindResponseForMainRequest.
839 ScheduleNextTask();
842 void Verify_MainResource_Blocked() {
843 EXPECT_FALSE(job_->is_waiting());
844 EXPECT_FALSE(job_->is_delivering_appcache_response());
846 EXPECT_EQ(0, handler_->found_cache_id_);
847 EXPECT_EQ(0, handler_->found_group_id_);
848 EXPECT_TRUE(handler_->found_manifest_url_.is_empty());
849 EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
850 EXPECT_TRUE(host_->main_resource_blocked_);
851 EXPECT_TRUE(host_->blocked_manifest_url_ == GURL("http://blah/manifest/"));
853 TestFinished();
856 // Test case helpers --------------------------------------------------
858 AppCache* MakeNewCache() {
859 AppCache* cache = new AppCache(
860 mock_storage(), mock_storage()->NewCacheId());
861 cache->set_complete(true);
862 AppCacheGroup* group = new AppCacheGroup(
863 mock_storage(), GURL("http://blah/manifest"),
864 mock_storage()->NewGroupId());
865 group->AddCache(cache);
866 return cache;
869 MockAppCacheStorage* mock_storage() {
870 return reinterpret_cast<MockAppCacheStorage*>(mock_service_->storage());
873 // Data members --------------------------------------------------
875 scoped_ptr<base::WaitableEvent> test_finished_event_;
876 std::stack<base::Closure> task_stack_;
877 scoped_ptr<MockAppCacheService> mock_service_;
878 scoped_ptr<AppCacheBackendImpl> backend_impl_;
879 scoped_ptr<MockFrontend> mock_frontend_;
880 scoped_ptr<MockAppCachePolicy> mock_policy_;
881 AppCacheHost* host_;
882 net::URLRequestContext empty_context_;
883 net::NetworkDelegate* empty_network_delegate_;
884 scoped_ptr<MockURLRequest> request_;
885 scoped_ptr<AppCacheRequestHandler> handler_;
886 scoped_refptr<AppCacheURLRequestJob> job_;
887 net::URLRequest::ProtocolFactory* orig_http_factory_;
889 static scoped_ptr<base::Thread> io_thread_;
890 static net::URLRequestJob* mock_factory_job_;
893 // static
894 scoped_ptr<base::Thread> AppCacheRequestHandlerTest::io_thread_;
895 net::URLRequestJob* AppCacheRequestHandlerTest::mock_factory_job_ = NULL;
897 TEST_F(AppCacheRequestHandlerTest, MainResource_Miss) {
898 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Miss);
901 TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) {
902 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit);
905 TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) {
906 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback);
909 TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
910 RunTestOnIOThread(
911 &AppCacheRequestHandlerTest::MainResource_FallbackOverride);
914 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
915 RunTestOnIOThread(
916 &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected);
919 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
920 RunTestOnIOThread(
921 &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected);
924 TEST_F(AppCacheRequestHandlerTest,
925 SubResource_Miss_WithWaitForCacheSelection) {
926 RunTestOnIOThread(
927 &AppCacheRequestHandlerTest::SubResource_Miss_WithWaitForCacheSelection);
930 TEST_F(AppCacheRequestHandlerTest, SubResource_Hit) {
931 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Hit);
934 TEST_F(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
935 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_RedirectFallback);
938 TEST_F(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
939 RunTestOnIOThread(
940 &AppCacheRequestHandlerTest::SubResource_NoRedirectFallback);
943 TEST_F(AppCacheRequestHandlerTest, SubResource_Network) {
944 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Network);
947 TEST_F(AppCacheRequestHandlerTest, DestroyedHost) {
948 RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHost);
951 TEST_F(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
952 RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHostWithWaitingJob);
955 TEST_F(AppCacheRequestHandlerTest, UnsupportedScheme) {
956 RunTestOnIOThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
959 TEST_F(AppCacheRequestHandlerTest, CanceledRequest) {
960 RunTestOnIOThread(&AppCacheRequestHandlerTest::CanceledRequest);
963 TEST_F(AppCacheRequestHandlerTest, WorkerRequest) {
964 RunTestOnIOThread(&AppCacheRequestHandlerTest::WorkerRequest);
967 TEST_F(AppCacheRequestHandlerTest, MainResource_Blocked) {
968 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Blocked);
971 } // namespace appcache