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 #include "include/flutter/plugin_registrar.h"
6
7 #include <iostream>
8 #include <map>
9
10 #include "include/flutter/engine_method_result.h"
11 #include "include/flutter/method_channel.h"
12
13 namespace flutter {
14
15 namespace {
16
17 // Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
18 // with a BinaryReply that will send a response on |message|'s response handle.
19 //
20 // This serves as an adaptor between the function-pointer-based message callback
21 // interface provided by the C API and the std::function-based message handler
22 // interface of BinaryMessenger.
ForwardToHandler(FlutterDesktopMessengerRef messenger,const FlutterDesktopMessage * message,void * user_data)23 void ForwardToHandler(FlutterDesktopMessengerRef messenger,
24 const FlutterDesktopMessage* message,
25 void* user_data) {
26 auto* response_handle = message->response_handle;
27 BinaryReply reply_handler = [messenger, response_handle](
28 const uint8_t* reply,
29 const size_t reply_size) mutable {
30 if (!response_handle) {
31 std::cerr << "Error: Response can be set only once. Ignoring "
32 "duplicate response."
33 << std::endl;
34 return;
35 }
36 FlutterDesktopMessengerSendResponse(messenger, response_handle, reply,
37 reply_size);
38 // The engine frees the response handle once
39 // FlutterDesktopSendMessageResponse is called.
40 response_handle = nullptr;
41 };
42
43 const BinaryMessageHandler& message_handler =
44 *static_cast<BinaryMessageHandler*>(user_data);
45
46 message_handler(message->message, message->message_size,
47 std::move(reply_handler));
48 }
49
50 } // namespace
51
52 // Wrapper around a FlutterDesktopMessengerRef that implements the
53 // BinaryMessenger API.
54 class BinaryMessengerImpl : public BinaryMessenger {
55 public:
BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)56 explicit BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)
57 : messenger_(core_messenger) {}
58
59 virtual ~BinaryMessengerImpl() = default;
60
61 // Prevent copying.
62 BinaryMessengerImpl(BinaryMessengerImpl const&) = delete;
63 BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete;
64
65 // |flutter::BinaryMessenger|
66 void Send(const std::string& channel,
67 const uint8_t* message,
68 const size_t message_size) const override;
69
70 // |flutter::BinaryMessenger|
71 void Send(const std::string& channel,
72 const uint8_t* message,
73 const size_t message_size,
74 BinaryReply reply) const override;
75
76 // |flutter::BinaryMessenger|
77 void SetMessageHandler(const std::string& channel,
78 BinaryMessageHandler handler) override;
79
80 private:
81 // Handle for interacting with the C API.
82 FlutterDesktopMessengerRef messenger_;
83
84 // A map from channel names to the BinaryMessageHandler that should be called
85 // for incoming messages on that channel.
86 std::map<std::string, BinaryMessageHandler> handlers_;
87 };
88
Send(const std::string & channel,const uint8_t * message,const size_t message_size) const89 void BinaryMessengerImpl::Send(const std::string& channel,
90 const uint8_t* message,
91 const size_t message_size) const {
92 FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
93 message_size);
94 }
95
Send(const std::string & channel,const uint8_t * message,const size_t message_size,BinaryReply reply) const96 void BinaryMessengerImpl::Send(const std::string& channel,
97 const uint8_t* message,
98 const size_t message_size,
99 BinaryReply reply) const {
100 if (reply == nullptr) {
101 std::cerr << "Calling BinaryMessengerImpl::Send expecting a reply, but the "
102 "callback is null.\n";
103 return;
104 }
105 struct Captures {
106 BinaryReply reply;
107 };
108 auto captures = new Captures();
109 captures->reply = reply;
110
111 auto message_reply = [](const uint8_t* data, size_t data_size,
112 void* user_data) {
113 auto captures = reinterpret_cast<Captures*>(user_data);
114 captures->reply(data, data_size);
115 delete captures;
116 };
117 bool result = FlutterDesktopMessengerSendWithReply(
118 messenger_, channel.c_str(), message, message_size, message_reply,
119 captures);
120 if (!result) {
121 delete captures;
122 }
123 }
124
SetMessageHandler(const std::string & channel,BinaryMessageHandler handler)125 void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
126 BinaryMessageHandler handler) {
127 if (!handler) {
128 handlers_.erase(channel);
129 FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
130 nullptr);
131 return;
132 }
133 // Save the handler, to keep it alive.
134 handlers_[channel] = std::move(handler);
135 BinaryMessageHandler* message_handler = &handlers_[channel];
136 // Set an adaptor callback that will invoke the handler.
137 FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
138 ForwardToHandler, message_handler);
139 }
140
141 // PluginRegistrar:
142
PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar)143 PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar)
144 : registrar_(registrar) {
145 auto core_messenger = FlutterDesktopRegistrarGetMessenger(registrar_);
146 messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger);
147 }
148
~PluginRegistrar()149 PluginRegistrar::~PluginRegistrar() {}
150
AddPlugin(std::unique_ptr<Plugin> plugin)151 void PluginRegistrar::AddPlugin(std::unique_ptr<Plugin> plugin) {
152 plugins_.insert(std::move(plugin));
153 }
154
EnableInputBlockingForChannel(const std::string & channel)155 void PluginRegistrar::EnableInputBlockingForChannel(
156 const std::string& channel) {
157 FlutterDesktopRegistrarEnableInputBlocking(registrar_, channel.c_str());
158 }
159
160 } // namespace flutter
161