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 |