summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjungkee.song <jungkee.song@samsung.com>2016-02-22 16:36:33 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-23 00:38:08 +0000
commit0ca977be9dbe2582e8f18415bd9299efd36fd329 (patch)
treecafa9477ab28c9a6c4c59380a6d86d0434380ef4
parentaf548e472716edd2834167d6c8cadc799ee30779 (diff)
downloadchromium_src-0ca977be9dbe2582e8f18415bd9299efd36fd329.zip
chromium_src-0ca977be9dbe2582e8f18415bd9299efd36fd329.tar.gz
chromium_src-0ca977be9dbe2582e8f18415bd9299efd36fd329.tar.bz2
Service Worker: Add Clients.get(id)
As per the latest spec update, this CL implements Clients.get(id) method. Spec discussion: https://github.com/slightlyoff/ServiceWorker/issues/723#issuecomment-151326898 Spec: https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#clients-get-method Intent to implement and ship: https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/XlBHOIOCjUk The layout tests for this CL are mostly taken from Mozilla's work instead of making new ones to ensure compatibility: https://bugzilla.mozilla.org/show_bug.cgi?id=1222464 BUG=552310 Review URL: https://codereview.chromium.org/1439333002 Cr-Commit-Position: refs/heads/master@{#376870}
-rw-r--r--content/browser/service_worker/service_worker_client_utils.cc70
-rw-r--r--content/browser/service_worker/service_worker_client_utils.h10
-rw-r--r--content/browser/service_worker/service_worker_provider_host.cc19
-rw-r--r--content/browser/service_worker/service_worker_provider_host.h6
-rw-r--r--content/browser/service_worker/service_worker_version.cc64
-rw-r--r--content/browser/service_worker/service_worker_version.h13
-rw-r--r--content/common/service_worker/service_worker_client_info.cc20
-rw-r--r--content/common/service_worker/service_worker_client_info.h5
-rw-r--r--content/common/service_worker/service_worker_messages.h10
-rw-r--r--content/renderer/service_worker/service_worker_context_client.cc36
-rw-r--r--content/renderer/service_worker/service_worker_context_client.h3
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get-cross-origin.html48
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get.html69
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-cross-origin-frame.html58
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-frame.html10
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-worker.js42
-rw-r--r--third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt1
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/Clients.idl1
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp20
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h5
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp45
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h1
-rw-r--r--third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h1
-rw-r--r--third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in1
-rw-r--r--third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp5
-rw-r--r--third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h1
-rw-r--r--third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h6
27 files changed, 495 insertions, 75 deletions
diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
index 26ef4d3..a7eb04f 100644
--- a/content/browser/service_worker/service_worker_client_utils.cc
+++ b/content/browser/service_worker/service_worker_client_utils.cc
@@ -176,15 +176,13 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context) {
- callback.Run(SERVICE_WORKER_ERROR_ABORT, std::string(),
- ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_ERROR_ABORT, ServiceWorkerClientInfo());
return;
}
if (render_process_id == ChildProcessHost::kInvalidUniqueID &&
render_frame_id == MSG_ROUTING_NONE) {
- callback.Run(SERVICE_WORKER_ERROR_FAILED, std::string(),
- ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_ERROR_FAILED, ServiceWorkerClientInfo());
return;
}
@@ -196,14 +194,13 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
provider_host->frame_id() != render_frame_id) {
continue;
}
- provider_host->GetWindowClientInfo(
- base::Bind(callback, SERVICE_WORKER_OK, provider_host->client_uuid()));
+ provider_host->GetWindowClientInfo(base::Bind(callback, SERVICE_WORKER_OK));
return;
}
// If here, it means that no provider_host was found, in which case, the
// renderer should still be informed that the window was opened.
- callback.Run(SERVICE_WORKER_OK, std::string(), ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_OK, ServiceWorkerClientInfo());
}
void AddWindowClient(
@@ -225,12 +222,11 @@ void AddNonWindowClient(ServiceWorkerProviderHost* host,
options.client_type != host_client_type)
return;
- ServiceWorkerClientInfo client_info(blink::WebPageVisibilityStateHidden,
- false, // is_focused
- host->document_url(),
- REQUEST_CONTEXT_FRAME_TYPE_NONE,
- base::TimeTicks(), host_client_type);
- client_info.client_uuid = host->client_uuid();
+ ServiceWorkerClientInfo client_info(
+ host->client_uuid(), blink::WebPageVisibilityStateHidden,
+ false, // is_focused
+ host->document_url(), REQUEST_CONTEXT_FRAME_TYPE_NONE, base::TimeTicks(),
+ host_client_type);
clients->push_back(client_info);
}
@@ -243,8 +239,8 @@ void OnGetWindowClientsOnUI(
for (const auto& it : clients_info) {
ServiceWorkerClientInfo info =
- ServiceWorkerProviderHost::GetWindowClientInfoOnUI(base::get<0>(it),
- base::get<1>(it));
+ ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
+ base::get<0>(it), base::get<1>(it), base::get<2>(it));
// If the request to the provider_host returned an empty
// ServiceWorkerClientInfo, that means that it wasn't possible to associate
@@ -259,7 +255,6 @@ void OnGetWindowClientsOnUI(
if (info.url.GetOrigin() != script_url.GetOrigin())
continue;
- info.client_uuid = base::get<2>(it);
clients->push_back(info);
}
@@ -371,6 +366,49 @@ void NavigateClient(const GURL& url,
base::Bind(&DidNavigate, context, script_url.GetOrigin(), callback)));
}
+void GetClient(
+ const base::WeakPtr<ServiceWorkerVersion>& controller,
+ const std::string& client_uuid,
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ const ServiceWorkerProviderHost::GetClientInfoCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerProviderHost* provider_host =
+ context->GetProviderHostByClientID(client_uuid);
+
+ if (!provider_host) {
+ // The client may already have been closed, just ignore.
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, ServiceWorkerClientInfo()));
+ return;
+ }
+
+ if (provider_host->document_url().GetOrigin() !=
+ controller->script_url().GetOrigin()) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, ServiceWorkerClientInfo()));
+ return;
+ }
+
+ if (provider_host->client_type() == blink::WebServiceWorkerClientTypeWindow) {
+ provider_host->GetWindowClientInfo(callback);
+ return;
+ }
+
+ DCHECK(provider_host->client_type() ==
+ blink::WebServiceWorkerClientTypeWorker ||
+ provider_host->client_type() ==
+ blink::WebServiceWorkerClientTypeSharedWorker);
+
+ ServiceWorkerClientInfo client_info(
+ provider_host->client_uuid(), blink::WebPageVisibilityStateHidden,
+ false, // is_focused
+ provider_host->document_url(), REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ base::TimeTicks(), provider_host->client_type());
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, client_info));
+}
+
void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
const ServiceWorkerClientQueryOptions& options,
const ClientsCallback& callback) {
diff --git a/content/browser/service_worker/service_worker_client_utils.h b/content/browser/service_worker/service_worker_client_utils.h
index 258268e..c4bf312 100644
--- a/content/browser/service_worker/service_worker_client_utils.h
+++ b/content/browser/service_worker/service_worker_client_utils.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/common/service_worker/service_worker_status_code.h"
class GURL;
@@ -25,7 +26,6 @@ namespace service_worker_client_utils {
using NavigationCallback =
base::Callback<void(ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info)>;
using ServiceWorkerClients = std::vector<ServiceWorkerClientInfo>;
using ClientsCallback = base::Callback<void(ServiceWorkerClients* clients)>;
@@ -47,6 +47,14 @@ void NavigateClient(const GURL& url,
const base::WeakPtr<ServiceWorkerContextCore>& context,
const NavigationCallback& callback);
+// Gets a client matched by |client_uuid|. |callback| is called with the client
+// information on completion.
+void GetClient(
+ const base::WeakPtr<ServiceWorkerVersion>& controller,
+ const std::string& client_uuid,
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ const ServiceWorkerProviderHost::GetClientInfoCallback& callback);
+
// Collects clients matched with |options|. |callback| is called with the client
// information sorted in MRU order (most recently focused order) on completion.
void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 1d79f52..639b442 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -36,7 +36,8 @@ namespace content {
namespace {
ServiceWorkerClientInfo FocusOnUIThread(int render_process_id,
- int render_frame_id) {
+ int render_frame_id,
+ const std::string& client_uuid) {
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
@@ -57,8 +58,8 @@ ServiceWorkerClientInfo FocusOnUIThread(int render_process_id,
// Move the web contents to the foreground.
web_contents->Activate();
- return ServiceWorkerProviderHost::GetWindowClientInfoOnUI(render_process_id,
- render_frame_id);
+ return ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
+ render_process_id, render_frame_id, client_uuid);
}
// PlzNavigate
@@ -440,7 +441,8 @@ void ServiceWorkerProviderHost::Focus(const GetClientInfoCallback& callback) {
}
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
- base::Bind(&FocusOnUIThread, render_process_id_, route_id_), callback);
+ base::Bind(&FocusOnUIThread, render_process_id_, route_id_, client_uuid_),
+ callback);
}
void ServiceWorkerProviderHost::GetWindowClientInfo(
@@ -452,14 +454,15 @@ void ServiceWorkerProviderHost::GetWindowClientInfo(
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, FROM_HERE,
base::Bind(&ServiceWorkerProviderHost::GetWindowClientInfoOnUI,
- render_process_id_, route_id_),
+ render_process_id_, route_id_, client_uuid_),
callback);
}
// static
ServiceWorkerClientInfo ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
int render_process_id,
- int render_frame_id) {
+ int render_frame_id,
+ const std::string& client_uuid) {
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
if (!render_frame_host)
@@ -469,8 +472,8 @@ ServiceWorkerClientInfo ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
// for a frame that is actually being navigated and isn't exactly what we are
// expecting.
return ServiceWorkerClientInfo(
- render_frame_host->GetVisibilityState(), render_frame_host->IsFocused(),
- render_frame_host->GetLastCommittedURL(),
+ client_uuid, render_frame_host->GetVisibilityState(),
+ render_frame_host->IsFocused(), render_frame_host->GetLastCommittedURL(),
render_frame_host->GetParent() ? REQUEST_CONTEXT_FRAME_TYPE_NESTED
: REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
render_frame_host->frame_tree_node()->last_focus_time(),
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index a40ffc2..59c243f 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -186,8 +186,10 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Same as above but has to be called from the UI thread.
// It is taking the process and frame ids in parameter because |this| is meant
// to live on the IO thread.
- static ServiceWorkerClientInfo GetWindowClientInfoOnUI(int render_process_id,
- int render_frame_id);
+ static ServiceWorkerClientInfo GetWindowClientInfoOnUI(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& client_uuid);
// Adds reference of this host's process to the |pattern|, the reference will
// be removed in destructor.
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index fe5ec41..105f168 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -892,6 +892,7 @@ void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerVersion, message)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClient, OnGetClient)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClients,
OnGetClients)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow,
@@ -944,6 +945,32 @@ void ServiceWorkerVersion::DispatchExtendableMessageEventAfterStartWorker(
request_id, message, sent_message_ports, new_routing_ids));
}
+void ServiceWorkerVersion::OnGetClient(int request_id,
+ const std::string& client_uuid) {
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient",
+ request_id, "client_uuid", client_uuid);
+ service_worker_client_utils::GetClient(
+ weak_factory_.GetWeakPtr(), client_uuid, context_,
+ base::Bind(&ServiceWorkerVersion::OnGetClientFinished,
+ weak_factory_.GetWeakPtr(), request_id));
+}
+
+void ServiceWorkerVersion::OnGetClientFinished(
+ int request_id,
+ const ServiceWorkerClientInfo& client_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::OnGetClient",
+ request_id, "client_type", client_info.client_type);
+
+ // When Clients.get() is called on the script evaluation phase, the running
+ // status can be STARTING here.
+ if (running_status() != STARTING && running_status() != RUNNING)
+ return;
+
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_DidGetClient(request_id, client_info));
+}
+
void ServiceWorkerVersion::OnGetClients(
int request_id,
const ServiceWorkerClientQueryOptions& options) {
@@ -1028,7 +1055,6 @@ void ServiceWorkerVersion::OnOpenWindow(int request_id, GURL url) {
void ServiceWorkerVersion::OnOpenWindowFinished(
int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1041,16 +1067,8 @@ void ServiceWorkerVersion::OnOpenWindowFinished(
return;
}
- ServiceWorkerClientInfo client(client_info);
-
- // If the |client_info| is empty, it means that the opened window wasn't
- // controlled but the action still succeeded. The renderer process is
- // expecting an empty client in such case.
- if (!client.IsEmpty())
- client.client_uuid = client_uuid;
-
- embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse(
- request_id, client));
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_OpenWindowResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnSetCachedMetadata(const GURL& url,
@@ -1133,24 +1151,19 @@ void ServiceWorkerVersion::OnFocusClient(int request_id,
return;
}
provider_host->Focus(base::Bind(&ServiceWorkerVersion::OnFocusClientFinished,
- weak_factory_.GetWeakPtr(), request_id,
- client_uuid));
+ weak_factory_.GetWeakPtr(), request_id));
}
void ServiceWorkerVersion::OnFocusClientFinished(
int request_id,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client) {
+ const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (running_status() != RUNNING)
return;
- ServiceWorkerClientInfo client_info(client);
- client_info.client_uuid = client_uuid;
-
- embedded_worker_->SendMessage(ServiceWorkerMsg_FocusClientResponse(
- request_id, client_info));
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_FocusClientResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnNavigateClient(int request_id,
@@ -1199,7 +1212,6 @@ void ServiceWorkerVersion::OnNavigateClient(int request_id,
void ServiceWorkerVersion::OnNavigateClientFinished(
int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1212,16 +1224,8 @@ void ServiceWorkerVersion::OnNavigateClientFinished(
return;
}
- ServiceWorkerClientInfo client(client_info);
-
- // If the |client_info| is empty, it means that the navigated client wasn't
- // controlled but the action still succeeded. The renderer process is
- // expecting an empty client in such case.
- if (!client.IsEmpty())
- client.client_uuid = client_uuid;
-
embedded_worker_->SendMessage(
- ServiceWorkerMsg_NavigateClientResponse(request_id, client));
+ ServiceWorkerMsg_NavigateClientResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnSkipWaiting(int request_id) {
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index fcc86a4..95109ba 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -535,6 +535,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Message handlers.
+ // This corresponds to the spec's get(id) steps.
+ void OnGetClient(int request_id, const std::string& client_uuid);
+
// This corresponds to the spec's matchAll(options) steps.
void OnGetClients(int request_id,
const ServiceWorkerClientQueryOptions& options);
@@ -544,7 +547,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
void OnOpenWindow(int request_id, GURL url);
void OnOpenWindowFinished(int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info);
void OnSetCachedMetadata(const GURL& url, const std::vector<char>& data);
@@ -562,15 +564,13 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL& url);
void OnNavigateClientFinished(int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client);
+ const ServiceWorkerClientInfo& client_info);
void OnSkipWaiting(int request_id);
void OnClaimClients(int request_id);
void OnPongFromWorker();
void OnFocusClientFinished(int request_id,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client);
+ const ServiceWorkerClientInfo& client_info);
void OnRegisterForeignFetchScopes(const std::vector<GURL>& sub_scopes,
const std::vector<url::Origin>& origins);
@@ -583,6 +583,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
void DidSkipWaiting(int request_id);
+ void OnGetClientFinished(int request_id,
+ const ServiceWorkerClientInfo& client_info);
+
void OnGetClientsFinished(int request_id, ServiceWorkerClients* clients);
// The timeout timer periodically calls OnTimeoutTimer, which stops the worker
diff --git a/content/common/service_worker/service_worker_client_info.cc b/content/common/service_worker/service_worker_client_info.cc
index c864369..5019575 100644
--- a/content/common/service_worker/service_worker_client_info.cc
+++ b/content/common/service_worker/service_worker_client_info.cc
@@ -10,25 +10,29 @@
namespace content {
ServiceWorkerClientInfo::ServiceWorkerClientInfo()
- : page_visibility_state(blink::WebPageVisibilityStateLast),
- is_focused(false),
- frame_type(REQUEST_CONTEXT_FRAME_TYPE_LAST),
- client_type(blink::WebServiceWorkerClientTypeLast),
- last_focus_time(base::TimeTicks()) {}
+ : ServiceWorkerClientInfo(std::string(),
+ blink::WebPageVisibilityStateLast,
+ false,
+ GURL(),
+ REQUEST_CONTEXT_FRAME_TYPE_LAST,
+ base::TimeTicks(),
+ blink::WebServiceWorkerClientTypeLast) {}
ServiceWorkerClientInfo::ServiceWorkerClientInfo(
+ const std::string& client_uuid,
blink::WebPageVisibilityState page_visibility_state,
bool is_focused,
const GURL& url,
RequestContextFrameType frame_type,
base::TimeTicks last_focus_time,
blink::WebServiceWorkerClientType client_type)
- : page_visibility_state(page_visibility_state),
+ : client_uuid(client_uuid),
+ page_visibility_state(page_visibility_state),
is_focused(is_focused),
url(url),
frame_type(frame_type),
- client_type(client_type),
- last_focus_time(last_focus_time) {}
+ last_focus_time(last_focus_time),
+ client_type(client_type) {}
bool ServiceWorkerClientInfo::IsEmpty() const {
return page_visibility_state == blink::WebPageVisibilityStateLast &&
diff --git a/content/common/service_worker/service_worker_client_info.h b/content/common/service_worker/service_worker_client_info.h
index 1c81fe3..c4b6c34 100644
--- a/content/common/service_worker/service_worker_client_info.h
+++ b/content/common/service_worker/service_worker_client_info.h
@@ -20,7 +20,8 @@ namespace content {
// constructor to fill the properties.
struct ServiceWorkerClientInfo {
ServiceWorkerClientInfo();
- ServiceWorkerClientInfo(blink::WebPageVisibilityState page_visibility_state,
+ ServiceWorkerClientInfo(const std::string& client_uuid,
+ blink::WebPageVisibilityState page_visibility_state,
bool is_focused,
const GURL& url,
RequestContextFrameType frame_type,
@@ -39,8 +40,8 @@ struct ServiceWorkerClientInfo {
bool is_focused;
GURL url;
RequestContextFrameType frame_type;
- blink::WebServiceWorkerClientType client_type;
base::TimeTicks last_focus_time;
+ blink::WebServiceWorkerClientType client_type;
};
} // namespace content
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h
index 6174cc5..2bd68cd 100644
--- a/content/common/service_worker/service_worker_messages.h
+++ b/content/common/service_worker/service_worker_messages.h
@@ -275,6 +275,11 @@ IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GeofencingEventFinished,
// Routed to the target ServiceWorkerVersion.
IPC_MESSAGE_ROUTED0(ServiceWorkerHostMsg_Pong)
+// Asks the browser to retrieve client of the sender ServiceWorker.
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GetClient,
+ int /* request_id */,
+ std::string /* client_uuid */)
+
// Asks the browser to retrieve clients of the sender ServiceWorker.
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GetClients,
int /* request_id */,
@@ -515,6 +520,11 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ClaimClientsError,
// Sent via EmbeddedWorker to Ping the worker, expecting a Pong in response.
IPC_MESSAGE_CONTROL0(ServiceWorkerMsg_Ping)
+// Sent via EmbeddedWorker as a response of GetClient.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DidGetClient,
+ int /* request_id */,
+ content::ServiceWorkerClientInfo)
+
// Sent via EmbeddedWorker as a response of GetClients.
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DidGetClients,
int /* request_id */,
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 34e20a7..ba47847 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -267,6 +267,7 @@ void ServiceWorkerContextClient::OnMessageReceived(
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CrossOriginMessageToWorker,
OnCrossOriginMessageToWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClient, OnDidGetClient)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients, OnDidGetClients)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse,
OnOpenWindowResponse)
@@ -299,6 +300,15 @@ blink::WebURL ServiceWorkerContextClient::scope() const {
return service_worker_scope_;
}
+void ServiceWorkerContextClient::getClient(
+ const blink::WebString& id,
+ blink::WebServiceWorkerClientCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = context_->client_callbacks.Add(callbacks);
+ Send(new ServiceWorkerHostMsg_GetClient(
+ GetRoutingID(), request_id, base::UTF16ToUTF8(base::StringPiece16(id))));
+}
+
void ServiceWorkerContextClient::getClients(
const blink::WebServiceWorkerClientQueryOptions& weboptions,
blink::WebServiceWorkerClientsCallbacks* callbacks) {
@@ -873,6 +883,26 @@ void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
proxy_->dispatchCrossOriginMessageEvent(web_client, message, ports);
}
+void ServiceWorkerContextClient::OnDidGetClient(
+ int request_id,
+ const ServiceWorkerClientInfo& client) {
+ TRACE_EVENT0("ServiceWorker", "ServiceWorkerContextClient::OnDidGetClient");
+ blink::WebServiceWorkerClientCallbacks* callbacks =
+ context_->client_callbacks.Lookup(request_id);
+ if (!callbacks) {
+ NOTREACHED() << "Got stray response: " << request_id;
+ return;
+ }
+ scoped_ptr<blink::WebServiceWorkerClientInfo> web_client;
+ if (!client.IsEmpty()) {
+ DCHECK(client.IsValid());
+ web_client.reset(new blink::WebServiceWorkerClientInfo(
+ ToWebServiceWorkerClientInfo(client)));
+ }
+ callbacks->onSuccess(blink::adoptWebPtr(web_client.release()));
+ context_->client_callbacks.Remove(request_id);
+}
+
void ServiceWorkerContextClient::OnDidGetClients(
int request_id, const std::vector<ServiceWorkerClientInfo>& clients) {
TRACE_EVENT0("ServiceWorker",
@@ -910,7 +940,7 @@ void ServiceWorkerContextClient::OnOpenWindowResponse(
web_client.reset(new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
}
- callbacks->onSuccess(adoptWebPtr(web_client.release()));
+ callbacks->onSuccess(blink::adoptWebPtr(web_client.release()));
context_->client_callbacks.Remove(request_id);
}
@@ -946,7 +976,7 @@ void ServiceWorkerContextClient::OnFocusClientResponse(
scoped_ptr<blink::WebServiceWorkerClientInfo> web_client (
new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
- callback->onSuccess(adoptWebPtr(web_client.release()));
+ callback->onSuccess(blink::adoptWebPtr(web_client.release()));
} else {
callback->onError(blink::WebServiceWorkerError(
blink::WebServiceWorkerError::ErrorTypeNotFound,
@@ -973,7 +1003,7 @@ void ServiceWorkerContextClient::OnNavigateClientResponse(
web_client.reset(new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
}
- callbacks->onSuccess(adoptWebPtr(web_client.release()));
+ callbacks->onSuccess(blink::adoptWebPtr(web_client.release()));
context_->client_callbacks.Remove(request_id);
}
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index aed6ce5..9b7bbad 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -92,6 +92,8 @@ class ServiceWorkerContextClient
// WebServiceWorkerContextClient overrides.
blink::WebURL scope() const override;
+ void getClient(const blink::WebString&,
+ blink::WebServiceWorkerClientCallbacks*) override;
void getClients(const blink::WebServiceWorkerClientQueryOptions&,
blink::WebServiceWorkerClientsCallbacks*) override;
void openWindow(const blink::WebURL&,
@@ -227,6 +229,7 @@ class ServiceWorkerContextClient
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports,
const std::vector<int>& new_routing_ids);
+ void OnDidGetClient(int request_id, const ServiceWorkerClientInfo& client);
void OnDidGetClients(
int request_id, const std::vector<ServiceWorkerClientInfo>& clients);
void OnOpenWindowResponse(int request_id,
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get-cross-origin.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get-cross-origin.html
new file mode 100644
index 0000000..e1ec570
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get-cross-origin.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>Service Worker: Clients.get across origins</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/get-host-info.js"></script>
+<script src="resources/test-helpers.js"></script>
+<script>
+var host_info = get_host_info();
+
+var scope = 'resources/clients-get-frame.html';
+var other_origin_iframe = host_info['HTTP_REMOTE_ORIGIN'] + base_path() +
+ 'resources/clients-get-cross-origin-frame.html';
+var my_origin_client_id;
+promise_test(function(t) {
+ return service_worker_unregister_and_register(
+ t, 'resources/clients-get-worker.js', scope)
+ .then(function(registration) {
+ add_completion_callback(function() { registration.unregister(); });
+ return wait_for_state(t, registration.installing, 'activated');
+ })
+ .then(function() {
+ return with_iframe(scope);
+ })
+ .then(function(frame1) {
+ add_completion_callback(function() { frame1.remove(); });
+ return new Promise(function(resolve, reject) {
+ function get_client_id(e) {
+ window.removeEventListener('message', get_client_id);
+ resolve(e.data.clientId);
+ }
+ window.addEventListener('message', get_client_id, false);
+ });
+ })
+ .then(function(client_id) {
+ my_origin_client_id = client_id;
+ return with_iframe(other_origin_iframe);
+ })
+ .then(function(frame2) {
+ add_completion_callback(function() { frame2.remove(); });
+ window.addEventListener('message', function(e) {
+ assert_equals(e.data.result, undefined);
+ t.done();
+ });
+ frame2.contentWindow.postMessage(
+ {clientId: my_origin_client_id}, host_info['HTTP_REMOTE_ORIGIN']);
+ });
+ }, 'Test Clients.get() cross origin');
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get.html
new file mode 100644
index 0000000..67110c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/clients-get.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>Service Worker: Clients.get</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/get-host-info.js"></script>
+<script src="resources/test-helpers.js"></script>
+<script>
+var scope = 'resources/clients-get-frame.html';
+var client_ids = [];
+var frame;
+promise_test(function(t) {
+ return service_worker_unregister_and_register(
+ t, 'resources/clients-get-worker.js', scope)
+ .then(function(registration) {
+ add_completion_callback(function() { registration.unregister(); });
+ return wait_for_state(t, registration.installing, 'activated');
+ })
+ .then(function() {
+ return with_iframe(scope + '#1');
+ })
+ .then(function(frame1) {
+ add_completion_callback(function() { frame1.remove(); });
+ frame1.focus();
+ return wait_for_clientId();
+ })
+ .then(function(client_id) {
+ client_ids.push(client_id);
+ return with_iframe(scope + '#2');
+ })
+ .then(function(frame2) {
+ frame = frame2;
+ add_completion_callback(function() { frame2.remove(); });
+ return wait_for_clientId();
+ })
+ .then(function(client_id) {
+ client_ids.push(client_id, 'invalid-id');
+ var channel = new MessageChannel();
+ var saw_message = new Promise(function(resolve) {
+ channel.port1.onmessage = resolve;
+ });
+ frame.contentWindow.navigator.serviceWorker.controller.postMessage(
+ {port: channel.port2, clientIds: client_ids}, [channel.port2]);
+ return saw_message;
+ })
+ .then(function(e) {
+ assert_equals(e.data.length, 3);
+ assert_array_equals(e.data[0], expected[0]);
+ assert_array_equals(e.data[1], expected[1]);
+ assert_equals(e.data[2], expected[2]);
+ });
+ }, 'Test Clients.get()');
+
+function wait_for_clientId() {
+ return new Promise(function(resolve, reject) {
+ function get_client_id(e) {
+ window.removeEventListener('message', get_client_id);
+ resolve(e.data.clientId);
+ }
+ window.addEventListener('message', get_client_id, false);
+ });
+}
+
+var expected = [
+ /* visibilityState, focused, url, frameType */
+ ['visible', true, normalizeURL(scope) + '#1', 'nested'],
+ ['visible', false, normalizeURL(scope) + '#2', 'nested'],
+ undefined
+];
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-cross-origin-frame.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-cross-origin-frame.html
new file mode 100644
index 0000000..0977600
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-cross-origin-frame.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/get-host-info.js"></script>
+<script src="test-helpers.js"></script>
+<script>
+var host_info = get_host_info();
+var scope = 'blank.html?clients-get';
+var script = 'clients-get-worker.js';
+
+var registration;
+var worker;
+var wait_for_worker_promise = navigator.serviceWorker.getRegistration(scope)
+ .then(function(reg) {
+ if (reg)
+ return reg.unregister();
+ })
+ .then(function() {
+ return navigator.serviceWorker.register(script, {scope: scope});
+ })
+ .then(function(reg) {
+ registration = reg;
+ worker = reg.installing;
+ return new Promise(function(resolve) {
+ worker.addEventListener('statechange', function() {
+ if (worker.state == 'activated')
+ resolve();
+ });
+ });
+ });
+
+function send_result(result) {
+ window.parent.postMessage(
+ {result: result},
+ host_info['HTTP_ORIGIN']);
+}
+
+window.addEventListener('message', function(e) {
+ assert_equals(e.origin, host_info['HTTP_ORIGIN']);
+ var cross_origin_client_ids = [];
+ cross_origin_client_ids.push(e.data.clientId);
+ wait_for_worker_promise
+ .then(function() {
+ return with_iframe(scope);
+ })
+ .then(function(iframe) {
+ add_completion_callback(function() { iframe.remove(); });
+ var channel = new MessageChannel();
+ channel.port1.onmessage = function(e) {
+ registration.unregister();
+ send_result(e.data);
+ };
+ iframe.contentWindow.navigator.serviceWorker.controller.postMessage(
+ {port:channel.port2, clientIds: cross_origin_client_ids},
+ [channel.port2]);
+ });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-frame.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-frame.html
new file mode 100644
index 0000000..7c94911
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-frame.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+fetch('clientId')
+ .then(function(response) {
+ return response.text();
+ })
+ .then(function(text) {
+ parent.postMessage({clientId: text}, '*');
+ });
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-worker.js
new file mode 100644
index 0000000..0b99798
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/clients-get-worker.js
@@ -0,0 +1,42 @@
+self.onfetch = function(e) {
+ if (e.request.url.indexOf('clients-get-frame.html') >= 0) {
+ // On navigation, the client id should be null.
+ if (e.clientId === null) {
+ e.respondWith(fetch(e.request));
+ } else {
+ e.respondWith(Response.error());
+ }
+ return;
+ }
+ e.respondWith(new Response(e.clientId));
+};
+
+self.onmessage = function(e) {
+ var port = e.data.port;
+ var client_ids = e.data.clientIds;
+ var message = [];
+
+ e.waitUntil(Promise.all(
+ client_ids.map(function(client_id) {
+ return self.clients.get(client_id);
+ }))
+ .then(function(clients) {
+ // No matching client for a given id or a matched client is off-origin
+ // from the service worker.
+ if (clients.length == 1 && clients[0] == undefined) {
+ port.postMessage(clients[0]);
+ } else {
+ clients.forEach(function(client) {
+ if (client instanceof Client) {
+ message.push([client.visibilityState,
+ client.focused,
+ client.url,
+ client.frameType]);
+ } else {
+ message.push(client);
+ }
+ });
+ port.postMessage(message);
+ }
+ }));
+};
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 33a8b91..c3b6026 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -39,6 +39,7 @@ interface Client
interface Clients
method claim
method constructor
+ method get
method matchAll
method openWindow
interface CloseEvent : Event
diff --git a/third_party/WebKit/Source/modules/serviceworkers/Clients.idl b/third_party/WebKit/Source/modules/serviceworkers/Clients.idl
index d15694b..df84bec 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/Clients.idl
+++ b/third_party/WebKit/Source/modules/serviceworkers/Clients.idl
@@ -8,6 +8,7 @@
GarbageCollected,
ImplementedAs=ServiceWorkerClients,
] interface Clients {
+ [RuntimeEnabled=ServiceWorkerClientsGetID, CallWith=ScriptState] Promise<any> get(DOMString id);
[CallWith=ScriptState] Promise<sequence<Client>> matchAll(optional ClientQueryOptions options);
[RuntimeEnabled=ServiceWorkerClientAttributes, CallWith=ScriptState] Promise<WindowClient?> openWindow(USVString url);
[CallWith=ScriptState] Promise<void> claim();
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
index 198f6e2..faeda84 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.cpp
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "modules/serviceworkers/ServiceWorkerClient.h"
+#include "modules/serviceworkers/ServiceWorkerWindowClient.h"
#include "bindings/core/v8/CallbackPromiseAdapter.h"
#include "bindings/core/v8/ExceptionState.h"
@@ -14,6 +15,25 @@
namespace blink {
+ServiceWorkerClient* ServiceWorkerClient::take(ScriptPromiseResolver*, PassOwnPtr<WebServiceWorkerClientInfo> webClient)
+{
+ if (!webClient)
+ return nullptr;
+
+ switch (webClient->clientType) {
+ case WebServiceWorkerClientTypeWindow:
+ return ServiceWorkerWindowClient::create(*webClient);
+ case WebServiceWorkerClientTypeWorker:
+ case WebServiceWorkerClientTypeSharedWorker:
+ return ServiceWorkerClient::create(*webClient);
+ case WebServiceWorkerClientTypeLast:
+ ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+ ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
ServiceWorkerClient* ServiceWorkerClient::create(const WebServiceWorkerClientInfo& info)
{
return new ServiceWorkerClient(info);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
index d4fd070..4bed79f 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClient.h
@@ -16,11 +16,16 @@
namespace blink {
class ExecutionContext;
+class ScriptPromiseResolver;
class ScriptState;
class MODULES_EXPORT ServiceWorkerClient : public GarbageCollectedFinalized<ServiceWorkerClient>, public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
+ // To be used by CallbackPromiseAdapter.
+ using WebType = OwnPtr<WebServiceWorkerClientInfo>;
+
+ static ServiceWorkerClient* take(ScriptPromiseResolver*, PassOwnPtr<WebServiceWorkerClientInfo>);
static ServiceWorkerClient* create(const WebServiceWorkerClientInfo&);
virtual ~ServiceWorkerClient();
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
index ff907d2..63a5149 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.cpp
@@ -60,6 +60,37 @@ WebServiceWorkerClientType getClientType(const String& type)
return WebServiceWorkerClientTypeWindow;
}
+class GetCallback : public WebServiceWorkerClientCallbacks {
+public:
+ explicit GetCallback(ScriptPromiseResolver* resolver)
+ : m_resolver(resolver) { }
+ ~GetCallback() override { }
+
+ void onSuccess(WebPassOwnPtr<WebServiceWorkerClientInfo> webClient) override
+ {
+ OwnPtr<WebServiceWorkerClientInfo> client = webClient.release();
+ if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped())
+ return;
+ if (!client) {
+ // Resolve the promise with undefined.
+ m_resolver->resolve();
+ return;
+ }
+ m_resolver->resolve(ServiceWorkerClient::take(m_resolver, client.release()));
+ }
+
+ void onError(const WebServiceWorkerError& error) override
+ {
+ if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped())
+ return;
+ m_resolver->reject(ServiceWorkerError::take(m_resolver.get(), error));
+ }
+
+private:
+ Persistent<ScriptPromiseResolver> m_resolver;
+ WTF_MAKE_NONCOPYABLE(GetCallback);
+};
+
} // namespace
ServiceWorkerClients* ServiceWorkerClients::create()
@@ -71,6 +102,20 @@ ServiceWorkerClients::ServiceWorkerClients()
{
}
+ScriptPromise ServiceWorkerClients::get(ScriptState* scriptState, const String& id)
+{
+ ExecutionContext* executionContext = scriptState->executionContext();
+ // TODO(jungkees): May be null due to worker termination: http://crbug.com/413518.
+ if (!executionContext)
+ return ScriptPromise();
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+
+ ServiceWorkerGlobalScopeClient::from(executionContext)->getClient(id, new GetCallback(resolver));
+ return promise;
+}
+
ScriptPromise ServiceWorkerClients::matchAll(ScriptState* scriptState, const ClientQueryOptions& options)
{
ExecutionContext* executionContext = scriptState->executionContext();
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h
index 111a711..b55fb53 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerClients.h
@@ -21,6 +21,7 @@ public:
static ServiceWorkerClients* create();
// Clients.idl
+ ScriptPromise get(ScriptState*, const String& id);
ScriptPromise matchAll(ScriptState*, const ClientQueryOptions&);
ScriptPromise openWindow(ScriptState*, const String& url);
ScriptPromise claim(ScriptState*);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
index 5b8405c..44f7c7c 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeClient.h
@@ -60,6 +60,7 @@ public:
virtual ~ServiceWorkerGlobalScopeClient() { }
// Called from ServiceWorkerClients.
+ virtual void getClient(const WebString&, WebServiceWorkerClientCallbacks*) = 0;
virtual void getClients(const WebServiceWorkerClientQueryOptions&, WebServiceWorkerClientsCallbacks*) = 0;
virtual void openWindow(const WebURL&, WebServiceWorkerClientCallbacks*) = 0;
virtual void setCachedMetadata(const WebURL&, const char*, size_t) = 0;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 7713541..0b5a809 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -170,6 +170,7 @@ ScrollAnchoring
ScrollTopLeftInterop status=experimental
ServiceWorkerClientAttributes status=stable
ServiceWorkerExtendableMessageEvent status=experimental
+ServiceWorkerClientsGetID status=experimental
ServiceWorkerPerformanceTimeline status=stable
ServiceWorkerWindowClientNavigate status=stable
ShadowDOMV1 status=experimental
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
index 90f3d1a..ba5b028 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.cpp
@@ -47,6 +47,11 @@ ServiceWorkerGlobalScopeClientImpl::~ServiceWorkerGlobalScopeClientImpl()
{
}
+void ServiceWorkerGlobalScopeClientImpl::getClient(const WebString& id, WebServiceWorkerClientCallbacks* callbacks)
+{
+ m_client.getClient(id, callbacks);
+}
+
void ServiceWorkerGlobalScopeClientImpl::getClients(const WebServiceWorkerClientQueryOptions& options, WebServiceWorkerClientsCallbacks* callbacks)
{
m_client.getClients(options, callbacks);
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
index da63472..2f1f9ce 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeClientImpl.h
@@ -49,6 +49,7 @@ public:
static PassOwnPtrWillBeRawPtr<ServiceWorkerGlobalScopeClient> create(WebServiceWorkerContextClient&);
~ServiceWorkerGlobalScopeClientImpl() override;
+ void getClient(const WebString&, WebServiceWorkerClientCallbacks*) override;
void getClients(const WebServiceWorkerClientQueryOptions&, WebServiceWorkerClientsCallbacks*) override;
void openWindow(const WebURL&, WebServiceWorkerClientCallbacks*) override;
void setCachedMetadata(const WebURL&, const char*, size_t) override;
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
index b44a8aa..747effe 100644
--- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
+++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h
@@ -153,6 +153,12 @@ public:
// Ownership of the passed callbacks is transferred to the callee, callee
// should delete the callbacks after calling either onSuccess or onError.
+ // WebServiceWorkerClientInfo and WebServiceWorkerError ownerships are
+ // passed to the WebServiceWorkerClientCallbacks implementation.
+ virtual void getClient(const WebString&, WebServiceWorkerClientCallbacks* callbacks) { BLINK_ASSERT_NOT_REACHED(); }
+
+ // Ownership of the passed callbacks is transferred to the callee, callee
+ // should delete the callbacks after calling either onSuccess or onError.
// WebServiceWorkerClientsInfo and WebServiceWorkerError ownerships are
// passed to the WebServiceWorkerClientsCallbacks implementation.
virtual void getClients(const WebServiceWorkerClientQueryOptions&, WebServiceWorkerClientsCallbacks* callbacks) { BLINK_ASSERT_NOT_REACHED(); }