Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_url_request_job.cc
blob46439b6982eab0f7c9566b06a8af82fbeda22ca9
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.
5 #include "content/browser/service_worker/service_worker_url_request_job.h"
7 #include "base/bind.h"
8 #include "base/strings/stringprintf.h"
9 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
10 #include "content/browser/service_worker/service_worker_provider_host.h"
11 #include "net/http/http_request_headers.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/http/http_response_info.h"
14 #include "net/http/http_util.h"
16 namespace content {
18 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
19 net::URLRequest* request,
20 net::NetworkDelegate* network_delegate,
21 base::WeakPtr<ServiceWorkerProviderHost> provider_host)
22 : net::URLRequestJob(request, network_delegate),
23 provider_host_(provider_host),
24 response_type_(NOT_DETERMINED),
25 is_started_(false),
26 weak_factory_(this) {
29 void ServiceWorkerURLRequestJob::FallbackToNetwork() {
30 DCHECK_EQ(NOT_DETERMINED, response_type_);
31 response_type_ = FALLBACK_TO_NETWORK;
32 MaybeStartRequest();
35 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() {
36 DCHECK_EQ(NOT_DETERMINED, response_type_);
37 response_type_ = FORWARD_TO_SERVICE_WORKER;
38 MaybeStartRequest();
41 void ServiceWorkerURLRequestJob::Start() {
42 is_started_ = true;
43 MaybeStartRequest();
46 void ServiceWorkerURLRequestJob::Kill() {
47 net::URLRequestJob::Kill();
48 fetch_dispatcher_.reset();
49 weak_factory_.InvalidateWeakPtrs();
52 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const {
53 // TODO(kinuko): refine this for better debug.
54 return net::URLRequestJob::GetLoadState();
57 bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) {
58 if (!http_info())
59 return false;
60 return http_info()->headers->GetCharset(charset);
63 bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const {
64 if (!http_info())
65 return false;
66 return http_info()->headers->GetMimeType(mime_type);
69 void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
70 if (!http_info())
71 return;
72 *info = *http_info();
75 int ServiceWorkerURLRequestJob::GetResponseCode() const {
76 if (!http_info())
77 return -1;
78 return http_info()->headers->response_code();
81 void ServiceWorkerURLRequestJob::SetExtraRequestHeaders(
82 const net::HttpRequestHeaders& headers) {
83 std::string range_header;
84 std::vector<net::HttpByteRange> ranges;
85 if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header) ||
86 !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
87 return;
90 // We don't support multiple range requests in one single URL request.
91 if (ranges.size() == 1U)
92 byte_range_ = ranges[0];
95 bool ServiceWorkerURLRequestJob::ReadRawData(
96 net::IOBuffer* buf, int buf_size, int *bytes_read) {
97 // TODO(kinuko): Implement this.
98 // If the response returned from ServiceWorker had an
99 // identifier to on-disk data (e.g. blob or cache entry) we'll need to
100 // pull the body from disk.
101 NOTIMPLEMENTED();
102 *bytes_read = 0;
103 return true;
106 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const {
107 if (!http_response_info_)
108 return NULL;
109 if (range_response_info_)
110 return range_response_info_.get();
111 return http_response_info_.get();
114 ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
117 void ServiceWorkerURLRequestJob::MaybeStartRequest() {
118 if (is_started_ && response_type_ != NOT_DETERMINED) {
119 // Start asynchronously.
120 base::MessageLoop::current()->PostTask(
121 FROM_HERE,
122 base::Bind(&ServiceWorkerURLRequestJob::StartRequest,
123 weak_factory_.GetWeakPtr()));
127 void ServiceWorkerURLRequestJob::StartRequest() {
128 switch (response_type_) {
129 case NOT_DETERMINED:
130 NOTREACHED();
131 return;
133 case FALLBACK_TO_NETWORK:
134 // Restart the request to create a new job. Our request handler will
135 // return NULL, and the default job (which will hit network) should be
136 // created.
137 NotifyRestartRequired();
138 return;
140 case FORWARD_TO_SERVICE_WORKER:
141 DCHECK(provider_host_ && provider_host_->active_version());
142 DCHECK(!fetch_dispatcher_);
144 // Send a fetch event to the ServiceWorker associated to the
145 // provider_host.
146 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
147 request(), provider_host_->active_version(),
148 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
149 weak_factory_.GetWeakPtr())));
150 fetch_dispatcher_->Run();
151 return;
154 NOTREACHED();
157 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
158 ServiceWorkerStatusCode status,
159 ServiceWorkerFetchEventResult fetch_result,
160 const ServiceWorkerResponse& response) {
161 fetch_dispatcher_.reset();
163 // Check if we're not orphaned.
164 if (!request())
165 return;
167 if (status != SERVICE_WORKER_OK) {
168 // Dispatching event has been failed, falling back to the network.
169 // (Tentative behavior described on github)
170 // TODO(kinuko): consider returning error if we've come here because
171 // unexpected worker termination etc (so that we could fix bugs).
172 // TODO(kinuko): Would be nice to log the error case.
173 response_type_ = FALLBACK_TO_NETWORK;
174 NotifyRestartRequired();
177 if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) {
178 // Change the response type and restart the request to fallback to
179 // the network.
180 response_type_ = FALLBACK_TO_NETWORK;
181 NotifyRestartRequired();
182 return;
185 // We should have response now.
186 DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
188 CreateResponseHeader(response);
189 NotifyHeadersComplete();
192 void ServiceWorkerURLRequestJob::CreateResponseHeader(
193 const ServiceWorkerResponse& response) {
194 // TODO(kinuko): If the response has an identifier to on-disk cache entry,
195 // pull response header from the disk.
196 std::string status_line(base::StringPrintf("HTTP/1.1 %d %s",
197 response.status_code,
198 response.status_text.c_str()));
199 status_line.push_back('\0');
200 scoped_refptr<net::HttpResponseHeaders> headers(
201 new net::HttpResponseHeaders(status_line));
202 for (std::map<std::string, std::string>::const_iterator it =
203 response.headers.begin();
204 it != response.headers.end(); ++it) {
205 std::string header;
206 header.reserve(it->first.size() + 2 + it->second.size());
207 header.append(it->first);
208 header.append(": ");
209 header.append(it->second);
210 headers->AddHeader(header);
213 http_response_info_.reset(new net::HttpResponseInfo());
214 http_response_info_->headers = headers;
217 } // namespace content