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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 case m::REQUEST_JOB_ERROR_STREAM_ABORTED: | 81 case m::REQUEST_JOB_ERROR_STREAM_ABORTED: |
| 82 return n::TYPE_SERVICE_WORKER_ERROR_STREAM_ABORTED; | 82 return n::TYPE_SERVICE_WORKER_ERROR_STREAM_ABORTED; |
| 83 case m::REQUEST_JOB_ERROR_KILLED: | 83 case m::REQUEST_JOB_ERROR_KILLED: |
| 84 return n::TYPE_SERVICE_WORKER_ERROR_KILLED; | 84 return n::TYPE_SERVICE_WORKER_ERROR_KILLED; |
| 85 case m::REQUEST_JOB_ERROR_KILLED_WITH_BLOB: | 85 case m::REQUEST_JOB_ERROR_KILLED_WITH_BLOB: |
| 86 return n::TYPE_SERVICE_WORKER_ERROR_KILLED_WITH_BLOB; | 86 return n::TYPE_SERVICE_WORKER_ERROR_KILLED_WITH_BLOB; |
| 87 case m::REQUEST_JOB_ERROR_KILLED_WITH_STREAM: | 87 case m::REQUEST_JOB_ERROR_KILLED_WITH_STREAM: |
| 88 return n::TYPE_SERVICE_WORKER_ERROR_KILLED_WITH_STREAM; | 88 return n::TYPE_SERVICE_WORKER_ERROR_KILLED_WITH_STREAM; |
| 89 case m::REQUEST_JOB_ERROR_BAD_DELEGATE: | 89 case m::REQUEST_JOB_ERROR_BAD_DELEGATE: |
| 90 return n::TYPE_SERVICE_WORKER_ERROR_BAD_DELEGATE; | 90 return n::TYPE_SERVICE_WORKER_ERROR_BAD_DELEGATE; |
| 91 case m::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED: | |
| 92 return n::TYPE_SERVICE_WORKER_ERROR_REQUEST_BODY_BLOB_FAILED; | |
| 91 // We can't log if there's no request; fallthrough. | 93 // We can't log if there's no request; fallthrough. |
| 92 case m::REQUEST_JOB_ERROR_NO_REQUEST: | 94 case m::REQUEST_JOB_ERROR_NO_REQUEST: |
| 93 // Obsolete types; fallthrough. | 95 // Obsolete types; fallthrough. |
| 94 case m::REQUEST_JOB_ERROR_DESTROYED: | 96 case m::REQUEST_JOB_ERROR_DESTROYED: |
| 95 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB: | 97 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB: |
| 96 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM: | 98 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM: |
| 97 // Invalid type. | 99 // Invalid type. |
| 98 case m::NUM_REQUEST_JOB_RESULT_TYPES: | 100 case m::NUM_REQUEST_JOB_RESULT_TYPES: |
| 99 NOTREACHED() << result; | 101 NOTREACHED() << result; |
| 100 } | 102 } |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 void ServiceWorkerURLRequestJob::MaybeStartRequest() { | 398 void ServiceWorkerURLRequestJob::MaybeStartRequest() { |
| 397 if (is_started_ && response_type_ != NOT_DETERMINED) { | 399 if (is_started_ && response_type_ != NOT_DETERMINED) { |
| 398 // Start asynchronously. | 400 // Start asynchronously. |
| 399 base::ThreadTaskRunnerHandle::Get()->PostTask( | 401 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 400 FROM_HERE, base::Bind(&ServiceWorkerURLRequestJob::StartRequest, | 402 FROM_HERE, base::Bind(&ServiceWorkerURLRequestJob::StartRequest, |
| 401 weak_factory_.GetWeakPtr())); | 403 weak_factory_.GetWeakPtr())); |
| 402 } | 404 } |
| 403 } | 405 } |
| 404 | 406 |
| 405 void ServiceWorkerURLRequestJob::StartRequest() { | 407 void ServiceWorkerURLRequestJob::StartRequest() { |
| 406 if (request()) { | 408 request()->net_log().AddEvent(net::NetLog::TYPE_SERVICE_WORKER_START_REQUEST); |
| 407 request()->net_log().AddEvent( | |
| 408 net::NetLog::TYPE_SERVICE_WORKER_START_REQUEST); | |
| 409 } | |
| 410 | 409 |
| 411 switch (response_type_) { | 410 switch (response_type_) { |
| 412 case NOT_DETERMINED: | 411 case NOT_DETERMINED: |
| 413 NOTREACHED(); | 412 NOTREACHED(); |
| 414 return; | 413 return; |
| 415 | 414 |
| 416 case FALLBACK_TO_NETWORK: | 415 case FALLBACK_TO_NETWORK: |
| 417 // Restart the request to create a new job. Our request handler will | 416 // Restart the request to create a new job. Our request handler will |
| 418 // return nullptr, and the default job (which will hit network) should be | 417 // return nullptr, and the default job (which will hit network) should be |
| 419 // created. | 418 // created. |
| 420 NotifyRestartRequired(); | 419 NotifyRestartRequired(); |
| 421 return; | 420 return; |
| 422 | 421 |
| 423 case FORWARD_TO_SERVICE_WORKER: | 422 case FORWARD_TO_SERVICE_WORKER: |
| 424 ServiceWorkerMetrics::URLRequestJobResult result = | 423 if (HasRequestBody()) { |
| 425 ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | 424 WaitForRequestBobyBlobsToComplete(); |
| 426 ServiceWorkerVersion* active_worker = | |
| 427 delegate_->GetServiceWorkerVersion(&result); | |
| 428 if (!active_worker) { | |
| 429 RecordResult(result); | |
| 430 DeliverErrorResponse(); | |
| 431 return; | 425 return; |
| 432 } | 426 } |
| 433 | 427 |
| 434 DCHECK(!fetch_dispatcher_); | 428 DispatchToWorker(); |
| 435 // Send a fetch event to the ServiceWorker associated to the | |
| 436 // provider_host. | |
| 437 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | |
| 438 CreateFetchRequest(), active_worker, resource_type_, | |
| 439 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, | |
| 440 weak_factory_.GetWeakPtr()), | |
| 441 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, | |
| 442 weak_factory_.GetWeakPtr()))); | |
| 443 worker_start_time_ = base::TimeTicks::Now(); | |
| 444 fetch_dispatcher_->Run(); | |
| 445 return; | 429 return; |
| 446 } | 430 } |
| 447 | 431 |
| 448 NOTREACHED(); | 432 NOTREACHED(); |
| 449 } | 433 } |
| 450 | 434 |
| 435 void ServiceWorkerURLRequestJob::DispatchToWorker() { | |
| 436 ServiceWorkerMetrics::URLRequestJobResult result = | |
| 437 ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | |
| 438 ServiceWorkerVersion* active_worker = | |
| 439 delegate_->GetServiceWorkerVersion(&result); | |
| 440 if (!active_worker) { | |
| 441 RecordResult(result); | |
| 442 DeliverErrorResponse(); | |
| 443 return; | |
| 444 } | |
| 445 | |
| 446 DCHECK(!fetch_dispatcher_); | |
| 447 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | |
| 448 CreateFetchRequest(), active_worker, resource_type_, | |
| 449 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, | |
| 450 weak_factory_.GetWeakPtr()), | |
| 451 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, | |
| 452 weak_factory_.GetWeakPtr()))); | |
| 453 worker_start_time_ = base::TimeTicks::Now(); | |
| 454 fetch_dispatcher_->Run(); | |
| 455 } | |
| 456 | |
| 451 std::unique_ptr<ServiceWorkerFetchRequest> | 457 std::unique_ptr<ServiceWorkerFetchRequest> |
| 452 ServiceWorkerURLRequestJob::CreateFetchRequest() { | 458 ServiceWorkerURLRequestJob::CreateFetchRequest() { |
| 453 std::string blob_uuid; | 459 std::string blob_uuid; |
| 454 uint64_t blob_size = 0; | 460 uint64_t blob_size = 0; |
| 455 // The upload data in URLRequest may have been cleared while handing redirect. | 461 // The upload data in URLRequest may have been cleared while handing redirect. |
| 456 if (request_->has_upload()) | 462 if (request_->has_upload()) |
| 457 CreateRequestBodyBlob(&blob_uuid, &blob_size); | 463 CreateRequestBodyBlob(&blob_uuid, &blob_size); |
| 458 std::unique_ptr<ServiceWorkerFetchRequest> request( | 464 std::unique_ptr<ServiceWorkerFetchRequest> request( |
| 459 new ServiceWorkerFetchRequest()); | 465 new ServiceWorkerFetchRequest()); |
| 460 request->mode = request_mode_; | 466 request->mode = request_mode_; |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 854 fall_back_required_, response_url_, | 860 fall_back_required_, response_url_, |
| 855 service_worker_response_type_, worker_start_time_, | 861 service_worker_response_type_, worker_start_time_, |
| 856 worker_ready_time_, response_is_in_cache_storage_, | 862 worker_ready_time_, response_is_in_cache_storage_, |
| 857 response_cache_storage_cache_name_); | 863 response_cache_storage_cache_name_); |
| 858 } | 864 } |
| 859 | 865 |
| 860 bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const { | 866 bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const { |
| 861 return ServiceWorkerUtils::IsMainResourceType(resource_type_); | 867 return ServiceWorkerUtils::IsMainResourceType(resource_type_); |
| 862 } | 868 } |
| 863 | 869 |
| 870 bool ServiceWorkerURLRequestJob::HasRequestBody() { | |
| 871 // |has_upload| must be checked since it may have been cleared while handling | |
| 872 // a redirect. | |
| 873 return request_->has_upload() && body_.get() && blob_storage_context_; | |
| 874 } | |
| 875 | |
| 876 void ServiceWorkerURLRequestJob::WaitForRequestBobyBlobsToComplete() { | |
| 877 DCHECK(HasRequestBody()); | |
| 878 | |
| 879 num_pending_request_body_blobs_ = 0; | |
| 880 for (const ResourceRequestBody::Element& element : (*body_->elements())) { | |
| 881 if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) | |
| 882 ++num_pending_request_body_blobs_; | |
| 883 } | |
| 884 | |
| 885 if (num_pending_request_body_blobs_ == 0) { | |
| 886 DispatchToWorker(); | |
| 887 return; | |
| 888 } | |
| 889 | |
| 890 TRACE_EVENT_ASYNC_BEGIN1( | |
| 891 "ServiceWorker", | |
| 892 "ServiceWorkerURLRequestJob::WaitForRequestBobyBlobsToComplete", this, | |
| 893 "URL", request()->url().spec()); | |
| 894 request()->net_log().AddEvent( | |
| 895 net::NetLog::TYPE_SERVICE_WORKER_REQUEST_BODY_BLOB_CONSTRUCTION_STARTED); | |
| 896 | |
| 897 for (const ResourceRequestBody::Element& element : (*body_->elements())) { | |
| 898 if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) { | |
| 899 std::unique_ptr<storage::BlobDataHandle> handle = | |
|
dmurph
2016/05/11 21:35:58
You can check if the blob is building before calli
falken
2016/05/12 08:49:33
Done. I had considered that but was worried about
| |
| 900 blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid()); | |
| 901 handle->RunOnConstructionComplete( | |
| 902 base::Bind(&ServiceWorkerURLRequestJob::OneRequestBodyBlobCompleted, | |
| 903 GetWeakPtr())); | |
| 904 } | |
| 905 } | |
| 906 } | |
| 907 | |
| 908 void ServiceWorkerURLRequestJob::OneRequestBodyBlobCompleted( | |
| 909 bool success, | |
| 910 storage::IPCBlobCreationCancelCode cancel_code) { | |
| 911 if (num_pending_request_body_blobs_ == 0) { | |
| 912 // We already ran the callback. | |
| 913 return; | |
| 914 } | |
| 915 | |
| 916 if (success) | |
| 917 --num_pending_request_body_blobs_; | |
| 918 else | |
| 919 num_pending_request_body_blobs_ = 0; | |
| 920 | |
| 921 if (num_pending_request_body_blobs_ == 0) | |
| 922 RequestBodyBlobsCompleted(success, cancel_code); | |
| 923 } | |
| 924 | |
| 925 void ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted( | |
| 926 bool success, | |
| 927 storage::IPCBlobCreationCancelCode cancel_code) { | |
| 928 TRACE_EVENT_ASYNC_END2( | |
| 929 "ServiceWorker", | |
| 930 "ServiceWorkerURLRequestJob::WaitForRequestBobyBlobsToComplete", this, | |
| 931 "Success", success, "IPCBlobCreationCancelCode", | |
| 932 static_cast<int>(cancel_code)); | |
| 933 | |
| 934 if (!success) { | |
| 935 RecordResult( | |
| 936 ServiceWorkerMetrics::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED); | |
| 937 NotifyStartError(net::URLRequestStatus::FromError(net::ERR_FAILED)); | |
| 938 return; | |
| 939 } | |
| 940 | |
| 941 request()->net_log().AddEvent( | |
| 942 net::NetLog::TYPE_SERVICE_WORKER_REQUEST_BODY_BLOB_CONSTRUCTION_FINISHED); | |
| 943 DispatchToWorker(); | |
| 944 } | |
| 945 | |
| 864 } // namespace content | 946 } // namespace content |
| OLD | NEW |