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 "base/run_loop.h"
6 #include "content/browser/fileapi/mock_url_request_delegate.h"
7 #include "content/browser/service_worker/embedded_worker_test_helper.h"
8 #include "content/browser/service_worker/service_worker_context_core.h"
9 #include "content/browser/service_worker/service_worker_context_request_handler.h"
10 #include "content/browser/service_worker/service_worker_provider_host.h"
11 #include "content/browser/service_worker/service_worker_registration.h"
12 #include "content/browser/service_worker/service_worker_utils.h"
13 #include "content/common/resource_request_body.h"
14 #include "content/public/test/mock_resource_context.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "net/base/load_flags.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_job_factory_impl.h"
20 #include "net/url_request/url_request_test_job.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "storage/browser/blob/blob_storage_context.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 int kMockRenderProcessId = 1224;
30 int kMockProviderId = 1;
31 const char kHeaders[] =
33 "Content-Type: text/javascript\0"
34 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
36 const char kScriptCode[] = "// no script code\n";
38 void EmptyCallback() {
41 net::URLRequestJob* CreateNormalURLRequestJob(
42 net::URLRequest* request,
43 net::NetworkDelegate* network_delegate) {
44 return new net::URLRequestTestJob(request,
46 std::string(kHeaders, arraysize(kHeaders)),
51 net::URLRequestJob* CreateInvalidMimeTypeJob(
52 net::URLRequest* request,
53 net::NetworkDelegate* network_delegate) {
54 const char kPlainTextHeaders[] =
56 "Content-Type: text/plain\0"
57 "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
59 return new net::URLRequestTestJob(
62 std::string(kPlainTextHeaders, arraysize(kPlainTextHeaders)),
67 class SSLCertificateErrorJob : public net::URLRequestTestJob {
69 SSLCertificateErrorJob(net::URLRequest* request,
70 net::NetworkDelegate* network_delegate,
71 const std::string& response_headers,
72 const std::string& response_data,
74 : net::URLRequestTestJob(request,
79 weak_factory_(this) {}
80 void Start() override {
81 base::MessageLoop::current()->PostTask(
83 base::Bind(&SSLCertificateErrorJob::NotifyError,
84 weak_factory_.GetWeakPtr()));
88 info.cert_status = net::CERT_STATUS_DATE_INVALID;
89 NotifySSLCertificateError(info, true);
93 ~SSLCertificateErrorJob() override {}
94 base::WeakPtrFactory<SSLCertificateErrorJob> weak_factory_;
97 net::URLRequestJob* CreateSSLCertificateErrorJob(
98 net::URLRequest* request,
99 net::NetworkDelegate* network_delegate) {
100 return new SSLCertificateErrorJob(request,
102 std::string(kHeaders, arraysize(kHeaders)),
107 class CertStatusErrorJob : public net::URLRequestTestJob {
109 CertStatusErrorJob(net::URLRequest* request,
110 net::NetworkDelegate* network_delegate,
111 const std::string& response_headers,
112 const std::string& response_data,
114 : net::URLRequestTestJob(request,
119 void GetResponseInfo(net::HttpResponseInfo* info) override {
120 URLRequestTestJob::GetResponseInfo(info);
121 info->ssl_info.cert_status = net::CERT_STATUS_DATE_INVALID;
125 ~CertStatusErrorJob() override {}
128 net::URLRequestJob* CreateCertStatusErrorJob(
129 net::URLRequest* request,
130 net::NetworkDelegate* network_delegate) {
131 return new CertStatusErrorJob(request,
133 std::string(kHeaders, arraysize(kHeaders)),
138 class MockHttpProtocolHandler
139 : public net::URLRequestJobFactory::ProtocolHandler {
141 typedef base::Callback<
142 net::URLRequestJob*(net::URLRequest*, net::NetworkDelegate*)> JobCallback;
144 MockHttpProtocolHandler(ResourceContext* resource_context)
145 : resource_context_(resource_context) {}
146 ~MockHttpProtocolHandler() override {}
148 net::URLRequestJob* MaybeCreateJob(
149 net::URLRequest* request,
150 net::NetworkDelegate* network_delegate) const override {
151 ServiceWorkerRequestHandler* handler =
152 ServiceWorkerRequestHandler::GetHandler(request);
154 return handler->MaybeCreateJob(
155 request, network_delegate, resource_context_);
157 return create_job_callback_.Run(request, network_delegate);
159 void SetCreateJobCallback(const JobCallback& callback) {
160 create_job_callback_ = callback;
164 ResourceContext* resource_context_;
165 JobCallback create_job_callback_;
169 class ServiceWorkerWriteToCacheJobTest : public testing::Test {
171 ServiceWorkerWriteToCacheJobTest()
172 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
173 mock_protocol_handler_(NULL) {}
174 ~ServiceWorkerWriteToCacheJobTest() override {}
176 void SetUp() override {
177 helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
179 // A new unstored registration/version.
180 scope_ = GURL("https://host/scope/");
181 script_url_ = GURL("https://host/script.js");
183 new ServiceWorkerRegistration(scope_, 1L, context()->AsWeakPtr());
184 version_ = new ServiceWorkerVersion(
185 registration_.get(), script_url_, 1L, context()->AsWeakPtr());
188 scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
189 kMockRenderProcessId, kMockProviderId, context()->AsWeakPtr(), NULL));
190 provider_host_ = host->AsWeakPtr();
191 context()->AddProviderHost(host.Pass());
192 provider_host_->running_hosted_version_ = version_;
194 context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
195 base::RunLoop().RunUntilIdle();
197 url_request_context_.reset(new net::URLRequestContext);
198 mock_protocol_handler_ = new MockHttpProtocolHandler(&resource_context_);
199 url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
200 url_request_job_factory_->SetProtocolHandler("https",
201 mock_protocol_handler_);
202 url_request_context_->set_job_factory(url_request_job_factory_.get());
204 request_ = url_request_context_->CreateRequest(
205 script_url_, net::DEFAULT_PRIORITY, &url_request_delegate_, NULL);
206 ServiceWorkerRequestHandler::InitializeHandler(
209 &blob_storage_context_,
210 kMockRenderProcessId,
213 FETCH_REQUEST_MODE_NO_CORS,
214 FETCH_CREDENTIALS_MODE_OMIT,
215 RESOURCE_TYPE_SERVICE_WORKER,
216 REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
217 REQUEST_CONTEXT_FRAME_TYPE_NONE,
218 scoped_refptr<ResourceRequestBody>());
221 void TearDown() override {
223 url_request_context_.reset();
224 url_request_job_factory_.reset();
225 mock_protocol_handler_ = NULL;
227 registration_ = NULL;
229 // URLRequestJobs may post clean-up tasks on destruction.
230 base::RunLoop().RunUntilIdle();
233 ServiceWorkerContextCore* context() const { return helper_->context(); }
234 ServiceWorkerContextWrapper* context_wrapper() const {
235 return helper_->context_wrapper();
239 TestBrowserThreadBundle browser_thread_bundle_;
240 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
241 scoped_refptr<ServiceWorkerRegistration> registration_;
242 scoped_refptr<ServiceWorkerVersion> version_;
243 base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
244 scoped_ptr<net::URLRequestContext> url_request_context_;
245 scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
246 scoped_ptr<net::URLRequest> request_;
247 MockHttpProtocolHandler* mock_protocol_handler_;
249 storage::BlobStorageContext blob_storage_context_;
250 content::MockResourceContext resource_context_;
252 MockURLRequestDelegate url_request_delegate_;
257 TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
258 mock_protocol_handler_->SetCreateJobCallback(
259 base::Bind(&CreateNormalURLRequestJob));
261 base::RunLoop().RunUntilIdle();
262 EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status());
263 EXPECT_NE(kInvalidServiceWorkerResponseId,
264 version_->script_cache_map()->LookupResourceId(script_url_));
267 TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
268 mock_protocol_handler_->SetCreateJobCallback(
269 base::Bind(&CreateInvalidMimeTypeJob));
271 base::RunLoop().RunUntilIdle();
272 EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
273 EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
274 EXPECT_EQ(kInvalidServiceWorkerResponseId,
275 version_->script_cache_map()->LookupResourceId(script_url_));
278 TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
279 mock_protocol_handler_->SetCreateJobCallback(
280 base::Bind(&CreateSSLCertificateErrorJob));
282 base::RunLoop().RunUntilIdle();
283 EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
284 EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
285 EXPECT_EQ(kInvalidServiceWorkerResponseId,
286 version_->script_cache_map()->LookupResourceId(script_url_));
289 TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
290 mock_protocol_handler_->SetCreateJobCallback(
291 base::Bind(&CreateCertStatusErrorJob));
293 base::RunLoop().RunUntilIdle();
294 EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
295 EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
296 EXPECT_EQ(kInvalidServiceWorkerResponseId,
297 version_->script_cache_map()->LookupResourceId(script_url_));
300 } // namespace content