• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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