Commit 9fc3225d authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

[PM] Add service worker clients to the graph

Bug: 993029
Change-Id: I87e33b72d6a340c48e4a9780c21de4c8693e42f0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2175552Reviewed-by: default avatarKenichi Ishibashi <bashi@chromium.org>
Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773049}
parent 7a14ada9
...@@ -119,6 +119,8 @@ static_library("performance_manager") { ...@@ -119,6 +119,8 @@ static_library("performance_manager") {
"render_process_host_proxy.cc", "render_process_host_proxy.cc",
"render_process_user_data.cc", "render_process_user_data.cc",
"render_process_user_data.h", "render_process_user_data.h",
"service_worker_client.cc",
"service_worker_client.h",
"service_worker_context_adapter.cc", "service_worker_context_adapter.cc",
"service_worker_context_adapter.h", "service_worker_context_adapter.h",
"tab_helper_frame_node_source.cc", "tab_helper_frame_node_source.cc",
......
...@@ -9,5 +9,6 @@ include_rules = [ ...@@ -9,5 +9,6 @@ include_rules = [
"+services/metrics/public/cpp", "+services/metrics/public/cpp",
"+services/service_manager/public/cpp", "+services/service_manager/public/cpp",
"+third_party/blink/public/mojom/favicon", "+third_party/blink/public/mojom/favicon",
"+third_party/blink/public/mojom/service_worker",
"+third_party/leveldatabase", "+third_party/leveldatabase",
] ]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/performance_manager/service_worker_client.h"
ServiceWorkerClient::ServiceWorkerClient(
content::GlobalFrameRoutingId render_frame_host_id)
: type_(blink::mojom::ServiceWorkerClientType::kWindow),
render_frame_host_id_(render_frame_host_id) {}
ServiceWorkerClient::ServiceWorkerClient(
content::DedicatedWorkerId dedicated_worker_id)
: type_(blink::mojom::ServiceWorkerClientType::kDedicatedWorker),
dedicated_worker_id_(dedicated_worker_id) {}
ServiceWorkerClient::ServiceWorkerClient(
content::SharedWorkerId shared_worker_id)
: type_(blink::mojom::ServiceWorkerClientType::kSharedWorker),
shared_worker_id_(shared_worker_id) {}
ServiceWorkerClient::ServiceWorkerClient(const ServiceWorkerClient& other) =
default;
ServiceWorkerClient& ServiceWorkerClient::operator=(
const ServiceWorkerClient& other) = default;
ServiceWorkerClient::~ServiceWorkerClient() = default;
content::GlobalFrameRoutingId ServiceWorkerClient::GetRenderFrameHostId()
const {
DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kWindow);
return render_frame_host_id_;
}
content::DedicatedWorkerId ServiceWorkerClient::GetDedicatedWorkerId() const {
DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kDedicatedWorker);
return dedicated_worker_id_;
}
content::SharedWorkerId ServiceWorkerClient::GetSharedWorkerId() const {
DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kSharedWorker);
return shared_worker_id_;
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_SERVICE_WORKER_CLIENT_H_
#define COMPONENTS_PERFORMANCE_MANAGER_SERVICE_WORKER_CLIENT_H_
#include "content/public/browser/dedicated_worker_id.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/shared_worker_id.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
// Represents a client of a service worker node.
//
// This class is essentially a tagged union where only the field corresponding
// to the |type()| can be accessed.
class ServiceWorkerClient {
public:
explicit ServiceWorkerClient(
content::GlobalFrameRoutingId render_frame_host_id);
explicit ServiceWorkerClient(content::DedicatedWorkerId dedicated_worker_id);
explicit ServiceWorkerClient(content::SharedWorkerId shared_worker_id);
ServiceWorkerClient(const ServiceWorkerClient& other);
ServiceWorkerClient& operator=(const ServiceWorkerClient& other);
~ServiceWorkerClient();
blink::mojom::ServiceWorkerClientType type() const { return type_; }
content::GlobalFrameRoutingId GetRenderFrameHostId() const;
content::DedicatedWorkerId GetDedicatedWorkerId() const;
content::SharedWorkerId GetSharedWorkerId() const;
private:
// The client type.
blink::mojom::ServiceWorkerClientType type_;
// The frame tree node ID, if this is a window client.
content::GlobalFrameRoutingId render_frame_host_id_;
union {
// The ID of the client, if this is a dedicated worker client.
content::DedicatedWorkerId dedicated_worker_id_;
// The ID of the client, if this is a shared worker client.
content::SharedWorkerId shared_worker_id_;
};
};
#endif // COMPONENTS_PERFORMANCE_MANAGER_SERVICE_WORKER_CLIENT_H_
...@@ -255,12 +255,36 @@ void ServiceWorkerContextAdapter::OnVersionStoppedRunning(int64_t version_id) { ...@@ -255,12 +255,36 @@ void ServiceWorkerContextAdapter::OnVersionStoppedRunning(int64_t version_id) {
observer.OnVersionStoppedRunning(version_id); observer.OnVersionStoppedRunning(version_id);
} }
void ServiceWorkerContextAdapter::OnControlleeAdded(
int64_t version_id,
const std::string& client_uuid,
const content::ServiceWorkerClientInfo& client_info) {
for (auto& observer : observer_list_)
observer.OnControlleeAdded(version_id, client_uuid, client_info);
}
void ServiceWorkerContextAdapter::OnControlleeRemoved(
int64_t version_id,
const std::string& client_uuid) {
for (auto& observer : observer_list_)
observer.OnControlleeRemoved(version_id, client_uuid);
}
void ServiceWorkerContextAdapter::OnNoControllees(int64_t version_id, void ServiceWorkerContextAdapter::OnNoControllees(int64_t version_id,
const GURL& scope) { const GURL& scope) {
for (auto& observer : observer_list_) for (auto& observer : observer_list_)
observer.OnNoControllees(version_id, scope); observer.OnNoControllees(version_id, scope);
} }
void ServiceWorkerContextAdapter::OnControlleeNavigationCommitted(
int64_t version_id,
const std::string& uuid,
content::GlobalFrameRoutingId render_frame_host_id) {
for (auto& observer : observer_list_)
observer.OnControlleeNavigationCommitted(version_id, uuid,
render_frame_host_id);
}
void ServiceWorkerContextAdapter::OnReportConsoleMessage( void ServiceWorkerContextAdapter::OnReportConsoleMessage(
int64_t version_id, int64_t version_id,
const content::ConsoleMessage& message) { const content::ConsoleMessage& message) {
......
...@@ -96,7 +96,17 @@ class ServiceWorkerContextAdapter ...@@ -96,7 +96,17 @@ class ServiceWorkerContextAdapter
int64_t version_id, int64_t version_id,
const content::ServiceWorkerRunningInfo& running_info) override; const content::ServiceWorkerRunningInfo& running_info) override;
void OnVersionStoppedRunning(int64_t version_id) override; void OnVersionStoppedRunning(int64_t version_id) override;
void OnControlleeAdded(
int64_t version_id,
const std::string& client_uuid,
const content::ServiceWorkerClientInfo& client_info) override;
void OnControlleeRemoved(int64_t version_id,
const std::string& client_uuid) override;
void OnNoControllees(int64_t version_id, const GURL& scope) override; void OnNoControllees(int64_t version_id, const GURL& scope) override;
void OnControlleeNavigationCommitted(
int64_t version_id,
const std::string& uuid,
content::GlobalFrameRoutingId render_frame_host_id) override;
void OnReportConsoleMessage(int64_t version_id, void OnReportConsoleMessage(int64_t version_id,
const content::ConsoleMessage& message) override; const content::ConsoleMessage& message) override;
void OnDestruct(ServiceWorkerContext* context) override; void OnDestruct(ServiceWorkerContext* context) override;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "components/performance_manager/service_worker_client.h"
#include "content/public/browser/dedicated_worker_id.h" #include "content/public/browser/dedicated_worker_id.h"
#include "content/public/browser/dedicated_worker_service.h" #include "content/public/browser/dedicated_worker_service.h"
#include "content/public/browser/global_routing_id.h" #include "content/public/browser/global_routing_id.h"
...@@ -31,7 +32,26 @@ class WorkerNodeImpl; ...@@ -31,7 +32,26 @@ class WorkerNodeImpl;
// This class keeps track of running workers of all types for a single browser // This class keeps track of running workers of all types for a single browser
// context and handles the ownership of the worker nodes. // context and handles the ownership of the worker nodes.
// //
// TODO(https://crbug.com/993029): Add support for service workers. // Most of the complexity of this class is tracking every worker's clients. Each
// type of worker handles them a bit differently.
//
// The simplest case is dedicated workers, where each worker always has exactly
// one frame client. Technically, it is possible to create a nested dedicated
// worker, but for now they are treated as child of the ancestor frame.
//
// Shared workers are quite similar to dedicated workers but they can have any
// number of clients. Also, a shared worker can temporary appear to have no
// clients shortly after being created and just before being destroyed.
//
// Service workers are more complicated to handle. They also can have any number
// of clients, but they aren't only frames. They could also be dedicated worker
// and shared worker clients. These different types of client are tracked using
// the ServiceWorkerClient class. Also, because of the important role the
// service worker plays with frame navigations, the service worker can be
// created before its first client's navigation has committed to a
// RenderFrameHost. So when a OnControlleeAdded() notification is received for
// a client frame, it is necessary to wait until the render frame host was
// determined.
class WorkerWatcher : public content::DedicatedWorkerService::Observer, class WorkerWatcher : public content::DedicatedWorkerService::Observer,
public content::SharedWorkerService::Observer, public content::SharedWorkerService::Observer,
public content::ServiceWorkerContextObserver { public content::ServiceWorkerContextObserver {
...@@ -76,20 +96,61 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer, ...@@ -76,20 +96,61 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer,
content::GlobalFrameRoutingId render_frame_host_id) override; content::GlobalFrameRoutingId render_frame_host_id) override;
// content::ServiceWorkerContextObserver: // content::ServiceWorkerContextObserver:
// Note: If you add a new function here, make sure it is also added to
// ServiceWorkerContextAdapter.
void OnVersionStartedRunning( void OnVersionStartedRunning(
int64_t version_id, int64_t version_id,
const content::ServiceWorkerRunningInfo& running_info) override; const content::ServiceWorkerRunningInfo& running_info) override;
void OnVersionStoppedRunning(int64_t version_id) override; void OnVersionStoppedRunning(int64_t version_id) override;
void OnControlleeAdded(
int64_t version_id,
const std::string& client_uuid,
const content::ServiceWorkerClientInfo& client_info) override;
void OnControlleeRemoved(int64_t version_id,
const std::string& client_uuid) override;
void OnControlleeNavigationCommitted(
int64_t version_id,
const std::string& client_uuid,
content::GlobalFrameRoutingId render_frame_host_id) override;
private: private:
friend class WorkerWatcherTest; friend class WorkerWatcherTest;
void ConnectClient(WorkerNodeImpl* worker_node, // Posts a task to the PM graph to connect/disconnect |worker_node| with the
content::GlobalFrameRoutingId client_render_frame_host_id); // frame node associated to |client_render_frame_host_id|.
void DisconnectClient( void ConnectFrameClient(
WorkerNodeImpl* worker_node,
content::GlobalFrameRoutingId client_render_frame_host_id);
void DisconnectFrameClient(
WorkerNodeImpl* worker_node, WorkerNodeImpl* worker_node,
content::GlobalFrameRoutingId client_render_frame_host_id); content::GlobalFrameRoutingId client_render_frame_host_id);
// Posts a task to the PM graph to connect/disconnect |worker_node| with the
// dedicated worker node associated to |client_dedicated_worker_id|.
void ConnectDedicatedWorkerClient(
WorkerNodeImpl* worker_node,
content::DedicatedWorkerId client_dedicated_worker_id);
void DisconnectDedicatedWorkerClient(
WorkerNodeImpl* worker_node,
content::DedicatedWorkerId client_dedicated_worker_id);
// Posts a task to the PM graph to connect/disconnect |worker_node| with the
// shared worker node associated to |client_shared_worker_id|.
void ConnectSharedWorkerClient(
WorkerNodeImpl* worker_node,
content::SharedWorkerId client_shared_worker_id);
void DisconnectSharedWorkerClient(
WorkerNodeImpl* worker_node,
content::SharedWorkerId client_shared_worker_id);
// Posts a task to the PM graph to connect/disconnect |service_worker_node|
// with all of its existing clients. Called when a service worker starts/stops
// running.
void ConnectAllServiceWorkerClients(WorkerNodeImpl* service_worker_node,
int64_t version_id);
void DisconnectAllServiceWorkerClients(WorkerNodeImpl* service_worker_node,
int64_t version_id);
void OnBeforeFrameNodeRemoved( void OnBeforeFrameNodeRemoved(
content::GlobalFrameRoutingId render_frame_host_id, content::GlobalFrameRoutingId render_frame_host_id,
FrameNodeImpl* frame_node); FrameNodeImpl* frame_node);
...@@ -143,13 +204,31 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer, ...@@ -143,13 +204,31 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer,
base::flat_map<int64_t /*version_id*/, std::unique_ptr<WorkerNodeImpl>> base::flat_map<int64_t /*version_id*/, std::unique_ptr<WorkerNodeImpl>>
service_worker_nodes_; service_worker_nodes_;
// Maps each frame to the shared workers that this frame is a client of. This // Keeps track of frame clients that are awaiting the navigation commit
// is used when a frame is torn down before the OnBeforeWorkerTerminated() is // notification. Used for service workers only.
// received, to ensure the deletion of the worker nodes in the right order base::flat_set<std::string /*client_uuid*/> client_frames_awaiting_commit_;
// (workers before frames).
// Maps each service worker to its clients.
base::flat_map<
int64_t /*version_id*/,
base::flat_map<std::string /*client_uuid*/, ServiceWorkerClient>>
service_worker_clients_;
// Maps each frame to the workers that this frame is a client of in the graph.
// This is used when a frame is torn down before the
// OnBeforeWorkerTerminated() is received, to ensure the deletion of the
// worker nodes in the right order (workers before frames).
base::flat_map<content::GlobalFrameRoutingId, base::flat_set<WorkerNodeImpl*>> base::flat_map<content::GlobalFrameRoutingId, base::flat_set<WorkerNodeImpl*>>
frame_node_child_workers_; frame_node_child_workers_;
// Maps each worker to the workers that this worker is a client of.
base::flat_map<content::DedicatedWorkerId, base::flat_set<WorkerNodeImpl*>>
dedicated_worker_child_workers_;
// Maps each worker to the workers that this worker is a client of.
base::flat_map<content::SharedWorkerId, base::flat_set<WorkerNodeImpl*>>
shared_worker_child_workers_;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
// Keeps track of how many OnClientRemoved() calls are expected for an // Keeps track of how many OnClientRemoved() calls are expected for an
// existing worker. This happens when OnBeforeFrameNodeRemoved() is invoked // existing worker. This happens when OnBeforeFrameNodeRemoved() is invoked
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment