-
Notifications
You must be signed in to change notification settings - Fork 24k
/
HostTarget.h
250 lines (216 loc) · 8.54 KB
/
HostTarget.h
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "ExecutionContextManager.h"
#include "HostCommand.h"
#include "InspectorInterfaces.h"
#include "InstanceTarget.h"
#include "ScopedExecutor.h"
#include "WeakList.h"
#include <optional>
#include <string>
#ifndef JSINSPECTOR_EXPORT
#ifdef _MSC_VER
#ifdef CREATE_SHARED_LIBRARY
#define JSINSPECTOR_EXPORT __declspec(dllexport)
#else
#define JSINSPECTOR_EXPORT
#endif // CREATE_SHARED_LIBRARY
#else // _MSC_VER
#define JSINSPECTOR_EXPORT __attribute__((visibility("default")))
#endif // _MSC_VER
#endif // !defined(JSINSPECTOR_EXPORT)
namespace facebook::react::jsinspector_modern {
class HostTargetSession;
class HostAgent;
class HostCommandSender;
class HostTarget;
/**
* Receives events from a HostTarget. This is a shared interface that each
* React Native platform needs to implement in order to integrate with the
* debugging stack.
*/
class HostTargetDelegate {
public:
HostTargetDelegate() = default;
HostTargetDelegate(const HostTargetDelegate&) = delete;
HostTargetDelegate(HostTargetDelegate&&) = default;
HostTargetDelegate& operator=(const HostTargetDelegate&) = delete;
HostTargetDelegate& operator=(HostTargetDelegate&&) = default;
// TODO(moti): This is 1:1 the shape of the corresponding CDP message -
// consider reusing typed/generated CDP interfaces when we have those.
struct PageReloadRequest {
// It isn't clear what the ignoreCache parameter of @cdp Page.reload should
// mean in React Native. We parse it, but don't do anything with it yet.
std::optional<bool> ignoreCache;
// TODO: Implement scriptToEvaluateOnLoad parameter of @cdp Page.reload.
std::optional<std::string> scriptToEvaluateOnLoad;
/**
* Equality operator, useful for unit tests
*/
inline bool operator==(const PageReloadRequest& rhs) const {
return ignoreCache == rhs.ignoreCache &&
scriptToEvaluateOnLoad == rhs.scriptToEvaluateOnLoad;
}
};
struct OverlaySetPausedInDebuggerMessageRequest {
/**
* The message to display in the overlay. If nullopt, hide the overlay.
*/
std::optional<std::string> message;
/**
* Equality operator, useful for unit tests
*/
inline bool operator==(
const OverlaySetPausedInDebuggerMessageRequest& rhs) const {
return message == rhs.message;
}
};
virtual ~HostTargetDelegate();
/**
* Called when the debugger requests a reload of the page. This is called on
* the thread on which messages are dispatched to the session (that is, where
* ILocalConnection::sendMessage was called).
*/
virtual void onReload(const PageReloadRequest& request) = 0;
/**
* Called when the debugger requests that the "paused in debugger" overlay be
* shown or hidden. If the message is nullopt, hide the overlay, otherwise
* show it with the given message. This is called on the inspector thread.
*
* If this method is called with a non-null message, it's guaranteed to
* eventually be called again with a null message. In all other respects,
* the timing and payload of these messages are fully controlled by the
* client.
*/
virtual void onSetPausedInDebuggerMessage(
const OverlaySetPausedInDebuggerMessageRequest& request) = 0;
};
/**
* The limited interface that HostTarget exposes to its associated
* sessions/agents.
*/
class HostTargetController final {
public:
explicit HostTargetController(HostTarget& target);
HostTargetDelegate& getDelegate();
bool hasInstance() const;
/**
* Increments the target's pause overlay counter. The counter represents the
* exact number of Agents that have (concurrently) requested the pause
* overlay to be shown. It's the caller's responsibility to only call this
* when the pause overlay's requested state transitions from hidden to
* visible.
*/
void incrementPauseOverlayCounter();
/**
* Decrements the target's pause overlay counter. The counter represents the
* exact number of Agents that have (concurrently) requested the pause
* overlay to be shown. It's the caller's responsibility to only call this
* when the pause overlay's requested state transitions from hidden to
* visible.
* \returns false if the counter has reached 0, otherwise true.
*/
bool decrementPauseOverlayCounter();
private:
HostTarget& target_;
size_t pauseOverlayCounter_{0};
};
/**
* The top-level Target in a React Native app. This is equivalent to the
* "Host" in React Native's architecture - the entity that manages the
* lifecycle of a React Instance.
*/
class JSINSPECTOR_EXPORT HostTarget
: public EnableExecutorFromThis<HostTarget> {
public:
struct SessionMetadata {
std::optional<std::string> integrationName;
};
/**
* Constructs a new HostTarget.
* \param delegate The HostTargetDelegate that will
* receive events from this HostTarget. The caller is responsible for ensuring
* that the HostTargetDelegate outlives this object.
* \param executor An executor that may be used to call methods on this
* HostTarget while it exists. \c create additionally guarantees that the
* executor will not be called after the HostTarget is destroyed.
* \note Copies of the provided executor may be destroyed on arbitrary
* threads, including after the HostTarget is destroyed. Callers must ensure
* that such destructor calls are safe - e.g. if using a lambda as the
* executor, all captured values must be safe to destroy from any thread.
*/
static std::shared_ptr<HostTarget> create(
HostTargetDelegate& delegate,
VoidExecutor executor);
HostTarget(const HostTarget&) = delete;
HostTarget(HostTarget&&) = delete;
HostTarget& operator=(const HostTarget&) = delete;
HostTarget& operator=(HostTarget&&) = delete;
~HostTarget();
/**
* Creates a new Session connected to this HostTarget, wrapped in an
* interface which is compatible with \c IInspector::addPage.
* The caller is responsible for destroying the connection before HostTarget
* is destroyed, on the same thread where HostTarget's constructor and
* destructor execute.
*/
std::unique_ptr<ILocalConnection> connect(
std::unique_ptr<IRemoteConnection> connectionToFrontend,
SessionMetadata sessionMetadata = {});
/**
* Registers an instance with this HostTarget.
* \param delegate The InstanceTargetDelegate that will receive events from
* this InstanceTarget. The caller is responsible for ensuring that the
* InstanceTargetDelegate outlives this object.
* \return An InstanceTarget reference representing the newly created
* instance. This reference is only valid until unregisterInstance is called
* (or the HostTarget is destroyed). \pre There isn't currently an instance
* registered with this HostTarget.
*/
InstanceTarget& registerInstance(InstanceTargetDelegate& delegate);
/**
* Unregisters an instance from this HostTarget.
* \param instance The InstanceTarget reference previously returned by
* registerInstance.
*/
void unregisterInstance(InstanceTarget& instance);
/**
* Sends an imperative command to the HostTarget. May be called from any
* thread.
*/
void sendCommand(HostCommand command);
private:
/**
* Constructs a new HostTarget.
* The caller must call setExecutor immediately afterwards.
* \param delegate The HostTargetDelegate that will
* receive events from this HostTarget. The caller is responsible for ensuring
* that the HostTargetDelegate outlives this object.
*/
HostTarget(HostTargetDelegate& delegate);
HostTargetDelegate& delegate_;
WeakList<HostTargetSession> sessions_;
HostTargetController controller_{*this};
// executionContextManager_ is a shared_ptr to guarantee its validity while
// the InstanceTarget is alive (just in case the InstanceTarget ends up
// briefly outliving the HostTarget, which it generally shouldn't).
std::shared_ptr<ExecutionContextManager> executionContextManager_;
std::shared_ptr<InstanceTarget> currentInstance_{nullptr};
std::unique_ptr<HostCommandSender> commandSender_;
inline HostTargetDelegate& getDelegate() {
return delegate_;
}
inline bool hasInstance() const {
return currentInstance_ != nullptr;
}
// Necessary to allow HostAgent to access HostTarget's internals in a
// controlled way (i.e. only HostTargetController gets friend access, while
// HostAgent itself doesn't).
friend class HostTargetController;
};
} // namespace facebook::react::jsinspector_modern