Commit f9ad5552 authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

[PM] Add service worker clients to the graph

Bug: 993029
Change-Id: I898a87e8ea515778f1edcb518ada06ddf3d8e8ca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2355089Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800352}
parent f49e90c4
......@@ -128,6 +128,8 @@ static_library("performance_manager") {
"render_process_host_proxy.cc",
"render_process_user_data.cc",
"render_process_user_data.h",
"service_worker_client.cc",
"service_worker_client.h",
"service_worker_context_adapter.cc",
"service_worker_context_adapter.h",
"tab_helper_frame_node_source.cc",
......
// 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(
blink::DedicatedWorkerToken dedicated_worker_token)
: type_(blink::mojom::ServiceWorkerClientType::kDedicatedWorker),
worker_token_(dedicated_worker_token) {}
ServiceWorkerClient::ServiceWorkerClient(
blink::SharedWorkerToken shared_worker_token)
: type_(blink::mojom::ServiceWorkerClientType::kSharedWorker),
worker_token_(shared_worker_token) {}
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_;
}
blink::DedicatedWorkerToken ServiceWorkerClient::GetDedicatedWorkerToken()
const {
DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kDedicatedWorker);
return worker_token_.GetAs<blink::DedicatedWorkerToken>();
}
blink::SharedWorkerToken ServiceWorkerClient::GetSharedWorkerToken() const {
DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kSharedWorker);
return worker_token_.GetAs<blink::SharedWorkerToken>();
}
// 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/global_routing_id.h"
#include "content/public/browser/service_worker_client_info.h"
#include "third_party/blink/public/common/tokens/tokens.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(
blink::DedicatedWorkerToken dedicated_worker_token);
explicit ServiceWorkerClient(blink::SharedWorkerToken shared_worker_token);
ServiceWorkerClient(const ServiceWorkerClient& other);
ServiceWorkerClient& operator=(const ServiceWorkerClient& other);
~ServiceWorkerClient();
blink::mojom::ServiceWorkerClientType type() const { return type_; }
content::GlobalFrameRoutingId GetRenderFrameHostId() const;
blink::DedicatedWorkerToken GetDedicatedWorkerToken() const;
blink::SharedWorkerToken GetSharedWorkerToken() const;
private:
// The client type.
blink::mojom::ServiceWorkerClientType type_;
union {
// The frame tree node ID, if this is a window client.
content::GlobalFrameRoutingId render_frame_host_id_;
// The token of the client, if this is a worker client.
content::DedicatedOrSharedWorkerToken worker_token_;
};
};
#endif // COMPONENTS_PERFORMANCE_MANAGER_SERVICE_WORKER_CLIENT_H_
......@@ -310,6 +310,15 @@ void ServiceWorkerContextAdapter::OnNoControllees(int64_t version_id,
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(
int64_t version_id,
const GURL& scope,
......
......@@ -107,6 +107,10 @@ class ServiceWorkerContextAdapter
void OnControlleeRemoved(int64_t version_id,
const std::string& client_uuid) 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,
const GURL& scope,
const content::ConsoleMessage& message) override;
......
......@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "base/sequence_checker.h"
#include "components/performance_manager/service_worker_client.h"
#include "content/public/browser/dedicated_worker_service.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/service_worker_context.h"
......@@ -31,7 +32,26 @@ class WorkerNodeImpl;
// This class keeps track of running workers of all types for a single browser
// 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 temporarily 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,
public content::SharedWorkerService::Observer,
public content::ServiceWorkerContextObserver {
......@@ -77,20 +97,61 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer,
content::GlobalFrameRoutingId render_frame_host_id) override;
// content::ServiceWorkerContextObserver:
// Note: If you add a new function here, make sure it is also added to
// ServiceWorkerContextAdapter.
void OnVersionStartedRunning(
int64_t version_id,
const content::ServiceWorkerRunningInfo& running_info) 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:
friend class WorkerWatcherTest;
void ConnectClient(WorkerNodeImpl* worker_node,
// Posts a task to the PM graph to connect/disconnect |worker_node| with the
// frame node associated to |client_render_frame_host_id|.
void ConnectFrameClient(
WorkerNodeImpl* worker_node,
content::GlobalFrameRoutingId client_render_frame_host_id);
void DisconnectClient(
void DisconnectFrameClient(
WorkerNodeImpl* worker_node,
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_token|.
void ConnectDedicatedWorkerClient(
WorkerNodeImpl* worker_node,
blink::DedicatedWorkerToken client_dedicated_worker_token);
void DisconnectDedicatedWorkerClient(
WorkerNodeImpl* worker_node,
blink::DedicatedWorkerToken client_dedicated_worker_token);
// 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,
blink::SharedWorkerToken client_shared_worker_id);
void DisconnectSharedWorkerClient(
WorkerNodeImpl* worker_node,
blink::SharedWorkerToken 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(
content::GlobalFrameRoutingId render_frame_host_id,
FrameNodeImpl* frame_node);
......@@ -147,13 +208,31 @@ class WorkerWatcher : public content::DedicatedWorkerService::Observer,
base::flat_map<int64_t /*version_id*/, std::unique_ptr<WorkerNodeImpl>>
service_worker_nodes_;
// Maps each frame to the shared workers that this frame is a client of. 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).
// Keeps track of frame clients that are awaiting the navigation commit
// notification. Used for service workers only.
base::flat_set<std::string /*client_uuid*/> client_frames_awaiting_commit_;
// 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*>>
frame_node_child_workers_;
// Maps each dedicated worker to all its child workers.
base::flat_map<blink::DedicatedWorkerToken, base::flat_set<WorkerNodeImpl*>>
dedicated_worker_child_workers_;
// Maps each shared worker to all its child workers.
base::flat_map<blink::SharedWorkerToken, base::flat_set<WorkerNodeImpl*>>
shared_worker_child_workers_;
#if DCHECK_IS_ON()
// Keeps track of how many OnClientRemoved() calls are expected for an
// 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