blob: 4e9c45f106168a4a7c1dd96d0adc750b28f42c2a [file] [log] [blame]
// Copyright 2019 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_SHARED_WORKER_WATCHER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_SHARED_WORKER_WATCHER_H_
#include <memory>
#include <string>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "content/public/browser/shared_worker_service.h"
namespace content {
class SharedWorkerInstance;
}
namespace performance_manager {
class FrameNodeImpl;
class FrameNodeSource;
class ProcessNodeSource;
class WorkerNodeImpl;
// This class keeps track of running shared workers for a single browser context
// and handles the ownership of the worker nodes.
class SharedWorkerWatcher : public content::SharedWorkerService::Observer {
public:
SharedWorkerWatcher(const std::string& browser_context_id,
content::SharedWorkerService* shared_worker_service,
ProcessNodeSource* process_node_source,
FrameNodeSource* frame_node_source);
~SharedWorkerWatcher() override;
// Cleans up this instance and ensures shared worker nodes are correctly
// destroyed on the PM graph.
void TearDown();
// content::SharedWorkerService::Observer:
void OnWorkerStarted(const content::SharedWorkerInstance& instance,
int worker_process_id,
const base::UnguessableToken& dev_tools_token) override;
void OnBeforeWorkerTerminated(
const content::SharedWorkerInstance& instance) override;
void OnClientAdded(const content::SharedWorkerInstance& instance,
int client_process_id,
int frame_id) override;
void OnClientRemoved(const content::SharedWorkerInstance& instance,
int client_process_id,
int frame_id) override;
private:
friend class SharedWorkerWatcherTest;
void OnBeforeFrameNodeRemoved(int render_process_id,
int frame_id,
FrameNodeImpl* frame_node);
bool AddChildWorker(int render_process_id,
int frame_id,
WorkerNodeImpl* child_worker_node);
bool RemoveChildWorker(int render_process_id,
int frame_id,
WorkerNodeImpl* child_worker_node);
// Helper function to retrieve an existing worker node.
WorkerNodeImpl* GetWorkerNode(const content::SharedWorkerInstance& instance);
// The ID of the BrowserContext who owns the shared worker service.
const std::string browser_context_id_;
// Observes the SharedWorkerService for this browser context.
ScopedObserver<content::SharedWorkerService,
content::SharedWorkerService::Observer>
shared_worker_service_observer_;
// Used to retrieve an existing process node from its render process ID.
ProcessNodeSource* const process_node_source_;
// Used to retrieve an existing frame node from its render process ID and
// frame ID. Also allows to subscribe to a frame's deletion notification.
FrameNodeSource* const frame_node_source_;
// Maps each SharedWorkerInstance to its worker node.
base::flat_map<content::SharedWorkerInstance, std::unique_ptr<WorkerNodeImpl>>
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).
struct FrameInfo {
int render_process_id;
int frame_id;
};
// Comparison operator to allow using FrameInfo as a key.
friend bool operator<(const FrameInfo& lhs, const FrameInfo& rhs);
base::flat_map<FrameInfo, base::flat_set<WorkerNodeImpl*>>
frame_node_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
// before OnClientRemoved().
base::flat_map<WorkerNodeImpl*, int> clients_to_remove_;
#endif // DCHECK_IS_ON()
DISALLOW_COPY_AND_ASSIGN(SharedWorkerWatcher);
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_SHARED_WORKER_WATCHER_H_