Commit 11160121 authored by horo's avatar horo Committed by Commit bot

Implement FetchEvent.navigationPreload

This CL depends on https://codereview.chromium.org/2410333006/

FetchEvent.navigationPreload will be implemented in the following steps.
[1/4] Introduce FetchEventPreloadHandle to pass the preload response to FetchEvent.
      https://codereview.chromium.org/2417793002/
[2/4] Implement ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload().
      https://codereview.chromium.org/2410333006/
[3/4] Implement FetchEvent.navigationPreload.
      https://codereview.chromium.org/2416843002/ This CL.
[4/4] Add browser tests for NavigationPreload.
      https://codereview.chromium.org/2413643005/

If ServiceWorkerContextClient::FetchEventDispatcherImpl receives preload_handle,
it creates a PreloadRequest. This PreloadRequest is a mojom::URLLoaderClient
owning mojom::URLLoader.

ServiceWorkerContextClient::DispatchFetchEvent() stores the PreloadRequest to
|context_| and calls ServiceWorkerGlobalScopeProxy::dispatchFetchEvent() with
|navigationPreloadSent| flag set.

If the flag is set, ServiceWorkerGlobalScopeProxy::dispatchFetchEvent() calls
FetchEvent::createPreloadResponseCallback() to create
WebServiceWorkerPreloadResponseCallbacks and calls registerPreloadResponseCallback
to pass the callback to ServiceWorkerContextClient.

ServiceWorkerContextClient::registerPreloadResponseCallback() calls
PreloadRequest::RegisterCallback() and the callback will be called when
OnStartLoadingResponseBody() is called or OnComplete() is called with an error.

BUG=649558

