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
154
content / services / auction_worklet / auction_v8_devtools_agent.h [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_SERVICES_AUCTION_WORKLET_AUCTION_V8_DEVTOOLS_AGENT_H_
#define CONTENT_SERVICES_AUCTION_WORKLET_AUCTION_V8_DEVTOOLS_AGENT_H_
#include <map>
#include <set>
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/unique_associated_receiver_set.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
#include "v8/include/v8-inspector.h"
namespace auction_worklet {
class AuctionV8Helper;
class AuctionV8DevToolsSession;
class DebugCommandQueue;
// Implementation of blink.mojom.DevToolsAgent for things run via
// AuctionV8Helper.
//
// Responsible for hooking up DevTools to V8 for auction worklets. Lives
// entirely on the V8 thread, including receiving Mojo messages there, though
// creates DevTools IO session receivers on `io_session_receiver_sequence`,
// as they are required to be on a different thread for use when the V8
// thread is busy.
//
// Receiver for per-context group blink::mojom::DevToolsAgent pipes.
// Creates/manages the lifetimes of the blink::mojom::DevToolsSessions. Also
// serves as the v8_inspector::V8InspectorClient to handle pause/resume calls
// received back from V8.
//
// To summarize, the thread split is as follows:
//
// Mojo thread:
// - AuctionWorkletService & its Mojo interface
// - BidderWorklet and SellerWorklet objects & their Mojo interfaces
// - IOSession objects & their Mojo interfaces
//
// V8 thread:
// - V8 parsing and running the worklet JavaScript.
// - AuctionV8DevToolsAgent and its mojo
// - AuctionV8DevToolsSession and its mojo
class AuctionV8DevToolsAgent : public blink::mojom::DevToolsAgent,
public v8_inspector::V8InspectorClient {
public:
// `v8_helper` is expected to own `this`.
// `debug_command_queue` is expected to be owned by `v8_helper`.
// `io_session_receiver_sequence` must be distinct from
// `v8_helper->v8_runner()`, and be able to grab mutexes (for short duration)
// and handle a Mojo connection.
AuctionV8DevToolsAgent(
AuctionV8Helper* v8_helper,
scoped_refptr<DebugCommandQueue> debug_command_queue,
scoped_refptr<base::SequencedTaskRunner> io_session_receiver_sequence);
AuctionV8DevToolsAgent(const AuctionV8DevToolsAgent&) = delete;
AuctionV8DevToolsAgent& operator=(const AuctionV8DevToolsAgent&) = delete;
~AuctionV8DevToolsAgent() override;
// Connects an incoming Mojo debugging connection to endpoint `agent`,
// expecting to debug things associated in the V8Helper with
// `context_group_id`.
void Connect(
mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> agent,
int context_group_id);
// If any session debugging `context_group_id` has an instrumentation
// breakpoint named `name` set, asks for execution to be paused at next
// statement.
void MaybeTriggerInstrumentationBreakpoint(int context_group_id,
const std::string& name);
// Cleans up all state associated with connections, so the v8 inspector can be
// safely deleted.
void DestroySessions();
private:
struct ContextGroupInfo {
ContextGroupInfo();
~ContextGroupInfo();
// Owned by `sessions_` in the AuctionV8DevToolsAgent object; stale entries
// removed by its SessionDestroyed().
std::set<raw_ptr<AuctionV8DevToolsSession, SetExperimental>> sessions;
};
AuctionV8Helper* v8_helper() { return v8_helper_; }
// DevToolsAgent implementation.
void AttachDevToolsSession(
mojo::PendingAssociatedRemote<blink::mojom::DevToolsSessionHost> host,
mojo::PendingAssociatedReceiver<blink::mojom::DevToolsSession>
session_receiver,
mojo::PendingReceiver<blink::mojom::DevToolsSession> io_session_receiver,
blink::mojom::DevToolsSessionStatePtr reattach_session_state,
bool client_expects_binary_responses,
bool client_is_trusted,
const std::string& session_id,
bool session_waits_for_debugger) override;
void InspectElement(const ::gfx::Point& point) override;
void ReportChildTargets(bool report,
bool wait_for_debugger,
ReportChildTargetsCallback callback) override;
// V8InspectorClient implementation.
// TODO(morlovich): Implement consoleAPIMessage and currentTimeMS and replace
// our limited hand-rolled console implementation.
void runMessageLoopOnPause(int context_group_id) override;
void quitMessageLoopOnPause() override;
void runIfWaitingForDebugger(int context_group_id) override;
// Called via ~AuctionV8DevToolsSession.
void SessionDestroyed(AuctionV8DevToolsSession* session);
const raw_ptr<AuctionV8Helper> v8_helper_; // owns this.
const scoped_refptr<base::SequencedTaskRunner> io_session_receiver_sequence_;
// Mojo pipes connected to `this`, and context group IDs associated with them.
mojo::AssociatedReceiverSet<blink::mojom::DevToolsAgent, int> receivers_;
// All AuctionV8DevToolsSession objects have their lifetime limited by their
// pipes and `this`.
mojo::UniqueAssociatedReceiverSet<blink::mojom::DevToolsSession> sessions_;
// Context groups with live AuctionV8DevToolsSessions. Each entry is created
// when a blink::mojom::DevToolsAgent in `receivers_` receives a
// AttachDevToolsSession() call and there are no live sessions associated with
// its context group ID. Keyed by context group ID.
//
// Empty entries are pruned by SessionDestroyed, which is called from
// ~AuctionV8DevToolsSession (via a callback).
std::map<int, ContextGroupInfo> context_groups_;
// Owned by `v8_helper` which owns `this`.
const raw_ptr<DebugCommandQueue> debug_command_queue_;
bool paused_ = false;
SEQUENCE_CHECKER(v8_sequence_checker_);
};
} // namespace auction_worklet
#endif // CONTENT_SERVICES_AUCTION_WORKLET_AUCTION_V8_DEVTOOLS_AGENT_H_