service worker: Implement NavigationPreloadManager.getState
BUG=649558
Review-Url: https://codereview.chromium.org/2443103002
Cr-Commit-Position: refs/heads/master@{#427596}
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index d236a73..030995a6 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -169,6 +169,9 @@
SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID = 145,
RDH_TRANSFERRING_REQUEST_NOT_FOUND = 146,
RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST = 147,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST = 148,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN = 149,
+ SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID = 150,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 810c63f..978aec54 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -53,6 +53,8 @@
const char kInvalidStateErrorMessage[] = "The object is in an invalid state.";
const char kEnableNavigationPreloadErrorPrefix[] =
"Failed to enable or disable navigation preload: ";
+const char kGetNavigationPreloadStateErrorPrefix[] =
+ "Failed to get navigation preload state: ";
const uint32_t kFilteredMessageClasses[] = {
ServiceWorkerMsgStart, EmbeddedWorkerMsgStart,
@@ -188,6 +190,8 @@
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_TerminateWorker, OnTerminateWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_EnableNavigationPreload,
OnEnableNavigationPreload)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetNavigationPreloadState,
+ OnGetNavigationPreloadState)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -724,6 +728,69 @@
Send(new ServiceWorkerMsg_DidEnableNavigationPreload(thread_id, request_id));
}
+void ServiceWorkerDispatcherHost::OnGetNavigationPreloadState(
+ int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id) {
+ ProviderStatus provider_status;
+ ServiceWorkerProviderHost* provider_host =
+ GetProviderHostForRequest(&provider_status, provider_id);
+ switch (provider_status) {
+ case ProviderStatus::NO_CONTEXT: // fallthrough
+ case ProviderStatus::DEAD_HOST:
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeAbort,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kShutdownErrorMessage)));
+ return;
+ case ProviderStatus::NO_HOST:
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST);
+ return;
+ case ProviderStatus::NO_URL:
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kNoDocumentURLErrorMessage)));
+ return;
+ case ProviderStatus::OK:
+ break;
+ }
+
+ ServiceWorkerRegistration* registration =
+ GetContext()->GetLiveRegistration(registration_id);
+ if (!registration) {
+ // |registration| must be alive because a renderer retains a registration
+ // reference at this point.
+ bad_message::ReceivedBadMessage(
+ this,
+ bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID);
+ return;
+ }
+
+ std::vector<GURL> urls = {provider_host->document_url(),
+ registration->pattern()};
+ if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN);
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ registration->pattern(), provider_host->topmost_frame_url(),
+ resource_context_, render_process_id_, provider_host->frame_id())) {
+ Send(new ServiceWorkerMsg_GetNavigationPreloadStateError(
+ thread_id, request_id, WebServiceWorkerError::ErrorTypeDisabled,
+ std::string(kGetNavigationPreloadStateErrorPrefix) +
+ std::string(kUserDeniedPermissionMessage)));
+ return;
+ }
+
+ Send(new ServiceWorkerMsg_DidGetNavigationPreloadState(
+ thread_id, request_id, registration->is_navigation_preload_enabled()));
+}
+
void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
int handle_id,
int provider_id,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index 8b30dcf..3408e04 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -139,6 +139,10 @@
int provider_id,
int64_t registration_id,
bool enable);
+ void OnGetNavigationPreloadState(int thread_id,
+ int request_id,
+ int provider_id,
+ int64_t registration_id);
void OnProviderDestroyed(int provider_id);
void OnSetHostedVersionId(int provider_id,
int64_t version_id,
diff --git a/content/browser/service_worker/service_worker_registration.h b/content/browser/service_worker/service_worker_registration.h
index 12bd008..d332fca5 100644
--- a/content/browser/service_worker/service_worker_registration.h
+++ b/content/browser/service_worker/service_worker_registration.h
@@ -95,6 +95,10 @@
return active_version() || waiting_version();
}
+ bool is_navigation_preload_enabled() const {
+ return is_navigation_preload_enabled_;
+ }
+
ServiceWorkerVersion* GetNewestVersion() const;
void AddListener(Listener* listener);
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index 6ca9fac..5619cf4 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -24,6 +24,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/content_constants.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebNavigationPreloadState.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
#include "url/url_constants.h"
@@ -81,6 +82,8 @@
OnDidGetRegistrationForReady)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidEnableNavigationPreload,
OnDidEnableNavigationPreload)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetNavigationPreloadState,
+ OnDidGetNavigationPreloadState)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
OnRegistrationError)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUpdateError,
@@ -93,6 +96,8 @@
OnGetRegistrationsError)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_EnableNavigationPreloadError,
OnEnableNavigationPreloadError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GetNavigationPreloadStateError,
+ OnGetNavigationPreloadStateError)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
OnServiceWorkerStateChanged)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
@@ -222,6 +227,17 @@
CurrentWorkerId(), request_id, provider_id, registration_id, enable));
}
+void ServiceWorkerDispatcher::GetNavigationPreloadState(
+ int provider_id,
+ int64_t registration_id,
+ std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks) {
+ DCHECK(callbacks);
+ int request_id =
+ get_navigation_preload_state_callbacks_.Add(callbacks.release());
+ thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetNavigationPreloadState(
+ CurrentWorkerId(), request_id, provider_id, registration_id));
+}
+
void ServiceWorkerDispatcher::AddProviderContext(
ServiceWorkerProviderContext* provider_context) {
DCHECK(provider_context);
@@ -547,6 +563,20 @@
enable_navigation_preload_callbacks_.Remove(request_id);
}
+void ServiceWorkerDispatcher::OnDidGetNavigationPreloadState(int thread_id,
+ int request_id,
+ bool enabled) {
+ WebGetNavigationPreloadStateCallbacks* callbacks =
+ get_navigation_preload_state_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+ // TODO(falken): Implement populating headerValue.
+ callbacks->onSuccess(
+ blink::WebNavigationPreloadState(enabled, blink::WebString()));
+ get_navigation_preload_state_callbacks_.Remove(request_id);
+}
+
void ServiceWorkerDispatcher::OnRegistrationError(
int thread_id,
int request_id,
@@ -674,6 +704,21 @@
enable_navigation_preload_callbacks_.Remove(request_id);
}
+void ServiceWorkerDispatcher::OnGetNavigationPreloadStateError(
+ int thread_id,
+ int request_id,
+ WebServiceWorkerError::ErrorType error_type,
+ const std::string& message) {
+ WebGetNavigationPreloadStateCallbacks* callbacks =
+ get_navigation_preload_state_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+ callbacks->onError(
+ WebServiceWorkerError(error_type, blink::WebString::fromUTF8(message)));
+ get_navigation_preload_state_callbacks_.Remove(request_id);
+}
+
void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
int thread_id,
int handle_id,
diff --git a/content/child/service_worker/service_worker_dispatcher.h b/content/child/service_worker/service_worker_dispatcher.h
index ccafedf..4a43c08 100644
--- a/content/child/service_worker/service_worker_dispatcher.h
+++ b/content/child/service_worker/service_worker_dispatcher.h
@@ -69,6 +69,8 @@
WebServiceWorkerGetRegistrationForReadyCallbacks;
using WebEnableNavigationPreloadCallbacks =
blink::WebServiceWorkerRegistration::WebEnableNavigationPreloadCallbacks;
+ using WebGetNavigationPreloadStateCallbacks = blink::
+ WebServiceWorkerRegistration::WebGetNavigationPreloadStateCallbacks;
ServiceWorkerDispatcher(
ThreadSafeSender* thread_safe_sender,
@@ -111,6 +113,11 @@
int64_t registration_id,
bool enable,
std::unique_ptr<WebEnableNavigationPreloadCallbacks> callbacks);
+ // Corresponds to NavigationPreloadManager.getState.
+ void GetNavigationPreloadState(
+ int provider_id,
+ int64_t registration_id,
+ std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks);
// Called when a new provider context for a document is created. Usually
// this happens when a new document is being loaded, and is called much
@@ -171,6 +178,8 @@
IDMapOwnPointer> GetRegistrationForReadyCallbackMap;
using EnableNavigationPreloadCallbackMap =
IDMap<WebEnableNavigationPreloadCallbacks, IDMapOwnPointer>;
+ using GetNavigationPreloadStateCallbackMap =
+ IDMap<WebGetNavigationPreloadStateCallbacks, IDMapOwnPointer>;
typedef std::map<int, blink::WebServiceWorkerProviderClient*>
ProviderClientMap;
@@ -216,6 +225,9 @@
const ServiceWorkerRegistrationObjectInfo& info,
const ServiceWorkerVersionAttributes& attrs);
void OnDidEnableNavigationPreload(int thread_id, int request_id);
+ void OnDidGetNavigationPreloadState(int thread_id,
+ int request_id,
+ bool enabled);
void OnRegistrationError(int thread_id,
int request_id,
blink::WebServiceWorkerError::ErrorType error_type,
@@ -243,6 +255,11 @@
int request_id,
blink::WebServiceWorkerError::ErrorType error_type,
const std::string& message);
+ void OnGetNavigationPreloadStateError(
+ int thread_id,
+ int request_id,
+ blink::WebServiceWorkerError::ErrorType error_type,
+ const std::string& message);
void OnServiceWorkerStateChanged(int thread_id,
int handle_id,
blink::WebServiceWorkerState state);
@@ -283,6 +300,7 @@
GetRegistrationsCallbackMap pending_get_registrations_callbacks_;
GetRegistrationForReadyCallbackMap get_for_ready_callbacks_;
EnableNavigationPreloadCallbackMap enable_navigation_preload_callbacks_;
+ GetNavigationPreloadStateCallbackMap get_navigation_preload_state_callbacks_;
ProviderClientMap provider_clients_;
ProviderContextMap provider_contexts_;
diff --git a/content/child/service_worker/web_service_worker_registration_impl.cc b/content/child/service_worker/web_service_worker_registration_impl.cc
index 8a00525d..3043e46 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.cc
+++ b/content/child/service_worker/web_service_worker_registration_impl.cc
@@ -13,6 +13,7 @@
#include "content/child/service_worker/web_service_worker_impl.h"
#include "content/child/service_worker/web_service_worker_provider_impl.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebNavigationPreloadState.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistrationProxy.h"
@@ -160,6 +161,18 @@
std::move(callbacks));
}
+void WebServiceWorkerRegistrationImpl::getNavigationPreloadState(
+ blink::WebServiceWorkerProvider* provider,
+ std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks) {
+ WebServiceWorkerProviderImpl* provider_impl =
+ static_cast<WebServiceWorkerProviderImpl*>(provider);
+ ServiceWorkerDispatcher* dispatcher =
+ ServiceWorkerDispatcher::GetThreadSpecificInstance();
+ DCHECK(dispatcher);
+ dispatcher->GetNavigationPreloadState(
+ provider_impl->provider_id(), registration_id(), std::move(callbacks));
+}
+
int64_t WebServiceWorkerRegistrationImpl::registration_id() const {
return handle_ref_->registration_id();
}
diff --git a/content/child/service_worker/web_service_worker_registration_impl.h b/content/child/service_worker/web_service_worker_registration_impl.h
index 18fb04a..d9ace78 100644
--- a/content/child/service_worker/web_service_worker_registration_impl.h
+++ b/content/child/service_worker/web_service_worker_registration_impl.h
@@ -59,6 +59,10 @@
bool enable,
blink::WebServiceWorkerProvider* provider,
std::unique_ptr<WebEnableNavigationPreloadCallbacks> callbacks) override;
+ void getNavigationPreloadState(
+ blink::WebServiceWorkerProvider* provider,
+ std::unique_ptr<WebGetNavigationPreloadStateCallbacks> callbacks)
+ override;
int64_t registration_id() const;
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h
index 0b858c9a..cf18879 100644
--- a/content/common/service_worker/service_worker_messages.h
+++ b/content/common/service_worker/service_worker_messages.h
@@ -195,6 +195,13 @@
int64_t /* registration_id */,
bool /* enable */)
+// Asks the browser to get navigation preload state for a registration.
+IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_GetNavigationPreloadState,
+ int /* thread_id */,
+ int /* request_id */,
+ int /* provider_id */,
+ int64_t /* registration_id */)
+
// Sends ExtendableMessageEvent to a service worker (renderer->browser).
IPC_MESSAGE_CONTROL5(
ServiceWorkerHostMsg_PostMessageToWorker,
@@ -491,6 +498,15 @@
int /* request_id */,
blink::WebServiceWorkerError::ErrorType /* code */,
std::string /* message */)
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_DidGetNavigationPreloadState,
+ int /* thread_id */,
+ int /* request_id */,
+ bool /* enabled */)
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_GetNavigationPreloadStateError,
+ int /* thread_id */,
+ int /* request_id */,
+ blink::WebServiceWorkerError::ErrorType /* code */,
+ std::string /* message */)
// Sends MessageEvent to a client document (browser->renderer).
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_MessageToDocument,
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 802341e8..4156260 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -364,6 +364,11 @@
crbug.com/635619 virtual/layout_ng/fast/block/float/width-update-after-clear.html [ Skip ]
# ====== LayoutNG-only failures until here ======
+# Requires ServiceWorkerNavigationPreload feature enabled. Run under
+# virtual/service-worker-navigation-preload only.
+crbug.com/649558 http/tests/serviceworker/navigation-preload/ [ Skip ]
+crbug.com/649558 virtual/mojo-service-worker/http/tests/serviceworker/navigation-preload/ [ Skip ]
+
# Run these tests with under virtual/scalefactor... only.
crbug.com/567837 fast/hidpi/static [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/get-state.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/get-state.html
new file mode 100644
index 0000000..07555e97
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/get-state.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>NavigationPreloadManager.getState</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/test-helpers.js"></script>
+<body>
+<script>
+function post_and_wait_for_reply(worker, message) {
+ return new Promise(resolve => {
+ navigator.serviceWorker.onmessage = e => { resolve(e.data); };
+ worker.postMessage(message);
+ });
+}
+
+promise_test(t => {
+ const scope = '../resources/getState';
+ const script = '../resources/empty-worker.js';
+ var registration;
+
+ return service_worker_unregister_and_register(t, script, scope)
+ .then(r => {
+ registration = r;
+ add_completion_callback(() => registration.unregister());
+ return registration.navigationPreload.getState();
+ })
+ .then(state => {
+ assert_equals(state.enabled, false,
+ '.enabled should be false by default');
+ return registration.navigationPreload.enable();
+ })
+ .then(() => registration.navigationPreload.getState())
+ .then(state => {
+ assert_equals(state.enabled, true,
+ '.enabled should be true after enable()');
+ return registration.navigationPreload.disable();
+ })
+ .then(() => registration.navigationPreload.getState())
+ .then(state => {
+ assert_equals(state.enabled, false,
+ '.enabled should be false after disable()');
+ });
+ }, 'getState');
+
+// This test sends commands to a worker to call enable()/disable()/getState().
+// It checks the results from the worker and verifies that they match the
+// navigation preload state accessible from the page.
+promise_test(t => {
+ const scope = 'resources/getState-worker';
+ const script = 'resources/get-state-worker.js';
+ var worker;
+ var registration;
+
+ return service_worker_unregister_and_register(t, script, scope)
+ .then(r => {
+ registration = r;
+ add_completion_callback(() => registration.unregister());
+ worker = registration.installing;
+ // Call getState().
+ return post_and_wait_for_reply(worker, 'getState');
+ })
+ .then(data => {
+ return Promise.all([data, registration.navigationPreload.getState()]);
+ })
+ .then(states => {
+ assert_equals(states[0].enabled, false,
+ '.enabled should be false by default (from worker)');
+ assert_equals(states[1].enabled, false,
+ '.enabled should be false by default (from page)');
+ // Call enable() and then getState().
+ return post_and_wait_for_reply(worker, 'enable');
+ })
+ .then(data => {
+ assert_equals(data, undefined, 'enable() should resolve to undefined');
+ return Promise.all([
+ post_and_wait_for_reply(worker, 'getState'),
+ registration.navigationPreload.getState()
+ ]);
+ })
+ .then(states => {
+ assert_equals(states[0].enabled, true,
+ '.enabled should be true after enable() (from worker)');
+ assert_equals(states[1].enabled, true,
+ '.enabled should be true after enable() (from page)');
+ // Call disable() and then getState().
+ return post_and_wait_for_reply(worker, 'disable');
+ })
+ .then(data => {
+ assert_equals(data, undefined,
+ '.disable() should resolve to undefined');
+ return Promise.all([
+ post_and_wait_for_reply(worker, 'getState'),
+ registration.navigationPreload.getState()
+ ]);
+ })
+ .then(states => {
+ assert_equals(states[0].enabled, false,
+ '.enabled should be false after disable() (from worker)');
+ assert_equals(states[1].enabled, false,
+ '.enabled should be false after disable() (from page)');
+ });
+ }, 'getState from a worker');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/resources/get-state-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/resources/get-state-worker.js
new file mode 100644
index 0000000..93ee461
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/navigation-preload/resources/get-state-worker.js
@@ -0,0 +1,19 @@
+// This worker listens for commands from the page and messages back
+// the result.
+
+function handle(message) {
+ const np = self.registration.navigationPreload;
+ switch (message) {
+ case 'getState':
+ return np.getState();
+ case 'enable':
+ return np.enable();
+ case 'disable':
+ return np.disable();
+ }
+ return Promise.reject('bad message');
+}
+
+self.addEventListener('message', e => {
+ e.waitUntil(handle(e.data).then(result => e.source.postMessage(result)));
+ });
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.cpp b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.cpp
index 4a9e0366b..ac7afe3 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.cpp
@@ -6,7 +6,9 @@
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMException.h"
+#include "modules/serviceworkers/NavigationPreloadState.h"
#include "modules/serviceworkers/ServiceWorkerError.h"
+#include "public/platform/modules/serviceworker/WebNavigationPreloadState.h"
namespace blink {
@@ -33,4 +35,32 @@
m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
}
+GetNavigationPreloadStateCallbacks::GetNavigationPreloadStateCallbacks(
+ ScriptPromiseResolver* resolver)
+ : m_resolver(resolver) {
+ DCHECK(m_resolver);
+}
+
+GetNavigationPreloadStateCallbacks::~GetNavigationPreloadStateCallbacks() {}
+
+void GetNavigationPreloadStateCallbacks::onSuccess(
+ const WebNavigationPreloadState& state) {
+ if (!m_resolver->getExecutionContext() ||
+ m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
+ return;
+ NavigationPreloadState dict;
+ dict.setEnabled(state.enabled);
+ if (!state.headerValue.isNull())
+ dict.setHeaderValue(state.headerValue);
+ m_resolver->resolve(dict);
+}
+
+void GetNavigationPreloadStateCallbacks::onError(
+ const WebServiceWorkerError& error) {
+ if (!m_resolver->getExecutionContext() ||
+ m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
+ return;
+ m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
+}
+
} // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.h b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.h
index 612fbe0e..4e935d4 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadCallbacks.h
@@ -10,6 +10,7 @@
namespace blink {
class ScriptPromiseResolver;
+struct WebNavigationPreloadState;
struct WebServiceWorkerError;
class EnableNavigationPreloadCallbacks final
@@ -27,6 +28,22 @@
WTF_MAKE_NONCOPYABLE(EnableNavigationPreloadCallbacks);
};
+class GetNavigationPreloadStateCallbacks final
+ : public WebServiceWorkerRegistration::
+ WebGetNavigationPreloadStateCallbacks {
+ public:
+ GetNavigationPreloadStateCallbacks(ScriptPromiseResolver*);
+ ~GetNavigationPreloadStateCallbacks() override;
+
+ // WebGetNavigationPreloadStateCallbacks interface.
+ void onSuccess(const WebNavigationPreloadState&) override;
+ void onError(const WebServiceWorkerError&) override;
+
+ private:
+ Persistent<ScriptPromiseResolver> m_resolver;
+ WTF_MAKE_NONCOPYABLE(GetNavigationPreloadStateCallbacks);
+};
+
} // namespace blink
#endif // NavigationPreloadCallbacks_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadManager.cpp b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadManager.cpp
index 9e89e74..9d2a79c 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadManager.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/NavigationPreloadManager.cpp
@@ -25,9 +25,19 @@
return ScriptPromise();
}
-ScriptPromise NavigationPreloadManager::getState(ScriptState*) {
- NOTIMPLEMENTED();
- return ScriptPromise();
+ScriptPromise NavigationPreloadManager::getState(ScriptState* scriptState) {
+ ServiceWorkerContainerClient* client =
+ ServiceWorkerContainerClient::from(m_registration->getExecutionContext());
+ if (!client || !client->provider()) {
+ return ScriptPromise::rejectWithDOMException(
+ scriptState, DOMException::create(InvalidStateError, "No provider."));
+ }
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+ m_registration->webRegistration()->getNavigationPreloadState(
+ client->provider(),
+ wrapUnique(new GetNavigationPreloadStateCallbacks(resolver)));
+ return promise;
}
NavigationPreloadManager::NavigationPreloadManager(
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index bab5fcab..3f99086 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -376,6 +376,7 @@
"platform/modules/screen_orientation/WebScreenOrientationClient.h",
"platform/modules/screen_orientation/WebScreenOrientationLockType.h",
"platform/modules/screen_orientation/WebScreenOrientationType.h",
+ "platform/modules/serviceworker/WebNavigationPreloadState.h",
"platform/modules/serviceworker/WebServiceWorker.h",
"platform/modules/serviceworker/WebServiceWorkerCache.h",
"platform/modules/serviceworker/WebServiceWorkerCacheError.h",
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebNavigationPreloadState.h b/third_party/WebKit/public/platform/modules/serviceworker/WebNavigationPreloadState.h
new file mode 100644
index 0000000..c30845e
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebNavigationPreloadState.h
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+#ifndef WebNavigationPreloadState_h
+#define WebNavigationPreloadState_h
+
+namespace blink {
+
+struct WebNavigationPreloadState {
+ WebNavigationPreloadState(bool enabled, const WebString& headerValue)
+ : enabled(enabled), headerValue(headerValue) {}
+
+ bool enabled;
+ WebString headerValue;
+};
+}
+
+#endif // WebNavigationPreloadState_h
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistration.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistration.h
index fe5ba1b..980fa38 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistration.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRegistration.h
@@ -13,6 +13,7 @@
class WebServiceWorkerProvider;
class WebServiceWorkerRegistrationProxy;
+struct WebNavigationPreloadState;
// The interface of the registration representation in the embedder. The
// embedder implements this interface and passes its handle
@@ -28,6 +29,9 @@
WebCallbacks<bool, const WebServiceWorkerError&>;
using WebEnableNavigationPreloadCallbacks =
WebCallbacks<void, const WebServiceWorkerError&>;
+ using WebGetNavigationPreloadStateCallbacks =
+ WebCallbacks<const WebNavigationPreloadState&,
+ const WebServiceWorkerError&>;
// The handle interface that retains a reference to the implementation of
// WebServiceWorkerRegistration in the embedder and is owned by
@@ -53,6 +57,9 @@
bool enable,
WebServiceWorkerProvider*,
std::unique_ptr<WebEnableNavigationPreloadCallbacks>) {}
+ virtual void getNavigationPreloadState(
+ WebServiceWorkerProvider*,
+ std::unique_ptr<WebGetNavigationPreloadStateCallbacks>) {}
};
} // namespace blink
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 6439193..2b8f31d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -74238,6 +74238,12 @@
<int value="143" label="SWDH_ENABLE_NAVIGATION_PRELOAD_NO_HOST"/>
<int value="144" label="SWDH_ENABLE_NAVIGATION_PRELOAD_INVALID_ORIGIN"/>
<int value="145" label="SWDH_ENABLE_NAVIGATION_PRELOAD_BAD_REGISTRATION_ID"/>
+ <int value="146" label="RDH_TRANSFERRING_REQUEST_NOT_FOUND"/>
+ <int value="147" label="RDH_TRANSFERRING_NONNAVIGATIONAL_REQUEST"/>
+ <int value="148" label="SWDH_GET_NAVIGATION_PRELOAD_STATE_NO_HOST"/>
+ <int value="149" label="SWDH_GET_NAVIGATION_PRELOAD_STATE_INVALID_ORIGIN"/>
+ <int value="150"
+ label="SWDH_GET_NAVIGATION_PRELOAD_STATE_BAD_REGISTRATION_ID"/>
</enum>
<enum name="BadMessageReasonExtensions" type="int">