Skip to content

Commit d736085

Browse files
authored
Extract codecs from plugin API (#110)
Extracts method codecs into stand-alone objects, and allows plugins to indicate that they use a codec other than JSON. This is an incremental step toward aligning the plugin API with Flutter's MethodChannel API. For now no other codecs are actually implemented in the framework, and the default is still JSON (unlike in existing Flutter code) so that this is only a minor breaking change, and only on Linux (unavoidable due to the initial use of Json::Value in key interfaces; the JsonPlugin class is designed to minimize impact on existing plugins). A future change will move to MethodChannel, which will be a more significant breaking change. Partially addresses issue #67 in that custom codecs are now supported, even though the Standard (binary) codec is not yet implemented.
1 parent d9393f7 commit d736085

35 files changed

+966
-369
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CALL_H_
15+
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CALL_H_
16+
17+
#include <string>
18+
19+
#include <json/json.h>
20+
21+
#include "method_call.h"
22+
23+
namespace flutter_desktop_embedding {
24+
25+
// A concrete implmentation of MethodCall for use with the JSON codec.
26+
class JsonMethodCall : public MethodCall {
27+
public:
28+
// Creates a MethodCall with the given name and, optionally, arguments.
29+
explicit JsonMethodCall(const std::string &method_name,
30+
const Json::Value &arguments = Json::Value());
31+
~JsonMethodCall();
32+
33+
// Prevent copying.
34+
JsonMethodCall(JsonMethodCall const &) = delete;
35+
JsonMethodCall &operator=(JsonMethodCall const &) = delete;
36+
37+
// MethodCall:
38+
// Returns a pointer to a Json::Value object. This will never return null;
39+
// 'no arguments' is represented with a JSON::nullValue.
40+
const void *arguments() const override;
41+
42+
// Returns a reference to the object pointed to by arguments().
43+
// This is a convience method for code that is interacting directly with a
44+
// JsonMethodCall to avoid casting and dereferencing.
45+
const Json::Value &GetArgumentsAsJson() const;
46+
47+
private:
48+
Json::Value arguments_;
49+
};
50+
51+
} // namespace flutter_desktop_embedding
52+
53+
#endif // LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CALL_H_
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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 LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CODEC_H_
15+
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CODEC_H_
16+
17+
#include <json/json.h>
18+
19+
#include "method_codec.h"
20+
21+
namespace flutter_desktop_embedding {
22+
23+
// An implementation of MethodCodec that uses JSON strings as the serialization.
24+
//
25+
// void* types in this implementation must always be Json::Value* types (from
26+
// the jsoncpp library).
27+
class JsonMethodCodec : public MethodCodec {
28+
public:
29+
// Returns the shared instance of the codec.
30+
static const JsonMethodCodec &GetInstance();
31+
32+
~JsonMethodCodec() = default;
33+
34+
// Prevent copying.
35+
JsonMethodCodec(JsonMethodCodec const &) = delete;
36+
JsonMethodCodec &operator=(JsonMethodCodec const &) = delete;
37+
38+
protected:
39+
// Instances should be obtained via GetInstance.
40+
JsonMethodCodec() = default;
41+
42+
// MethodCodec:
43+
std::unique_ptr<MethodCall> DecodeMethodCallInternal(
44+
const uint8_t *message, const size_t message_size) const override;
45+
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal(
46+
const MethodCall &method_call) const override;
47+
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal(
48+
const void *result) const override;
49+
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal(
50+
const std::string &error_code, const std::string &error_message,
51+
const void *error_details) const override;
52+
53+
private:
54+
// Serializes |json| into a byte stream.
55+
std::unique_ptr<std::vector<uint8_t>> EncodeJsonObject(
56+
const Json::Value &json) const;
57+
};
58+
59+
} // namespace flutter_desktop_embedding
60+
61+
#endif // LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_METHOD_CODEC_H_
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_PLUGIN_H_
15+
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_PLUGIN_H_
16+
17+
#include "json_method_call.h"
18+
#include "plugin.h"
19+
20+
namespace flutter_desktop_embedding {
21+
22+
// A base class for plugins using the JSON method codec.
23+
//
24+
// Provides a few utility shims from the type-agnostic Plugin class.
25+
class JsonPlugin : public Plugin {
26+
public:
27+
// See Plugin for constructor details.
28+
explicit JsonPlugin(const std::string &channel, bool input_blocking = false);
29+
virtual ~JsonPlugin();
30+
31+
// Prevent copying.
32+
JsonPlugin(JsonPlugin const &) = delete;
33+
JsonPlugin &operator=(JsonPlugin const &) = delete;
34+
35+
// Plugin implementation:
36+
const MethodCodec &GetCodec() const override;
37+
void HandleMethodCall(const MethodCall &method_call,
38+
std::unique_ptr<MethodResult> result) override;
39+
40+
protected:
41+
// Identical to HandleMethodCall, except that the call has been cast to the
42+
// more specific type. Subclasses must implement this instead of
43+
// HandleMethodCall.
44+
virtual void HandleJsonMethodCall(const JsonMethodCall &method_call,
45+
std::unique_ptr<MethodResult> result) = 0;
46+
47+
// Calls InvokeMethodCall with a JsonMethodCall constructed from the given
48+
// values.
49+
void InvokeMethod(const std::string &method,
50+
const Json::Value &arguments = Json::Value());
51+
};
52+
53+
} // namespace flutter_desktop_embedding
54+
55+
#endif // LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_PLUGIN_H_

linux/library/include/flutter_desktop_embedding/method_call.h

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,31 @@
1414
#ifndef LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_CALL_H_
1515
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_CALL_H_
1616

17-
#include <json/json.h>
18-
19-
#include <memory>
2017
#include <string>
2118

22-
#include <flutter_embedder.h>
23-
2419
namespace flutter_desktop_embedding {
2520

2621
// An object encapsulating a method call from Flutter.
27-
// TODO: Move serialization details into a method codec class, to match mobile
28-
// Flutter plugin APIs.
2922
class MethodCall {
3023
public:
31-
// Creates a MethodCall with the given name and, optionally, arguments.
32-
explicit MethodCall(const std::string &method_name,
33-
const Json::Value &arguments = Json::Value());
24+
// Creates a MethodCall with the given name. Used only as a superclass
25+
// constructor for subclasses, which should also take the arguments.
26+
explicit MethodCall(const std::string &method_name);
27+
virtual ~MethodCall();
3428

35-
// Returns a new MethodCall created from a JSON message received from the
36-
// Flutter engine.
37-
static std::unique_ptr<MethodCall> CreateFromMessage(
38-
const Json::Value &message);
39-
~MethodCall();
29+
// Prevent copying.
30+
MethodCall(MethodCall const &) = delete;
31+
MethodCall &operator=(MethodCall const &) = delete;
4032

4133
// The name of the method being called.
4234
const std::string &method_name() const { return method_name_; }
4335

44-
// The arguments to the method call, or a nullValue if there are none.
45-
const Json::Value &arguments() const { return arguments_; }
46-
47-
// Returns a version of the method call serialized in the format expected by
48-
// the Flutter engine.
49-
Json::Value AsMessage() const;
36+
// The arguments to the method call, or NULL if there are none. The type of
37+
// the object being pointed to is determined by the concrete subclasses.
38+
virtual const void *arguments() const = 0;
5039

5140
private:
5241
std::string method_name_;
53-
Json::Value arguments_;
5442
};
5543

5644
} // namespace flutter_desktop_embedding
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_CODEC_H_
15+
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_CODEC_H_
16+
17+
#include <memory>
18+
#include <string>
19+
#include <vector>
20+
21+
#include "method_call.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+
class MethodCodec {
28+
public:
29+
virtual ~MethodCodec();
30+
31+
// Returns the MethodCall encoded in |message|, or nullptr if it cannot be
32+
// decoded.
33+
// TODO: Consider adding absl as a dependency and using absl::Span.
34+
std::unique_ptr<MethodCall> DecodeMethodCall(const uint8_t *message,
35+
const size_t message_size) const;
36+
37+
// Returns a binary encoding of the given |method_call|, or nullptr if the
38+
// method call cannot be serialized by this codec.
39+
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCall(
40+
const MethodCall &method_call) const;
41+
42+
// Returns a binary encoding of |result|. |result| must be a type supported
43+
// by the codec.
44+
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelope(
45+
const void *result = nullptr) const;
46+
47+
// Returns a binary encoding of |error|. The |error_details| must be a type
48+
// supported by the codec.
49+
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelope(
50+
const std::string &error_code, const std::string &error_message = "",
51+
const void *error_details = nullptr) const;
52+
53+
protected:
54+
// Implementations of the public interface, to be provided by subclasses.
55+
virtual std::unique_ptr<MethodCall> DecodeMethodCallInternal(
56+
const uint8_t *message, const size_t message_size) const = 0;
57+
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal(
58+
const MethodCall &method_call) const = 0;
59+
virtual std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal(
60+
const void *result) const = 0;
61+
virtual std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal(
62+
const std::string &error_code, const std::string &error_message,
63+
const void *error_details) const = 0;
64+
};
65+
66+
} // namespace flutter_desktop_embedding
67+
68+
#endif // LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_CODEC_H_

