Expose a send method with a string params

Summary:
For C++, folly::dynamic is used throughout.

On iOS and Android though, Flipper goes through multiple conversions to get to a folly::dynamic only to ultimately obtain a JSON string from it.

Let's take a look at Android:

There are multiple types like FlipperObject, FlipperArray that wrap around a JSONObject.

When data needs to be sent:
1. The JSONObject is asked for its string representation.
2. The string representation is then parsed by folly to construct the folly::dynamic instance.
3. The step above involves an extra boundary cross through JNI.
4. Ultimately, a socket or ws connection does not understand folly::dynamic so we then get a JSON string representation from it.
5. Data is sent.

As described above, for big enough objects, this represents an issue.

So, the idea of this change, is to allow plugins to send a JSON string instead. This will remove a few serialisation/deserialisation steps from the process.

*Note: this API is not currently used by anything so there's no impact to existing plugins.*

Changelog: expose a send method that accept a string as params

Reviewed By: LukeDefeo

Differential Revision: D38741582

fbshipit-source-id: 78e0acd80fc8c97378ee986cbaf377078996ed60
This commit is contained in:
Lorenzo Blasa
2022-08-17 09:18:20 -07:00
committed by Facebook GitHub Bot
parent 2833958488
commit c2ed2484d9
11 changed files with 89 additions and 1 deletions

View File

