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> |
| 11 #include <map> | 11 #include <map> |
| 12 #include <memory> | 12 #include <memory> |
| 13 #include <string> | 13 #include <string> |
| 14 #include <utility> | 14 #include <utility> |
| 15 #include <vector> | 15 #include <vector> |
| 16 | 16 |
| 17 #include "base/bind.h" | 17 #include "base/bind.h" |
| 18 #include "base/files/file.h" | |
| 18 #include "base/guid.h" | 19 #include "base/guid.h" |
| 19 #include "base/location.h" | 20 #include "base/location.h" |
| 20 #include "base/single_thread_task_runner.h" | 21 #include "base/single_thread_task_runner.h" |
| 21 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
| 23 #include "base/task_runner.h" | |
| 24 #include "base/task_runner_util.h" | |
| 22 #include "base/threading/thread_task_runner_handle.h" | 25 #include "base/threading/thread_task_runner_handle.h" |
| 23 #include "base/time/time.h" | 26 #include "base/time/time.h" |
| 24 #include "content/browser/resource_context_impl.h" | 27 #include "content/browser/resource_context_impl.h" |
| 25 #include "content/browser/service_worker/embedded_worker_instance.h" | 28 #include "content/browser/service_worker/embedded_worker_instance.h" |
| 26 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h" | 29 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h" |
| 27 #include "content/browser/service_worker/service_worker_provider_host.h" | 30 #include "content/browser/service_worker/service_worker_provider_host.h" |
| 28 #include "content/browser/service_worker/service_worker_response_info.h" | 31 #include "content/browser/service_worker/service_worker_response_info.h" |
| 29 #include "content/browser/streams/stream.h" | 32 #include "content/browser/streams/stream.h" |
| 30 #include "content/browser/streams/stream_context.h" | 33 #include "content/browser/streams/stream_context.h" |
| 31 #include "content/browser/streams/stream_registry.h" | 34 #include "content/browser/streams/stream_registry.h" |
| 32 #include "content/common/resource_request_body_impl.h" | 35 #include "content/common/resource_request_body_impl.h" |
| 33 #include "content/common/service_worker/service_worker_types.h" | 36 #include "content/common/service_worker/service_worker_types.h" |
| 34 #include "content/common/service_worker/service_worker_utils.h" | 37 #include "content/common/service_worker/service_worker_utils.h" |
| 35 #include "content/public/browser/blob_handle.h" | 38 #include "content/public/browser/blob_handle.h" |
| 39 #include "content/public/browser/browser_thread.h" | |
| 36 #include "content/public/browser/resource_request_info.h" | 40 #include "content/public/browser/resource_request_info.h" |
| 37 #include "content/public/browser/service_worker_context.h" | 41 #include "content/public/browser/service_worker_context.h" |
| 38 #include "content/public/common/referrer.h" | 42 #include "content/public/common/referrer.h" |
| 39 #include "net/base/net_errors.h" | 43 #include "net/base/net_errors.h" |
| 40 #include "net/http/http_request_headers.h" | 44 #include "net/http/http_request_headers.h" |
| 41 #include "net/http/http_response_headers.h" | 45 #include "net/http/http_response_headers.h" |
| 42 #include "net/http/http_response_info.h" | 46 #include "net/http/http_response_info.h" |
| 43 #include "net/http/http_util.h" | 47 #include "net/http/http_util.h" |
| 44 #include "net/log/net_log.h" | 48 #include "net/log/net_log.h" |
| 45 #include "storage/browser/blob/blob_data_builder.h" | 49 #include "storage/browser/blob/blob_data_builder.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB: | 102 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB: |
| 99 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM: | 103 case m::REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM: |
| 100 // Invalid type. | 104 // Invalid type. |
| 101 case m::NUM_REQUEST_JOB_RESULT_TYPES: | 105 case m::NUM_REQUEST_JOB_RESULT_TYPES: |
| 102 NOTREACHED() << result; | 106 NOTREACHED() << result; |
| 103 } | 107 } |
| 104 NOTREACHED() << result; | 108 NOTREACHED() << result; |
| 105 return n::TYPE_FAILED; | 109 return n::TYPE_FAILED; |
| 106 } | 110 } |
| 107 | 111 |
| 112 bool PopulateUnknownFileLengths( | |
| 113 std::vector<ResourceRequestBodyImpl::Element>* elements) { | |
| 114 for (ResourceRequestBodyImpl::Element& element : *elements) { | |
| 115 if (element.type() == ResourceRequestBodyImpl::Element::TYPE_FILE && | |
| 116 element.length() == ResourceRequestBodyImpl::Element::kUnknownSize) { | |
| 117 // Try to open our file. | |
| 118 base::File file(element.path(), | |
| 119 base::File::FLAG_OPEN | base::File::FLAG_READ); | |
| 120 if (file.error_details() != base::File::FILE_OK) | |
| 121 return false; | |
| 122 | |
| 123 base::File::Info file_info; | |
| 124 if (!file.GetInfo(&file_info)) | |
| 125 return false; | |
| 126 | |
| 127 element.SetToFilePathRange(element.path(), element.offset(), | |
| 128 file_info.size, | |
| 129 element.expected_modification_time()); | |
| 130 } | |
| 131 } | |
| 132 return true; | |
| 133 } | |
| 134 | |
| 108 } // namespace | 135 } // namespace |
| 109 | 136 |
| 110 class ServiceWorkerURLRequestJob::BlobConstructionWaiter { | 137 class ServiceWorkerURLRequestJob::BlobFilesWaiter { |
| 111 public: | 138 public: |
| 112 explicit BlobConstructionWaiter(ServiceWorkerURLRequestJob* owner) | 139 explicit BlobFilesWaiter(ServiceWorkerURLRequestJob* owner) |
| 113 : owner_(owner), weak_factory_(this) { | 140 : owner_(owner), weak_factory_(this) { |
| 114 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "BlobConstructionWaiter", this, | 141 TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "BlobFilesWaiter", this, "URL", |
| 115 "URL", owner_->request()->url().spec()); | 142 owner_->request()->url().spec()); |
| 116 owner_->request()->net_log().BeginEvent( | 143 owner_->request()->net_log().BeginEvent( |
| 117 net::NetLog::TYPE_SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_BLOB); | 144 net::NetLog::TYPE_SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_FILES); |
| 118 } | 145 } |
| 119 | 146 |
| 120 ~BlobConstructionWaiter() { | 147 ~BlobFilesWaiter() { |
| 121 owner_->request()->net_log().EndEvent( | 148 owner_->request()->net_log().EndEvent( |
| 122 net::NetLog::TYPE_SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_BLOB, | 149 net::NetLog::TYPE_SERVICE_WORKER_WAITING_FOR_REQUEST_BODY_FILES, |
| 123 net::NetLog::BoolCallback("success", phase_ == Phase::SUCCESS)); | 150 net::NetLog::BoolCallback("success", phase_ == Phase::SUCCESS)); |
| 124 TRACE_EVENT_ASYNC_END1("ServiceWorker", "BlobConstructionWaiter", this, | 151 TRACE_EVENT_ASYNC_END1("ServiceWorker", "BlobFilesWaiter", this, "Success", |
| 125 "Success", phase_ == Phase::SUCCESS); | 152 phase_ == Phase::SUCCESS); |
| 126 } | 153 } |
| 127 | 154 |
| 128 void RunOnComplete(const base::Callback<void(bool)>& callback) { | 155 void RunOnComplete(base::TaskRunner* file_runner, |
| 156 const base::Callback<void(bool)>& callback) { | |
| 129 DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_)); | 157 DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_)); |
| 130 phase_ = Phase::WAITING; | 158 phase_ = Phase::WAITING; |
| 131 num_pending_request_body_blobs_ = 0; | 159 body_ = owner_->body_; |
| 132 callback_ = callback; | 160 callback_ = callback; |
| 133 | 161 |
| 134 for (const ResourceRequestBodyImpl::Element& element : | 162 bool needsFileStats = false; |
|
falken
2016/07/22 04:22:19
needs_file_stats
dmurph
2016/08/02 00:58:02
Done.
| |
| 135 *(owner_->body_->elements())) { | 163 for (const ResourceRequestBodyImpl::Element& element : *body_->elements()) { |
| 136 if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB) | 164 if (element.type() == ResourceRequestBodyImpl::Element::TYPE_FILE && |
| 137 continue; | 165 element.length() == ResourceRequestBodyImpl::Element::kUnknownSize) { |
| 138 | 166 needsFileStats = true; |
| 139 std::unique_ptr<storage::BlobDataHandle> handle = | |
| 140 owner_->blob_storage_context_->GetBlobDataFromUUID( | |
| 141 element.blob_uuid()); | |
| 142 if (handle->IsBroken()) { | |
| 143 Complete(false); | |
| 144 return; | |
| 145 } | |
| 146 if (handle->IsBeingBuilt()) { | |
| 147 ++num_pending_request_body_blobs_; | |
| 148 handle->RunOnConstructionComplete( | |
| 149 base::Bind(&BlobConstructionWaiter::OneRequestBodyBlobCompleted, | |
| 150 weak_factory_.GetWeakPtr())); | |
| 151 } | 167 } |
| 152 } | 168 } |
| 153 | 169 |
| 154 if (num_pending_request_body_blobs_ == 0) | 170 if (!needsFileStats) { |
| 155 Complete(true); | 171 Complete(true); |
| 172 return; | |
| 173 } | |
| 174 | |
| 175 PostTaskAndReplyWithResult( | |
| 176 file_runner, FROM_HERE, | |
| 177 base::Bind(&PopulateUnknownFileLengths, body_->elements_mutable()), | |
| 178 base::Bind(&ServiceWorkerURLRequestJob::BlobFilesWaiter::Complete, | |
| 179 weak_factory_.GetWeakPtr())); | |
| 156 } | 180 } |
| 157 | 181 |
| 158 private: | 182 private: |
| 159 enum class Phase { INITIAL, WAITING, SUCCESS, FAIL }; | 183 enum class Phase { INITIAL, WAITING, SUCCESS, FAIL }; |
| 160 | 184 |
| 161 void OneRequestBodyBlobCompleted( | |
| 162 bool success, | |
| 163 storage::IPCBlobCreationCancelCode cancel_code) { | |
| 164 DCHECK_GT(num_pending_request_body_blobs_, 0UL); | |
| 165 | |
| 166 if (success) | |
| 167 --num_pending_request_body_blobs_; | |
| 168 else | |
| 169 num_pending_request_body_blobs_ = 0; | |
| 170 | |
| 171 if (num_pending_request_body_blobs_ == 0) | |
| 172 Complete(success); | |
| 173 } | |
| 174 | |
| 175 void Complete(bool success) { | 185 void Complete(bool success) { |
| 176 DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_)); | 186 DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_)); |
| 177 phase_ = success ? Phase::SUCCESS : Phase::FAIL; | 187 phase_ = success ? Phase::SUCCESS : Phase::FAIL; |
| 178 // Destroys |this|. | 188 // Destroys |this|. |
| 179 callback_.Run(success); | 189 callback_.Run(success); |
| 180 } | 190 } |
| 181 | 191 |
| 182 // Owns and must outlive |this|. | 192 // Owns and must outlive |this|. |
| 183 ServiceWorkerURLRequestJob* owner_; | 193 ServiceWorkerURLRequestJob* owner_; |
| 184 | 194 |
| 185 scoped_refptr<ResourceRequestBodyImpl> body_; | 195 scoped_refptr<ResourceRequestBodyImpl> body_; |
| 186 base::Callback<void(bool)> callback_; | 196 base::Callback<void(bool)> callback_; |
| 187 size_t num_pending_request_body_blobs_ = 0; | |
| 188 Phase phase_ = Phase::INITIAL; | 197 Phase phase_ = Phase::INITIAL; |
| 189 base::WeakPtrFactory<BlobConstructionWaiter> weak_factory_; | 198 base::WeakPtrFactory<BlobFilesWaiter> weak_factory_; |
| 190 | 199 |
| 191 DISALLOW_COPY_AND_ASSIGN(BlobConstructionWaiter); | 200 DISALLOW_COPY_AND_ASSIGN(BlobFilesWaiter); |
| 192 }; | 201 }; |
| 193 | 202 |
| 194 bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid( | 203 bool ServiceWorkerURLRequestJob::Delegate::RequestStillValid( |
| 195 ServiceWorkerMetrics::URLRequestJobResult* result) { | 204 ServiceWorkerMetrics::URLRequestJobResult* result) { |
| 196 return true; | 205 return true; |
| 197 } | 206 } |
| 198 | 207 |
| 199 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( | 208 ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob( |
| 200 net::URLRequest* request, | 209 net::URLRequest* request, |
| 201 net::NetworkDelegate* network_delegate, | 210 net::NetworkDelegate* network_delegate, |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 FinalizeFallbackToNetwork(); | 525 FinalizeFallbackToNetwork(); |
| 517 return; | 526 return; |
| 518 | 527 |
| 519 case FALLBACK_TO_RENDERER: | 528 case FALLBACK_TO_RENDERER: |
| 520 FinalizeFallbackToRenderer(); | 529 FinalizeFallbackToRenderer(); |
| 521 return; | 530 return; |
| 522 | 531 |
| 523 case FORWARD_TO_SERVICE_WORKER: | 532 case FORWARD_TO_SERVICE_WORKER: |
| 524 if (HasRequestBody()) { | 533 if (HasRequestBody()) { |
| 525 DCHECK(!blob_construction_waiter_); | 534 DCHECK(!blob_construction_waiter_); |
| 526 blob_construction_waiter_.reset(new BlobConstructionWaiter(this)); | 535 blob_construction_waiter_.reset(new BlobFilesWaiter(this)); |
| 527 blob_construction_waiter_->RunOnComplete( | 536 blob_construction_waiter_->RunOnComplete( |
| 537 BrowserThread::GetBlockingPool(), | |
| 528 base::Bind(&ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted, | 538 base::Bind(&ServiceWorkerURLRequestJob::RequestBodyBlobsCompleted, |
| 529 GetWeakPtr())); | 539 GetWeakPtr())); |
| 530 return; | 540 return; |
| 531 } | 541 } |
| 532 | 542 |
| 533 RequestBodyBlobsCompleted(true); | 543 RequestBodyBlobsCompleted(true); |
| 534 return; | 544 return; |
| 535 } | 545 } |
| 536 | 546 |
| 537 NOTREACHED(); | 547 NOTREACHED(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 request->referrer = | 585 request->referrer = |
| 576 Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault); | 586 Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault); |
| 577 } | 587 } |
| 578 request->fetch_type = fetch_type_; | 588 request->fetch_type = fetch_type_; |
| 579 return request; | 589 return request; |
| 580 } | 590 } |
| 581 | 591 |
| 582 void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid, | 592 void ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid, |
| 583 uint64_t* blob_size) { | 593 uint64_t* blob_size) { |
| 584 DCHECK(HasRequestBody()); | 594 DCHECK(HasRequestBody()); |
| 585 // To ensure the blobs stick around until the end of the reading. | 595 const std::string uuid(base::GenerateGUID()); |
| 586 std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; | 596 storage::BlobDataBuilder blob_builder(uuid); |
| 587 std::vector<std::unique_ptr<storage::BlobDataSnapshot>> snapshots; | |
| 588 // TODO(dmurph): Allow blobs to be added below, so that the context can | |
| 589 // efficiently re-use blob items for the new blob. | |
| 590 std::vector<const ResourceRequestBodyImpl::Element*> resolved_elements; | |
| 591 for (const ResourceRequestBodyImpl::Element& element : (*body_->elements())) { | 597 for (const ResourceRequestBodyImpl::Element& element : (*body_->elements())) { |
| 592 if (element.type() != ResourceRequestBodyImpl::Element::TYPE_BLOB) { | 598 blob_builder.AppendIPCDataElement(element); |
| 593 resolved_elements.push_back(&element); | |
| 594 continue; | |
| 595 } | |
| 596 std::unique_ptr<storage::BlobDataHandle> handle = | |
| 597 blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid()); | |
| 598 std::unique_ptr<storage::BlobDataSnapshot> snapshot = | |
| 599 handle->CreateSnapshot(); | |
| 600 if (snapshot->items().empty()) | |
| 601 continue; | |
| 602 const auto& items = snapshot->items(); | |
| 603 for (const auto& item : items) { | |
| 604 DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type()); | |
| 605 resolved_elements.push_back(item->data_element_ptr()); | |
| 606 } | |
| 607 handles.push_back(std::move(handle)); | |
| 608 snapshots.push_back(std::move(snapshot)); | |
| 609 } | |
| 610 | |
| 611 const std::string uuid(base::GenerateGUID()); | |
| 612 uint64_t total_size = 0; | |
| 613 | |
| 614 storage::BlobDataBuilder blob_builder(uuid); | |
| 615 for (size_t i = 0; i < resolved_elements.size(); ++i) { | |
| 616 const ResourceRequestBodyImpl::Element& element = *resolved_elements[i]; | |
| 617 if (total_size != std::numeric_limits<uint64_t>::max() && | |
| 618 element.length() != std::numeric_limits<uint64_t>::max()) | |
| 619 total_size += element.length(); | |
| 620 else | |
| 621 total_size = std::numeric_limits<uint64_t>::max(); | |
|
falken
2016/07/22 04:22:19
Seems we can get rid of #include <limits> now. May
dmurph
2016/08/02 00:58:02
Done.
| |
| 622 switch (element.type()) { | |
| 623 case ResourceRequestBodyImpl::Element::TYPE_BYTES: | |
| 624 blob_builder.AppendData(element.bytes(), element.length()); | |
| 625 break; | |
| 626 case ResourceRequestBodyImpl::Element::TYPE_FILE: | |
| 627 blob_builder.AppendFile(element.path(), element.offset(), | |
| 628 element.length(), | |
| 629 element.expected_modification_time()); | |
| 630 break; | |
| 631 case ResourceRequestBodyImpl::Element::TYPE_BLOB: | |
| 632 // Blob elements should be resolved beforehand. | |
| 633 NOTREACHED(); | |
| 634 break; | |
| 635 case ResourceRequestBodyImpl::Element::TYPE_FILE_FILESYSTEM: | |
| 636 blob_builder.AppendFileSystemFile(element.filesystem_url(), | |
| 637 element.offset(), element.length(), | |
| 638 element.expected_modification_time()); | |
| 639 break; | |
| 640 default: | |
| 641 NOTIMPLEMENTED(); | |
| 642 } | |
|
falken
2016/07/22 04:22:19
nice deletion!
| |
| 643 } | 599 } |
| 644 | 600 |
| 645 request_body_blob_data_handle_ = | 601 request_body_blob_data_handle_ = |
| 646 blob_storage_context_->AddFinishedBlob(&blob_builder); | 602 blob_storage_context_->AddFinishedBlob(&blob_builder); |
| 647 *blob_uuid = uuid; | 603 *blob_uuid = uuid; |
| 648 *blob_size = total_size; | 604 *blob_size = request_body_blob_data_handle_->size(); |
| 649 } | 605 } |
| 650 | 606 |
| 651 void ServiceWorkerURLRequestJob::DidPrepareFetchEvent( | 607 void ServiceWorkerURLRequestJob::DidPrepareFetchEvent( |
| 652 scoped_refptr<ServiceWorkerVersion> version) { | 608 scoped_refptr<ServiceWorkerVersion> version) { |
| 653 worker_ready_time_ = base::TimeTicks::Now(); | 609 worker_ready_time_ = base::TimeTicks::Now(); |
| 654 load_timing_info_.send_start = worker_ready_time_; | 610 load_timing_info_.send_start = worker_ready_time_; |
| 655 | 611 |
| 656 // Record the time taken for the browser to find and possibly start an active | 612 // Record the time taken for the browser to find and possibly start an active |
| 657 // worker to which to dispatch a FetchEvent for a main frame resource request. | 613 // worker to which to dispatch a FetchEvent for a main frame resource request. |
| 658 // For context, a FetchEvent can only be dispatched to an ACTIVATED worker | 614 // For context, a FetchEvent can only be dispatched to an ACTIVATED worker |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1038 CreateFetchRequest(), active_worker, resource_type_, request()->net_log(), | 994 CreateFetchRequest(), active_worker, resource_type_, request()->net_log(), |
| 1039 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, | 995 base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent, |
| 1040 weak_factory_.GetWeakPtr(), active_worker), | 996 weak_factory_.GetWeakPtr(), active_worker), |
| 1041 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, | 997 base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent, |
| 1042 weak_factory_.GetWeakPtr()))); | 998 weak_factory_.GetWeakPtr()))); |
| 1043 worker_start_time_ = base::TimeTicks::Now(); | 999 worker_start_time_ = base::TimeTicks::Now(); |
| 1044 fetch_dispatcher_->Run(); | 1000 fetch_dispatcher_->Run(); |
| 1045 } | 1001 } |
| 1046 | 1002 |
| 1047 } // namespace content | 1003 } // namespace content |
| OLD | NEW |