提交 82728570 编写于 作者: A Adam Barth 提交者: GitHub

Response messages (#3134)

Add plunbing for Host-to-Dart platform messages

We'll use the plumbing in this direction for things like key events.
上级 1a40ee95
......@@ -149,7 +149,8 @@ void RuntimeHolder::UpdateSemantics(std::vector<blink::SemanticsNode> update) {}
void RuntimeHolder::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
message->InvokeCallbackWithError();
if (auto response = message->response())
response->CompleteWithError();
}
void RuntimeHolder::DidCreateMainIsolate(Dart_Isolate isolate) {
......
......@@ -58,6 +58,10 @@ source_set("ui") {
"text/text_box.h",
"ui_dart_state.cc",
"ui_dart_state.h",
"window/platform_message_response_dart.cc",
"window/platform_message_response_dart.h",
"window/platform_message_response.cc",
"window/platform_message_response.h",
"window/platform_message.cc",
"window/platform_message.h",
"window/pointer_data.cc",
......
......@@ -44,6 +44,16 @@ void _popRoute() {
window.onPopRoute();
}
void _dispatchPlatformMessage(String name, ByteData data, int responseId) {
if (window.onPlatformMessage != null) {
window.onPlatformMessage(name, data, (ByteData responseData) {
window._respondToPlatformMessage(responseId, responseData);
});
} else {
window._respondToPlatformMessage(responseId, null);
}
}
void _dispatchPointerDataPacket(ByteData packet) {
if (window.onPointerDataPacket != null)
window.onPointerDataPacket(_unpackPointerDataPacket(packet));
......
......@@ -19,8 +19,15 @@ typedef void SemanticsActionCallback(int id, SemanticsAction action);
/// Signature for [Window.onAppLifecycleStateChanged].
typedef void AppLifecycleStateCallback(AppLifecycleState state);
/// Signature for responses to platform messages.
///
/// Used as a parameter to [Window.sendPlatformMessage] and
/// [Window.onPlatformMessage].
typedef void PlatformMessageResponseCallback(ByteData data);
/// Signature for [Window.onPlatformMessage].
typedef void PlatformMessageCallback(String name, ByteData data, PlatformMessageResponseCallback callback);
/// States that an application can be in.
enum AppLifecycleState {
// These values must match the order of the values of
......@@ -215,6 +222,12 @@ class Window {
/// semantics update cannot be used further.
void updateSemantics(SemanticsUpdate update) native "Window_updateSemantics";
/// Sends a message to a platform-specific plugin.
///
/// The `name` parameter determines which plugin receives the message. The
/// `data` parameter contains the message payload and is typically UTF-8
/// encoded JSON but can be arbitrary data. If the plugin replies to the
/// message, `callback` will be called with the response.
void sendPlatformMessage(String name,
ByteData data,
PlatformMessageResponseCallback callback) {
......@@ -224,6 +237,21 @@ class Window {
PlatformMessageResponseCallback callback,
ByteData data) native "Window_sendPlatformMessage";
/// Called whenever this window receives a message from a platform-specific
/// plugin.
///
/// The `name` parameter determines which plugin sent the message. The `data`
/// parameter is the payload and is typically UTF-8 encoded JSON but can be
/// arbitrary data.
///
/// Message handlers must call the function given in the `callback` parameter.
/// If the handler does not need to respond, the handler should pass `null` to
/// the callback.
PlatformMessageCallback onPlatformMessage;
/// Called by [_dispatchPlatformMessage].
void _respondToPlatformMessage(int responseId, ByteData data)
native "Window_respondToPlatformMessage";
}
/// The [Window] singleton. This object exposes the size of the display, the
......
......@@ -6,68 +6,15 @@
#include <utility>
#include "flutter/common/threads.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
namespace blink {
PlatformMessage::PlatformMessage(std::string name,
std::vector<char> data,
tonic::DartPersistentValue callback)
ftl::RefPtr<PlatformMessageResponse> response)
: name_(std::move(name)),
data_(std::move(data)),
callback_(std::move(callback)) {}
PlatformMessage::~PlatformMessage() {
if (!callback_.is_empty()) {
Threads::UI()->PostTask(
ftl::MakeCopyable([callback = std::move(callback_)]() mutable {
callback.Clear();
}));
}
}
void PlatformMessage::InvokeCallback(std::vector<char> data) {
if (callback_.is_empty())
return;
Threads::UI()->PostTask(ftl::MakeCopyable(
[ callback = std::move(callback_), data = std::move(data) ]() mutable {
tonic::DartState* dart_state = callback.dart_state().get();
if (!dart_state)
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);
}
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
void PlatformMessage::InvokeCallbackWithError() {
InvokeCallback(std::vector<char>());
}
response_(std::move(response)) {}
void PlatformMessage::ClearData() {
data_.clear();
}
PlatformMessage::~PlatformMessage() = default;
} // namespace blink
......@@ -5,13 +5,12 @@
#ifndef FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_H_
#define FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_H_
#include <functional>
#include <string>
#include <vector>
#include "flutter/lib/ui/window/platform_message_response.h"
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/memory/ref_ptr.h"
#include "lib/tonic/dart_persistent_value.h"
namespace blink {
......@@ -20,27 +19,22 @@ class PlatformMessage : public ftl::RefCountedThreadSafe<PlatformMessage> {
FRIEND_MAKE_REF_COUNTED(PlatformMessage);
public:
using Sink = std::function<void(ftl::RefPtr<PlatformMessage>)>;
const std::string& name() const { return name_; }
const std::vector<char>& data() const { return data_; }
bool has_callback() const { return !callback_.is_empty(); }
// Callable on any thread.
void InvokeCallback(std::vector<char> data);
void InvokeCallbackWithError();
void ClearData();
const ftl::RefPtr<PlatformMessageResponse>& response() const {
return response_;
}
private:
PlatformMessage(std::string name,
std::vector<char> data,
tonic::DartPersistentValue callback);
ftl::RefPtr<PlatformMessageResponse> response);
~PlatformMessage();
std::string name_;
std::vector<char> data_;
tonic::DartPersistentValue callback_;
ftl::RefPtr<PlatformMessageResponse> response_;
};
} // namespace blink
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/lib/ui/window/platform_message_response.h"
namespace blink {
PlatformMessageResponse::PlatformMessageResponse() = default;
PlatformMessageResponse::~PlatformMessageResponse() = default;
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_H_
#define FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_H_
#include <vector>
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/memory/ref_ptr.h"
namespace blink {
class PlatformMessageResponse
: public ftl::RefCountedThreadSafe<PlatformMessageResponse> {
FRIEND_REF_COUNTED_THREAD_SAFE(PlatformMessageResponse);
public:
// Callable on any thread.
virtual void Complete(std::vector<char> data) = 0;
// TODO(abarth): You should be able to pass data with the error.
virtual void CompleteWithError() = 0;
bool is_complete() const { return is_complete_; }
protected:
PlatformMessageResponse();
virtual ~PlatformMessageResponse();
bool is_complete_ = false;
};
} // namespace blink
#endif // FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/lib/ui/window/platform_message_response_dart.h"
#include <utility>
#include "flutter/common/threads.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
namespace blink {
PlatformMessageResponseDart::PlatformMessageResponseDart(
tonic::DartPersistentValue callback)
: callback_(std::move(callback)) {}
PlatformMessageResponseDart::~PlatformMessageResponseDart() {
if (!callback_.is_empty()) {
Threads::UI()->PostTask(
ftl::MakeCopyable([callback = std::move(callback_)]() mutable {
callback.Clear();
}));
}
}
void PlatformMessageResponseDart::Complete(std::vector<char> data) {
if (callback_.is_empty())
return;
FTL_DCHECK(!is_complete_);
is_complete_ = true;
Threads::UI()->PostTask(ftl::MakeCopyable(
[ callback = std::move(callback_), data = std::move(data) ]() mutable {
tonic::DartState* dart_state = callback.dart_state().get();
if (!dart_state)
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);
}
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
void PlatformMessageResponseDart::CompleteWithError() {
// TODO(abarth): We should have a dedicated error pathway.
Complete(std::vector<char>());
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_DART_H_
#define FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_DART_H_
#include "flutter/lib/ui/window/platform_message_response.h"
#include "lib/tonic/dart_persistent_value.h"
namespace blink {
class PlatformMessageResponseDart : public PlatformMessageResponse {
FRIEND_MAKE_REF_COUNTED(PlatformMessageResponseDart);
public:
// Callable on any thread.
void Complete(std::vector<char> data) override;
void CompleteWithError() override;
protected:
explicit PlatformMessageResponseDart(tonic::DartPersistentValue callback);
~PlatformMessageResponseDart() override;
tonic::DartPersistentValue callback_;
};
} // namespace blink
#endif // FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_RESPONSE_DART_H_
......@@ -6,6 +6,7 @@
#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/platform_message_response_dart.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_args.h"
#include "lib/tonic/dart_library_natives.h"
......@@ -20,6 +21,26 @@ using tonic::ToDart;
namespace blink {
namespace {
Dart_Handle ToByteData(const std::vector<char> buffer) {
if (buffer.empty())
return Dart_Null();
Dart_Handle data_handle =
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
if (Dart_IsError(data_handle))
return data_handle;
Dart_TypedData_Type type;
void* data = nullptr;
intptr_t num_bytes = 0;
FTL_CHECK(!Dart_IsError(
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));
memcpy(data, buffer.data(), num_bytes);
Dart_TypedDataReleaseData(data_handle);
return data_handle;
}
void ScheduleFrame(Dart_NativeArguments args) {
UIDartState::Current()->window()->client()->ScheduleFrame();
}
......@@ -52,18 +73,35 @@ void SendPlatformMessage(Dart_Handle window,
const tonic::DartByteData& data) {
UIDartState* dart_state = UIDartState::Current();
const char* buffer = static_cast<const char*>(data.data());
auto message = ftl::MakeRefCounted<blink::PlatformMessage>(
name, std::vector<char>(buffer, buffer + data.length_in_bytes()),
tonic::DartPersistentValue(dart_state, callback));
ftl::RefPtr<PlatformMessageResponse> response;
if (!Dart_IsNull(callback)) {
response = ftl::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback));
}
UIDartState::Current()->window()->client()->HandlePlatformMessage(
std::move(message));
ftl::MakeRefCounted<PlatformMessage>(
name, std::vector<char>(buffer, buffer + data.length_in_bytes()),
response));
}
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}
void RespondToPlatformMessage(Dart_Handle window,
int response_id,
const tonic::DartByteData& data) {
const char* buffer = static_cast<const char*>(data.data());
UIDartState::Current()->window()->CompletePlatformMessageResponse(
response_id, std::vector<char>(buffer, buffer + data.length_in_bytes()));
}
void _RespondToPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&RespondToPlatformMessage, args);
}
} // namespace
WindowClient::~WindowClient() {}
......@@ -138,26 +176,35 @@ void Window::PopRoute() {
DartInvokeField(library_.value(), "_popRoute", {});
}
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
void Window::DispatchPlatformMessage(ftl::RefPtr<PlatformMessage> message) {
tonic::DartState* dart_state = library_.dart_state().get();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle data_handle =
Dart_NewTypedData(Dart_TypedData_kByteData, packet.data().size());
Dart_Handle data_handle = ToByteData(message->data());
if (Dart_IsError(data_handle))
return;
Dart_TypedData_Type type;
void* data = nullptr;
intptr_t len = 0;
if (Dart_IsError(Dart_TypedDataAcquireData(data_handle, &type, &data, &len)))
return;
int response_id = 0;
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
memcpy(data, packet.data().data(), len);
DartInvokeField(library_.value(), "_dispatchPlatformMessage",
{ToDart(message->name()), data_handle, ToDart(response_id)});
}
Dart_TypedDataReleaseData(data_handle);
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
tonic::DartState* dart_state = library_.dart_state().get();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle data_handle = ToByteData(packet.data());
if (Dart_IsError(data_handle))
return;
DartInvokeField(library_.value(), "_dispatchPointerDataPacket",
{data_handle});
}
......@@ -196,10 +243,23 @@ void Window::OnAppLifecycleStateChanged(sky::AppLifecycleState state) {
{ToDart(static_cast<int>(state))});
}
void Window::CompletePlatformMessageResponse(int response_id,
std::vector<char> data) {
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->Complete(std::move(data));
}
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
{"Window_render", Render, 2, true},
{"Window_updateSemantics", UpdateSemantics, 2, true},
});
......
......@@ -5,6 +5,8 @@
#ifndef FLUTTER_LIB_UI_WINDOW_WINDOW_H_
#define FLUTTER_LIB_UI_WINDOW_WINDOW_H_
#include <unordered_map>
#include "flutter/lib/ui/semantics/semantics_update.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/lib/ui/window/pointer_data_packet.h"
......@@ -42,6 +44,7 @@ class Window {
void UpdateLocale(const std::string& language_code,
const std::string& country_code);
void UpdateSemanticsEnabled(bool enabled);
void DispatchPlatformMessage(ftl::RefPtr<PlatformMessage> message);
void DispatchPointerDataPacket(const PointerDataPacket& packet);
void DispatchSemanticsAction(int32_t id, SemanticsAction action);
void BeginFrame(ftl::TimePoint frameTime);
......@@ -51,11 +54,18 @@ class Window {
void OnAppLifecycleStateChanged(sky::AppLifecycleState state);
void CompletePlatformMessageResponse(int response_id, std::vector<char> data);
static void RegisterNatives(tonic::DartLibraryNatives* natives);
private:
WindowClient* client_;
tonic::DartPersistentValue library_;
// We use id 0 to mean that no response is expected.
int next_response_id_ = 1;
std::unordered_map<int, ftl::RefPtr<blink::PlatformMessageResponse>>
pending_responses_;
};
} // namespace blink
......
......@@ -3,6 +3,7 @@ dart:io,_Platform,set:_nativeScript
dart:isolate,::,_startMainIsolate
dart:mojo.internal,MojoHandleWatcher,mojoControlHandle
dart:ui,::,_beginFrame
dart:ui,::,_dispatchPlatformMessage
dart:ui,::,_dispatchPointerDataPacket
dart:ui,::,_dispatchSemanticsAction
dart:ui,::,_getGetBaseURLClosure
......
......@@ -88,6 +88,12 @@ void RuntimeController::BeginFrame(ftl::TimePoint frame_time) {
GetWindow()->BeginFrame(frame_time);
}
void RuntimeController::DispatchPlatformMessage(
ftl::RefPtr<PlatformMessage> message) {
TRACE_EVENT0("flutter", "RuntimeController::DispatchPlatformMessage");
GetWindow()->DispatchPlatformMessage(std::move(message));
}
void RuntimeController::DispatchPointerDataPacket(
const PointerDataPacket& packet) {
TRACE_EVENT0("flutter", "RuntimeController::DispatchPointerDataPacket");
......
......@@ -39,6 +39,7 @@ class RuntimeController : public WindowClient, public IsolateClient {
void BeginFrame(ftl::TimePoint frame_time);
void DispatchPlatformMessage(ftl::RefPtr<PlatformMessage> message);
void DispatchPointerDataPacket(const PointerDataPacket& packet);
void DispatchSemanticsAction(int32_t id, SemanticsAction action);
......
......@@ -158,20 +158,23 @@ void Engine::OnLocaleChanged(const mojo::String& language_code,
runtime_->SetLocale(language_code_, country_code_);
}
void Engine::DispatchPlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
if (runtime_)
runtime_->DispatchPlatformMessage(std::move(message));
}
void Engine::DispatchPointerDataPacket(const PointerDataPacket& packet) {
TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket");
if (runtime_)
runtime_->DispatchPointerDataPacket(packet);
}
void Engine::DispatchSemanticsAction(int id, blink::SemanticsAction action) {
TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket");
if (runtime_)
runtime_->DispatchSemanticsAction(id, action);
}
void Engine::SetSemanticsEnabled(bool enabled) {
TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket");
semantics_enabled_ = enabled;
if (runtime_)
runtime_->SetSemanticsEnabled(semantics_enabled_);
......
......@@ -51,6 +51,7 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate {
void ConnectToEngine(mojo::InterfaceRequest<SkyEngine> request);
void OnOutputSurfaceCreated(const ftl::Closure& gpu_continuation);
void OnOutputSurfaceDestroyed(const ftl::Closure& gpu_continuation);
void DispatchPlatformMessage(ftl::RefPtr<blink::PlatformMessage> message);
void DispatchPointerDataPacket(const PointerDataPacket& packet);
void DispatchSemanticsAction(int id, blink::SemanticsAction action);
void SetSemanticsEnabled(bool enabled);
......
......@@ -32,11 +32,21 @@ PlatformView::~PlatformView() {
blink::Threads::UI()->PostTask([engine]() { delete engine; });
}
void PlatformView::DispatchPlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
blink::Threads::UI()->PostTask(
[ engine = engine_->GetWeakPtr(), message = std::move(message) ] {
if (engine) {
engine->DispatchPlatformMessage(message);
}
});
}
void PlatformView::DispatchSemanticsAction(int32_t id,
blink::SemanticsAction action) {
blink::Threads::UI()->PostTask(
[ engine = engine_->GetWeakPtr(), id, action ] {
if (engine.get()) {
if (engine) {
engine->DispatchSemanticsAction(
id, static_cast<blink::SemanticsAction>(action));
}
......@@ -45,7 +55,7 @@ void PlatformView::DispatchSemanticsAction(int32_t id,
void PlatformView::SetSemanticsEnabled(bool enabled) {
blink::Threads::UI()->PostTask([ engine = engine_->GetWeakPtr(), enabled ] {
if (engine.get())
if (engine)
engine->SetSemanticsEnabled(enabled);
});
}
......@@ -56,7 +66,7 @@ void PlatformView::ConnectToEngine(
view = GetWeakPtr(), engine = engine().GetWeakPtr(),
request = std::move(request)
]() mutable {
if (engine.get())
if (engine)
engine->ConnectToEngine(std::move(request));
Shell::Shared().AddPlatformView(view);
}));
......@@ -118,7 +128,8 @@ void PlatformView::UpdateSemantics(std::vector<blink::SemanticsNode> update) {}
void PlatformView::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
message->InvokeCallbackWithError();
if (auto response = message->response())
response->CompleteWithError();
}
void PlatformView::SetupResourceContextOnIOThread() {
......
......@@ -36,6 +36,7 @@ class PlatformView {
virtual ~PlatformView();
void DispatchPlatformMessage(ftl::RefPtr<blink::PlatformMessage> message);
void DispatchSemanticsAction(int32_t id, blink::SemanticsAction action);
void SetSemanticsEnabled(bool enabled);
......
......@@ -127,16 +127,17 @@ void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
jstring java_response) {
if (!response_id)
return;
auto it = pending_messages_.find(response_id);
if (it == pending_messages_.end())
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
std::string response;
if (java_response)
response = base::android::ConvertJavaStringToUTF8(env, java_response);
response = base::android::ConvertJavaStringToUTF8(env, java_response);
auto response = std::move(it->second);
pending_responses_.erase(it);
// TODO(abarth): There's an extra copy here.
it->second->InvokeCallback(
response->Complete(
std::vector<char>(response.data(), response.data() + response.size()));
pending_messages_.erase(it);
}
void PlatformViewAndroid::HandlePlatformMessage(
......@@ -148,9 +149,9 @@ void PlatformViewAndroid::HandlePlatformMessage(
return;
int response_id = 0;
if (message->has_callback()) {
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_messages_[response_id] = message;
pending_responses_[response_id] = response;
}
base::StringPiece message_name = message->name();
......@@ -162,7 +163,7 @@ void PlatformViewAndroid::HandlePlatformMessage(
base::android::ConvertUTF8ToJavaString(env, message_name);
auto java_message_data =
base::android::ConvertUTF8ToJavaString(env, message_data);
message->ClearData();
message = nullptr;
// This call can re-enter in InvokePlatformMessageResponseCallback.
Java_FlutterView_handlePlatformMessage(
......
......@@ -75,8 +75,8 @@ class PlatformViewAndroid : public PlatformView {
// We use id 0 to mean that no response is expected.
int next_response_id_ = 1;
std::unordered_map<int, ftl::RefPtr<blink::PlatformMessage>>
pending_messages_;
std::unordered_map<int, ftl::RefPtr<blink::PlatformMessageResponse>>
pending_responses_;
void UpdateThreadPriorities();
......
......@@ -36,12 +36,14 @@ void ApplicationMessagesImpl::AddBinding(
void ApplicationMessagesImpl::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
NSString* string = [NSString stringWithUTF8String:message->data().data()];
ftl::RefPtr<blink::PlatformMessageResponse> completer = message->response();
{
auto it = listeners_.find(message->name());
if (it != listeners_.end()) {
NSString* response = [it->second didReceiveString:string];
message->InvokeCallback(SysNSStringToVector(response));
if (completer)
completer->Complete(SysNSStringToVector(response));
return;
}
}
......@@ -52,7 +54,8 @@ void ApplicationMessagesImpl::HandlePlatformMessage(
[it->second
didReceiveString:string
callback:^(NSString* response) {
message->InvokeCallback(SysNSStringToVector(response));
if (completer)
completer->Complete(SysNSStringToVector(response));
}];
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册