提交 68194b8d 编写于 作者: M Mikkel Nygaard Ravn 提交者: GitHub

Distinguish between null platform message and one with zero-byte payload (#3577)

上级 8df4ec7a
......@@ -13,6 +13,13 @@ PlatformMessage::PlatformMessage(std::string channel,
ftl::RefPtr<PlatformMessageResponse> response)
: channel_(std::move(channel)),
data_(std::move(data)),
hasData_(true),
response_(std::move(response)) {}
PlatformMessage::PlatformMessage(std::string channel,
ftl::RefPtr<PlatformMessageResponse> response)
: channel_(std::move(channel)),
data_(),
hasData_(false),
response_(std::move(response)) {}
PlatformMessage::~PlatformMessage() = default;
......
......@@ -21,6 +21,7 @@ class PlatformMessage : public ftl::RefCountedThreadSafe<PlatformMessage> {
public:
const std::string& channel() const { return channel_; }
const std::vector<uint8_t>& data() const { return data_; }
bool hasData() { return hasData_; }
const ftl::RefPtr<PlatformMessageResponse>& response() const {
return response_;
......@@ -30,10 +31,13 @@ class PlatformMessage : public ftl::RefCountedThreadSafe<PlatformMessage> {
PlatformMessage(std::string name,
std::vector<uint8_t> data,
ftl::RefPtr<PlatformMessageResponse> response);
PlatformMessage(std::string name,
ftl::RefPtr<PlatformMessageResponse> response);
~PlatformMessage();
std::string channel_;
std::vector<uint8_t> data_;
bool hasData_;
ftl::RefPtr<PlatformMessageResponse> response_;
};
......
......@@ -19,8 +19,7 @@ class PlatformMessageResponse
public:
// Callable on any thread.
virtual void Complete(std::vector<uint8_t> data) = 0;
// TODO(abarth): You should be able to pass data with the error.
virtual void CompleteWithError() = 0;
virtual void CompleteEmpty() = 0;
bool is_complete() const { return is_complete_; }
......
......@@ -38,32 +38,36 @@ void PlatformMessageResponseDart::Complete(std::vector<uint8_t> data) {
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer;
if (data.empty()) {
byte_buffer = Dart_Null();
} else {
byte_buffer =
Dart_NewTypedData(Dart_TypedData_kByteData, data.size());
DART_CHECK_VALID(byte_buffer);
void* buffer;
intptr_t length;
Dart_TypedData_Type type;
DART_CHECK_VALID(
Dart_TypedDataAcquireData(byte_buffer, &type, &buffer, &length));
FTL_CHECK(type == Dart_TypedData_kByteData);
FTL_CHECK(static_cast<size_t>(length) == data.size());
memcpy(buffer, data.data(), length);
Dart_TypedDataReleaseData(byte_buffer);
}
Dart_Handle byte_buffer = Dart_NewTypedData(
Dart_TypedData_kByteData, data.size());
DART_CHECK_VALID(byte_buffer);
void* buffer;
intptr_t length;
Dart_TypedData_Type type;
DART_CHECK_VALID(
Dart_TypedDataAcquireData(byte_buffer, &type, &buffer, &length));
FTL_CHECK(type == Dart_TypedData_kByteData);
FTL_CHECK(static_cast<size_t>(length) == data.size());
memcpy(buffer, data.data(), length);
Dart_TypedDataReleaseData(byte_buffer);
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
void PlatformMessageResponseDart::CompleteWithError() {
// TODO(abarth): We should have a dedicated error pathway.
Complete(std::vector<uint8_t>());
void PlatformMessageResponseDart::CompleteEmpty() {
if (callback_.is_empty())
return;
FTL_DCHECK(!is_complete_);
is_complete_ = true;
Threads::UI()->PostTask(ftl::MakeCopyable(
[ callback = std::move(callback_) ]() mutable {
tonic::DartState* dart_state = callback.dart_state().get();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
tonic::DartInvoke(callback.Release(), {Dart_Null()});
}));
}
} // namespace blink
......@@ -16,7 +16,7 @@ class PlatformMessageResponseDart : public PlatformMessageResponse {
public:
// Callable on any thread.
void Complete(std::vector<uint8_t> data) override;
void CompleteWithError() override;
void CompleteEmpty() override;
protected:
explicit PlatformMessageResponseDart(tonic::DartPersistentValue callback);
......
......@@ -22,9 +22,6 @@ namespace blink {
namespace {
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
if (buffer.empty())
return Dart_Null();
Dart_Handle data_handle =
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
if (Dart_IsError(data_handle))
......@@ -72,18 +69,23 @@ void SendPlatformMessage(Dart_Handle window,
Dart_Handle callback,
const tonic::DartByteData& data) {
UIDartState* dart_state = UIDartState::Current();
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
ftl::RefPtr<PlatformMessageResponse> response;
if (!Dart_IsNull(callback)) {
response = ftl::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback));
}
UIDartState::Current()->window()->client()->HandlePlatformMessage(
ftl::MakeRefCounted<PlatformMessage>(
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
response));
if (Dart_IsNull(data.dart_handle())) {
UIDartState::Current()->window()->client()->HandlePlatformMessage(
ftl::MakeRefCounted<PlatformMessage>(name, response));
} else {
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
UIDartState::Current()->window()->client()->HandlePlatformMessage(
ftl::MakeRefCounted<PlatformMessage>(
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
response));
}
}
void _SendPlatformMessage(Dart_NativeArguments args) {
......@@ -93,10 +95,15 @@ void _SendPlatformMessage(Dart_NativeArguments args) {
void RespondToPlatformMessage(Dart_Handle window,
int response_id,
const tonic::DartByteData& data) {
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
UIDartState::Current()->window()->CompletePlatformMessageResponse(
response_id,
std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
if (Dart_IsNull(data.dart_handle())) {
UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
response_id);
} else {
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
UIDartState::Current()->window()->CompletePlatformMessageResponse(
response_id,
std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
}
}
void _RespondToPlatformMessage(Dart_NativeArguments args) {
......@@ -162,8 +169,9 @@ void Window::DispatchPlatformMessage(ftl::RefPtr<PlatformMessage> message) {
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle data_handle = ToByteData(message->data());
Dart_Handle data_handle = (message->hasData())
? ToByteData(message->data())
: Dart_Null();
if (Dart_IsError(data_handle))
return;
......@@ -215,6 +223,17 @@ void Window::BeginFrame(ftl::TimePoint frameTime) {
});
}
void Window::CompletePlatformMessageEmptyResponse(int response_id) {
if (!response_id)
return;
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
auto response = std::move(it->second);
pending_responses_.erase(it);
response->CompleteEmpty();
}
void Window::CompletePlatformMessageResponse(int response_id,
std::vector<uint8_t> data) {
if (!response_id)
......
......@@ -51,6 +51,7 @@ class Window {
void CompletePlatformMessageResponse(int response_id,
std::vector<uint8_t> data);
void CompletePlatformMessageEmptyResponse(int response_id);
static void RegisterNatives(tonic::DartLibraryNatives* natives);
......
......@@ -400,7 +400,7 @@ void Engine::HandleAssetPlatformMessage(
if (GetAssetAsBuffer(asset_name, &asset_data)) {
response->Complete(std::move(asset_data));
} else {
response->CompleteWithError();
response->CompleteEmpty();
}
}
......
......@@ -133,7 +133,7 @@ void PlatformView::UpdateSemantics(std::vector<blink::SemanticsNode> update) {}
void PlatformView::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
if (auto response = message->response())
response->CompleteWithError();
response->CompleteEmpty();
}
void PlatformView::SetupResourceContextOnIOThread() {
......
......@@ -56,7 +56,7 @@ public final class StandardMessageCodec implements MessageCodec<Object> {
@Override
public Object decodeMessage(ByteBuffer message) {
if (message == null || !message.hasRemaining()) {
if (message == null) {
return null;
}
message.order(ByteOrder.nativeOrder());
......
......@@ -567,10 +567,14 @@ public class FlutterView extends SurfaceView
private static native Bitmap nativeGetBitmap(long nativePlatformViewAndroid);
// Send a platform message to Dart.
// Send a data-carrying platform message to Dart.
private static native void nativeDispatchPlatformMessage(long nativePlatformViewAndroid,
String channel, ByteBuffer message, int position, int responseId);
// Send an empty platform message to Dart.
private static native void nativeDispatchEmptyPlatformMessage(long nativePlatformViewAndroid,
String channel, int responseId);
private static native void nativeDispatchPointerDataPacket(long nativePlatformViewAndroid,
ByteBuffer buffer, int position);
......@@ -580,10 +584,14 @@ public class FlutterView extends SurfaceView
private static native void nativeSetSemanticsEnabled(long nativePlatformViewAndroid,
boolean enabled);
// Send a response to a platform message received from Dart.
// Send a data-carrying response to a platform message received from Dart.
private static native void nativeInvokePlatformMessageResponseCallback(
long nativePlatformViewAndroid, int responseId, ByteBuffer message, int position);
// Send an empty response to a platform message received from Dart.
private static native void nativeInvokePlatformMessageEmptyResponseCallback(
long nativePlatformViewAndroid, int responseId);
private void updateViewportMetrics() {
nativeSetViewportMetrics(mNativePlatformView,
mMetrics.devicePixelRatio,
......@@ -600,22 +608,27 @@ public class FlutterView extends SurfaceView
OnBinaryMessageListenerAsync listener = mMessageListeners.get(channel);
if (listener != null) {
try {
listener.onMessage(this, ByteBuffer.wrap(message),
final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
listener.onMessage(this, buffer,
new BinaryMessageResponse() {
@Override
public void send(ByteBuffer response) {
nativeInvokePlatformMessageResponseCallback(mNativePlatformView,
responseId, response, response == null ? 0 : response.position());
if (response == null) {
nativeInvokePlatformMessageEmptyResponseCallback(mNativePlatformView,
responseId);
} else {
nativeInvokePlatformMessageResponseCallback(mNativePlatformView,
responseId, response, response.position());
}
}
});
} catch (Exception ex) {
Log.e(TAG, "Uncaught exception in binary message listener", ex);
nativeInvokePlatformMessageResponseCallback(mNativePlatformView, responseId,
null, 0);
nativeInvokePlatformMessageEmptyResponseCallback(mNativePlatformView, responseId);
}
return;
}
nativeInvokePlatformMessageResponseCallback(mNativePlatformView, responseId, null, 0);
nativeInvokePlatformMessageEmptyResponseCallback(mNativePlatformView, responseId);
}
private int mNextResponseId = 1;
......@@ -626,7 +639,7 @@ public class FlutterView extends SurfaceView
BinaryMessageReplyCallback callback = mPendingResponses.remove(responseId);
if (callback != null) {
try {
callback.onReply(ByteBuffer.wrap(response));
callback.onReply(response == null ? null : ByteBuffer.wrap(response));
} catch (Exception ex) {
Log.e(TAG, "Uncaught exception in binary message listener reply", ex);
}
......@@ -767,8 +780,12 @@ public class FlutterView extends SurfaceView
responseId = mNextResponseId++;
mPendingResponses.put(responseId, callback);
}
nativeDispatchPlatformMessage(mNativePlatformView, channel, message,
message == null ? 0 : message.position(), responseId);
if (message == null) {
nativeDispatchEmptyPlatformMessage(mNativePlatformView, channel, responseId);
} else {
nativeDispatchPlatformMessage(mNativePlatformView, channel, message,
message.position(), responseId);
}
}
/**
......
......@@ -43,7 +43,16 @@ class PlatformMessageResponseAndroid : public blink::PlatformMessageResponse {
}));
}
void CompleteWithError() override { Complete(std::vector<uint8_t>()); }
void CompleteEmpty() override {
ftl::RefPtr<PlatformMessageResponseAndroid> self(this);
blink::Threads::Platform()->PostTask(
ftl::MakeCopyable([ self ]() mutable {
if (!self->view_)
return;
static_cast<PlatformViewAndroid*>(self->view_.get())
->HandlePlatformMessageEmptyResponse(self->response_id_);
}));
}
private:
PlatformMessageResponseAndroid(int response_id,
......@@ -217,13 +226,10 @@ void PlatformViewAndroid::DispatchPlatformMessage(JNIEnv* env,
jobject java_message_data,
jint java_message_position,
jint response_id) {
std::vector<uint8_t> message;
if (java_message_data) {
uint8_t* message_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
message = std::vector<uint8_t>(message_data,
message_data + java_message_position);
}
uint8_t* message_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
std::vector<uint8_t> message =
std::vector<uint8_t>(message_data, message_data + java_message_position);
ftl::RefPtr<blink::PlatformMessageResponse> response;
if (response_id) {
......@@ -236,6 +242,20 @@ void PlatformViewAndroid::DispatchPlatformMessage(JNIEnv* env,
std::move(name), std::move(message), std::move(response)));
}
void PlatformViewAndroid::DispatchEmptyPlatformMessage(JNIEnv* env,
std::string name,
jint response_id) {
ftl::RefPtr<blink::PlatformMessageResponse> response;
if (response_id) {
response = ftl::MakeRefCounted<PlatformMessageResponseAndroid>(
response_id, GetWeakPtr());
}
PlatformView::DispatchPlatformMessage(
ftl::MakeRefCounted<blink::PlatformMessage>(
std::move(name), std::move(response)));
}
void PlatformViewAndroid::DispatchPointerDataPacket(JNIEnv* env,
jobject buffer,
jint position) {
......@@ -260,18 +280,28 @@ void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
std::vector<uint8_t> response;
if (java_response_data) {
uint8_t* response_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_response_data));
response = std::vector<uint8_t>(response_data,
response_data + java_response_position);
}
uint8_t* response_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_response_data));
std::vector<uint8_t> response = std::vector<uint8_t>(response_data,
response_data + java_response_position);
auto message_response = std::move(it->second);
pending_responses_.erase(it);
message_response->Complete(std::move(response));
}
void PlatformViewAndroid::InvokePlatformMessageEmptyResponseCallback(
JNIEnv* env,
jint response_id) {
if (!response_id)
return;
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
auto message_response = std::move(it->second);
pending_responses_.erase(it);
message_response->CompleteEmpty();
}
void PlatformViewAndroid::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
JNIEnv* env = fml::jni::AttachCurrentThread();
......@@ -284,18 +314,25 @@ void PlatformViewAndroid::HandlePlatformMessage(
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
fml::jni::ScopedJavaLocalRef<jbyteArray> message_array(env,
env->NewByteArray(message->data().size()));
env->SetByteArrayRegion(
message_array.obj(), 0, message->data().size(),
reinterpret_cast<const jbyte*>(message->data().data()));
auto java_channel = fml::jni::StringToJavaString(env, message->channel());
message = nullptr;
// This call can re-enter in InvokePlatformMessageResponseCallback.
FlutterViewHandlePlatformMessage(
env, view.obj(), java_channel.obj(), message_array.obj(), response_id);
if (message->hasData()) {
fml::jni::ScopedJavaLocalRef<jbyteArray> message_array(env,
env->NewByteArray(message->data().size()));
env->SetByteArrayRegion(
message_array.obj(), 0, message->data().size(),
reinterpret_cast<const jbyte*>(message->data().data()));
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(
env, view.obj(), java_channel.obj(), message_array.obj(), response_id);
} else {
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(
env, view.obj(), java_channel.obj(), nullptr, response_id);
}
}
void PlatformViewAndroid::HandlePlatformMessageResponse(
......@@ -307,7 +344,6 @@ void PlatformViewAndroid::HandlePlatformMessageResponse(
if (view.is_null())
return;
fml::jni::ScopedJavaLocalRef<jbyteArray> data_array(env,
env->NewByteArray(data.size()));
env->SetByteArrayRegion(data_array.obj(), 0, data.size(),
......@@ -317,6 +353,18 @@ void PlatformViewAndroid::HandlePlatformMessageResponse(
data_array.obj());
}
void PlatformViewAndroid::HandlePlatformMessageEmptyResponse(
int response_id) {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> view = flutter_view_.get(env);
if (view.is_null())
return;
FlutterViewHandlePlatformMessageResponse(env, view.obj(), response_id,
nullptr);
}
void PlatformViewAndroid::DispatchSemanticsAction(jint id, jint action) {
PlatformView::DispatchSemanticsAction(
id, static_cast<blink::SemanticsAction>(action));
......
......@@ -57,6 +57,10 @@ class PlatformViewAndroid : public PlatformView {
jint message_position,
jint response_id);
void DispatchEmptyPlatformMessage(JNIEnv* env,
std::string name,
jint response_id);
void DispatchPointerDataPacket(JNIEnv* env, jobject buffer, jint position);
void InvokePlatformMessageResponseCallback(JNIEnv* env,
......@@ -64,6 +68,9 @@ class PlatformViewAndroid : public PlatformView {
jobject java_response_data,
jint java_response_position);
void InvokePlatformMessageEmptyResponseCallback(JNIEnv* env,
jint response_id);
void DispatchSemanticsAction(jint id, jint action);
void SetSemanticsEnabled(jboolean enabled);
......@@ -82,6 +89,8 @@ class PlatformViewAndroid : public PlatformView {
void HandlePlatformMessageResponse(int response_id,
std::vector<uint8_t> data);
void HandlePlatformMessageEmptyResponse(int response_id);
void RunFromSource(const std::string& assets_directory,
const std::string& main,
const std::string& packages) override;
......
......@@ -147,6 +147,15 @@ static void DispatchPlatformMessage(JNIEnv* env,
responseId);
}
static void DispatchEmptyPlatformMessage(JNIEnv* env,
jobject jcaller,
jlong platform_view,
jstring channel,
jint responseId) {
return PLATFORM_VIEW->DispatchEmptyPlatformMessage(
env, fml::jni::JavaStringToString(env, channel), responseId);
}
static void DispatchPointerDataPacket(JNIEnv* env,
jobject jcaller,
jlong platform_view,
......@@ -180,6 +189,14 @@ static void InvokePlatformMessageResponseCallback(JNIEnv* env,
env, responseId, message, position);
}
static void InvokePlatformMessageEmptyResponseCallback(JNIEnv* env,
jobject jcaller,
jlong platform_view,
jint responseId) {
return PLATFORM_VIEW->InvokePlatformMessageEmptyResponseCallback(
env, responseId);
}
bool PlatformViewAndroid::Register(JNIEnv* env) {
if (env == nullptr) {
return false;
......@@ -249,6 +266,11 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
.signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
.fnPtr = reinterpret_cast<void*>(&shell::DispatchPlatformMessage),
},
{
.name = "nativeDispatchEmptyPlatformMessage",
.signature = "(JLjava/lang/String;I)V",
.fnPtr = reinterpret_cast<void*>(&shell::DispatchEmptyPlatformMessage),
},
{
.name = "nativeDispatchPointerDataPacket",
.signature = "(JLjava/nio/ByteBuffer;I)V",
......@@ -270,6 +292,12 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
.fnPtr = reinterpret_cast<void*>(
&shell::InvokePlatformMessageResponseCallback),
},
{
.name = "nativeInvokePlatformMessageEmptyResponseCallback",
.signature = "(JI)V",
.fnPtr = reinterpret_cast<void*>(
&shell::InvokePlatformMessageEmptyResponseCallback),
},
};
if (env->RegisterNatives(g_flutter_view_class->obj(), methods,
......
......@@ -7,8 +7,6 @@
namespace shell {
std::vector<uint8_t> GetVectorFromNSData(NSData* data) {
if (!data.length)
return std::vector<uint8_t>();
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data.bytes);
return std::vector<uint8_t>(bytes, bytes + data.length);
}
......
......@@ -56,7 +56,7 @@ FLUTTER_EXPORT
*/
- (void)sendBinaryMessage:(NSData* _Nullable)message
channelName:(NSString*)channelName
binaryReplyHandler:(FlutterBinaryReplyHandler)handler;
binaryReplyHandler:(FlutterBinaryReplyHandler _Nullable)handler;
/**
Registers a message handler for incoming binary messages from the Flutter side
......
......@@ -218,7 +218,9 @@ NSObject const* FlutterMethodNotImplemented = [NSObject new];
NSData* message = [_codec encodeMethodCall:methodCall];
FlutterBinaryReplyHandler replyHandler = ^(NSData* reply) {
if (resultReceiver) {
resultReceiver([_codec decodeEnvelope:reply]);
resultReceiver((reply == nil)
? FlutterMethodNotImplemented
: [_codec decodeEnvelope:reply]);
}
};
[_messenger sendBinaryMessage:message
......
......@@ -14,14 +14,10 @@
}
- (NSData*)encode:(NSData*)message {
if (!message.length)
return nil;
return message;
}
- (NSData*)decode:(NSData*)message {
if (!message.length)
return nil;
return message;
}
@end
......@@ -36,14 +32,14 @@
}
- (NSData*)encode:(NSString*)message {
if (!message.length)
if (message == nil)
return nil;
const char* utf8 = message.UTF8String;
return [NSData dataWithBytes:utf8 length:strlen(utf8)];
}
- (NSString*)decode:(NSData*)message {
if (!message.length)
if (message == nil)
return nil;
return [[[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding]
autorelease];
......@@ -69,7 +65,7 @@
}
- (id)decode:(NSData*)message {
if (!message.length)
if (message == nil)
return nil;
id decoded =
[NSJSONSerialization JSONObjectWithData:message options:0 error:nil];
......
......@@ -25,7 +25,7 @@
}
- (id)decode:(NSData*)message {
if (!message.length)
if (message == nil)
return nil;
FlutterStandardReader* reader =
[FlutterStandardReader readerWithData:message];
......
......@@ -38,7 +38,13 @@ class PlatformMessageResponseDarwin : public blink::PlatformMessageResponse {
}));
}
void CompleteWithError() override { Complete(std::vector<uint8_t>()); }
void CompleteEmpty() override {
ftl::RefPtr<PlatformMessageResponseDarwin> self(this);
blink::Threads::Platform()->PostTask(
ftl::MakeCopyable([ self ]() mutable {
self->callback_.get()(nil);
}));
}
private:
explicit PlatformMessageResponseDarwin(
......@@ -581,27 +587,23 @@ constexpr CGFloat kStandardStatusBarHeight = 20.0;
#pragma mark - Application Messages
- (void)sendBinaryMessage:(NSData*)message channelName:(NSString*)channel {
NSAssert(channel, @"The channel must not be null");
if (message == nil)
message = [NSData data];
_platformView->DispatchPlatformMessage(
ftl::MakeRefCounted<blink::PlatformMessage>(
channel.UTF8String, shell::GetVectorFromNSData(message), nil));
[self sendBinaryMessage:message channelName:channel binaryReplyHandler:nil];
}
- (void)sendBinaryMessage:(NSData*)message
channelName:(NSString*)channel
binaryReplyHandler:(FlutterBinaryReplyHandler)callback {
NSAssert(channel, @"The channel must not be null");
NSAssert(callback, @"The callback must not be null");
if (message == nil)
message = [NSData data];
_platformView->DispatchPlatformMessage(
ftl::MakeRefCounted<blink::PlatformMessage>(
channel.UTF8String, shell::GetVectorFromNSData(message),
ftl::MakeRefCounted<PlatformMessageResponseDarwin>(^(NSData* reply) {
callback(reply);
})));
ftl::RefPtr<PlatformMessageResponseDarwin> response = (callback == nil)
? nullptr
: ftl::MakeRefCounted<PlatformMessageResponseDarwin>(^(NSData* reply) {
callback(reply);
});
ftl::RefPtr<blink::PlatformMessage> platformMessage = (message == nil)
? ftl::MakeRefCounted<blink::PlatformMessage>(channel.UTF8String, response)
: ftl::MakeRefCounted<blink::PlatformMessage>(channel.UTF8String,
shell::GetVectorFromNSData(message), response);
_platformView->DispatchPlatformMessage(platformMessage);
}
- (void)setBinaryMessageHandlerOnChannel:(NSString*)channel
......
......@@ -16,20 +16,26 @@ PlatformMessageRouter::~PlatformMessageRouter() = default;
void PlatformMessageRouter::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
NSData* data = GetNSDataFromVector(message->data());
ftl::RefPtr<blink::PlatformMessageResponse> completer = message->response();
auto it = message_handlers_.find(message->channel());
if (it != message_handlers_.end()) {
FlutterBinaryMessageHandler handler = it->second;
NSData* data = nil;
if (message->hasData()) {
data = GetNSDataFromVector(message->data());
}
handler(data, ^(NSData* reply) {
if (completer) {
completer->Complete(GetVectorFromNSData(reply));
if (reply) {
completer->Complete(GetVectorFromNSData(reply));
} else {
completer->CompleteEmpty();
}
}
});
} else {
if (completer) {
completer->Complete(GetVectorFromNSData(nil));
completer->CompleteEmpty();
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册