linux/library/include/flutter_desktop_embedding/method_result.h

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,34 @@
1414
#ifndef LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_RESULT_H_
1515
#define LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_RESULT_H_
1616

17-
#include <json/json.h>
18-
19-
#include <memory>
2017
#include <string>
2118

22-
#include <flutter_embedder.h>
23-
2419
namespace flutter_desktop_embedding {
2520

2621
// Encapsulates a result sent back to the Flutter engine in response to a
2722
// MethodCall. Only one method should be called on any given instance.
2823
class MethodResult {
2924
public:
25+
MethodResult();
26+
virtual ~MethodResult();
27+
28+
// Prevent copying.
29+
MethodResult(MethodResult const &) = delete;
30+
MethodResult &operator=(MethodResult const &) = delete;
31+
3032
// Sends a success response, indicating that the call completed successfully.
31-
// An optional value can be provided as part of the success message.
32-
void Success(const Json::Value &result = Json::Value());
33+
// An optional value can be provided as part of the success message. The value
34+
// must be a type handled by the channel's codec.
35+
void Success(const void *result = nullptr);
3336

3437
// Sends an error response, indicating that the call was understood but
3538
// handling failed in some way. A string error code must be provided, and in
3639
// addition an optional user-readable error_message and/or details object can
37-
// be included.
40+
// be included. The details, if provided, must be a type handled by the
41+
// channel's codec.
3842
void Error(const std::string &error_code,
3943
const std::string &error_message = "",
40-
const Json::Value &error_details = Json::Value());
44+
const void *error_details = nullptr);
4145

4246
// Sends a not-implemented response, indicating that the method either was not
4347
// recognized, or has not been implemented.
@@ -46,45 +50,13 @@ class MethodResult {
4650
protected:
4751
// Internal implementation of the interface methods above, to be implemented
4852
// in subclasses.
49-
virtual void SuccessInternal(const Json::Value &result) = 0;
53+
virtual void SuccessInternal(const void *result) = 0;
5054
virtual void ErrorInternal(const std::string &error_code,
5155
const std::string &error_message,
52-
const Json::Value &error_details) = 0;
56+
const void *error_details) = 0;
5357
virtual void NotImplementedInternal() = 0;
5458
};
5559