Review-Url: https://codereview.chromium.org/2416843002
Cr-Commit-Position: refs/heads/master@{#427303}
parent 8eb38982
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "content/child/service_worker/web_service_worker_provider_impl.h" #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/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.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/child/webmessageportchannel_impl.h"
#include "content/common/devtools_messages.h" #include "content/common/devtools_messages.h"
#include "content/common/message_port_messages.h" #include "content/common/message_port_messages.h"
...@@ -59,6 +60,7 @@ ...@@ -59,6 +60,7 @@
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h" #include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h" #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientQueryOptions.h" #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientQueryOptions.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h" #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h" #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
#include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebDataSource.h"
...@@ -189,6 +191,9 @@ struct ServiceWorkerContextClient::WorkerContextData { ...@@ -189,6 +191,9 @@ struct ServiceWorkerContextClient::WorkerContextData {
IDMap<const base::Callback<void(ServiceWorkerStatusCode, IDMap<const base::Callback<void(ServiceWorkerStatusCode,
base::Time /* dispatch_event_time */)>, base::Time /* dispatch_event_time */)>,
IDMapOwnPointer>; IDMapOwnPointer>;
using NavigationPreloadRequestsMap =
IDMap<ServiceWorkerContextClient::NavigationPreloadRequest,
IDMapOwnPointer>;
explicit WorkerContextData(ServiceWorkerContextClient* owner) explicit WorkerContextData(ServiceWorkerContextClient* owner)
: weak_factory(owner), proxy_weak_factory(owner->proxy_) {} : weak_factory(owner), proxy_weak_factory(owner->proxy_) {}
...@@ -215,6 +220,9 @@ struct ServiceWorkerContextClient::WorkerContextData { ...@@ -215,6 +220,9 @@ struct ServiceWorkerContextClient::WorkerContextData {
// Pending callbacks for Fetch Events. // Pending callbacks for Fetch Events.
FetchEventCallbacksMap fetch_event_callbacks; FetchEventCallbacksMap fetch_event_callbacks;
// Pending navigation preload requests.
NavigationPreloadRequestsMap preload_requests;
service_manager::InterfaceRegistry interface_registry; service_manager::InterfaceRegistry interface_registry;
// This is not used when mojo for the service workers is enabled. At that // This is not used when mojo for the service workers is enabled. At that
// time, remote interfaces are stored in EmbeddedWorkerInstanceClientImpl. // time, remote interfaces are stored in EmbeddedWorkerInstanceClientImpl.
...@@ -225,6 +233,93 @@ struct ServiceWorkerContextClient::WorkerContextData { ...@@ -225,6 +233,93 @@ struct ServiceWorkerContextClient::WorkerContextData {
base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory; base::WeakPtrFactory<blink::WebServiceWorkerContextProxy> proxy_weak_factory;
}; };
class ServiceWorkerContextClient::NavigationPreloadRequest final
: public mojom::URLLoaderClient {
public:
NavigationPreloadRequest(int fetch_event_id,
const GURL& url,
mojom::FetchEventPreloadHandlePtr preload_handle)
: fetch_event_id_(fetch_event_id),
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 (result_reported_)
return;
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
if (!client)
return;
client->OnNavigationPreloadError(
fetch_event_id_,
base::MakeUnique<blink::WebServiceWorkerError>(
blink::WebServiceWorkerError::ErrorTypeAbort,
blink::WebString::fromUTF8(
"Service Worker navigation preload aborted. Need to guard with "
"respondWith or waitUntil.")));
}
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 {
DCHECK(!result_reported_);
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
if (!client)
return;
client->OnNavigationPreloadResponse(
fetch_event_id_, std::move(response_),
base::MakeUnique<WebDataConsumerHandleImpl>(std::move(body)));
result_reported_ = true;
}
void OnComplete(const ResourceRequestCompletionStatus& status) override {
// We don't report to |client| if OnStartLoadingResponseBody() has already
// called OnNavigationPreloadResponse().
if (result_reported_)
return;
DCHECK_NE(0, status.error_code);
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
if (!client)
return;
client->OnNavigationPreloadError(
fetch_event_id_,
base::MakeUnique<blink::WebServiceWorkerError>(
blink::WebServiceWorkerError::ErrorTypeNetwork,
blink::WebString::fromUTF8(
"Service Worker navigation preload network error.")));
result_reported_ = true;
}
private:
const int fetch_event_id_;
mojom::URLLoaderPtr url_loader_;
mojo::Binding<mojom::URLLoaderClient> binding_;
std::unique_ptr<blink::WebServiceWorkerResponse> response_;
bool result_reported_ = false;
};
class ServiceWorkerContextClient::FetchEventDispatcherImpl class ServiceWorkerContextClient::FetchEventDispatcherImpl
: public NON_EXPORTED_BASE(mojom::FetchEventDispatcher) { : public NON_EXPORTED_BASE(mojom::FetchEventDispatcher) {
public: public:
...@@ -247,12 +342,13 @@ class ServiceWorkerContextClient::FetchEventDispatcherImpl ...@@ -247,12 +342,13 @@ class ServiceWorkerContextClient::FetchEventDispatcherImpl
callback.Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now()); callback.Run(SERVICE_WORKER_ERROR_ABORT, base::Time::Now());
return; return;
} }
if (preload_handle) { client->DispatchFetchEvent(
// TODO(horo): Implement this to pass |preload_handle| to FetchEvent. fetch_event_id, request,
NOTIMPLEMENTED(); preload_handle
return; ? base::MakeUnique<NavigationPreloadRequest>(
} fetch_event_id, request.url, std::move(preload_handle))
client->DispatchFetchEvent(fetch_event_id, request, callback); : nullptr,
callback);
} }
private: private:
...@@ -635,6 +731,12 @@ void ServiceWorkerContextClient::didHandleFetchEvent( ...@@ -635,6 +731,12 @@ void ServiceWorkerContextClient::didHandleFetchEvent(
int fetch_event_id, int fetch_event_id,
blink::WebServiceWorkerEventResult result, blink::WebServiceWorkerEventResult result,
double event_dispatch_time) { 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 = const FetchCallback* callback =
context_->fetch_event_callbacks.Lookup(fetch_event_id); context_->fetch_event_callbacks.Lookup(fetch_event_id);
if (!callback) if (!callback)
...@@ -887,12 +989,18 @@ void ServiceWorkerContextClient::OnInstallEvent(int request_id) { ...@@ -887,12 +989,18 @@ void ServiceWorkerContextClient::OnInstallEvent(int request_id) {
void ServiceWorkerContextClient::DispatchFetchEvent( void ServiceWorkerContextClient::DispatchFetchEvent(
int fetch_event_id, int fetch_event_id,
const ServiceWorkerFetchRequest& request, const ServiceWorkerFetchRequest& request,
std::unique_ptr<NavigationPreloadRequest> preload_request,
const FetchCallback& callback) { const FetchCallback& callback) {
const bool navigation_preload_sent = !!preload_request;
blink::WebServiceWorkerRequest webRequest; blink::WebServiceWorkerRequest webRequest;
TRACE_EVENT0("ServiceWorker", TRACE_EVENT0("ServiceWorker",
"ServiceWorkerContextClient::DispatchFetchEvent"); "ServiceWorkerContextClient::DispatchFetchEvent");
context_->fetch_event_callbacks.AddWithID(new FetchCallback(callback), context_->fetch_event_callbacks.AddWithID(new FetchCallback(callback),
fetch_event_id); fetch_event_id);
if (preload_request) {
context_->preload_requests.AddWithID(std::move(preload_request),
fetch_event_id);
}
webRequest.setURL(blink::WebURL(request.url)); webRequest.setURL(blink::WebURL(request.url));
webRequest.setMethod(blink::WebString::fromUTF8(request.method)); webRequest.setMethod(blink::WebString::fromUTF8(request.method));
...@@ -922,7 +1030,8 @@ void ServiceWorkerContextClient::DispatchFetchEvent( ...@@ -922,7 +1030,8 @@ void ServiceWorkerContextClient::DispatchFetchEvent(
if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) { if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) {
proxy_->dispatchForeignFetchEvent(fetch_event_id, webRequest); proxy_->dispatchForeignFetchEvent(fetch_event_id, webRequest);
} else { } else {
proxy_->dispatchFetchEvent(fetch_event_id, webRequest); proxy_->dispatchFetchEvent(fetch_event_id, webRequest,
navigation_preload_sent);
} }
} }
...@@ -1149,6 +1258,20 @@ void ServiceWorkerContextClient::OnPing() { ...@@ -1149,6 +1258,20 @@ void ServiceWorkerContextClient::OnPing() {
Send(new ServiceWorkerHostMsg_Pong(GetRoutingID())); Send(new ServiceWorkerHostMsg_Pong(GetRoutingID()));
} }
void ServiceWorkerContextClient::OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerResponse> response,
std::unique_ptr<blink::WebDataConsumerHandle> data_consumer_handle) {
proxy_->onNavigationPreloadResponse(fetch_event_id, std::move(response),
std::move(data_consumer_handle));
}
void ServiceWorkerContextClient::OnNavigationPreloadError(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerError> error) {
proxy_->onNavigationPreloadError(fetch_event_id, std::move(error));
}
base::WeakPtr<ServiceWorkerContextClient> base::WeakPtr<ServiceWorkerContextClient>
ServiceWorkerContextClient::GetWeakPtr() { ServiceWorkerContextClient::GetWeakPtr() {
DCHECK(worker_task_runner_->RunsTasksOnCurrentThread()); DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
......
...@@ -39,10 +39,12 @@ class TaskRunner; ...@@ -39,10 +39,12 @@ class TaskRunner;
} }
namespace blink { namespace blink {
class WebDataConsumerHandle;
class WebDataSource; class WebDataSource;
struct WebServiceWorkerClientQueryOptions; struct WebServiceWorkerClientQueryOptions;
class WebServiceWorkerContextProxy; class WebServiceWorkerContextProxy;
class WebServiceWorkerProvider; class WebServiceWorkerProvider;
class WebServiceWorkerResponse;
struct WebSyncRegistration; struct WebSyncRegistration;
} }
...@@ -202,6 +204,7 @@ class ServiceWorkerContextClient ...@@ -202,6 +204,7 @@ class ServiceWorkerContextClient
private: private:
struct WorkerContextData; struct WorkerContextData;
class FetchEventDispatcherImpl; class FetchEventDispatcherImpl;
class NavigationPreloadRequest;
// Get routing_id for sending message to the ServiceWorkerVersion // Get routing_id for sending message to the ServiceWorkerVersion
// in the browser process. // in the browser process.
...@@ -218,9 +221,11 @@ class ServiceWorkerContextClient ...@@ -218,9 +221,11 @@ class ServiceWorkerContextClient
int request_id, int request_id,
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params); const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEvent(int request_id); void OnInstallEvent(int request_id);
void DispatchFetchEvent(int fetch_event_id, void DispatchFetchEvent(
const ServiceWorkerFetchRequest& request, int fetch_event_id,
const FetchCallback& callback); const ServiceWorkerFetchRequest& request,
std::unique_ptr<NavigationPreloadRequest> preload_request,
const FetchCallback& callback);
void OnNotificationClickEvent( void OnNotificationClickEvent(
int request_id, int request_id,
const std::string& notification_id, const std::string& notification_id,
...@@ -251,6 +256,14 @@ class ServiceWorkerContextClient ...@@ -251,6 +256,14 @@ class ServiceWorkerContextClient
const base::string16& message); const base::string16& message);
void OnPing(); void OnPing();
void OnNavigationPreloadResponse(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerResponse> response,
std::unique_ptr<blink::WebDataConsumerHandle> data_consumer_handle);
void OnNavigationPreloadError(
int fetch_event_id,
std::unique_ptr<blink::WebServiceWorkerError> error);
base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr(); base::WeakPtr<ServiceWorkerContextClient> GetWeakPtr();
const int embedded_worker_id_; const int embedded_worker_id_;
......
...@@ -197,6 +197,7 @@ interface ExtendableMessageEvent : ExtendableEvent ...@@ -197,6 +197,7 @@ interface ExtendableMessageEvent : ExtendableEvent
interface FetchEvent : ExtendableEvent interface FetchEvent : ExtendableEvent
getter clientId getter clientId
getter isReload getter isReload
getter navigationPreload
getter request getter request
method constructor method constructor
method respondWith method respondWith
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
P(Finished##__VA_ARGS__) \ P(Finished##__VA_ARGS__) \
P(Loaded##__VA_ARGS__) \ P(Loaded##__VA_ARGS__) \
P(Released##__VA_ARGS__) \ P(Released##__VA_ARGS__) \
P(UserChoice##__VA_ARGS__) P(UserChoice##__VA_ARGS__) \
P(PreloadResponse##__VA_ARGS__)
#endif // ScriptPromiseProperties_h #endif // ScriptPromiseProperties_h
...@@ -4,10 +4,17 @@ ...@@ -4,10 +4,17 @@
#include "modules/serviceworkers/FetchEvent.h" #include "modules/serviceworkers/FetchEvent.h"
#include "bindings/core/v8/ScriptState.h"
#include "bindings/core/v8/ToV8.h" #include "bindings/core/v8/ToV8.h"
#include "bindings/core/v8/V8HiddenValue.h" #include "bindings/core/v8/V8HiddenValue.h"
#include "modules/fetch/BytesConsumerForDataConsumerHandle.h"
#include "modules/fetch/Request.h" #include "modules/fetch/Request.h"
#include "modules/fetch/Response.h"
#include "modules/serviceworkers/ServiceWorkerError.h"
#include "modules/serviceworkers/ServiceWorkerGlobalScope.h" #include "modules/serviceworkers/ServiceWorkerGlobalScope.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
#include "wtf/PtrUtil.h"
#include "wtf/RefPtr.h" #include "wtf/RefPtr.h"
namespace blink { namespace blink {
...@@ -15,16 +22,18 @@ namespace blink { ...@@ -15,16 +22,18 @@ namespace blink {
FetchEvent* FetchEvent::create(ScriptState* scriptState, FetchEvent* FetchEvent::create(ScriptState* scriptState,
const AtomicString& type, const AtomicString& type,
const FetchEventInit& initializer) { const FetchEventInit& initializer) {
return new FetchEvent(scriptState, type, initializer, nullptr, nullptr); return new FetchEvent(scriptState, type, initializer, nullptr, nullptr,
false);
} }
FetchEvent* FetchEvent::create(ScriptState* scriptState, FetchEvent* FetchEvent::create(ScriptState* scriptState,
const AtomicString& type, const AtomicString& type,
const FetchEventInit& initializer, const FetchEventInit& initializer,
RespondWithObserver* respondWithObserver, RespondWithObserver* respondWithObserver,
WaitUntilObserver* waitUntilObserver) { WaitUntilObserver* waitUntilObserver,
bool navigationPreloadSent) {
return new FetchEvent(scriptState, type, initializer, respondWithObserver, return new FetchEvent(scriptState, type, initializer, respondWithObserver,
waitUntilObserver); waitUntilObserver, navigationPreloadSent);
} }
Request* FetchEvent::request() const { Request* FetchEvent::request() const {
...@@ -47,6 +56,10 @@ void FetchEvent::respondWith(ScriptState* scriptState, ...@@ -47,6 +56,10 @@ void FetchEvent::respondWith(ScriptState* scriptState,
m_observer->respondWith(scriptState, scriptPromise, exceptionState); m_observer->respondWith(scriptState, scriptPromise, exceptionState);
} }
ScriptPromise FetchEvent::navigationPreload(ScriptState* scriptState) {
return m_navigationPreloadProperty->promise(scriptState->world());
}
const AtomicString& FetchEvent::interfaceName() const { const AtomicString& FetchEvent::interfaceName() const {
return EventNames::FetchEvent; return EventNames::FetchEvent;
} }
...@@ -55,9 +68,21 @@ FetchEvent::FetchEvent(ScriptState* scriptState, ...@@ -55,9 +68,21 @@ FetchEvent::FetchEvent(ScriptState* scriptState,
const AtomicString& type, const AtomicString& type,
const FetchEventInit& initializer, const FetchEventInit& initializer,
RespondWithObserver* respondWithObserver, RespondWithObserver* respondWithObserver,
WaitUntilObserver* waitUntilObserver) WaitUntilObserver* waitUntilObserver,
bool navigationPreloadSent)
: ExtendableEvent(type, initializer, waitUntilObserver), : ExtendableEvent(type, initializer, waitUntilObserver),
m_observer(respondWithObserver) { m_scriptState(scriptState),
m_observer(respondWithObserver),
m_navigationPreloadProperty(new PreloadResponseProperty(
scriptState->getExecutionContext(),
this,
PreloadResponseProperty::PreloadResponse)) {
if (!navigationPreloadSent) {
// TODO(horo): This behavior is still under the spec discussion.
// https://github.com/w3c/ServiceWorker/issues/920#issuecomment-255874864
m_navigationPreloadProperty->resolve(nullptr);
}
m_clientId = initializer.clientId(); m_clientId = initializer.clientId();
m_isReload = initializer.isReload(); m_isReload = initializer.isReload();
if (initializer.hasRequest()) { if (initializer.hasRequest()) {
...@@ -84,9 +109,43 @@ FetchEvent::FetchEvent(ScriptState* scriptState, ...@@ -84,9 +109,43 @@ FetchEvent::FetchEvent(ScriptState* scriptState,
} }
} }
void FetchEvent::onNavigationPreloadResponse(
std::unique_ptr<WebServiceWorkerResponse> response,
std::unique_ptr<WebDataConsumerHandle> dataConsumeHandle) {
if (!m_scriptState->contextIsValid())
return;
DCHECK(m_navigationPreloadProperty);
ScriptState::Scope scope(m_scriptState.get());
FetchResponseData* responseData =
FetchResponseData::createWithBuffer(new BodyStreamBuffer(
m_scriptState.get(), new BytesConsumerForDataConsumerHandle(
m_scriptState->getExecutionContext(),
std::move(dataConsumeHandle))));
responseData->setURL(response->url());
responseData->setStatus(response->status());
responseData->setStatusMessage(response->statusText());
responseData->setResponseTime(response->responseTime());
for (const auto& header : response->headers())
responseData->headerList()->append(header.key, header.value);
FetchResponseData* taintedResponse =
responseData->createBasicFilteredResponse();
m_navigationPreloadProperty->resolve(
Response::create(m_scriptState->getExecutionContext(), taintedResponse));
}
void FetchEvent::onNavigationPreloadError(
std::unique_ptr<WebServiceWorkerError> error) {
if (!m_scriptState->contextIsValid())
return;
DCHECK(m_navigationPreloadProperty);
m_navigationPreloadProperty->reject(
ServiceWorkerError::take(nullptr, *error.get()));
}
DEFINE_TRACE(FetchEvent) { DEFINE_TRACE(FetchEvent) {
visitor->trace(m_observer); visitor->trace(m_observer);
visitor->trace(m_request); visitor->trace(m_request);
visitor->trace(m_navigationPreloadProperty);
ExtendableEvent::trace(visitor); ExtendableEvent::trace(visitor);
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define FetchEvent_h #define FetchEvent_h
#include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseProperty.h"
#include "modules/EventModules.h" #include "modules/EventModules.h"
#include "modules/ModulesExport.h" #include "modules/ModulesExport.h"
#include "modules/fetch/Request.h" #include "modules/fetch/Request.h"
...@@ -19,7 +20,12 @@ namespace blink { ...@@ -19,7 +20,12 @@ namespace blink {
class ExceptionState; class ExceptionState;
class Request; class Request;
class Response;
class RespondWithObserver; class RespondWithObserver;
class ScriptState;
class WebDataConsumerHandle;
struct WebServiceWorkerError;
class WebServiceWorkerResponse;
// A fetch event is dispatched by the client to a service worker's script // A fetch event is dispatched by the client to a service worker's script
// context. RespondWithObserver can be used to notify the client about the // context. RespondWithObserver can be used to notify the client about the
...@@ -28,6 +34,9 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent { ...@@ -28,6 +34,9 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
using PreloadResponseProperty = ScriptPromiseProperty<Member<FetchEvent>,
Member<Response>,
Member<DOMException>>;
static FetchEvent* create(ScriptState*, static FetchEvent* create(ScriptState*,
const AtomicString& type, const AtomicString& type,
const FetchEventInit&); const FetchEventInit&);
...@@ -35,13 +44,19 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent { ...@@ -35,13 +44,19 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
const AtomicString& type, const AtomicString& type,
const FetchEventInit&, const FetchEventInit&,
RespondWithObserver*, RespondWithObserver*,
WaitUntilObserver*); WaitUntilObserver*,
bool navigationPreloadSent);
Request* request() const; Request* request() const;
String clientId() const; String clientId() const;
bool isReload() const; bool isReload() const;
void respondWith(ScriptState*, ScriptPromise, ExceptionState&); void respondWith(ScriptState*, ScriptPromise, ExceptionState&);
ScriptPromise navigationPreload(ScriptState*);
void onNavigationPreloadResponse(std::unique_ptr<WebServiceWorkerResponse>,
std::unique_ptr<WebDataConsumerHandle>);
void onNavigationPreloadError(std::unique_ptr<WebServiceWorkerError>);
const AtomicString& interfaceName() const override; const AtomicString& interfaceName() const override;
...@@ -52,11 +67,14 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent { ...@@ -52,11 +67,14 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
const AtomicString& type, const AtomicString& type,
const FetchEventInit&, const FetchEventInit&,
RespondWithObserver*, RespondWithObserver*,
WaitUntilObserver*); WaitUntilObserver*,
bool navigationPreloadSent);
private: private:
RefPtr<ScriptState> m_scriptState;
Member<RespondWithObserver> m_observer; Member<RespondWithObserver> m_observer;
Member<Request> m_request; Member<Request> m_request;
Member<PreloadResponseProperty> m_navigationPreloadProperty;
String m_clientId; String m_clientId;
bool m_isReload; bool m_isReload;
}; };
......
...@@ -13,4 +13,5 @@ ...@@ -13,4 +13,5 @@
readonly attribute boolean isReload; readonly attribute boolean isReload;
[CallWith=ScriptState, RaisesException] void respondWith(Promise<Response> r); [CallWith=ScriptState, RaisesException] void respondWith(Promise<Response> r);
[RuntimeEnabled=ServiceWorkerNavigationPreload, CallWith=ScriptState] readonly attribute Promise<Response> navigationPreload;
}; };
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include "public/platform/modules/notifications/WebNotificationData.h" #include "public/platform/modules/notifications/WebNotificationData.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerEventResult.h" #include "public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerRequest.h" #include "public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
#include "public/web/WebSerializedScriptValue.h" #include "public/web/WebSerializedScriptValue.h"
#include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h" #include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
#include "web/WebEmbeddedWorkerImpl.h" #include "web/WebEmbeddedWorkerImpl.h"
...@@ -85,6 +86,7 @@ ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() { ...@@ -85,6 +86,7 @@ ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() {
DEFINE_TRACE(ServiceWorkerGlobalScopeProxy) { DEFINE_TRACE(ServiceWorkerGlobalScopeProxy) {
visitor->trace(m_document); visitor->trace(m_document);
visitor->trace(m_pendingPreloadFetchEvents);
} }
void ServiceWorkerGlobalScopeProxy::setRegistration( void ServiceWorkerGlobalScopeProxy::setRegistration(
...@@ -151,7 +153,8 @@ void ServiceWorkerGlobalScopeProxy::dispatchExtendableMessageEvent( ...@@ -151,7 +153,8 @@ void ServiceWorkerGlobalScopeProxy::dispatchExtendableMessageEvent(
void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent( void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
int fetchEventID, int fetchEventID,
const WebServiceWorkerRequest& webRequest) { const WebServiceWorkerRequest& webRequest,
bool navigationPreloadSent) {
ScriptState::Scope scope( ScriptState::Scope scope(
workerGlobalScope()->scriptController()->getScriptState()); workerGlobalScope()->scriptController()->getScriptState());
WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create( WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(
...@@ -168,9 +171,16 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent( ...@@ -168,9 +171,16 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
eventInit.setClientId( eventInit.setClientId(
webRequest.isMainResourceLoad() ? WebString() : webRequest.clientId()); webRequest.isMainResourceLoad() ? WebString() : webRequest.clientId());
eventInit.setIsReload(webRequest.isReload()); eventInit.setIsReload(webRequest.isReload());
ScriptState* scriptState =
workerGlobalScope()->scriptController()->getScriptState();
FetchEvent* fetchEvent = FetchEvent::create( FetchEvent* fetchEvent = FetchEvent::create(
workerGlobalScope()->scriptController()->getScriptState(), scriptState, EventTypeNames::fetch, eventInit, respondWithObserver,
EventTypeNames::fetch, eventInit, respondWithObserver, waitUntilObserver); waitUntilObserver, navigationPreloadSent);
if (navigationPreloadSent) {
// Keep |fetchEvent| until onNavigationPreloadResponse() or
// onNavigationPreloadError() will be called.
m_pendingPreloadFetchEvents.add(fetchEventID, fetchEvent);
}
waitUntilObserver->willDispatchEvent(); waitUntilObserver->willDispatchEvent();
respondWithObserver->willDispatchEvent(); respondWithObserver->willDispatchEvent();
DispatchEventResult dispatchResult = DispatchEventResult dispatchResult =
...@@ -181,6 +191,24 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent( ...@@ -181,6 +191,24 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
waitUntilObserver->didDispatchEvent(false /* errorOccurred */); waitUntilObserver->didDispatchEvent(false /* errorOccurred */);
} }
void ServiceWorkerGlobalScopeProxy::onNavigationPreloadResponse(
int fetchEventID,
std::unique_ptr<WebServiceWorkerResponse> response,
std::unique_ptr<WebDataConsumerHandle> dataConsumeHandle) {
FetchEvent* fetchEvent = m_pendingPreloadFetchEvents.take(fetchEventID);
DCHECK(fetchEvent);
fetchEvent->onNavigationPreloadResponse(std::move(response),
std::move(dataConsumeHandle));
}
void ServiceWorkerGlobalScopeProxy::onNavigationPreloadError(
int fetchEventID,
std::unique_ptr<WebServiceWorkerError> error) {
FetchEvent* fetchEvent = m_pendingPreloadFetchEvents.take(fetchEventID);
DCHECK(fetchEvent);
fetchEvent->onNavigationPreloadError(std::move(error));
}
void ServiceWorkerGlobalScopeProxy::dispatchForeignFetchEvent( void ServiceWorkerGlobalScopeProxy::dispatchForeignFetchEvent(
int fetchEventID, int fetchEventID,
const WebServiceWorkerRequest& webRequest) { const WebServiceWorkerRequest& webRequest) {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "core/workers/WorkerReportingProxy.h" #include "core/workers/WorkerReportingProxy.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
#include "platform/heap/HeapAllocator.h"
#include "platform/weborigin/KURL.h" #include "platform/weborigin/KURL.h"
#include "public/platform/WebString.h" #include "public/platform/WebString.h"
#include "public/web/modules/serviceworker/WebServiceWorkerContextProxy.h" #include "public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
...@@ -43,10 +44,14 @@ namespace blink { ...@@ -43,10 +44,14 @@ namespace blink {
class ConsoleMessage; class ConsoleMessage;
class Document; class Document;
class FetchEvent;
class ServiceWorkerGlobalScope; class ServiceWorkerGlobalScope;
class WebDataConsumerHandle;
class WebEmbeddedWorkerImpl; class WebEmbeddedWorkerImpl;
class WebServiceWorkerContextClient; class WebServiceWorkerContextClient;
struct WebServiceWorkerError;
class WebServiceWorkerRequest; class WebServiceWorkerRequest;
class WebServiceWorkerResponse;
// This class is created and destructed on the main thread, but live most // This class is created and destructed on the main thread, but live most
// of its time as a resident of the worker thread. // of its time as a resident of the worker thread.
...@@ -89,7 +94,8 @@ class ServiceWorkerGlobalScopeProxy final ...@@ -89,7 +94,8 @@ class ServiceWorkerGlobalScopeProxy final
const WebMessagePortChannelArray&, const WebMessagePortChannelArray&,
std::unique_ptr<WebServiceWorker::Handle>) override; std::unique_ptr<WebServiceWorker::Handle>) override;
void dispatchFetchEvent(int fetchEventID, void dispatchFetchEvent(int fetchEventID,
const WebServiceWorkerRequest&) override; const WebServiceWorkerRequest&,
bool navigationPreloadSent) override;
void dispatchForeignFetchEvent(int fetchEventID, void dispatchForeignFetchEvent(int fetchEventID,
const WebServiceWorkerRequest&) override; const WebServiceWorkerRequest&) override;
void dispatchInstallEvent(int) override; void dispatchInstallEvent(int) override;
...@@ -104,6 +110,13 @@ class ServiceWorkerGlobalScopeProxy final ...@@ -104,6 +110,13 @@ class ServiceWorkerGlobalScopeProxy final
void dispatchPushEvent(int, const WebString& data) override; void dispatchPushEvent(int, const WebString& data) override;
void dispatchSyncEvent(int, const WebString& tag, LastChanceOption) override; void dispatchSyncEvent(int, const WebString& tag, LastChanceOption) override;
bool hasFetchEventHandler() override; bool hasFetchEventHandler() override;
void onNavigationPreloadResponse(
int fetchEventID,
std::unique_ptr<WebServiceWorkerResponse>,
std::unique_ptr<WebDataConsumerHandle>) override;
void onNavigationPreloadError(
int fetchEventID,
std::unique_ptr<WebServiceWorkerError>) override;
// WorkerReportingProxy overrides: // WorkerReportingProxy overrides:
void reportException(const String& errorMessage, void reportException(const String& errorMessage,
...@@ -148,6 +161,8 @@ class ServiceWorkerGlobalScopeProxy final ...@@ -148,6 +161,8 @@ class ServiceWorkerGlobalScopeProxy final
WebEmbeddedWorkerImpl* m_embeddedWorker; WebEmbeddedWorkerImpl* m_embeddedWorker;
Member<Document> m_document; Member<Document> m_document;
HeapHashMap<int, Member<FetchEvent>> m_pendingPreloadFetchEvents;
WebServiceWorkerContextClient* m_client; WebServiceWorkerContextClient* m_client;
CrossThreadPersistent<ServiceWorkerGlobalScope> m_workerGlobalScope; CrossThreadPersistent<ServiceWorkerGlobalScope> m_workerGlobalScope;
......
...@@ -39,10 +39,13 @@ ...@@ -39,10 +39,13 @@
namespace blink { namespace blink {
class WebDataConsumerHandle;
class WebServiceWorkerRequest; class WebServiceWorkerRequest;
class WebServiceWorkerResponse;
class WebString; class WebString;
struct WebNotificationData; struct WebNotificationData;
struct WebServiceWorkerClientInfo; struct WebServiceWorkerClientInfo;
struct WebServiceWorkerError;
// A proxy interface to talk to the worker's GlobalScope implementation. // A proxy interface to talk to the worker's GlobalScope implementation.
// All methods of this class must be called on the worker thread. // All methods of this class must be called on the worker thread.
...@@ -67,9 +70,9 @@ class WebServiceWorkerContextProxy { ...@@ -67,9 +70,9 @@ class WebServiceWorkerContextProxy {
const WebMessagePortChannelArray&, const WebMessagePortChannelArray&,
std::unique_ptr<WebServiceWorker::Handle>) = 0; std::unique_ptr<WebServiceWorker::Handle>) = 0;
virtual void dispatchInstallEvent(int eventID) = 0; virtual void dispatchInstallEvent(int eventID) = 0;
virtual void dispatchFetchEvent( virtual void dispatchFetchEvent(int fetchEventID,
int fetchEventID, const WebServiceWorkerRequest& webRequest,
const WebServiceWorkerRequest& webRequest) = 0; bool navigationPreloadSent) = 0;
virtual void dispatchForeignFetchEvent( virtual void dispatchForeignFetchEvent(
int fetchEventID, int fetchEventID,
const WebServiceWorkerRequest& webRequest) = 0; const WebServiceWorkerRequest& webRequest) = 0;
...@@ -92,6 +95,14 @@ class WebServiceWorkerContextProxy { ...@@ -92,6 +95,14 @@ class WebServiceWorkerContextProxy {
virtual void dispatchSyncEvent(int syncEventID, virtual void dispatchSyncEvent(int syncEventID,
const WebString& tag, const WebString& tag,
LastChanceOption) = 0; LastChanceOption) = 0;
virtual void onNavigationPreloadResponse(
int fetchEventID,
std::unique_ptr<WebServiceWorkerResponse>,
std::unique_ptr<WebDataConsumerHandle>) = 0;
virtual void onNavigationPreloadError(
int fetchEventID,
std::unique_ptr<WebServiceWorkerError>) = 0;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment