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_url_request_job.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_request_headers.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_response_headers.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_response_info.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_util.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "webkit/browser/blob/blob_data_handle.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "webkit/browser/blob/blob_storage_context.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "webkit/browser/blob/blob_url_request_job_factory.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequest* request,
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : net::URLRequestJob(request, network_delegate),
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      provider_host_(provider_host),
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      response_type_(NOT_DETERMINED),
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      is_started_(false),
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      blob_storage_context_(blob_storage_context),
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      weak_factory_(this) {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::FallbackToNetwork() {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(NOT_DETERMINED, response_type_);
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_type_ = FALLBACK_TO_NETWORK;
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::ForwardToServiceWorker() {
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(NOT_DETERMINED, response_type_);
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_type_ = FORWARD_TO_SERVICE_WORKER;
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::Start() {
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  is_started_ = true;
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::Kill() {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  net::URLRequestJob::Kill();
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fetch_dispatcher_.reset();
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  blob_request_.reset();
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const {
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(kinuko): refine this for better debug.
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return net::URLRequestJob::GetLoadState();
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->GetCharset(charset);
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const {
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->GetMimeType(mime_type);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *info = *http_info();
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ServiceWorkerURLRequestJob::GetResponseCode() const {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return -1;
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->response_code();
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::SetExtraRequestHeaders(
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string range_header;
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<net::HttpByteRange> ranges;
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header) ||
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We don't support multiple range requests in one single URL request.
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (ranges.size() == 1U)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    byte_range_ = ranges[0];
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::ReadRawData(
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::IOBuffer* buf, int buf_size, int *bytes_read) {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!blob_request_) {
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *bytes_read = 0;
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  blob_request_->Read(buf, buf_size, bytes_read);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::URLRequestStatus status = blob_request_->status();
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetStatus(status);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status.is_io_pending())
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return status.is_success();
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnReceivedRedirect(net::URLRequest* request,
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                    const GURL& new_url,
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                    bool* defer_redirect) {
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnAuthRequired(
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::AuthChallengeInfo* auth_info) {
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnCertificateRequested(
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::SSLCertRequestInfo* cert_request_info) {
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnSSLCertificateError(
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const net::SSLInfo& ssl_info,
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool fatal) {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnBeforeNetworkStart(net::URLRequest* request,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                      bool* defer) {
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnResponseStarted(net::URLRequest* request) {
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(falken): Add Content-Length, Content-Type if they were not provided in
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the ServiceWorkerResponse.
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CommitResponseHeader();
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnReadCompleted(net::URLRequest* request,
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 int bytes_read) {
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetStatus(request->status());
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!request->status().is_success()) {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NotifyDone(request->status());
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NotifyReadComplete(bytes_read);
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (bytes_read == 0)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NotifyDone(request->status());
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const {
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_response_info_)
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return NULL;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (range_response_info_)
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return range_response_info_.get();
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_response_info_.get();
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::MaybeStartRequest() {
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (is_started_ && response_type_ != NOT_DETERMINED) {
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Start asynchronously.
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FROM_HERE,
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(&ServiceWorkerURLRequestJob::StartRequest,
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::StartRequest() {
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (response_type_) {
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case NOT_DETERMINED:
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case FALLBACK_TO_NETWORK:
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Restart the request to create a new job. Our request handler will
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // return NULL, and the default job (which will hit network) should be
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // created.
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NotifyRestartRequired();
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case FORWARD_TO_SERVICE_WORKER:
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(provider_host_ && provider_host_->active_version());
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK(!fetch_dispatcher_);
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Send a fetch event to the ServiceWorker associated to the
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // provider_host.
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          request(), provider_host_->active_version(),
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     weak_factory_.GetWeakPtr())));
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      fetch_dispatcher_->Run();
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NOTREACHED();
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerStatusCode status,
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerFetchEventResult fetch_result,
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const ServiceWorkerResponse& response) {
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fetch_dispatcher_.reset();
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Check if we're not orphaned.
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!request())
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (status != SERVICE_WORKER_OK) {
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Dispatching event has been failed, falling back to the network.
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // (Tentative behavior described on github)
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(kinuko): consider returning error if we've come here because
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // unexpected worker termination etc (so that we could fix bugs).
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(kinuko): Would be nice to log the error case.
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    response_type_ = FALLBACK_TO_NETWORK;
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyRestartRequired();
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) {
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Change the response type and restart the request to fallback to
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // the network.
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    response_type_ = FALLBACK_TO_NETWORK;
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyRestartRequired();
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We should have a response now.
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set up a request for reading the blob.
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!response.blob_uuid.empty() && blob_storage_context_) {
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle =
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!blob_data_handle) {
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The renderer gave us a bad blob UUID.
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DeliverErrorResponse();
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return;
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blob_request_ = webkit_blob::BlobProtocolHandler::CreateBlobRequest(
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        blob_data_handle.Pass(), request()->context(), this);
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blob_request_->Start();
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateResponseHeader(
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      response.status_code, response.status_text, response.headers);
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!blob_request_)
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CommitResponseHeader();
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::CreateResponseHeader(
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int status_code,
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& status_text,
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::map<std::string, std::string>& headers) {
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(kinuko): If the response has an identifier to on-disk cache entry,
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // pull response header from the disk.
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string status_line(
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::StringPrintf("HTTP/1.1 %d %s", status_code, status_text.c_str()));
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  status_line.push_back('\0');
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  http_response_headers_ = new net::HttpResponseHeaders(status_line);
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (std::map<std::string, std::string>::const_iterator it = headers.begin();
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != headers.end();
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    std::string header;
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.reserve(it->first.size() + 2 + it->second.size());
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(it->first);
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(": ");
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(it->second);
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    http_response_headers_->AddHeader(header);
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::CommitResponseHeader() {
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  http_response_info_.reset(new net::HttpResponseInfo());
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  http_response_info_->headers.swap(http_response_headers_);
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NotifyHeadersComplete();
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::DeliverErrorResponse() {
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(falken): Print an error to the console of the ServiceWorker and of
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the requesting page.
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateResponseHeader(500,
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       "Service Worker Response Error",
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       std::map<std::string, std::string>());
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CommitResponseHeader();
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
305