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}
This commit is contained in:
content/renderer/service_worker
third_party/WebKit
LayoutTests
virtual
service-worker-navigation-preload
http
tests
serviceworker
Source
bindings
modules
serviceworkers
web
public
web
modules
serviceworker
@@ -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"
|
||||
@@ -59,6 +60,7 @@
|
||||
#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/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/WebServiceWorkerResponse.h"
|
||||
#include "third_party/WebKit/public/web/WebDataSource.h"
|
||||
@@ -189,6 +191,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 +220,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 +233,93 @@ struct ServiceWorkerContextClient::WorkerContextData {
|
||||
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
|
||||
: public NON_EXPORTED_BASE(mojom::FetchEventDispatcher) {
|
||||
public:
|
||||
@@ -247,12 +342,13 @@ 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>(
|
||||
fetch_event_id, request.url, std::move(preload_handle))
|
||||
: nullptr,
|
||||
callback);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -635,6 +731,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)
|
||||
@@ -887,12 +989,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 +1030,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1149,6 +1258,20 @@ void ServiceWorkerContextClient::OnPing() {
|
||||
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>
|
||||
ServiceWorkerContextClient::GetWeakPtr() {
|
||||
DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
|
||||
|
@@ -39,10 +39,12 @@ class TaskRunner;
|
||||
}
|
||||
|
||||
namespace blink {
|
||||
class WebDataConsumerHandle;
|
||||
class WebDataSource;
|
||||
struct WebServiceWorkerClientQueryOptions;
|
||||
class WebServiceWorkerContextProxy;
|
||||
class WebServiceWorkerProvider;
|
||||
class WebServiceWorkerResponse;
|
||||
struct WebSyncRegistration;
|
||||
}
|
||||
|
||||
@@ -202,6 +204,7 @@ class ServiceWorkerContextClient
|
||||
private:
|
||||
struct WorkerContextData;
|
||||
class FetchEventDispatcherImpl;
|
||||
class NavigationPreloadRequest;
|
||||
|
||||
// Get routing_id for sending message to the ServiceWorkerVersion
|
||||
// in the browser process.
|
||||
@@ -218,9 +221,11 @@ class ServiceWorkerContextClient
|
||||
int request_id,
|
||||
const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
|
||||
void OnInstallEvent(int request_id);
|
||||
void DispatchFetchEvent(int fetch_event_id,
|
||||
const ServiceWorkerFetchRequest& request,
|
||||
const FetchCallback& callback);
|
||||
void DispatchFetchEvent(
|
||||
int fetch_event_id,
|
||||
const ServiceWorkerFetchRequest& request,
|
||||
std::unique_ptr<NavigationPreloadRequest> preload_request,
|
||||
const FetchCallback& callback);
|
||||
void OnNotificationClickEvent(
|
||||
int request_id,
|
||||
const std::string& notification_id,
|
||||
@@ -251,6 +256,14 @@ class ServiceWorkerContextClient
|
||||
const base::string16& message);
|
||||
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();
|
||||
|
||||
const int embedded_worker_id_;
|
||||
|
@@ -197,6 +197,7 @@ interface ExtendableMessageEvent : ExtendableEvent
|
||||
interface FetchEvent : ExtendableEvent
|
||||
getter clientId
|
||||
getter isReload
|
||||
getter navigationPreload
|
||||
getter request
|
||||
method constructor
|
||||
method respondWith
|
||||
|
@@ -12,6 +12,7 @@
|
||||
P(Finished##__VA_ARGS__) \
|
||||
P(Loaded##__VA_ARGS__) \
|
||||
P(Released##__VA_ARGS__) \
|
||||
P(UserChoice##__VA_ARGS__)
|
||||
P(UserChoice##__VA_ARGS__) \
|
||||
P(PreloadResponse##__VA_ARGS__)
|
||||
|
||||
#endif // ScriptPromiseProperties_h
|
||||
|
@@ -4,10 +4,17 @@
|
||||
|
||||
#include "modules/serviceworkers/FetchEvent.h"
|
||||
|
||||
#include "bindings/core/v8/ScriptState.h"
|
||||
#include "bindings/core/v8/ToV8.h"
|
||||
#include "bindings/core/v8/V8HiddenValue.h"
|
||||
#include "modules/fetch/BytesConsumerForDataConsumerHandle.h"
|
||||
#include "modules/fetch/Request.h"
|
||||
#include "modules/fetch/Response.h"
|
||||
#include "modules/serviceworkers/ServiceWorkerError.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"
|
||||
|
||||
namespace blink {
|
||||
@@ -15,16 +22,18 @@ namespace blink {
|
||||
FetchEvent* FetchEvent::create(ScriptState* scriptState,
|
||||
const AtomicString& type,
|
||||
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,
|
||||
const AtomicString& type,
|
||||
const FetchEventInit& initializer,
|
||||
RespondWithObserver* respondWithObserver,
|
||||
WaitUntilObserver* waitUntilObserver) {
|
||||
WaitUntilObserver* waitUntilObserver,
|
||||
bool navigationPreloadSent) {
|
||||
return new FetchEvent(scriptState, type, initializer, respondWithObserver,
|
||||
waitUntilObserver);
|
||||
waitUntilObserver, navigationPreloadSent);
|
||||
}
|
||||
|
||||
Request* FetchEvent::request() const {
|
||||
@@ -47,6 +56,10 @@ void FetchEvent::respondWith(ScriptState* scriptState,
|
||||
m_observer->respondWith(scriptState, scriptPromise, exceptionState);
|
||||
}
|
||||
|
||||
ScriptPromise FetchEvent::navigationPreload(ScriptState* scriptState) {
|
||||
return m_navigationPreloadProperty->promise(scriptState->world());
|
||||
}
|
||||
|
||||
const AtomicString& FetchEvent::interfaceName() const {
|
||||
return EventNames::FetchEvent;
|
||||
}
|
||||
@@ -55,9 +68,21 @@ FetchEvent::FetchEvent(ScriptState* scriptState,
|
||||
const AtomicString& type,
|
||||
const FetchEventInit& initializer,
|
||||
RespondWithObserver* respondWithObserver,
|
||||
WaitUntilObserver* waitUntilObserver)
|
||||
WaitUntilObserver* waitUntilObserver,
|
||||
bool navigationPreloadSent)
|
||||
: 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_isReload = initializer.isReload();
|
||||
if (initializer.hasRequest()) {
|
||||
@@ -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) {
|
||||
visitor->trace(m_observer);
|
||||
visitor->trace(m_request);
|
||||
visitor->trace(m_navigationPreloadProperty);
|
||||
ExtendableEvent::trace(visitor);
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#define FetchEvent_h
|
||||
|
||||
#include "bindings/core/v8/ScriptPromise.h"
|
||||
#include "bindings/core/v8/ScriptPromiseProperty.h"
|
||||
#include "modules/EventModules.h"
|
||||
#include "modules/ModulesExport.h"
|
||||
#include "modules/fetch/Request.h"
|
||||
@@ -19,7 +20,12 @@ namespace blink {
|
||||
|
||||
class ExceptionState;
|
||||
class Request;
|
||||
class Response;
|
||||
class RespondWithObserver;
|
||||
class ScriptState;
|
||||
class WebDataConsumerHandle;
|
||||
struct WebServiceWorkerError;
|
||||
class WebServiceWorkerResponse;
|
||||
|
||||
// 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
|
||||
@@ -28,6 +34,9 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
|
||||
public:
|
||||
using PreloadResponseProperty = ScriptPromiseProperty<Member<FetchEvent>,
|
||||
Member<Response>,
|
||||
Member<DOMException>>;
|
||||
static FetchEvent* create(ScriptState*,
|
||||
const AtomicString& type,
|
||||
const FetchEventInit&);
|
||||
@@ -35,13 +44,19 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
|
||||
const AtomicString& type,
|
||||
const FetchEventInit&,
|
||||
RespondWithObserver*,
|
||||
WaitUntilObserver*);
|
||||
WaitUntilObserver*,
|
||||
bool navigationPreloadSent);
|
||||
|
||||
Request* request() const;
|
||||
String clientId() const;
|
||||
bool isReload() const;
|
||||
|
||||
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;
|
||||
|
||||
@@ -52,11 +67,14 @@ class MODULES_EXPORT FetchEvent final : public ExtendableEvent {
|
||||
const AtomicString& type,
|
||||
const FetchEventInit&,
|
||||
RespondWithObserver*,
|
||||
WaitUntilObserver*);
|
||||
WaitUntilObserver*,
|
||||
bool navigationPreloadSent);
|
||||
|
||||
private:
|
||||
RefPtr<ScriptState> m_scriptState;
|
||||
Member<RespondWithObserver> m_observer;
|
||||
Member<Request> m_request;
|
||||
Member<PreloadResponseProperty> m_navigationPreloadProperty;
|
||||
String m_clientId;
|
||||
bool m_isReload;
|
||||
};
|
||||
|
@@ -13,4 +13,5 @@
|
||||
readonly attribute boolean isReload;
|
||||
|
||||
[CallWith=ScriptState, RaisesException] void respondWith(Promise<Response> r);
|
||||
[RuntimeEnabled=ServiceWorkerNavigationPreload, CallWith=ScriptState] readonly attribute Promise<Response> navigationPreload;
|
||||
};
|
||||
|
@@ -60,6 +60,7 @@
|
||||
#include "public/platform/modules/notifications/WebNotificationData.h"
|
||||
#include "public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
|
||||
#include "public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
|
||||
#include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
|
||||
#include "public/web/WebSerializedScriptValue.h"
|
||||
#include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
|
||||
#include "web/WebEmbeddedWorkerImpl.h"
|
||||
@@ -85,6 +86,7 @@ ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() {
|
||||
|
||||
DEFINE_TRACE(ServiceWorkerGlobalScopeProxy) {
|
||||
visitor->trace(m_document);
|
||||
visitor->trace(m_pendingPreloadFetchEvents);
|
||||
}
|
||||
|
||||
void ServiceWorkerGlobalScopeProxy::setRegistration(
|
||||
@@ -151,7 +153,8 @@ void ServiceWorkerGlobalScopeProxy::dispatchExtendableMessageEvent(
|
||||
|
||||
void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
|
||||
int fetchEventID,
|
||||
const WebServiceWorkerRequest& webRequest) {
|
||||
const WebServiceWorkerRequest& webRequest,
|
||||
bool navigationPreloadSent) {
|
||||
ScriptState::Scope scope(
|
||||
workerGlobalScope()->scriptController()->getScriptState());
|
||||
WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(
|
||||
@@ -168,9 +171,16 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
|
||||
eventInit.setClientId(
|
||||
webRequest.isMainResourceLoad() ? WebString() : webRequest.clientId());
|
||||
eventInit.setIsReload(webRequest.isReload());
|
||||
ScriptState* scriptState =
|
||||
workerGlobalScope()->scriptController()->getScriptState();
|
||||
FetchEvent* fetchEvent = FetchEvent::create(
|
||||
workerGlobalScope()->scriptController()->getScriptState(),
|
||||
EventTypeNames::fetch, eventInit, respondWithObserver, waitUntilObserver);
|
||||
scriptState, EventTypeNames::fetch, eventInit, respondWithObserver,
|
||||
waitUntilObserver, navigationPreloadSent);
|
||||
if (navigationPreloadSent) {
|
||||
// Keep |fetchEvent| until onNavigationPreloadResponse() or
|
||||
// onNavigationPreloadError() will be called.
|
||||
m_pendingPreloadFetchEvents.add(fetchEventID, fetchEvent);
|
||||
}
|
||||
waitUntilObserver->willDispatchEvent();
|
||||
respondWithObserver->willDispatchEvent();
|
||||
DispatchEventResult dispatchResult =
|
||||
@@ -181,6 +191,24 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(
|
||||
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(
|
||||
int fetchEventID,
|
||||
const WebServiceWorkerRequest& webRequest) {
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "core/workers/WorkerReportingProxy.h"
|
||||
#include "platform/heap/Handle.h"
|
||||
#include "platform/heap/HeapAllocator.h"
|
||||
#include "platform/weborigin/KURL.h"
|
||||
#include "public/platform/WebString.h"
|
||||
#include "public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
|
||||
@@ -43,10 +44,14 @@ namespace blink {
|
||||
|
||||
class ConsoleMessage;
|
||||
class Document;
|
||||
class FetchEvent;
|
||||
class ServiceWorkerGlobalScope;
|
||||
class WebDataConsumerHandle;
|
||||
class WebEmbeddedWorkerImpl;
|
||||
class WebServiceWorkerContextClient;
|
||||
struct WebServiceWorkerError;
|
||||
class WebServiceWorkerRequest;
|
||||
class WebServiceWorkerResponse;
|
||||
|
||||
// This class is created and destructed on the main thread, but live most
|
||||
// of its time as a resident of the worker thread.
|
||||
@@ -89,7 +94,8 @@ class ServiceWorkerGlobalScopeProxy final
|
||||
const WebMessagePortChannelArray&,
|
||||
std::unique_ptr<WebServiceWorker::Handle>) override;
|
||||
void dispatchFetchEvent(int fetchEventID,
|
||||
const WebServiceWorkerRequest&) override;
|
||||
const WebServiceWorkerRequest&,
|
||||
bool navigationPreloadSent) override;
|
||||
void dispatchForeignFetchEvent(int fetchEventID,
|
||||
const WebServiceWorkerRequest&) override;
|
||||
void dispatchInstallEvent(int) override;
|
||||
@@ -104,6 +110,13 @@ class ServiceWorkerGlobalScopeProxy final
|
||||
void dispatchPushEvent(int, const WebString& data) override;
|
||||
void dispatchSyncEvent(int, const WebString& tag, LastChanceOption) 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:
|
||||
void reportException(const String& errorMessage,
|
||||
@@ -148,6 +161,8 @@ class ServiceWorkerGlobalScopeProxy final
|
||||
WebEmbeddedWorkerImpl* m_embeddedWorker;
|
||||
Member<Document> m_document;
|
||||
|
||||
HeapHashMap<int, Member<FetchEvent>> m_pendingPreloadFetchEvents;
|
||||
|
||||
WebServiceWorkerContextClient* m_client;
|
||||
|
||||
CrossThreadPersistent<ServiceWorkerGlobalScope> m_workerGlobalScope;
|
||||
|
@@ -39,10 +39,13 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
class WebDataConsumerHandle;
|
||||
class WebServiceWorkerRequest;
|
||||
class WebServiceWorkerResponse;
|
||||
class WebString;
|
||||
struct WebNotificationData;
|
||||
struct WebServiceWorkerClientInfo;
|
||||
struct WebServiceWorkerError;
|
||||
|
||||
// A proxy interface to talk to the worker's GlobalScope implementation.
|
||||
// All methods of this class must be called on the worker thread.
|
||||
@@ -67,9 +70,9 @@ class WebServiceWorkerContextProxy {
|
||||
const WebMessagePortChannelArray&,
|
||||
std::unique_ptr<WebServiceWorker::Handle>) = 0;
|
||||
virtual void dispatchInstallEvent(int eventID) = 0;
|
||||
virtual void dispatchFetchEvent(
|
||||
int fetchEventID,
|
||||
const WebServiceWorkerRequest& webRequest) = 0;
|
||||
virtual void dispatchFetchEvent(int fetchEventID,
|
||||
const WebServiceWorkerRequest& webRequest,
|
||||
bool navigationPreloadSent) = 0;
|
||||
virtual void dispatchForeignFetchEvent(
|
||||
int fetchEventID,
|
||||
const WebServiceWorkerRequest& webRequest) = 0;
|
||||
@@ -92,6 +95,14 @@ class WebServiceWorkerContextProxy {
|
||||
virtual void dispatchSyncEvent(int syncEventID,
|
||||
const WebString& tag,
|
||||
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
|
||||
|
Reference in New Issue
Block a user