 Chromium Code Reviews
 Chromium Code Reviews Issue 2843043002:
  network service: Create URLLoader for service worker navigation case
    
  
    Issue 2843043002:
  network service: Create URLLoader for service worker navigation case 
  | Index: content/browser/service_worker/service_worker_url_loader_factory_creation.cc | 
| diff --git a/content/browser/service_worker/service_worker_url_loader_factory_creation.cc b/content/browser/service_worker/service_worker_url_loader_factory_creation.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..0f6c3dc8fe6ca63088c7ffe7d317275af4b5cb5a | 
| --- /dev/null | 
| +++ b/content/browser/service_worker/service_worker_url_loader_factory_creation.cc | 
| @@ -0,0 +1,198 @@ | 
| +// Copyright 2017 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "content/browser/service_worker/service_worker_url_loader_factory_creation.h" | 
| + | 
| +#include "content/browser/service_worker/service_worker_context_wrapper.h" | 
| +#include "content/browser/service_worker/service_worker_navigation_handle_core.h" | 
| +#include "content/browser/service_worker/service_worker_provider_host.h" | 
| +#include "content/common/service_worker/service_worker_utils.h" | 
| +#include "content/common/url_loader.mojom.h" | 
| +#include "content/public/browser/browser_thread.h" | 
| +#include "content/public/common/origin_util.h" | 
| +#include "content/public/common/service_manager_connection.h" | 
| +#include "content/public/common/service_names.mojom.h" | 
| +#include "mojo/public/cpp/bindings/strong_binding.h" | 
| +#include "net/base/url_util.h" | 
| +#include "services/service_manager/public/cpp/connector.h" | 
| + | 
| +namespace content { | 
| + | 
| +namespace { | 
| + | 
| +std::unique_ptr<service_manager::Connector> GetConnector() { | 
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| + return ServiceManagerConnection::GetForProcess()->GetConnector()->Clone(); | 
| +} | 
| + | 
| +// A URLLoader implementation created by ControlleeHandlerFactory, used to serve | 
| +// requests to the document that's using a service worker. Currently simply | 
| +// proxies to the network service, rather than issuing the fetch request to the | 
| +// context provider host. | 
| +class ControlleeURLLoaderImpl : public mojom::URLLoader, | 
| + public mojom::URLLoaderClient { | 
| + public: | 
| + ControlleeURLLoaderImpl(mojom::URLLoaderAssociatedRequest loader, | 
| 
kinuko
2017/05/01 15:07:57
Someone needs to own this?
 | 
| + uint32_t options, | 
| + const ResourceRequest& request, | 
| + mojom::URLLoaderClientPtr client, | 
| + ServiceWorkerProviderHost* provider_host) | 
| + : binding_(this), client_(std::move(client)), weak_ptr_factory_(this) { | 
| + // The corresponding provider_host may already have associated a | 
| + // registration in redirect case, unassociate it now. | 
| + provider_host->DisassociateRegistration(); | 
| + | 
| + // Also prevent a register job for establishing an association to a new | 
| + // registration while we're finding an existing registration. | 
| + provider_host->SetAllowAssociation(false); | 
| + | 
| + GURL stripped_url = net::SimplifyUrlForRequest(request.url); | 
| + provider_host->SetDocumentUrl(stripped_url); | 
| + provider_host->SetTopmostFrameUrl(request.first_party_for_cookies); | 
| + | 
| + // TODO(scottmg): As an intermediate step, all requests are forwarded to the | 
| + // network service. Acquire a connector that can be used on the IO thread by | 
| + // posting to the UI thread here. | 
| + BrowserThread::PostTaskAndReplyWithResult( | 
| + BrowserThread::UI, FROM_HERE, base::Bind(&GetConnector), | 
| + base::Bind(&ControlleeURLLoaderImpl::ContinueAfterGettingConnector, | 
| + weak_ptr_factory_.GetWeakPtr(), request)); | 
| + } | 
| + | 
| + // mojom::URLLoader implementation: | 
| + void FollowRedirect() override {} | 
| + void SetPriority(net::RequestPriority priority, | 
| + int32_t intra_priority_value) override {} | 
| + | 
| + // mojom::URLLoaderClient implementation. This implementation is only required | 
| + // temporarily while this is a simple forwarder to the real network service, | 
| + // but can be removed. | 
| + void OnReceiveResponse( | 
| + const ResourceResponseHead& head, | 
| + const base::Optional<net::SSLInfo>& ssl_info, | 
| + mojom::DownloadedTempFilePtr downloaded_file) override { | 
| + client_->OnReceiveResponse(head, ssl_info, std::move(downloaded_file)); | 
| + } | 
| + void OnReceiveRedirect(const net::RedirectInfo& redirect_info, | 
| + const ResourceResponseHead& head) override {} | 
| + void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} | 
| + void OnUploadProgress(int64_t current_position, | 
| + int64_t total_size, | 
| + OnUploadProgressCallback callback) override {} | 
| + void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} | 
| + void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} | 
| + void OnStartLoadingResponseBody( | 
| + mojo::ScopedDataPipeConsumerHandle body) override { | 
| + client_->OnStartLoadingResponseBody(std::move(body)); | 
| + } | 
| + void OnComplete( | 
| + const ResourceRequestCompletionStatus& completion_status) override { | 
| + client_->OnComplete(completion_status); | 
| + } | 
| + | 
| + private: | 
| + void ContinueAfterGettingConnector( | 
| + const ResourceRequest& request, | 
| + std::unique_ptr<service_manager::Connector> connector) { | 
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| + connector->BindInterface(mojom::kNetworkServiceName, | 
| + &network_url_loader_factory_); | 
| + | 
| + mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; | 
| + binding_.Bind(&url_loader_client_ptr_to_pass); | 
| + | 
| + network_url_loader_factory_->CreateLoaderAndStart( | 
| + mojo::MakeRequest(&url_loader_associated_ptr_), 0 /* routing_id? */, | 
| + 0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, request, | 
| + std::move(url_loader_client_ptr_to_pass)); | 
| + } | 
| + | 
| + mojom::URLLoaderFactoryPtr network_url_loader_factory_; | 
| + mojom::URLLoaderAssociatedPtr url_loader_associated_ptr_; | 
| + mojo::Binding<mojom::URLLoaderClient> binding_; | 
| + mojom::URLLoaderClientPtr client_; | 
| + | 
| + std::unique_ptr<base::WeakPtrFactory<ControlleeURLLoaderImpl>> | 
| + weak_ptr_factory_ui_; | 
| + base::WeakPtrFactory<ControlleeURLLoaderImpl> weak_ptr_factory_; | 
| + | 
| + DISALLOW_COPY_AND_ASSIGN(ControlleeURLLoaderImpl); | 
| +}; | 
| + | 
| +// URLLoaderFactory implementation for the document side. | 
| +class ControlleeHandlerFactory : public mojom::URLLoaderFactory { | 
| + public: | 
| + ControlleeHandlerFactory(ServiceWorkerProviderHost* provider_host) | 
| 
kinuko
2017/05/01 02:06:24
explicit
 | 
| + : provider_host_(provider_host) {} | 
| + ~ControlleeHandlerFactory() override {} | 
| + | 
| + void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest loader, | 
| + int32_t routing_id, | 
| + int32_t request_id, | 
| + uint32_t options, | 
| + const ResourceRequest& request, | 
| + mojom::URLLoaderClientPtr client) override { | 
| + new ControlleeURLLoaderImpl(std::move(loader), options, request, | 
| + std::move(client), provider_host_); | 
| + } | 
| + | 
| + void SyncLoad(int32_t routing_id, | 
| + int32_t request_id, | 
| + const ResourceRequest& request, | 
| + SyncLoadCallback callback) override { | 
| + NOTREACHED(); | 
| + } | 
| + | 
| + private: | 
| + ServiceWorkerProviderHost* provider_host_; | 
| + | 
| + DISALLOW_COPY_AND_ASSIGN(ControlleeHandlerFactory); | 
| +}; | 
| + | 
| +} // namespace | 
| + | 
| +// static | 
| +mojom::URLLoaderFactoryPtrInfo | 
| +ServiceWorkerURLLoaderFactoryCreation::InitializeForNavigation( | 
| 
kinuko
2017/05/01 02:06:24
would be good if we could reuse some of the code i
 | 
| + const NavigationFactoryCreationData& creation_data) { | 
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| + | 
| + if (!creation_data.navigation_handle || | 
| + (!creation_data.request->url.SchemeIsHTTPOrHTTPS() && | 
| + !OriginCanAccessServiceWorkers(creation_data.request->url))) { | 
| + return mojom::URLLoaderFactoryPtrInfo(); | 
| + } | 
| + | 
| + std::unique_ptr<ServiceWorkerProviderHost> provider_host = | 
| + ServiceWorkerProviderHost::PreCreateNavigationHost( | 
| + creation_data.navigation_handle->context_wrapper() | 
| + ->context() | 
| + ->AsWeakPtr(), | 
| + creation_data.is_parent_frame_secure, | 
| + creation_data.web_contents_getter); | 
| + | 
| + // TODO(scottmg): For the time being, we always connect through our handler. | 
| + // In the future this will check if there's a SW active for this request | 
| + if (ServiceWorkerUtils::IsMainResourceType(creation_data.resource_type) || | 
| + provider_host->controlling_version()) { | 
| + mojom::URLLoaderFactoryPtr controllee; | 
| + mojo::MakeStrongBinding( | 
| + base::MakeUnique<ControlleeHandlerFactory>(provider_host.get()), | 
| + mojo::MakeRequest(&controllee)); | 
| 
kinuko
2017/05/01 15:07:57
I'm still not fully sure why we need this proxy cl
 | 
| + | 
| + // Transfer ownership to the ServiceWorkerNavigationHandleCore. | 
| + // In the case of a successful navigation, the SWProviderHost will be | 
| + // transferred to its "final" destination in the OnProviderCreated handler. | 
| + // If the navigation fails, it will be destroyed along with the | 
| + // ServiceWorkerNavigationHandleCore. | 
| + creation_data.navigation_handle->DidPreCreateProviderHost( | 
| + std::move(provider_host)); | 
| + | 
| + return controllee.PassInterface(); | 
| + } | 
| + | 
| + return mojom::URLLoaderFactoryPtrInfo(); | 
| +} | 
| + | 
| +} // namespace content |