Skip to content

Commit a5d6156

Browse files
huntiefacebook-github-bot
authored andcommitted
Support CDP response previews for chunked data (#52582)
Summary: Pull Request resolved: #52582 Continues integration of `NetworkReporter` (jsinspector-modern) on Android, to enable the Network panel in React Native DevTools. NOTE: As with iOS, all changes are gated behind the `enableNetworkEventReporting` and `fuseboxNetworkInspectionEnabled` feature flags. **This diff** Updates the Android inputs to `NetworkReporter` to support incremental string data HTTP responses (`Transfer-Encoding: chunked`). Implemented: - Incremental response case for `Network.getResponseBody` (fetch response previews). - `Network.dataReceived` (incremental response update event). This means that incremental responses, such as Metro bundle requests, can be displayed as previews in React Native DevTools. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D77927896 fbshipit-source-id: 6eff2e7b94d3f784bbc33b1fecdc20242f98b39f
1 parent 0114253 commit a5d6156

4 files changed

Lines changed: 81 additions & 2 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/InspectorNetworkReporter.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ internal object InspectorNetworkReporter {
5858
expectedDataLength: Long
5959
)
6060

61+
/**
62+
* Report when additional chunks of the response body have been received.
63+
*
64+
* Corresponds to `Network.dataReceived` in CDP.
65+
*/
66+
@JvmStatic external fun reportDataReceived(requestId: Int, dataLength: Int)
67+
6168
/**
6269
* Report when a network request is complete and we are no longer receiving response data.
6370
* - Corresponds to `Network.loadingFinished` in CDP.
@@ -71,4 +78,13 @@ internal object InspectorNetworkReporter {
7178
*/
7279
@JvmStatic
7380
external fun maybeStoreResponseBody(requestId: Int, body: String, base64Encoded: Boolean)
81+
82+
/**
83+
* Incrementally store a response body preview, when a string response is received in chunks.
84+
* Buffered contents will be flushed to `NetworkReporter` with `reportResponseEnd`.
85+
*
86+
* As with `maybeStoreResponseBody`, calling this method is optional and a no-op if CDP debugging
87+
* is disabled.
88+
*/
89+
@JvmStatic external fun maybeStoreResponseBodyIncremental(requestId: Int, data: String)
7490
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkEventUtil.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ internal object NetworkEventUtil {
6666
progress: Long,
6767
total: Long
6868
) {
69+
if (ReactNativeFeatureFlags.enableNetworkEventReporting() && data != null) {
70+
InspectorNetworkReporter.reportDataReceived(requestId, data.encodeToByteArray().size)
71+
InspectorNetworkReporter.maybeStoreResponseBodyIncremental(requestId, data)
72+
}
6973
reactContext?.emitDeviceEvent(
7074
"didReceiveNetworkIncrementalData",
7175
buildReadableArray {

packages/react-native/ReactAndroid/src/main/jni/react/jni/InspectorNetworkReporter.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
#include <cstddef>
1313
#include <string>
14+
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
15+
#include <unordered_map>
16+
#endif
1417

1518
using namespace facebook::jni;
1619
using namespace facebook::react::jsinspector_modern;
@@ -49,6 +52,13 @@ std::string limitRequestBodySize(std::string requestBody) {
4952

5053
} // namespace
5154

55+
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
56+
57+
// Dictionary to buffer incremental response bodies (CDP debugging active only)
58+
static std::unordered_map<int, std::string> responseBuffers;
59+
60+
#endif
61+
5262
/* static */ void InspectorNetworkReporter::reportRequestStart(
5363
const jni::alias_ref<jclass> /*unused*/,
5464
jint requestId,
@@ -93,12 +103,30 @@ std::string limitRequestBodySize(std::string requestBody) {
93103
static_cast<std::int64_t>(encodedDataLength));
94104
}
95105

106+
/* static */ void InspectorNetworkReporter::reportDataReceived(
107+
jni::alias_ref<jclass> /*unused*/,
108+
jint requestId,
109+
jint dataLength) {
110+
NetworkReporter::getInstance().reportDataReceived(
111+
std::to_string(requestId), dataLength, std::nullopt);
112+
}
113+
96114
/* static */ void InspectorNetworkReporter::reportResponseEnd(
97115
jni::alias_ref<jclass> /*unused*/,
98116
jint requestId,
99117
jlong encodedDataLength) {
100118
NetworkReporter::getInstance().reportResponseEnd(
101119
std::to_string(requestId), static_cast<std::int64_t>(encodedDataLength));
120+
121+
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
122+
// Debug build: Check for buffered response body and flush to NetworkReporter
123+
auto buffer = responseBuffers[requestId];
124+
if (!buffer.empty()) {
125+
NetworkReporter::getInstance().storeResponseBody(
126+
std::to_string(requestId), buffer, false);
127+
responseBuffers.erase(requestId);
128+
}
129+
#endif
102130
}
103131

104132
/* static */ void InspectorNetworkReporter::maybeStoreResponseBody(
@@ -118,20 +146,41 @@ std::string limitRequestBodySize(std::string requestBody) {
118146
#endif
119147
}
120148

149+
/* static */ void InspectorNetworkReporter::maybeStoreResponseBodyIncremental(
150+
jni::alias_ref<jclass> /*unused*/,
151+
jint requestId,
152+
jni::alias_ref<jstring> data) {
153+
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
154+
// Debug build: Buffer incremental response body contents
155+
auto& networkReporter = NetworkReporter::getInstance();
156+
if (!networkReporter.isDebuggingEnabled()) {
157+
return;
158+
}
159+
160+
auto& buffer = responseBuffers[requestId];
161+
buffer += data->toStdString();
162+
#endif
163+
}
164+
121165
/* static */ void InspectorNetworkReporter::registerNatives() {
122166
javaClassLocal()->registerNatives({
123167
makeNativeMethod(
124168
"reportRequestStart", InspectorNetworkReporter::reportRequestStart),
125169
makeNativeMethod(
126170
"reportResponseStart", InspectorNetworkReporter::reportResponseStart),
127-
makeNativeMethod(
128-
"reportResponseEnd", InspectorNetworkReporter::reportResponseEnd),
129171
makeNativeMethod(
130172
"reportConnectionTiming",
131173
InspectorNetworkReporter::reportConnectionTiming),
174+
makeNativeMethod(
175+
"reportDataReceived", InspectorNetworkReporter::reportDataReceived),
176+
makeNativeMethod(
177+
"reportResponseEnd", InspectorNetworkReporter::reportResponseEnd),
132178
makeNativeMethod(
133179
"maybeStoreResponseBody",
134180
InspectorNetworkReporter::maybeStoreResponseBody),
181+
makeNativeMethod(
182+
"maybeStoreResponseBodyIncremental",
183+
InspectorNetworkReporter::maybeStoreResponseBodyIncremental),
135184
});
136185
}
137186

packages/react-native/ReactAndroid/src/main/jni/react/jni/InspectorNetworkReporter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ class InspectorNetworkReporter
3939
jni::alias_ref<jni::JMap<jstring, jstring>> responseHeaders,
4040
jlong encodedDataLength);
4141

42+
static void reportDataReceived(
43+
jni::alias_ref<jclass> /*unused*/,
44+
jint requestId,
45+
jint dataLength);
46+
4247
static void reportResponseEnd(
4348
jni::alias_ref<jclass> /*unused*/,
4449
jint requestId,
@@ -50,6 +55,11 @@ class InspectorNetworkReporter
5055
jni::alias_ref<jstring> body,
5156
jboolean base64Encoded);
5257

58+
static void maybeStoreResponseBodyIncremental(
59+
jni::alias_ref<jclass> /*unused*/,
60+
jint requestId,
61+
jni::alias_ref<jstring> data);
62+
5363
static void registerNatives();
5464

5565
private:

0 commit comments

Comments
 (0)