diff options
| author | jungkee.song <jungkee.song@samsung.com> | 2016-02-22 16:36:33 -0800 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2016-02-23 00:38:08 +0000 |
| commit | 0ca977be9dbe2582e8f18415bd9299efd36fd329 (patch) | |
| tree | cafa9477ab28c9a6c4c59380a6d86d0434380ef4 | |
| parent | af548e472716edd2834167d6c8cadc799ee30779 (diff) | |
| download | chromium_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}
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(); } |
