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)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <map>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <vector>
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/guid.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/time.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/common/resource_request_body.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/common/service_worker/service_worker_types.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/blob_handle.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/public/browser/resource_request_info.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/net_errors.h"
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_request_headers.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_response_headers.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_response_info.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/http/http_util.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_data_handle.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_storage_context.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_url_request_job_factory.h"
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/page_transition_types.h"
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequest* request,
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::NetworkDelegate* network_delegate,
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::WeakPtr<ServiceWorkerProviderHost> provider_host,
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_refptr<ResourceRequestBody> body)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : net::URLRequestJob(request, network_delegate),
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      provider_host_(provider_host),
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      response_type_(NOT_DETERMINED),
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      is_started_(false),
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      blob_storage_context_(blob_storage_context),
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      body_(body),
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      weak_factory_(this) {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::FallbackToNetwork() {
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(NOT_DETERMINED, response_type_);
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_type_ = FALLBACK_TO_NETWORK;
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::ForwardToServiceWorker() {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(NOT_DETERMINED, response_type_);
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  response_type_ = FORWARD_TO_SERVICE_WORKER;
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::Start() {
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  is_started_ = true;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MaybeStartRequest();
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::Kill() {
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  net::URLRequestJob::Kill();
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fetch_dispatcher_.reset();
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  blob_request_.reset();
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const {
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(kinuko): refine this for better debug.
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return net::URLRequestJob::GetLoadState();
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) {
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->GetCharset(charset);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const {
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->GetMimeType(mime_type);
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *info = *http_info();
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info->response_time = response_time_;
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerURLRequestJob::GetLoadTimingInfo(
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::LoadTimingInfo* load_timing_info) const {
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *load_timing_info = load_timing_info_;
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ServiceWorkerURLRequestJob::GetResponseCode() const {
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_info())
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return -1;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_info()->headers->response_code();
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::SetExtraRequestHeaders(
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string range_header;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<net::HttpByteRange> ranges;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header) ||
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We don't support multiple range requests in one single URL request.
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (ranges.size() == 1U)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    byte_range_ = ranges[0];
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ServiceWorkerURLRequestJob::ReadRawData(
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::IOBuffer* buf, int buf_size, int *bytes_read) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!blob_request_) {
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *bytes_read = 0;
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  blob_request_->Read(buf, buf_size, bytes_read);
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net::URLRequestStatus status = blob_request_->status();
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetStatus(status);
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status.is_io_pending())
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return status.is_success();
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnReceivedRedirect(
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::URLRequest* request,
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const net::RedirectInfo& redirect_info,
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool* defer_redirect) {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnAuthRequired(
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::AuthChallengeInfo* auth_info) {
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnCertificateRequested(
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::SSLCertRequestInfo* cert_request_info) {
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnSSLCertificateError(
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequest* request,
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const net::SSLInfo& ssl_info,
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool fatal) {
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnBeforeNetworkStart(net::URLRequest* request,
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                      bool* defer) {
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnResponseStarted(net::URLRequest* request) {
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(falken): Add Content-Length, Content-Type if they were not provided in
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the ServiceWorkerResponse.
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  response_time_ = base::Time::Now();
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CommitResponseHeader();
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::OnReadCompleted(net::URLRequest* request,
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                 int bytes_read) {
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetStatus(request->status());
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!request->status().is_success()) {
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NotifyDone(request->status());
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NotifyReadComplete(bytes_read);
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (bytes_read == 0)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NotifyDone(request->status());
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const {
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!http_response_info_)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return NULL;
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (range_response_info_)
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return range_response_info_.get();
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return http_response_info_.get();
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerURLRequestJob::GetExtraResponseInfo(
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool* was_fetched_via_service_worker,
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    GURL* original_url_via_service_worker,
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_start_time,
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_ready_time,
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks* fetch_end_time) const {
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (response_type_ != FORWARD_TO_SERVICE_WORKER) {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *was_fetched_via_service_worker = false;
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *original_url_via_service_worker = GURL();
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *was_fetched_via_service_worker = true;
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *original_url_via_service_worker = response_url_;
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *fetch_start_time = fetch_start_time_;
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *fetch_ready_time = fetch_ready_time_;
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *fetch_end_time = fetch_end_time_;
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::MaybeStartRequest() {
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (is_started_ && response_type_ != NOT_DETERMINED) {
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Start asynchronously.
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FROM_HERE,
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(&ServiceWorkerURLRequestJob::StartRequest,
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   weak_factory_.GetWeakPtr()));
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::StartRequest() {
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (response_type_) {
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case NOT_DETERMINED:
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case FALLBACK_TO_NETWORK:
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Restart the request to create a new job. Our request handler will
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // return NULL, and the default job (which will hit network) should be
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // created.
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NotifyRestartRequired();
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case FORWARD_TO_SERVICE_WORKER:
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(provider_host_ && provider_host_->active_version());
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK(!fetch_dispatcher_);
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Send a fetch event to the ServiceWorker associated to the
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // provider_host.
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          CreateFetchRequest(),
24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          provider_host_->active_version(),
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     weak_factory_.GetWeakPtr()),
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     weak_factory_.GetWeakPtr())));
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fetch_start_time_ = base::TimeTicks::Now();
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      load_timing_info_.send_start = fetch_start_time_;
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      fetch_dispatcher_->Run();
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NOTREACHED();
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_ptr<ServiceWorkerFetchRequest>
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ServiceWorkerURLRequestJob::CreateFetchRequest() {
26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string blob_uuid;
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint64 blob_size = 0;
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateRequestBodyBlob(&blob_uuid, &blob_size);
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<ServiceWorkerFetchRequest> request(
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      new ServiceWorkerFetchRequest());
26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->url = request_->url();
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->method = request_->method();
27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const net::HttpRequestHeaders& headers = request_->extra_request_headers();
27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    request->headers[it.name()] = it.value();
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->blob_uuid = blob_uuid;
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->blob_size = blob_size;
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request->referrer = GURL(request_->referrer());
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (info) {
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    request->is_reload = ui::PageTransitionCoreTypeIs(
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD);
28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return request.Pass();
28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                       uint64* blob_size) {
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!body_.get() || !blob_storage_context_)
28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::vector<const ResourceRequestBody::Element*> resolved_elements;
29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < body_->elements()->size(); ++i) {
29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const ResourceRequestBody::Element& element = (*body_->elements())[i];
29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) {
29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      resolved_elements.push_back(&element);
29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      continue;
29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<storage::BlobDataHandle> handle =
29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid());
29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (handle->data()->items().empty())
29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      continue;
30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    for (size_t i = 0; i < handle->data()->items().size(); ++i) {
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const storage::BlobData::Item& item = handle->data()->items().at(i);
30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DCHECK_NE(storage::BlobData::Item::TYPE_BLOB, item.type());
30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      resolved_elements.push_back(&item);
30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::string uuid(base::GenerateGUID());
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uint64 total_size = 0;
30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < resolved_elements.size(); ++i) {
31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const ResourceRequestBody::Element& element = *resolved_elements[i];
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (total_size != kuint64max && element.length() != kuint64max)
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      total_size += element.length();
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      total_size = kuint64max;
31603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    switch (element.type()) {
31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      case ResourceRequestBody::Element::TYPE_BYTES:
31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        blob_data->AppendData(element.bytes(), element.length());
31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        break;
32003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      case ResourceRequestBody::Element::TYPE_FILE:
32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        blob_data->AppendFile(element.path(),
32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              element.offset(),
32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              element.length(),
32403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              element.expected_modification_time());
32503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        break;
32603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      case ResourceRequestBody::Element::TYPE_BLOB:
32703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // Blob elements should be resolved beforehand.
32803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        NOTREACHED();
32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        break;
33003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
33103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        blob_data->AppendFileSystemFile(element.filesystem_url(),
33203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                        element.offset(),
33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                        element.length(),
33403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                        element.expected_modification_time());
33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        break;
33603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      default:
33703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        NOTIMPLEMENTED();
33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
34103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_body_blob_data_handle_ =
34203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      blob_storage_context_->AddFinishedBlob(blob_data.get());
34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *blob_uuid = uuid;
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *blob_size = total_size;
34503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerURLRequestJob::DidPrepareFetchEvent() {
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  fetch_ready_time_ = base::TimeTicks::Now();
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerStatusCode status,
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ServiceWorkerFetchEventResult fetch_result,
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const ServiceWorkerResponse& response) {
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  fetch_dispatcher_.reset();
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Check if we're not orphaned.
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!request())
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (status != SERVICE_WORKER_OK) {
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Dispatching event has been failed, falling back to the network.
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // (Tentative behavior described on github)
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(kinuko): consider returning error if we've come here because
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // unexpected worker termination etc (so that we could fix bugs).
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(kinuko): Would be nice to log the error case.
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    response_type_ = FALLBACK_TO_NETWORK;
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyRestartRequired();
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) {
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Change the response type and restart the request to fallback to
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // the network.
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    response_type_ = FALLBACK_TO_NETWORK;
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyRestartRequired();
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We should have a response now.
382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Treat a response whose status is 0 as a Network Error.
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (response.status_code == 0) {
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyDone(
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  fetch_end_time_ = base::TimeTicks::Now();
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  load_timing_info_.send_end = fetch_end_time_;
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set up a request for reading the blob.
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!response.blob_uuid.empty() && blob_storage_context_) {
39603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<storage::BlobDataHandle> blob_data_handle =
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!blob_data_handle) {
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The renderer gave us a bad blob UUID.
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DeliverErrorResponse();
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return;
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
40303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        blob_data_handle.Pass(), request()->context(), this);
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blob_request_->Start();
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  response_url_ = response.url;
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CreateResponseHeader(
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      response.status_code, response.status_text, response.headers);
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  load_timing_info_.receive_headers_end = base::TimeTicks::Now();
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!blob_request_)
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CommitResponseHeader();
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerURLRequestJob::CreateResponseHeader(
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int status_code,
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& status_text,
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerHeaderMap& headers) {
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(kinuko): If the response has an identifier to on-disk cache entry,
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // pull response header from the disk.
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string status_line(
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::StringPrintf("HTTP/1.1 %d %s", status_code, status_text.c_str()));
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  status_line.push_back('\0');
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  http_response_headers_ = new net::HttpResponseHeaders(status_line);
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (ServiceWorkerHeaderMap::const_iterator it = headers.begin();
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != headers.end();
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    std::string header;
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.reserve(it->first.size() + 2 + it->second.size());
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(it->first);
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(": ");
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header.append(it->second);
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    http_response_headers_->AddHeader(header);
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::CommitResponseHeader() {
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  http_response_info_.reset(new net::HttpResponseInfo());
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  http_response_info_->headers.swap(http_response_headers_);
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NotifyHeadersComplete();
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ServiceWorkerURLRequestJob::DeliverErrorResponse() {
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(falken): Print an error to the console of the ServiceWorker and of
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the requesting page.
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CreateResponseHeader(
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      500, "Service Worker Response Error", ServiceWorkerHeaderMap());
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CommitResponseHeader();
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
453