PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/jsinspector-modern/network
Просмотр файла: NetworkReporter.cpp
/*
* 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.
*/
#include "NetworkReporter.h"
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
#include "CdpNetwork.h"
#endif
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
#include <jsinspector-modern/cdp/CdpJson.h>
#endif
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/performance/timeline/PerformanceEntryReporter.h>
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
#include <chrono>
#endif
#include <glog/logging.h>
#include <stdexcept>
namespace facebook::react::jsinspector_modern {
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
namespace {
/**
* Get the current Unix timestamp in seconds (µs precision, CDP format).
*/
double getCurrentUnixTimestampSeconds() {
auto now = std::chrono::system_clock::now().time_since_epoch();
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(now).count();
auto micros =
std::chrono::duration_cast<std::chrono::microseconds>(now).count() %
1000000;
return static_cast<double>(seconds) +
(static_cast<double>(micros) / 1000000.0);
}
} // namespace
#endif
NetworkReporter& NetworkReporter::getInstance() {
static NetworkReporter instance;
return instance;
}
void NetworkReporter::setFrontendChannel(FrontendChannel frontendChannel) {
frontendChannel_ = std::move(frontendChannel);
}
bool NetworkReporter::enableDebugging() {
if (debuggingEnabled_.load(std::memory_order_acquire)) {
return false;
}
debuggingEnabled_.store(true, std::memory_order_release);
return true;
}
bool NetworkReporter::disableDebugging() {
if (!debuggingEnabled_.load(std::memory_order_acquire)) {
return false;
}
debuggingEnabled_.store(false, std::memory_order_release);
requestBodyBuffer_.clear();
return true;
}
void NetworkReporter::reportRequestStart(
const std::string& requestId,
const RequestInfo& requestInfo,
int encodedDataLength,
const std::optional<ResponseInfo>& redirectResponse) {
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp();
// All builds: Annotate PerformanceResourceTiming metadata
{
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
perfTimingsBuffer_.emplace(
requestId,
ResourceTimingData{
.url = requestInfo.url,
.fetchStart = now,
.requestStart = now,
});
}
}
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
double timestamp = getCurrentUnixTimestampSeconds();
auto request = cdp::network::Request::fromInputParams(requestInfo);
auto params = cdp::network::RequestWillBeSentParams{
.requestId = requestId,
.loaderId = "",
.documentURL = "mobile",
.request = std::move(request),
// NOTE: Both timestamp and wallTime use the same unit, however wallTime
// is relative to an "arbitrary epoch". In our implementation, use the
// Unix epoch for both.
.timestamp = timestamp,
.wallTime = timestamp,
.initiator = folly::dynamic::object("type", "script"),
.redirectHasExtraInfo = redirectResponse.has_value(),
};
if (redirectResponse.has_value()) {
params.redirectResponse = cdp::network::Response::fromInputParams(
redirectResponse.value(), encodedDataLength);
}
frontendChannel_(
cdp::jsonNotification("Network.requestWillBeSent", params.toDynamic()));
#endif
}
void NetworkReporter::reportConnectionTiming(
const std::string& requestId,
const std::optional<Headers>& headers) {
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp();
// All builds: Annotate PerformanceResourceTiming metadata
{
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
auto it = perfTimingsBuffer_.find(requestId);
if (it != perfTimingsBuffer_.end()) {
it->second.connectStart = now;
}
}
}
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
auto params = cdp::network::RequestWillBeSentExtraInfoParams{
.requestId = requestId,
.headers = headers.value_or(Headers{}),
.connectTiming = {.requestTime = getCurrentUnixTimestampSeconds()},
};
frontendChannel_(cdp::jsonNotification(
"Network.requestWillBeSentExtraInfo", params.toDynamic()));
#endif
}
void NetworkReporter::reportResponseStart(
const std::string& requestId,
const ResponseInfo& responseInfo,
int encodedDataLength) {
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp();
// All builds: Annotate PerformanceResourceTiming metadata
{
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
auto it = perfTimingsBuffer_.find(requestId);
if (it != perfTimingsBuffer_.end()) {
it->second.connectEnd = now;
it->second.responseStart = now;
it->second.responseStatus = responseInfo.statusCode;
}
}
}
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
auto response =
cdp::network::Response::fromInputParams(responseInfo, encodedDataLength);
auto resourceType = cdp::network::resourceTypeFromMimeType(response.mimeType);
resourceTypeMap_.emplace(requestId, resourceType);
auto params = cdp::network::ResponseReceivedParams{
.requestId = requestId,
.loaderId = "",
.timestamp = getCurrentUnixTimestampSeconds(),
.type = resourceType,
.response = response,
.hasExtraInfo = false,
};
frontendChannel_(
cdp::jsonNotification("Network.responseReceived", params.toDynamic()));
#endif
}
void NetworkReporter::reportDataReceived(
const std::string& requestId,
int dataLength,
const std::optional<int>& encodedDataLength) {
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
auto params = cdp::network::DataReceivedParams{
.requestId = requestId,
.timestamp = getCurrentUnixTimestampSeconds(),
.dataLength = dataLength,
.encodedDataLength = encodedDataLength.value_or(dataLength),
};
frontendChannel_(
cdp::jsonNotification("Network.dataReceived", params.toDynamic()));
#endif
}
void NetworkReporter::reportResponseEnd(
const std::string& requestId,
int encodedDataLength) {
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
auto now = PerformanceEntryReporter::getInstance()->getCurrentTimeStamp();
// All builds: Report PerformanceResourceTiming event
{
std::lock_guard<std::mutex> lock(perfTimingsMutex_);
auto it = perfTimingsBuffer_.find(requestId);
if (it != perfTimingsBuffer_.end()) {
auto& eventData = it->second;
PerformanceEntryReporter::getInstance()->reportResourceTiming(
eventData.url,
eventData.fetchStart,
eventData.requestStart,
eventData.connectStart.value_or(now),
eventData.connectEnd.value_or(now),
eventData.responseStart.value_or(now),
now,
eventData.responseStatus);
perfTimingsBuffer_.erase(requestId);
}
}
}
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
auto params = cdp::network::LoadingFinishedParams{
.requestId = requestId,
.timestamp = getCurrentUnixTimestampSeconds(),
.encodedDataLength = encodedDataLength,
};
frontendChannel_(
cdp::jsonNotification("Network.loadingFinished", params.toDynamic()));
#endif
}
void NetworkReporter::reportRequestFailed(
const std::string& requestId,
bool cancelled) const {
#ifdef REACT_NATIVE_DEBUGGER_ENABLED
// Debug build: CDP event handling
if (!isDebuggingEnabledNoSync()) {
return;
}
auto params = cdp::network::LoadingFailedParams{
.requestId = requestId,
.timestamp = getCurrentUnixTimestampSeconds(),
.type = resourceTypeMap_.find(requestId) != resourceTypeMap_.end()
? resourceTypeMap_.at(requestId)
: "Other",
.errorText = cancelled ? "net::ERR_ABORTED" : "net::ERR_FAILED",
.canceled = cancelled,
};
frontendChannel_(
cdp::jsonNotification("Network.loadingFailed", params.toDynamic()));
#endif
}
void NetworkReporter::storeResponseBody(
const std::string& requestId,
std::string_view body,
bool base64Encoded) {
std::lock_guard<std::mutex> lock(requestBodyMutex_);
requestBodyBuffer_.put(requestId, body, base64Encoded);
}
std::optional<std::tuple<std::string, bool>> NetworkReporter::getResponseBody(
const std::string& requestId) {
std::lock_guard<std::mutex> lock(requestBodyMutex_);
auto responseBody = requestBodyBuffer_.get(requestId);
if (responseBody == nullptr) {
return std::nullopt;
}
return std::make_optional<std::tuple<std::string, bool>>(
responseBody->data, responseBody->base64Encoded);
}
} // namespace facebook::react::jsinspector_modern
Выполнить команду
Для локальной разработки. Не используйте в интернете!