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 "content/browser/service_worker/service_worker_request_handler.h"
6
7 #include <string>
8
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/browser/service_worker/service_worker_utils.h"
15 #include "content/common/resource_request_body.h"
16 #include "content/common/service_worker/service_worker_types.h"
17 #include "net/base/net_util.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_interceptor.h"
20 #include "storage/browser/blob/blob_storage_context.h"
21
22 namespace content {
23
24 namespace {
25
26 int kUserDataKey; // Key value is not important.
27
28 class ServiceWorkerRequestInterceptor
29 : public net::URLRequestInterceptor {
30 public:
ServiceWorkerRequestInterceptor()31 ServiceWorkerRequestInterceptor() {}
~ServiceWorkerRequestInterceptor()32 virtual ~ServiceWorkerRequestInterceptor() {}
MaybeInterceptRequest(net::URLRequest * request,net::NetworkDelegate * network_delegate) const33 virtual net::URLRequestJob* MaybeInterceptRequest(
34 net::URLRequest* request,
35 net::NetworkDelegate* network_delegate) const OVERRIDE {
36 ServiceWorkerRequestHandler* handler =
37 ServiceWorkerRequestHandler::GetHandler(request);
38 if (!handler)
39 return NULL;
40 return handler->MaybeCreateJob(request, network_delegate);
41 }
42
43 private:
44 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor);
45 };
46
47 // This is work around to avoid hijacking CORS preflight.
48 // TODO(horo): Remove this check when we implement "HTTP fetch" correctly.
49 // http://fetch.spec.whatwg.org/#concept-http-fetch
IsMethodSupportedForServiceWroker(const std::string & method)50 bool IsMethodSupportedForServiceWroker(const std::string& method) {
51 return method != "OPTIONS";
52 }
53
54 } // namespace
55
InitializeHandler(net::URLRequest * request,ServiceWorkerContextWrapper * context_wrapper,storage::BlobStorageContext * blob_storage_context,int process_id,int provider_id,bool skip_service_worker,ResourceType resource_type,scoped_refptr<ResourceRequestBody> body)56 void ServiceWorkerRequestHandler::InitializeHandler(
57 net::URLRequest* request,
58 ServiceWorkerContextWrapper* context_wrapper,
59 storage::BlobStorageContext* blob_storage_context,
60 int process_id,
61 int provider_id,
62 bool skip_service_worker,
63 ResourceType resource_type,
64 scoped_refptr<ResourceRequestBody> body) {
65 if (!request->url().SchemeIsHTTPOrHTTPS() ||
66 !IsMethodSupportedForServiceWroker(request->method())) {
67 return;
68 }
69
70 if (!context_wrapper || !context_wrapper->context() ||
71 provider_id == kInvalidServiceWorkerProviderId) {
72 return;
73 }
74
75 ServiceWorkerProviderHost* provider_host =
76 context_wrapper->context()->GetProviderHost(process_id, provider_id);
77 if (!provider_host || !provider_host->IsContextAlive())
78 return;
79
80 if (skip_service_worker) {
81 if (ServiceWorkerUtils::IsMainResourceType(resource_type))
82 provider_host->SetDocumentUrl(net::SimplifyUrlForRequest(request->url()));
83 return;
84 }
85
86 scoped_ptr<ServiceWorkerRequestHandler> handler(
87 provider_host->CreateRequestHandler(
88 resource_type, blob_storage_context->AsWeakPtr(), body));
89 if (!handler)
90 return;
91
92 request->SetUserData(&kUserDataKey, handler.release());
93 }
94
GetHandler(net::URLRequest * request)95 ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler(
96 net::URLRequest* request) {
97 return reinterpret_cast<ServiceWorkerRequestHandler*>(
98 request->GetUserData(&kUserDataKey));
99 }
100
101 scoped_ptr<net::URLRequestInterceptor>
CreateInterceptor()102 ServiceWorkerRequestHandler::CreateInterceptor() {
103 return scoped_ptr<net::URLRequestInterceptor>(
104 new ServiceWorkerRequestInterceptor);
105 }
106
~ServiceWorkerRequestHandler()107 ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
108 }
109
ServiceWorkerRequestHandler(base::WeakPtr<ServiceWorkerContextCore> context,base::WeakPtr<ServiceWorkerProviderHost> provider_host,base::WeakPtr<storage::BlobStorageContext> blob_storage_context,ResourceType resource_type)110 ServiceWorkerRequestHandler::ServiceWorkerRequestHandler(
111 base::WeakPtr<ServiceWorkerContextCore> context,
112 base::WeakPtr<ServiceWorkerProviderHost> provider_host,
113 base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
114 ResourceType resource_type)
115 : context_(context),
116 provider_host_(provider_host),
117 blob_storage_context_(blob_storage_context),
118 resource_type_(resource_type) {
119 }
120
121 } // namespace content
122