Skip to content

Commit 32b1b70

Browse files
[windows] Expose the binary messenger from FlutterEngine (flutter#20551)
Relands flutter/engine#20399 Makes BinaryMessenger available from FlutterEngine, rather than just the plugin registrar. This allows for method channels directly in applications without building them as plugins, and matches the other platforms. Requires some restructuring of code and GN targets in the client wrappers to make the internals in the shared section usable by the implementations of platform-specific parts of the wrappers. Also fixes a latent issue with EnableInputBlocking symbols being declared but not defined for Windows that came up during testing of the restructing. Fixes flutter#62871
1 parent 76d4922 commit 32b1b70

24 files changed

+316
-194
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,9 @@ FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.h
836836
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.cc
837837
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.h
838838
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/basic_message_channel_unittests.cc
839+
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h
839840
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/byte_buffer_streams.h
841+
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc
840842
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/encodable_value_unittests.cc
841843
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc
842844
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/event_channel_unittests.cc

shell/platform/common/cpp/client_wrapper/BUILD.gn

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import("core_wrapper_files.gni")
88
# Client library build for internal use by the shell implementation.
99
source_set("client_wrapper") {
1010
sources = core_cpp_client_wrapper_sources
11-
public = core_cpp_client_wrapper_includes
11+
public = core_cpp_client_wrapper_includes +
12+
core_cpp_client_wrapper_internal_headers
1213

1314
deps = [ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
1415

@@ -23,7 +24,8 @@ source_set("client_wrapper") {
2324
# legacy version is removed.
2425
source_set("client_wrapper_legacy_encodable_value") {
2526
sources = core_cpp_client_wrapper_sources
26-
public = core_cpp_client_wrapper_includes
27+
public = core_cpp_client_wrapper_includes +
28+
core_cpp_client_wrapper_internal_headers
2729

2830
deps = [ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
2931

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
6+
#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
7+
8+
#include <flutter_messenger.h>
9+
10+
#include <map>
11+
#include <string>
12+
13+
#include "include/flutter/binary_messenger.h"
14+
15+
namespace flutter {
16+
17+
// Wrapper around a FlutterDesktopMessengerRef that implements the
18+
// BinaryMessenger API.
19+
class BinaryMessengerImpl : public BinaryMessenger {
20+
public:
21+
explicit BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger);
22+
23+
virtual ~BinaryMessengerImpl();
24+
25+
// Prevent copying.
26+
BinaryMessengerImpl(BinaryMessengerImpl const&) = delete;
27+
BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete;
28+
29+
// |flutter::BinaryMessenger|
30+
void Send(const std::string& channel,
31+
const uint8_t* message,
32+
size_t message_size,
33+
BinaryReply reply) const override;
34+
35+
// |flutter::BinaryMessenger|
36+
void SetMessageHandler(const std::string& channel,
37+
BinaryMessageHandler handler) override;
38+
39+
private:
40+
// Handle for interacting with the C API.
41+
FlutterDesktopMessengerRef messenger_;
42+
43+
// A map from channel names to the BinaryMessageHandler that should be called
44+
// for incoming messages on that channel.
45+
std::map<std::string, BinaryMessageHandler> handlers_;
46+
};
47+
48+
} // namespace flutter
49+
50+
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// This file contains the implementations of any class in the wrapper that
6+
// - is not fully inline, and
7+
// - is necessary for all clients of the wrapper (either app or plugin).
8+
// It exists instead of the usual structure of having some_class_name.cc files
9+
// so that changes to the set of things that need non-header implementations
10+
// are not breaking changes for the template.
11+
//
12+
// If https://github.com/flutter/flutter/issues/57146 is fixed, this can be
13+
// removed in favor of the normal structure since templates will no longer
14+
// manually include files.
15+
16+
#include <assert.h>
17+
18+
#include <iostream>
19+
20+
#include "binary_messenger_impl.h"
21+
#include "include/flutter/engine_method_result.h"
22+
23+
namespace flutter {
24+
25+
// ========== binary_messenger_impl.h ==========
26+
27+
namespace {
28+
// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
29+
// with a BinaryReply that will send a response on |message|'s response handle.
30+
//
31+
// This serves as an adaptor between the function-pointer-based message callback
32+
// interface provided by the C API and the std::function-based message handler
33+
// interface of BinaryMessenger.
34+
void ForwardToHandler(FlutterDesktopMessengerRef messenger,
35+
const FlutterDesktopMessage* message,
36+
void* user_data) {
37+
auto* response_handle = message->response_handle;
38+
BinaryReply reply_handler = [messenger, response_handle](
39+
const uint8_t* reply,
40+
size_t reply_size) mutable {
41+
if (!response_handle) {
42+
std::cerr << "Error: Response can be set only once. Ignoring "
43+
"duplicate response."
44+
<< std::endl;
45+
return;
46+
}
47+
FlutterDesktopMessengerSendResponse(messenger, response_handle, reply,
48+
reply_size);
49+
// The engine frees the response handle once
50+
// FlutterDesktopSendMessageResponse is called.
51+
response_handle = nullptr;
52+
};
53+
54+
const BinaryMessageHandler& message_handler =
55+
*static_cast<BinaryMessageHandler*>(user_data);
56+
57+
message_handler(message->message, message->message_size,
58+
std::move(reply_handler));
59+
}
60+
} // namespace
61+
62+
BinaryMessengerImpl::BinaryMessengerImpl(
63+
FlutterDesktopMessengerRef core_messenger)
64+
: messenger_(core_messenger) {}
65+
66+
BinaryMessengerImpl::~BinaryMessengerImpl() = default;
67+
68+
void BinaryMessengerImpl::Send(const std::string& channel,
69+
const uint8_t* message,
70+
size_t message_size,
71+
BinaryReply reply) const {
72+
if (reply == nullptr) {
73+
FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
74+
message_size);
75+
return;
76+
}
77+
struct Captures {
78+
BinaryReply reply;
79+
};
80+
auto captures = new Captures();
81+
captures->reply = reply;
82+
83+
auto message_reply = [](const uint8_t* data, size_t data_size,
84+
void* user_data) {
85+
auto captures = reinterpret_cast<Captures*>(user_data);
86+
captures->reply(data, data_size);
87+
delete captures;
88+
};
89+
bool result = FlutterDesktopMessengerSendWithReply(
90+
messenger_, channel.c_str(), message, message_size, message_reply,
91+
captures);
92+
if (!result) {
93+
delete captures;
94+
}
95+
}
96+
97+
void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
98+
BinaryMessageHandler handler) {
99+
if (!handler) {
100+
handlers_.erase(channel);
101+
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
102+
nullptr);
103+
return;
104+
}
105+
// Save the handler, to keep it alive.
106+
handlers_[channel] = std::move(handler);
107+
BinaryMessageHandler* message_handler = &handlers_[channel];
108+
// Set an adaptor callback that will invoke the handler.
109+
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
110+
ForwardToHandler, message_handler);
111+
}
112+
113+
// ========== engine_method_result.h ==========
114+
115+
namespace internal {
116+
117+
ReplyManager::ReplyManager(BinaryReply reply_handler)
118+
: reply_handler_(std::move(reply_handler)) {
119+
assert(reply_handler_);
120+
}
121+
122+
ReplyManager::~ReplyManager() {
123+
if (reply_handler_) {
124+
// Warn, rather than send a not-implemented response, since the engine may
125+
// no longer be valid at this point.
126+
std::cerr
127+
<< "Warning: Failed to respond to a message. This is a memory leak."
128+
<< std::endl;
129+
}
130+
}
131+
132+
void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
133+
if (!reply_handler_) {
134+
std::cerr
135+
<< "Error: Only one of Success, Error, or NotImplemented can be "
136+
"called,"
137+
<< " and it can be called exactly once. Ignoring duplicate result."
138+
<< std::endl;
139+
return;
140+
}
141+
142+
const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
143+
size_t message_size = data ? data->size() : 0;
144+
reply_handler_(message, message_size);
145+
reply_handler_ = nullptr;
146+
}
147+
148+
} // namespace internal
149+
150+
} // namespace flutter

shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,26 @@ core_cpp_client_wrapper_includes =
2727
],
2828
"abspath")
2929

30+
# Headers that aren't public for clients of the wrapper, but are considered
31+
# public for the purpose of BUILD dependencies (e.g., to allow
32+
# windows/client_wrapper implementation files to include them).
33+
core_cpp_client_wrapper_internal_headers =
34+
get_path_info([
35+
"binary_messenger_impl.h",
36+
"byte_buffer_streams.h",
37+
],
38+
"abspath")
39+
3040
# TODO: Once the wrapper API is more stable, consolidate to as few files as is
3141
# reasonable (without forcing different kinds of clients to take unnecessary
3242
# code) to simplify use.
3343
core_cpp_client_wrapper_sources = get_path_info([
34-
"byte_buffer_streams.h",
35-
"engine_method_result.cc",
44+
"core_implementations.cc",
3645
"plugin_registrar.cc",
3746
"standard_codec.cc",
3847
],
3948
"abspath")
49+
50+
# Temporary shim, published for backwards compatibility.
51+
# See comment in the file for more detail.
52+
temporary_shim_files = get_path_info([ "engine_method_result.cc" ], "abspath")

shell/platform/common/cpp/client_wrapper/engine_method_result.cc

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,10 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#include "include/flutter/engine_method_result.h"
5+
// This file is deprecated in favor of core_implementations.cc. This is a
6+
// temporary forwarding implementation so that the switch to
7+
// core_implementations.cc isn't an immediate breaking change, allowing for the
8+
// template to be updated to include it and update the template version before
9+
// removing this file.
610

7-
#include <assert.h>
8-
#include <iostream>
9-
10-
namespace flutter {
11-
namespace internal {
12-
13-
ReplyManager::ReplyManager(BinaryReply reply_handler)
14-
: reply_handler_(std::move(reply_handler)) {
15-
assert(reply_handler_);
16-
}
17-
18-
ReplyManager::~ReplyManager() {
19-
if (reply_handler_) {
20-
// Warn, rather than send a not-implemented response, since the engine may
21-
// no longer be valid at this point.
22-
std::cerr
23-
<< "Warning: Failed to respond to a message. This is a memory leak."
24-
<< std::endl;
25-
}
26-
}
27-
28-
void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
29-
if (!reply_handler_) {
30-
std::cerr
31-
<< "Error: Only one of Success, Error, or NotImplemented can be "
32-
"called,"
33-
<< " and it can be called exactly once. Ignoring duplicate result."
34-
<< std::endl;
35-
return;
36-
}
37-
38-
const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
39-
size_t message_size = data ? data->size() : 0;
40-
reply_handler_(message, message_size);
41-
reply_handler_ = nullptr;
42-
}
43-
44-
} // namespace internal
45-
} // namespace flutter
11+
#include "core_implementations.cc"

0 commit comments

Comments
 (0)