| Index: content/browser/service_worker/service_worker_client_utils.cc
|
| diff --git a/content/browser/service_worker/service_worker_client_navigation_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
|
| similarity index 55%
|
| rename from content/browser/service_worker/service_worker_client_navigation_utils.cc
|
| rename to content/browser/service_worker/service_worker_client_utils.cc
|
| index 5147bd12dcabdcce324dc21dabe31aeac8d04a17..26ef4d35f181bd9a43c4bb5922c5698da78e6aa3 100644
|
| --- a/content/browser/service_worker/service_worker_client_navigation_utils.cc
|
| +++ b/content/browser/service_worker/service_worker_client_utils.cc
|
| @@ -2,15 +2,19 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/browser/service_worker/service_worker_client_navigation_utils.h"
|
| +#include "content/browser/service_worker/service_worker_client_utils.h"
|
| +
|
| +#include <algorithm>
|
|
|
| #include "base/macros.h"
|
| #include "content/browser/frame_host/frame_tree_node.h"
|
| #include "content/browser/frame_host/render_frame_host_impl.h"
|
| #include "content/browser/service_worker/service_worker_context_core.h"
|
| #include "content/browser/service_worker/service_worker_context_wrapper.h"
|
| +#include "content/browser/service_worker/service_worker_version.h"
|
| #include "content/browser/storage_partition_impl.h"
|
| #include "content/common/service_worker/service_worker_client_info.h"
|
| +#include "content/common/service_worker/service_worker_types.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/content_browser_client.h"
|
| #include "content/public/browser/page_navigator.h"
|
| @@ -20,11 +24,13 @@
|
| #include "url/gurl.h"
|
|
|
| namespace content {
|
| -namespace service_worker_client_navigation_utils {
|
| +namespace service_worker_client_utils {
|
|
|
| namespace {
|
|
|
| using OpenURLCallback = base::Callback<void(int, int)>;
|
| +using GetWindowClientsCallback =
|
| + base::Callback<void(scoped_ptr<ServiceWorkerClients>)>;
|
|
|
| // The OpenURLObserver class is a WebContentsObserver that will wait for a
|
| // WebContents to be initialized, run the |callback| passed to its constructor
|
| @@ -200,6 +206,141 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
|
| callback.Run(SERVICE_WORKER_OK, std::string(), ServiceWorkerClientInfo());
|
| }
|
|
|
| +void AddWindowClient(
|
| + ServiceWorkerProviderHost* host,
|
| + std::vector<base::Tuple<int, int, std::string>>* client_info) {
|
| + if (host->client_type() != blink::WebServiceWorkerClientTypeWindow)
|
| + return;
|
| + client_info->push_back(base::MakeTuple(host->process_id(), host->frame_id(),
|
| + host->client_uuid()));
|
| +}
|
| +
|
| +void AddNonWindowClient(ServiceWorkerProviderHost* host,
|
| + const ServiceWorkerClientQueryOptions& options,
|
| + ServiceWorkerClients* clients) {
|
| + blink::WebServiceWorkerClientType host_client_type = host->client_type();
|
| + if (host_client_type == blink::WebServiceWorkerClientTypeWindow)
|
| + return;
|
| + if (options.client_type != blink::WebServiceWorkerClientTypeAll &&
|
| + 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();
|
| + clients->push_back(client_info);
|
| +}
|
| +
|
| +void OnGetWindowClientsOnUI(
|
| + // The tuple contains process_id, frame_id, client_uuid.
|
| + const std::vector<base::Tuple<int, int, std::string>>& clients_info,
|
| + const GURL& script_url,
|
| + const GetWindowClientsCallback& callback) {
|
| + scoped_ptr<ServiceWorkerClients> clients(new ServiceWorkerClients);
|
| +
|
| + for (const auto& it : clients_info) {
|
| + ServiceWorkerClientInfo info =
|
| + ServiceWorkerProviderHost::GetWindowClientInfoOnUI(base::get<0>(it),
|
| + base::get<1>(it));
|
| +
|
| + // If the request to the provider_host returned an empty
|
| + // ServiceWorkerClientInfo, that means that it wasn't possible to associate
|
| + // it with a valid RenderFrameHost. It might be because the frame was killed
|
| + // or navigated in between.
|
| + if (info.IsEmpty())
|
| + continue;
|
| +
|
| + // We can get info for a frame that was navigating end ended up with a
|
| + // different URL than expected. In such case, we should make sure to not
|
| + // expose cross-origin WindowClient.
|
| + if (info.url.GetOrigin() != script_url.GetOrigin())
|
| + continue;
|
| +
|
| + info.client_uuid = base::get<2>(it);
|
| + clients->push_back(info);
|
| + }
|
| +
|
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
| + base::Bind(callback, base::Passed(&clients)));
|
| +}
|
| +
|
| +struct ServiceWorkerClientInfoSortMRU {
|
| + bool operator()(const ServiceWorkerClientInfo& a,
|
| + const ServiceWorkerClientInfo& b) const {
|
| + return a.last_focus_time > b.last_focus_time;
|
| + }
|
| +};
|
| +
|
| +void DidGetClients(const ClientsCallback& callback,
|
| + ServiceWorkerClients* clients) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + // Sort clients so that the most recently active tab is in the front.
|
| + std::sort(clients->begin(), clients->end(), ServiceWorkerClientInfoSortMRU());
|
| +
|
| + callback.Run(clients);
|
| +}
|
| +
|
| +void GetNonWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
|
| + const ServiceWorkerClientQueryOptions& options,
|
| + ServiceWorkerClients* clients) {
|
| + if (!options.include_uncontrolled) {
|
| + for (auto& controllee : controller->controllee_map())
|
| + AddNonWindowClient(controllee.second, options, clients);
|
| + } else if (controller->context()) {
|
| + GURL origin = controller->script_url().GetOrigin();
|
| + for (auto it = controller->context()->GetClientProviderHostIterator(origin);
|
| + !it->IsAtEnd(); it->Advance()) {
|
| + AddNonWindowClient(it->GetProviderHost(), options, clients);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void DidGetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
|
| + const ServiceWorkerClientQueryOptions& options,
|
| + const ClientsCallback& callback,
|
| + scoped_ptr<ServiceWorkerClients> clients) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (options.client_type == blink::WebServiceWorkerClientTypeAll)
|
| + GetNonWindowClients(controller, options, clients.get());
|
| + DidGetClients(callback, clients.get());
|
| +}
|
| +
|
| +void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
|
| + const ServiceWorkerClientQueryOptions& options,
|
| + const ClientsCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + DCHECK(options.client_type == blink::WebServiceWorkerClientTypeWindow ||
|
| + options.client_type == blink::WebServiceWorkerClientTypeAll);
|
| +
|
| + std::vector<base::Tuple<int, int, std::string>> clients_info;
|
| + if (!options.include_uncontrolled) {
|
| + for (auto& controllee : controller->controllee_map())
|
| + AddWindowClient(controllee.second, &clients_info);
|
| + } else if (controller->context()) {
|
| + GURL origin = controller->script_url().GetOrigin();
|
| + for (auto it = controller->context()->GetClientProviderHostIterator(origin);
|
| + !it->IsAtEnd(); it->Advance()) {
|
| + AddWindowClient(it->GetProviderHost(), &clients_info);
|
| + }
|
| + }
|
| +
|
| + if (clients_info.empty()) {
|
| + DidGetWindowClients(controller, options, callback,
|
| + make_scoped_ptr(new ServiceWorkerClients));
|
| + return;
|
| + }
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(
|
| + &OnGetWindowClientsOnUI, clients_info, controller->script_url(),
|
| + base::Bind(&DidGetWindowClients, controller, options, callback)));
|
| +}
|
| +
|
| } // namespace
|
|
|
| void OpenWindow(const GURL& url,
|
| @@ -230,5 +371,27 @@ void NavigateClient(const GURL& url,
|
| base::Bind(&DidNavigate, context, script_url.GetOrigin(), callback)));
|
| }
|
|
|
| -} // namespace service_worker_client_navigation_utils
|
| +void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
|
| + const ServiceWorkerClientQueryOptions& options,
|
| + const ClientsCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + ServiceWorkerClients clients;
|
| + if (!controller->HasControllee() && !options.include_uncontrolled) {
|
| + DidGetClients(callback, &clients);
|
| + return;
|
| + }
|
| +
|
| + // For Window clients we want to query the info on the UI thread first.
|
| + if (options.client_type == blink::WebServiceWorkerClientTypeWindow ||
|
| + options.client_type == blink::WebServiceWorkerClientTypeAll) {
|
| + GetWindowClients(controller, options, callback);
|
| + return;
|
| + }
|
| +
|
| + GetNonWindowClients(controller, options, &clients);
|
| + DidGetClients(callback, &clients);
|
| +}
|
| +
|
| +} // namespace service_worker_client_utils
|
| } // namespace content
|
|
|