Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(415)

Side by Side Diff: content/browser/service_worker/service_worker_url_request_job.cc

Issue 2055053003: [BlobAsync] Disk support for blob storage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed layout tests, cleaned up test visibility Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698