| 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 |