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 "content/browser/service_worker/service_worker_request_handler.h"
9 #include "content/browser/service_worker/service_worker_context_core.h"
10 #include "content/browser/service_worker/service_worker_context_wrapper.h"
11 #include "content/browser/service_worker/service_worker_provider_host.h"
12 #include "content/browser/service_worker/service_worker_registration.h"
13 #include "content/browser/service_worker/service_worker_url_request_job.h"
14 #include "content/common/resource_request_body.h"
15 #include "content/common/service_worker/service_worker_types.h"
16 #include "content/common/service_worker/service_worker_utils.h"
17 #include "content/public/browser/resource_context.h"
18 #include "content/public/common/origin_util.h"
19 #include "net/base/net_util.h"
20 #include "net/url_request/url_request.h"
21 #include "net/url_request/url_request_interceptor.h"
22 #include "storage/browser/blob/blob_storage_context.h"
28 int kUserDataKey
; // Key value is not important.
30 class ServiceWorkerRequestInterceptor
31 : public net::URLRequestInterceptor
{
33 explicit ServiceWorkerRequestInterceptor(ResourceContext
* resource_context
)
34 : resource_context_(resource_context
) {}
35 ~ServiceWorkerRequestInterceptor() override
{}
36 net::URLRequestJob
* MaybeInterceptRequest(
37 net::URLRequest
* request
,
38 net::NetworkDelegate
* network_delegate
) const override
{
39 ServiceWorkerRequestHandler
* handler
=
40 ServiceWorkerRequestHandler::GetHandler(request
);
43 return handler
->MaybeCreateJob(
44 request
, network_delegate
, resource_context_
);
48 ResourceContext
* resource_context_
;
49 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor
);
54 void ServiceWorkerRequestHandler::InitializeHandler(
55 net::URLRequest
* request
,
56 ServiceWorkerContextWrapper
* context_wrapper
,
57 storage::BlobStorageContext
* blob_storage_context
,
60 bool skip_service_worker
,
61 FetchRequestMode request_mode
,
62 FetchCredentialsMode credentials_mode
,
63 FetchRedirectMode redirect_mode
,
64 ResourceType resource_type
,
65 RequestContextType request_context_type
,
66 RequestContextFrameType frame_type
,
67 scoped_refptr
<ResourceRequestBody
> body
) {
68 // Create the handler even for insecure HTTP since it's used in the
69 // case of redirect to HTTPS.
70 if (!request
->url().SchemeIsHTTPOrHTTPS() &&
71 !OriginCanAccessServiceWorkers(request
->url())) {
75 if (!context_wrapper
|| !context_wrapper
->context() ||
76 provider_id
== kInvalidServiceWorkerProviderId
) {
80 ServiceWorkerProviderHost
* provider_host
=
81 context_wrapper
->context()->GetProviderHost(process_id
, provider_id
);
82 if (!provider_host
|| !provider_host
->IsContextAlive())
85 if (skip_service_worker
) {
86 if (ServiceWorkerUtils::IsMainResourceType(resource_type
)) {
87 provider_host
->SetDocumentUrl(net::SimplifyUrlForRequest(request
->url()));
88 provider_host
->SetTopmostFrameUrl(request
->first_party_for_cookies());
89 // A page load with skip_service_worker should be triggered by
90 // shift-reload, so retain all live matching registrations.
91 provider_host
->AddAllMatchingRegistrations();
96 scoped_ptr
<ServiceWorkerRequestHandler
> handler(
97 provider_host
->CreateRequestHandler(
98 request_mode
, credentials_mode
, redirect_mode
, resource_type
,
99 request_context_type
, frame_type
, blob_storage_context
->AsWeakPtr(),
104 request
->SetUserData(&kUserDataKey
, handler
.release());
107 ServiceWorkerRequestHandler
* ServiceWorkerRequestHandler::GetHandler(
108 net::URLRequest
* request
) {
109 return static_cast<ServiceWorkerRequestHandler
*>(
110 request
->GetUserData(&kUserDataKey
));
113 scoped_ptr
<net::URLRequestInterceptor
>
114 ServiceWorkerRequestHandler::CreateInterceptor(
115 ResourceContext
* resource_context
) {
116 return scoped_ptr
<net::URLRequestInterceptor
>(
117 new ServiceWorkerRequestInterceptor(resource_context
));
120 bool ServiceWorkerRequestHandler::IsControlledByServiceWorker(
121 net::URLRequest
* request
) {
122 ServiceWorkerRequestHandler
* handler
= GetHandler(request
);
123 if (!handler
|| !handler
->provider_host_
)
125 return handler
->provider_host_
->associated_registration() ||
126 handler
->provider_host_
->running_hosted_version();
129 void ServiceWorkerRequestHandler::PrepareForCrossSiteTransfer(
130 int old_process_id
) {
131 if (!provider_host_
|| !context_
)
133 old_process_id_
= old_process_id
;
134 old_provider_id_
= provider_host_
->provider_id();
135 host_for_cross_site_transfer_
=
136 context_
->TransferProviderHostOut(old_process_id
,
137 provider_host_
->provider_id());
138 DCHECK_EQ(provider_host_
.get(), host_for_cross_site_transfer_
.get());
141 void ServiceWorkerRequestHandler::CompleteCrossSiteTransfer(
142 int new_process_id
, int new_provider_id
) {
143 if (!host_for_cross_site_transfer_
.get() || !context_
)
145 DCHECK_EQ(provider_host_
.get(), host_for_cross_site_transfer_
.get());
146 context_
->TransferProviderHostIn(
149 host_for_cross_site_transfer_
.Pass());
150 DCHECK_EQ(provider_host_
->provider_id(), new_provider_id
);
153 void ServiceWorkerRequestHandler::MaybeCompleteCrossSiteTransferInOldProcess(
154 int old_process_id
) {
155 if (!host_for_cross_site_transfer_
.get() || !context_
||
156 old_process_id_
!= old_process_id
) {
159 CompleteCrossSiteTransfer(old_process_id_
, old_provider_id_
);
162 ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
165 ServiceWorkerRequestHandler::ServiceWorkerRequestHandler(
166 base::WeakPtr
<ServiceWorkerContextCore
> context
,
167 base::WeakPtr
<ServiceWorkerProviderHost
> provider_host
,
168 base::WeakPtr
<storage::BlobStorageContext
> blob_storage_context
,
169 ResourceType resource_type
)
171 provider_host_(provider_host
),
172 blob_storage_context_(blob_storage_context
),
173 resource_type_(resource_type
),
175 old_provider_id_(kInvalidServiceWorkerProviderId
) {
178 } // namespace content