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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "content/browser/service_worker/service_worker_response_info.h" | 34 #include "content/browser/service_worker/service_worker_response_info.h" |
35 #include "content/browser/service_worker/service_worker_stream_reader.h" | 35 #include "content/browser/service_worker/service_worker_stream_reader.h" |
36 #include "content/common/resource_request_body_impl.h" | 36 #include "content/common/resource_request_body_impl.h" |
37 #include "content/common/service_worker/service_worker_types.h" | 37 #include "content/common/service_worker/service_worker_types.h" |
38 #include "content/common/service_worker/service_worker_utils.h" | 38 #include "content/common/service_worker/service_worker_utils.h" |
39 #include "content/public/browser/blob_handle.h" | 39 #include "content/public/browser/blob_handle.h" |
40 #include "content/public/browser/browser_thread.h" | 40 #include "content/public/browser/browser_thread.h" |
41 #include "content/public/browser/resource_request_info.h" | 41 #include "content/public/browser/resource_request_info.h" |
42 #include "content/public/browser/service_worker_context.h" | 42 #include "content/public/browser/service_worker_context.h" |
43 #include "content/public/common/referrer.h" | 43 #include "content/public/common/referrer.h" |
| 44 #include "mojo/public/cpp/system/simple_watcher.h" |
44 #include "net/base/net_errors.h" | 45 #include "net/base/net_errors.h" |
45 #include "net/http/http_request_headers.h" | 46 #include "net/http/http_request_headers.h" |
46 #include "net/http/http_response_headers.h" | 47 #include "net/http/http_response_headers.h" |
47 #include "net/http/http_response_info.h" | 48 #include "net/http/http_response_info.h" |
48 #include "net/http/http_util.h" | 49 #include "net/http/http_util.h" |
49 #include "net/log/net_log.h" | 50 #include "net/log/net_log.h" |
50 #include "net/log/net_log_event_type.h" | 51 #include "net/log/net_log_event_type.h" |
51 #include "net/log/net_log_with_source.h" | 52 #include "net/log/net_log_with_source.h" |
52 #include "storage/browser/blob/blob_data_builder.h" | 53 #include "storage/browser/blob/blob_data_builder.h" |
53 #include "storage/browser/blob/blob_data_handle.h" | 54 #include "storage/browser/blob/blob_data_handle.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 base::File::Info file_info; | 120 base::File::Info file_info; |
120 if (!base::GetFileInfo(path, &file_info) || file_info.is_directory) | 121 if (!base::GetFileInfo(path, &file_info) || file_info.is_directory) |
121 return std::vector<int64_t>(); | 122 return std::vector<int64_t>(); |
122 sizes.push_back(file_info.size); | 123 sizes.push_back(file_info.size); |
123 } | 124 } |
124 return sizes; | 125 return sizes; |
125 } | 126 } |
126 | 127 |
127 } // namespace | 128 } // namespace |
128 | 129 |
| 130 class ServiceWorkerDataPipeReader { |
| 131 public: |
| 132 ServiceWorkerDataPipeReader( |
| 133 ServiceWorkerURLRequestJob* owner, |
| 134 scoped_refptr<ServiceWorkerVersion> streaming_version, |
| 135 mojo::ScopedDataPipeConsumerHandle stream) |
| 136 : owner_(owner), |
| 137 streaming_version_(streaming_version), |
| 138 handle_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), |
| 139 stream_(std::move(stream)) { |
| 140 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerDataPipeReader", |
| 141 this, "Url", owner->request()->url().spec()); |
| 142 streaming_version_->AddStreamingURLRequestJob(owner_); |
| 143 } |
| 144 ~ServiceWorkerDataPipeReader() { |
| 145 // LOG(ERROR) << "~ServiceWorkerDataPipeReader"; |
| 146 if (streaming_version_) { |
| 147 streaming_version_->RemoveStreamingURLRequestJob(owner_); |
| 148 streaming_version_ = nullptr; |
| 149 } |
| 150 TRACE_EVENT_ASYNC_END0("ServiceWorker", "ServiceWorkerDataPipeReader", |
| 151 this); |
| 152 } |
| 153 void Start() { |
| 154 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", |
| 155 this, "Start"); |
| 156 // LOG(ERROR) << "ServiceWorkerDataPipeReader::Start"; |
| 157 handle_watcher_.Watch( |
| 158 stream_.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 159 base::Bind(&ServiceWorkerDataPipeReader::OnHandleGotReadable, |
| 160 base::Unretained(this))); |
| 161 handle_watcher_.ArmOrNotify(); |
| 162 owner_->OnResponseStarted(); |
| 163 } |
| 164 void OnHandleGotReadable(MojoResult) { |
| 165 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", |
| 166 this, "OnHandleGotReadable"); |
| 167 // LOG(ERROR) << "OnHandleGotReadable"; |
| 168 if (!stream_pending_buffer_) |
| 169 return; |
| 170 uint32_t size_to_pass = stream_pending_buffer_size_; |
| 171 MojoResult mojo_result = |
| 172 mojo::ReadDataRaw(stream_.get(), stream_pending_buffer_->data(), |
| 173 &size_to_pass, MOJO_READ_DATA_FLAG_NONE); |
| 174 if (mojo_result == MOJO_RESULT_SHOULD_WAIT) { |
| 175 handle_watcher_.ArmOrNotify(); |
| 176 return; |
| 177 } |
| 178 stream_pending_buffer_ = nullptr; |
| 179 stream_pending_buffer_size_ = 0; |
| 180 |
| 181 switch (mojo_result) { |
| 182 case MOJO_RESULT_OK: |
| 183 owner_->OnReadRawDataComplete(size_to_pass); |
| 184 return; |
| 185 case MOJO_RESULT_FAILED_PRECONDITION: |
| 186 handle_watcher_.Cancel(); |
| 187 owner_->RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); |
| 188 owner_->OnReadRawDataComplete(0); |
| 189 return; |
| 190 case MOJO_RESULT_BUSY: |
| 191 case MOJO_RESULT_RESOURCE_EXHAUSTED: |
| 192 owner_->OnReadRawDataComplete(net::ERR_FAILED); |
| 193 return; |
| 194 } |
| 195 } |
| 196 int ReadRawData(net::IOBuffer* buf, int buf_size) { |
| 197 TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker", "ServiceWorkerDataPipeReader", |
| 198 this, "ReadRawData"); |
| 199 uint32_t size_to_pass = buf_size; |
| 200 MojoResult mojo_result = mojo::ReadDataRaw( |
| 201 stream_.get(), buf->data(), &size_to_pass, MOJO_READ_DATA_FLAG_NONE); |
| 202 switch (mojo_result) { |
| 203 case MOJO_RESULT_OK: |
| 204 return size_to_pass; |
| 205 case MOJO_RESULT_FAILED_PRECONDITION: |
| 206 handle_watcher_.Cancel(); |
| 207 owner_->RecordResult(ServiceWorkerMetrics::REQUEST_JOB_STREAM_RESPONSE); |
| 208 return 0; |
| 209 case MOJO_RESULT_BUSY: |
| 210 return net::ERR_FAILED; |
| 211 case MOJO_RESULT_SHOULD_WAIT: |
| 212 stream_pending_buffer_ = buf; |
| 213 stream_pending_buffer_size_ = buf_size; |
| 214 handle_watcher_.ArmOrNotify(); |
| 215 return net::ERR_IO_PENDING; |
| 216 case MOJO_RESULT_RESOURCE_EXHAUSTED: |
| 217 return net::ERR_FAILED; |
| 218 } |
| 219 return net::ERR_FAILED; |
| 220 } |
| 221 |
| 222 private: |
| 223 ServiceWorkerURLRequestJob* owner_; |
| 224 scoped_refptr<ServiceWorkerVersion> streaming_version_; |
| 225 scoped_refptr<net::IOBuffer> stream_pending_buffer_; |
| 226 int stream_pending_buffer_size_ = 0; |
| 227 mojo::SimpleWatcher handle_watcher_; |
| 228 mojo::ScopedDataPipeConsumerHandle stream_; |
| 229 }; |
| 230 |
129 // Sets the size on each DataElement in the request body that is a file with | 231 // Sets the size on each DataElement in the request body that is a file with |
130 // unknown size. This ensures ServiceWorkerURLRequestJob::CreateRequestBodyBlob | 232 // unknown size. This ensures ServiceWorkerURLRequestJob::CreateRequestBodyBlob |
131 // can successfuly create a blob from the data elements, as files with unknown | 233 // can successfuly create a blob from the data elements, as files with unknown |
132 // sizes are not supported by the blob storage system. | 234 // sizes are not supported by the blob storage system. |
133 class ServiceWorkerURLRequestJob::FileSizeResolver { | 235 class ServiceWorkerURLRequestJob::FileSizeResolver { |
134 public: | 236 public: |
135 explicit FileSizeResolver(ServiceWorkerURLRequestJob* owner) | 237 explicit FileSizeResolver(ServiceWorkerURLRequestJob* owner) |
136 : owner_(owner), weak_factory_(this) { | 238 : owner_(owner), weak_factory_(this) { |
137 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "FileSizeResolver", this, "URL", | 239 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "FileSizeResolver", this, "URL", |
138 owner_->request()->url().spec()); | 240 owner_->request()->url().spec()); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 fall_back_required_(false), | 356 fall_back_required_(false), |
255 body_(body), | 357 body_(body), |
256 fetch_type_(fetch_type), | 358 fetch_type_(fetch_type), |
257 timeout_(timeout), | 359 timeout_(timeout), |
258 weak_factory_(this) { | 360 weak_factory_(this) { |
259 DCHECK(delegate_) << "ServiceWorkerURLRequestJob requires a delegate"; | 361 DCHECK(delegate_) << "ServiceWorkerURLRequestJob requires a delegate"; |
260 } | 362 } |
261 | 363 |
262 ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() { | 364 ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() { |
263 stream_reader_.reset(); | 365 stream_reader_.reset(); |
| 366 data_pipe_reader_.reset(); |
264 file_size_resolver_.reset(); | 367 file_size_resolver_.reset(); |
265 | 368 |
266 if (!ShouldRecordResult()) | 369 if (!ShouldRecordResult()) |
267 return; | 370 return; |
268 ServiceWorkerMetrics::URLRequestJobResult result = | 371 ServiceWorkerMetrics::URLRequestJobResult result = |
269 ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED; | 372 ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED; |
270 if (response_body_type_ == STREAM) | 373 if (response_body_type_ == STREAM) |
271 result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED_WITH_STREAM; | 374 result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED_WITH_STREAM; |
272 else if (response_body_type_ == BLOB) | 375 else if (response_body_type_ == BLOB) |
273 result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED_WITH_BLOB; | 376 result = ServiceWorkerMetrics::REQUEST_JOB_ERROR_KILLED_WITH_BLOB; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 } | 408 } |
306 | 409 |
307 void ServiceWorkerURLRequestJob::Start() { | 410 void ServiceWorkerURLRequestJob::Start() { |
308 is_started_ = true; | 411 is_started_ = true; |
309 MaybeStartRequest(); | 412 MaybeStartRequest(); |
310 } | 413 } |
311 | 414 |
312 void ServiceWorkerURLRequestJob::Kill() { | 415 void ServiceWorkerURLRequestJob::Kill() { |
313 net::URLRequestJob::Kill(); | 416 net::URLRequestJob::Kill(); |
314 stream_reader_.reset(); | 417 stream_reader_.reset(); |
| 418 data_pipe_reader_.reset(); |
315 fetch_dispatcher_.reset(); | 419 fetch_dispatcher_.reset(); |
316 blob_reader_.reset(); | 420 blob_reader_.reset(); |
317 weak_factory_.InvalidateWeakPtrs(); | 421 weak_factory_.InvalidateWeakPtrs(); |
318 } | 422 } |
319 | 423 |
320 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { | 424 net::LoadState ServiceWorkerURLRequestJob::GetLoadState() const { |
321 // TODO(kinuko): refine this for better debug. | 425 // TODO(kinuko): refine this for better debug. |
322 return net::URLRequestJob::GetLoadState(); | 426 return net::URLRequestJob::GetLoadState(); |
323 } | 427 } |
324 | 428 |
325 bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) { | 429 bool ServiceWorkerURLRequestJob::GetCharset(std::string* charset) { |
326 if (!http_info()) | 430 if (!http_info()) |
327 return false; | 431 return false; |
| 432 // LOG(ERROR) << "http_info()->headers " << http_info()->headers; |
328 return http_info()->headers->GetCharset(charset); | 433 return http_info()->headers->GetCharset(charset); |
329 } | 434 } |
330 | 435 |
331 bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const { | 436 bool ServiceWorkerURLRequestJob::GetMimeType(std::string* mime_type) const { |
332 if (!http_info()) | 437 if (!http_info()) |
333 return false; | 438 return false; |
334 return http_info()->headers->GetMimeType(mime_type); | 439 return http_info()->headers->GetMimeType(mime_type); |
335 } | 440 } |
336 | 441 |
337 void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { | 442 void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { |
(...skipping 23 matching lines...) Expand all Loading... |
361 if (ranges.size() == 1U) | 466 if (ranges.size() == 1U) |
362 byte_range_ = ranges[0]; | 467 byte_range_ = ranges[0]; |
363 } | 468 } |
364 | 469 |
365 int ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { | 470 int ServiceWorkerURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { |
366 DCHECK(buf); | 471 DCHECK(buf); |
367 DCHECK_GE(buf_size, 0); | 472 DCHECK_GE(buf_size, 0); |
368 | 473 |
369 if (stream_reader_) | 474 if (stream_reader_) |
370 return stream_reader_->ReadRawData(buf, buf_size); | 475 return stream_reader_->ReadRawData(buf, buf_size); |
| 476 if (data_pipe_reader_) |
| 477 return data_pipe_reader_->ReadRawData(buf, buf_size); |
371 if (blob_reader_) | 478 if (blob_reader_) |
372 return blob_reader_->ReadRawData(buf, buf_size); | 479 return blob_reader_->ReadRawData(buf, buf_size); |
373 | 480 |
374 return 0; | 481 return 0; |
375 } | 482 } |
376 | 483 |
377 void ServiceWorkerURLRequestJob::OnResponseStarted() { | 484 void ServiceWorkerURLRequestJob::OnResponseStarted() { |
378 if (response_time_.is_null()) | 485 if (response_time_.is_null()) |
379 response_time_ = base::Time::Now(); | 486 response_time_ = base::Time::Now(); |
380 CommitResponseHeader(); | 487 CommitResponseHeader(); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame( | 663 ServiceWorkerMetrics::RecordActivatedWorkerPreparationForMainFrame( |
557 worker_ready_time_ - request()->creation_time(), initial_worker_status_, | 664 worker_ready_time_ - request()->creation_time(), initial_worker_status_, |
558 worker_start_situation_, did_navigation_preload_); | 665 worker_start_situation_, did_navigation_preload_); |
559 MaybeReportNavigationPreloadMetrics(); | 666 MaybeReportNavigationPreloadMetrics(); |
560 } | 667 } |
561 | 668 |
562 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent( | 669 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent( |
563 ServiceWorkerStatusCode status, | 670 ServiceWorkerStatusCode status, |
564 ServiceWorkerFetchEventResult fetch_result, | 671 ServiceWorkerFetchEventResult fetch_result, |
565 const ServiceWorkerResponse& response, | 672 const ServiceWorkerResponse& response, |
| 673 mojo::ScopedDataPipeConsumerHandle stream, |
566 const scoped_refptr<ServiceWorkerVersion>& version) { | 674 const scoped_refptr<ServiceWorkerVersion>& version) { |
567 // Do not clear |fetch_dispatcher_| if it has dispatched a navigation preload | 675 // Do not clear |fetch_dispatcher_| if it has dispatched a navigation preload |
568 // request to keep the mojom::URLLoader related objects in it, because the | 676 // request to keep the mojom::URLLoader related objects in it, because the |
569 // preload response might still need to be streamed even after calling | 677 // preload response might still need to be streamed even after calling |
570 // respondWith(). | 678 // respondWith(). |
571 if (!did_navigation_preload_) { | 679 if (!did_navigation_preload_) { |
572 fetch_dispatcher_.reset(); | 680 fetch_dispatcher_.reset(); |
573 } | 681 } |
574 ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status); | 682 ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status); |
575 | 683 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 // Set up a request for reading the stream. | 739 // Set up a request for reading the stream. |
632 if (response.stream_url.is_valid()) { | 740 if (response.stream_url.is_valid()) { |
633 DCHECK(response.blob_uuid.empty()); | 741 DCHECK(response.blob_uuid.empty()); |
634 SetResponseBodyType(STREAM); | 742 SetResponseBodyType(STREAM); |
635 SetResponse(response); | 743 SetResponse(response); |
636 stream_reader_.reset(new ServiceWorkerStreamReader(this, version)); | 744 stream_reader_.reset(new ServiceWorkerStreamReader(this, version)); |
637 stream_reader_->Start(response.stream_url); | 745 stream_reader_->Start(response.stream_url); |
638 return; | 746 return; |
639 } | 747 } |
640 | 748 |
| 749 if (stream.is_valid()) { |
| 750 // LOG(ERROR) << "response.status_code " << response.status_code; |
| 751 // LOG(ERROR) << "stream.is_valid()"; |
| 752 SetResponseBodyType(STREAM); |
| 753 SetResponse(response); |
| 754 data_pipe_reader_.reset( |
| 755 new ServiceWorkerDataPipeReader(this, version, std::move(stream))); |
| 756 data_pipe_reader_->Start(); |
| 757 return; |
| 758 } |
| 759 |
641 // Set up a request for reading the blob. | 760 // Set up a request for reading the blob. |
642 if (!response.blob_uuid.empty() && blob_storage_context_) { | 761 if (!response.blob_uuid.empty() && blob_storage_context_) { |
643 SetResponseBodyType(BLOB); | 762 SetResponseBodyType(BLOB); |
644 std::unique_ptr<storage::BlobDataHandle> blob_data_handle = | 763 std::unique_ptr<storage::BlobDataHandle> blob_data_handle = |
645 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); | 764 blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); |
646 if (!blob_data_handle) { | 765 if (!blob_data_handle) { |
647 // The renderer gave us a bad blob UUID. | 766 // The renderer gave us a bad blob UUID. |
648 RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_BLOB); | 767 RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_BLOB); |
649 DeliverErrorResponse(); | 768 DeliverErrorResponse(); |
650 return; | 769 return; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 DCHECK(!reported_navigation_preload_metrics_); | 1027 DCHECK(!reported_navigation_preload_metrics_); |
909 reported_navigation_preload_metrics_ = true; | 1028 reported_navigation_preload_metrics_ = true; |
910 | 1029 |
911 ServiceWorkerMetrics::RecordNavigationPreloadResponse( | 1030 ServiceWorkerMetrics::RecordNavigationPreloadResponse( |
912 worker_ready_time_ - worker_start_time_, | 1031 worker_ready_time_ - worker_start_time_, |
913 navigation_preload_response_time_ - worker_start_time_, | 1032 navigation_preload_response_time_ - worker_start_time_, |
914 initial_worker_status_, worker_start_situation_); | 1033 initial_worker_status_, worker_start_situation_); |
915 } | 1034 } |
916 | 1035 |
917 } // namespace content | 1036 } // namespace content |
OLD | NEW |