siyao
4 年前
当前提交
55b07fc4
共有 51 个文件被更改,包括 4218 次插入 和 84 次删除
-
131com.unity.uiwidgets/Runtime/services/platform_channel.cs
-
81com.unity.uiwidgets/Runtime/services/system_channels.cs
-
45engine/Build.bee.cs
-
16engine/src/shell/platform/embedder/embedder.h
-
198engine/src/shell/platform/unity/windows/text_input_plugin.cc
-
49engine/src/shell/platform/unity/windows/text_input_plugin.h
-
313engine/src/shell/platform/unity/windows/uiwidgets_windows.cc
-
69engine/src/shell/platform/unity/windows/window_state.h
-
93engine/src/shell/platform/common/cpp/client_wrapper/basic_message_channel_unittests.cc
-
105engine/src/shell/platform/common/cpp/client_wrapper/byte_stream_wrappers.h
-
330engine/src/shell/platform/common/cpp/client_wrapper/encodable_value_unittests.cc
-
45engine/src/shell/platform/common/cpp/client_wrapper/engine_method_result.cc
-
108engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/basic_message_channel.h
-
34engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/binary_messenger.h
-
428engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/encodable_value.h
-
70engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/engine_method_result.h
-
32engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/json_message_codec.h
-
40engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/json_method_codec.h
-
16engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/json_type.h
-
48engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/message_codec.h
-
33engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_call.h
-
82engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_channel.h
-
70engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_codec.h
-
42engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_result.h
-
48engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/plugin_registrar.h
-
26engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/plugin_registry.h
-
32engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_message_codec.h
-
40engine/src/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_method_codec.h
-
70engine/src/shell/platform/common/cpp/client_wrapper/json_message_codec.cc
-
140engine/src/shell/platform/common/cpp/client_wrapper/json_method_codec.cc
-
23engine/src/shell/platform/common/cpp/client_wrapper/method_call_unittests.cc
-
94engine/src/shell/platform/common/cpp/client_wrapper/method_channel_unittests.cc
-
160engine/src/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc
-
95engine/src/shell/platform/common/cpp/client_wrapper/plugin_registrar_unittests.cc
-
383engine/src/shell/platform/common/cpp/client_wrapper/standard_codec.cc
-
54engine/src/shell/platform/common/cpp/client_wrapper/standard_codec_serializer.h
-
173engine/src/shell/platform/common/cpp/client_wrapper/standard_message_codec_unittests.cc
-
105engine/src/shell/platform/common/cpp/client_wrapper/standard_method_codec_unittests.cc
-
58engine/src/shell/platform/common/cpp/incoming_message_dispatcher.cc
-
78engine/src/shell/platform/common/cpp/incoming_message_dispatcher.h
-
24engine/src/shell/platform/common/cpp/public/uiwidgets_export.h
-
61engine/src/shell/platform/common/cpp/public/uiwidgets_messenger.h
-
28engine/src/shell/platform/common/cpp/public/uiwidgets_plugin_registrar.h
-
132engine/src/shell/platform/unity/windows/public/uiwidgets_windows.h
|
|||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "shell/platform/unity/windows/text_input_plugin.h"
|
|||
|
|||
#include <windows.h>
|
|||
|
|||
#include <cstdint>
|
|||
#include <iostream>
|
|||
|
|||
#include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/json_method_codec.h"
|
|||
|
|||
static constexpr char kSetEditingStateMethod[] = "TextInput.setEditingState"; |
|||
static constexpr char kClearClientMethod[] = "TextInput.clearClient"; |
|||
static constexpr char kSetClientMethod[] = "TextInput.setClient"; |
|||
static constexpr char kShowMethod[] = "TextInput.show"; |
|||
static constexpr char kHideMethod[] = "TextInput.hide"; |
|||
|
|||
static constexpr char kMultilineInputType[] = "TextInputType.multiline"; |
|||
|
|||
static constexpr char kUpdateEditingStateMethod[] = |
|||
"TextInputClient.updateEditingState"; |
|||
static constexpr char kPerformActionMethod[] = "TextInputClient.performAction"; |
|||
|
|||
static constexpr char kSelectionBaseKey[] = "selectionBase"; |
|||
static constexpr char kSelectionExtentKey[] = "selectionExtent"; |
|||
|
|||
static constexpr char kTextKey[] = "text"; |
|||
|
|||
static constexpr char kChannelName[] = "flutter/textinput"; |
|||
|
|||
static constexpr char kBadArgumentError[] = "Bad Arguments"; |
|||
static constexpr char kInternalConsistencyError[] = |
|||
"Internal Consistency Error"; |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// void TextInputPlugin::CharHook(Win32FlutterWindow* window,
|
|||
// char32_t code_point) {
|
|||
// if (active_model_ == nullptr) {
|
|||
// return;
|
|||
// }
|
|||
// active_model_->AddCharacter(code_point);
|
|||
// SendStateUpdate(*active_model_);
|
|||
// }
|
|||
|
|||
// void TextInputPlugin::KeyboardHook(Win32FlutterWindow* window,
|
|||
// int key,
|
|||
// int scancode,
|
|||
// int action,
|
|||
// int mods) {
|
|||
// if (active_model_ == nullptr) {
|
|||
// return;
|
|||
// }
|
|||
// if (action == WM_KEYDOWN) {
|
|||
// switch (key) {
|
|||
// case VK_LEFT:
|
|||
// if (active_model_->MoveCursorBack()) {
|
|||
// SendStateUpdate(*active_model_);
|
|||
// }
|
|||
// break;
|
|||
// case VK_RIGHT:
|
|||
// if (active_model_->MoveCursorForward()) {
|
|||
// SendStateUpdate(*active_model_);
|
|||
// }
|
|||
// break;
|
|||
// case VK_END:
|
|||
// active_model_->MoveCursorToEnd();
|
|||
// SendStateUpdate(*active_model_);
|
|||
// break;
|
|||
// case VK_HOME:
|
|||
// active_model_->MoveCursorToBeginning();
|
|||
// SendStateUpdate(*active_model_);
|
|||
// break;
|
|||
// case VK_BACK:
|
|||
// if (active_model_->Backspace()) {
|
|||
// SendStateUpdate(*active_model_);
|
|||
// }
|
|||
// break;
|
|||
// case VK_DELETE:
|
|||
// if (active_model_->Delete()) {
|
|||
// SendStateUpdate(*active_model_);
|
|||
// }
|
|||
// break;
|
|||
// case VK_RETURN:
|
|||
// EnterPressed(active_model_.get());
|
|||
// break;
|
|||
// default:
|
|||
// break;
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
|
|||
TextInputPlugin::TextInputPlugin(uiwidgets::BinaryMessenger* messenger) |
|||
: channel_(std::make_unique<uiwidgets::MethodChannel<rapidjson::Document>>( |
|||
messenger, |
|||
kChannelName, |
|||
&uiwidgets::JsonMethodCodec::GetInstance()))/*,
|
|||
active_model_(nullptr)*/ { |
|||
channel_->SetMethodCallHandler( |
|||
[this]( |
|||
const uiwidgets::MethodCall<rapidjson::Document>& call, |
|||
std::unique_ptr<uiwidgets::MethodResult<rapidjson::Document>> result) { |
|||
HandleMethodCall(call, std::move(result)); |
|||
}); |
|||
} |
|||
|
|||
TextInputPlugin::~TextInputPlugin() = default; |
|||
|
|||
void TextInputPlugin::HandleMethodCall( |
|||
const uiwidgets::MethodCall<rapidjson::Document>& method_call, |
|||
std::unique_ptr<uiwidgets::MethodResult<rapidjson::Document>> result) { |
|||
const std::string& method = method_call.method_name(); |
|||
|
|||
if (method.compare(kShowMethod) == 0 || method.compare(kHideMethod) == 0) { |
|||
// These methods are no-ops.
|
|||
} else if (method.compare(kClearClientMethod) == 0) { |
|||
//active_model_ = nullptr;
|
|||
} else { |
|||
// Every following method requires args.
|
|||
if (!method_call.arguments() || method_call.arguments()->IsNull()) { |
|||
result->Error(kBadArgumentError, "Method invoked without args"); |
|||
return; |
|||
} |
|||
const rapidjson::Document& args = *method_call.arguments(); |
|||
|
|||
if (method.compare(kSetClientMethod) == 0) { |
|||
const rapidjson::Value& client_id_json = args[0]; |
|||
const rapidjson::Value& client_config = args[1]; |
|||
if (client_id_json.IsNull()) { |
|||
result->Error(kBadArgumentError, "Could not set client, ID is null."); |
|||
return; |
|||
} |
|||
if (client_config.IsNull()) { |
|||
result->Error(kBadArgumentError, |
|||
"Could not set client, missing arguments."); |
|||
return; |
|||
} |
|||
int client_id = client_id_json.GetInt(); |
|||
//active_model_ =
|
|||
// std::make_unique<TextInputModel>(client_id, client_config);
|
|||
} else if (method.compare(kSetEditingStateMethod) == 0) { |
|||
/*if (active_model_ == nullptr) {
|
|||
result->Error( |
|||
kInternalConsistencyError, |
|||
"Set editing state has been invoked, but no client is set."); |
|||
return; |
|||
}*/ |
|||
auto text = args.FindMember(kTextKey); |
|||
if (text == args.MemberEnd() || text->value.IsNull()) { |
|||
result->Error(kBadArgumentError, |
|||
"Set editing state has been invoked, but without text."); |
|||
return; |
|||
} |
|||
auto selection_base = args.FindMember(kSelectionBaseKey); |
|||
auto selection_extent = args.FindMember(kSelectionExtentKey); |
|||
if (selection_base == args.MemberEnd() || |
|||
selection_base->value.IsNull() || |
|||
selection_extent == args.MemberEnd() || |
|||
selection_extent->value.IsNull()) { |
|||
result->Error(kInternalConsistencyError, |
|||
"Selection base/extent values invalid."); |
|||
return; |
|||
} |
|||
/* active_model_->SetEditingState(selection_base->value.GetInt(),
|
|||
selection_extent->value.GetInt(), |
|||
text->value.GetString());*/ |
|||
} else { |
|||
// Unhandled method.
|
|||
result->NotImplemented(); |
|||
return; |
|||
} |
|||
} |
|||
// All error conditions return early, so if nothing has gone wrong indicate
|
|||
// success.
|
|||
result->Success(); |
|||
} |
|||
|
|||
// void TextInputPlugin::SendStateUpdate(const TextInputModel& model) {
|
|||
// channel_->InvokeMethod(kUpdateEditingStateMethod, model.GetState());
|
|||
// }
|
|||
|
|||
// void TextInputPlugin::EnterPressed(TextInputModel* model) {
|
|||
// if (model->input_type() == kMultilineInputType) {
|
|||
// model->AddCharacter('\n');
|
|||
// SendStateUpdate(*model);
|
|||
// }
|
|||
// auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
|||
// auto& allocator = args->GetAllocator();
|
|||
// args->PushBack(model->client_id(), allocator);
|
|||
// args->PushBack(rapidjson::Value(model->input_action(), allocator).Move(),
|
|||
// allocator);
|
|||
|
|||
// channel_->InvokeMethod(kPerformActionMethod, std::move(args));
|
|||
// }
|
|||
|
|||
} // namespace flutter
|
|
|||
|
|||
|
|||
#ifndef UIWidgets_SHELL_PLATFORM_WINDOWS_TEXT_INPUT_PLUGIN_H_ |
|||
#define UIWidgets_SHELL_PLATFORM_WINDOWS_TEXT_INPUT_PLUGIN_H_ |
|||
|
|||
#include <map> |
|||
#include <memory> |
|||
|
|||
#include "rapidjson/document.h" |
|||
#include "rapidjson/rapidjson.h" |
|||
#include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/binary_messenger.h" |
|||
#include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_channel.h" |
|||
//#include "shell/platform/common/cpp/text_input_model.h" |
|||
//#include "shell/platform/windows/keyboard_hook_handler.h" |
|||
#include "shell/platform/unity/windows/public/uiwidgets_windows.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// class Win32UIWidgetsWindow; |
|||
|
|||
// class TextInputPlugin : public KeyboardHookHandler { |
|||
class TextInputPlugin { |
|||
public: |
|||
explicit TextInputPlugin(uiwidgets::BinaryMessenger* messenger); |
|||
|
|||
virtual ~TextInputPlugin(); |
|||
|
|||
//void KeyboardHook(Win32UIWidgetsWindow* window, int key, int scancode, |
|||
// int action, int mods) override; |
|||
|
|||
//void CharHook(Win32UIWidgetsWindow* window, char32_t code_point) override; |
|||
|
|||
private: |
|||
//void SendStateUpdate(const TextInputModel& model); |
|||
|
|||
//void EnterPressed(TextInputModel* model); |
|||
|
|||
void HandleMethodCall( |
|||
const uiwidgets::MethodCall<rapidjson::Document>& method_call, |
|||
std::unique_ptr<uiwidgets::MethodResult<rapidjson::Document>> result); |
|||
|
|||
std::unique_ptr<uiwidgets::MethodChannel<rapidjson::Document>> channel_; |
|||
|
|||
//std::unique_ptr<TextInputModel> active_model_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "shell/platform/unity/windows/public/uiwidgets_windows.h"
|
|||
|
|||
#include <assert.h>
|
|||
|
|||
#include <algorithm>
|
|||
#include <chrono>
|
|||
#include <cstdlib>
|
|||
#include <filesystem>
|
|||
#include <iostream>
|
|||
#include <vector>
|
|||
|
|||
#include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/plugin_registrar.h"
|
|||
//#include "shell/platform/common/cpp/incoming_message_dispatcher.h"
|
|||
//#include "shell/platform/common/cpp/path_utils.h"
|
|||
#include "shell/platform/embedder/embedder.h"
|
|||
//#include "shell/platform/unity/windows/dpi_utils.h"
|
|||
//#include "shell/platform/unity/windows/key_event_handler.h"
|
|||
//#include "shell/platform/unity/windows/keyboard_hook_handler.h"
|
|||
//#include "shell/platform/unity/windows/platform_handler.h"
|
|||
#include "shell/platform/unity/windows/text_input_plugin.h"
|
|||
//#include "shell/platform/unity/windows/win32_uiwidgets_window.h"
|
|||
#include "shell/platform/unity/windows/win32_task_runner.h"
|
|||
#include "shell/platform/unity/windows/window_state.h"
|
|||
|
|||
//static_assert(UIWIDGETS_ENGINE_VERSION == 1, "");
|
|||
|
|||
// Spins up an instance of the UIWidgets Engine.
|
|||
//
|
|||
// This function launches the UIWidgets Engine in a background thread, supplying
|
|||
// the necessary callbacks for rendering within a win32window (if one is
|
|||
// provided).
|
|||
//
|
|||
// Returns the state object for the engine, or null on failure to start the
|
|||
// engine.
|
|||
//static std::unique_ptr<UIWidgetsDesktopEngineState> RunUIWidgetsEngine(
|
|||
// uiwidgets::Win32UIWidgetsWindow* window,
|
|||
// const UIWidgetsDesktopEngineProperties& engine_properties) {
|
|||
// auto state = std::make_unique<UIWidgetsDesktopEngineState>();
|
|||
//
|
|||
// // UIWidgetsProjectArgs is expecting a full argv, so when processing it for
|
|||
// // flags the first item is treated as the executable and ignored. Add a dummy
|
|||
// // value so that all provided arguments are used.
|
|||
// std::vector<const char*> argv = {"placeholder"};
|
|||
// if (engine_properties.switches_count > 0) {
|
|||
// argv.insert(argv.end(), &engine_properties.switches[0],
|
|||
// &engine_properties.switches[engine_properties.switches_count]);
|
|||
// }
|
|||
//
|
|||
// window->CreateRenderSurface();
|
|||
//
|
|||
// // Provide the necessary callbacks for rendering within a win32 child window.
|
|||
// UIWidgetsRendererConfig config = {};
|
|||
// config.type = kOpenGL;
|
|||
// config.open_gl.struct_size = sizeof(config.open_gl);
|
|||
// config.open_gl.make_current = [](void* user_data) -> bool {
|
|||
// auto host = static_cast<uiwidgets::Win32UIWidgetsWindow*>(user_data);
|
|||
// return host->MakeCurrent();
|
|||
// };
|
|||
// config.open_gl.clear_current = [](void* user_data) -> bool {
|
|||
// auto host = static_cast<uiwidgets::Win32UIWidgetsWindow*>(user_data);
|
|||
// return host->ClearContext();
|
|||
// };
|
|||
// config.open_gl.present = [](void* user_data) -> bool {
|
|||
// auto host = static_cast<uiwidgets::Win32UIWidgetsWindow*>(user_data);
|
|||
// return host->SwapBuffers();
|
|||
// };
|
|||
// config.open_gl.fbo_callback = [](void* user_data) -> uint32_t { return 0; };
|
|||
// config.open_gl.gl_proc_resolver = [](void* user_data,
|
|||
// const char* what) -> void* {
|
|||
// return reinterpret_cast<void*>(eglGetProcAddress(what));
|
|||
// };
|
|||
// config.open_gl.make_resource_current = [](void* user_data) -> bool {
|
|||
// auto host = static_cast<uiwidgets::Win32UIWidgetsWindow*>(user_data);
|
|||
// return host->MakeResourceCurrent();
|
|||
// };
|
|||
//
|
|||
// // Configure task runner interop.
|
|||
// auto state_ptr = state.get();
|
|||
// state->task_runner = std::make_unique<uiwidgets::Win32TaskRunner>(
|
|||
// GetCurrentThreadId(), [state_ptr](const auto* task) {
|
|||
// if (UIWidgetsEngineRunTask(state_ptr->engine, task) != kSuccess) {
|
|||
// std::cerr << "Could not post an engine task." << std::endl;
|
|||
// }
|
|||
// });
|
|||
// UIWidgetsTaskRunnerDescription platform_task_runner = {};
|
|||
// platform_task_runner.struct_size = sizeof(UIWidgetsTaskRunnerDescription);
|
|||
// platform_task_runner.user_data = state->task_runner.get();
|
|||
// platform_task_runner.runs_task_on_current_thread_callback =
|
|||
// [](void* user_data) -> bool {
|
|||
// return reinterpret_cast<uiwidgets::Win32TaskRunner*>(user_data)
|
|||
// ->RunsTasksOnCurrentThread();
|
|||
// };
|
|||
// platform_task_runner.post_task_callback = [](UIWidgetsTask task,
|
|||
// uint64_t target_time_nanos,
|
|||
// void* user_data) -> void {
|
|||
// reinterpret_cast<uiwidgets::Win32TaskRunner*>(user_data)->PostTask(
|
|||
// task, target_time_nanos);
|
|||
// };
|
|||
//
|
|||
// UIWidgetsCustomTaskRunners custom_task_runners = {};
|
|||
// custom_task_runners.struct_size = sizeof(UIWidgetsCustomTaskRunners);
|
|||
// custom_task_runners.platform_task_runner = &platform_task_runner;
|
|||
//
|
|||
// std::filesystem::path assets_path(engine_properties.assets_path);
|
|||
// std::filesystem::path icu_path(engine_properties.icu_data_path);
|
|||
// if (assets_path.is_relative() || icu_path.is_relative()) {
|
|||
// // Treat relative paths as relative to the directory of this executable.
|
|||
// std::filesystem::path executable_location =
|
|||
// uiwidgets::GetExecutableDirectory();
|
|||
// if (executable_location.empty()) {
|
|||
// std::cerr
|
|||
// << "Unable to find executable location to resolve resource paths."
|
|||
// << std::endl;
|
|||
// return nullptr;
|
|||
// }
|
|||
// assets_path = std::filesystem::path(executable_location) / assets_path;
|
|||
// icu_path = std::filesystem::path(executable_location) / icu_path;
|
|||
// }
|
|||
// std::string assets_path_string = assets_path.u8string();
|
|||
// std::string icu_path_string = icu_path.u8string();
|
|||
//
|
|||
// UIWidgetsProjectArgs args = {};
|
|||
// args.struct_size = sizeof(UIWidgetsProjectArgs);
|
|||
// args.assets_path = assets_path_string.c_str();
|
|||
// args.icu_data_path = icu_path_string.c_str();
|
|||
// args.command_line_argc = static_cast<int>(argv.size());
|
|||
// args.command_line_argv = &argv[0];
|
|||
// args.platform_message_callback =
|
|||
// [](const UIWidgetsPlatformMessage* engine_message,
|
|||
// void* user_data) -> void {
|
|||
// auto window = reinterpret_cast<uiwidgets::Win32UIWidgetsWindow*>(user_data);
|
|||
// return window->HandlePlatformMessage(engine_message);
|
|||
// };
|
|||
// args.custom_task_runners = &custom_task_runners;
|
|||
//
|
|||
// UIWIDGETS_API_SYMBOL(UIWidgetsEngine) engine = nullptr;
|
|||
// auto result =
|
|||
// UIWidgetsEngineRun(UIWIDGETS_ENGINE_VERSION, &config, &args, window, &engine);
|
|||
// if (result != kSuccess || engine == nullptr) {
|
|||
// std::cerr << "Failed to start UIWidgets engine: error " << result
|
|||
// << std::endl;
|
|||
// return nullptr;
|
|||
// }
|
|||
// state->engine = engine;
|
|||
// return state;
|
|||
//}
|
|||
//
|
|||
//UIWidgetsDesktopViewControllerRef UIWidgetsDesktopCreateViewController(
|
|||
// int width,
|
|||
// int height,
|
|||
// const UIWidgetsDesktopEngineProperties& engine_properties) {
|
|||
// UIWidgetsDesktopViewControllerRef state =
|
|||
// uiwidgets::Win32UIWidgetsWindow::CreateWin32UIWidgetsWindow(width, height);
|
|||
//
|
|||
// auto engine_state = RunUIWidgetsEngine(state->view.get(), engine_properties);
|
|||
//
|
|||
// if (!engine_state) {
|
|||
// return nullptr;
|
|||
// }
|
|||
// state->view->SetState(engine_state->engine);
|
|||
// state->engine_state = std::move(engine_state);
|
|||
// return state;
|
|||
//}
|
|||
//
|
|||
//UIWidgetsDesktopViewControllerRef UIWidgetsDesktopCreateViewControllerLegacy(
|
|||
// int initial_width,
|
|||
// int initial_height,
|
|||
// const char* assets_path,
|
|||
// const char* icu_data_path,
|
|||
// const char** arguments,
|
|||
// size_t argument_count) {
|
|||
// std::filesystem::path assets_path_fs = std::filesystem::u8path(assets_path);
|
|||
// std::filesystem::path icu_data_path_fs =
|
|||
// std::filesystem::u8path(icu_data_path);
|
|||
// UIWidgetsDesktopEngineProperties engine_properties = {};
|
|||
// engine_properties.assets_path = assets_path_fs.c_str();
|
|||
// engine_properties.icu_data_path = icu_data_path_fs.c_str();
|
|||
// engine_properties.switches = arguments;
|
|||
// engine_properties.switches_count = argument_count;
|
|||
//
|
|||
// return UIWidgetsDesktopCreateViewController(initial_width, initial_height,
|
|||
// engine_properties);
|
|||
//}
|
|||
//
|
|||
//uint64_t UIWidgetsDesktopProcessMessages(
|
|||
// UIWidgetsDesktopViewControllerRef controller) {
|
|||
// return controller->engine_state->task_runner->ProcessTasks().count();
|
|||
//}
|
|||
//
|
|||
//void UIWidgetsDesktopDestroyViewController(
|
|||
// UIWidgetsDesktopViewControllerRef controller) {
|
|||
// UIWidgetsEngineShutdown(controller->engine_state->engine);
|
|||
// delete controller;
|
|||
//}
|
|||
//
|
|||
//UIWidgetsDesktopPluginRegistrarRef UIWidgetsDesktopGetPluginRegistrar(
|
|||
// UIWidgetsDesktopViewControllerRef controller,
|
|||
// const char* plugin_name) {
|
|||
// // Currently, one registrar acts as the registrar for all plugins, so the
|
|||
// // name is ignored. It is part of the API to reduce churn in the future when
|
|||
// // aligning more closely with the UIWidgets registrar system.
|
|||
//
|
|||
// return controller->view->GetRegistrar();
|
|||
//}
|
|||
//
|
|||
//UIWidgetsDesktopViewRef UIWidgetsDesktopGetView(
|
|||
// UIWidgetsDesktopViewControllerRef controller) {
|
|||
// return controller->view_wrapper.get();
|
|||
//}
|
|||
//
|
|||
//HWND UIWidgetsDesktopViewGetHWND(UIWidgetsDesktopViewRef view) {
|
|||
// return view->window->GetWindowHandle();
|
|||
//}
|
|||
//
|
|||
//UINT UIWidgetsDesktopGetDpiForHWND(HWND hwnd) {
|
|||
// return uiwidgets::GetDpiForHWND(hwnd);
|
|||
//}
|
|||
//
|
|||
//UINT UIWidgetsDesktopGetDpiForMonitor(HMONITOR monitor) {
|
|||
// return uiwidgets::GetDpiForMonitor(monitor);
|
|||
//}
|
|||
//
|
|||
//UIWidgetsDesktopEngineRef UIWidgetsDesktopRunEngine(
|
|||
// const UIWidgetsDesktopEngineProperties& engine_properties) {
|
|||
// auto engine = RunUIWidgetsEngine(nullptr, engine_properties);
|
|||
// return engine.release();
|
|||
//}
|
|||
//
|
|||
//bool UIWidgetsDesktopShutDownEngine(UIWidgetsDesktopEngineRef engine_ref) {
|
|||
// std::cout << "Shutting down uiwidgets engine process." << std::endl;
|
|||
// auto result = UIWidgetsEngineShutdown(engine_ref->engine);
|
|||
// delete engine_ref;
|
|||
// return (result == kSuccess);
|
|||
//}
|
|||
|
|||
void UIWidgetsDesktopRegistrarEnableInputBlocking( |
|||
UIWidgetsDesktopPluginRegistrarRef registrar, |
|||
const char* channel) { |
|||
registrar->messenger->dispatcher->EnableInputBlockingForChannel(channel); |
|||
} |
|||
|
|||
UIWidgetsDesktopMessengerRef UIWidgetsDesktopRegistrarGetMessenger( |
|||
UIWidgetsDesktopPluginRegistrarRef registrar) { |
|||
return registrar->messenger.get(); |
|||
} |
|||
|
|||
//UIWidgetsDesktopViewRef UIWidgetsDesktopRegistrarGetView(
|
|||
// UIWidgetsDesktopPluginRegistrarRef registrar) {
|
|||
// return registrar->window;
|
|||
//}
|
|||
//
|
|||
bool UIWidgetsDesktopMessengerSendWithReply(UIWidgetsDesktopMessengerRef messenger, |
|||
const char* channel, |
|||
const uint8_t* message, |
|||
const size_t message_size, |
|||
const UIWidgetsDesktopBinaryReply reply, |
|||
void* user_data) { |
|||
UIWidgetsPlatformMessageResponseHandle* response_handle = nullptr; |
|||
if (reply != nullptr && user_data != nullptr) { |
|||
UIWidgetsEngineResult result = UIWidgetsPlatformMessageCreateResponseHandle( |
|||
messenger->engine, reply, user_data, &response_handle); |
|||
if (result != kSuccess) { |
|||
std::cout << "Failed to create response handle\n"; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
UIWidgetsPlatformMessage platform_message = { |
|||
sizeof(UIWidgetsPlatformMessage), |
|||
channel, |
|||
message, |
|||
message_size, |
|||
response_handle, |
|||
}; |
|||
|
|||
UIWidgetsEngineResult message_result = |
|||
UIWidgetsEngineSendPlatformMessage(messenger->engine, &platform_message); |
|||
|
|||
if (response_handle != nullptr) { |
|||
UIWidgetsPlatformMessageReleaseResponseHandle(messenger->engine, |
|||
response_handle); |
|||
} |
|||
|
|||
return message_result == kSuccess; |
|||
} |
|||
|
|||
bool UIWidgetsDesktopMessengerSend(UIWidgetsDesktopMessengerRef messenger, |
|||
const char* channel, |
|||
const uint8_t* message, |
|||
const size_t message_size) { |
|||
return UIWidgetsDesktopMessengerSendWithReply(messenger, channel, message, |
|||
message_size, nullptr, nullptr); |
|||
} |
|||
|
|||
void UIWidgetsDesktopMessengerSendResponse( |
|||
UIWidgetsDesktopMessengerRef messenger, |
|||
const UIWidgetsDesktopMessageResponseHandle* handle, |
|||
const uint8_t* data, |
|||
size_t data_length) { |
|||
UIWidgetsEngineSendPlatformMessageResponse(messenger->engine, handle, data, |
|||
data_length); |
|||
} |
|||
|
|||
void UIWidgetsDesktopMessengerSetCallback(UIWidgetsDesktopMessengerRef messenger, |
|||
const char* channel, |
|||
UIWidgetsDesktopMessageCallback callback, |
|||
void* user_data) { |
|||
messenger->dispatcher->SetMessageCallback(channel, callback, user_data); |
|||
} |
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_WINDOWS_UIWIDGETS_WINDOW_STATE_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_WINDOWS_UIWIDGETS_WINDOW_STATE_H_ |
|||
|
|||
#include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/plugin_registrar.h" |
|||
#include "shell/platform/common/cpp/incoming_message_dispatcher.h" |
|||
#include "shell/platform/embedder/embedder.h" |
|||
//#include "shell/platform/unity/windows/key_event_handler.h" |
|||
//#include "shell/platform/unity/windows/keyboard_hook_handler.h" |
|||
//#include "shell/platform/unity/windows/platform_handler.h" |
|||
#include "shell/platform/unity/windows/text_input_plugin.h" |
|||
#include "shell/platform/unity/windows/win32_task_runner.h" |
|||
|
|||
namespace uiwidgets { |
|||
struct Win32UIWidgetsWindow; |
|||
} |
|||
|
|||
// Struct for storing state within an instance of the windows native (HWND or |
|||
// CoreWindow) Window. |
|||
struct UIWidgetsDesktopViewControllerState { |
|||
// The win32 window that owns this state object. |
|||
std::unique_ptr<uiwidgets::Win32UIWidgetsWindow> view; |
|||
|
|||
// The state associate with the engine backing the view. |
|||
std::unique_ptr<UIWidgetsDesktopEngineState> engine_state; |
|||
|
|||
// The window handle given to API clients. |
|||
std::unique_ptr<UIWidgetsDesktopView> view_wrapper; |
|||
}; |
|||
|
|||
// Opaque reference for the native windows itself. This is separate from the |
|||
// controller so that it can be provided to plugins without giving them access |
|||
// to all of the controller-based functionality. |
|||
struct UIWidgetsDesktopView { |
|||
// The window that (indirectly) owns this state object. |
|||
uiwidgets::Win32UIWidgetsWindow* window; |
|||
}; |
|||
|
|||
// Struct for storing state of a UIWidgets engine instance. |
|||
struct UIWidgetsDesktopEngineState { |
|||
// The handle to the UIWidgets engine instance. |
|||
UIWIDGETS_API_SYMBOL(UIWidgetsEngine) engine; |
|||
|
|||
// Task runner for tasks posted from the engine. |
|||
std::unique_ptr<uiwidgets::Win32TaskRunner> task_runner; |
|||
}; |
|||
|
|||
// State associated with the plugin registrar. |
|||
struct UIWidgetsDesktopPluginRegistrar { |
|||
// The plugin messenger handle given to API clients. |
|||
std::unique_ptr<UIWidgetsDesktopMessenger> messenger; |
|||
|
|||
// The handle for the window associated with this registrar. |
|||
UIWidgetsDesktopView* window; |
|||
}; |
|||
|
|||
// State associated with the messenger used to communicate with the engine. |
|||
struct UIWidgetsDesktopMessenger { |
|||
// The UIWidgets engine this messenger sends outgoing messages to. |
|||
UIWIDGETS_API_SYMBOL(UIWidgetsEngine) engine; |
|||
|
|||
// The message dispatcher for handling incoming messages. |
|||
uiwidgets::IncomingMessageDispatcher* dispatcher; |
|||
}; |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_WINDOWS_UIWIDGETS_WINDOW_STATE_H_ |
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/basic_message_channel.h"
|
|||
|
|||
// #include <memory>
|
|||
// #include <string>
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/binary_messenger.h"
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_message_codec.h"
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// namespace {
|
|||
|
|||
// class TestBinaryMessenger : public BinaryMessenger {
|
|||
// public:
|
|||
// void Send(const std::string& channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size) const override {}
|
|||
|
|||
// void Send(const std::string& channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size,
|
|||
// BinaryReply reply) const override {}
|
|||
|
|||
// void SetMessageHandler(const std::string& channel,
|
|||
// BinaryMessageHandler handler) override {
|
|||
// last_message_handler_channel_ = channel;
|
|||
// last_message_handler_ = handler;
|
|||
// }
|
|||
|
|||
// std::string last_message_handler_channel() {
|
|||
// return last_message_handler_channel_;
|
|||
// }
|
|||
|
|||
// BinaryMessageHandler last_message_handler() { return last_message_handler_; }
|
|||
|
|||
// private:
|
|||
// std::string last_message_handler_channel_;
|
|||
// BinaryMessageHandler last_message_handler_;
|
|||
// };
|
|||
|
|||
// } // namespace
|
|||
|
|||
// // Tests that SetMessageHandler sets a handler that correctly interacts with
|
|||
// // the binary messenger.
|
|||
// TEST(BasicMessageChannelTest, Registration) {
|
|||
// TestBinaryMessenger messenger;
|
|||
// const std::string channel_name("some_channel");
|
|||
// const StandardMessageCodec& codec = StandardMessageCodec::GetInstance();
|
|||
// BasicMessageChannel channel(&messenger, channel_name, &codec);
|
|||
|
|||
// bool callback_called = false;
|
|||
// const std::string message_value("hello");
|
|||
// channel.SetMessageHandler(
|
|||
// [&callback_called, message_value](const auto& message, auto reply) {
|
|||
// callback_called = true;
|
|||
// // Ensure that the wrapper recieved a correctly decoded message and a
|
|||
// // reply.
|
|||
// EXPECT_EQ(message.StringValue(), message_value);
|
|||
// EXPECT_NE(reply, nullptr);
|
|||
// });
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_NE(messenger.last_message_handler(), nullptr);
|
|||
// // Send a test message to trigger the handler test assertions.
|
|||
// auto message = codec.EncodeMessage(EncodableValue(message_value));
|
|||
|
|||
// messenger.last_message_handler()(
|
|||
// message->data(), message->size(),
|
|||
// [](const uint8_t* reply, const size_t reply_size) {});
|
|||
// EXPECT_EQ(callback_called, true);
|
|||
// }
|
|||
|
|||
// // Tests that SetMessageHandler with a null handler unregisters the handler.
|
|||
// TEST(BasicMessageChannelTest, Unregistration) {
|
|||
// TestBinaryMessenger messenger;
|
|||
// const std::string channel_name("some_channel");
|
|||
// BasicMessageChannel channel(&messenger, channel_name,
|
|||
// &uiwidgets::StandardMessageCodec::GetInstance());
|
|||
|
|||
// channel.SetMessageHandler([](const auto& message, auto reply) {});
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_NE(messenger.last_message_handler(), nullptr);
|
|||
|
|||
// channel.SetMessageHandler(nullptr);
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_EQ(messenger.last_message_handler(), nullptr);
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ |
|||
|
|||
// Utility classes for interacting with a buffer of bytes as a stream, for use |
|||
// in message channel codecs. |
|||
|
|||
#include <cstdint> |
|||
#include <cstring> |
|||
#include <iostream> |
|||
#include <vector> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// Wraps an array of bytes with utility methods for treating it as a readable |
|||
// stream. |
|||
class ByteBufferStreamReader { |
|||
public: |
|||
// Createa a reader reading from |bytes|, which must have a length of |size|. |
|||
// |bytes| must remain valid for the lifetime of this object. |
|||
explicit ByteBufferStreamReader(const uint8_t* bytes, size_t size) |
|||
: bytes_(bytes), size_(size) {} |
|||
|
|||
// Reads and returns the next byte from the stream. |
|||
uint8_t ReadByte() { |
|||
if (location_ >= size_) { |
|||
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl; |
|||
return 0; |
|||
} |
|||
return bytes_[location_++]; |
|||
} |
|||
|
|||
// Reads the next |length| bytes from the stream into |buffer|. The caller |
|||
// is responsible for ensuring that |buffer| is large enough. |
|||
void ReadBytes(uint8_t* buffer, size_t length) { |
|||
if (location_ + length > size_) { |
|||
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl; |
|||
return; |
|||
} |
|||
std::memcpy(buffer, &bytes_[location_], length); |
|||
location_ += length; |
|||
} |
|||
|
|||
// Advances the read cursor to the next multiple of |alignment| relative to |
|||
// the start of the wrapped byte buffer, unless it is already aligned. |
|||
void ReadAlignment(uint8_t alignment) { |
|||
uint8_t mod = location_ % alignment; |
|||
if (mod) { |
|||
location_ += alignment - mod; |
|||
} |
|||
} |
|||
|
|||
private: |
|||
// The buffer to read from. |
|||
const uint8_t* bytes_; |
|||
// The total size of the buffer. |
|||
size_t size_; |
|||
// The current read location. |
|||
size_t location_ = 0; |
|||
}; |
|||
|
|||
// Wraps an array of bytes with utility methods for treating it as a writable |
|||
// stream. |
|||
class ByteBufferStreamWriter { |
|||
public: |
|||
// Createa a writter that writes into |buffer|. |
|||
// |buffer| must remain valid for the lifetime of this object. |
|||
explicit ByteBufferStreamWriter(std::vector<uint8_t>* buffer) |
|||
: bytes_(buffer) { |
|||
assert(buffer); |
|||
} |
|||
|
|||
// Writes |byte| to the wrapped buffer. |
|||
void WriteByte(uint8_t byte) { bytes_->push_back(byte); } |
|||
|
|||
// Writes the next |length| bytes from |bytes| into the wrapped buffer. |
|||
// The caller is responsible for ensuring that |buffer| is large enough. |
|||
void WriteBytes(const uint8_t* bytes, size_t length) { |
|||
assert(length > 0); |
|||
bytes_->insert(bytes_->end(), bytes, bytes + length); |
|||
} |
|||
|
|||
// Writes 0s until the next multiple of |alignment| relative to |
|||
// the start of the wrapped byte buffer, unless the write positition is |
|||
// already aligned. |
|||
void WriteAlignment(uint8_t alignment) { |
|||
uint8_t mod = bytes_->size() % alignment; |
|||
if (mod) { |
|||
for (int i = 0; i < alignment - mod; ++i) { |
|||
WriteByte(0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private: |
|||
// The buffer to write to. |
|||
std::vector<uint8_t>* bytes_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ |
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/encodable_value.h"
|
|||
|
|||
// #include <limits>
|
|||
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// // Verifies that value.type() is |type|, and that of all the Is* methods, only
|
|||
// // the one that matches the type is true.
|
|||
// void VerifyType(EncodableValue& value,
|
|||
// EncodableValue::EncodableValue::Type type) {
|
|||
// EXPECT_EQ(value.type(), type);
|
|||
|
|||
// EXPECT_EQ(value.IsNull(), type == EncodableValue::Type::kNull);
|
|||
// EXPECT_EQ(value.IsBool(), type == EncodableValue::Type::kBool);
|
|||
// EXPECT_EQ(value.IsInt(), type == EncodableValue::Type::kInt);
|
|||
// EXPECT_EQ(value.IsLong(), type == EncodableValue::Type::kLong);
|
|||
// EXPECT_EQ(value.IsDouble(), type == EncodableValue::Type::kDouble);
|
|||
// EXPECT_EQ(value.IsString(), type == EncodableValue::Type::kString);
|
|||
// EXPECT_EQ(value.IsByteList(), type == EncodableValue::Type::kByteList);
|
|||
// EXPECT_EQ(value.IsIntList(), type == EncodableValue::Type::kIntList);
|
|||
// EXPECT_EQ(value.IsLongList(), type == EncodableValue::Type::kLongList);
|
|||
// EXPECT_EQ(value.IsDoubleList(), type == EncodableValue::Type::kDoubleList);
|
|||
// EXPECT_EQ(value.IsList(), type == EncodableValue::Type::kList);
|
|||
// EXPECT_EQ(value.IsMap(), type == EncodableValue::Type::kMap);
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Null) {
|
|||
// EncodableValue value;
|
|||
// VerifyType(value, EncodableValue::Type::kNull);
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Bool) {
|
|||
// EncodableValue value(false);
|
|||
// VerifyType(value, EncodableValue::Type::kBool);
|
|||
|
|||
// EXPECT_FALSE(value.BoolValue());
|
|||
// value = true;
|
|||
// EXPECT_TRUE(value.BoolValue());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Int) {
|
|||
// EncodableValue value(42);
|
|||
// VerifyType(value, EncodableValue::Type::kInt);
|
|||
|
|||
// EXPECT_EQ(value.IntValue(), 42);
|
|||
// value = std::numeric_limits<int32_t>::max();
|
|||
// EXPECT_EQ(value.IntValue(), std::numeric_limits<int32_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, LongValueFromInt) {
|
|||
// EncodableValue value(std::numeric_limits<int32_t>::max());
|
|||
// EXPECT_EQ(value.LongValue(), std::numeric_limits<int32_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Long) {
|
|||
// EncodableValue value(INT64_C(42));
|
|||
// VerifyType(value, EncodableValue::Type::kLong);
|
|||
|
|||
// EXPECT_EQ(value.LongValue(), 42);
|
|||
// value = std::numeric_limits<int64_t>::max();
|
|||
// EXPECT_EQ(value.LongValue(), std::numeric_limits<int64_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Double) {
|
|||
// EncodableValue value(3.14);
|
|||
// VerifyType(value, EncodableValue::Type::kDouble);
|
|||
|
|||
// EXPECT_EQ(value.DoubleValue(), 3.14);
|
|||
// value = std::numeric_limits<double>::max();
|
|||
// EXPECT_EQ(value.DoubleValue(), std::numeric_limits<double>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, String) {
|
|||
// std::string hello("Hello, world!");
|
|||
// EncodableValue value(hello);
|
|||
// VerifyType(value, EncodableValue::Type::kString);
|
|||
|
|||
// EXPECT_EQ(value.StringValue(), hello);
|
|||
// value = "Goodbye";
|
|||
// EXPECT_EQ(value.StringValue(), "Goodbye");
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, UInt8List) {
|
|||
// std::vector<uint8_t> data = {0, 2};
|
|||
// EncodableValue value(data);
|
|||
// VerifyType(value, EncodableValue::Type::kByteList);
|
|||
|
|||
// std::vector<uint8_t>& list_value = value.ByteListValue();
|
|||
// list_value.push_back(std::numeric_limits<uint8_t>::max());
|
|||
// EXPECT_EQ(list_value[0], 0);
|
|||
// EXPECT_EQ(list_value[1], 2);
|
|||
|
|||
// ASSERT_EQ(list_value.size(), 3u);
|
|||
// EXPECT_EQ(data.size(), 2u);
|
|||
// EXPECT_EQ(list_value[2], std::numeric_limits<uint8_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Int32List) {
|
|||
// std::vector<int32_t> data = {-10, 2};
|
|||
// EncodableValue value(data);
|
|||
// VerifyType(value, EncodableValue::Type::kIntList);
|
|||
|
|||
// std::vector<int32_t>& list_value = value.IntListValue();
|
|||
// list_value.push_back(std::numeric_limits<int32_t>::max());
|
|||
// EXPECT_EQ(list_value[0], -10);
|
|||
// EXPECT_EQ(list_value[1], 2);
|
|||
|
|||
// ASSERT_EQ(list_value.size(), 3u);
|
|||
// EXPECT_EQ(data.size(), 2u);
|
|||
// EXPECT_EQ(list_value[2], std::numeric_limits<int32_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Int64List) {
|
|||
// std::vector<int64_t> data = {-10, 2};
|
|||
// EncodableValue value(data);
|
|||
// VerifyType(value, EncodableValue::Type::kLongList);
|
|||
|
|||
// std::vector<int64_t>& list_value = value.LongListValue();
|
|||
// list_value.push_back(std::numeric_limits<int64_t>::max());
|
|||
// EXPECT_EQ(list_value[0], -10);
|
|||
// EXPECT_EQ(list_value[1], 2);
|
|||
|
|||
// ASSERT_EQ(list_value.size(), 3u);
|
|||
// EXPECT_EQ(data.size(), 2u);
|
|||
// EXPECT_EQ(list_value[2], std::numeric_limits<int64_t>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, DoubleList) {
|
|||
// std::vector<double> data = {-10.0, 2.0};
|
|||
// EncodableValue value(data);
|
|||
// VerifyType(value, EncodableValue::Type::kDoubleList);
|
|||
|
|||
// std::vector<double>& list_value = value.DoubleListValue();
|
|||
// list_value.push_back(std::numeric_limits<double>::max());
|
|||
// EXPECT_EQ(list_value[0], -10.0);
|
|||
// EXPECT_EQ(list_value[1], 2.0);
|
|||
|
|||
// ASSERT_EQ(list_value.size(), 3u);
|
|||
// EXPECT_EQ(data.size(), 2u);
|
|||
// EXPECT_EQ(list_value[2], std::numeric_limits<double>::max());
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, List) {
|
|||
// EncodableList encodables = {
|
|||
// EncodableValue(1),
|
|||
// EncodableValue(2.0),
|
|||
// EncodableValue("Three"),
|
|||
// };
|
|||
// EncodableValue value(encodables);
|
|||
// VerifyType(value, EncodableValue::Type::kList);
|
|||
|
|||
// EncodableList& list_value = value.ListValue();
|
|||
// EXPECT_EQ(list_value[0].IntValue(), 1);
|
|||
// EXPECT_EQ(list_value[1].DoubleValue(), 2.0);
|
|||
// EXPECT_EQ(list_value[2].StringValue(), "Three");
|
|||
|
|||
// // Ensure that it's a modifiable copy of the original array.
|
|||
// list_value.push_back(EncodableValue(true));
|
|||
// ASSERT_EQ(list_value.size(), 4u);
|
|||
// EXPECT_EQ(encodables.size(), 3u);
|
|||
// EXPECT_EQ(value.ListValue()[3].BoolValue(), true);
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, Map) {
|
|||
// EncodableMap encodables = {
|
|||
// {EncodableValue(), EncodableValue(std::vector<int32_t>{1, 2, 3})},
|
|||
// {EncodableValue(1), EncodableValue(INT64_C(10000))},
|
|||
// {EncodableValue("two"), EncodableValue(7)},
|
|||
// };
|
|||
// EncodableValue value(encodables);
|
|||
// VerifyType(value, EncodableValue::Type::kMap);
|
|||
|
|||
// EncodableMap& map_value = value.MapValue();
|
|||
// EXPECT_EQ(map_value[EncodableValue()].IsIntList(), true);
|
|||
// EXPECT_EQ(map_value[EncodableValue(1)].LongValue(), INT64_C(10000));
|
|||
// EXPECT_EQ(map_value[EncodableValue("two")].IntValue(), 7);
|
|||
|
|||
// // Ensure that it's a modifiable copy of the original map.
|
|||
// map_value[EncodableValue(true)] = EncodableValue(false);
|
|||
// ASSERT_EQ(map_value.size(), 4u);
|
|||
// EXPECT_EQ(encodables.size(), 3u);
|
|||
// EXPECT_EQ(map_value[EncodableValue(true)].BoolValue(), false);
|
|||
// }
|
|||
|
|||
// TEST(EncodableValueTest, EmptyTypeConstructor) {
|
|||
// EXPECT_TRUE(EncodableValue(EncodableValue::Type::kNull).IsNull());
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kBool).BoolValue(), false);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kInt).IntValue(), 0);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kLong).LongValue(),
|
|||
// INT64_C(0));
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kDouble).DoubleValue(), 0.0);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kString).StringValue().size(),
|
|||
// 0u);
|
|||
// EXPECT_EQ(
|
|||
// EncodableValue(EncodableValue::Type::kByteList).ByteListValue().size(),
|
|||
// 0u);
|
|||
// EXPECT_EQ(
|
|||
// EncodableValue(EncodableValue::Type::kIntList).IntListValue().size(), 0u);
|
|||
// EXPECT_EQ(
|
|||
// EncodableValue(EncodableValue::Type::kLongList).LongListValue().size(),
|
|||
// 0u);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kDoubleList)
|
|||
// .DoubleListValue()
|
|||
// .size(),
|
|||
// 0u);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kList).ListValue().size(), 0u);
|
|||
// EXPECT_EQ(EncodableValue(EncodableValue::Type::kMap).MapValue().size(), 0u);
|
|||
// }
|
|||
|
|||
// // Tests that the < operator meets the requirements of using EncodableValue as
|
|||
// // a map key.
|
|||
// TEST(EncodableValueTest, Comparison) {
|
|||
// EncodableList values = {
|
|||
// // Null
|
|||
// EncodableValue(),
|
|||
// // Bool
|
|||
// EncodableValue(true),
|
|||
// EncodableValue(false),
|
|||
// // Int
|
|||
// EncodableValue(-7),
|
|||
// EncodableValue(0),
|
|||
// EncodableValue(100),
|
|||
// // Long
|
|||
// EncodableValue(INT64_C(-7)),
|
|||
// EncodableValue(INT64_C(0)),
|
|||
// EncodableValue(INT64_C(100)),
|
|||
// // Double
|
|||
// EncodableValue(-7.0),
|
|||
// EncodableValue(0.0),
|
|||
// EncodableValue(100.0),
|
|||
// // String
|
|||
// EncodableValue("one"),
|
|||
// EncodableValue("two"),
|
|||
// // ByteList
|
|||
// EncodableValue(std::vector<uint8_t>{0, 1}),
|
|||
// EncodableValue(std::vector<uint8_t>{0, 10}),
|
|||
// // IntList
|
|||
// EncodableValue(std::vector<int32_t>{0, 1}),
|
|||
// EncodableValue(std::vector<int32_t>{0, 100}),
|
|||
// // LongList
|
|||
// EncodableValue(std::vector<int64_t>{0, INT64_C(1)}),
|
|||
// EncodableValue(std::vector<int64_t>{0, INT64_C(100)}),
|
|||
// // DoubleList
|
|||
// EncodableValue(std::vector<int64_t>{0, INT64_C(1)}),
|
|||
// EncodableValue(std::vector<int64_t>{0, INT64_C(100)}),
|
|||
// // List
|
|||
// EncodableValue(EncodableList{EncodableValue(), EncodableValue(true)}),
|
|||
// EncodableValue(EncodableList{EncodableValue(), EncodableValue(1.0)}),
|
|||
// // Map
|
|||
// EncodableValue(EncodableMap{{EncodableValue(), EncodableValue(true)},
|
|||
// {EncodableValue(7), EncodableValue(7.0)}}),
|
|||
// EncodableValue(
|
|||
// EncodableMap{{EncodableValue(), EncodableValue(1.0)},
|
|||
// {EncodableValue("key"), EncodableValue("value")}}),
|
|||
// };
|
|||
|
|||
// for (size_t i = 0; i < values.size(); ++i) {
|
|||
// const auto& a = values[i];
|
|||
// for (size_t j = 0; j < values.size(); ++j) {
|
|||
// const auto& b = values[j];
|
|||
// if (i == j) {
|
|||
// // Identical objects should always be equal.
|
|||
// EXPECT_FALSE(a < b);
|
|||
// EXPECT_FALSE(b < a);
|
|||
// } else {
|
|||
// // All other comparisons should be consistent, but the direction doesn't
|
|||
// // matter.
|
|||
// EXPECT_NE(a < b, b < a);
|
|||
// }
|
|||
// }
|
|||
|
|||
// // Different non-collection objects with the same value should be equal;
|
|||
// // different collections should always be unequal regardless of contents.
|
|||
// bool is_collection = a.IsByteList() || a.IsIntList() || a.IsLongList() ||
|
|||
// a.IsDoubleList() || a.IsList() || a.IsMap();
|
|||
// EncodableValue copy(a);
|
|||
// bool is_equal = !(a < copy || copy < a);
|
|||
// EXPECT_EQ(is_equal, !is_collection);
|
|||
// }
|
|||
// }
|
|||
|
|||
// // Tests that structures are deep-copied.
|
|||
// TEST(EncodableValueTest, DeepCopy) {
|
|||
// EncodableList encodables = {
|
|||
// EncodableValue(EncodableMap{
|
|||
// {EncodableValue(), EncodableValue(std::vector<int32_t>{1, 2, 3})},
|
|||
// {EncodableValue(1), EncodableValue(INT64_C(0000))},
|
|||
// {EncodableValue("two"), EncodableValue(7)},
|
|||
// }),
|
|||
// EncodableValue(EncodableList{
|
|||
// EncodableValue(),
|
|||
// EncodableValue(),
|
|||
// EncodableValue(
|
|||
// EncodableMap{{EncodableValue("a"), EncodableValue("b")}}),
|
|||
// }),
|
|||
// };
|
|||
|
|||
// EncodableValue value(encodables);
|
|||
// ASSERT_TRUE(value.IsList());
|
|||
|
|||
// // Spot-check innermost collection values.
|
|||
// EXPECT_EQ(value.ListValue()[0].MapValue()[EncodableValue("two")].IntValue(),
|
|||
// 7);
|
|||
// EXPECT_EQ(value.ListValue()[1]
|
|||
// .ListValue()[2]
|
|||
// .MapValue()[EncodableValue("a")]
|
|||
// .StringValue(),
|
|||
// "b");
|
|||
|
|||
// // Modify those values in the original structure.
|
|||
// encodables[0].MapValue()[EncodableValue("two")] = EncodableValue();
|
|||
// encodables[1].ListValue()[2].MapValue()[EncodableValue("a")] = 99;
|
|||
|
|||
// // Re-check innermost collection values to ensure that they haven't changed.
|
|||
// EXPECT_EQ(value.ListValue()[0].MapValue()[EncodableValue("two")].IntValue(),
|
|||
// 7);
|
|||
// EXPECT_EQ(value.ListValue()[1]
|
|||
// .ListValue()[2]
|
|||
// .MapValue()[EncodableValue("a")]
|
|||
// .StringValue(),
|
|||
// "b");
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "include/uiwidgets/engine_method_result.h"
|
|||
|
|||
#include <assert.h>
|
|||
#include <iostream>
|
|||
|
|||
namespace uiwidgets { |
|||
namespace internal { |
|||
|
|||
ReplyManager::ReplyManager(BinaryReply reply_handler) |
|||
: reply_handler_(std::move(reply_handler)) { |
|||
assert(reply_handler_); |
|||
} |
|||
|
|||
ReplyManager::~ReplyManager() { |
|||
if (reply_handler_) { |
|||
// Warn, rather than send a not-implemented response, since the engine may
|
|||
// no longer be valid at this point.
|
|||
std::cerr |
|||
<< "Warning: Failed to respond to a message. This is a memory leak." |
|||
<< std::endl; |
|||
} |
|||
} |
|||
|
|||
void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) { |
|||
if (!reply_handler_) { |
|||
std::cerr |
|||
<< "Error: Only one of Success, Error, or NotImplemented can be " |
|||
"called," |
|||
<< " and it can be called exactly once. Ignoring duplicate result." |
|||
<< std::endl; |
|||
return; |
|||
} |
|||
|
|||
const uint8_t* message = data && !data->empty() ? data->data() : nullptr; |
|||
size_t message_size = data ? data->size() : 0; |
|||
reply_handler_(message, message_size); |
|||
reply_handler_ = nullptr; |
|||
} |
|||
|
|||
} // namespace internal
|
|||
} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_BASIC_MESSAGE_CHANNEL_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_BASIC_MESSAGE_CHANNEL_H_ |
|||
|
|||
#include <iostream> |
|||
#include <string> |
|||
|
|||
#include "binary_messenger.h" |
|||
#include "message_codec.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// A message reply callback. |
|||
// |
|||
// Used for submitting a reply back to a UIWidgets message sender. |
|||
template <typename T> |
|||
using MessageReply = std::function<void(const T& reply)>; |
|||
|
|||
// A handler for receiving a message from the UIWidgets engine. |
|||
// |
|||
// Implementations must asynchronously call reply exactly once with the reply |
|||
// to the message. |
|||
template <typename T> |
|||
using MessageHandler = |
|||
std::function<void(const T& message, const MessageReply<T>& reply)>; |
|||
|
|||
// A channel for communicating with the UIWidgets engine by sending asynchronous |
|||
// messages. |
|||
template <typename T> |
|||
class BasicMessageChannel { |
|||
public: |
|||
// Creates an instance that sends and receives method calls on the channel |
|||
// named |name|, encoded with |codec| and dispatched via |messenger|. |
|||
BasicMessageChannel(BinaryMessenger* messenger, |
|||
const std::string& name, |
|||
const MessageCodec<T>* codec) |
|||
: messenger_(messenger), name_(name), codec_(codec) {} |
|||
|
|||
~BasicMessageChannel() = default; |
|||
|
|||
// Prevent copying. |
|||
BasicMessageChannel(BasicMessageChannel const&) = delete; |
|||
BasicMessageChannel& operator=(BasicMessageChannel const&) = delete; |
|||
|
|||
// Sends a message to the UIWidgets engine on this channel. |
|||
void Send(const T& message) { |
|||
std::unique_ptr<std::vector<uint8_t>> raw_message = |
|||
codec_->EncodeMessage(message); |
|||
messenger_->Send(name_, raw_message->data(), raw_message->size()); |
|||
} |
|||
|
|||
// Sends a message to the UIWidgets engine on this channel expecting a reply. |
|||
void Send(const T& message, BinaryReply reply) { |
|||
std::unique_ptr<std::vector<uint8_t>> raw_message = |
|||
codec_->EncodeMessage(message); |
|||
messenger_->Send(name_, raw_message->data(), raw_message->size(), reply); |
|||
} |
|||
|
|||
// Registers a handler that should be called any time a message is |
|||
// received on this channel. A null handler will remove any previous handler. |
|||
// |
|||
// Note that the BasicMessageChannel does not own the handler, and will not |
|||
// unregister it on destruction, so the caller is responsible for |
|||
// unregistering explicitly if it should no longer be called. |
|||
void SetMessageHandler(const MessageHandler<T>& handler) const { |
|||
if (!handler) { |
|||
messenger_->SetMessageHandler(name_, nullptr); |
|||
return; |
|||
} |
|||
const auto* codec = codec_; |
|||
std::string channel_name = name_; |
|||
BinaryMessageHandler binary_handler = [handler, codec, channel_name]( |
|||
const uint8_t* binary_message, |
|||
const size_t binary_message_size, |
|||
BinaryReply binary_reply) { |
|||
// Use this channel's codec to decode the message and build a reply |
|||
// handler. |
|||
std::unique_ptr<T> message = |
|||
codec->DecodeMessage(binary_message, binary_message_size); |
|||
if (!message) { |
|||
std::cerr << "Unable to decode message on channel " << channel_name |
|||
<< std::endl; |
|||
binary_reply(nullptr, 0); |
|||
return; |
|||
} |
|||
|
|||
MessageReply<T> unencoded_reply = [binary_reply, |
|||
codec](const T& unencoded_response) { |
|||
auto binary_response = codec->EncodeMessage(unencoded_response); |
|||
binary_reply(binary_response->data(), binary_response->size()); |
|||
}; |
|||
handler(*message, std::move(unencoded_reply)); |
|||
}; |
|||
messenger_->SetMessageHandler(name_, std::move(binary_handler)); |
|||
} |
|||
|
|||
private: |
|||
BinaryMessenger* messenger_; |
|||
std::string name_; |
|||
const MessageCodec<T>* codec_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_BASIC_MESSAGE_CHANNEL_H_ |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_BINARY_MESSENGER_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_BINARY_MESSENGER_H_ |
|||
|
|||
#include <functional> |
|||
#include <string> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
typedef std::function<void(const uint8_t* reply, const size_t reply_size)> |
|||
BinaryReply; |
|||
|
|||
typedef std::function<void(const uint8_t* message, const size_t message_size, |
|||
BinaryReply reply)> |
|||
BinaryMessageHandler; |
|||
|
|||
class BinaryMessenger { |
|||
public: |
|||
virtual ~BinaryMessenger() = default; |
|||
|
|||
virtual void Send(const std::string& channel, const uint8_t* message, |
|||
const size_t message_size) const = 0; |
|||
|
|||
virtual void Send(const std::string& channel, const uint8_t* message, |
|||
const size_t message_size, BinaryReply reply) const = 0; |
|||
|
|||
virtual void SetMessageHandler(const std::string& channel, |
|||
BinaryMessageHandler handler) = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_ENCODABLE_VALUE_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_ENCODABLE_VALUE_H_ |
|||
|
|||
#include <assert.h> |
|||
|
|||
#include <cstdint> |
|||
#include <map> |
|||
#include <string> |
|||
#include <utility> |
|||
#include <vector> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double"); |
|||
|
|||
class EncodableValue; |
|||
|
|||
using EncodableList = std::vector<EncodableValue>; |
|||
using EncodableMap = std::map<EncodableValue, EncodableValue>; |
|||
|
|||
class EncodableValue { |
|||
public: |
|||
enum class Type { |
|||
kNull, |
|||
kBool, |
|||
kInt, |
|||
kLong, |
|||
kDouble, |
|||
kString, |
|||
kByteList, |
|||
kIntList, |
|||
kLongList, |
|||
kDoubleList, |
|||
kList, |
|||
kMap, |
|||
}; |
|||
|
|||
EncodableValue() {} |
|||
|
|||
explicit EncodableValue(bool value) : bool_(value), type_(Type::kBool) {} |
|||
|
|||
explicit EncodableValue(int32_t value) : int_(value), type_(Type::kInt) {} |
|||
|
|||
explicit EncodableValue(int64_t value) : long_(value), type_(Type::kLong) {} |
|||
|
|||
explicit EncodableValue(double value) |
|||
: double_(value), type_(Type::kDouble) {} |
|||
|
|||
explicit EncodableValue(const char* value) |
|||
: string_(new std::string(value)), type_(Type::kString) {} |
|||
|
|||
explicit EncodableValue(const std::string& value) |
|||
: string_(new std::string(value)), type_(Type::kString) {} |
|||
|
|||
explicit EncodableValue(std::vector<uint8_t> list) |
|||
: byte_list_(new std::vector<uint8_t>(std::move(list))), |
|||
type_(Type::kByteList) {} |
|||
|
|||
explicit EncodableValue(std::vector<int32_t> list) |
|||
: int_list_(new std::vector<int32_t>(std::move(list))), |
|||
type_(Type::kIntList) {} |
|||
|
|||
explicit EncodableValue(std::vector<int64_t> list) |
|||
: long_list_(new std::vector<int64_t>(std::move(list))), |
|||
type_(Type::kLongList) {} |
|||
|
|||
explicit EncodableValue(std::vector<double> list) |
|||
: double_list_(new std::vector<double>(std::move(list))), |
|||
type_(Type::kDoubleList) {} |
|||
|
|||
explicit EncodableValue(EncodableList list) |
|||
: list_(new EncodableList(std::move(list))), type_(Type::kList) {} |
|||
|
|||
explicit EncodableValue(EncodableMap map) |
|||
: map_(new EncodableMap(std::move(map))), type_(Type::kMap) {} |
|||
|
|||
explicit EncodableValue(Type type) : type_(type) { |
|||
switch (type_) { |
|||
case Type::kNull: |
|||
break; |
|||
case Type::kBool: |
|||
bool_ = false; |
|||
break; |
|||
case Type::kInt: |
|||
int_ = 0; |
|||
break; |
|||
case Type::kLong: |
|||
long_ = 0; |
|||
break; |
|||
case Type::kDouble: |
|||
double_ = 0.0; |
|||
break; |
|||
case Type::kString: |
|||
string_ = new std::string(); |
|||
break; |
|||
case Type::kByteList: |
|||
byte_list_ = new std::vector<uint8_t>(); |
|||
break; |
|||
case Type::kIntList: |
|||
int_list_ = new std::vector<int32_t>(); |
|||
break; |
|||
case Type::kLongList: |
|||
long_list_ = new std::vector<int64_t>(); |
|||
break; |
|||
case Type::kDoubleList: |
|||
double_list_ = new std::vector<double>(); |
|||
break; |
|||
case Type::kList: |
|||
list_ = new std::vector<EncodableValue>(); |
|||
break; |
|||
case Type::kMap: |
|||
map_ = new std::map<EncodableValue, EncodableValue>(); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
~EncodableValue() { DestroyValue(); } |
|||
|
|||
EncodableValue(const EncodableValue& other) { |
|||
DestroyValue(); |
|||
|
|||
type_ = other.type_; |
|||
switch (type_) { |
|||
case Type::kNull: |
|||
break; |
|||
case Type::kBool: |
|||
bool_ = other.bool_; |
|||
break; |
|||
case Type::kInt: |
|||
int_ = other.int_; |
|||
break; |
|||
case Type::kLong: |
|||
long_ = other.long_; |
|||
break; |
|||
case Type::kDouble: |
|||
double_ = other.double_; |
|||
break; |
|||
case Type::kString: |
|||
string_ = new std::string(*other.string_); |
|||
break; |
|||
case Type::kByteList: |
|||
byte_list_ = new std::vector<uint8_t>(*other.byte_list_); |
|||
break; |
|||
case Type::kIntList: |
|||
int_list_ = new std::vector<int32_t>(*other.int_list_); |
|||
break; |
|||
case Type::kLongList: |
|||
long_list_ = new std::vector<int64_t>(*other.long_list_); |
|||
break; |
|||
case Type::kDoubleList: |
|||
double_list_ = new std::vector<double>(*other.double_list_); |
|||
break; |
|||
case Type::kList: |
|||
list_ = new std::vector<EncodableValue>(*other.list_); |
|||
break; |
|||
case Type::kMap: |
|||
map_ = new std::map<EncodableValue, EncodableValue>(*other.map_); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
EncodableValue(EncodableValue&& other) noexcept { *this = std::move(other); } |
|||
|
|||
EncodableValue& operator=(const EncodableValue& other) { |
|||
if (&other == this) { |
|||
return *this; |
|||
} |
|||
using std::swap; |
|||
EncodableValue temp(other); |
|||
swap(*this, temp); |
|||
return *this; |
|||
} |
|||
|
|||
EncodableValue& operator=(EncodableValue&& other) noexcept { |
|||
if (&other == this) { |
|||
return *this; |
|||
} |
|||
DestroyValue(); |
|||
|
|||
type_ = other.type_; |
|||
switch (type_) { |
|||
case Type::kNull: |
|||
break; |
|||
case Type::kBool: |
|||
bool_ = other.bool_; |
|||
break; |
|||
case Type::kInt: |
|||
int_ = other.int_; |
|||
break; |
|||
case Type::kLong: |
|||
long_ = other.long_; |
|||
break; |
|||
case Type::kDouble: |
|||
double_ = other.double_; |
|||
break; |
|||
case Type::kString: |
|||
string_ = other.string_; |
|||
break; |
|||
case Type::kByteList: |
|||
byte_list_ = other.byte_list_; |
|||
break; |
|||
case Type::kIntList: |
|||
int_list_ = other.int_list_; |
|||
break; |
|||
case Type::kLongList: |
|||
long_list_ = other.long_list_; |
|||
break; |
|||
case Type::kDoubleList: |
|||
double_list_ = other.double_list_; |
|||
break; |
|||
case Type::kList: |
|||
list_ = other.list_; |
|||
break; |
|||
case Type::kMap: |
|||
map_ = other.map_; |
|||
break; |
|||
} |
|||
|
|||
other.type_ = Type::kNull; |
|||
return *this; |
|||
} |
|||
|
|||
template <typename T> |
|||
EncodableValue& operator=(const T& value) { |
|||
*this = EncodableValue(value); |
|||
return *this; |
|||
} |
|||
|
|||
bool operator<(const EncodableValue& other) const { |
|||
if (type_ != other.type_) { |
|||
return type_ < other.type_; |
|||
} |
|||
switch (type_) { |
|||
case Type::kNull: |
|||
return false; |
|||
case Type::kBool: |
|||
return bool_ < other.bool_; |
|||
case Type::kInt: |
|||
return int_ < other.int_; |
|||
case Type::kLong: |
|||
return long_ < other.long_; |
|||
case Type::kDouble: |
|||
return double_ < other.double_; |
|||
case Type::kString: |
|||
return *string_ < *other.string_; |
|||
case Type::kByteList: |
|||
case Type::kIntList: |
|||
case Type::kLongList: |
|||
case Type::kDoubleList: |
|||
case Type::kList: |
|||
case Type::kMap: |
|||
return this < &other; |
|||
} |
|||
assert(false); |
|||
return false; |
|||
} |
|||
|
|||
bool BoolValue() const { |
|||
assert(IsBool()); |
|||
return bool_; |
|||
} |
|||
|
|||
int32_t IntValue() const { |
|||
assert(IsInt()); |
|||
return int_; |
|||
} |
|||
|
|||
int64_t LongValue() const { |
|||
assert(IsLong() || IsInt()); |
|||
if (IsLong()) { |
|||
return long_; |
|||
} |
|||
return int_; |
|||
} |
|||
|
|||
double DoubleValue() const { |
|||
assert(IsDouble()); |
|||
return double_; |
|||
} |
|||
|
|||
const std::string& StringValue() const { |
|||
assert(IsString()); |
|||
return *string_; |
|||
} |
|||
|
|||
const std::vector<uint8_t>& ByteListValue() const { |
|||
assert(IsByteList()); |
|||
return *byte_list_; |
|||
} |
|||
|
|||
std::vector<uint8_t>& ByteListValue() { |
|||
assert(IsByteList()); |
|||
return *byte_list_; |
|||
} |
|||
|
|||
const std::vector<int32_t>& IntListValue() const { |
|||
assert(IsIntList()); |
|||
return *int_list_; |
|||
} |
|||
|
|||
std::vector<int32_t>& IntListValue() { |
|||
assert(IsIntList()); |
|||
return *int_list_; |
|||
} |
|||
|
|||
const std::vector<int64_t>& LongListValue() const { |
|||
assert(IsLongList()); |
|||
return *long_list_; |
|||
} |
|||
|
|||
std::vector<int64_t>& LongListValue() { |
|||
assert(IsLongList()); |
|||
return *long_list_; |
|||
} |
|||
|
|||
const std::vector<double>& DoubleListValue() const { |
|||
assert(IsDoubleList()); |
|||
return *double_list_; |
|||
} |
|||
|
|||
std::vector<double>& DoubleListValue() { |
|||
assert(IsDoubleList()); |
|||
return *double_list_; |
|||
} |
|||
|
|||
const EncodableList& ListValue() const { |
|||
assert(IsList()); |
|||
return *list_; |
|||
} |
|||
|
|||
EncodableList& ListValue() { |
|||
assert(IsList()); |
|||
return *list_; |
|||
} |
|||
|
|||
const EncodableMap& MapValue() const { |
|||
assert(IsMap()); |
|||
return *map_; |
|||
} |
|||
|
|||
EncodableMap& MapValue() { |
|||
assert(IsMap()); |
|||
return *map_; |
|||
} |
|||
|
|||
bool IsNull() const { return type_ == Type::kNull; } |
|||
|
|||
bool IsBool() const { return type_ == Type::kBool; } |
|||
|
|||
bool IsInt() const { return type_ == Type::kInt; } |
|||
|
|||
bool IsLong() const { return type_ == Type::kLong; } |
|||
|
|||
bool IsDouble() const { return type_ == Type::kDouble; } |
|||
|
|||
bool IsString() const { return type_ == Type::kString; } |
|||
|
|||
bool IsByteList() const { return type_ == Type::kByteList; } |
|||
|
|||
bool IsIntList() const { return type_ == Type::kIntList; } |
|||
|
|||
bool IsLongList() const { return type_ == Type::kLongList; } |
|||
|
|||
bool IsDoubleList() const { return type_ == Type::kDoubleList; } |
|||
|
|||
bool IsList() const { return type_ == Type::kList; } |
|||
|
|||
bool IsMap() const { return type_ == Type::kMap; } |
|||
|
|||
Type type() const { return type_; } |
|||
|
|||
private: |
|||
void DestroyValue() { |
|||
switch (type_) { |
|||
case Type::kNull: |
|||
case Type::kBool: |
|||
case Type::kInt: |
|||
case Type::kLong: |
|||
case Type::kDouble: |
|||
break; |
|||
case Type::kString: |
|||
delete string_; |
|||
break; |
|||
case Type::kByteList: |
|||
delete byte_list_; |
|||
break; |
|||
case Type::kIntList: |
|||
delete int_list_; |
|||
break; |
|||
case Type::kLongList: |
|||
delete long_list_; |
|||
break; |
|||
case Type::kDoubleList: |
|||
delete double_list_; |
|||
break; |
|||
case Type::kList: |
|||
delete list_; |
|||
break; |
|||
case Type::kMap: |
|||
delete map_; |
|||
break; |
|||
} |
|||
|
|||
type_ = Type::kNull; |
|||
} |
|||
|
|||
union { |
|||
bool bool_; |
|||
int32_t int_; |
|||
int64_t long_; |
|||
double double_; |
|||
std::string* string_; |
|||
std::vector<uint8_t>* byte_list_; |
|||
std::vector<int32_t>* int_list_; |
|||
std::vector<int64_t>* long_list_; |
|||
std::vector<double>* double_list_; |
|||
std::vector<EncodableValue>* list_; |
|||
std::map<EncodableValue, EncodableValue>* map_; |
|||
}; |
|||
|
|||
Type type_ = Type::kNull; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_ENGINE_METHOD_RESULT_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_ENGINE_METHOD_RESULT_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include "binary_messenger.h" |
|||
#include "method_codec.h" |
|||
#include "method_result.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
namespace internal { |
|||
|
|||
class ReplyManager { |
|||
public: |
|||
ReplyManager(BinaryReply reply_handler_); |
|||
~ReplyManager(); |
|||
|
|||
ReplyManager(ReplyManager const&) = delete; |
|||
ReplyManager& operator=(ReplyManager const&) = delete; |
|||
|
|||
void SendResponseData(const std::vector<uint8_t>* data); |
|||
|
|||
private: |
|||
BinaryReply reply_handler_; |
|||
}; |
|||
} // namespace internal |
|||
|
|||
template <typename T> |
|||
class EngineMethodResult : public MethodResult<T> { |
|||
public: |
|||
EngineMethodResult(BinaryReply reply_handler, const MethodCodec<T>* codec) |
|||
: reply_manager_( |
|||
std::make_unique<internal::ReplyManager>(std::move(reply_handler))), |
|||
codec_(codec) {} |
|||
|
|||
~EngineMethodResult() = default; |
|||
|
|||
protected: |
|||
void SuccessInternal(const T* result) override { |
|||
std::unique_ptr<std::vector<uint8_t>> data = |
|||
codec_->EncodeSuccessEnvelope(result); |
|||
reply_manager_->SendResponseData(data.get()); |
|||
} |
|||
|
|||
void ErrorInternal(const std::string& error_code, |
|||
const std::string& error_message, |
|||
const T* error_details) override { |
|||
std::unique_ptr<std::vector<uint8_t>> data = |
|||
codec_->EncodeErrorEnvelope(error_code, error_message, error_details); |
|||
reply_manager_->SendResponseData(data.get()); |
|||
} |
|||
|
|||
void NotImplementedInternal() override { |
|||
reply_manager_->SendResponseData(nullptr); |
|||
} |
|||
|
|||
private: |
|||
std::unique_ptr<internal::ReplyManager> reply_manager_; |
|||
|
|||
const MethodCodec<T>* codec_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_MESSAGE_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_MESSAGE_CODEC_H_ |
|||
|
|||
#include "json_type.h" |
|||
#include "message_codec.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class JsonMessageCodec : public MessageCodec<JsonValueType> { |
|||
public: |
|||
static const JsonMessageCodec& GetInstance(); |
|||
|
|||
~JsonMessageCodec() = default; |
|||
|
|||
JsonMessageCodec(JsonMessageCodec const&) = delete; |
|||
JsonMessageCodec& operator=(JsonMessageCodec const&) = delete; |
|||
|
|||
protected: |
|||
JsonMessageCodec() = default; |
|||
|
|||
std::unique_ptr<JsonValueType> DecodeMessageInternal( |
|||
const uint8_t* binary_message, const size_t message_size) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal( |
|||
const JsonValueType& message) const override; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_METHOD_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_METHOD_CODEC_H_ |
|||
|
|||
#include "json_type.h" |
|||
#include "method_call.h" |
|||
#include "method_codec.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class JsonMethodCodec : public MethodCodec<JsonValueType> { |
|||
public: |
|||
static const JsonMethodCodec& GetInstance(); |
|||
|
|||
~JsonMethodCodec() = default; |
|||
|
|||
JsonMethodCodec(JsonMethodCodec const&) = delete; |
|||
JsonMethodCodec& operator=(JsonMethodCodec const&) = delete; |
|||
|
|||
protected: |
|||
JsonMethodCodec() = default; |
|||
|
|||
std::unique_ptr<MethodCall<JsonValueType>> DecodeMethodCallInternal( |
|||
const uint8_t* message, const size_t message_size) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal( |
|||
const MethodCall<JsonValueType>& method_call) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal( |
|||
const JsonValueType* result) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal( |
|||
const std::string& error_code, const std::string& error_message, |
|||
const JsonValueType* error_details) const override; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_TYPE_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_JSON_TYPE_H_ |
|||
|
|||
//#ifdef USE_RAPID_JSON |
|||
#include <rapidjson/document.h> |
|||
|
|||
using JsonValueType = rapidjson::Document; |
|||
#/*else |
|||
#include <json/json.h> |
|||
|
|||
using JsonValueType = Json::Value; |
|||
#endif*/ |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_MESSAGE_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_MESSAGE_CODEC_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
template <typename T> |
|||
class MessageCodec { |
|||
public: |
|||
MessageCodec() = default; |
|||
|
|||
virtual ~MessageCodec() = default; |
|||
|
|||
MessageCodec(MessageCodec<T> const&) = delete; |
|||
MessageCodec& operator=(MessageCodec<T> const&) = delete; |
|||
|
|||
std::unique_ptr<T> DecodeMessage(const uint8_t* binary_message, |
|||
const size_t message_size) const { |
|||
return std::move(DecodeMessageInternal(binary_message, message_size)); |
|||
} |
|||
|
|||
std::unique_ptr<T> DecodeMessage( |
|||
const std::vector<uint8_t>& binary_message) const { |
|||
size_t size = binary_message.size(); |
|||
const uint8_t* data = size > 0 ? &binary_message[0] : nullptr; |
|||
return std::move(DecodeMessageInternal(data, size)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMessage(const T& message) const { |
|||
return std::move(EncodeMessageInternal(message)); |
|||
} |
|||
|
|||
protected: |
|||
virtual std::unique_ptr<T> DecodeMessageInternal( |
|||
const uint8_t* binary_message, const size_t message_size) const = 0; |
|||
|
|||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal( |
|||
const T& message) const = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_TYPED_METHOD_CALL_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_TYPED_METHOD_CALL_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
template <typename T> |
|||
class MethodCall { |
|||
public: |
|||
MethodCall(const std::string& method_name, std::unique_ptr<T> arguments) |
|||
: method_name_(method_name), arguments_(std::move(arguments)) {} |
|||
|
|||
virtual ~MethodCall() = default; |
|||
|
|||
MethodCall(MethodCall<T> const&) = delete; |
|||
MethodCall& operator=(MethodCall<T> const&) = delete; |
|||
|
|||
const std::string& method_name() const { return method_name_; } |
|||
|
|||
const T* arguments() const { return arguments_.get(); } |
|||
|
|||
private: |
|||
std::string method_name_; |
|||
std::unique_ptr<T> arguments_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_CHANNEL_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_CHANNEL_H_ |
|||
|
|||
#include <iostream> |
|||
#include <string> |
|||
|
|||
#include "binary_messenger.h" |
|||
#include "engine_method_result.h" |
|||
#include "method_call.h" |
|||
#include "method_codec.h" |
|||
#include "method_result.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
template <typename T> |
|||
using MethodCallHandler = std::function<void( |
|||
const MethodCall<T>& call, std::unique_ptr<MethodResult<T>> result)>; |
|||
|
|||
template <typename T> |
|||
class MethodChannel { |
|||
public: |
|||
MethodChannel(BinaryMessenger* messenger, const std::string& name, |
|||
const MethodCodec<T>* codec) |
|||
: messenger_(messenger), name_(name), codec_(codec) {} |
|||
|
|||
~MethodChannel() = default; |
|||
|
|||
MethodChannel(MethodChannel const&) = delete; |
|||
MethodChannel& operator=(MethodChannel const&) = delete; |
|||
|
|||
void InvokeMethod(const std::string& method, std::unique_ptr<T> arguments) { |
|||
MethodCall<T> method_call(method, std::move(arguments)); |
|||
std::unique_ptr<std::vector<uint8_t>> message = |
|||
codec_->EncodeMethodCall(method_call); |
|||
messenger_->Send(name_, message->data(), message->size(), nullptr); |
|||
} |
|||
|
|||
void InvokeMethod(const std::string& method, std::unique_ptr<T> arguments, |
|||
uiwidgets::BinaryReply reply) { |
|||
MethodCall<T> method_call(method, std::move(arguments)); |
|||
std::unique_ptr<std::vector<uint8_t>> message = |
|||
codec_->EncodeMethodCall(method_call); |
|||
messenger_->Send(name_, message->data(), message->size(), reply); |
|||
} |
|||
|
|||
void SetMethodCallHandler(MethodCallHandler<T> handler) const { |
|||
if (!handler) { |
|||
messenger_->SetMessageHandler(name_, nullptr); |
|||
return; |
|||
} |
|||
const auto* codec = codec_; |
|||
std::string channel_name = name_; |
|||
BinaryMessageHandler binary_handler = [handler, codec, channel_name]( |
|||
const uint8_t* message, |
|||
const size_t message_size, |
|||
BinaryReply reply) { |
|||
auto result = |
|||
std::make_unique<EngineMethodResult<T>>(std::move(reply), codec); |
|||
std::unique_ptr<MethodCall<T>> method_call = |
|||
codec->DecodeMethodCall(message, message_size); |
|||
if (!method_call) { |
|||
std::cerr << "Unable to construct method call from message on channel " |
|||
<< channel_name << std::endl; |
|||
result->NotImplemented(); |
|||
return; |
|||
} |
|||
handler(*method_call, std::move(result)); |
|||
}; |
|||
messenger_->SetMessageHandler(name_, std::move(binary_handler)); |
|||
} |
|||
|
|||
private: |
|||
BinaryMessenger* messenger_; |
|||
std::string name_; |
|||
const MethodCodec<T>* codec_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_CODEC_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include "method_call.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
template <typename T> |
|||
class MethodCodec { |
|||
public: |
|||
MethodCodec() = default; |
|||
|
|||
virtual ~MethodCodec() = default; |
|||
|
|||
MethodCodec(MethodCodec<T> const&) = delete; |
|||
MethodCodec& operator=(MethodCodec<T> const&) = delete; |
|||
|
|||
std::unique_ptr<MethodCall<T>> DecodeMethodCall( |
|||
const uint8_t* message, const size_t message_size) const { |
|||
return std::move(DecodeMethodCallInternal(message, message_size)); |
|||
} |
|||
|
|||
std::unique_ptr<MethodCall<T>> DecodeMethodCall( |
|||
const std::vector<uint8_t>& message) const { |
|||
size_t size = message.size(); |
|||
const uint8_t* data = size > 0 ? &message[0] : nullptr; |
|||
return std::move(DecodeMethodCallInternal(data, size)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCall( |
|||
const MethodCall<T>& method_call) const { |
|||
return std::move(EncodeMethodCallInternal(method_call)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelope( |
|||
const T* result = nullptr) const { |
|||
return std::move(EncodeSuccessEnvelopeInternal(result)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelope( |
|||
const std::string& error_code, const std::string& error_message = "", |
|||
const T* error_details = nullptr) const { |
|||
return std::move( |
|||
EncodeErrorEnvelopeInternal(error_code, error_message, error_details)); |
|||
} |
|||
|
|||
protected: |
|||
virtual std::unique_ptr<MethodCall<T>> DecodeMethodCallInternal( |
|||
const uint8_t* message, const size_t message_size) const = 0; |
|||
|
|||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal( |
|||
const MethodCall<T>& method_call) const = 0; |
|||
|
|||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal( |
|||
const T* result) const = 0; |
|||
|
|||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal( |
|||
const std::string& error_code, const std::string& error_message, |
|||
const T* error_details) const = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_RESULT_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_METHOD_RESULT_H_ |
|||
|
|||
#include <string> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
template <typename T> |
|||
class MethodResult { |
|||
public: |
|||
MethodResult() = default; |
|||
|
|||
virtual ~MethodResult() = default; |
|||
|
|||
MethodResult(MethodResult const&) = delete; |
|||
MethodResult& operator=(MethodResult const&) = delete; |
|||
|
|||
void Success(const T* result = nullptr) { SuccessInternal(result); } |
|||
|
|||
void Error(const std::string& error_code, |
|||
const std::string& error_message = "", |
|||
const T* error_details = nullptr) { |
|||
ErrorInternal(error_code, error_message, error_details); |
|||
} |
|||
|
|||
void NotImplemented() { NotImplementedInternal(); } |
|||
|
|||
protected: |
|||
virtual void SuccessInternal(const T* result) = 0; |
|||
|
|||
virtual void ErrorInternal(const std::string& error_code, |
|||
const std::string& error_message, |
|||
const T* error_details) = 0; |
|||
|
|||
virtual void NotImplementedInternal() = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_PLUGIN_REGISTRAR_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_PLUGIN_REGISTRAR_H_ |
|||
|
|||
#include "shell/platform/common/cpp/public/uiwidgets_plugin_registrar.h" |
|||
|
|||
#include <memory> |
|||
#include <set> |
|||
#include <string> |
|||
|
|||
#include "binary_messenger.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Plugin; |
|||
|
|||
class PluginRegistrar { |
|||
public: |
|||
explicit PluginRegistrar(UIWidgetsDesktopPluginRegistrarRef core_registrar); |
|||
|
|||
virtual ~PluginRegistrar(); |
|||
|
|||
PluginRegistrar(PluginRegistrar const&) = delete; |
|||
PluginRegistrar& operator=(PluginRegistrar const&) = delete; |
|||
|
|||
BinaryMessenger* messenger() { return messenger_.get(); } |
|||
|
|||
void AddPlugin(std::unique_ptr<Plugin> plugin); |
|||
|
|||
void EnableInputBlockingForChannel(const std::string& channel); |
|||
|
|||
private: |
|||
UIWidgetsDesktopPluginRegistrarRef registrar_; |
|||
|
|||
std::unique_ptr<BinaryMessenger> messenger_; |
|||
|
|||
std::set<std::unique_ptr<Plugin>> plugins_; |
|||
}; |
|||
|
|||
class Plugin { |
|||
public: |
|||
virtual ~Plugin() = default; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_PLUGIN_REGISTRY_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_PLUGIN_REGISTRY_H_ |
|||
|
|||
#include "shell/platform/common/cpp/public/uiwidgets_plugin_registrar.h" |
|||
|
|||
#include <string> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class PluginRegistry { |
|||
public: |
|||
PluginRegistry() = default; |
|||
virtual ~PluginRegistry() = default; |
|||
|
|||
PluginRegistry(PluginRegistry const&) = delete; |
|||
PluginRegistry& operator=(PluginRegistry const&) = delete; |
|||
|
|||
virtual UIWidgetsDesktopPluginRegistrarRef GetRegistrarForPlugin( |
|||
const std::string& plugin_name) = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_STANDARD_MESSAGE_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_STANDARD_MESSAGE_CODEC_H_ |
|||
|
|||
#include "encodable_value.h" |
|||
#include "message_codec.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class StandardMessageCodec : public MessageCodec<EncodableValue> { |
|||
public: |
|||
static const StandardMessageCodec& GetInstance(); |
|||
|
|||
~StandardMessageCodec(); |
|||
|
|||
StandardMessageCodec(StandardMessageCodec const&) = delete; |
|||
StandardMessageCodec& operator=(StandardMessageCodec const&) = delete; |
|||
|
|||
protected: |
|||
StandardMessageCodec(); |
|||
|
|||
std::unique_ptr<EncodableValue> DecodeMessageInternal( |
|||
const uint8_t* binary_message, const size_t message_size) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal( |
|||
const EncodableValue& message) const override; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_STANDARD_METHOD_CODEC_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_UIWIDGETS_STANDARD_METHOD_CODEC_H_ |
|||
|
|||
#include "encodable_value.h" |
|||
#include "method_call.h" |
|||
#include "method_codec.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class StandardMethodCodec : public MethodCodec<EncodableValue> { |
|||
public: |
|||
static const StandardMethodCodec& GetInstance(); |
|||
|
|||
~StandardMethodCodec() = default; |
|||
|
|||
StandardMethodCodec(StandardMethodCodec const&) = delete; |
|||
StandardMethodCodec& operator=(StandardMethodCodec const&) = delete; |
|||
|
|||
protected: |
|||
StandardMethodCodec() = default; |
|||
|
|||
std::unique_ptr<MethodCall<EncodableValue>> DecodeMethodCallInternal( |
|||
const uint8_t* message, const size_t message_size) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal( |
|||
const MethodCall<EncodableValue>& method_call) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal( |
|||
const EncodableValue* result) const override; |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal( |
|||
const std::string& error_code, const std::string& error_message, |
|||
const EncodableValue* error_details) const override; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif |
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
//#define USE_RAPID_JSON
|
|||
#include "include/uiwidgets/json_message_codec.h"
|
|||
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
|
|||
//#ifdef USE_RAPID_JSON
|
|||
#include "rapidjson/error/en.h"
|
|||
#include "rapidjson/stringbuffer.h"
|
|||
#include "rapidjson/writer.h"
|
|||
//#endif
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// static
|
|||
const JsonMessageCodec& JsonMessageCodec::GetInstance() { |
|||
static JsonMessageCodec sInstance; |
|||
return sInstance; |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> JsonMessageCodec::EncodeMessageInternal( |
|||
const JsonValueType& message) const { |
|||
//#ifdef USE_RAPID_JSON
|
|||
// TODO: Look into alternate writers that would avoid the buffer copy.
|
|||
rapidjson::StringBuffer buffer; |
|||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); |
|||
message.Accept(writer); |
|||
const char* buffer_start = buffer.GetString(); |
|||
return std::make_unique<std::vector<uint8_t>>( |
|||
buffer_start, buffer_start + buffer.GetSize()); |
|||
//#else
|
|||
// Json::StreamWriterBuilder writer_builder;
|
|||
// std::string serialization = Json::writeString(writer_builder, message);
|
|||
// return std::make_unique<std::vector<uint8_t>>(serialization.begin(),
|
|||
// serialization.end());
|
|||
//#endif
|
|||
} |
|||
|
|||
std::unique_ptr<JsonValueType> JsonMessageCodec::DecodeMessageInternal( |
|||
const uint8_t* binary_message, |
|||
const size_t message_size) const { |
|||
auto raw_message = reinterpret_cast<const char*>(binary_message); |
|||
auto json_message = std::make_unique<JsonValueType>(); |
|||
std::string parse_errors; |
|||
bool parsing_successful = false; |
|||
//#ifdef USE_RAPID_JSON
|
|||
rapidjson::ParseResult result = |
|||
json_message->Parse(raw_message, message_size); |
|||
parsing_successful = result == rapidjson::ParseErrorCode::kParseErrorNone; |
|||
if (!parsing_successful) { |
|||
parse_errors = rapidjson::GetParseError_En(result.Code()); |
|||
} |
|||
//#else
|
|||
// Json::CharReaderBuilder reader_builder;
|
|||
// std::unique_ptr<Json::CharReader> parser(reader_builder.newCharReader());
|
|||
// parsing_successful = parser->parse(raw_message, raw_message + message_size,
|
|||
// json_message.get(), &parse_errors);
|
|||
//#endif
|
|||
if (!parsing_successful) { |
|||
std::cerr << "Unable to parse JSON message:" << std::endl |
|||
<< parse_errors << std::endl; |
|||
return nullptr; |
|||
} |
|||
return json_message; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "include/uiwidgets/json_method_codec.h"
|
|||
|
|||
#include "include/uiwidgets/json_message_codec.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
namespace { |
|||
// Keys used in MethodCall encoding.
|
|||
constexpr char kMessageMethodKey[] = "method"; |
|||
constexpr char kMessageArgumentsKey[] = "args"; |
|||
} // namespace
|
|||
|
|||
// static
|
|||
const JsonMethodCodec& JsonMethodCodec::GetInstance() { |
|||
static JsonMethodCodec sInstance; |
|||
return sInstance; |
|||
} |
|||
|
|||
std::unique_ptr<MethodCall<JsonValueType>> |
|||
JsonMethodCodec::DecodeMethodCallInternal(const uint8_t* message, |
|||
const size_t message_size) const { |
|||
std::unique_ptr<JsonValueType> json_message = |
|||
JsonMessageCodec::GetInstance().DecodeMessage(message, message_size); |
|||
if (!json_message) { |
|||
return nullptr; |
|||
} |
|||
|
|||
//#if USE_RAPID_JSON
|
|||
auto method_name_iter = json_message->FindMember(kMessageMethodKey); |
|||
if (method_name_iter == json_message->MemberEnd()) { |
|||
return nullptr; |
|||
} |
|||
if (!method_name_iter->value.IsString()) { |
|||
return nullptr; |
|||
} |
|||
std::string method_name(method_name_iter->value.GetString()); |
|||
auto arguments_iter = json_message->FindMember(kMessageArgumentsKey); |
|||
std::unique_ptr<rapidjson::Document> arguments; |
|||
if (arguments_iter != json_message->MemberEnd()) { |
|||
// Pull the arguments subtree up to the root of json_message. This is
|
|||
// destructive to json_message, but the full value is no longer needed, and
|
|||
// this avoids a subtree copy.
|
|||
// Note: The static_cast is for compatibility with RapidJSON 1.1; master
|
|||
// already allows swapping a Document with a Value directly. Once there is
|
|||
// a new RapidJSON release (at which point clients can be expected to have
|
|||
// that change in the version they depend on) remove the cast.
|
|||
static_cast<rapidjson::Value*>(json_message.get()) |
|||
->Swap(arguments_iter->value); |
|||
// Swap it into |arguments|. This moves the allocator ownership, so that
|
|||
// the data won't be deleted when json_message goes out of scope.
|
|||
arguments = std::make_unique<rapidjson::Document>(); |
|||
arguments->Swap(*json_message); |
|||
} |
|||
return std::make_unique<MethodCall<rapidjson::Document>>( |
|||
method_name, std::move(arguments)); |
|||
//#else
|
|||
// Json::Value method = (*json_message)[kMessageMethodKey];
|
|||
// if (method.isNull()) {
|
|||
// return nullptr;
|
|||
// }
|
|||
// return std::make_unique<MethodCall<Json::Value>>(
|
|||
// method.asString(),
|
|||
// std::make_unique<Json::Value>((*json_message)[kMessageArgumentsKey]));
|
|||
//#endif
|
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> JsonMethodCodec::EncodeMethodCallInternal( |
|||
const MethodCall<JsonValueType>& method_call) const { |
|||
//#if USE_RAPID_JSON
|
|||
// TODO: Consider revisiting the codec APIs to avoid the need to copy
|
|||
// everything when doing encoding (e.g., by having a version that takes
|
|||
// owership of the object to encode, so that it can be moved instead).
|
|||
rapidjson::Document message(rapidjson::kObjectType); |
|||
auto& allocator = message.GetAllocator(); |
|||
rapidjson::Value name(method_call.method_name(), allocator); |
|||
rapidjson::Value arguments; |
|||
if (method_call.arguments()) { |
|||
arguments.CopyFrom(*method_call.arguments(), allocator); |
|||
} |
|||
message.AddMember(kMessageMethodKey, name, allocator); |
|||
message.AddMember(kMessageArgumentsKey, arguments, allocator); |
|||
//#else
|
|||
// Json::Value message(Json::objectValue);
|
|||
// message[kMessageMethodKey] = method_call.method_name();
|
|||
// const Json::Value* arguments = method_call.arguments();
|
|||
// message[kMessageArgumentsKey] = arguments ? *arguments : Json::Value();
|
|||
//#endif
|
|||
|
|||
return JsonMessageCodec::GetInstance().EncodeMessage(message); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
JsonMethodCodec::EncodeSuccessEnvelopeInternal( |
|||
const JsonValueType* result) const { |
|||
//#if USE_RAPID_JSON
|
|||
rapidjson::Document envelope; |
|||
envelope.SetArray(); |
|||
rapidjson::Value result_value; |
|||
if (result) { |
|||
result_value.CopyFrom(*result, envelope.GetAllocator()); |
|||
} |
|||
envelope.PushBack(result_value, envelope.GetAllocator()); |
|||
//#else
|
|||
// Json::Value envelope(Json::arrayValue);
|
|||
// envelope.append(result == nullptr ? Json::Value() : *result);
|
|||
//#endif
|
|||
|
|||
return JsonMessageCodec::GetInstance().EncodeMessage(envelope); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
JsonMethodCodec::EncodeErrorEnvelopeInternal( |
|||
const std::string& error_code, |
|||
const std::string& error_message, |
|||
const JsonValueType* error_details) const { |
|||
//#if USE_RAPID_JSON
|
|||
rapidjson::Document envelope(rapidjson::kArrayType); |
|||
auto& allocator = envelope.GetAllocator(); |
|||
envelope.PushBack(rapidjson::Value(error_code, allocator), allocator); |
|||
envelope.PushBack(rapidjson::Value(error_message, allocator), allocator); |
|||
rapidjson::Value details_value; |
|||
if (error_details) { |
|||
details_value.CopyFrom(*error_details, allocator); |
|||
} |
|||
envelope.PushBack(details_value, allocator); |
|||
//#else
|
|||
// Json::Value envelope(Json::arrayValue);
|
|||
// envelope.append(error_code);
|
|||
// envelope.append(error_message.empty() ? Json::Value() : error_message);
|
|||
// envelope.append(error_details == nullptr ? Json::Value() : *error_details);
|
|||
//#endif
|
|||
|
|||
return JsonMessageCodec::GetInstance().EncodeMessage(envelope); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_call.h"
|
|||
|
|||
// #include <memory>
|
|||
// #include <string>
|
|||
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// TEST(MethodCallTest, Basic) {
|
|||
// const std::string method_name("method_name");
|
|||
// const int argument = 42;
|
|||
// MethodCall<int> method_call(method_name, std::make_unique<int>(argument));
|
|||
// EXPECT_EQ(method_call.method_name(), method_name);
|
|||
// ASSERT_NE(method_call.arguments(), nullptr);
|
|||
// EXPECT_EQ(*method_call.arguments(), 42);
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
//// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
//// Use of this source code is governed by a BSD-style license that can be
|
|||
//// found in the LICENSE file.
|
|||
//
|
|||
//#include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/method_channel.h"
|
|||
//
|
|||
//#include <memory>
|
|||
//#include <string>
|
|||
//
|
|||
//#include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/binary_messenger.h"
|
|||
//#include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_method_codec.h"
|
|||
//#include "gtest/gtest.h"
|
|||
//
|
|||
//namespace uiwidgets {
|
|||
//
|
|||
//namespace {
|
|||
//
|
|||
//class TestBinaryMessenger : public BinaryMessenger {
|
|||
// public:
|
|||
// void Send(const std::string& channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size) const override {}
|
|||
//
|
|||
// void Send(const std::string& channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size,
|
|||
// BinaryReply reply) const override {}
|
|||
//
|
|||
// void SetMessageHandler(const std::string& channel,
|
|||
// BinaryMessageHandler handler) override {
|
|||
// last_message_handler_channel_ = channel;
|
|||
// last_message_handler_ = handler;
|
|||
// }
|
|||
//
|
|||
// std::string last_message_handler_channel() {
|
|||
// return last_message_handler_channel_;
|
|||
// }
|
|||
//
|
|||
// BinaryMessageHandler last_message_handler() { return last_message_handler_; }
|
|||
//
|
|||
// private:
|
|||
// std::string last_message_handler_channel_;
|
|||
// BinaryMessageHandler last_message_handler_;
|
|||
//};
|
|||
//
|
|||
//} // namespace
|
|||
//
|
|||
//// Tests that SetMethodCallHandler sets a handler that correctly interacts with
|
|||
//// the binary messenger.
|
|||
//TEST(MethodChannelTest, Registration) {
|
|||
// TestBinaryMessenger messenger;
|
|||
// const std::string channel_name("some_channel");
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// MethodChannel channel(&messenger, channel_name, &codec);
|
|||
//
|
|||
// bool callback_called = false;
|
|||
// const std::string method_name("hello");
|
|||
// channel.SetMethodCallHandler(
|
|||
// [&callback_called, method_name](const auto& call, auto result) {
|
|||
// callback_called = true;
|
|||
// // Ensure that the wrapper recieved a correctly decoded call and a
|
|||
// // result.
|
|||
// EXPECT_EQ(call.method_name(), method_name);
|
|||
// EXPECT_NE(result, nullptr);
|
|||
// });
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_NE(messenger.last_message_handler(), nullptr);
|
|||
// // Send a test message to trigger the handler test assertions.
|
|||
// MethodCall<EncodableValue> call(method_name, nullptr);
|
|||
// auto message = codec.EncodeMethodCall(call);
|
|||
//
|
|||
// messenger.last_message_handler()(
|
|||
// message->data(), message->size(),
|
|||
// [](const uint8_t* reply, const size_t reply_size) {});
|
|||
// EXPECT_EQ(callback_called, true);
|
|||
//}
|
|||
//
|
|||
//// Tests that SetMethodCallHandler with a null handler unregisters the handler.
|
|||
//TEST(MethodChannelTest, Unregistration) {
|
|||
// TestBinaryMessenger messenger;
|
|||
// const std::string channel_name("some_channel");
|
|||
// MethodChannel channel(&messenger, channel_name,
|
|||
// &uiwidgets::StandardMethodCodec::GetInstance());
|
|||
//
|
|||
// channel.SetMethodCallHandler([](const auto& call, auto result) {});
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_NE(messenger.last_message_handler(), nullptr);
|
|||
//
|
|||
// channel.SetMethodCallHandler(nullptr);
|
|||
// EXPECT_EQ(messenger.last_message_handler_channel(), channel_name);
|
|||
// EXPECT_EQ(messenger.last_message_handler(), nullptr);
|
|||
//}
|
|||
//
|
|||
//} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "include/uiwidgets/plugin_registrar.h"
|
|||
|
|||
#include <iostream>
|
|||
#include <map>
|
|||
|
|||
#include "include/uiwidgets/engine_method_result.h"
|
|||
#include "include/uiwidgets/method_channel.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
namespace { |
|||
|
|||
// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
|
|||
// with a BinaryReply that will send a response on |message|'s response handle.
|
|||
//
|
|||
// This serves as an adaptor between the function-pointer-based message callback
|
|||
// interface provided by the C API and the std::function-based message handler
|
|||
// interface of BinaryMessenger.
|
|||
void ForwardToHandler(UIWidgetsDesktopMessengerRef messenger, |
|||
const UIWidgetsDesktopMessage* message, |
|||
void* user_data) { |
|||
auto* response_handle = message->response_handle; |
|||
BinaryReply reply_handler = [messenger, response_handle]( |
|||
const uint8_t* reply, |
|||
const size_t reply_size) mutable { |
|||
if (!response_handle) { |
|||
std::cerr << "Error: Response can be set only once. Ignoring " |
|||
"duplicate response." |
|||
<< std::endl; |
|||
return; |
|||
} |
|||
UIWidgetsDesktopMessengerSendResponse(messenger, response_handle, reply, |
|||
reply_size); |
|||
// The engine frees the response handle once
|
|||
// UIWidgetsDesktopSendMessageResponse is called.
|
|||
response_handle = nullptr; |
|||
}; |
|||
|
|||
const BinaryMessageHandler& message_handler = |
|||
*static_cast<BinaryMessageHandler*>(user_data); |
|||
|
|||
message_handler(message->message, message->message_size, |
|||
std::move(reply_handler)); |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
// Wrapper around a UIWidgetsDesktopMessengerRef that implements the
|
|||
// BinaryMessenger API.
|
|||
class BinaryMessengerImpl : public BinaryMessenger { |
|||
public: |
|||
explicit BinaryMessengerImpl(UIWidgetsDesktopMessengerRef core_messenger) |
|||
: messenger_(core_messenger) {} |
|||
|
|||
virtual ~BinaryMessengerImpl() = default; |
|||
|
|||
// Prevent copying.
|
|||
BinaryMessengerImpl(BinaryMessengerImpl const&) = delete; |
|||
BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete; |
|||
|
|||
// |uiwidgets::BinaryMessenger|
|
|||
void Send(const std::string& channel, |
|||
const uint8_t* message, |
|||
const size_t message_size) const override; |
|||
|
|||
// |uiwidgets::BinaryMessenger|
|
|||
void Send(const std::string& channel, |
|||
const uint8_t* message, |
|||
const size_t message_size, |
|||
BinaryReply reply) const override; |
|||
|
|||
// |uiwidgets::BinaryMessenger|
|
|||
void SetMessageHandler(const std::string& channel, |
|||
BinaryMessageHandler handler) override; |
|||
|
|||
private: |
|||
// Handle for interacting with the C API.
|
|||
UIWidgetsDesktopMessengerRef messenger_; |
|||
|
|||
// A map from channel names to the BinaryMessageHandler that should be called
|
|||
// for incoming messages on that channel.
|
|||
std::map<std::string, BinaryMessageHandler> handlers_; |
|||
}; |
|||
|
|||
void BinaryMessengerImpl::Send(const std::string& channel, |
|||
const uint8_t* message, |
|||
const size_t message_size) const { |
|||
UIWidgetsDesktopMessengerSend(messenger_, channel.c_str(), message, |
|||
message_size); |
|||
} |
|||
|
|||
void BinaryMessengerImpl::Send(const std::string& channel, |
|||
const uint8_t* message, |
|||
const size_t message_size, |
|||
BinaryReply reply) const { |
|||
if (reply == nullptr) { |
|||
UIWidgetsDesktopMessengerSend(messenger_, channel.c_str(), message, |
|||
message_size); |
|||
return; |
|||
} |
|||
struct Captures { |
|||
BinaryReply reply; |
|||
}; |
|||
auto captures = new Captures(); |
|||
captures->reply = reply; |
|||
|
|||
auto message_reply = [](const uint8_t* data, size_t data_size, |
|||
void* user_data) { |
|||
auto captures = reinterpret_cast<Captures*>(user_data); |
|||
captures->reply(data, data_size); |
|||
delete captures; |
|||
}; |
|||
bool result = UIWidgetsDesktopMessengerSendWithReply( |
|||
messenger_, channel.c_str(), message, message_size, message_reply, |
|||
captures); |
|||
if (!result) { |
|||
delete captures; |
|||
} |
|||
} |
|||
|
|||
void BinaryMessengerImpl::SetMessageHandler(const std::string& channel, |
|||
BinaryMessageHandler handler) { |
|||
if (!handler) { |
|||
handlers_.erase(channel); |
|||
UIWidgetsDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr, |
|||
nullptr); |
|||
return; |
|||
} |
|||
// Save the handler, to keep it alive.
|
|||
handlers_[channel] = std::move(handler); |
|||
BinaryMessageHandler* message_handler = &handlers_[channel]; |
|||
// Set an adaptor callback that will invoke the handler.
|
|||
UIWidgetsDesktopMessengerSetCallback(messenger_, channel.c_str(), |
|||
ForwardToHandler, message_handler); |
|||
} |
|||
|
|||
// PluginRegistrar:
|
|||
|
|||
PluginRegistrar::PluginRegistrar(UIWidgetsDesktopPluginRegistrarRef registrar) |
|||
: registrar_(registrar) { |
|||
auto core_messenger = UIWidgetsDesktopRegistrarGetMessenger(registrar_); |
|||
messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger); |
|||
} |
|||
|
|||
PluginRegistrar::~PluginRegistrar() {} |
|||
|
|||
void PluginRegistrar::AddPlugin(std::unique_ptr<Plugin> plugin) { |
|||
plugins_.insert(std::move(plugin)); |
|||
} |
|||
|
|||
void PluginRegistrar::EnableInputBlockingForChannel( |
|||
const std::string& channel) { |
|||
UIWidgetsDesktopRegistrarEnableInputBlocking(registrar_, channel.c_str()); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include <memory>
|
|||
// #include <vector>
|
|||
|
|||
// #include "shell/platform/common/cpp/client_wrapper/include/uiwidgets/plugin_registrar.h"
|
|||
// #include "shell/platform/common/cpp/client_wrapper/testing/stub_uiwidgets_api.h"
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// namespace {
|
|||
|
|||
// // Stub implementation to validate calls to the API.
|
|||
// class TestApi : public testing::StubUIWidgetsApi {
|
|||
// public:
|
|||
// // |uiwidgets::testing::StubUIWidgetsApi|
|
|||
// bool MessengerSend(const char* channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size) override {
|
|||
// last_data_sent_ = message;
|
|||
// return message_engine_result;
|
|||
// }
|
|||
|
|||
// bool MessengerSendWithReply(const char* channel,
|
|||
// const uint8_t* message,
|
|||
// const size_t message_size,
|
|||
// const UIWidgetsDesktopBinaryReply reply,
|
|||
// void* user_data) override {
|
|||
// last_data_sent_ = message;
|
|||
// return message_engine_result;
|
|||
// }
|
|||
|
|||
// // Called for UIWidgetsDesktopMessengerSetCallback.
|
|||
// void MessengerSetCallback(const char* channel,
|
|||
// UIWidgetsDesktopMessageCallback callback,
|
|||
// void* user_data) override {
|
|||
// last_callback_set_ = callback;
|
|||
// }
|
|||
|
|||
// const uint8_t* last_data_sent() { return last_data_sent_; }
|
|||
// UIWidgetsDesktopMessageCallback last_callback_set() {
|
|||
// return last_callback_set_;
|
|||
// }
|
|||
|
|||
// private:
|
|||
// const uint8_t* last_data_sent_ = nullptr;
|
|||
// UIWidgetsDesktopMessageCallback last_callback_set_ = nullptr;
|
|||
// };
|
|||
|
|||
// } // namespace
|
|||
|
|||
// // Tests that the registrar returns a messenger that passes Send through to the
|
|||
// // C API.
|
|||
// TEST(MethodCallTest, MessengerSend) {
|
|||
// testing::ScopedStubUIWidgetsApi scoped_api_stub(std::make_unique<TestApi>());
|
|||
// auto test_api = static_cast<TestApi*>(scoped_api_stub.stub());
|
|||
|
|||
// auto dummy_registrar_handle =
|
|||
// reinterpret_cast<UIWidgetsDesktopPluginRegistrarRef>(1);
|
|||
// PluginRegistrar registrar(dummy_registrar_handle);
|
|||
// BinaryMessenger* messenger = registrar.messenger();
|
|||
|
|||
// std::vector<uint8_t> message = {1, 2, 3, 4};
|
|||
// messenger->Send("some_channel", &message[0], message.size());
|
|||
// EXPECT_EQ(test_api->last_data_sent(), &message[0]);
|
|||
// }
|
|||
|
|||
// // Tests that the registrar returns a messenger that passes callback
|
|||
// // registration and unregistration through to the C API.
|
|||
// TEST(MethodCallTest, MessengerSetMessageHandler) {
|
|||
// testing::ScopedStubUIWidgetsApi scoped_api_stub(std::make_unique<TestApi>());
|
|||
// auto test_api = static_cast<TestApi*>(scoped_api_stub.stub());
|
|||
|
|||
// auto dummy_registrar_handle =
|
|||
// reinterpret_cast<UIWidgetsDesktopPluginRegistrarRef>(1);
|
|||
// PluginRegistrar registrar(dummy_registrar_handle);
|
|||
// BinaryMessenger* messenger = registrar.messenger();
|
|||
// const std::string channel_name("foo");
|
|||
|
|||
// // Register.
|
|||
// BinaryMessageHandler binary_handler = [](const uint8_t* message,
|
|||
// const size_t message_size,
|
|||
// BinaryReply reply) {};
|
|||
// messenger->SetMessageHandler(channel_name, std::move(binary_handler));
|
|||
// EXPECT_NE(test_api->last_callback_set(), nullptr);
|
|||
|
|||
// // Unregister.
|
|||
// messenger->SetMessageHandler(channel_name, nullptr);
|
|||
// EXPECT_EQ(test_api->last_callback_set(), nullptr);
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
// This file contains what would normally be standard_codec_serializer.cc,
|
|||
// standard_message_codec.cc, and standard_method_codec.cc. They are grouped
|
|||
// together to simplify use of the client wrapper, since the common case is
|
|||
// that any client that needs one of these files needs all three.
|
|||
|
|||
#include "include/uiwidgets/standard_message_codec.h"
|
|||
#include "include/uiwidgets/standard_method_codec.h"
|
|||
#include "standard_codec_serializer.h"
|
|||
|
|||
#include <assert.h>
|
|||
#include <cstring>
|
|||
#include <iostream>
|
|||
#include <map>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// ===== standard_codec_serializer.h =====
|
|||
|
|||
namespace { |
|||
|
|||
// The order/values here must match the constants in message_codecs.dart.
|
|||
enum class EncodedType { |
|||
kNull = 0, |
|||
kTrue, |
|||
kFalse, |
|||
kInt32, |
|||
kInt64, |
|||
kLargeInt, // No longer used. If encountered, treat as kString.
|
|||
kFloat64, |
|||
kString, |
|||
kUInt8List, |
|||
kInt32List, |
|||
kInt64List, |
|||
kFloat64List, |
|||
kList, |
|||
kMap, |
|||
}; |
|||
|
|||
// Returns the encoded type that should be written when serializing |value|.
|
|||
EncodedType EncodedTypeForValue(const EncodableValue& value) { |
|||
switch (value.type()) { |
|||
case EncodableValue::Type::kNull: |
|||
return EncodedType::kNull; |
|||
case EncodableValue::Type::kBool: |
|||
return value.BoolValue() ? EncodedType::kTrue : EncodedType::kFalse; |
|||
case EncodableValue::Type::kInt: |
|||
return EncodedType::kInt32; |
|||
case EncodableValue::Type::kLong: |
|||
return EncodedType::kInt64; |
|||
case EncodableValue::Type::kDouble: |
|||
return EncodedType::kFloat64; |
|||
case EncodableValue::Type::kString: |
|||
return EncodedType::kString; |
|||
case EncodableValue::Type::kByteList: |
|||
return EncodedType::kUInt8List; |
|||
case EncodableValue::Type::kIntList: |
|||
return EncodedType::kInt32List; |
|||
case EncodableValue::Type::kLongList: |
|||
return EncodedType::kInt64List; |
|||
case EncodableValue::Type::kDoubleList: |
|||
return EncodedType::kFloat64List; |
|||
case EncodableValue::Type::kList: |
|||
return EncodedType::kList; |
|||
case EncodableValue::Type::kMap: |
|||
return EncodedType::kMap; |
|||
} |
|||
assert(false); |
|||
return EncodedType::kNull; |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
StandardCodecSerializer::StandardCodecSerializer() = default; |
|||
|
|||
StandardCodecSerializer::~StandardCodecSerializer() = default; |
|||
|
|||
EncodableValue StandardCodecSerializer::ReadValue( |
|||
ByteBufferStreamReader* stream) const { |
|||
EncodedType type = static_cast<EncodedType>(stream->ReadByte()); |
|||
; |
|||
switch (type) { |
|||
case EncodedType::kNull: |
|||
return EncodableValue(); |
|||
case EncodedType::kTrue: |
|||
return EncodableValue(true); |
|||
case EncodedType::kFalse: |
|||
return EncodableValue(false); |
|||
case EncodedType::kInt32: { |
|||
int32_t int_value = 0; |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&int_value), 4); |
|||
return EncodableValue(int_value); |
|||
} |
|||
case EncodedType::kInt64: { |
|||
int64_t long_value = 0; |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&long_value), 8); |
|||
return EncodableValue(long_value); |
|||
} |
|||
case EncodedType::kFloat64: { |
|||
double double_value = 0; |
|||
stream->ReadAlignment(8); |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&double_value), 8); |
|||
return EncodableValue(double_value); |
|||
} |
|||
case EncodedType::kLargeInt: |
|||
case EncodedType::kString: { |
|||
size_t size = ReadSize(stream); |
|||
std::string string_value; |
|||
string_value.resize(size); |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&string_value[0]), size); |
|||
return EncodableValue(string_value); |
|||
} |
|||
case EncodedType::kUInt8List: |
|||
return ReadVector<uint8_t>(stream); |
|||
case EncodedType::kInt32List: |
|||
return ReadVector<int32_t>(stream); |
|||
case EncodedType::kInt64List: |
|||
return ReadVector<int64_t>(stream); |
|||
case EncodedType::kFloat64List: |
|||
return ReadVector<double>(stream); |
|||
case EncodedType::kList: { |
|||
size_t length = ReadSize(stream); |
|||
EncodableList list_value; |
|||
list_value.reserve(length); |
|||
for (size_t i = 0; i < length; ++i) { |
|||
list_value.push_back(ReadValue(stream)); |
|||
} |
|||
return EncodableValue(list_value); |
|||
} |
|||
case EncodedType::kMap: { |
|||
size_t length = ReadSize(stream); |
|||
EncodableMap map_value; |
|||
for (size_t i = 0; i < length; ++i) { |
|||
EncodableValue key = ReadValue(stream); |
|||
EncodableValue value = ReadValue(stream); |
|||
map_value.emplace(std::move(key), std::move(value)); |
|||
} |
|||
return EncodableValue(map_value); |
|||
} |
|||
} |
|||
std::cerr << "Unknown type in StandardCodecSerializer::ReadValue: " |
|||
<< static_cast<int>(type) << std::endl; |
|||
return EncodableValue(); |
|||
} |
|||
|
|||
void StandardCodecSerializer::WriteValue(const EncodableValue& value, |
|||
ByteBufferStreamWriter* stream) const { |
|||
stream->WriteByte(static_cast<uint8_t>(EncodedTypeForValue(value))); |
|||
switch (value.type()) { |
|||
case EncodableValue::Type::kNull: |
|||
case EncodableValue::Type::kBool: |
|||
// Null and bool are encoded directly in the type.
|
|||
break; |
|||
case EncodableValue::Type::kInt: { |
|||
int32_t int_value = value.IntValue(); |
|||
stream->WriteBytes(reinterpret_cast<const uint8_t*>(&int_value), 4); |
|||
break; |
|||
} |
|||
case EncodableValue::Type::kLong: { |
|||
int64_t long_value = value.LongValue(); |
|||
stream->WriteBytes(reinterpret_cast<const uint8_t*>(&long_value), 8); |
|||
break; |
|||
} |
|||
case EncodableValue::Type::kDouble: { |
|||
stream->WriteAlignment(8); |
|||
double double_value = value.DoubleValue(); |
|||
stream->WriteBytes(reinterpret_cast<const uint8_t*>(&double_value), 8); |
|||
break; |
|||
} |
|||
case EncodableValue::Type::kString: { |
|||
const auto& string_value = value.StringValue(); |
|||
size_t size = string_value.size(); |
|||
WriteSize(size, stream); |
|||
if (size > 0) { |
|||
stream->WriteBytes( |
|||
reinterpret_cast<const uint8_t*>(string_value.data()), size); |
|||
} |
|||
break; |
|||
} |
|||
case EncodableValue::Type::kByteList: |
|||
WriteVector(value.ByteListValue(), stream); |
|||
break; |
|||
case EncodableValue::Type::kIntList: |
|||
WriteVector(value.IntListValue(), stream); |
|||
break; |
|||
case EncodableValue::Type::kLongList: |
|||
WriteVector(value.LongListValue(), stream); |
|||
break; |
|||
case EncodableValue::Type::kDoubleList: |
|||
WriteVector(value.DoubleListValue(), stream); |
|||
break; |
|||
case EncodableValue::Type::kList: |
|||
WriteSize(value.ListValue().size(), stream); |
|||
for (const auto& item : value.ListValue()) { |
|||
WriteValue(item, stream); |
|||
} |
|||
break; |
|||
case EncodableValue::Type::kMap: |
|||
WriteSize(value.MapValue().size(), stream); |
|||
for (const auto& pair : value.MapValue()) { |
|||
WriteValue(pair.first, stream); |
|||
WriteValue(pair.second, stream); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
|
|||
size_t StandardCodecSerializer::ReadSize(ByteBufferStreamReader* stream) const { |
|||
uint8_t byte = stream->ReadByte(); |
|||
if (byte < 254) { |
|||
return byte; |
|||
} else if (byte == 254) { |
|||
uint16_t value; |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 2); |
|||
return value; |
|||
} else { |
|||
uint32_t value; |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 4); |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
void StandardCodecSerializer::WriteSize(size_t size, |
|||
ByteBufferStreamWriter* stream) const { |
|||
if (size < 254) { |
|||
stream->WriteByte(static_cast<uint8_t>(size)); |
|||
} else if (size <= 0xffff) { |
|||
stream->WriteByte(254); |
|||
uint16_t value = static_cast<uint16_t>(size); |
|||
stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 2); |
|||
} else { |
|||
stream->WriteByte(255); |
|||
uint32_t value = static_cast<uint32_t>(size); |
|||
stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 4); |
|||
} |
|||
} |
|||
|
|||
template <typename T> |
|||
EncodableValue StandardCodecSerializer::ReadVector( |
|||
ByteBufferStreamReader* stream) const { |
|||
size_t count = ReadSize(stream); |
|||
std::vector<T> vector; |
|||
vector.resize(count); |
|||
uint8_t type_size = static_cast<uint8_t>(sizeof(T)); |
|||
if (type_size > 1) { |
|||
stream->ReadAlignment(type_size); |
|||
} |
|||
stream->ReadBytes(reinterpret_cast<uint8_t*>(vector.data()), |
|||
count * type_size); |
|||
return EncodableValue(vector); |
|||
} |
|||
|
|||
template <typename T> |
|||
void StandardCodecSerializer::WriteVector( |
|||
const std::vector<T> vector, |
|||
ByteBufferStreamWriter* stream) const { |
|||
size_t count = vector.size(); |
|||
WriteSize(count, stream); |
|||
if (count == 0) { |
|||
return; |
|||
} |
|||
uint8_t type_size = static_cast<uint8_t>(sizeof(T)); |
|||
if (type_size > 1) { |
|||
stream->WriteAlignment(type_size); |
|||
} |
|||
stream->WriteBytes(reinterpret_cast<const uint8_t*>(vector.data()), |
|||
count * type_size); |
|||
} |
|||
|
|||
// ===== standard_message_codec.h =====
|
|||
|
|||
// static
|
|||
const StandardMessageCodec& StandardMessageCodec::GetInstance() { |
|||
static StandardMessageCodec sInstance; |
|||
return sInstance; |
|||
} |
|||
|
|||
StandardMessageCodec::StandardMessageCodec() = default; |
|||
|
|||
StandardMessageCodec::~StandardMessageCodec() = default; |
|||
|
|||
std::unique_ptr<EncodableValue> StandardMessageCodec::DecodeMessageInternal( |
|||
const uint8_t* binary_message, |
|||
const size_t message_size) const { |
|||
StandardCodecSerializer serializer; |
|||
ByteBufferStreamReader stream(binary_message, message_size); |
|||
return std::make_unique<EncodableValue>(serializer.ReadValue(&stream)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
StandardMessageCodec::EncodeMessageInternal( |
|||
const EncodableValue& message) const { |
|||
StandardCodecSerializer serializer; |
|||
auto encoded = std::make_unique<std::vector<uint8_t>>(); |
|||
ByteBufferStreamWriter stream(encoded.get()); |
|||
serializer.WriteValue(message, &stream); |
|||
return encoded; |
|||
} |
|||
|
|||
// ===== standard_method_codec.h =====
|
|||
|
|||
// static
|
|||
const StandardMethodCodec& StandardMethodCodec::GetInstance() { |
|||
static StandardMethodCodec sInstance; |
|||
return sInstance; |
|||
} |
|||
|
|||
std::unique_ptr<MethodCall<EncodableValue>> |
|||
StandardMethodCodec::DecodeMethodCallInternal(const uint8_t* message, |
|||
const size_t message_size) const { |
|||
StandardCodecSerializer serializer; |
|||
ByteBufferStreamReader stream(message, message_size); |
|||
EncodableValue method_name = serializer.ReadValue(&stream); |
|||
if (!method_name.IsString()) { |
|||
std::cerr << "Invalid method call; method name is not a string." |
|||
<< std::endl; |
|||
return nullptr; |
|||
} |
|||
auto arguments = |
|||
std::make_unique<EncodableValue>(serializer.ReadValue(&stream)); |
|||
return std::make_unique<MethodCall<EncodableValue>>(method_name.StringValue(), |
|||
std::move(arguments)); |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
StandardMethodCodec::EncodeMethodCallInternal( |
|||
const MethodCall<EncodableValue>& method_call) const { |
|||
StandardCodecSerializer serializer; |
|||
auto encoded = std::make_unique<std::vector<uint8_t>>(); |
|||
ByteBufferStreamWriter stream(encoded.get()); |
|||
serializer.WriteValue(EncodableValue(method_call.method_name()), &stream); |
|||
if (method_call.arguments()) { |
|||
serializer.WriteValue(*method_call.arguments(), &stream); |
|||
} else { |
|||
serializer.WriteValue(EncodableValue(), &stream); |
|||
} |
|||
return encoded; |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
StandardMethodCodec::EncodeSuccessEnvelopeInternal( |
|||
const EncodableValue* result) const { |
|||
StandardCodecSerializer serializer; |
|||
auto encoded = std::make_unique<std::vector<uint8_t>>(); |
|||
ByteBufferStreamWriter stream(encoded.get()); |
|||
stream.WriteByte(0); |
|||
if (result) { |
|||
serializer.WriteValue(*result, &stream); |
|||
} else { |
|||
serializer.WriteValue(EncodableValue(), &stream); |
|||
} |
|||
return encoded; |
|||
} |
|||
|
|||
std::unique_ptr<std::vector<uint8_t>> |
|||
StandardMethodCodec::EncodeErrorEnvelopeInternal( |
|||
const std::string& error_code, |
|||
const std::string& error_message, |
|||
const EncodableValue* error_details) const { |
|||
StandardCodecSerializer serializer; |
|||
auto encoded = std::make_unique<std::vector<uint8_t>>(); |
|||
ByteBufferStreamWriter stream(encoded.get()); |
|||
stream.WriteByte(1); |
|||
serializer.WriteValue(EncodableValue(error_code), &stream); |
|||
if (error_message.empty()) { |
|||
serializer.WriteValue(EncodableValue(), &stream); |
|||
} else { |
|||
serializer.WriteValue(EncodableValue(error_message), &stream); |
|||
} |
|||
if (error_details) { |
|||
serializer.WriteValue(*error_details, &stream); |
|||
} else { |
|||
serializer.WriteValue(EncodableValue(), &stream); |
|||
} |
|||
return encoded; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ |
|||
|
|||
#include "byte_stream_wrappers.h" |
|||
#include "include/uiwidgets/encodable_value.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// Encapsulates the logic for encoding/decoding EncodableValues to/from the |
|||
// standard codec binary representation. |
|||
class StandardCodecSerializer { |
|||
public: |
|||
StandardCodecSerializer(); |
|||
~StandardCodecSerializer(); |
|||
|
|||
// Prevent copying. |
|||
StandardCodecSerializer(StandardCodecSerializer const&) = delete; |
|||
StandardCodecSerializer& operator=(StandardCodecSerializer const&) = delete; |
|||
|
|||
// Reads and returns the next value from |stream|. |
|||
EncodableValue ReadValue(ByteBufferStreamReader* stream) const; |
|||
|
|||
// Writes the encoding of |value| to |stream|. |
|||
void WriteValue(const EncodableValue& value, |
|||
ByteBufferStreamWriter* stream) const; |
|||
|
|||
protected: |
|||
// Reads the variable-length size from the current position in |stream|. |
|||
size_t ReadSize(ByteBufferStreamReader* stream) const; |
|||
|
|||
// Writes the variable-length size encoding to |stream|. |
|||
void WriteSize(size_t size, ByteBufferStreamWriter* stream) const; |
|||
|
|||
// Reads a fixed-type list whose values are of type T from the current |
|||
// position in |stream|, and returns it as the corresponding EncodableValue. |
|||
// |T| must correspond to one of the support list value types of |
|||
// EncodableValue. |
|||
template <typename T> |
|||
EncodableValue ReadVector(ByteBufferStreamReader* stream) const; |
|||
|
|||
// Writes |vector| to |stream| as a fixed-type list. |T| must correspond to |
|||
// one of the support list value types of EncodableValue. |
|||
template <typename T> |
|||
void WriteVector(const std::vector<T> vector, |
|||
ByteBufferStreamWriter* stream) const; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ |
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_message_codec.h"
|
|||
|
|||
// #include <map>
|
|||
// #include <vector>
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/testing/encodable_value_utils.h"
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// // Validates round-trip encoding and decoding of |value|, and checks that the
|
|||
// // encoded value matches |expected_encoding|.
|
|||
// static void CheckEncodeDecode(const EncodableValue& value,
|
|||
// const std::vector<uint8_t>& expected_encoding) {
|
|||
// const StandardMessageCodec& codec = StandardMessageCodec::GetInstance();
|
|||
// auto encoded = codec.EncodeMessage(value);
|
|||
// ASSERT_TRUE(encoded);
|
|||
// EXPECT_EQ(*encoded, expected_encoding);
|
|||
|
|||
// auto decoded = codec.DecodeMessage(*encoded);
|
|||
// EXPECT_TRUE(testing::EncodableValuesAreEqual(value, *decoded));
|
|||
// }
|
|||
|
|||
// // Validates round-trip encoding and decoding of |value|, and checks that the
|
|||
// // encoded value has the given prefix and length.
|
|||
// //
|
|||
// // This should be used only for Map, where asserting the order of the elements
|
|||
// // in a test is undesirable.
|
|||
// static void CheckEncodeDecodeWithEncodePrefix(
|
|||
// const EncodableValue& value,
|
|||
// const std::vector<uint8_t>& expected_encoding_prefix,
|
|||
// size_t expected_encoding_length) {
|
|||
// EXPECT_TRUE(value.IsMap());
|
|||
// const StandardMessageCodec& codec = StandardMessageCodec::GetInstance();
|
|||
// auto encoded = codec.EncodeMessage(value);
|
|||
// ASSERT_TRUE(encoded);
|
|||
|
|||
// EXPECT_EQ(encoded->size(), expected_encoding_length);
|
|||
// ASSERT_GT(encoded->size(), expected_encoding_prefix.size());
|
|||
// EXPECT_TRUE(std::equal(
|
|||
// encoded->begin(), encoded->begin() + expected_encoding_prefix.size(),
|
|||
// expected_encoding_prefix.begin(), expected_encoding_prefix.end()));
|
|||
|
|||
// auto decoded = codec.DecodeMessage(*encoded);
|
|||
// EXPECT_TRUE(testing::EncodableValuesAreEqual(value, *decoded));
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeNull) {
|
|||
// std::vector<uint8_t> bytes = {0x00};
|
|||
// CheckEncodeDecode(EncodableValue(), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeTrue) {
|
|||
// std::vector<uint8_t> bytes = {0x01};
|
|||
// CheckEncodeDecode(EncodableValue(true), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeFalse) {
|
|||
// std::vector<uint8_t> bytes = {0x02};
|
|||
// CheckEncodeDecode(EncodableValue(false), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeInt32) {
|
|||
// std::vector<uint8_t> bytes = {0x03, 0x78, 0x56, 0x34, 0x12};
|
|||
// CheckEncodeDecode(EncodableValue(0x12345678), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeInt64) {
|
|||
// std::vector<uint8_t> bytes = {0x04, 0xef, 0xcd, 0xab, 0x90,
|
|||
// 0x78, 0x56, 0x34, 0x12};
|
|||
// CheckEncodeDecode(EncodableValue(INT64_C(0x1234567890abcdef)), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeDouble) {
|
|||
// std::vector<uint8_t> bytes = {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
// 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40};
|
|||
// CheckEncodeDecode(EncodableValue(3.14159265358979311599796346854), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeString) {
|
|||
// std::vector<uint8_t> bytes = {0x07, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
|
|||
// 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64};
|
|||
// CheckEncodeDecode(EncodableValue(u8"hello world"), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeStringWithNonAsciiCodePoint) {
|
|||
// std::vector<uint8_t> bytes = {0x07, 0x05, 0x68, 0xe2, 0x98, 0xba, 0x77};
|
|||
// CheckEncodeDecode(EncodableValue(u8"h\u263Aw"), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeStringWithNonBMPCodePoint) {
|
|||
// std::vector<uint8_t> bytes = {0x07, 0x06, 0x68, 0xf0, 0x9f, 0x98, 0x82, 0x77};
|
|||
// CheckEncodeDecode(EncodableValue(u8"h\U0001F602w"), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeEmptyString) {
|
|||
// std::vector<uint8_t> bytes = {0x07, 0x00};
|
|||
// CheckEncodeDecode(EncodableValue(u8""), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeList) {
|
|||
// std::vector<uint8_t> bytes = {
|
|||
// 0x0c, 0x05, 0x00, 0x07, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x06,
|
|||
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x51, 0xb8, 0x1e,
|
|||
// 0x09, 0x40, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x03, 0x2a,
|
|||
// 0x00, 0x00, 0x00, 0x07, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64,
|
|||
// };
|
|||
// EncodableValue value(EncodableList{
|
|||
// EncodableValue(),
|
|||
// EncodableValue("hello"),
|
|||
// EncodableValue(3.14),
|
|||
// EncodableValue(47),
|
|||
// EncodableValue(EncodableList{
|
|||
// EncodableValue(42),
|
|||
// EncodableValue("nested"),
|
|||
// }),
|
|||
// });
|
|||
// CheckEncodeDecode(value, bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeEmptyList) {
|
|||
// std::vector<uint8_t> bytes = {0x0c, 0x00};
|
|||
// CheckEncodeDecode(EncodableValue(EncodableList{}), bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeMap) {
|
|||
// std::vector<uint8_t> bytes_prefix = {0x0d, 0x04};
|
|||
// EncodableValue value(EncodableMap{
|
|||
// {EncodableValue("a"), EncodableValue(3.14)},
|
|||
// {EncodableValue("b"), EncodableValue(47)},
|
|||
// {EncodableValue(), EncodableValue()},
|
|||
// {EncodableValue(3.14), EncodableValue(EncodableList{
|
|||
// EncodableValue("nested"),
|
|||
// })},
|
|||
// });
|
|||
// CheckEncodeDecodeWithEncodePrefix(value, bytes_prefix, 48);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeByteArray) {
|
|||
// std::vector<uint8_t> bytes = {0x08, 0x04, 0xba, 0x5e, 0xba, 0x11};
|
|||
// EncodableValue value(std::vector<uint8_t>{0xba, 0x5e, 0xba, 0x11});
|
|||
// CheckEncodeDecode(value, bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeInt32Array) {
|
|||
// std::vector<uint8_t> bytes = {0x09, 0x03, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
|
|||
// 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
|
|||
// EncodableValue value(std::vector<int32_t>{0x12345678, -1, 0});
|
|||
// CheckEncodeDecode(value, bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeInt64Array) {
|
|||
// std::vector<uint8_t> bytes = {0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
// 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12,
|
|||
// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|||
// EncodableValue value(std::vector<int64_t>{0x1234567890abcdef, -1});
|
|||
// CheckEncodeDecode(value, bytes);
|
|||
// }
|
|||
|
|||
// TEST(StandardMessageCodec, CanEncodeAndDecodeFloat64Array) {
|
|||
// std::vector<uint8_t> bytes = {0x0b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
// 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40,
|
|||
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40};
|
|||
// EncodableValue value(
|
|||
// std::vector<double>{3.14159265358979311599796346854, 1000.0});
|
|||
// CheckEncodeDecode(value, bytes);
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
// // Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// // Use of this source code is governed by a BSD-style license that can be
|
|||
// // found in the LICENSE file.
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/include/uiwidgets/standard_method_codec.h"
|
|||
|
|||
// #include "uiwidgets/shell/platform/common/cpp/client_wrapper/testing/encodable_value_utils.h"
|
|||
// #include "gtest/gtest.h"
|
|||
|
|||
// namespace uiwidgets {
|
|||
|
|||
// namespace {
|
|||
|
|||
// // Returns true if the given method calls have the same method name, and their
|
|||
// // arguments have equivalent values.
|
|||
// bool MethodCallsAreEqual(const MethodCall<EncodableValue>& a,
|
|||
// const MethodCall<EncodableValue>& b) {
|
|||
// if (a.method_name() != b.method_name()) {
|
|||
// return false;
|
|||
// }
|
|||
// // Treat nullptr and Null as equivalent.
|
|||
// if ((!a.arguments() || a.arguments()->IsNull()) &&
|
|||
// (!b.arguments() || b.arguments()->IsNull())) {
|
|||
// return true;
|
|||
// }
|
|||
// return testing::EncodableValuesAreEqual(*a.arguments(), *b.arguments());
|
|||
// }
|
|||
|
|||
// } // namespace
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesMethodCallsWithNullArguments) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// MethodCall<EncodableValue> call("hello", nullptr);
|
|||
// auto encoded = codec.EncodeMethodCall(call);
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::unique_ptr<MethodCall<EncodableValue>> decoded =
|
|||
// codec.DecodeMethodCall(*encoded);
|
|||
// ASSERT_NE(decoded.get(), nullptr);
|
|||
// EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
|
|||
// }
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesMethodCallsWithArgument) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// MethodCall<EncodableValue> call(
|
|||
// "hello", std::make_unique<EncodableValue>(EncodableList{
|
|||
// EncodableValue(42),
|
|||
// EncodableValue("world"),
|
|||
// }));
|
|||
// auto encoded = codec.EncodeMethodCall(call);
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::unique_ptr<MethodCall<EncodableValue>> decoded =
|
|||
// codec.DecodeMethodCall(*encoded);
|
|||
// ASSERT_NE(decoded.get(), nullptr);
|
|||
// EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
|
|||
// }
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithNullResult) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// auto encoded = codec.EncodeSuccessEnvelope();
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::vector<uint8_t> bytes = {0x00, 0x00};
|
|||
// EXPECT_EQ(*encoded, bytes);
|
|||
// // TODO: Add round-trip check once decoding replies is implemented.
|
|||
// }
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithResult) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// EncodableValue result(42);
|
|||
// auto encoded = codec.EncodeSuccessEnvelope(&result);
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::vector<uint8_t> bytes = {0x00, 0x03, 0x2a, 0x00, 0x00, 0x00};
|
|||
// EXPECT_EQ(*encoded, bytes);
|
|||
// // TODO: Add round-trip check once decoding replies is implemented.
|
|||
// }
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesErrorEnvelopesWithNulls) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// auto encoded = codec.EncodeErrorEnvelope("errorCode");
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::vector<uint8_t> bytes = {0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f,
|
|||
// 0x72, 0x43, 0x6f, 0x64, 0x65, 0x00, 0x00};
|
|||
// EXPECT_EQ(*encoded, bytes);
|
|||
// // TODO: Add round-trip check once decoding replies is implemented.
|
|||
// }
|
|||
|
|||
// TEST(StandardMethodCodec, HandlesErrorEnvelopesWithDetails) {
|
|||
// const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
|
|||
// EncodableValue details(EncodableList{
|
|||
// EncodableValue("a"),
|
|||
// EncodableValue(42),
|
|||
// });
|
|||
// auto encoded =
|
|||
// codec.EncodeErrorEnvelope("errorCode", "something failed", &details);
|
|||
// ASSERT_NE(encoded.get(), nullptr);
|
|||
// std::vector<uint8_t> bytes = {
|
|||
// 0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f,
|
|||
// 0x64, 0x65, 0x07, 0x10, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
|
|||
// 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
|
|||
// 0x0c, 0x02, 0x07, 0x01, 0x61, 0x03, 0x2a, 0x00, 0x00, 0x00,
|
|||
// };
|
|||
// EXPECT_EQ(*encoded, bytes);
|
|||
// // TODO: Add round-trip check once decoding replies is implemented.
|
|||
// }
|
|||
|
|||
// } // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "shell/platform/common/cpp/incoming_message_dispatcher.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
IncomingMessageDispatcher::IncomingMessageDispatcher( |
|||
UIWidgetsDesktopMessengerRef messenger) |
|||
: messenger_(messenger) {} |
|||
|
|||
IncomingMessageDispatcher::~IncomingMessageDispatcher() = default; |
|||
|
|||
/// @note Procedure doesn't copy all closures.
|
|||
void IncomingMessageDispatcher::HandleMessage( |
|||
const UIWidgetsDesktopMessage& message, |
|||
const std::function<void(void)>& input_block_cb, |
|||
const std::function<void(void)>& input_unblock_cb) { |
|||
std::string channel(message.channel); |
|||
|
|||
// Find the handler for the channel; if there isn't one, report the failure.
|
|||
if (callbacks_.find(channel) == callbacks_.end()) { |
|||
UIWidgetsDesktopMessengerSendResponse(messenger_, message.response_handle, |
|||
nullptr, 0); |
|||
return; |
|||
} |
|||
auto& callback_info = callbacks_[channel]; |
|||
UIWidgetsDesktopMessageCallback message_callback = callback_info.first; |
|||
|
|||
// Process the call, handling input blocking if requested.
|
|||
bool block_input = input_blocking_channels_.count(channel) > 0; |
|||
if (block_input) { |
|||
input_block_cb(); |
|||
} |
|||
message_callback(messenger_, &message, callback_info.second); |
|||
if (block_input) { |
|||
input_unblock_cb(); |
|||
} |
|||
} |
|||
|
|||
void IncomingMessageDispatcher::SetMessageCallback( |
|||
const std::string& channel, |
|||
UIWidgetsDesktopMessageCallback callback, |
|||
void* user_data) { |
|||
if (!callback) { |
|||
callbacks_.erase(channel); |
|||
return; |
|||
} |
|||
callbacks_[channel] = std::make_pair(callback, user_data); |
|||
} |
|||
|
|||
void IncomingMessageDispatcher::EnableInputBlockingForChannel( |
|||
const std::string& channel) { |
|||
input_blocking_channels_.insert(channel); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ |
|||
|
|||
#include <functional> |
|||
#include <map> |
|||
#include <set> |
|||
#include <string> |
|||
#include <utility> |
|||
|
|||
#include "shell/platform/common/cpp/public/uiwidgets_messenger.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// Manages per-channel registration of callbacks for handling messages from the |
|||
// UIWidgets engine, and dispatching incoming messages to those handlers. |
|||
class IncomingMessageDispatcher { |
|||
public: |
|||
// Creates a new IncomingMessageDispatcher. |messenger| must remain valid as |
|||
// long as this object exists. |
|||
explicit IncomingMessageDispatcher(UIWidgetsDesktopMessengerRef messenger); |
|||
|
|||
virtual ~IncomingMessageDispatcher(); |
|||
|
|||
// Prevent copying. |
|||
IncomingMessageDispatcher(IncomingMessageDispatcher const&) = delete; |
|||
IncomingMessageDispatcher& operator=(IncomingMessageDispatcher const&) = |
|||
delete; |
|||
|
|||
// Routes |message| to to the registered handler for its channel, if any. |
|||
// |
|||
// If input blocking has been enabled on that channel, wraps the call to the |
|||
// handler with calls to the given callbacks to block and then unblock input. |
|||
// |
|||
// If no handler is registered for the message's channel, sends a |
|||
// NotImplemented response to the engine. |
|||
void HandleMessage( |
|||
const UIWidgetsDesktopMessage& message, |
|||
const std::function<void(void)>& input_block_cb = [] {}, |
|||
const std::function<void(void)>& input_unblock_cb = [] {}); |
|||
|
|||
// Registers a message callback for incoming messages from the UIWidgets |
|||
// side on the specified channel. |callback| will be called with the message |
|||
// and |user_data| any time a message arrives on that channel. |
|||
// |
|||
// Replaces any existing callback. Pass a null callback to unregister the |
|||
// existing callback. |
|||
void SetMessageCallback(const std::string& channel, |
|||
UIWidgetsDesktopMessageCallback callback, |
|||
void* user_data); |
|||
|
|||
// Enables input blocking on the given channel name. |
|||
// |
|||
// If set, then the parent window should disable input callbacks |
|||
// while waiting for the handler for messages on that channel to run. |
|||
void EnableInputBlockingForChannel(const std::string& channel); |
|||
|
|||
private: |
|||
// Handle for interacting with the C messaging API. |
|||
UIWidgetsDesktopMessengerRef messenger_; |
|||
|
|||
// A map from channel names to the UIWidgetsDesktopMessageCallback that should |
|||
// be called for incoming messages on that channel, along with the void* user |
|||
// data to pass to it. |
|||
std::map<std::string, std::pair<UIWidgetsDesktopMessageCallback, void*>> |
|||
callbacks_; |
|||
|
|||
// Channel names for which input blocking should be enabled during the call to |
|||
// that channel's handler. |
|||
std::set<std::string> input_blocking_channels_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_EXPORT_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_EXPORT_H_ |
|||
|
|||
#ifdef UIWIDGETS_DESKTOP_LIBRARY |
|||
|
|||
#ifdef _WIN32 |
|||
#define UIWIDGETS_EXPORT __declspec(dllexport) |
|||
#else |
|||
#define UIWIDGETS_EXPORT __attribute__((visibility("default"))) |
|||
#endif |
|||
|
|||
#else |
|||
|
|||
#ifdef _WIN32 |
|||
#define UIWIDGETS_EXPORT __declspec(dllimport) |
|||
#else |
|||
#define UIWIDGETS_EXPORT |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_MESSENGER_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_MESSENGER_H_ |
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
|
|||
#include "uiwidgets_export.h" |
|||
|
|||
#if defined(__cplusplus) |
|||
extern "C" { |
|||
#endif |
|||
|
|||
typedef struct UIWidgetsDesktopMessenger* UIWidgetsDesktopMessengerRef; |
|||
|
|||
typedef struct _UIWidgetsPlatformMessageResponseHandle |
|||
UIWidgetsDesktopMessageResponseHandle; |
|||
|
|||
typedef void (*UIWidgetsDesktopBinaryReply)(const uint8_t* data, size_t data_size, |
|||
void* user_data); |
|||
|
|||
typedef struct { |
|||
size_t struct_size; |
|||
|
|||
const char* channel; |
|||
|
|||
const uint8_t* message; |
|||
|
|||
size_t message_size; |
|||
|
|||
const UIWidgetsDesktopMessageResponseHandle* response_handle; |
|||
} UIWidgetsDesktopMessage; |
|||
|
|||
typedef void (*UIWidgetsDesktopMessageCallback)( |
|||
UIWidgetsDesktopMessengerRef /* messenger */, |
|||
const UIWidgetsDesktopMessage* /* message*/, void* /* user data */); |
|||
|
|||
UIWIDGETS_EXPORT bool UIWidgetsDesktopMessengerSend( |
|||
UIWidgetsDesktopMessengerRef messenger, const char* channel, |
|||
const uint8_t* message, const size_t message_size); |
|||
|
|||
UIWIDGETS_EXPORT bool UIWidgetsDesktopMessengerSendWithReply( |
|||
UIWidgetsDesktopMessengerRef messenger, const char* channel, |
|||
const uint8_t* message, const size_t message_size, |
|||
const UIWidgetsDesktopBinaryReply reply, void* user_data); |
|||
|
|||
UIWIDGETS_EXPORT void UIWidgetsDesktopMessengerSendResponse( |
|||
UIWidgetsDesktopMessengerRef messenger, |
|||
const UIWidgetsDesktopMessageResponseHandle* handle, const uint8_t* data, |
|||
size_t data_length); |
|||
|
|||
UIWIDGETS_EXPORT void UIWidgetsDesktopMessengerSetCallback( |
|||
UIWidgetsDesktopMessengerRef messenger, const char* channel, |
|||
UIWidgetsDesktopMessageCallback callback, void* user_data); |
|||
|
|||
#if defined(__cplusplus) |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|
|||
|
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_PLUGIN_REGISTRAR_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_COMMON_CPP_PUBLIC_UIWIDGETS_PLUGIN_REGISTRAR_H_ |
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
|
|||
#include "uiwidgets_export.h" |
|||
#include "uiwidgets_messenger.h" |
|||
|
|||
#if defined(__cplusplus) |
|||
extern "C" { |
|||
#endif |
|||
|
|||
typedef struct UIWidgetsDesktopPluginRegistrar* UIWidgetsDesktopPluginRegistrarRef; |
|||
|
|||
UIWIDGETS_EXPORT UIWidgetsDesktopMessengerRef |
|||
UIWidgetsDesktopRegistrarGetMessenger(UIWidgetsDesktopPluginRegistrarRef registrar); |
|||
|
|||
UIWIDGETS_EXPORT void UIWidgetsDesktopRegistrarEnableInputBlocking( |
|||
UIWidgetsDesktopPluginRegistrarRef registrar, const char* channel); |
|||
|
|||
#if defined(__cplusplus) |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|
|||
// Copyright 2013 The UIWidgets Authors. All rights reserved. |
|||
// Use of this source code is governed by a BSD-style license that can be |
|||
// found in the LICENSE file. |
|||
|
|||
#ifndef UIWIDGETS_SHELL_PLATFORM_WINDOWS_PUBLIC_UIWIDGETS_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_WINDOWS_PUBLIC_UIWIDGETS_H_ |
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
#include "shell/platform/common/cpp/public/uiwidgets_export.h" |
|||
#include "shell/platform/common/cpp/public/uiwidgets_messenger.h" |
|||
#include "shell/platform/common/cpp/public/uiwidgets_plugin_registrar.h" |
|||
|
|||
#include "Windows.h" |
|||
|
|||
#if defined(__cplusplus) |
|||
extern "C" { |
|||
#endif |
|||
|
|||
// Opaque reference to a UIWidgets window controller. |
|||
typedef struct UIWidgetsDesktopViewControllerState* |
|||
UIWidgetsDesktopViewControllerRef; |
|||
|
|||
// Opaque reference to a UIWidgets window. |
|||
typedef struct UIWidgetsDesktopView* UIWidgetsDesktopViewRef; |
|||
|
|||
// Opaque reference to a UIWidgets engine instance. |
|||
typedef struct UIWidgetsDesktopEngineState* UIWidgetsDesktopEngineRef; |
|||
|
|||
// Properties for configuring a UIWidgets engine instance. |
|||
typedef struct { |
|||
// The path to the uiwidgets_assets folder for the application to be run. |
|||
// This can either be an absolute path or a path relative to the directory |
|||
// containing the executable. |
|||
const wchar_t* assets_path; |
|||
|
|||
// The path to the icudtl.dat file for the version of UIWidgets you are using. |
|||
// This can either be an absolute path or a path relative to the directory |
|||
// containing the executable. |
|||
const wchar_t* icu_data_path; |
|||
|
|||
// The switches to pass to the UIWidgets engine. |
|||
// |
|||
// See: https://github.com/uiwidgets/engine/blob/master/shell/common/switches.h |
|||
// for details. Not all arguments will apply to desktop. |
|||
const char** switches; |
|||
|
|||
// The number of elements in |switches|. |
|||
size_t switches_count; |
|||
} UIWidgetsDesktopEngineProperties; |
|||
|
|||
// Creates a View with the given dimensions running a UIWidgets Application. |
|||
// |
|||
// This will set up and run an associated UIWidgets engine using the settings in |
|||
// |engine_properties|. |
|||
// |
|||
// Returns a null pointer in the event of an error. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopViewControllerRef |
|||
UIWidgetsDesktopCreateViewController( |
|||
int width, |
|||
int height, |
|||
const UIWidgetsDesktopEngineProperties& engine_properties); |
|||
|
|||
// DEPRECATED. Will be removed soon; switch to the version above. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopViewControllerRef |
|||
UIWidgetsDesktopCreateViewControllerLegacy(int initial_width, |
|||
int initial_height, |
|||
const char* assets_path, |
|||
const char* icu_data_path, |
|||
const char** arguments, |
|||
size_t argument_count); |
|||
|
|||
// Shuts down the engine instance associated with |controller|, and cleans up |
|||
// associated state. |
|||
// |
|||
// |controller| is no longer valid after this call. |
|||
UIWIDGETS_EXPORT void UIWidgetsDesktopDestroyViewController( |
|||
UIWidgetsDesktopViewControllerRef controller); |
|||
|
|||
// Returns the plugin registrar handle for the plugin with the given name. |
|||
// |
|||
// The name must be unique across the application. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopPluginRegistrarRef |
|||
UIWidgetsDesktopGetPluginRegistrar(UIWidgetsDesktopViewControllerRef controller, |
|||
const char* plugin_name); |
|||
|
|||
// Returns the view managed by the given controller. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopViewRef |
|||
UIWidgetsDesktopGetView(UIWidgetsDesktopViewControllerRef controller); |
|||
|
|||
// Processes any pending events in the UIWidgets engine, and returns the |
|||
// number of nanoseconds until the next scheduled event (or max, if none). |
|||
// |
|||
// This should be called on every run of the application-level runloop, and |
|||
// a wait for native events in the runloop should never be longer than the |
|||
// last return value from this function. |
|||
UIWIDGETS_EXPORT uint64_t |
|||
UIWidgetsDesktopProcessMessages(UIWidgetsDesktopViewControllerRef controller); |
|||
|
|||
// Return backing HWND for manipulation in host application. |
|||
UIWIDGETS_EXPORT HWND UIWidgetsDesktopViewGetHWND(UIWidgetsDesktopViewRef view); |
|||
|
|||
// Gets the DPI for a given |hwnd|, depending on the supported APIs per |
|||
// windows version and DPI awareness mode. If nullptr is passed, returns the DPI |
|||
// of the primary monitor. |
|||
UIWIDGETS_EXPORT UINT UIWidgetsDesktopGetDpiForHWND(HWND hwnd); |
|||
|
|||
// Gets the DPI for a given |monitor|. If the API is not available, a default |
|||
// DPI of 96 is returned. |
|||
UIWIDGETS_EXPORT UINT UIWidgetsDesktopGetDpiForMonitor(HMONITOR monitor); |
|||
|
|||
// Runs an instance of a headless UIWidgets engine. |
|||
// |
|||
// Returns a null pointer in the event of an error. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopEngineRef UIWidgetsDesktopRunEngine( |
|||
const UIWidgetsDesktopEngineProperties& engine_properties); |
|||
|
|||
// Shuts down the given engine instance. Returns true if the shutdown was |
|||
// successful. |engine_ref| is no longer valid after this call. |
|||
UIWIDGETS_EXPORT bool UIWidgetsDesktopShutDownEngine( |
|||
UIWidgetsDesktopEngineRef engine_ref); |
|||
|
|||
// Returns the view associated with this registrar's engine instance |
|||
// This is a Windows-specific extension to uiwidgets_plugin_registrar.h. |
|||
UIWIDGETS_EXPORT UIWidgetsDesktopViewRef |
|||
UIWidgetsDesktopRegistrarGetView(UIWidgetsDesktopPluginRegistrarRef registrar); |
|||
|
|||
#if defined(__cplusplus) |
|||
} // extern "C" |
|||
#endif |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_WINDOWS_PUBLIC_UIWIDGETS_WINDOWS_H_ |
撰写
预览
正在加载...
取消
保存
Reference in new issue