Don't trigger HW acceleration from Toasts on low-end devices.
[chromium-blink-merge.git] / content / browser / appcache / appcache_request_handler_unittest.cc
blob3dbaf8532e76d8bdf4eee1de11e6b1755168b6bc
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.
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/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "content/browser/appcache/appcache.h"
18 #include "content/browser/appcache/appcache_backend_impl.h"
19 #include "content/browser/appcache/appcache_request_handler.h"
20 #include "content/browser/appcache/appcache_url_request_job.h"
21 #include "content/browser/appcache/mock_appcache_policy.h"
22 #include "content/browser/appcache/mock_appcache_service.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/request_priority.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/url_request/url_request.h"
27 #include "net/url_request/url_request_context.h"
28 #include "net/url_request/url_request_error_job.h"
29 #include "net/url_request/url_request_job_factory.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 namespace content {
34 static const int kMockProcessId = 1;
36 class AppCacheRequestHandlerTest : public testing::Test {
37 public:
38 class MockFrontend : public AppCacheFrontend {
39 public:
40 void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
42 void OnStatusChanged(const std::vector<int>& host_ids,
43 AppCacheStatus status) override {}
45 void OnEventRaised(const std::vector<int>& host_ids,
46 AppCacheEventID event_id) override {}
48 void OnErrorEventRaised(const std::vector<int>& host_ids,
49 const AppCacheErrorDetails& details) override {}
51 void OnProgressEventRaised(const std::vector<int>& host_ids,
52 const GURL& url,
53 int num_total,
54 int num_complete) override {}
56 void OnLogMessage(int host_id,
57 AppCacheLogLevel log_level,
58 const std::string& message) override {}
60 void OnContentBlocked(int host_id, 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 void OnResponseStarted(net::URLRequest* request) override {}
76 void OnReadCompleted(net::URLRequest* request, int bytes_read) override {}
79 class MockURLRequestJob : public net::URLRequestJob {
80 public:
81 MockURLRequestJob(net::URLRequest* request,
82 net::NetworkDelegate* network_delegate,
83 int response_code)
84 : net::URLRequestJob(request, network_delegate),
85 response_code_(response_code),
86 has_response_info_(false) {}
87 MockURLRequestJob(net::URLRequest* request,
88 net::NetworkDelegate* network_delegate,
89 const net::HttpResponseInfo& info)
90 : net::URLRequestJob(request, network_delegate),
91 response_code_(info.headers->response_code()),
92 has_response_info_(true),
93 response_info_(info) {}
95 protected:
96 ~MockURLRequestJob() override {}
97 void Start() override { NotifyHeadersComplete(); }
98 int GetResponseCode() const override { return response_code_; }
99 void GetResponseInfo(net::HttpResponseInfo* info) override {
100 if (!has_response_info_)
101 return;
102 *info = response_info_;
105 private:
106 int response_code_;
107 bool has_response_info_;
108 net::HttpResponseInfo response_info_;
111 class MockURLRequestJobFactory : public net::URLRequestJobFactory {
112 public:
113 MockURLRequestJobFactory() : job_(NULL) {
116 ~MockURLRequestJobFactory() override { DCHECK(!job_); }
118 void SetJob(net::URLRequestJob* job) {
119 job_ = job;
122 net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
123 const std::string& scheme,
124 net::URLRequest* request,
125 net::NetworkDelegate* network_delegate) const override {
126 if (job_) {
127 net::URLRequestJob* temp = job_;
128 job_ = NULL;
129 return temp;
130 } else {
131 // Some of these tests trigger UpdateJobs which start URLRequests.
132 // We short circuit those be returning error jobs.
133 return new net::URLRequestErrorJob(request,
134 network_delegate,
135 net::ERR_INTERNET_DISCONNECTED);
139 net::URLRequestJob* MaybeInterceptRedirect(
140 net::URLRequest* request,
141 net::NetworkDelegate* network_delegate,
142 const GURL& location) const override {
143 return nullptr;
146 net::URLRequestJob* MaybeInterceptResponse(
147 net::URLRequest* request,
148 net::NetworkDelegate* network_delegate) const override {
149 return nullptr;
152 bool IsHandledProtocol(const std::string& scheme) const override {
153 return scheme == "http";
156 bool IsHandledURL(const GURL& url) const override {
157 return url.SchemeIs("http");
160 bool IsSafeRedirectTarget(const GURL& location) const override {
161 return false;
164 private:
165 mutable net::URLRequestJob* job_;
168 static void SetUpTestCase() {
169 io_thread_.reset(new base::Thread("AppCacheRequestHandlerTest Thread"));
170 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
171 io_thread_->StartWithOptions(options);
174 static void TearDownTestCase() {
175 io_thread_.reset(NULL);
178 // Test harness --------------------------------------------------
180 AppCacheRequestHandlerTest() : host_(NULL) {}
182 template <class Method>
183 void RunTestOnIOThread(Method method) {
184 test_finished_event_ .reset(new base::WaitableEvent(false, false));
185 io_thread_->task_runner()->PostTask(
186 FROM_HERE,
187 base::Bind(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
188 base::Unretained(this), method));
189 test_finished_event_->Wait();
192 void SetUpTest() {
193 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
194 mock_service_.reset(new MockAppCacheService);
195 mock_service_->set_request_context(&empty_context_);
196 mock_policy_.reset(new MockAppCachePolicy);
197 mock_service_->set_appcache_policy(mock_policy_.get());
198 mock_frontend_.reset(new MockFrontend);
199 backend_impl_.reset(new AppCacheBackendImpl);
200 backend_impl_->Initialize(mock_service_.get(), mock_frontend_.get(),
201 kMockProcessId);
202 const int kHostId = 1;
203 backend_impl_->RegisterHost(kHostId);
204 host_ = backend_impl_->GetHost(kHostId);
205 job_factory_.reset(new MockURLRequestJobFactory());
206 empty_context_.set_job_factory(job_factory_.get());
209 void TearDownTest() {
210 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
211 job_ = NULL;
212 handler_.reset();
213 request_.reset();
214 backend_impl_.reset();
215 mock_frontend_.reset();
216 mock_service_.reset();
217 mock_policy_.reset();
218 job_factory_.reset();
219 host_ = NULL;
222 void TestFinished() {
223 // We unwind the stack prior to finishing up to let stack
224 // based objects get deleted.
225 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
226 base::ThreadTaskRunnerHandle::Get()->PostTask(
227 FROM_HERE, base::Bind(&AppCacheRequestHandlerTest::TestFinishedUnwound,
228 base::Unretained(this)));
231 void TestFinishedUnwound() {
232 TearDownTest();
233 test_finished_event_->Signal();
236 void PushNextTask(const base::Closure& task) {
237 task_stack_.push(task);
240 void ScheduleNextTask() {
241 DCHECK(base::MessageLoop::current() == io_thread_->message_loop());
242 if (task_stack_.empty()) {
243 TestFinished();
244 return;
246 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task_stack_.top());
247 task_stack_.pop();
250 // MainResource_Miss --------------------------------------------------
252 void MainResource_Miss() {
253 PushNextTask(
254 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
255 base::Unretained(this)));
257 request_ = empty_context_.CreateRequest(
258 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
259 handler_.reset(host_->CreateRequestHandler(request_.get(),
260 RESOURCE_TYPE_MAIN_FRAME,
261 false));
262 EXPECT_TRUE(handler_.get());
264 job_ = handler_->MaybeLoadResource(request_.get(),
265 request_->context()->network_delegate());
266 EXPECT_TRUE(job_.get());
267 EXPECT_TRUE(job_->is_waiting());
269 // We have to wait for completion of storage->FindResponseForMainRequest.
270 ScheduleNextTask();
273 void Verify_MainResource_Miss() {
274 EXPECT_FALSE(job_->is_waiting());
275 EXPECT_TRUE(job_->is_delivering_network_response());
277 int64 cache_id = kAppCacheNoCacheId;
278 GURL manifest_url;
279 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
280 EXPECT_EQ(kAppCacheNoCacheId, cache_id);
281 EXPECT_EQ(GURL(), manifest_url);
282 EXPECT_EQ(0, handler_->found_group_id_);
284 AppCacheURLRequestJob* fallback_job;
285 fallback_job = handler_->MaybeLoadFallbackForRedirect(
286 request_.get(),
287 request_->context()->network_delegate(),
288 GURL("http://blah/redirect"));
289 EXPECT_FALSE(fallback_job);
290 fallback_job = handler_->MaybeLoadFallbackForResponse(
291 request_.get(), request_->context()->network_delegate());
292 EXPECT_FALSE(fallback_job);
294 EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
296 TestFinished();
299 // MainResource_Hit --------------------------------------------------
301 void MainResource_Hit() {
302 PushNextTask(
303 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
304 base::Unretained(this)));
306 request_ = empty_context_.CreateRequest(
307 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
308 handler_.reset(host_->CreateRequestHandler(request_.get(),
309 RESOURCE_TYPE_MAIN_FRAME,
310 false));
311 EXPECT_TRUE(handler_.get());
313 mock_storage()->SimulateFindMainResource(
314 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
315 GURL(), AppCacheEntry(),
316 1, 2, GURL("http://blah/manifest/"));
318 job_ = handler_->MaybeLoadResource(request_.get(),
319 request_->context()->network_delegate());
320 EXPECT_TRUE(job_.get());
321 EXPECT_TRUE(job_->is_waiting());
323 // We have to wait for completion of storage->FindResponseForMainRequest.
324 ScheduleNextTask();
327 void Verify_MainResource_Hit() {
328 EXPECT_FALSE(job_->is_waiting());
329 EXPECT_TRUE(job_->is_delivering_appcache_response());
331 int64 cache_id = kAppCacheNoCacheId;
332 GURL manifest_url;
333 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
334 EXPECT_EQ(1, cache_id);
335 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
336 EXPECT_EQ(2, handler_->found_group_id_);
338 AppCacheURLRequestJob* fallback_job;
339 fallback_job = handler_->MaybeLoadFallbackForResponse(
340 request_.get(), request_->context()->network_delegate());
341 EXPECT_FALSE(fallback_job);
343 EXPECT_EQ(GURL("http://blah/manifest/"),
344 host_->preferred_manifest_url());
346 TestFinished();
349 // MainResource_Fallback --------------------------------------------------
351 void MainResource_Fallback() {
352 PushNextTask(
353 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
354 base::Unretained(this)));
356 request_ = empty_context_.CreateRequest(
357 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
358 handler_.reset(host_->CreateRequestHandler(request_.get(),
359 RESOURCE_TYPE_MAIN_FRAME,
360 false));
361 EXPECT_TRUE(handler_.get());
363 mock_storage()->SimulateFindMainResource(
364 AppCacheEntry(),
365 GURL("http://blah/fallbackurl"),
366 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
367 1, 2, GURL("http://blah/manifest/"));
369 job_ = handler_->MaybeLoadResource(request_.get(),
370 request_->context()->network_delegate());
371 EXPECT_TRUE(job_.get());
372 EXPECT_TRUE(job_->is_waiting());
374 // We have to wait for completion of storage->FindResponseForMainRequest.
375 ScheduleNextTask();
378 void SimulateResponseCode(int response_code) {
379 job_factory_->SetJob(
380 new MockURLRequestJob(
381 request_.get(),
382 request_->context()->network_delegate(),
383 response_code));
384 request_->Start();
385 // All our simulation needs to satisfy are the following two DCHECKs
386 DCHECK(request_->status().is_success());
387 DCHECK_EQ(response_code, request_->GetResponseCode());
390 void SimulateResponseInfo(const net::HttpResponseInfo& info) {
391 job_factory_->SetJob(
392 new MockURLRequestJob(
393 request_.get(),
394 request_->context()->network_delegate(), info));
395 request_->Start();
398 void Verify_MainResource_Fallback() {
399 EXPECT_FALSE(job_->is_waiting());
400 EXPECT_TRUE(job_->is_delivering_network_response());
402 // When the request is restarted, the existing job is dropped so a
403 // real network job gets created. We expect NULL here which will cause
404 // the net library to create a real job.
405 job_ = handler_->MaybeLoadResource(request_.get(),
406 request_->context()->network_delegate());
407 EXPECT_FALSE(job_.get());
409 // Simulate an http error of the real network job.
410 SimulateResponseCode(500);
412 job_ = handler_->MaybeLoadFallbackForResponse(
413 request_.get(), request_->context()->network_delegate());
414 EXPECT_TRUE(job_.get());
415 EXPECT_TRUE(job_->is_delivering_appcache_response());
417 int64 cache_id = kAppCacheNoCacheId;
418 GURL manifest_url;
419 handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
420 EXPECT_EQ(1, cache_id);
421 EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
422 EXPECT_TRUE(host_->main_resource_was_namespace_entry_);
423 EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->namespace_entry_url_);
425 EXPECT_EQ(GURL("http://blah/manifest/"),
426 host_->preferred_manifest_url());
428 TestFinished();
431 // MainResource_FallbackOverride --------------------------------------------
433 void MainResource_FallbackOverride() {
434 PushNextTask(base::Bind(
435 &AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
436 base::Unretained(this)));
438 request_ = empty_context_.CreateRequest(
439 GURL("http://blah/fallback-override"), net::DEFAULT_PRIORITY,
440 &delegate_);
441 handler_.reset(host_->CreateRequestHandler(request_.get(),
442 RESOURCE_TYPE_MAIN_FRAME,
443 false));
444 EXPECT_TRUE(handler_.get());
446 mock_storage()->SimulateFindMainResource(
447 AppCacheEntry(),
448 GURL("http://blah/fallbackurl"),
449 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
450 1, 2, GURL("http://blah/manifest/"));
452 job_ = handler_->MaybeLoadResource(request_.get(),
453 request_->context()->network_delegate());
454 EXPECT_TRUE(job_.get());
455 EXPECT_TRUE(job_->is_waiting());
457 // We have to wait for completion of storage->FindResponseForMainRequest.
458 ScheduleNextTask();
461 void Verify_MainResource_FallbackOverride() {
462 EXPECT_FALSE(job_->is_waiting());
463 EXPECT_TRUE(job_->is_delivering_network_response());
465 // When the request is restarted, the existing job is dropped so a
466 // real network job gets created. We expect NULL here which will cause
467 // the net library to create a real job.
468 job_ = handler_->MaybeLoadResource(request_.get(),
469 request_->context()->network_delegate());
470 EXPECT_FALSE(job_.get());
472 // Simulate an http error of the real network job, but with custom
473 // headers that override the fallback behavior.
474 const char kOverrideHeaders[] =
475 "HTTP/1.1 404 BOO HOO\0"
476 "x-chromium-appcache-fallback-override: disallow-fallback\0"
477 "\0";
478 net::HttpResponseInfo info;
479 info.headers = new net::HttpResponseHeaders(
480 std::string(kOverrideHeaders, arraysize(kOverrideHeaders)));
481 SimulateResponseInfo(info);
483 job_ = handler_->MaybeLoadFallbackForResponse(
484 request_.get(), request_->context()->network_delegate());
485 EXPECT_FALSE(job_.get());
487 TestFinished();
490 // SubResource_Miss_WithNoCacheSelected ----------------------------------
492 void SubResource_Miss_WithNoCacheSelected() {
493 request_ = empty_context_.CreateRequest(
494 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
495 handler_.reset(host_->CreateRequestHandler(request_.get(),
496 RESOURCE_TYPE_SUB_RESOURCE,
497 false));
499 // We avoid creating handler when possible, sub-resource requests are not
500 // subject to retrieval from an appcache when there's no associated cache.
501 EXPECT_FALSE(handler_.get());
503 TestFinished();
506 // SubResource_Miss_WithCacheSelected ----------------------------------
508 void SubResource_Miss_WithCacheSelected() {
509 // A sub-resource load where the resource is not in an appcache, or
510 // in a network or fallback namespace, should result in a failed request.
511 host_->AssociateCompleteCache(MakeNewCache());
513 request_ = empty_context_.CreateRequest(
514 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
515 handler_.reset(host_->CreateRequestHandler(request_.get(),
516 RESOURCE_TYPE_SUB_RESOURCE,
517 false));
518 EXPECT_TRUE(handler_.get());
520 job_ = handler_->MaybeLoadResource(request_.get(),
521 request_->context()->network_delegate());
522 EXPECT_TRUE(job_.get());
523 EXPECT_TRUE(job_->is_delivering_error_response());
525 AppCacheURLRequestJob* fallback_job;
526 fallback_job = handler_->MaybeLoadFallbackForRedirect(
527 request_.get(),
528 request_->context()->network_delegate(),
529 GURL("http://blah/redirect"));
530 EXPECT_FALSE(fallback_job);
531 fallback_job = handler_->MaybeLoadFallbackForResponse(
532 request_.get(), request_->context()->network_delegate());
533 EXPECT_FALSE(fallback_job);
535 TestFinished();
538 // SubResource_Miss_WithWaitForCacheSelection -----------------------------
540 void SubResource_Miss_WithWaitForCacheSelection() {
541 // Precondition, the host is waiting on cache selection.
542 scoped_refptr<AppCache> cache(MakeNewCache());
543 host_->pending_selected_cache_id_ = cache->cache_id();
544 host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
546 request_ = empty_context_.CreateRequest(
547 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
548 handler_.reset(host_->CreateRequestHandler(request_.get(),
549 RESOURCE_TYPE_SUB_RESOURCE,
550 false));
551 EXPECT_TRUE(handler_.get());
552 job_ = handler_->MaybeLoadResource(request_.get(),
553 request_->context()->network_delegate());
554 EXPECT_TRUE(job_.get());
555 EXPECT_TRUE(job_->is_waiting());
557 host_->FinishCacheSelection(cache.get(), NULL);
558 EXPECT_FALSE(job_->is_waiting());
559 EXPECT_TRUE(job_->is_delivering_error_response());
561 AppCacheURLRequestJob* fallback_job;
562 fallback_job = handler_->MaybeLoadFallbackForRedirect(
563 request_.get(),
564 request_->context()->network_delegate(),
565 GURL("http://blah/redirect"));
566 EXPECT_FALSE(fallback_job);
567 fallback_job = handler_->MaybeLoadFallbackForResponse(
568 request_.get(), request_->context()->network_delegate());
569 EXPECT_FALSE(fallback_job);
571 TestFinished();
574 // SubResource_Hit -----------------------------
576 void SubResource_Hit() {
577 host_->AssociateCompleteCache(MakeNewCache());
579 mock_storage()->SimulateFindSubResource(
580 AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
582 request_ = empty_context_.CreateRequest(
583 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
584 handler_.reset(host_->CreateRequestHandler(request_.get(),
585 RESOURCE_TYPE_SUB_RESOURCE,
586 false));
587 EXPECT_TRUE(handler_.get());
588 job_ = handler_->MaybeLoadResource(request_.get(),
589 request_->context()->network_delegate());
590 EXPECT_TRUE(job_.get());
591 EXPECT_TRUE(job_->is_delivering_appcache_response());
593 AppCacheURLRequestJob* fallback_job;
594 fallback_job = handler_->MaybeLoadFallbackForRedirect(
595 request_.get(),
596 request_->context()->network_delegate(),
597 GURL("http://blah/redirect"));
598 EXPECT_FALSE(fallback_job);
599 fallback_job = handler_->MaybeLoadFallbackForResponse(
600 request_.get(), request_->context()->network_delegate());
601 EXPECT_FALSE(fallback_job);
603 TestFinished();
606 // SubResource_RedirectFallback -----------------------------
608 void SubResource_RedirectFallback() {
609 // Redirects to resources in the a different origin are subject to
610 // fallback namespaces.
611 host_->AssociateCompleteCache(MakeNewCache());
613 mock_storage()->SimulateFindSubResource(
614 AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
616 request_ = empty_context_.CreateRequest(
617 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
618 handler_.reset(host_->CreateRequestHandler(request_.get(),
619 RESOURCE_TYPE_SUB_RESOURCE,
620 false));
621 EXPECT_TRUE(handler_.get());
622 job_ = handler_->MaybeLoadResource(request_.get(),
623 request_->context()->network_delegate());
624 EXPECT_FALSE(job_.get());
626 job_ = handler_->MaybeLoadFallbackForRedirect(
627 request_.get(),
628 request_->context()->network_delegate(),
629 GURL("http://not_blah/redirect"));
630 EXPECT_TRUE(job_.get());
631 EXPECT_TRUE(job_->is_delivering_appcache_response());
633 AppCacheURLRequestJob* fallback_job;
634 fallback_job = handler_->MaybeLoadFallbackForResponse(
635 request_.get(), request_->context()->network_delegate());
636 EXPECT_FALSE(fallback_job);
638 TestFinished();
641 // SubResource_NoRedirectFallback -----------------------------
643 void SubResource_NoRedirectFallback() {
644 // Redirects to resources in the same-origin are not subject to
645 // fallback namespaces.
646 host_->AssociateCompleteCache(MakeNewCache());
648 mock_storage()->SimulateFindSubResource(
649 AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
651 request_ = empty_context_.CreateRequest(
652 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
653 handler_.reset(host_->CreateRequestHandler(request_.get(),
654 RESOURCE_TYPE_SUB_RESOURCE,
655 false));
656 EXPECT_TRUE(handler_.get());
657 job_ = handler_->MaybeLoadResource(request_.get(),
658 request_->context()->network_delegate());
659 EXPECT_FALSE(job_.get());
661 AppCacheURLRequestJob* fallback_job;
662 fallback_job = handler_->MaybeLoadFallbackForRedirect(
663 request_.get(),
664 request_->context()->network_delegate(),
665 GURL("http://blah/redirect"));
666 EXPECT_FALSE(fallback_job);
668 SimulateResponseCode(200);
669 fallback_job = handler_->MaybeLoadFallbackForResponse(
670 request_.get(), request_->context()->network_delegate());
671 EXPECT_FALSE(fallback_job);
673 TestFinished();
676 // SubResource_Network -----------------------------
678 void SubResource_Network() {
679 // A sub-resource load where the resource is in a network namespace,
680 // should result in the system using a 'real' job to do the network
681 // retrieval.
682 host_->AssociateCompleteCache(MakeNewCache());
684 mock_storage()->SimulateFindSubResource(
685 AppCacheEntry(), AppCacheEntry(), true);
687 request_ = empty_context_.CreateRequest(
688 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
689 handler_.reset(host_->CreateRequestHandler(request_.get(),
690 RESOURCE_TYPE_SUB_RESOURCE,
691 false));
692 EXPECT_TRUE(handler_.get());
693 job_ = handler_->MaybeLoadResource(request_.get(),
694 request_->context()->network_delegate());
695 EXPECT_FALSE(job_.get());
697 AppCacheURLRequestJob* fallback_job;
698 fallback_job = handler_->MaybeLoadFallbackForRedirect(
699 request_.get(),
700 request_->context()->network_delegate(),
701 GURL("http://blah/redirect"));
702 EXPECT_FALSE(fallback_job);
703 fallback_job = handler_->MaybeLoadFallbackForResponse(
704 request_.get(), request_->context()->network_delegate());
705 EXPECT_FALSE(fallback_job);
707 TestFinished();
710 // DestroyedHost -----------------------------
712 void DestroyedHost() {
713 host_->AssociateCompleteCache(MakeNewCache());
715 mock_storage()->SimulateFindSubResource(
716 AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
718 request_ = empty_context_.CreateRequest(
719 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
720 handler_.reset(host_->CreateRequestHandler(request_.get(),
721 RESOURCE_TYPE_SUB_RESOURCE,
722 false));
723 EXPECT_TRUE(handler_.get());
725 backend_impl_->UnregisterHost(1);
726 host_ = NULL;
728 EXPECT_FALSE(handler_->MaybeLoadResource(
729 request_.get(), request_->context()->network_delegate()));
730 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
731 request_.get(),
732 request_->context()->network_delegate(),
733 GURL("http://blah/redirect")));
734 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
735 request_.get(), request_->context()->network_delegate()));
737 TestFinished();
740 // DestroyedHostWithWaitingJob -----------------------------
742 void DestroyedHostWithWaitingJob() {
743 // Precondition, the host is waiting on cache selection.
744 host_->pending_selected_cache_id_ = 1;
746 request_ = empty_context_.CreateRequest(
747 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
748 handler_.reset(host_->CreateRequestHandler(request_.get(),
749 RESOURCE_TYPE_SUB_RESOURCE,
750 false));
751 EXPECT_TRUE(handler_.get());
753 job_ = handler_->MaybeLoadResource(request_.get(),
754 request_->context()->network_delegate());
755 EXPECT_TRUE(job_.get());
756 EXPECT_TRUE(job_->is_waiting());
758 backend_impl_->UnregisterHost(1);
759 host_ = NULL;
760 EXPECT_TRUE(job_->has_been_killed());
762 EXPECT_FALSE(handler_->MaybeLoadResource(
763 request_.get(), request_->context()->network_delegate()));
764 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
765 request_.get(),
766 request_->context()->network_delegate(),
767 GURL("http://blah/redirect")));
768 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
769 request_.get(), request_->context()->network_delegate()));
771 TestFinished();
774 // UnsupportedScheme -----------------------------
776 void UnsupportedScheme() {
777 // Precondition, the host is waiting on cache selection.
778 host_->pending_selected_cache_id_ = 1;
780 request_ = empty_context_.CreateRequest(
781 GURL("ftp://blah/"), net::DEFAULT_PRIORITY, &delegate_);
782 handler_.reset(host_->CreateRequestHandler(request_.get(),
783 RESOURCE_TYPE_SUB_RESOURCE,
784 false));
785 EXPECT_TRUE(handler_.get()); // we could redirect to http (conceivably)
787 EXPECT_FALSE(handler_->MaybeLoadResource(
788 request_.get(), request_->context()->network_delegate()));
789 EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
790 request_.get(),
791 request_->context()->network_delegate(),
792 GURL("ftp://blah/redirect")));
793 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
794 request_.get(), request_->context()->network_delegate()));
796 TestFinished();
799 // CanceledRequest -----------------------------
801 void CanceledRequest() {
802 request_ = empty_context_.CreateRequest(
803 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
804 handler_.reset(host_->CreateRequestHandler(request_.get(),
805 RESOURCE_TYPE_MAIN_FRAME,
806 false));
807 EXPECT_TRUE(handler_.get());
809 job_ = handler_->MaybeLoadResource(request_.get(),
810 request_->context()->network_delegate());
811 EXPECT_TRUE(job_.get());
812 EXPECT_TRUE(job_->is_waiting());
813 EXPECT_FALSE(job_->has_been_started());
815 job_factory_->SetJob(job_.get());
816 request_->Start();
817 EXPECT_TRUE(job_->has_been_started());
819 request_->Cancel();
820 EXPECT_TRUE(job_->has_been_killed());
822 EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(
823 request_.get(), request_->context()->network_delegate()));
825 TestFinished();
828 // WorkerRequest -----------------------------
830 void WorkerRequest() {
831 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
832 RESOURCE_TYPE_MAIN_FRAME));
833 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
834 RESOURCE_TYPE_SUB_FRAME));
835 EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
836 RESOURCE_TYPE_SHARED_WORKER));
837 EXPECT_FALSE(AppCacheRequestHandler::IsMainResourceType(
838 RESOURCE_TYPE_WORKER));
840 request_ = empty_context_.CreateRequest(
841 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
843 const int kParentHostId = host_->host_id();
844 const int kWorkerHostId = 2;
845 const int kAbandonedWorkerHostId = 3;
846 const int kNonExsitingHostId = 700;
848 backend_impl_->RegisterHost(kWorkerHostId);
849 AppCacheHost* worker_host = backend_impl_->GetHost(kWorkerHostId);
850 worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
851 handler_.reset(worker_host->CreateRequestHandler(
852 request_.get(), RESOURCE_TYPE_SHARED_WORKER, false));
853 EXPECT_TRUE(handler_.get());
854 // Verify that the handler is associated with the parent host.
855 EXPECT_EQ(host_, handler_->host_);
857 // Create a new worker host, but associate it with a parent host that
858 // does not exists to simulate the host having been torn down.
859 backend_impl_->UnregisterHost(kWorkerHostId);
860 backend_impl_->RegisterHost(kAbandonedWorkerHostId);
861 worker_host = backend_impl_->GetHost(kAbandonedWorkerHostId);
862 EXPECT_EQ(NULL, backend_impl_->GetHost(kNonExsitingHostId));
863 worker_host->SelectCacheForWorker(kNonExsitingHostId, kMockProcessId);
864 handler_.reset(worker_host->CreateRequestHandler(
865 request_.get(), RESOURCE_TYPE_SHARED_WORKER, false));
866 EXPECT_FALSE(handler_.get());
868 TestFinished();
871 // MainResource_Blocked --------------------------------------------------
873 void MainResource_Blocked() {
874 PushNextTask(
875 base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
876 base::Unretained(this)));
878 request_ = empty_context_.CreateRequest(
879 GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_);
880 handler_.reset(host_->CreateRequestHandler(request_.get(),
881 RESOURCE_TYPE_MAIN_FRAME,
882 false));
883 EXPECT_TRUE(handler_.get());
885 mock_policy_->can_load_return_value_ = false;
886 mock_storage()->SimulateFindMainResource(
887 AppCacheEntry(AppCacheEntry::EXPLICIT, 1),
888 GURL(), AppCacheEntry(),
889 1, 2, GURL("http://blah/manifest/"));
891 job_ = handler_->MaybeLoadResource(request_.get(),
892 request_->context()->network_delegate());
893 EXPECT_TRUE(job_.get());
894 EXPECT_TRUE(job_->is_waiting());
896 // We have to wait for completion of storage->FindResponseForMainRequest.
897 ScheduleNextTask();
900 void Verify_MainResource_Blocked() {
901 EXPECT_FALSE(job_->is_waiting());
902 EXPECT_FALSE(job_->is_delivering_appcache_response());
904 EXPECT_EQ(0, handler_->found_cache_id_);
905 EXPECT_EQ(0, handler_->found_group_id_);
906 EXPECT_TRUE(handler_->found_manifest_url_.is_empty());
907 EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
908 EXPECT_TRUE(host_->main_resource_blocked_);
909 EXPECT_TRUE(host_->blocked_manifest_url_ == GURL("http://blah/manifest/"));
911 TestFinished();
914 // Test case helpers --------------------------------------------------
916 AppCache* MakeNewCache() {
917 AppCache* cache = new AppCache(
918 mock_storage(), mock_storage()->NewCacheId());
919 cache->set_complete(true);
920 AppCacheGroup* group = new AppCacheGroup(
921 mock_storage(), GURL("http://blah/manifest"),
922 mock_storage()->NewGroupId());
923 group->AddCache(cache);
924 return cache;
927 MockAppCacheStorage* mock_storage() {
928 return reinterpret_cast<MockAppCacheStorage*>(mock_service_->storage());
931 // Data members --------------------------------------------------
933 scoped_ptr<base::WaitableEvent> test_finished_event_;
934 std::stack<base::Closure> task_stack_;
935 scoped_ptr<MockAppCacheService> mock_service_;
936 scoped_ptr<AppCacheBackendImpl> backend_impl_;
937 scoped_ptr<MockFrontend> mock_frontend_;
938 scoped_ptr<MockAppCachePolicy> mock_policy_;
939 AppCacheHost* host_;
940 net::URLRequestContext empty_context_;
941 scoped_ptr<MockURLRequestJobFactory> job_factory_;
942 MockURLRequestDelegate delegate_;
943 scoped_ptr<net::URLRequest> request_;
944 scoped_ptr<AppCacheRequestHandler> handler_;
945 scoped_refptr<AppCacheURLRequestJob> job_;
947 static scoped_ptr<base::Thread> io_thread_;
950 // static
951 scoped_ptr<base::Thread> AppCacheRequestHandlerTest::io_thread_;
953 TEST_F(AppCacheRequestHandlerTest, MainResource_Miss) {
954 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Miss);
957 TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) {
958 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Hit);
961 TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) {
962 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Fallback);
965 TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
966 RunTestOnIOThread(
967 &AppCacheRequestHandlerTest::MainResource_FallbackOverride);
970 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
971 RunTestOnIOThread(
972 &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected);
975 TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
976 RunTestOnIOThread(
977 &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected);
980 TEST_F(AppCacheRequestHandlerTest,
981 SubResource_Miss_WithWaitForCacheSelection) {
982 RunTestOnIOThread(
983 &AppCacheRequestHandlerTest::SubResource_Miss_WithWaitForCacheSelection);
986 TEST_F(AppCacheRequestHandlerTest, SubResource_Hit) {
987 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Hit);
990 TEST_F(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
991 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_RedirectFallback);
994 TEST_F(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
995 RunTestOnIOThread(
996 &AppCacheRequestHandlerTest::SubResource_NoRedirectFallback);
999 TEST_F(AppCacheRequestHandlerTest, SubResource_Network) {
1000 RunTestOnIOThread(&AppCacheRequestHandlerTest::SubResource_Network);
1003 TEST_F(AppCacheRequestHandlerTest, DestroyedHost) {
1004 RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHost);
1007 TEST_F(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
1008 RunTestOnIOThread(&AppCacheRequestHandlerTest::DestroyedHostWithWaitingJob);
1011 TEST_F(AppCacheRequestHandlerTest, UnsupportedScheme) {
1012 RunTestOnIOThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
1015 TEST_F(AppCacheRequestHandlerTest, CanceledRequest) {
1016 RunTestOnIOThread(&AppCacheRequestHandlerTest::CanceledRequest);
1019 TEST_F(AppCacheRequestHandlerTest, WorkerRequest) {
1020 RunTestOnIOThread(&AppCacheRequestHandlerTest::WorkerRequest);
1023 TEST_F(AppCacheRequestHandlerTest, MainResource_Blocked) {
1024 RunTestOnIOThread(&AppCacheRequestHandlerTest::MainResource_Blocked);
1027 } // namespace content