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

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

Issue 2645493002: Increase the lifetime of Navigation Preload related objects. (Closed)
Patch Set: Keep the URL loader related assetsalive while the FetchEvent is onging. Created 3 years, 11 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_fetch_dispatcher.h" 5 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader); 68 DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader);
69 }; 69 };
70 70
71 // This class wraps a mojo::InterfacePtr<URLLoaderClient>. It also is a 71 // This class wraps a mojo::InterfacePtr<URLLoaderClient>. It also is a
72 // URLLoaderClient implementation and delegates URLLoaderClient calls to the 72 // URLLoaderClient implementation and delegates URLLoaderClient calls to the
73 // wrapped client. 73 // wrapped client.
74 class DelegatingURLLoaderClient final : public mojom::URLLoaderClient { 74 class DelegatingURLLoaderClient final : public mojom::URLLoaderClient {
75 public: 75 public:
76 explicit DelegatingURLLoaderClient(mojom::URLLoaderClientPtr client) 76 explicit DelegatingURLLoaderClient(mojom::URLLoaderClientPtr client)
77 : binding_(this), client_(std::move(client)) {} 77 : binding_(this), client_(std::move(client)) {}
78 ~DelegatingURLLoaderClient() override {} 78 ~DelegatingURLLoaderClient() override {
79 if (!completed_) {
80 // Let the service worker know that the request has been canceled.
81 ResourceRequestCompletionStatus status;
82 status.error_code = net::ERR_ABORTED;
83 client_->OnComplete(status);
84 }
85 }
79 86
80 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override { 87 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {
81 client_->OnDataDownloaded(data_length, encoded_length); 88 client_->OnDataDownloaded(data_length, encoded_length);
82 } 89 }
83 void OnTransferSizeUpdated(int32_t transfer_size_diff) override { 90 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {
84 client_->OnTransferSizeUpdated(transfer_size_diff); 91 client_->OnTransferSizeUpdated(transfer_size_diff);
85 } 92 }
86 void OnReceiveResponse( 93 void OnReceiveResponse(
87 const ResourceResponseHead& head, 94 const ResourceResponseHead& head,
88 mojom::DownloadedTempFilePtr downloaded_file) override { 95 mojom::DownloadedTempFilePtr downloaded_file) override {
89 client_->OnReceiveResponse(head, std::move(downloaded_file)); 96 client_->OnReceiveResponse(head, std::move(downloaded_file));
90 } 97 }
91 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, 98 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
92 const ResourceResponseHead& head) override { 99 const ResourceResponseHead& head) override {
93 client_->OnReceiveRedirect(redirect_info, head); 100 client_->OnReceiveRedirect(redirect_info, head);
94 } 101 }
95 void OnStartLoadingResponseBody( 102 void OnStartLoadingResponseBody(
96 mojo::ScopedDataPipeConsumerHandle body) override { 103 mojo::ScopedDataPipeConsumerHandle body) override {
97 client_->OnStartLoadingResponseBody(std::move(body)); 104 client_->OnStartLoadingResponseBody(std::move(body));
98 } 105 }
99 void OnComplete( 106 void OnComplete(
100 const ResourceRequestCompletionStatus& completion_status) override { 107 const ResourceRequestCompletionStatus& completion_status) override {
101 client_->OnComplete(completion_status); 108 client_->OnComplete(completion_status);
109 completed_ = true;
102 } 110 }
103 111
104 void Bind(mojom::URLLoaderClientAssociatedPtrInfo* ptr_info, 112 void Bind(mojom::URLLoaderClientAssociatedPtrInfo* ptr_info,
105 mojo::AssociatedGroup* associated_group) { 113 mojo::AssociatedGroup* associated_group) {
106 binding_.Bind(ptr_info, associated_group); 114 binding_.Bind(ptr_info, associated_group);
107 } 115 }
108 116
109 private: 117 private:
110 mojo::AssociatedBinding<mojom::URLLoaderClient> binding_; 118 mojo::AssociatedBinding<mojom::URLLoaderClient> binding_;
111 mojom::URLLoaderClientPtr client_; 119 mojom::URLLoaderClientPtr client_;
120 bool completed_ = false;
112 121
113 DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoaderClient); 122 DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoaderClient);
114 }; 123 };
115 124
116 using EventType = ServiceWorkerMetrics::EventType; 125 using EventType = ServiceWorkerMetrics::EventType;
117 EventType ResourceTypeToEventType(ResourceType resource_type) { 126 EventType ResourceTypeToEventType(ResourceType resource_type) {
118 switch (resource_type) { 127 switch (resource_type) {
119 case RESOURCE_TYPE_MAIN_FRAME: 128 case RESOURCE_TYPE_MAIN_FRAME:
120 return EventType::FETCH_MAIN_FRAME; 129 return EventType::FETCH_MAIN_FRAME;
121 case RESOURCE_TYPE_SUB_FRAME: 130 case RESOURCE_TYPE_SUB_FRAME:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 base::Bind(&NetLogServiceWorkerStatusCallback, status)); 166 base::Bind(&NetLogServiceWorkerStatusCallback, status));
158 } 167 }
159 168
160 ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType( 169 ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType(
161 ServiceWorkerFetchType type) { 170 ServiceWorkerFetchType type) {
162 if (type == ServiceWorkerFetchType::FOREIGN_FETCH) 171 if (type == ServiceWorkerFetchType::FOREIGN_FETCH)
163 return ServiceWorkerMetrics::EventType::FOREIGN_FETCH_WAITUNTIL; 172 return ServiceWorkerMetrics::EventType::FOREIGN_FETCH_WAITUNTIL;
164 return ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL; 173 return ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL;
165 } 174 }
166 175
167 void OnFetchEventFinished(
168 ServiceWorkerVersion* version,
169 int event_finish_id,
170 mojom::URLLoaderFactoryPtr url_loader_factory,
171 std::unique_ptr<mojom::URLLoader> url_loader,
172 std::unique_ptr<mojom::URLLoaderClient> url_loader_client,
173 ServiceWorkerStatusCode status,
174 base::Time dispatch_event_time) {
175 version->FinishRequest(event_finish_id, status != SERVICE_WORKER_ERROR_ABORT,
176 dispatch_event_time);
177 }
178
179 } // namespace 176 } // namespace
180 177
181 // Helper to receive the fetch event response even if 178 // Helper to receive the fetch event response even if
182 // ServiceWorkerFetchDispatcher has been destroyed. 179 // ServiceWorkerFetchDispatcher has been destroyed.
183 class ServiceWorkerFetchDispatcher::ResponseCallback { 180 class ServiceWorkerFetchDispatcher::ResponseCallback {
184 public: 181 public:
185 ResponseCallback(base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher, 182 ResponseCallback(base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
186 ServiceWorkerVersion* version) 183 ServiceWorkerVersion* version)
187 : fetch_dispatcher_(fetch_dispatcher), version_(version) {} 184 : fetch_dispatcher_(fetch_dispatcher), version_(version) {}
188 185
(...skipping 12 matching lines...) Expand all
201 } 198 }
202 199
203 private: 200 private:
204 base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_; 201 base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
205 // Owns |this|. 202 // Owns |this|.
206 ServiceWorkerVersion* version_; 203 ServiceWorkerVersion* version_;
207 204
208 DISALLOW_COPY_AND_ASSIGN(ResponseCallback); 205 DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
209 }; 206 };
210 207
208 // This class keeps the URL loader related assets alive while the FetchEvent is
209 // onging in the service worker.
210 class ServiceWorkerFetchDispatcher::URLLoaderAssets
211 : public base::RefCounted<ServiceWorkerFetchDispatcher::URLLoaderAssets> {
212 public:
213 URLLoaderAssets(mojom::URLLoaderFactoryPtr url_loader_factory,
214 std::unique_ptr<mojom::URLLoader> url_loader,
215 std::unique_ptr<mojom::URLLoaderClient> url_loader_client)
216 : url_loader_factory_(std::move(url_loader_factory)),
217 url_loader_(std::move(url_loader)),
218 url_loader_client_(std::move(url_loader_client)) {}
219
220 private:
221 friend class base::RefCounted<URLLoaderAssets>;
222 virtual ~URLLoaderAssets() {}
223
224 mojom::URLLoaderFactoryPtr url_loader_factory_;
225 std::unique_ptr<mojom::URLLoader> url_loader_;
226 std::unique_ptr<mojom::URLLoaderClient> url_loader_client_;
227
228 DISALLOW_COPY_AND_ASSIGN(URLLoaderAssets);
229 };
230
211 ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher( 231 ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
212 std::unique_ptr<ServiceWorkerFetchRequest> request, 232 std::unique_ptr<ServiceWorkerFetchRequest> request,
213 ServiceWorkerVersion* version, 233 ServiceWorkerVersion* version,
214 ResourceType resource_type, 234 ResourceType resource_type,
215 const base::Optional<base::TimeDelta>& timeout, 235 const base::Optional<base::TimeDelta>& timeout,
216 const net::NetLogWithSource& net_log, 236 const net::NetLogWithSource& net_log,
217 const base::Closure& prepare_callback, 237 const base::Closure& prepare_callback,
218 const FetchCallback& fetch_callback) 238 const FetchCallback& fetch_callback)
219 : version_(version), 239 : version_(version),
220 net_log_(net_log), 240 net_log_(net_log),
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 345
326 ResponseCallback* response_callback = 346 ResponseCallback* response_callback =
327 new ResponseCallback(weak_factory_.GetWeakPtr(), version_.get()); 347 new ResponseCallback(weak_factory_.GetWeakPtr(), version_.get());
328 version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>( 348 version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>(
329 fetch_event_id, 349 fetch_event_id,
330 base::Bind(&ServiceWorkerFetchDispatcher::ResponseCallback::Run, 350 base::Bind(&ServiceWorkerFetchDispatcher::ResponseCallback::Run,
331 base::Owned(response_callback))); 351 base::Owned(response_callback)));
332 352
333 // |event_dispatcher| is owned by |version_|. So it is safe to pass the 353 // |event_dispatcher| is owned by |version_|. So it is safe to pass the
334 // unretained raw pointer of |version_| to OnFetchEventFinished callback. 354 // unretained raw pointer of |version_| to OnFetchEventFinished callback.
335 // Pass |url_loader_factory_|, |url_Loader_| and |url_loader_client_| to the 355 // Pass |url_loader_assets_| to the callback to keep the URL loader related
336 // callback to keep them alive while the FetchEvent is onging in the service 356 // assets alive while the FetchEvent is onging in the service worker.
falken 2017/01/19 05:26:47 ongoing
horo 2017/01/19 05:48:57 Done.
337 // worker.
338 version_->event_dispatcher()->DispatchFetchEvent( 357 version_->event_dispatcher()->DispatchFetchEvent(
339 fetch_event_id, *request_, std::move(preload_handle_), 358 fetch_event_id, *request_, std::move(preload_handle_),
340 base::Bind(&OnFetchEventFinished, base::Unretained(version_.get()), 359 base::Bind(&ServiceWorkerFetchDispatcher::OnFetchEventFinished,
341 event_finish_id, base::Passed(std::move(url_loader_factory_)), 360 base::Unretained(version_.get()), event_finish_id,
342 base::Passed(std::move(url_loader_)), 361 url_loader_assets_));
343 base::Passed(std::move(url_loader_client_))));
344 } 362 }
345 363
346 void ServiceWorkerFetchDispatcher::DidFailToDispatch( 364 void ServiceWorkerFetchDispatcher::DidFailToDispatch(
347 ServiceWorkerStatusCode status) { 365 ServiceWorkerStatusCode status) {
348 EndNetLogEventWithServiceWorkerStatus( 366 EndNetLogEventWithServiceWorkerStatus(
349 net_log_, net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT, status); 367 net_log_, net::NetLogEventType::SERVICE_WORKER_FETCH_EVENT, status);
350 DidFail(status); 368 DidFail(status);
351 } 369 }
352 370
353 void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) { 371 void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
(...skipping 19 matching lines...) Expand all
373 did_complete_ = true; 391 did_complete_ = true;
374 net_log_.EndEvent( 392 net_log_.EndEvent(
375 net::NetLogEventType::SERVICE_WORKER_DISPATCH_FETCH_EVENT, 393 net::NetLogEventType::SERVICE_WORKER_DISPATCH_FETCH_EVENT,
376 base::Bind(&NetLogFetchEventCallback, status, fetch_result)); 394 base::Bind(&NetLogFetchEventCallback, status, fetch_result));
377 395
378 FetchCallback fetch_callback = fetch_callback_; 396 FetchCallback fetch_callback = fetch_callback_;
379 scoped_refptr<ServiceWorkerVersion> version = version_; 397 scoped_refptr<ServiceWorkerVersion> version = version_;
380 fetch_callback.Run(status, fetch_result, response, version); 398 fetch_callback.Run(status, fetch_result, response, version);
381 } 399 }
382 400
383 void ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload( 401 bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
384 net::URLRequest* original_request) { 402 net::URLRequest* original_request) {
385 if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME && 403 if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME &&
386 resource_type_ != RESOURCE_TYPE_SUB_FRAME) { 404 resource_type_ != RESOURCE_TYPE_SUB_FRAME) {
387 return; 405 return false;
388 } 406 }
389 if (!version_->navigation_preload_state().enabled) 407 if (!version_->navigation_preload_state().enabled)
390 return; 408 return false;
391 // TODO(horo): Currently NavigationPreload doesn't support request body. 409 // TODO(horo): Currently NavigationPreload doesn't support request body.
392 if (!request_->blob_uuid.empty()) 410 if (!request_->blob_uuid.empty())
393 return; 411 return false;
394 412
395 ServiceWorkerVersion::NavigationPreloadSupportStatus support_status = 413 ServiceWorkerVersion::NavigationPreloadSupportStatus support_status =
396 version_->GetNavigationPreloadSupportStatus(); 414 version_->GetNavigationPreloadSupportStatus();
397 if (support_status != 415 if (support_status !=
398 ServiceWorkerVersion::NavigationPreloadSupportStatus::SUPPORTED) { 416 ServiceWorkerVersion::NavigationPreloadSupportStatus::SUPPORTED) {
399 return; 417 return false;
400 } 418 }
401 419
402 ResourceRequestInfoImpl* original_info = 420 ResourceRequestInfoImpl* original_info =
403 ResourceRequestInfoImpl::ForRequest(original_request); 421 ResourceRequestInfoImpl::ForRequest(original_request);
404 ResourceRequesterInfo* requester_info = original_info->requester_info(); 422 ResourceRequesterInfo* requester_info = original_info->requester_info();
405 if (IsBrowserSideNavigationEnabled()) { 423 if (IsBrowserSideNavigationEnabled()) {
406 DCHECK(requester_info->IsBrowserSideNavigation()); 424 DCHECK(requester_info->IsBrowserSideNavigation());
407 } else { 425 } else {
408 DCHECK(requester_info->IsRenderer()); 426 DCHECK(requester_info->IsRenderer());
409 if (!requester_info->filter()) 427 if (!requester_info->filter())
410 return; 428 return false;
411 } 429 }
412 430
413 DCHECK(!url_loader_factory_); 431 DCHECK(!url_loader_assets_);
414 mojom::URLLoaderFactoryPtr factory; 432
433 mojom::URLLoaderFactoryPtr url_loader_factory;
415 URLLoaderFactoryImpl::Create( 434 URLLoaderFactoryImpl::Create(
416 ResourceRequesterInfo::CreateForNavigationPreload(requester_info), 435 ResourceRequesterInfo::CreateForNavigationPreload(requester_info),
417 mojo::MakeRequest(&url_loader_factory_)); 436 mojo::MakeRequest(&url_loader_factory));
418 437
419 preload_handle_ = mojom::FetchEventPreloadHandle::New(); 438 preload_handle_ = mojom::FetchEventPreloadHandle::New();
420 439
421 ResourceRequest request; 440 ResourceRequest request;
422 request.method = original_request->method(); 441 request.method = original_request->method();
423 request.url = original_request->url(); 442 request.url = original_request->url();
424 // TODO(horo): Set first_party_for_cookies to support Same-site Cookies. 443 // TODO(horo): Set first_party_for_cookies to support Same-site Cookies.
425 request.request_initiator = original_request->initiator().has_value() 444 request.request_initiator = original_request->initiator().has_value()
426 ? original_request->initiator() 445 ? original_request->initiator()
427 : url::Origin(original_request->url()); 446 : url::Origin(original_request->url());
(...skipping 22 matching lines...) Expand all
450 DCHECK_LT(request_id, -1); 469 DCHECK_LT(request_id, -1);
451 470
452 preload_handle_ = mojom::FetchEventPreloadHandle::New(); 471 preload_handle_ = mojom::FetchEventPreloadHandle::New();
453 mojom::URLLoaderClientPtr url_loader_client_ptr; 472 mojom::URLLoaderClientPtr url_loader_client_ptr;
454 preload_handle_->url_loader_client_request = 473 preload_handle_->url_loader_client_request =
455 mojo::MakeRequest(&url_loader_client_ptr); 474 mojo::MakeRequest(&url_loader_client_ptr);
456 auto url_loader_client = base::MakeUnique<DelegatingURLLoaderClient>( 475 auto url_loader_client = base::MakeUnique<DelegatingURLLoaderClient>(
457 std::move(url_loader_client_ptr)); 476 std::move(url_loader_client_ptr));
458 mojom::URLLoaderClientAssociatedPtrInfo url_loader_client_associated_ptr_info; 477 mojom::URLLoaderClientAssociatedPtrInfo url_loader_client_associated_ptr_info;
459 url_loader_client->Bind(&url_loader_client_associated_ptr_info, 478 url_loader_client->Bind(&url_loader_client_associated_ptr_info,
460 url_loader_factory_.associated_group()); 479 url_loader_factory.associated_group());
461 mojom::URLLoaderAssociatedPtr url_loader_associated_ptr; 480 mojom::URLLoaderAssociatedPtr url_loader_associated_ptr;
462 481
463 url_loader_factory_->CreateLoaderAndStart( 482 url_loader_factory->CreateLoaderAndStart(
464 mojo::MakeRequest(&url_loader_associated_ptr, 483 mojo::MakeRequest(&url_loader_associated_ptr,
465 url_loader_factory_.associated_group()), 484 url_loader_factory.associated_group()),
466 original_info->GetRouteID(), request_id, request, 485 original_info->GetRouteID(), request_id, request,
467 std::move(url_loader_client_associated_ptr_info)); 486 std::move(url_loader_client_associated_ptr_info));
468 487
469 std::unique_ptr<DelegatingURLLoader> url_loader( 488 std::unique_ptr<DelegatingURLLoader> url_loader(
470 new DelegatingURLLoader(std::move(url_loader_associated_ptr))); 489 new DelegatingURLLoader(std::move(url_loader_associated_ptr)));
falken 2017/01/19 05:26:46 nit: this could be MakeUnique(std::move())
horo 2017/01/19 05:48:57 Done.
471 preload_handle_->url_loader = url_loader->CreateInterfacePtrAndBind(); 490 preload_handle_->url_loader = url_loader->CreateInterfacePtrAndBind();
472 url_loader_ = std::move(url_loader); 491
473 url_loader_client_ = std::move(url_loader_client); 492 url_loader_assets_ =
493 new URLLoaderAssets(std::move(url_loader_factory), std::move(url_loader),
494 std::move(url_loader_client));
falken 2017/01/19 05:26:47 nit MakeUnique
horo 2017/01/19 05:48:57 It's not a unique_ptr.
495
496 return true;
474 } 497 }
475 498
476 ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType() 499 ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()
477 const { 500 const {
478 if (request_->fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) 501 if (request_->fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH)
479 return ServiceWorkerMetrics::EventType::FOREIGN_FETCH; 502 return ServiceWorkerMetrics::EventType::FOREIGN_FETCH;
480 return ResourceTypeToEventType(resource_type_); 503 return ResourceTypeToEventType(resource_type_);
481 } 504 }
482 505
506 // static
507 void ServiceWorkerFetchDispatcher::OnFetchEventFinished(
508 ServiceWorkerVersion* version,
509 int event_finish_id,
510 scoped_refptr<URLLoaderAssets> url_loader_assets,
511 ServiceWorkerStatusCode status,
512 base::Time dispatch_event_time) {
513 version->FinishRequest(event_finish_id, status != SERVICE_WORKER_ERROR_ABORT,
514 dispatch_event_time);
515 }
516
483 } // namespace content 517 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698