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); |
} |
} |