Skip to content

Commit 867e99e

Browse files
authored
[linux/windows] Add BasicMessageChannel (#219)
Implements BasicMessageChannel, adds MessageCodec, and makes JsonMessageCodec public. Converts the key event handler from using BinaryMessenger directly to using a BasicMessageChannel to send events now that it's available.
1 parent 64bb275 commit 867e99e

11 files changed

+212
-49
lines changed

library/BUILD.gn

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,21 @@ published_shared_library("flutter_embedder") {
3636
if (is_linux || is_win) {
3737
sources += [
3838
"common/engine_method_result.cc",
39-
"common/internal/json_message_codec.cc",
40-
"common/internal/json_message_codec.h",
4139
"common/internal/plugin_handler.cc",
4240
"common/internal/plugin_handler.h",
4341
"common/internal/text_input_model.cc",
4442
"common/internal/text_input_model.h",
43+
"common/json_message_codec.cc",
4544
"common/json_method_codec.cc",
4645
]
4746
public += [
47+
"include/flutter_desktop_embedding/basic_message_channel.h",
4848
"include/flutter_desktop_embedding/binary_messenger.h",
4949
"include/flutter_desktop_embedding/engine_method_result.h",
5050
"include/flutter_desktop_embedding/fde_export.h",
51+
"include/flutter_desktop_embedding/json_message_codec.h",
5152
"include/flutter_desktop_embedding/json_method_codec.h",
53+
"include/flutter_desktop_embedding/message_codec.h",
5254
"include/flutter_desktop_embedding/method_call.h",
5355
"include/flutter_desktop_embedding/method_channel.h",
5456
"include/flutter_desktop_embedding/method_codec.h",

library/common/glfw/key_event_handler.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <json/json.h>
1717
#include <iostream>
1818

19-
#include "library/common/internal/json_message_codec.h"
19+
#include "library/include/flutter_desktop_embedding/json_message_codec.h"
2020

2121
static constexpr char kChannelName[] = "flutter/keyevent";
2222

@@ -32,8 +32,9 @@ static constexpr char kRepeat[] = "repeat";
3232

3333
namespace flutter_desktop_embedding {
3434

35-
KeyEventHandler::KeyEventHandler(const BinaryMessenger *messenger)
36-
: messenger_(messenger), channel_(kChannelName) {}
35+
KeyEventHandler::KeyEventHandler(BinaryMessenger *messenger)
36+
: channel_(std::make_unique<BasicMessageChannel<Json::Value>>(
37+
messenger, kChannelName, &JsonMessageCodec::GetInstance())) {}
3738

3839
KeyEventHandler::~KeyEventHandler() {}
3940

@@ -43,23 +44,22 @@ void KeyEventHandler::KeyboardHook(GLFWwindow *window, int key, int scancode,
4344
int action, int mods) {
4445
// TODO: Translate to a cross-platform key code system rather than passing
4546
// the native key code.
46-
Json::Value args;
47-
args[kKeyCodeKey] = key;
48-
args[kKeyMapKey] = kAndroidKeyMap;
47+
Json::Value event;
48+
event[kKeyCodeKey] = key;
49+
event[kKeyMapKey] = kAndroidKeyMap;
4950

5051
switch (action) {
5152
case GLFW_PRESS:
52-
args[kTypeKey] = kKeyDown;
53+
event[kTypeKey] = kKeyDown;
5354
break;
5455
case GLFW_RELEASE:
55-
args[kTypeKey] = kKeyUp;
56+
event[kTypeKey] = kKeyUp;
5657
break;
5758
default:
5859
std::cerr << "Unknown key event action: " << action << std::endl;
5960
return;
6061
}
61-
auto message = JsonMessageCodec::GetInstance().EncodeMessage(args);
62-
messenger_->Send(channel_, message->data(), message->size());
62+
channel_->Send(event);
6363
}
6464

6565
} // namespace flutter_desktop_embedding

library/common/glfw/key_event_handler.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
#ifndef LIBRARY_COMMON_GLFW_KEY_EVENT_HANDLER_H_
1515
#define LIBRARY_COMMON_GLFW_KEY_EVENT_HANDLER_H_
1616

17+
#include <memory>
18+
19+
#include <json/json.h>
20+
1721
#include "library/common/glfw/keyboard_hook_handler.h"
22+
#include "library/include/flutter_desktop_embedding/basic_message_channel.h"
1823
#include "library/include/flutter_desktop_embedding/binary_messenger.h"
1924

2025
namespace flutter_desktop_embedding {
@@ -24,7 +29,7 @@ namespace flutter_desktop_embedding {
2429
// Handles key events and forwards them to the Flutter engine.
2530
class KeyEventHandler : public KeyboardHookHandler {
2631
public:
27-
explicit KeyEventHandler(const BinaryMessenger *messenger);
32+
explicit KeyEventHandler(BinaryMessenger *messenger);
2833
virtual ~KeyEventHandler();
2934

3035
// KeyboardHookHandler.
@@ -33,10 +38,8 @@ class KeyEventHandler : public KeyboardHookHandler {
3338
void CharHook(GLFWwindow *window, unsigned int code_point) override;
3439

3540
private:
36-
// Binds this plugin to the given caller-owned binary messenger. It must
37-
// remain valid for the life of the plugin.
38-
const BinaryMessenger *messenger_;
39-
std::string channel_;
41+
// The Flutter system channel for key event messages.
42+
std::unique_ptr<BasicMessageChannel<Json::Value>> channel_;
4043
};
4144

4245
} // namespace flutter_desktop_embedding

library/common/internal/json_message_codec.cc renamed to library/common/json_message_codec.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
#include "library/common/internal/json_message_codec.h"
14+
#include "library/include/flutter_desktop_embedding/json_message_codec.h"
1515

1616
#include <iostream>
1717
#include <string>
@@ -24,7 +24,7 @@ const JsonMessageCodec &JsonMessageCodec::GetInstance() {
2424
return sInstance;
2525
}
2626

27-
std::unique_ptr<std::vector<uint8_t>> JsonMessageCodec::EncodeMessage(
27+
std::unique_ptr<std::vector<uint8_t>> JsonMessageCodec::EncodeMessageInternal(
2828
const Json::Value &message) const {
2929
Json::StreamWriterBuilder writer_builder;
3030
std::string serialization = Json::writeString(writer_builder, message);
@@ -33,12 +33,12 @@ std::unique_ptr<std::vector<uint8_t>> JsonMessageCodec::EncodeMessage(
3333
serialization.end());
3434
}
3535

36-
std::unique_ptr<Json::Value> JsonMessageCodec::DecodeMessage(
37-
const uint8_t *message, const size_t message_size) const {
36+
std::unique_ptr<Json::Value> JsonMessageCodec::DecodeMessageInternal(
37+
const uint8_t *binary_message, const size_t message_size) const {
3838
Json::CharReaderBuilder reader_builder;
3939
std::unique_ptr<Json::CharReader> parser(reader_builder.newCharReader());
4040

41-
auto raw_message = reinterpret_cast<const char *>(message);
41+
auto raw_message = reinterpret_cast<const char *>(binary_message);
4242
auto json_message = std::make_unique<Json::Value>();
4343
std::string parse_errors;
4444
bool parsing_successful =

library/common/json_method_codec.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414
#include "library/include/flutter_desktop_embedding/json_method_codec.h"
1515

16-
#include "library/common/internal/json_message_codec.h"
16+
#include "library/include/flutter_desktop_embedding/json_message_codec.h"
1717

1818
namespace flutter_desktop_embedding {
1919

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_
15+
#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_
16+
17+
#include <iostream>
18+
#include <string>
19+
20+
#include "binary_messenger.h"
21+
#include "fde_export.h"
22+
#include "message_codec.h"
23+
24+
namespace flutter_desktop_embedding {
25+
26+
// A message reply callback.
27+
//
28+
// Used for submitting a reply back to a Flutter message sender.
29+
template <typename T>
30+
using MessageReply = std::function<void(const T &reply)>;
31+
32+
// A handler for receiving a message from the Flutter engine.
33+
//
34+
// Implementations must asynchronously call reply exactly once with the reply
35+
// to the message.
36+
template <typename T>
37+
using MessageHandler =
38+
std::function<void(const T &message, MessageReply<T> reply)>;
39+
40+
// A channel for communicating with the Flutter engine by sending asynchronous
41+
// messages.
42+
template <typename T>
43+
class FDE_EXPORT BasicMessageChannel {
44+
public:
45+
// Creates an instance that sends and receives method calls on the channel
46+
// named |name|, encoded with |codec| and dispatched via |messenger|.
47+
//
48+
// TODO: Make codec optional once the standard codec is supported (Issue #67).
49+
BasicMessageChannel(BinaryMessenger *messenger, const std::string &name,
50+
const MessageCodec<T> *codec)
51+
: messenger_(messenger), name_(name), codec_(codec) {}
52+
~BasicMessageChannel() {}
53+
54+
// Prevent copying.
55+
BasicMessageChannel(BasicMessageChannel const &) = delete;
56+
BasicMessageChannel &operator=(BasicMessageChannel const &) = delete;
57+
58+
// Sends a message to the Flutter engine on this channel.
59+
void Send(const T &message) {
60+
std::unique_ptr<std::vector<uint8_t>> raw_message =
61+
codec_->EncodeMessage(message);
62+
messenger_->Send(name_, raw_message->data(), raw_message->size());
63+
}
64+
65+
// TODO: Add support for a version of Send expecting a reply once
66+
// https://github.com/flutter/flutter/issues/18852 is fixed.
67+
68+
// Registers a handler that should be called any time a message is
69+
// received on this channel.
70+
void SetMessageHandler(MessageHandler<T> handler) const {
71+
const auto *codec = codec_;
72+
std::string channel_name = name_;
73+
BinaryMessageHandler binary_handler = [handler, codec, channel_name](
74+
const uint8_t *binary_message,
75+
const size_t binary_message_size,
76+
BinaryReply binary_reply) {
77+
// Use this channel's codec to decode the message and build a reply
78+
// handler.
79+
std::unique_ptr<T> message =
80+
codec->DecodeMessage(binary_message, binary_message_size);
81+
if (!message) {
82+
std::cerr << "Unable to decode message on channel " << channel_name
83+
<< std::endl;
84+
binary_reply(nullptr, 0);
85+
return;
86+
}
87+
88+
MessageReply<T> unencoded_reply = [binary_reply,
89+
codec](const T &unencoded_response) {
90+
auto binary_response = codec->EncodeMessage(unencoded_response);
91+
binary_reply(binary_response->data(), binary_response->size());
92+
};
93+
handler(*message, std::move(unencoded_reply));
94+
};
95+
messenger_->SetMessageHandler(name_, std::move(binary_handler));
96+
}
97+
98+
private:
99+
BinaryMessenger *messenger_;
100+
std::string name_;
101+
const MessageCodec<T> *codec_;
102+
};
103+
104+
} // namespace flutter_desktop_embedding
105+
106+
#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_

library/include/flutter_desktop_embedding/binary_messenger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
// the message/message_size pairs.
2424
namespace flutter_desktop_embedding {
2525

26-
// A message reply callback.
26+
// A binary message reply callback.
2727
//
28-
// Used for submitting a reply back to a Flutter message sender.
28+
// Used for submitting a binary reply back to a Flutter message sender.
2929
typedef std::function<void(const uint8_t *reply, const size_t reply_size)>
3030
BinaryReply;
3131

library/common/internal/json_message_codec.h renamed to library/include/flutter_desktop_embedding/json_message_codec.h

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,19 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
#ifndef LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_
15-
#define LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_
16-
17-
#include <memory>
18-
#include <vector>
14+
#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_
15+
#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_
1916

2017
#include <json/json.h>
2118

19+
#include "fde_export.h"
20+
#include "message_codec.h"
21+
2222
namespace flutter_desktop_embedding {
2323

2424
// A message encoding/decoding mechanism for communications to/from the
2525
// Flutter engine via JSON channels.
26-
//
27-
// TODO: Make this public, once generalizing a MessageCodec parent interface is
28-
// addressed; this is complicated by the return type of EncodeMessage.
29-
// Part of issue #102.
30-
class JsonMessageCodec {
26+
class JsonMessageCodec : public MessageCodec<Json::Value> {
3127
public:
3228
// Returns the shared instance of the codec.
3329
static const JsonMessageCodec &GetInstance();
@@ -38,22 +34,17 @@ class JsonMessageCodec {
3834
JsonMessageCodec(JsonMessageCodec const &) = delete;
3935
JsonMessageCodec &operator=(JsonMessageCodec const &) = delete;
4036

41-
// Returns a binary encoding of the given message, or nullptr if the
42-
// message cannot be serialized by this codec.
43-
std::unique_ptr<std::vector<uint8_t>> EncodeMessage(
44-
const Json::Value &message) const;
45-
46-
// Returns the JSON object encoded in |message|, or nullptr if it cannot be
47-
// decoded.
48-
// TODO: Consider adding absl as a dependency and using absl::Span.
49-
std::unique_ptr<Json::Value> DecodeMessage(const uint8_t *message,
50-
const size_t message_size) const;
51-
5237
protected:
5338
// Instances should be obtained via GetInstance.
5439
JsonMessageCodec() = default;
40+
41+
// MessageCodec:
42+
std::unique_ptr<Json::Value> DecodeMessageInternal(
43+
const uint8_t *binary_message, const size_t message_size) const override;
44+
std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal(
45+
const Json::Value &message) const override;
5546
};
5647

5748
} // namespace flutter_desktop_embedding
5849

59-
#endif // LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_
50+
#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_
15+
#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_
16+
17+
#include <memory>
18+
#include <string>
19+
#include <vector>
20+
21+
#include "fde_export.h"
22+
23+
namespace flutter_desktop_embedding {
24+
25+
// Translates between a binary message and higher-level method call and
26+
// response/error objects.
27+
template <typename T>
28+
class FDE_EXPORT MessageCodec {
29+
public:
30+
MessageCodec() = default;
31+
virtual ~MessageCodec() = default;
32+
33+
// Prevent copying.
34+
MessageCodec(MessageCodec<T> const &) = delete;
35+
MessageCodec &operator=(MessageCodec<T> const &) = delete;
36+
37+
// Returns the message encoded in |binary_message|, or nullptr if it cannot be
38+
// decoded by this codec.
39+
// TODO: Consider adding absl as a dependency and using absl::Span.
40+
std::unique_ptr<T> DecodeMessage(const uint8_t *binary_message,
41+
const size_t message_size) const {
42+
return std::move(DecodeMessageInternal(binary_message, message_size));
43+
}
44+
45+
// Returns a binary encoding of the given |message|, or nullptr if the
46+
// message cannot be serialized by this codec.
47+
std::unique_ptr<std::vector<uint8_t>> EncodeMessage(const T &message) const {
48+
return std::move(EncodeMessageInternal(message));
49+
}
50+
51+
protected:
52+
// Implementations of the public interface, to be provided by subclasses.
53+
virtual std::unique_ptr<T> DecodeMessageInternal(
54+
const uint8_t *binary_message, const size_t message_size) const = 0;
55+
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal(
56+
const T &message) const = 0;
57+
};
58+
59+
} // namespace flutter_desktop_embedding
60+
61+
#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_

0 commit comments

Comments
 (0)