56-
// Implemention of MethodResult using JSON as the protocol.
57-
// TODO: Move this logic into method codecs.
58-
class JsonMethodResult : public MethodResult {
59-
public:
60-
// Creates a result object that will send results to |engine|, tagged as
61-
// associated with |response_handle|. The engine pointer must remain valid for
62-
// as long as this object exists.
63-
JsonMethodResult(FlutterEngine engine,
64-
const FlutterPlatformMessageResponseHandle *response_handle);
65-
~JsonMethodResult();
66-
67-
protected:
68-
void SuccessInternal(const Json::Value &result) override;
69-
void ErrorInternal(const std::string &error_code,
70-
const std::string &error_message,
71-
const Json::Value &error_details) override;
72-
void NotImplementedInternal() override;
73-
74-
private:
75-
// Sends the given JSON response object to the engine.
76-
void SendResponseJson(const Json::Value &response);
77-
78-
// Sends the given response data (which must either be nullptr or a serialized
79-
// JSON response) to the engine.
80-
// Uses a pointer rather than a reference since nullptr is used to indicate
81-
// not-implemented (which is represented to Flutter by no data).
82-
void SendResponse(const std::string *serialized_response);
83-
84-
FlutterEngine engine_;
85-
const FlutterPlatformMessageResponseHandle *response_handle_;
86-
};
87-
8860
} // namespace flutter_desktop_embedding
8961

9062
#endif // LINUX_LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_METHOD_RESULT_H_

0 commit comments

Comments
 (0)