@@ -514,6 +514,7 @@ class JFlipperConnectionImpl
registerHybrid({ registerHybrid({
makeNativeMethod("sendObject", JFlipperConnectionImpl::sendObject), makeNativeMethod("sendObject", JFlipperConnectionImpl::sendObject),
makeNativeMethod("sendArray", JFlipperConnectionImpl::sendArray), makeNativeMethod("sendArray", JFlipperConnectionImpl::sendArray),
makeNativeMethod("sendString", JFlipperConnectionImpl::sendString),
makeNativeMethod("reportError", JFlipperConnectionImpl::reportError), makeNativeMethod("reportError", JFlipperConnectionImpl::reportError),
makeNativeMethod( makeNativeMethod(
"reportErrorWithMetadata", "reportErrorWithMetadata",
@@ -522,6 +523,10 @@ class JFlipperConnectionImpl
}); });
} }
void sendString(const std::string method, const std::string params) {
_connection->send(std::move(method), std::move(params));
}
void sendObject( void sendObject(
const std::string method, const std::string method,
jni::alias_ref<JFlipperObject> json) { jni::alias_ref<JFlipperObject> json) {

View File

@@ -40,10 +40,17 @@ class FlipperConnectionImpl implements FlipperConnection {
sendArray(method, params); sendArray(method, params);
} }
@Override
public void send(String method, String params) {
sendString(method, params);
}
public native void sendObject(String method, FlipperObject params); public native void sendObject(String method, FlipperObject params);
public native void sendArray(String method, FlipperArray params); public native void sendArray(String method, FlipperArray params);
public native void sendString(String method, String params);
@Override @Override
public native void reportErrorWithMetadata(String reason, String stackTrace); public native void reportErrorWithMetadata(String reason, String stackTrace);

View File

@@ -26,6 +26,12 @@ public interface FlipperConnection {
*/ */
void send(String method, FlipperArray params); void send(String method, FlipperArray params);
/**
* Call a remote method on the Flipper desktop application, passing an optional JSON string as a
* parameter.
*/
void send(String method, String message);
/** Report client error with reason and stacktrace as an argument */ /** Report client error with reason and stacktrace as an argument */
void reportErrorWithMetadata(String reason, String stackTrace); void reportErrorWithMetadata(String reason, String stackTrace);

View File

@@ -47,6 +47,19 @@ public class FlipperConnectionMock implements FlipperConnection {
paramList.add(params); paramList.add(params);
} }
@Override
public void send(String method, String params) {
final List<Object> paramList;
if (sent.containsKey(method)) {
paramList = sent.get(method);
} else {
paramList = new ArrayList<>();
sent.put(method, paramList);
}
paramList.add(params);
}
@Override @Override
public void reportErrorWithMetadata(String reason, String stackTrace) { public void reportErrorWithMetadata(String reason, String stackTrace) {
errors.add(new Throwable(reason)); errors.add(new Throwable(reason));

View File

@@ -27,12 +27,19 @@ class FlipperConnection {
virtual ~FlipperConnection() {} virtual ~FlipperConnection() {}
/** /**
Invoke a method on the Flipper desktop plugin with with a matching identifier. Invoke a method on the Flipper desktop plugin with a matching identifier.
*/ */
virtual void send( virtual void send(
const std::string& method, const std::string& method,
const folly::dynamic& params) = 0; const folly::dynamic& params) = 0;
/**
Invoke a method on the Flipper desktop plugin with a matching
identifier.
Note: The `message` argument is expected to contain a valid JSON.
*/
virtual void send(const std::string& method, const std::string& params) = 0;
/** /**
Report an error to the Flipper desktop app Report an error to the Flipper desktop app
*/ */

View File

@@ -8,6 +8,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <sstream>
#include <string> #include <string>
#include "FlipperConnection.h" #include "FlipperConnection.h"
#include "FlipperConnectionManager.h" #include "FlipperConnectionManager.h"
@@ -52,6 +53,23 @@ class FlipperConnectionImpl : public FlipperConnection {
socket_->sendMessage(message); socket_->sendMessage(message);
} }
void send(const std::string& method, const std::string& params) override {
std::stringstream ss;
ss << "{"
"\"method\": \"execute\","
"\"params\": {"
"\"api\": \""
<< name_
<< "\","
"\"method\": \""
<< method
<< "\","
"\"params\":"
<< params << "}}";
socket_->sendMessage(ss.str());
}
void error(const std::string& message, const std::string& stacktrace) void error(const std::string& message, const std::string& stacktrace)
override { override {
socket_->sendMessage(folly::dynamic::object( socket_->sendMessage(folly::dynamic::object(

View File

@@ -54,6 +54,12 @@ class FlipperConnectionManager {
*/ */
virtual void sendMessage(const folly::dynamic& message) = 0; virtual void sendMessage(const folly::dynamic& message) = 0;
/**
Send message to the ws server.
Note: The `message` argument is expected to contain a valid JSON.
*/
virtual void sendMessage(const std::string& message) = 0;
/** /**
Handler for connection and message receipt from the ws server. Handler for connection and message receipt from the ws server.
The callbacks should be set before a connection is established. The callbacks should be set before a connection is established.

View File

@@ -341,6 +341,20 @@ void FlipperConnectionManagerImpl::sendMessage(const folly::dynamic& message) {
}); });
} }
void FlipperConnectionManagerImpl::sendMessage(const std::string& message) {
flipperScheduler_->schedule([this, message]() {
try {
if (client_) {
client_->send(message, []() {});
}
} catch (std::length_error& e) {
// Skip sending messages that are too large.
log(e.what());
return;
}
});
}
void FlipperConnectionManagerImpl::onMessageReceived( void FlipperConnectionManagerImpl::onMessageReceived(
const folly::dynamic& message, const folly::dynamic& message,
std::unique_ptr<FlipperResponder> responder) { std::unique_ptr<FlipperResponder> responder) {

View File

@@ -42,6 +42,8 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager {
void sendMessage(const folly::dynamic& message) override; void sendMessage(const folly::dynamic& message) override;
void sendMessage(const std::string& message) override;
void onMessageReceived( void onMessageReceived(
const folly::dynamic& message, const folly::dynamic& message,
std::unique_ptr<FlipperResponder> responder) override; std::unique_ptr<FlipperResponder> responder) override;

View File

@@ -40,6 +40,10 @@ class FlipperConnectionManagerMock : public FlipperConnectionManager {
messages.push_back(message); messages.push_back(message);
} }
void sendMessage(const std::string& message) override {
messages.push_back(folly::parseJson(message));
}
void setCertificateProvider( void setCertificateProvider(
const std::shared_ptr<FlipperCertificateProvider> provider) override{}; const std::shared_ptr<FlipperCertificateProvider> provider) override{};

View File

@@ -8,6 +8,7 @@
#pragma once #pragma once
#include <Flipper/FlipperConnection.h> #include <Flipper/FlipperConnection.h>
#include <folly/json.h>
#include <map> #include <map>
#include <queue> #include <queue>
#include <string> #include <string>
@@ -22,6 +23,11 @@ class FlipperConnectionMock : public FlipperConnection {
sent_message_history[method].push(params); sent_message_history[method].push(params);
} }
void send(const std::string& method, const std::string& params) override {
sent_[method] = folly::parseJson(params);
sent_message_history[method].push(params);
}
void receive(const std::string& method, const FlipperReceiver& receiver) void receive(const std::string& method, const FlipperReceiver& receiver)
override { override {
receivers_[method] = receiver; receivers_[method] = receiver;