Flutter Engine
method_channel.h
Go to the documentation of this file.
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_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
6 #define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
7 
8 #include <iostream>
9 #include <string>
10 
11 #include "binary_messenger.h"
12 #include "engine_method_result.h"
13 #include "method_call.h"
14 #include "method_codec.h"
15 #include "method_result.h"
16 
17 namespace flutter {
18 
19 class EncodableValue;
20 
21 // A handler for receiving a method call from the Flutter engine.
22 //
23 // Implementations must asynchronously call exactly one of the methods on
24 // |result| to indicate the result of the method call.
25 template <typename T>
26 using MethodCallHandler =
27  std::function<void(const MethodCall<T>& call,
28  std::unique_ptr<MethodResult<T>> result)>;
29 
30 // A channel for communicating with the Flutter engine using invocation of
31 // asynchronous methods.
32 template <typename T = EncodableValue>
34  public:
35  // Creates an instance that sends and receives method calls on the channel
36  // named |name|, encoded with |codec| and dispatched via |messenger|.
38  const std::string& name,
39  const MethodCodec<T>* codec)
40  : messenger_(messenger), name_(name), codec_(codec) {}
41 
42  ~MethodChannel() = default;
43 
44  // Prevent copying.
45  MethodChannel(MethodChannel const&) = delete;
46  MethodChannel& operator=(MethodChannel const&) = delete;
47 
48  // Sends a message to the Flutter engine on this channel.
49  //
50  // If |result| is provided, one of its methods will be invoked with the
51  // response from the engine.
52  void InvokeMethod(const std::string& method,
53  std::unique_ptr<T> arguments,
54  std::unique_ptr<MethodResult<T>> result = nullptr) {
55  MethodCall<T> method_call(method, std::move(arguments));
56  std::unique_ptr<std::vector<uint8_t>> message =
57  codec_->EncodeMethodCall(method_call);
58  if (!result) {
59  messenger_->Send(name_, message->data(), message->size(), nullptr);
60  return;
61  }
62 
63  // std::function requires a copyable lambda, so convert to a shared pointer.
64  // This is safe since only one copy of the shared_pointer will ever be
65  // accessed.
66  std::shared_ptr<MethodResult<T>> shared_result(result.release());
67  const auto* codec = codec_;
68  std::string channel_name = name_;
69  BinaryReply reply_handler = [shared_result, codec, channel_name](
70  const uint8_t* reply, size_t reply_size) {
71  if (reply_size == 0) {
72  shared_result->NotImplemented();
73  return;
74  }
75  // Use this channel's codec to decode and handle the
76  // reply.
77  bool decoded = codec->DecodeAndProcessResponseEnvelope(
78  reply, reply_size, shared_result.get());
79  if (!decoded) {
80  std::cerr << "Unable to decode reply to method "
81  "invocation on channel "
82  << channel_name << std::endl;
83  shared_result->NotImplemented();
84  }
85  };
86 
87  messenger_->Send(name_, message->data(), message->size(),
88  std::move(reply_handler));
89  }
90 
91  // Registers a handler that should be called any time a method call is
92  // received on this channel. A null handler will remove any previous handler.
93  //
94  // Note that the MethodChannel does not own the handler, and will not
95  // unregister it on destruction, so the caller is responsible for
96  // unregistering explicitly if it should no longer be called.
98  if (!handler) {
99  messenger_->SetMessageHandler(name_, nullptr);
100  return;
101  }
102  const auto* codec = codec_;
103  std::string channel_name = name_;
104  BinaryMessageHandler binary_handler = [handler, codec, channel_name](
105  const uint8_t* message,
106  size_t message_size,
107  BinaryReply reply) {
108  // Use this channel's codec to decode the call and build a result handler.
109  auto result =
110  std::make_unique<EngineMethodResult<T>>(std::move(reply), codec);
111  std::unique_ptr<MethodCall<T>> method_call =
112  codec->DecodeMethodCall(message, message_size);
113  if (!method_call) {
114  std::cerr << "Unable to construct method call from message on channel "
115  << channel_name << std::endl;
116  result->NotImplemented();
117  return;
118  }
119  handler(*method_call, std::move(result));
120  };
121  messenger_->SetMessageHandler(name_, std::move(binary_handler));
122  }
123 
124  private:
125  BinaryMessenger* messenger_;
126  std::string name_;
127  const MethodCodec<T>* codec_;
128 };
129 
130 } // namespace flutter
131 
132 #endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
G_BEGIN_DECLS FlMethodCall * method_call
std::function< void(const MethodCall< T > &call, std::unique_ptr< MethodResult< T > > result)> MethodCallHandler
void SetMethodCallHandler(MethodCallHandler< T > handler) const
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
void InvokeMethod(const std::string &method, std::unique_ptr< T > arguments, std::unique_ptr< MethodResult< T >> result=nullptr)
MethodChannel & operator=(MethodChannel const &)=delete
virtual void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler)=0
const char * name
Definition: fuchsia.cc:50
MethodChannel(BinaryMessenger *messenger, const std::string &name, const MethodCodec< T > *codec)
virtual void Send(const std::string &channel, const uint8_t *message, size_t message_size, BinaryReply reply=nullptr) const =0
std::function< void(const uint8_t *message, size_t message_size, BinaryReply reply)> BinaryMessageHandler