Chromium Code Reviews| 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), | |
| 58 stream_total_bytes_read_(0), | |
| 59 stream_max_range_(0), | |
| 51 request_mode_(request_mode), | 60 request_mode_(request_mode), |
| 52 credentials_mode_(credentials_mode), | 61 credentials_mode_(credentials_mode), |
| 53 request_context_type_(request_context_type), | 62 request_context_type_(request_context_type), |
| 54 frame_type_(frame_type), | 63 frame_type_(frame_type), |
| 55 fall_back_required_(false), | 64 fall_back_required_(false), |
| 56 body_(body), | 65 body_(body), |
| 57 weak_factory_(this) { | 66 weak_factory_(this) { |
| 58 } | 67 } |
| 59 | 68 |
| 60 void ServiceWorkerURLRequestJob::FallbackToNetwork() { | 69 void ServiceWorkerURLRequestJob::FallbackToNetwork() { |
| 61 DCHECK_EQ(NOT_DETERMINED, response_type_); | 70 DCHECK_EQ(NOT_DETERMINED, response_type_); |
| 62 response_type_ = FALLBACK_TO_NETWORK; | 71 response_type_ = FALLBACK_TO_NETWORK; |
| 63 MaybeStartRequest(); | 72 MaybeStartRequest(); |
| 64 } | 73 } |
| 65 | 74 |
| 66 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() { | 75 void ServiceWorkerURLRequestJob::ForwardToServiceWorker() { |
| 67 DCHECK_EQ(NOT_DETERMINED, response_type_); | 76 DCHECK_EQ(NOT_DETERMINED, response_type_); |
| 68 response_type_ = FORWARD_TO_SERVICE_WORKER; | 77 response_type_ = FORWARD_TO_SERVICE_WORKER; |
| 69 MaybeStartRequest(); | 78 MaybeStartRequest(); |
| 70 } | 79 } |
| 71 | 80 |
| 72 void ServiceWorkerURLRequestJob::Start() { | 81 void ServiceWorkerURLRequestJob::Start() { |
| 73 is_started_ = true; | 82 is_started_ = true; |
| 74 MaybeStartRequest(); | 83 MaybeStartRequest(); |
| 75 } | 84 } |
| 76 | 85 |
| 77 void ServiceWorkerURLRequestJob::Kill() { | 86 void ServiceWorkerURLRequestJob::Kill() { |
| 78 net::URLRequestJob::Kill(); | 87 net::URLRequestJob::Kill(); |
| 88 if (stream_.get()) { | |
| 89 stream_->RemoveReadObserver(this); | |
| 90 stream_->Abort(); | |
| 91 stream_ = nullptr; | |
| 92 } | |
| 93 if (!waiting_stream_url_.is_empty()) { | |
| 94 StreamRegistry* stream_registry = | |
| 95 GetStreamContextForResourceContext(resource_context_)->registry(); | |
| 96 stream_registry->RemoveRegisterObserver(waiting_stream_url_); | |
| 97 stream_registry->NotifyReaderAbortedBeforeRegistration(waiting_stream_url_); | |
| 98 } | |
| 79 fetch_dispatcher_.reset(); | 99 fetch_dispatcher_.reset(); |
| 80 blob_request_.reset(); | 100 blob_request_.reset(); |
| 81 weak_factory_.InvalidateWeakPtrs(); | 101 weak_factory_.InvalidateWeakPtrs(); |
| 82 } | 102 } |
| 83 | 103 |
| 84 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { | 104 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { |
| 85 // TODO(kinuko): refine this for better debug. | 105 // TODO(kinuko): refine this for better debug. |
| 86 return net::URLRequestJob::GetLoadState(); | 106 return net::URLRequestJob::GetLoadState(); |
| 87 } | 107 } |
| 88 | 108 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { | 144 !net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { |
| 125 return; | 145 return; |
| 126 } | 146 } |
| 127 | 147 |
| 128 // We don't support multiple range requests in one single URL request. | 148 // We don't support multiple range requests in one single URL request. |
| 129 if (ranges.size() == 1U) | 149 if (ranges.size() == 1U) |
| 130 byte_range_ = ranges[0]; | 150 byte_range_ = ranges[0]; |
| 131 } | 151 } |
| 132 | 152 |
| 133 bool ServiceWorkerURLRequestJob::ReadRawData( | 153 bool ServiceWorkerURLRequestJob::ReadRawData( |
| 134 net::IOBuffer* buf, int buf_size, int *bytes_read) { | 154 net::IOBuffer* buf, int buf_size, int *bytes_read) { |
|
nhiroki
2014/11/27 05:03:25
DCHECK_GE(buf_size, 0)?
horo
2014/11/27 06:52:49
Done.
| |
| 155 if (stream_.get()) { | |
| 156 DCHECK(buf); | |
| 157 DCHECK(bytes_read); | |
|
nhiroki
2014/11/27 05:03:25
Can you move these checks into the beginning of th
horo
2014/11/27 06:52:49
Done.
| |
| 158 int to_read = buf_size; | |
| 159 if (stream_max_range_ && to_read) { | |
| 160 if (to_read + stream_total_bytes_read_ > stream_max_range_) | |
| 161 to_read = stream_max_range_ - stream_total_bytes_read_; | |
| 162 | |
| 163 if (to_read <= 0) { | |
|
nhiroki
2014/11/27 05:03:25
"to_read < 0" seems a bug because...
1) |buf_size
horo
2014/11/27 06:52:49
We don't need stream_total_bytes_read_ nor stream_
| |
| 164 *bytes_read = 0; | |
| 165 return true; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 switch (stream_->ReadRawData(buf, to_read, bytes_read)) { | |
| 170 case Stream::STREAM_HAS_DATA: | |
|
nhiroki
2014/11/27 05:03:25
"DCHECK_GT(bytes_read, 0)" like line 276?
horo
2014/11/27 06:52:49
Done.
| |
| 171 case Stream::STREAM_COMPLETE: | |
| 172 stream_total_bytes_read_ += *bytes_read; | |
| 173 return true; | |
| 174 case Stream::STREAM_EMPTY: | |
| 175 stream_pending_buffer_ = buf; | |
| 176 stream_pending_buffer_size_ = to_read; | |
| 177 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | |
| 178 return false; | |
| 179 case Stream::STREAM_ABORTED: | |
| 180 // Handle this as connection reset. | |
| 181 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
| 182 net::ERR_CONNECTION_RESET)); | |
| 183 return false; | |
| 184 } | |
| 185 NOTREACHED(); | |
| 186 return false; | |
| 187 } | |
| 135 if (!blob_request_) { | 188 if (!blob_request_) { |
| 136 *bytes_read = 0; | 189 *bytes_read = 0; |
| 137 return true; | 190 return true; |
| 138 } | 191 } |
| 139 | 192 |
| 140 blob_request_->Read(buf, buf_size, bytes_read); | 193 blob_request_->Read(buf, buf_size, bytes_read); |
| 141 net::URLRequestStatus status = blob_request_->status(); | 194 net::URLRequestStatus status = blob_request_->status(); |
| 142 SetStatus(status); | 195 SetStatus(status); |
| 143 if (status.is_io_pending()) | 196 if (status.is_io_pending()) |
| 144 return false; | 197 return false; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 SetStatus(request->status()); | 251 SetStatus(request->status()); |
| 199 if (!request->status().is_success()) { | 252 if (!request->status().is_success()) { |
| 200 NotifyDone(request->status()); | 253 NotifyDone(request->status()); |
| 201 return; | 254 return; |
| 202 } | 255 } |
| 203 NotifyReadComplete(bytes_read); | 256 NotifyReadComplete(bytes_read); |
| 204 if (bytes_read == 0) | 257 if (bytes_read == 0) |
| 205 NotifyDone(request->status()); | 258 NotifyDone(request->status()); |
| 206 } | 259 } |
| 207 | 260 |
| 261 void ServiceWorkerURLRequestJob::OnDataAvailable(Stream* stream) { | |
| 262 // Clear the IO_PENDING status. | |
| 263 SetStatus(net::URLRequestStatus()); | |
| 264 // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() | |
| 265 // operation waiting for IO completion. | |
| 266 if (!stream_pending_buffer_.get()) | |
| 267 return; | |
| 268 | |
| 269 // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() | |
| 270 // by URLRequestJob. | |
| 271 | |
| 272 int bytes_read; | |
| 273 switch (stream_->ReadRawData( | |
| 274 stream_pending_buffer_.get(), stream_pending_buffer_size_, &bytes_read)) { | |
| 275 case Stream::STREAM_HAS_DATA: | |
| 276 DCHECK_GT(bytes_read, 0); | |
| 277 break; | |
| 278 case Stream::STREAM_COMPLETE: | |
| 279 // Ensure this. Calling NotifyReadComplete call with 0 signals | |
| 280 // completion. | |
| 281 bytes_read = 0; | |
|
nhiroki
2014/11/27 05:03:25
This looks odd... at line 298 |stream_total_bytes_
horo
2014/11/27 06:52:50
I think checking bytes_read == 0 is enough.
| |
| 282 break; | |
| 283 case Stream::STREAM_EMPTY: | |
| 284 NOTREACHED(); | |
| 285 break; | |
| 286 case Stream::STREAM_ABORTED: | |
| 287 // Handle this as connection reset. | |
| 288 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
| 289 net::ERR_CONNECTION_RESET)); | |
| 290 break; | |
| 291 } | |
| 292 | |
| 293 // Clear the buffers before notifying the read is complete, so that it is | |
| 294 // safe for the observer to read. | |
| 295 stream_pending_buffer_ = NULL; | |
|
nhiroki
2014/11/27 05:03:25
nullptr?
horo
2014/11/27 06:52:49
Done.
| |
| 296 stream_pending_buffer_size_ = 0; | |
| 297 | |
| 298 stream_total_bytes_read_ += bytes_read; | |
| 299 NotifyReadComplete(bytes_read); | |
| 300 } | |
| 301 | |
| 302 void ServiceWorkerURLRequestJob::OnStreamRegistered(Stream* stream) { | |
| 303 StreamContext* stream_context = | |
| 304 GetStreamContextForResourceContext(resource_context_); | |
| 305 stream_context->registry()->RemoveRegisterObserver(waiting_stream_url_); | |
| 306 waiting_stream_url_ = GURL(); | |
| 307 stream_ = stream; | |
| 308 stream_->SetReadObserver(this); | |
| 309 CommitResponseHeader(); | |
| 310 } | |
| 311 | |
| 208 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const { | 312 const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const { |
| 209 if (!http_response_info_) | 313 if (!http_response_info_) |
| 210 return NULL; | 314 return NULL; |
| 211 if (range_response_info_) | 315 if (range_response_info_) |
| 212 return range_response_info_.get(); | 316 return range_response_info_.get(); |
| 213 return http_response_info_.get(); | 317 return http_response_info_.get(); |
| 214 } | 318 } |
| 215 | 319 |
| 216 void ServiceWorkerURLRequestJob::GetExtraResponseInfo( | 320 void ServiceWorkerURLRequestJob::GetExtraResponseInfo( |
| 217 bool* was_fetched_via_service_worker, | 321 bool* was_fetched_via_service_worker, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 // Treat a response whose status is 0 as a Network Error. | 535 // Treat a response whose status is 0 as a Network Error. |
| 432 if (response.status_code == 0) { | 536 if (response.status_code == 0) { |
| 433 NotifyDone( | 537 NotifyDone( |
| 434 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); | 538 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); |
| 435 return; | 539 return; |
| 436 } | 540 } |
| 437 | 541 |
| 438 fetch_end_time_ = base::TimeTicks::Now(); | 542 fetch_end_time_ = base::TimeTicks::Now(); |
| 439 load_timing_info_.send_end = fetch_end_time_; | 543 load_timing_info_.send_end = fetch_end_time_; |
| 440 | 544 |
| 545 // Set up a request for reading the stream. | |
| 546 if (response.stream_url.is_valid()) { | |
| 547 DCHECK(response.blob_uuid.empty()); | |
| 548 response_url_ = response.url; | |
| 549 service_worker_response_type_ = response.response_type; | |
| 550 CreateResponseHeader( | |
| 551 response.status_code, response.status_text, response.headers); | |
| 552 load_timing_info_.receive_headers_end = base::TimeTicks::Now(); | |
| 553 StreamContext* stream_context = | |
| 554 GetStreamContextForResourceContext(resource_context_); | |
| 555 stream_ = | |
| 556 stream_context->registry()->GetStream(response.stream_url); | |
| 557 if (!stream_.get()) { | |
| 558 waiting_stream_url_ = response.stream_url; | |
| 559 // Wait for StreamHostMsg_StartBuilding message from the ServieWorker. | |
| 560 stream_context->registry()->SetRegisterObserver(waiting_stream_url_, | |
| 561 this); | |
| 562 return; | |
| 563 } | |
| 564 stream_->SetReadObserver(this); | |
| 565 CommitResponseHeader(); | |
| 566 return; | |
| 567 } | |
| 441 // Set up a request for reading the blob. | 568 // Set up a request for reading the blob. |
| 442 if (!response.blob_uuid.empty() && blob_storage_context_) { | 569 if (!response.blob_uuid.empty() && blob_storage_context_) { |
| 443 scoped_ptr<storage::BlobDataHandle> blob_data_handle = | 570 scoped_ptr<storage::BlobDataHandle> blob_data_handle = |
| 444 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); | 571 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); |
| 445 if (!blob_data_handle) { | 572 if (!blob_data_handle) { |
| 446 // The renderer gave us a bad blob UUID. | 573 // The renderer gave us a bad blob UUID. |
| 447 DeliverErrorResponse(); | 574 DeliverErrorResponse(); |
| 448 return; | 575 return; |
| 449 } | 576 } |
| 450 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( | 577 blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 | 618 |
| 492 void ServiceWorkerURLRequestJob::DeliverErrorResponse() { | 619 void ServiceWorkerURLRequestJob::DeliverErrorResponse() { |
| 493 // TODO(falken): Print an error to the console of the ServiceWorker and of | 620 // TODO(falken): Print an error to the console of the ServiceWorker and of |
| 494 // the requesting page. | 621 // the requesting page. |
| 495 CreateResponseHeader( | 622 CreateResponseHeader( |
| 496 500, "Service Worker Response Error", ServiceWorkerHeaderMap()); | 623 500, "Service Worker Response Error", ServiceWorkerHeaderMap()); |
| 497 CommitResponseHeader(); | 624 CommitResponseHeader(); |
| 498 } | 625 } |
| 499 | 626 |
| 500 } // namespace content | 627 } // namespace content |
| OLD | NEW |