1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_request_handler.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_context_wrapper.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_url_request_job.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_utils.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/common/resource_request_body.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/common/service_worker/service_worker_types.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/net_util.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_request.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/url_request/url_request_interceptor.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_storage_context.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int kUserDataKey;  // Key value is not important.
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ServiceWorkerRequestInterceptor
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : public net::URLRequestInterceptor {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ServiceWorkerRequestInterceptor() {}
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~ServiceWorkerRequestInterceptor() {}
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::URLRequest* request,
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerRequestHandler* handler =
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ServiceWorkerRequestHandler::GetHandler(request);
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!handler)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return NULL;
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return handler->MaybeCreateJob(request, network_delegate);
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This is work around to avoid hijacking CORS preflight.
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(horo): Remove this check when we implement "HTTP fetch" correctly.
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// http://fetch.spec.whatwg.org/#concept-http-fetch
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsMethodSupportedForServiceWroker(const std::string& method) {
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return method != "OPTIONS";
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerRequestHandler::InitializeHandler(
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequest* request,
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerContextWrapper* context_wrapper,
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    storage::BlobStorageContext* blob_storage_context,
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int process_id,
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int provider_id,
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool skip_service_worker,
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ResourceType resource_type,
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_refptr<ResourceRequestBody> body) {
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!request->url().SchemeIsHTTPOrHTTPS() ||
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !IsMethodSupportedForServiceWroker(request->method())) {
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!context_wrapper || !context_wrapper->context() ||
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      provider_id == kInvalidServiceWorkerProviderId) {
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ServiceWorkerProviderHost* provider_host =
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context_wrapper->context()->GetProviderHost(process_id, provider_id);
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!provider_host || !provider_host->IsContextAlive())
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (skip_service_worker) {
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (ServiceWorkerUtils::IsMainResourceType(resource_type))
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      provider_host->SetDocumentUrl(net::SimplifyUrlForRequest(request->url()));
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<ServiceWorkerRequestHandler> handler(
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      provider_host->CreateRequestHandler(
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          resource_type, blob_storage_context->AsWeakPtr(), body));
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!handler)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  request->SetUserData(&kUserDataKey, handler.release());
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler(
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequest* request) {
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return reinterpret_cast<ServiceWorkerRequestHandler*>(
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      request->GetUserData(&kUserDataKey));
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<net::URLRequestInterceptor>
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerRequestHandler::CreateInterceptor() {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return scoped_ptr<net::URLRequestInterceptor>(
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new ServiceWorkerRequestInterceptor);
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerRequestHandler::ServiceWorkerRequestHandler(
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WeakPtr<ServiceWorkerContextCore> context,
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ResourceType resource_type)
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : context_(context),
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      provider_host_(provider_host),
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      blob_storage_context_(blob_storage_context),
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      resource_type_(resource_type) {
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
122