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: 31 ServiceWorkerRequestInterceptor() {} 32 virtual ~ServiceWorkerRequestInterceptor() {} 33 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 50 bool IsMethodSupportedForServiceWroker(const std::string& method) { 51 return method != "OPTIONS"; 52 } 53 54 } // namespace 55 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 95 ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler( 96 net::URLRequest* request) { 97 return reinterpret_cast<ServiceWorkerRequestHandler*>( 98 request->GetUserData(&kUserDataKey)); 99 } 100 101 scoped_ptr<net::URLRequestInterceptor> 102 ServiceWorkerRequestHandler::CreateInterceptor() { 103 return scoped_ptr<net::URLRequestInterceptor>( 104 new ServiceWorkerRequestInterceptor); 105 } 106 107 ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() { 108 } 109 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