Chromium Code Reviews| 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 |