1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_CLIENT_CONNECTION_MANAGER_H_
#define COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_CLIENT_CONNECTION_MANAGER_H_
#include <unordered_set>
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host_creation_observer.h"
#include "content/public/browser/render_process_host_observer.h"
namespace content {
class RenderProcessHost;
} // namespace content
namespace heap_profiling {
class Controller;
enum class Mode;
// This class is responsible for connecting HeapProfilingClients to the
// HeapProfilingService.
// * It inherits from content::RenderProcessHostCreationObserver to listen for
// the creation of the renderer processes.
// * It registers itself as a content::BrowserChildProcessObserver to listen
// for the creation of non-renderer processes.
// When a new process is created, it checks the current |Mode| to see whether
// the process should be profiled. If so, it grabs the HeapProfilingClient from
// the newly created process and connects it to the HeapProfilingService.
//
// This class is intended to be used from the browser/privileged process of the
// embedder.
//
// This class must be constructed/accessed/destroyed from the UI thread.
//
// This class can be subclassed for exactly one reason: to allow embedders to
// override AllowedToProfileRenderer in order to prevent incognito renderers
// from being profiled.
class ClientConnectionManager
: public content::BrowserChildProcessObserver,
public content::RenderProcessHostCreationObserver,
public content::RenderProcessHostObserver {
public:
// The owner of this instance must guarantee that |controller_| outlives this
// class.
// |controller| must be bound to the IO thread.
ClientConnectionManager(base::WeakPtr<Controller> controller, Mode mode);
ClientConnectionManager(const ClientConnectionManager&) = delete;
ClientConnectionManager& operator=(const ClientConnectionManager&) = delete;
~ClientConnectionManager() override;
// Start must be called immediately after the constructor. The only reason
// that this is not a part of the constructor is to allow tests to skip this
// step.
void Start();
Mode GetMode();
// In addition to profiling `pid`, this will change the Mode to kManual. From
// here on out, the caller must manually specify processes to be profiled.
// Invokes `started_profiling_closure` if and when profiling starts
// successfully.
void StartProfilingProcess(base::ProcessId pid,
mojom::ProfilingService::AddProfilingClientCallback
started_profiling_closure);
virtual bool AllowedToProfileRenderer(content::RenderProcessHost* host);
private:
FRIEND_TEST_ALL_PREFIXES(ChromeClientConnectionManager,
ShouldProfileNewRenderer);
// Exists for testing only.
void SetModeForTesting(Mode mode);
// New processes will be profiled as they are created. Existing processes msut
// be manually checked upon creation.
void StartProfilingExistingProcessesIfNecessary();
// BrowserChildProcessObserver
// Observe connection of non-renderer child processes.
void BrowserChildProcessLaunchedAndConnected(
const content::ChildProcessData& data) override;
void StartProfilingNonRendererChild(
const content::ChildProcessData& data,
mojom::ProfilingService::AddProfilingClientCallback
started_profiling_closure);
// content::RenderProcessHostCreationObserver
void OnRenderProcessHostCreated(content::RenderProcessHost* host) override;
// RenderProcessHostObserver:
// RenderProcessHostDestroyed() corresponds to death of an underlying
// RenderProcess. RenderProcessExited() corresponds to when the
// RenderProcessHost's lifetime is ending. Ideally, we'd only listen to the
// former, but if the RenderProcessHost is destroyed before the RenderProcess,
// then the former is never observed.
void RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
bool ShouldProfileNewRenderer(content::RenderProcessHost* renderer);
void StartProfilingRenderer(
content::RenderProcessHost* renderer,
mojom::ProfilingService::AddProfilingClientCallback
started_profiling_closure);
// The owner of this instance must guarantee that |controller_| outlives this
// class.
// |controller_| must be bound to the IO thread.
base::WeakPtr<Controller> controller_;
Mode mode_;
base::ScopedMultiSourceObservation<content::RenderProcessHost,
content::RenderProcessHostObserver>
host_observation_{this};
// This is used to identify the currently profiled renderers. Elements should
// only be accessed on the UI thread and their values should be considered
// opaque.
//
// Semantically, the elements must be something that identifies which specific
// RenderProcess is being profiled. When the underlying RenderProcess goes
// away, the element must be removed. The RenderProcessHost pointer and the
// RenderProcessHostCreationObserver notification can be used to provide these
// semantics.
//
// This variable represents renderers that have been instructed to start
// profiling - it does not reflect whether a renderer is currently still being
// profiled. That information is only known by the profiling service, and for
// simplicity, it's easier to just track this variable in this process.
std::unordered_set<raw_ptr<void, CtnExperimental>> profiled_renderers_;
};
} // namespace heap_profiling
#endif // COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_CLIENT_CONNECTION_MANAGER_H_
|