Chromium Code Reviews| Index: content/renderer/service_worker/service_worker_context_client.cc |
| diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc |
| index b4167723f70b9cf6ce9005eb2ccfdf4ca4553647..59f0cf5154e95834f60b4a767f29ef40fd23a472 100644 |
| --- a/content/renderer/service_worker/service_worker_context_client.cc |
| +++ b/content/renderer/service_worker/service_worker_context_client.cc |
| @@ -27,6 +27,7 @@ |
| #include "content/child/service_worker/web_service_worker_provider_impl.h" |
| #include "content/child/service_worker/web_service_worker_registration_impl.h" |
| #include "content/child/thread_safe_sender.h" |
| +#include "content/child/web_data_consumer_handle_impl.h" |
| #include "content/child/webmessageportchannel_impl.h" |
| #include "content/common/devtools_messages.h" |
| #include "content/common/message_port_messages.h" |
| @@ -189,6 +190,9 @@ struct ServiceWorkerContextClient::WorkerContextData { |
| IDMap<const base::Callback<void(ServiceWorkerStatusCode, |
| base::Time /* dispatch_event_time */)>, |
| IDMapOwnPointer>; |
| + using NavigationPreloadRequestsMap = |
| + IDMap<ServiceWorkerContextClient::NavigationPreloadRequest, |
| + IDMapOwnPointer>; |
| explicit WorkerContextData(ServiceWorkerContextClient* owner) |
| : weak_factory(owner), proxy_weak_factory(owner->proxy_) {} |
| @@ -215,6 +219,9 @@ struct ServiceWorkerContextClient::WorkerContextData { |
| // Pending callbacks for Fetch Events. |
| FetchEventCallbacksMap fetch_event_callbacks; |
| + // Pending navigation preload requests. |
| + NavigationPreloadRequestsMap preload_requests; |
| + |
| service_manager::InterfaceRegistry interface_registry; |
| // This is not used when mojo for the service workers is enabled. At that |
| // time, remote interfaces are stored in EmbeddedWorkerInstanceClientImpl. |
| @@ -225,6 +232,82 @@ struct ServiceWorkerContextClient::WorkerContextData { |
| base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory; |
| }; |
| +class ServiceWorkerContextClient::NavigationPreloadRequest final |
| + : public mojom::URLLoaderClient { |
| + public: |
| + NavigationPreloadRequest(const GURL& url, |
| + mojom::FetchEventPreloadHandlePtr preload_handle) |
| + : url_loader_(std::move(preload_handle->url_loader)), |
| + binding_(this, std::move(preload_handle->url_loader_client_request)), |
| + response_(base::MakeUnique<blink::WebServiceWorkerResponse>()) { |
| + response_->setURL(url); |
| + } |
| + |
| + ~NavigationPreloadRequest() override { |
| + if (callback_) { |
| + callback_->onError(blink::WebServiceWorkerError( |
| + blink::WebServiceWorkerError::ErrorTypeAbort, |
| + blink::WebString::fromUTF8( |
| + "Service Worker navigation preload aborted. Need to guard with " |
| + "respondWith or waitUntil."))); |
| + } |
| + } |
| + |
| + void RegisterCallback( |
| + std::unique_ptr<blink::WebServiceWorkerPreloadResponseCallbacks> |
| + callback) { |
| + callback_ = std::move(callback); |
| + } |
| + |
| + void OnReceiveResponse(const ResourceResponseHead& response_head) override { |
| + DCHECK(response_); |
| + DCHECK(response_head.headers); |
| + response_->setStatus(response_head.headers->response_code()); |
| + response_->setStatusText( |
| + blink::WebString::fromUTF8(response_head.headers->GetStatusText())); |
| + response_->setResponseType(blink::WebServiceWorkerResponseTypeBasic); |
| + size_t iter = 0; |
| + std::string header_name; |
| + std::string header_value; |
| + while (response_head.headers->EnumerateHeaderLines(&iter, &header_name, |
| + &header_value)) { |
| + response_->appendHeader(blink::WebString::fromUTF8(header_name), |
| + blink::WebString::fromUTF8(header_value)); |
| + } |
| + response_->setResponseTime(response_head.response_time.ToInternalValue()); |
| + } |
| + |
| + void OnStartLoadingResponseBody( |
| + mojo::ScopedDataPipeConsumerHandle body) override { |
| + std::unique_ptr<blink::WebServiceWorkerPreloadResponseCallbacks> callback( |
| + std::move(callback_)); |
| + DCHECK(callback); |
| + blink::WebServiceWorkerPreloadResponseCallbacksResult result; |
| + result.handle = |
| + base::MakeUnique<WebDataConsumerHandleImpl>(std::move(body)); |
| + result.response = std::move(response_); |
| + callback->onSuccess(&result); |
| + } |
| + |
| + void OnComplete(const ResourceRequestCompletionStatus& status) override { |
| + if (!callback_) |
|
dcheng
2016/10/21 06:44:23
Just to help me understand: why does this need to
horo
2016/10/21 10:56:39
If an error happens before receiving the HTTP resp
|
| + return; |
| + DCHECK_NE(0, status.error_code); |
| + std::unique_ptr<blink::WebServiceWorkerPreloadResponseCallbacks> callback( |
| + std::move(callback_)); |
| + callback->onError(blink::WebServiceWorkerError( |
| + blink::WebServiceWorkerError::ErrorTypeNetwork, |
| + blink::WebString::fromUTF8( |
| + "Service Worker navigation preload network error."))); |
| + } |
| + |
| + private: |
| + mojom::URLLoaderPtr url_loader_; |
| + mojo::Binding<mojom::URLLoaderClient> binding_; |
| + std::unique_ptr<blink::WebServiceWorkerResponse> response_; |
| + std::unique_ptr<blink::WebServiceWorkerPreloadResponseCallbacks> callback_; |
| +}; |
| + |
| class ServiceWorkerContextClient::FetchEventDispatcherImpl |
| : public NON_EXPORTED_BASE(mojom::FetchEventDispatcher) { |
| public: |
| @@ -247,12 +330,12 @@ class ServiceWorkerContextClient::FetchEventDispatcherImpl |
| callback.Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now()); |
| return; |
| } |
| - if (preload_handle) { |
| - // TODO(horo): Implement this to pass |preload_handle| to FetchEvent. |
| - NOTIMPLEMENTED(); |
| - return; |
| - } |
| - client->DispatchFetchEvent(fetch_event_id, request, callback); |
| + client->DispatchFetchEvent(fetch_event_id, request, |
| + preload_handle |
| + ? base::MakeUnique<NavigationPreloadRequest>( |
| + request.url, std::move(preload_handle)) |
| + : nullptr, |
| + callback); |
| } |
| private: |
| @@ -635,6 +718,12 @@ void ServiceWorkerContextClient::didHandleFetchEvent( |
| int fetch_event_id, |
| blink::WebServiceWorkerEventResult result, |
| double event_dispatch_time) { |
| + if (context_->preload_requests.Lookup(fetch_event_id)) { |
| + // Deletes NavigationPreloadRequest. If the network request is ongoing, it |
| + // will be canceled by deleting the mojom::URLLoaderPtr in the |
| + // NavigationPreloadRequest. |
| + context_->preload_requests.Remove(fetch_event_id); |
| + } |
| const FetchCallback* callback = |
| context_->fetch_event_callbacks.Lookup(fetch_event_id); |
| if (!callback) |
| @@ -797,6 +886,14 @@ void ServiceWorkerContextClient::registerForeignFetchScopes( |
| std::vector<url::Origin>(origins.begin(), origins.end()))); |
| } |
| +void ServiceWorkerContextClient::registerPreloadResponseCallback( |
| + int eventID, |
| + std::unique_ptr<blink::WebServiceWorkerPreloadResponseCallbacks> callback) { |
| + ServiceWorkerContextClient::NavigationPreloadRequest* preload_request = |
| + context_->preload_requests.Lookup(eventID); |
| + preload_request->RegisterCallback(std::move(callback)); |
| +} |
| + |
| void ServiceWorkerContextClient::DispatchSyncEvent( |
| const std::string& tag, |
| blink::WebServiceWorkerContextProxy::LastChanceOption last_chance, |
| @@ -887,12 +984,18 @@ void ServiceWorkerContextClient::OnInstallEvent(int request_id) { |
| void ServiceWorkerContextClient::DispatchFetchEvent( |
| int fetch_event_id, |
| const ServiceWorkerFetchRequest& request, |
| + std::unique_ptr<NavigationPreloadRequest> preload_request, |
| const FetchCallback& callback) { |
| + const bool navigation_preload_sent = !!preload_request; |
| blink::WebServiceWorkerRequest webRequest; |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerContextClient::DispatchFetchEvent"); |
| context_->fetch_event_callbacks.AddWithID(new FetchCallback(callback), |
| fetch_event_id); |
| + if (preload_request) { |
| + context_->preload_requests.AddWithID(std::move(preload_request), |
| + fetch_event_id); |
| + } |
| webRequest.setURL(blink::WebURL(request.url)); |
| webRequest.setMethod(blink::WebString::fromUTF8(request.method)); |
| @@ -922,7 +1025,8 @@ void ServiceWorkerContextClient::DispatchFetchEvent( |
| if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) { |
| proxy_->dispatchForeignFetchEvent(fetch_event_id, webRequest); |
| } else { |
| - proxy_->dispatchFetchEvent(fetch_event_id, webRequest); |
| + proxy_->dispatchFetchEvent(fetch_event_id, webRequest, |
| + navigation_preload_sent); |
| } |
| } |