OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_url_request_job.h" | 5 #include "content/browser/service_worker/service_worker_url_request_job.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/guid.h" | 12 #include "base/guid.h" |
13 #include "base/profiler/scoped_tracker.h" | 13 #include "base/profiler/scoped_tracker.h" |
14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "content/browser/resource_context_impl.h" | |
16 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h" | 17 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h" |
17 #include "content/browser/service_worker/service_worker_provider_host.h" | 18 #include "content/browser/service_worker/service_worker_provider_host.h" |
19 #include "content/browser/streams/stream.h" | |
20 #include "content/browser/streams/stream_context.h" | |
21 #include "content/browser/streams/stream_registry.h" | |
18 #include "content/common/resource_request_body.h" | 22 #include "content/common/resource_request_body.h" |
19 #include "content/common/service_worker/service_worker_types.h" | 23 #include "content/common/service_worker/service_worker_types.h" |
20 #include "content/public/browser/blob_handle.h" | 24 #include "content/public/browser/blob_handle.h" |
21 #include "content/public/browser/resource_request_info.h" | 25 #include "content/public/browser/resource_request_info.h" |
22 #include "content/public/browser/service_worker_context.h" | 26 #include "content/public/browser/service_worker_context.h" |
23 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
24 #include "net/http/http_request_headers.h" | 28 #include "net/http/http_request_headers.h" |
25 #include "net/http/http_response_headers.h" | 29 #include "net/http/http_response_headers.h" |
26 #include "net/http/http_response_info.h" | 30 #include "net/http/http_response_info.h" |
27 #include "net/http/http_util.h" | 31 #include "net/http/http_util.h" |
28 #include "storage/browser/blob/blob_data_handle.h" | 32 #include "storage/browser/blob/blob_data_handle.h" |
29 #include "storage/browser/blob/blob_storage_context.h" | 33 #include "storage/browser/blob/blob_storage_context.h" |
30 #include "storage/browser/blob/blob_url_request_job_factory.h" | 34 #include "storage/browser/blob/blob_url_request_job_factory.h" |
31 #include "ui/base/page_transition_types.h" | 35 #include "ui/base/page_transition_types.h" |
32 | 36 |
33 namespace content { | 37 namespace content { |
34 | 38 |
35 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( | 39 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( |
36 net::URLRequest* request, | 40 net::URLRequest* request, |
37 net::NetworkDelegate* network_delegate, | 41 net::NetworkDelegate* network_delegate, |
38 base::WeakPtr<ServiceWorkerProviderHost> provider_host, | 42 base::WeakPtr<ServiceWorkerProviderHost> provider_host, |
39 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, | 43 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, |
44 const ResourceContext* resource_context, | |
40 FetchRequestMode request_mode, | 45 FetchRequestMode request_mode, |
41 FetchCredentialsMode credentials_mode, | 46 FetchCredentialsMode credentials_mode, |
42 RequestContextType request_context_type, | 47 RequestContextType request_context_type, |
43 RequestContextFrameType frame_type, | 48 RequestContextFrameType frame_type, |
44 scoped_refptr<ResourceRequestBody> body) | 49 scoped_refptr<ResourceRequestBody> body) |
45 : net::URLRequestJob(request, network_delegate), | 50 : net::URLRequestJob(request, network_delegate), |
46 provider_host_(provider_host), | 51 provider_host_(provider_host), |
47 response_type_(NOT_DETERMINED), | 52 response_type_(NOT_DETERMINED), |
48 is_started_(false), | 53 is_started_(false), |
49 service_worker_response_type_(blink::WebServiceWorkerResponseTypeDefault), | 54 service_worker_response_type_(blink::WebServiceWorkerResponseTypeDefault), |
50 blob_storage_context_(blob_storage_context), | 55 blob_storage_context_(blob_storage_context), |
56 resource_context_(resource_context), | |
57 stream_pending_buffer_size_(0), | |
51 request_mode_(request_mode), | 58 request_mode_(request_mode), |
52 credentials_mode_(credentials_mode), | 59 credentials_mode_(credentials_mode), |
53 request_context_type_(request_context_type), | 60 request_context_type_(request_context_type), |
54 frame_type_(frame_type), | 61 frame_type_(frame_type), |
55 fall_back_required_(false), | 62 fall_back_required_(false), |
56 body_(body), | 63 body_(body), |
57 weak_factory_(this) { | 64 weak_factory_(this) { |
58 } | 65 } |
59 | 66 |
60 void ServiceWorkerURLRequestJob::FallbackToNetwork() { | 67 void ServiceWorkerURLRequestJob::FallbackToNetwork() { |
61 DCHECK_EQ(NOT_DETERMINED, response_type_); | 68 DCHECK_EQ(NOT_DETERMINED, response_type_); |
62 response_type_ = FALLBACK_TO_NETWORK; | 69 response_type_ = FALLBACK_TO_NETWORK; |
63 MaybeStartRequest(); | 70 MaybeStartRequest(); |
64 } | 71 } |
65 | 72 |
66 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() { | 73 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() { |
67 DCHECK_EQ(NOT_DETERMINED, response_type_); | 74 DCHECK_EQ(NOT_DETERMINED, response_type_); |
68 response_type_ = FORWARD_TO_SERVICE_WORKER; | 75 response_type_ = FORWARD_TO_SERVICE_WORKER; |
69 MaybeStartRequest(); | 76 MaybeStartRequest(); |
70 } | 77 } |
71 | 78 |
72 void ServiceWorkerURLRequestJob::Start() { | 79 void ServiceWorkerURLRequestJob::Start() { |
73 is_started_ = true; | 80 is_started_ = true; |
74 MaybeStartRequest(); | 81 MaybeStartRequest(); |
75 } | 82 } |
76 | 83 |
77 void ServiceWorkerURLRequestJob::Kill() { | 84 void ServiceWorkerURLRequestJob::Kill() { |
78 net::URLRequestJob::Kill(); | 85 net::URLRequestJob::Kill(); |
86 if (stream_.get()) { | |
nhiroki
2014/12/03 08:15:08
FYI: Boolean testing of scoped_refptr has been re-
horo
2014/12/05 05:51:53
Done.
| |
87 stream_->RemoveReadObserver(this); | |
88 stream_->Abort(); | |
89 stream_ = nullptr; | |
90 } | |
91 if (!waiting_stream_url_.is_empty()) { | |
92 StreamRegistry* stream_registry = | |
93 GetStreamContextForResourceContext(resource_context_)->registry(); | |
94 stream_registry->RemoveRegisterObserver(waiting_stream_url_); | |
95 stream_registry->NotifyReaderAbortedBeforeRegistration(waiting_stream_url_); | |
96 } | |
79 fetch_dispatcher_.reset(); | 97 fetch_dispatcher_.reset(); |
80 blob_request_.reset(); | 98 blob_request_.reset(); |
81 weak_factory_.InvalidateWeakPtrs(); | 99 weak_factory_.InvalidateWeakPtrs(); |
82 } | 100 } |
83 | 101 |
84 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { | 102 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { |
85 // TODO(kinuko): refine this for better debug. | 103 // TODO(kinuko): refine this for better debug. |
86 return net::URLRequestJob::GetLoadState(); | 104 return net::URLRequestJob::GetLoadState(); |
87 } | 105 } |
88 | 106 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 return; | 143 return; |
126 } | 144 } |
127 | 145 |
128 // We don't support multiple range requests in one single URL request. | 146 // We don't support multiple range requests in one single URL request. |
129 if (ranges.size() == 1U) | 147 if (ranges.size() == 1U) |
130 byte_range_ = ranges[0]; | 148 byte_range_ = ranges[0]; |
131 } | 149 } |
132 | 150 |
133 bool ServiceWorkerURLRequestJob::ReadRawData( | 151 bool ServiceWorkerURLRequestJob::ReadRawData( |
134 net::IOBuffer* buf, int buf_size, int *bytes_read) { | 152 net::IOBuffer* buf, int buf_size, int *bytes_read) { |
153 DCHECK(buf); | |
154 DCHECK_GE(buf_size, 0); | |
155 DCHECK(bytes_read); | |
tyoshino (SeeGerritForStatus)
2014/12/03 08:13:33
can we assert that waiting_stream_url_ is empty he
horo
2014/12/05 05:51:53
Done.
| |
156 if (stream_.get()) { | |
157 switch (stream_->ReadRawData(buf, buf_size, bytes_read)) { | |
158 case Stream::STREAM_HAS_DATA: | |
159 DCHECK_GT(*bytes_read, 0); | |
nhiroki
2014/12/03 08:15:07
You might want to add "return" here and "DCHECK(!b
horo
2014/12/05 05:51:53
Done.
| |
160 case Stream::STREAM_COMPLETE: | |
161 return true; | |
162 case Stream::STREAM_EMPTY: | |
163 stream_pending_buffer_ = buf; | |
164 stream_pending_buffer_size_ = buf_size; | |
165 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | |
166 return false; | |
167 case Stream::STREAM_ABORTED: | |
168 // Handle this as connection reset. | |
169 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
170 net::ERR_CONNECTION_RESET)); | |
171 return false; | |
172 } | |
173 NOTREACHED(); | |
174 return false; | |
175 } | |
tyoshino (SeeGerritForStatus)
2014/12/03 08:13:33
insert a blank line here
L176-L179 should be grou
horo
2014/12/05 05:51:53
Done.
| |
135 if (!blob_request_) { | 176 if (!blob_request_) { |
136 *bytes_read = 0; | 177 *bytes_read = 0; |
137 return true; | 178 return true; |
138 } | 179 } |
139 | 180 |
140 blob_request_->Read(buf, buf_size, bytes_read); | 181 blob_request_->Read(buf, buf_size, bytes_read); |
141 net::URLRequestStatus status = blob_request_->status(); | 182 net::URLRequestStatus status = blob_request_->status(); |
142 SetStatus(status); | 183 SetStatus(status); |
143 if (status.is_io_pending()) | 184 if (status.is_io_pending()) |
144 return false; | 185 return false; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 SetStatus(request->status()); | 239 SetStatus(request->status()); |
199 if (!request->status().is_success()) { | 240 if (!request->status().is_success()) { |
200 NotifyDone(request->status()); | 241 NotifyDone(request->status()); |
201 return; | 242 return; |
202 } | 243 } |
203 NotifyReadComplete(bytes_read); | 244 NotifyReadComplete(bytes_read); |
204 if (bytes_read == 0) | 245 if (bytes_read == 0) |
205 NotifyDone(request->status()); | 246 NotifyDone(request->status()); |
206 } | 247 } |
207 | 248 |
249 void ServiceWorkerURLRequestJob::OnDataAvailable(Stream* stream) { | |
250 // Clear the IO_PENDING status. | |
251 SetStatus(net::URLRequestStatus()); | |
252 // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() | |
tyoshino (SeeGerritForStatus)
2014/12/03 08:13:33
stream_pending_buffer_
horo
2014/12/05 05:51:53
Done.
| |
253 // operation waiting for IO completion. | |
254 if (!stream_pending_buffer_.get()) | |
255 return; | |
256 | |
257 // stream_pending_buffer_ is set to the IOBuffer instance provided to | |
258 // ReadRawData() by URLRequestJob. | |
259 | |
260 int bytes_read = 0; | |
261 switch (stream_->ReadRawData( | |
262 stream_pending_buffer_.get(), stream_pending_buffer_size_, &bytes_read)) { | |
263 case Stream::STREAM_HAS_DATA: | |
264 DCHECK_GT(bytes_read, 0); | |
265 break; | |
266 case Stream::STREAM_COMPLETE: | |
267 // Calling NotifyReadComplete call with 0 signals completion. | |
268 DCHECK(!bytes_read); | |
269 break; | |
270 case Stream::STREAM_EMPTY: | |
271 NOTREACHED(); | |
272 break; | |
273 case Stream::STREAM_ABORTED: | |
274 // Handle this as connection reset. | |
275 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
276 net::ERR_CONNECTION_RESET)); | |
277 break; | |
278 } | |
279 | |
280 // Clear the buffers before notifying the read is complete, so that it is | |
281 // safe for the observer to read. | |
282 stream_pending_buffer_ = nullptr; | |
283 stream_pending_buffer_size_ = 0; | |
284 NotifyReadComplete(bytes_read); | |
285 } | |
286 | |
287 void ServiceWorkerURLRequestJob::OnStreamRegistered(Stream* stream) { | |
288 StreamContext* stream_context = | |
289 GetStreamContextForResourceContext(resource_context_); | |
290 stream_context->registry()->RemoveRegisterObserver(waiting_stream_url_); | |
291 waiting_stream_url_ = GURL(); | |
292 stream_ = stream; | |
293 stream_->SetReadObserver(this); | |
294 CommitResponseHeader(); | |
295 } | |
296 | |
208 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const { | 297 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const { |
209 if (!http_response_info_) | 298 if (!http_response_info_) |
210 return NULL; | 299 return nullptr; |
211 if (range_response_info_) | 300 if (range_response_info_) |
212 return range_response_info_.get(); | 301 return range_response_info_.get(); |
213 return http_response_info_.get(); | 302 return http_response_info_.get(); |
214 } | 303 } |
215 | 304 |
216 void ServiceWorkerURLRequestJob::GetExtraResponseInfo( | 305 void ServiceWorkerURLRequestJob::GetExtraResponseInfo( |
217 bool* was_fetched_via_service_worker, | 306 bool* was_fetched_via_service_worker, |
218 bool* was_fallback_required_by_service_worker, | 307 bool* was_fallback_required_by_service_worker, |
219 GURL* original_url_via_service_worker, | 308 GURL* original_url_via_service_worker, |
220 blink::WebServiceWorkerResponseType* response_type_via_service_worker, | 309 blink::WebServiceWorkerResponseType* response_type_via_service_worker, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 } | 342 } |
254 | 343 |
255 void ServiceWorkerURLRequestJob::StartRequest() { | 344 void ServiceWorkerURLRequestJob::StartRequest() { |
256 switch (response_type_) { | 345 switch (response_type_) { |
257 case NOT_DETERMINED: | 346 case NOT_DETERMINED: |
258 NOTREACHED(); | 347 NOTREACHED(); |
259 return; | 348 return; |
260 | 349 |
261 case FALLBACK_TO_NETWORK: | 350 case FALLBACK_TO_NETWORK: |
262 // Restart the request to create a new job. Our request handler will | 351 // Restart the request to create a new job. Our request handler will |
263 // return NULL, and the default job (which will hit network) should be | 352 // return nullptr, and the default job (which will hit network) should be |
264 // created. | 353 // created. |
265 NotifyRestartRequired(); | 354 NotifyRestartRequired(); |
266 return; | 355 return; |
267 | 356 |
268 case FORWARD_TO_SERVICE_WORKER: | 357 case FORWARD_TO_SERVICE_WORKER: |
269 DCHECK(provider_host_ && provider_host_->active_version()); | 358 DCHECK(provider_host_ && provider_host_->active_version()); |
270 DCHECK(!fetch_dispatcher_); | 359 DCHECK(!fetch_dispatcher_); |
271 // Send a fetch event to the ServiceWorker associated to the | 360 // Send a fetch event to the ServiceWorker associated to the |
272 // provider_host. | 361 // provider_host. |
273 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | 362 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 // Treat a response whose status is 0 as a Network Error. | 520 // Treat a response whose status is 0 as a Network Error. |
432 if (response.status_code == 0) { | 521 if (response.status_code == 0) { |
433 NotifyDone( | 522 NotifyDone( |
434 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); | 523 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); |
435 return; | 524 return; |
436 } | 525 } |
437 | 526 |
438 fetch_end_time_ = base::TimeTicks::Now(); | 527 fetch_end_time_ = base::TimeTicks::Now(); |
439 load_timing_info_.send_end = fetch_end_time_; | 528 load_timing_info_.send_end = fetch_end_time_; |
440 | 529 |
530 // Set up a request for reading the stream. | |
531 if (response.stream_url.is_valid()) { | |
532 DCHECK(response.blob_uuid.empty()); | |
533 response_url_ = response.url; | |
534 service_worker_response_type_ = response.response_type; | |
535 CreateResponseHeader( | |
536 response.status_code, response.status_text, response.headers); | |
537 load_timing_info_.receive_headers_end = base::TimeTicks::Now(); | |
538 StreamContext* stream_context = | |
539 GetStreamContextForResourceContext(resource_context_); | |
540 stream_ = | |
541 stream_context->registry()->GetStream(response.stream_url); | |
542 if (!stream_.get()) { | |
543 waiting_stream_url_ = response.stream_url; | |
544 // Wait for StreamHostMsg_StartBuilding message from the ServieWorker. | |
545 stream_context->registry()->SetRegisterObserver(waiting_stream_url_, | |
546 this); | |
547 return; | |
548 } | |
549 stream_->SetReadObserver(this); | |
550 CommitResponseHeader(); | |
551 return; | |
552 } | |
441 // Set up a request for reading the blob. | 553 // Set up a request for reading the blob. |
442 if (!response.blob_uuid.empty() && blob_storage_context_) { | 554 if (!response.blob_uuid.empty() && blob_storage_context_) { |
443 scoped_ptr<storage::BlobDataHandle> blob_data_handle = | 555 scoped_ptr<storage::BlobDataHandle> blob_data_handle = |
444 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); | 556 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); |
445 if (!blob_data_handle) { | 557 if (!blob_data_handle) { |
446 // The renderer gave us a bad blob UUID. | 558 // The renderer gave us a bad blob UUID. |
447 DeliverErrorResponse(); | 559 DeliverErrorResponse(); |
448 return; | 560 return; |
449 } | 561 } |
450 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( | 562 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 | 603 |
492 void ServiceWorkerURLRequestJob::DeliverErrorResponse() { | 604 void ServiceWorkerURLRequestJob::DeliverErrorResponse() { |
493 // TODO(falken): Print an error to the console of the ServiceWorker and of | 605 // TODO(falken): Print an error to the console of the ServiceWorker and of |
494 // the requesting page. | 606 // the requesting page. |
495 CreateResponseHeader( | 607 CreateResponseHeader( |
496 500, "Service Worker Response Error", ServiceWorkerHeaderMap()); | 608 500, "Service Worker Response Error", ServiceWorkerHeaderMap()); |
497 CommitResponseHeader(); | 609 CommitResponseHeader(); |
498 } | 610 } |
499 | 611 |
500 } // namespace content | 612 } // namespace content |
OLD | NEW |