Flutter Engine
event_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_EVENT_CHANNEL_H_
6 #define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
7 
8 #include <iostream>
9 #include <memory>
10 #include <string>
11 
12 #include "binary_messenger.h"
13 #include "engine_method_result.h"
14 #include "event_sink.h"
15 #include "event_stream_handler.h"
16 
17 namespace flutter {
18 
19 class EncodableValue;
20 
21 // A named channel for communicating with the Flutter application using
22 // asynchronous event streams. Incoming requests for event stream setup are
23 // decoded from binary on receipt, and C++ responses and events are encoded into
24 // binary before being transmitted back to Flutter. The MethodCodec used must be
25 // compatible with the one used by the Flutter application. This can be achieved
26 // by creating an EventChannel
27 // ("https://docs.flutter.io/flutter/services/EventChannel-class.html")
28 // counterpart of this channel on the Dart side.
29 // The C++ type of stream configuration arguments, events, and error details are
30 // templated, but only values supported by the specified MethodCodec can be
31 // used.
32 template <typename T = EncodableValue>
33 class EventChannel {
34  public:
35  // Creates an instance that sends and receives event handler 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  ~EventChannel() = default;
42 
43  // Prevent copying.
44  EventChannel(EventChannel const&) = delete;
45  EventChannel& operator=(EventChannel const&) = delete;
46 
47  // Registers a stream handler on this channel.
48  // If no handler has been registered, any incoming stream setup requests will
49  // be handled silently by providing an empty stream.
50  void SetStreamHandler(std::unique_ptr<StreamHandler<T>> handler) {
51  if (!handler) {
52  messenger_->SetMessageHandler(name_, nullptr);
53  is_listening_ = false;
54  return;
55  }
56 
57  // std::function requires a copyable lambda, so convert to a shared pointer.
58  // This is safe since only one copy of the shared_pointer will ever be
59  // accessed.
60  std::shared_ptr<StreamHandler<T>> shared_handler(handler.release());
61  const MethodCodec<T>* codec = codec_;
62  const std::string channel_name = name_;
63  const BinaryMessenger* messenger = messenger_;
64  BinaryMessageHandler binary_handler = [shared_handler, codec, channel_name,
65  messenger,
66  this](const uint8_t* message,
67  const size_t message_size,
68  BinaryReply reply) {
69  constexpr char kOnListenMethod[] = "listen";
70  constexpr char kOnCancelMethod[] = "cancel";
71 
72  std::unique_ptr<MethodCall<T>> method_call =
73  codec->DecodeMethodCall(message, message_size);
74  if (!method_call) {
75  std::cerr << "Unable to construct method call from message on channel: "
76  << channel_name << std::endl;
77  reply(nullptr, 0);
78  return;
79  }
80 
81  const std::string& method = method_call->method_name();
82  if (method.compare(kOnListenMethod) == 0) {
83  if (is_listening_) {
84  std::unique_ptr<StreamHandlerError<T>> error =
85  shared_handler->OnCancel(nullptr);
86  if (error) {
87  std::cerr << "Failed to cancel existing stream: "
88  << (error->error_code) << ", " << (error->error_message)
89  << ", " << (error->error_details);
90  }
91  }
92  is_listening_ = true;
93 
94  std::unique_ptr<std::vector<uint8_t>> result;
95  auto sink = std::make_unique<EventSinkImplementation>(
96  messenger, channel_name, codec);
97  std::unique_ptr<StreamHandlerError<T>> error =
98  shared_handler->OnListen(method_call->arguments(), std::move(sink));
99  if (error) {
100  result = codec->EncodeErrorEnvelope(
101  error->error_code, error->error_message, error->error_details);
102  } else {
103  result = codec->EncodeSuccessEnvelope();
104  }
105  reply(result->data(), result->size());
106  } else if (method.compare(kOnCancelMethod) == 0) {
107  std::unique_ptr<std::vector<uint8_t>> result;
108  if (is_listening_) {
109  std::unique_ptr<StreamHandlerError<T>> error =
110  shared_handler->OnCancel(method_call->arguments());
111  if (error) {
112  result = codec->EncodeErrorEnvelope(
113  error->error_code, error->error_message, error->error_details);
114  } else {
115  result = codec->EncodeSuccessEnvelope();
116  }
117  is_listening_ = false;
118  } else {
119  result = codec->EncodeErrorEnvelope(
120  "error", "No active stream to cancel", nullptr);
121  }
122  reply(result->data(), result->size());
123  } else {
124  reply(nullptr, 0);
125  }
126  };
127  messenger_->SetMessageHandler(name_, std::move(binary_handler));
128  }
129 
130  private:
131  class EventSinkImplementation : public EventSink<T> {
132  public:
133  EventSinkImplementation(const BinaryMessenger* messenger,
134  const std::string& name,
135  const MethodCodec<T>* codec)
136  : messenger_(messenger), name_(name), codec_(codec) {}
137  ~EventSinkImplementation() = default;
138 
139  // Prevent copying.
140  EventSinkImplementation(EventSinkImplementation const&) = delete;
141  EventSinkImplementation& operator=(EventSinkImplementation const&) = delete;
142 
143  private:
144  const BinaryMessenger* messenger_;
145  const std::string name_;
146  const MethodCodec<T>* codec_;
147 
148  protected:
149  void SuccessInternal(const T* event = nullptr) override {
150  auto result = codec_->EncodeSuccessEnvelope(event);
151  messenger_->Send(name_, result->data(), result->size());
152  }
153 
154  void ErrorInternal(const std::string& error_code,
155  const std::string& error_message,
156  const T* error_details) override {
157  auto result =
158  codec_->EncodeErrorEnvelope(error_code, error_message, error_details);
159  messenger_->Send(name_, result->data(), result->size());
160  }
161 
162  void EndOfStreamInternal() override { messenger_->Send(name_, nullptr, 0); }
163  };
164 
165  BinaryMessenger* messenger_;
166  const std::string name_;
167  const MethodCodec<T>* codec_;
168  bool is_listening_;
169 };
170 
171 } // namespace flutter
172 
173 #endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
G_BEGIN_DECLS FlMethodCall * method_call
void SetStreamHandler(std::unique_ptr< StreamHandler< T >> handler)
Definition: event_channel.h:50
FlMethodResponse GError ** error
EventChannel & operator=(EventChannel const &)=delete
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
std::unique_ptr< std::vector< uint8_t > > EncodeErrorEnvelope(const std::string &error_code, const std::string &error_message="", const T *error_details=nullptr) const
Definition: method_codec.h:62
EventChannel(BinaryMessenger *messenger, const std::string &name, const MethodCodec< T > *codec)
Definition: event_channel.h:37
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelope(const T *result=nullptr) const
Definition: method_codec.h:55
GdkEventButton * event
Definition: fl_view.cc:62
virtual void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler)=0
const char * name
Definition: fuchsia.cc:50
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