Skip to content

Commit ef26028

Browse files
motiz88facebook-github-bot
authored andcommitted
Support using the Network domain in multiple concurrent sessions (facebook#55240)
Summary: Changelog: [General][Fixed] Send network events to all CDP clients with the Network domain enabled Differential Revision: D90888854
1 parent 3772ef2 commit ef26028

File tree

5 files changed

+105
-40
lines changed

5 files changed

+105
-40
lines changed

packages/react-native/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ class Stream : public NetworkRequestListener,
259259
};
260260
} // namespace
261261

262+
NetworkIOAgent::~NetworkIOAgent() {
263+
if (networkAgentId_) {
264+
NetworkHandler::getInstance().disableAgent(*networkAgentId_);
265+
networkAgentId_ = std::nullopt;
266+
}
267+
}
268+
262269
bool NetworkIOAgent::handleRequest(
263270
const cdp::PreparsedRequest& req,
264271
LoadNetworkResourceDelegate& delegate) {
@@ -278,15 +285,17 @@ bool NetworkIOAgent::handleRequest(
278285

279286
// @cdp Network.enable support is experimental.
280287
if (req.method == "Network.enable") {
281-
networkHandler.setFrontendChannel(frontendChannel_);
282-
networkHandler.enable();
288+
networkAgentId_ = networkHandler.enableAgent(frontendChannel_);
283289
// NOTE: Domain enable/disable responses are sent by HostAgent.
284290
return false;
285291
}
286292

287293
// @cdp Network.disable support is experimental.
288294
if (req.method == "Network.disable") {
289-
networkHandler.disable();
295+
if (networkAgentId_) {
296+
networkHandler.disableAgent(*networkAgentId_);
297+
networkAgentId_ = std::nullopt;
298+
}
290299
// NOTE: Domain enable/disable responses are sent by HostAgent.
291300
return false;
292301
}

packages/react-native/ReactCommon/jsinspector-modern/NetworkIOAgent.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,13 @@ class NetworkIOAgent {
211211
{
212212
}
213213

214+
~NetworkIOAgent();
215+
216+
NetworkIOAgent(const NetworkIOAgent &) = delete;
217+
NetworkIOAgent &operator=(const NetworkIOAgent &) = delete;
218+
NetworkIOAgent(NetworkIOAgent &&) = delete;
219+
NetworkIOAgent &operator=(NetworkIOAgent &&) = delete;
220+
214221
/**
215222
* Handle a CDP request. The response will be sent over the provided
216223
* \c FrontendChannel synchronously or asynchronously.
@@ -247,6 +254,12 @@ class NetworkIOAgent {
247254
*/
248255
unsigned long nextStreamId_{0};
249256

257+
/**
258+
* If non-nullopt, indicates that this agent has enabled the Network domain
259+
* via NetworkHandler, storing the agent ID for cleanup.
260+
*/
261+
std::optional<size_t> networkAgentId_;
262+
250263
/**
251264
* Begin loading an HTTP resource, delegating platform-specific
252265
* implementation, responding to the frontend on headers received or on error.

packages/react-native/ReactCommon/jsinspector-modern/network/NetworkHandler.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,31 @@ NetworkHandler& NetworkHandler::getInstance() {
3737
return instance;
3838
}
3939

40-
void NetworkHandler::setFrontendChannel(FrontendChannel frontendChannel) {
41-
frontendChannel_ = std::move(frontendChannel);
40+
size_t NetworkHandler::enableAgent(FrontendChannel frontendChannel) {
41+
std::lock_guard<std::mutex> lock(agentsMutex_);
42+
size_t id = nextAgentId_++;
43+
agents_.push_back({id, std::move(frontendChannel)});
44+
enabled_.store(true, std::memory_order_release);
45+
return id;
4246
}
4347

44-
bool NetworkHandler::enable() {
45-
if (enabled_.load(std::memory_order_acquire)) {
46-
return false;
47-
}
48+
void NetworkHandler::disableAgent(size_t agentId) {
49+
std::lock_guard<std::mutex> lock(agentsMutex_);
50+
agents_.remove_if(
51+
[agentId](const AgentRecord& r) { return r.id == agentId; });
52+
if (agents_.empty()) {
53+
enabled_.store(false, std::memory_order_release);
4854

49-
enabled_.store(true, std::memory_order_release);
50-
return true;
55+
std::lock_guard<std::mutex> lock2(requestBodyMutex_);
56+
responseBodyBuffer_.clear();
57+
}
5158
}
5259

53-
bool NetworkHandler::disable() {
54-
if (!enabled_.load(std::memory_order_acquire)) {
55-
return false;
60+
void NetworkHandler::sendToAllAgents(std::string_view message) {
61+
std::lock_guard<std::mutex> lock(agentsMutex_);
62+
for (auto& agent : agents_) {
63+
agent.channel(message);
5664
}
57-
58-
enabled_.store(false, std::memory_order_release);
59-
std::lock_guard<std::mutex> lock(requestBodyMutex_);
60-
responseBodyBuffer_.clear();
61-
return true;
6265
}
6366

6467
void NetworkHandler::onRequestWillBeSent(
@@ -89,7 +92,7 @@ void NetworkHandler::onRequestWillBeSent(
8992
.redirectResponse = redirectResponse,
9093
};
9194

92-
frontendChannel_(
95+
sendToAllAgents(
9396
cdp::jsonNotification("Network.requestWillBeSent", params.toDynamic()));
9497
}
9598

@@ -106,7 +109,7 @@ void NetworkHandler::onRequestWillBeSentExtraInfo(
106109
.connectTiming = {.requestTime = getCurrentUnixTimestampSeconds()},
107110
};
108111

109-
frontendChannel_(
112+
sendToAllAgents(
110113
cdp::jsonNotification(
111114
"Network.requestWillBeSentExtraInfo", params.toDynamic()));
112115
}
@@ -133,7 +136,7 @@ void NetworkHandler::onResponseReceived(
133136
.hasExtraInfo = false,
134137
};
135138

136-
frontendChannel_(
139+
sendToAllAgents(
137140
cdp::jsonNotification("Network.responseReceived", params.toDynamic()));
138141
}
139142

@@ -152,7 +155,7 @@ void NetworkHandler::onDataReceived(
152155
.encodedDataLength = encodedDataLength,
153156
};
154157

155-
frontendChannel_(
158+
sendToAllAgents(
156159
cdp::jsonNotification("Network.dataReceived", params.toDynamic()));
157160
}
158161

@@ -169,7 +172,7 @@ void NetworkHandler::onLoadingFinished(
169172
.encodedDataLength = encodedDataLength,
170173
};
171174

172-
frontendChannel_(
175+
sendToAllAgents(
173176
cdp::jsonNotification("Network.loadingFinished", params.toDynamic()));
174177
}
175178

@@ -192,7 +195,7 @@ void NetworkHandler::onLoadingFailed(
192195
.canceled = cancelled,
193196
};
194197

195-
frontendChannel_(
198+
sendToAllAgents(
196199
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
197200
}
198201
}

packages/react-native/ReactCommon/jsinspector-modern/network/NetworkHandler.h

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <folly/dynamic.h>
1414

1515
#include <atomic>
16+
#include <list>
1617
#include <mutex>
1718
#include <string>
1819
#include <tuple>
@@ -36,24 +37,17 @@ class NetworkHandler {
3637
static NetworkHandler &getInstance();
3738

3839
/**
39-
* Set the channel used to send CDP events to the frontend. This should be
40-
* supplied before calling `enable`.
40+
* Register a frontend channel for receiving Network domain events.
41+
* Implicitly enables the domain if this is the first agent.
42+
* \returns An agent ID to be passed to disableAgent() on cleanup.
4143
*/
42-
void setFrontendChannel(FrontendChannel frontendChannel);
44+
size_t enableAgent(FrontendChannel frontendChannel);
4345

4446
/**
45-
* Enable network debugging. Returns `false` if already enabled.
46-
*
47-
* @cdp Network.enable
48-
*/
49-
bool enable();
50-
51-
/**
52-
* Disable network debugging. Returns `false` if not initially enabled.
53-
*
54-
* @cdp Network.disable
47+
* Unregister a frontend channel by its ID.
48+
* Implicitly disables the domain if this was the last agent.
5549
*/
56-
bool disable();
50+
void disableAgent(size_t agentId);
5751

5852
/**
5953
* Returns whether network debugging is currently enabled.
@@ -134,7 +128,19 @@ class NetworkHandler {
134128

135129
std::optional<folly::dynamic> consumeStoredRequestInitiator(const std::string &requestId);
136130

137-
FrontendChannel frontendChannel_;
131+
/**
132+
* Send a message to all registered frontend channels.
133+
*/
134+
void sendToAllAgents(std::string_view message);
135+
136+
struct AgentRecord {
137+
size_t id;
138+
FrontendChannel channel;
139+
};
140+
141+
std::list<AgentRecord> agents_;
142+
size_t nextAgentId_{0};
143+
std::mutex agentsMutex_;
138144

139145
std::map<std::string, std::string> resourceTypeMap_{};
140146
std::map<std::string, folly::dynamic> requestInitiatorById_{};

packages/react-native/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,40 @@ TEST_P(NetworkReporterTest, testCreateRequestIdWithoutNetworkDomain) {
588588
EXPECT_NE(id1, id2);
589589
}
590590

591+
TEST_P(NetworkReporterTest, testTwoSessionsReceiveNetworkEvents) {
592+
auto secondary = this->connectSecondary();
593+
594+
this->expectMessageFromPage(JsonEq(R"({"id": 1, "result": {}})"));
595+
this->toPage_->sendMessage(R"({"id": 1, "method": "Network.enable"})");
596+
597+
EXPECT_CALL(
598+
secondary.fromPage(), onMessage(JsonEq(R"({"id": 2, "result": {}})")));
599+
secondary.toPage().sendMessage(R"({"id": 2, "method": "Network.enable"})");
600+
601+
// Both sessions should receive the network event
602+
this->expectMessageFromPage(JsonParsed(AllOf(
603+
AtJsonPtr("/method", "Network.requestWillBeSent"),
604+
AtJsonPtr("/params/requestId", "multi-session-request"))));
605+
EXPECT_CALL(
606+
secondary.fromPage(),
607+
onMessage(JsonParsed(AllOf(
608+
AtJsonPtr("/method", "Network.requestWillBeSent"),
609+
AtJsonPtr("/params/requestId", "multi-session-request")))));
610+
611+
RequestInfo requestInfo;
612+
requestInfo.url = "https://example.com/test";
613+
requestInfo.httpMethod = "GET";
614+
NetworkReporter::getInstance().reportRequestStart(
615+
"multi-session-request", requestInfo, 0, std::nullopt);
616+
617+
this->expectMessageFromPage(JsonEq(R"({"id": 3, "result": {}})"));
618+
this->toPage_->sendMessage(R"({"id": 3, "method": "Network.disable"})");
619+
620+
EXPECT_CALL(
621+
secondary.fromPage(), onMessage(JsonEq(R"({"id": 4, "result": {}})")));
622+
secondary.toPage().sendMessage(R"({"id": 4, "method": "Network.disable"})");
623+
}
624+
591625
struct NetworkReporterTracingTestParams {
592626
bool enableNetworkEventReporting;
593627
bool enableNetworkDomain;

0 commit comments

Comments
 (0)