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 } |
| 101 NOTREACHED() << result; | 103 NOTREACHED() << result; |
| 102 return n::TYPE_FAILED; | 104 return n::TYPE_FAILED; |
| 103 } | 105 } |
| 104 | 106 |
| 105 } // namespace | 107 } // namespace |
| 106 | 108 |
| 109 class ServiceWorkerURLRequestJob::BlobConstructionWaiter { | |
| 110 public: | |
| 111 explicit BlobConstructionWaiter(ServiceWorkerURLRequestJob* owner) | |
| 112 : owner_(owner), weak_factory_(this) { | |
| 113 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "BlobConstructionWaiter", this, | |
| 114 "URL", owner_->request()->url().spec()); | |
| 115 owner_->request()->net_log().AddEvent( | |
| 116 net::NetLog:: | |
| 117 TYPE_SERVICE_WORKER_REQUEST_BODY_BLOB_CONSTRUCTION_STARTED); | |
|
mmenke
2016/05/16 15:30:02
Would it make sense to use BeginEvent / EndEvent w
falken
2016/05/17 02:03:14
Done.
| |
| 118 } | |
| 119 | |
| 120 ~BlobConstructionWaiter() { | |
| 121 owner_->request()->net_log().AddEvent( | |
| 122 net::NetLog:: | |
| 123 TYPE_SERVICE_WORKER_REQUEST_BODY_BLOB_CONSTRUCTION_FINISHED, | |
| 124 net::NetLog::BoolCallback("Success", phase_ == Phase::SUCCESS)); | |
| 125 TRACE_EVENT_ASYNC_END1("ServiceWorker", "BlobConstructionWaiter", this, | |
| 126 "Success", phase_ == Phase::SUCCESS); | |
| 127 } | |
| 128 | |
| 129 void RunOnComplete(const base::Callback<void(bool)>& callback) { | |
| 130 DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_)); | |
| 131 phase_ = Phase::WAITING; | |
| 132 num_pending_request_body_blobs_ = 0; | |
| 133 callback_ = callback; | |
| 134 | |
| 135 for (const ResourceRequestBody::Element& element : | |
| 136 *(owner_->body_->elements())) { | |
| 137 if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) | |
| 138 continue; | |
| 139 | |
| 140 std::unique_ptr<storage::BlobDataHandle> handle = | |
| 141 owner_->blob_storage_context_->GetBlobDataFromUUID( | |
| 142 element.blob_uuid()); | |
| 143 if (handle->IsBroken()) { | |
| 144 Complete(false); | |
| 145 return; | |
| 146 } | |
| 147 if (handle->IsBeingBuilt()) { | |
| 148 ++num_pending_request_body_blobs_; | |
| 149 handle->RunOnConstructionComplete( | |
| 150 base::Bind(&BlobConstructionWaiter::OneRequestBodyBlobCompleted, | |
| 151 weak_factory_.GetWeakPtr())); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 if (num_pending_request_body_blobs_ == 0) | |
| 156 Complete(true); | |
| 157 } | |
| 158 | |
| 159 private: | |
| 160 enum class Phase { INITIAL, WAITING, SUCCESS, FAIL }; | |
| 161 | |
| 162 void OneRequestBodyBlobCompleted( | |
| 163 bool success, | |
| 164 storage::IPCBlobCreationCancelCode cancel_code) { | |
| 165 DCHECK_GT(num_pending_request_body_blobs_, 0UL); | |
| 166 | |
| 167 if (success) | |
| 168 --num_pending_request_body_blobs_; | |
| 169 else | |
| 170 num_pending_request_body_blobs_ = 0; | |
| 171 | |
| 172 if (num_pending_request_body_blobs_ == 0) | |
| 173 Complete(success); | |
| 174 } | |
| 175 | |
| 176 void Complete(bool success) { | |
| 177 DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_)); | |
| 178 phase_ = success ? Phase::SUCCESS : Phase::FAIL; | |
| 179 // Destroys |this|. | |
| 180 callback_.Run(success); | |
| 181 } | |
| 182 | |
| 183 // Owns and must outlive |this|. | |
| 184 ServiceWorkerURLRequestJob* owner_; | |
| 185 | |
| 186 scoped_refptr<ResourceRequestBody> body_; | |
| 187 base::Callback<void(bool)> callback_; | |
| 188 size_t num_pending_request_body_blobs_ = 0; | |
| 189 Phase phase_ = Phase::INITIAL; | |
| 190 base::WeakPtrFactory<BlobConstructionWaiter> weak_factory_; | |
| 191 | |
| 192 DISALLOW_COPY_AND_ASSIGN(BlobConstructionWaiter); | |
| 193 }; | |
| 194 | |
| 107 bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid( | 195 bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid( |
| 108 ServiceWorkerMetrics::URLRequestJobResult* result) { | 196 ServiceWorkerMetrics::URLRequestJobResult* result) { |
| 109 return true; | 197 return true; |
| 110 } | 198 } |
| 111 | 199 |
| 112 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( | 200 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( |
| 113 net::URLRequest* request, | 201 net::URLRequest* request, |
| 114 net::NetworkDelegate* network_delegate, | 202 net::NetworkDelegate* network_delegate, |
| 115 const std::string& client_id, | 203 const std::string& client_id, |
| 116 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, | 204 base::WeakPtr<storage::BlobStorageContext> blob_storage_context, |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 void ServiceWorkerURLRequestJob::MaybeStartRequest() { | 484 void ServiceWorkerURLRequestJob::MaybeStartRequest() { |
| 397 if (is_started_ && response_type_ != NOT_DETERMINED) { | 485 if (is_started_ && response_type_ != NOT_DETERMINED) { |
| 398 // Start asynchronously. | 486 // Start asynchronously. |
| 399 base::ThreadTaskRunnerHandle::Get()->PostTask( | 487 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 400 FROM_HERE, base::Bind(&ServiceWorkerURLRequestJob::StartRequest, | 488 FROM_HERE, base::Bind(&ServiceWorkerURLRequestJob::StartRequest, |
| 401 weak_factory_.GetWeakPtr())); | 489 weak_factory_.GetWeakPtr())); |
| 402 } | 490 } |
| 403 } | 491 } |
| 404 | 492 |
| 405 void ServiceWorkerURLRequestJob::StartRequest() { | 493 void ServiceWorkerURLRequestJob::StartRequest() { |
| 406 if (request()) { | 494 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 | 495 |
| 411 switch (response_type_) { | 496 switch (response_type_) { |
| 412 case NOT_DETERMINED: | 497 case NOT_DETERMINED: |
| 413 NOTREACHED(); | 498 NOTREACHED(); |
| 414 return; | 499 return; |
| 415 | 500 |
| 416 case FALLBACK_TO_NETWORK: | 501 case FALLBACK_TO_NETWORK: |
| 417 // Restart the request to create a new job. Our request handler will | 502 // 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 | 503 // return nullptr, and the default job (which will hit network) should be |
| 419 // created. | 504 // created. |
| 420 NotifyRestartRequired(); | 505 NotifyRestartRequired(); |
| 421 return; | 506 return; |
| 422 | 507 |
| 423 case FORWARD_TO_SERVICE_WORKER: | 508 case FORWARD_TO_SERVICE_WORKER: |
| 424 ServiceWorkerMetrics::URLRequestJobResult result = | 509 if (HasRequestBody()) { |
| 425 ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | 510 DCHECK(!blob_construction_waiter_); |
| 426 ServiceWorkerVersion* active_worker = | 511 blob_construction_waiter_.reset(new BlobConstructionWaiter(this)); |
| 427 delegate_->GetServiceWorkerVersion(&result); | 512 blob_construction_waiter_->RunOnComplete( |
| 428 if (!active_worker) { | 513 base::Bind(&ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted, |
| 429 RecordResult(result); | 514 GetWeakPtr())); |
| 430 DeliverErrorResponse(); | |
| 431 return; | 515 return; |
| 432 } | 516 } |
| 433 | 517 |
| 434 DCHECK(!fetch_dispatcher_); | 518 RequestBodyBlobsCompleted(true); |
| 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; | 519 return; |
| 446 } | 520 } |
| 447 | 521 |
| 448 NOTREACHED(); | 522 NOTREACHED(); |
| 449 } | 523 } |
| 450 | 524 |
| 451 std::unique_ptr<ServiceWorkerFetchRequest> | 525 std::unique_ptr<ServiceWorkerFetchRequest> |
| 452 ServiceWorkerURLRequestJob::CreateFetchRequest() { | 526 ServiceWorkerURLRequestJob::CreateFetchRequest() { |
| 453 std::string blob_uuid; | 527 std::string blob_uuid; |
| 454 uint64_t blob_size = 0; | 528 uint64_t blob_size = 0; |
| 455 // The upload data in URLRequest may have been cleared while handing redirect. | 529 if (HasRequestBody()) |
| 456 if (request_->has_upload()) | |
| 457 CreateRequestBodyBlob(&blob_uuid, &blob_size); | 530 CreateRequestBodyBlob(&blob_uuid, &blob_size); |
| 458 std::unique_ptr<ServiceWorkerFetchRequest> request( | 531 std::unique_ptr<ServiceWorkerFetchRequest> request( |
| 459 new ServiceWorkerFetchRequest()); | 532 new ServiceWorkerFetchRequest()); |
| 460 request->mode = request_mode_; | 533 request->mode = request_mode_; |
| 461 request->is_main_resource_load = IsMainResourceLoad(); | 534 request->is_main_resource_load = IsMainResourceLoad(); |
| 462 request->request_context_type = request_context_type_; | 535 request->request_context_type = request_context_type_; |
| 463 request->frame_type = frame_type_; | 536 request->frame_type = frame_type_; |
| 464 request->url = request_->url(); | 537 request->url = request_->url(); |
| 465 request->method = request_->method(); | 538 request->method = request_->method(); |
| 466 const net::HttpRequestHeaders& headers = request_->extra_request_headers(); | 539 const net::HttpRequestHeaders& headers = request_->extra_request_headers(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 484 CHECK( | 557 CHECK( |
| 485 request_->referrer_policy() == | 558 request_->referrer_policy() == |
| 486 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); | 559 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); |
| 487 request->referrer = | 560 request->referrer = |
| 488 Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault); | 561 Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault); |
| 489 } | 562 } |
| 490 request->fetch_type = fetch_type_; | 563 request->fetch_type = fetch_type_; |
| 491 return request; | 564 return request; |
| 492 } | 565 } |
| 493 | 566 |
| 494 bool ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid, | 567 void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid, |
| 495 uint64_t* blob_size) { | 568 uint64_t* blob_size) { |
| 496 if (!body_.get() || !blob_storage_context_) | 569 DCHECK(HasRequestBody()); |
| 497 return false; | |
| 498 | |
| 499 // To ensure the blobs stick around until the end of the reading. | 570 // To ensure the blobs stick around until the end of the reading. |
| 500 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; | 571 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; |
| 501 std::vector<std::unique_ptr<storage::BlobDataSnapshot>> snapshots; | 572 std::vector<std::unique_ptr<storage::BlobDataSnapshot>> snapshots; |
| 502 // TODO(dmurph): Allow blobs to be added below, so that the context can | 573 // TODO(dmurph): Allow blobs to be added below, so that the context can |
| 503 // efficiently re-use blob items for the new blob. | 574 // efficiently re-use blob items for the new blob. |
| 504 std::vector<const ResourceRequestBody::Element*> resolved_elements; | 575 std::vector<const ResourceRequestBody::Element*> resolved_elements; |
| 505 for (const ResourceRequestBody::Element& element : (*body_->elements())) { | 576 for (const ResourceRequestBody::Element& element : (*body_->elements())) { |
| 506 if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) { | 577 if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) { |
| 507 resolved_elements.push_back(&element); | 578 resolved_elements.push_back(&element); |
| 508 continue; | 579 continue; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 break; | 624 break; |
| 554 default: | 625 default: |
| 555 NOTIMPLEMENTED(); | 626 NOTIMPLEMENTED(); |
| 556 } | 627 } |
| 557 } | 628 } |
| 558 | 629 |
| 559 request_body_blob_data_handle_ = | 630 request_body_blob_data_handle_ = |
| 560 blob_storage_context_->AddFinishedBlob(&blob_builder); | 631 blob_storage_context_->AddFinishedBlob(&blob_builder); |
| 561 *blob_uuid = uuid; | 632 *blob_uuid = uuid; |
| 562 *blob_size = total_size; | 633 *blob_size = total_size; |
| 563 return true; | |
| 564 } | 634 } |
| 565 | 635 |
| 566 void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() { | 636 void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() { |
| 567 worker_ready_time_ = base::TimeTicks::Now(); | 637 worker_ready_time_ = base::TimeTicks::Now(); |
| 568 load_timing_info_.send_start = worker_ready_time_; | 638 load_timing_info_.send_start = worker_ready_time_; |
| 569 } | 639 } |
| 570 | 640 |
| 571 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent( | 641 void ServiceWorkerURLRequestJob::DidDispatchFetchEvent( |
| 572 ServiceWorkerStatusCode status, | 642 ServiceWorkerStatusCode status, |
| 573 ServiceWorkerFetchEventResult fetch_result, | 643 ServiceWorkerFetchEventResult fetch_result, |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 854 fall_back_required_, response_url_, | 924 fall_back_required_, response_url_, |
| 855 service_worker_response_type_, worker_start_time_, | 925 service_worker_response_type_, worker_start_time_, |
| 856 worker_ready_time_, response_is_in_cache_storage_, | 926 worker_ready_time_, response_is_in_cache_storage_, |
| 857 response_cache_storage_cache_name_); | 927 response_cache_storage_cache_name_); |
| 858 } | 928 } |
| 859 | 929 |
| 860 bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const { | 930 bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const { |
| 861 return ServiceWorkerUtils::IsMainResourceType(resource_type_); | 931 return ServiceWorkerUtils::IsMainResourceType(resource_type_); |
| 862 } | 932 } |
| 863 | 933 |
| 934 bool ServiceWorkerURLRequestJob::HasRequestBody() { | |
| 935 // URLRequest::has_upload() must be checked since its upload data may have | |
| 936 // been cleared while handling a redirect. | |
| 937 return request_->has_upload() && body_.get() && blob_storage_context_; | |
| 938 } | |
| 939 | |
| 940 void ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted(bool success) { | |
| 941 blob_construction_waiter_.reset(); | |
| 942 if (!success) { | |
| 943 RecordResult( | |
| 944 ServiceWorkerMetrics::REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED); | |
| 945 // TODO(falken): This and below should probably be NotifyStartError, not | |
| 946 // DeliverErrorResponse. But changing it causes | |
| 947 // ServiceWorkerURLRequestJobTest.DeletedProviderHostBeforeFetchEvent to | |
| 948 // fail. | |
| 949 DeliverErrorResponse(); | |
| 950 return; | |
| 951 } | |
| 952 | |
| 953 ServiceWorkerMetrics::URLRequestJobResult result = | |
| 954 ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | |
| 955 ServiceWorkerVersion* active_worker = | |
| 956 delegate_->GetServiceWorkerVersion(&result); | |
| 957 if (!active_worker) { | |
| 958 RecordResult(result); | |
| 959 DeliverErrorResponse(); | |
| 960 return; | |
| 961 } | |
| 962 | |
| 963 DCHECK(!fetch_dispatcher_); | |
| 964 fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | |
| 965 CreateFetchRequest(), active_worker, resource_type_, | |
| 966 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, | |
| 967 weak_factory_.GetWeakPtr()), | |
| 968 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, | |
| 969 weak_factory_.GetWeakPtr()))); | |
| 970 worker_start_time_ = base::TimeTicks::Now(); | |
| 971 fetch_dispatcher_->Run(); | |
| 972 } | |
| 973 | |
| 864 } // namespace content | 974 } // namespace content |
| OLD | NEW |