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