summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kutsan (GitHub) <akutsan@luxoft.com>2020-02-27 17:36:08 +0200
committerGitHub <noreply@github.com>2020-02-27 10:36:08 -0500
commitf416c47429dd9a495c15ea6d078ea30ee2971b4a (patch)
treede72bb92b2c6ce2a89600b26555ea76a7a861052
parentd5994e8111f2fe46d8735ef2680d4235dada807f (diff)
downloadsdl_core-f416c47429dd9a495c15ea6d078ea30ee2971b4a.tar.gz
Feature/Web Engine support (#3221)
* Add ini file parameters for WebEngineSupport Issue : #3197 * Add Server WebSocket transport * Policy changes for Web Engine support Issue : #3197 * Changes in HMI_API for WebEngineSupport Issue : #3197 * Add application manager implementation for WebEngineSupport Add appropriate commands Make changes in application manager Issue : #3197 * Bug fix : Do not override message params if request setups it * Update SDD * fixup! Add application manager implementation for WebEngineSupport * fixup! Add Server WebSocket transport * Rename websocket dir to websocket_server * Rename WebSocketTransport adapter to WebSocketServerTransportAdapter * fixup! Update SDD * Fix/update app list after unregistration (#3252) * fixup! Rename WebSocketTransport adapter to WebSocketServerTransportAdapter * fixup! Rename websocket dir to websocket_server * Don't remove enabled WebEngine apps from pending apps * Rework WebEngine device ID generation * Fix build after back merge * Fix get app properties (#3258) Co-authored-by: Maksym Ked (GitHub) <41471947+mked-luxoft@users.noreply.github.com> * Remove unused vin_code variable Co-authored-by: Maksym Ked (GitHub) <41471947+mked-luxoft@users.noreply.github.com> Co-authored-by: Andriy Byzhynar (GitHub) <AByzhynar@luxoft.com> Co-authored-by: Ira Lytvynenko (GitHub) <ILytvynenko@luxoft.com> Co-authored-by: Andrii Kalinich (GitHub) <AKalinich@luxoft.com>
-rw-r--r--CMakeLists.txt13
-rw-r--r--Doxyfile3
-rw-r--r--src/appMain/smartDeviceLink.ini9
-rw-r--r--src/components/application_manager/include/application_manager/application_manager_impl.h8
-rw-r--r--src/components/application_manager/include/application_manager/message_helper.h9
-rw-r--r--src/components/application_manager/include/application_manager/policies/policy_handler.h49
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h80
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h78
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h77
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h78
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h79
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_request.cc144
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_response.cc60
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_request.cc114
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_response.cc62
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_app_properties_change_notification.cc59
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc37
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc23
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/hmi_command_factory.cc19
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_request_test.cc367
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_response_test.cc66
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_request_test.cc304
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_response_test.cc66
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/on_app_properties_change_notification_test.cc92
-rw-r--r--src/components/application_manager/src/application_manager_impl.cc250
-rw-r--r--src/components/application_manager/src/commands/request_from_hmi.cc5
-rw-r--r--src/components/application_manager/src/message_helper/message_helper.cc57
-rw-r--r--src/components/application_manager/src/policies/policy_handler.cc239
-rw-r--r--src/components/application_manager/test/application_manager_impl_test.cc158
-rw-r--r--src/components/application_manager/test/include/application_manager/commands/commands_test.h15
-rw-r--r--src/components/application_manager/test/include/application_manager/mock_message_helper.h3
-rw-r--r--[-rwxr-xr-x]src/components/application_manager/test/mock_message_helper.cc7
-rw-r--r--src/components/application_manager/test/policy_handler_test.cc416
-rw-r--r--src/components/config_profile/include/config_profile/profile.h44
-rw-r--r--src/components/config_profile/src/profile.cc95
-rw-r--r--src/components/connection_handler/include/connection_handler/connection_handler_impl.h6
-rw-r--r--src/components/connection_handler/src/connection_handler_impl.cc106
-rw-r--r--src/components/include/application_manager/application_manager.h21
-rw-r--r--src/components/include/application_manager/policies/policy_handler_interface.h92
-rw-r--r--src/components/include/connection_handler/connection_handler.h13
-rw-r--r--src/components/include/connection_handler/connection_handler_observer.h5
-rw-r--r--src/components/include/policy/policy_external/policy/policy_listener.h8
-rw-r--r--src/components/include/policy/policy_external/policy/policy_manager.h61
-rw-r--r--src/components/include/policy/policy_regular/policy/policy_listener.h7
-rw-r--r--src/components/include/policy/policy_regular/policy/policy_manager.h63
-rw-r--r--src/components/include/test/application_manager/mock_application_manager.h6
-rw-r--r--src/components/include/test/application_manager/policies/mock_policy_handler_interface.h22
-rw-r--r--src/components/include/test/connection_handler/mock_connection_handler.h2
-rw-r--r--src/components/include/test/connection_handler/mock_connection_handler_observer.h1
-rw-r--r--src/components/include/test/policy/policy_external/policy/mock_cache_manager.h10
-rw-r--r--src/components/include/test/policy/policy_external/policy/mock_policy_listener.h2
-rw-r--r--src/components/include/test/policy/policy_external/policy/mock_policy_manager.h14
-rw-r--r--src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h10
-rw-r--r--src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h2
-rw-r--r--src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h14
-rw-r--r--src/components/include/test/transport_manager/mock_transport_manager.h2
-rw-r--r--src/components/include/test/transport_manager/mock_transport_manager_settings.h6
-rw-r--r--src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h4
-rw-r--r--src/components/include/transport_manager/common.h5
-rw-r--r--src/components/include/transport_manager/transport_adapter/transport_adapter.h11
-rw-r--r--src/components/include/transport_manager/transport_manager.h12
-rw-r--r--src/components/include/transport_manager/transport_manager_settings.h17
-rw-r--r--src/components/interfaces/HMI_API.xml103
-rw-r--r--src/components/policy/policy_external/include/policy/cache_manager.h34
-rw-r--r--src/components/policy/policy_external/include/policy/cache_manager_interface.h36
-rw-r--r--src/components/policy/policy_external/include/policy/policy_helper.h4
-rw-r--r--src/components/policy/policy_external/include/policy/policy_manager_impl.h46
-rw-r--r--src/components/policy/policy_external/include/policy/policy_types.h70
-rw-r--r--src/components/policy/policy_external/src/cache_manager.cc60
-rw-r--r--src/components/policy/policy_external/src/policy_helper.cc78
-rw-r--r--src/components/policy/policy_external/src/policy_manager_impl.cc59
-rw-r--r--src/components/policy/policy_external/test/policy_manager_impl_ptu_test.cc17
-rw-r--r--src/components/policy/policy_external/test/policy_manager_impl_test_base.cc4
-rw-r--r--src/components/policy/policy_regular/include/policy/cache_manager.h31
-rw-r--r--src/components/policy/policy_regular/include/policy/cache_manager_interface.h36
-rw-r--r--src/components/policy/policy_regular/include/policy/policy_helper.h4
-rw-r--r--src/components/policy/policy_regular/include/policy/policy_manager_impl.h50
-rw-r--r--src/components/policy/policy_regular/include/policy/policy_types.h72
-rw-r--r--src/components/policy/policy_regular/src/cache_manager.cc60
-rw-r--r--src/components/policy/policy_regular/src/policy_helper.cc78
-rw-r--r--src/components/policy/policy_regular/src/policy_manager_impl.cc60
-rw-r--r--src/components/policy/policy_regular/test/policy_manager_impl_test.cc6
-rw-r--r--src/components/transport_manager/CMakeLists.txt12
-rw-r--r--src/components/transport_manager/docs/SDL.SDD.WebEngineSupport.dox127
-rw-r--r--src/components/transport_manager/docs/assets/WES_classes.pngbin0 -> 55856 bytes
-rw-r--r--src/components/transport_manager/docs/assets/WES_sequence.pngbin0 -> 77759 bytes
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h2
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h13
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_manager_default.h4
-rw-r--r--src/components/transport_manager/include/transport_manager/transport_manager_impl.h6
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h126
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_device.h75
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_listener.h120
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h64
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_server_transport_adapter.h136
-rw-r--r--src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h107
-rw-r--r--src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc38
-rw-r--r--src/components/transport_manager/src/transport_manager_default.cc26
-rw-r--r--src/components/transport_manager/src/transport_manager_impl.cc76
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_connection.cc218
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_device.cc94
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_listener.cc299
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_secure_session.cc79
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_server_transport_adapter.cc141
-rw-r--r--src/components/transport_manager/src/websocket_server/websocket_session.cc162
-rw-r--r--src/components/transport_manager/test/CMakeLists.txt10
-rw-r--r--src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h82
-rw-r--r--src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h117
-rw-r--r--src/components/transport_manager/test/tcp_client_listener_test.cc62
-rw-r--r--src/components/transport_manager/test/test_certs/ca-cert.pem23
-rw-r--r--src/components/transport_manager/test/test_certs/client-cert.pem21
-rw-r--r--src/components/transport_manager/test/test_certs/client-key.pem28
-rw-r--r--src/components/transport_manager/test/test_certs/invalid_cert.pem22
-rw-r--r--src/components/transport_manager/test/test_certs/invalid_key.pem28
-rw-r--r--src/components/transport_manager/test/test_certs/server-cert.pem21
-rw-r--r--src/components/transport_manager/test/test_certs/server-key.pem28
-rw-r--r--src/components/transport_manager/test/transport_manager_default_test.cc21
-rw-r--r--src/components/transport_manager/test/websocket_client_connection_test.cc482
-rw-r--r--src/components/transport_manager/test/websocket_connection_test.cc504
-rw-r--r--src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc193
-rw-r--r--src/components/transport_manager/test/websocket_server_listener_test.cc260
121 files changed, 7307 insertions, 1135 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b344f91342..764a050b91 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,7 @@ option(BUILD_SHARED_LIBS "Build all libraries as shared (if ON) or static (if OF
option(BUILD_BT_SUPPORT "Bluetooth support" ON)
option(BUILD_USB_SUPPORT "libusb support" ON)
option(BUILD_CLOUD_APP_SUPPORT "Cloud App Transport Support" ON)
+option(BUILD_WEBSOCKET_SERVER_SUPPORT "Web Engine App Transport Support" ON)
option(BUILD_BACKTRACE_SUPPORT "backtrace support" ON)
option(BUILD_TESTS "Possibility to build and run tests" OFF)
option(TELEMETRY_MONITOR "Enable profiling time test util" ON)
@@ -209,6 +210,13 @@ get_property(cValue CACHE ENABLE_HMI_PTU_DECRYPTION PROPERTY VALUE)
file(APPEND "${build_config_path}" "//${cHelpString}\n")
file(APPEND "${build_config_path}" "ENABLE_HMI_PTU_DECRYPTION:${cType}=${cValue}\n")
+get_property(cHelpString CACHE BUILD_WEBSOCKET_SERVER_SUPPORT PROPERTY HELPSTRING)
+get_property(cType CACHE BUILD_WEBSOCKET_SERVER_SUPPORT PROPERTY TYPE)
+get_property(cValue CACHE BUILD_WEBSOCKET_SERVER_SUPPORT PROPERTY VALUE)
+file(APPEND "${build_config_path}" "//${cHelpString}\n")
+file(APPEND "${build_config_path}" "BUILD_WEBSOCKET_SERVER_SUPPORT:${cType}=${cValue}\n")
+
+
add_custom_target(pasa-tarball
COMMAND ${CMAKE_SOURCE_DIR}/tools/Utils/export-customer-specific.sh ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} pasa
COMMAND tar -cz -C /tmp/PASA -f ${CMAKE_BINARY_DIR}/pasa.tar.gz .
@@ -323,6 +331,11 @@ if (BUILD_CLOUD_APP_SUPPORT)
message(STATUS "Cloud app websocket support enabled")
endif()
+if (BUILD_WEBSOCKET_SERVER_SUPPORT)
+ add_definitions(-DWEBSOCKET_SERVER_TRANSPORT_SUPPORT)
+ message(STATUS "Web engine app websocket support enabled")
+endif()
+
if (BUILD_BACKTRACE_SUPPORT)
add_definitions(-DBACKTRACE_SUPPORT)
message(STATUS "Backtrace support enabled")
diff --git a/Doxyfile b/Doxyfile
index 8674bd3114..79f0c3510e 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -900,7 +900,8 @@ EXAMPLE_RECURSIVE = NO
IMAGE_PATH = \
src/components/security_manager/docs/assets \
- src/components/protocol_handler/docs/assets
+ src/components/protocol_handler/docs/assets \
+ src/components/transport_manager/docs/assets
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
diff --git a/src/appMain/smartDeviceLink.ini b/src/appMain/smartDeviceLink.ini
index baf8cf6073..31302f24c6 100644
--- a/src/appMain/smartDeviceLink.ini
+++ b/src/appMain/smartDeviceLink.ini
@@ -202,6 +202,15 @@ TCPAdapterPort = 12345
; If the name is omitted, Core will listen on all network interfaces by binding to INADDR_ANY.
TCPAdapterNetworkInterface =
+; WebSocket connection address used for incoming connections
+WebSocketServerAddress = 0.0.0.0
+; Listening port for incoming connection to websocket server
+WebSocketServerPort = 2020
+; WS Server Certificate
+; WSServerCertificatePath = server-cert.pem
+; WSServerKeyPath = server-key.pem
+; WSServerCACertificatePath = ca-cert.pem
+
; 128 bit uuid for bluetooth device discovery. Please format as 16 seperate bytes.
;BluetoothUUID = 0x93, 0x6D, 0xA0, 0x1F, 0x9A, 0xBD, 0x4D, 0x9D, 0x80, 0xC7, 0x02, 0xAF, 0x85, 0xC8, 0x22, 0xA8
diff --git a/src/components/application_manager/include/application_manager/application_manager_impl.h b/src/components/application_manager/include/application_manager/application_manager_impl.h
index ab7cf95139..1e361a75c9 100644
--- a/src/components/application_manager/include/application_manager/application_manager_impl.h
+++ b/src/components/application_manager/include/application_manager/application_manager_impl.h
@@ -409,7 +409,13 @@ class ApplicationManagerImpl
void CreatePendingApplication(
const transport_manager::ConnectionUID connection_id,
const transport_manager::DeviceInfo& device_info,
- connection_handler::DeviceHandle device_id);
+ connection_handler::DeviceHandle device_id) OVERRIDE;
+
+ void OnWebEngineDeviceCreated() OVERRIDE;
+
+ void CreatePendingLocalApplication(const std::string& policy_app_id) OVERRIDE;
+
+ void RemovePendingApplication(const std::string& policy_app_id) OVERRIDE;
void SetPendingApplicationState(
const transport_manager::ConnectionUID connection_id,
diff --git a/src/components/application_manager/include/application_manager/message_helper.h b/src/components/application_manager/include/application_manager/message_helper.h
index aff4659323..5d95a2468d 100644
--- a/src/components/application_manager/include/application_manager/message_helper.h
+++ b/src/components/application_manager/include/application_manager/message_helper.h
@@ -380,6 +380,15 @@ class MessageHelper {
static void SendOnAppUnregNotificationToHMI(ApplicationConstSharedPtr app,
bool is_unexpected_disconnect,
ApplicationManager& app_mngr);
+ /**
+ * @brief Creates BasicCommunication.OnAppPropertiesChange
+ * notification to the HMI
+ * @param policy_app_id unique policy app id
+ * @param app_mngr application manager
+ * @return smart object with BC.OnAppPropertiesChange notification
+ */
+ static smart_objects::SmartObjectSPtr CreateOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id, ApplicationManager& app_mngr);
static smart_objects::SmartObjectSPtr GetBCActivateAppRequestToHMI(
ApplicationConstSharedPtr app,
diff --git a/src/components/application_manager/include/application_manager/policies/policy_handler.h b/src/components/application_manager/include/application_manager/policies/policy_handler.h
index a03288f9a9..b517a7d82c 100644
--- a/src/components/application_manager/include/application_manager/policies/policy_handler.h
+++ b/src/components/application_manager/include/application_manager/policies/policy_handler.h
@@ -427,6 +427,8 @@ class PolicyHandler : public PolicyHandlerInterface,
custom_str::CustomString GetAppName(
const std::string& policy_app_id) OVERRIDE;
+ std::vector<std::string> GetApplicationPolicyIDs() const OVERRIDE;
+
/**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
@@ -436,6 +438,13 @@ class PolicyHandler : public PolicyHandlerInterface,
std::vector<std::string>& enabled_apps) const OVERRIDE;
/**
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ std::vector<std::string> GetEnabledLocalApps() const OVERRIDE;
+
+ /**
* @brief Checks if a given application is an enabled cloud application
* @param policy_app_id Unique application id
* @return true, if the application is an enabled cloud application,
@@ -444,33 +453,24 @@ class PolicyHandler : public PolicyHandlerInterface,
const bool CheckCloudAppEnabled(
const std::string& policy_app_id) const OVERRIDE;
- /**
- * @brief Get cloud app policy information, all fields that aren't set for a
- * given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- bool GetCloudAppParameters(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const OVERRIDE;
+ bool GetAppProperties(
+ const std::string& policy_app_id,
+ policy::AppProperties& out_app_properties) const OVERRIDE;
void OnAuthTokenUpdated(const std::string& policy_app_id,
const std::string& auth_token) OVERRIDE;
+ void OnSetAppProperties(
+ const smart_objects::SmartObject& properties) OVERRIDE;
+
+ AppPropertiesState GetAppPropertiesStatus(
+ const smart_objects::SmartObject& properties,
+ const std::string& app_id) const OVERRIDE;
+
+ bool IsNewApplication(const std::string& policy_app_id) const OVERRIDE;
+
+ void OnLocalAppAdded() OVERRIDE;
+
/**
* @brief Callback for when a SetCloudAppProperties message is received
* from a mobile app
@@ -533,6 +533,9 @@ class PolicyHandler : public PolicyHandlerInterface,
const std::string& device_id,
const std::string& policy_app_id) const OVERRIDE;
+ void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const OVERRIDE;
+
virtual void OnPTExchangeNeeded() OVERRIDE;
virtual void GetAvailableApps(std::queue<std::string>& apps) OVERRIDE;
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h
new file mode 100644
index 0000000000..484a82ca4c
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_REQUEST_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_REQUEST_H_
+
+#include "application_manager/commands/request_from_hmi.h"
+
+namespace sdl_rpc_plugin {
+namespace app_mngr = application_manager;
+
+namespace commands {
+
+/**
+ * @brief BCGetAppPropertiesRequest command class
+ **/
+class BCGetAppPropertiesRequest : public app_mngr::commands::RequestFromHMI {
+ public:
+ /**
+ * @brief BCGetAppPropertiesRequest class constructor
+ *
+ * @param message Incoming SmartObject message
+ **/
+ BCGetAppPropertiesRequest(const app_mngr::commands::MessageSharedPtr& message,
+ app_mngr::ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler);
+
+ /**
+ * @brief BCGetAppPropertiesRequest class destructor
+ **/
+ virtual ~BCGetAppPropertiesRequest() = default;
+
+ /**
+ * @brief Execute command
+ **/
+ void Run() FINAL;
+
+ private:
+ void FillAppProperties(const std::string& policy_app_id,
+ smart_objects::SmartObject& out_properties) const;
+
+ DISALLOW_COPY_AND_ASSIGN(BCGetAppPropertiesRequest);
+};
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
+
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_REQUEST_H_
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h
new file mode 100644
index 0000000000..5634663254
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_RESPONSE_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_RESPONSE_H_
+
+#include "application_manager/commands/response_to_hmi.h"
+
+namespace sdl_rpc_plugin {
+namespace app_mngr = application_manager;
+
+namespace commands {
+
+/**
+ * @brief BCGetAppPropertiesResponse command class
+ **/
+class BCGetAppPropertiesResponse : public app_mngr::commands::ResponseToHMI {
+ public:
+ /**
+ * @brief BCGetAppPropertiesResponse class constructor
+ *
+ * @param message Incoming SmartObject message
+ **/
+ BCGetAppPropertiesResponse(
+ const app_mngr::commands::MessageSharedPtr& message,
+ app_mngr::ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler);
+
+ /**
+ * @brief BCGetAppPropertiesResponse class destructor
+ **/
+ virtual ~BCGetAppPropertiesResponse() = default;
+
+ /**
+ * @brief Execute command
+ **/
+ void Run() FINAL;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BCGetAppPropertiesResponse);
+};
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
+
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_GET_APP_PROPERTIES_RESPONSE_H_
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h
new file mode 100644
index 0000000000..491d2196e5
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_REQUEST_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_REQUEST_H_
+
+#include "application_manager/commands/request_from_hmi.h"
+
+namespace sdl_rpc_plugin {
+namespace app_mngr = application_manager;
+
+namespace commands {
+
+/**
+ * @brief BCSetAppPropertiesRequest command class
+ **/
+class BCSetAppPropertiesRequest : public app_mngr::commands::RequestFromHMI {
+ public:
+ /**
+ * @brief BCSetAppPropertiesRequest class constructor
+ *
+ * @param message Incoming SmartObject message
+ **/
+ BCSetAppPropertiesRequest(const app_mngr::commands::MessageSharedPtr& message,
+ app_mngr::ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler);
+
+ /**
+ * @brief BCSetAppPropertiesRequest class destructor
+ **/
+ virtual ~BCSetAppPropertiesRequest() = default;
+
+ /**
+ * @brief Execute command
+ **/
+ void Run() FINAL;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BCSetAppPropertiesRequest);
+};
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
+
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_REQUEST_H_
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h
new file mode 100644
index 0000000000..e9872196c9
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_RESPONSE_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_RESPONSE_H_
+
+#include "application_manager/commands/response_to_hmi.h"
+
+namespace sdl_rpc_plugin {
+namespace app_mngr = application_manager;
+
+namespace commands {
+
+/**
+ * @brief BCSetAppPropertiesResponse command class
+ **/
+class BCSetAppPropertiesResponse : public app_mngr::commands::ResponseToHMI {
+ public:
+ /**
+ * @brief BCSetAppPropertiesResponse class constructor
+ *
+ * @param message Incoming SmartObject message
+ **/
+ BCSetAppPropertiesResponse(
+ const app_mngr::commands::MessageSharedPtr& message,
+ app_mngr::ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler);
+
+ /**
+ * @brief BCSetAppPropertiesResponse class destructor
+ **/
+ virtual ~BCSetAppPropertiesResponse() = default;
+
+ /**
+ * @brief Execute command
+ **/
+ void Run() FINAL;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BCSetAppPropertiesResponse);
+};
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
+
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_BC_SET_APP_PROPERTIES_RESPONSE_H_
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h
new file mode 100644
index 0000000000..7feb2ef85e
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_ON_APP_PROPERTIES_CHANGE_NOTIFICATION_H_
+#define SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_ON_APP_PROPERTIES_CHANGE_NOTIFICATION_H_
+
+#include "application_manager/commands/notification_to_hmi.h"
+
+namespace sdl_rpc_plugin {
+namespace app_mngr = application_manager;
+
+namespace commands {
+
+/**
+ * @brief OnAppPropertiesChangeNotification command class
+ **/
+class OnAppPropertiesChangeNotification
+ : public app_mngr::commands::NotificationToHMI {
+ public:
+ /**
+ * @brief OnAppPropertiesChangeNotification class constructor
+ *
+ * @param message Incoming SmartObject message
+ **/
+ OnAppPropertiesChangeNotification(
+ const app_mngr::commands::MessageSharedPtr& message,
+ app_mngr::ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handle);
+
+ /**
+ * @brief OnAppPropertiesChangeNotification class destructor
+ **/
+ virtual ~OnAppPropertiesChangeNotification() = default;
+
+ /**
+ * @brief Execute command
+ **/
+ void Run() FINAL;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OnAppPropertiesChangeNotification);
+};
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
+
+#endif // SRC_COMPONENTS_APPLICATION_MANAGER_RPC_PLUGINS_SDL_RPC_PLUGIN_INCLUDE_SDL_RPC_PLUGIN_COMMANDS_HMI_ON_APP_PROPERTIES_CHANGE_NOTIFICATION_H_
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_request.cc
new file mode 100644
index 0000000000..0dafa21e33
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_request.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (c) 2020, Ford Motor Company, Livio
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the the copyright holders nor the names of their
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h"
+#include "application_manager/policies/policy_handler_interface.h"
+#include "application_manager/rpc_service.h"
+#include "interfaces/MOBILE_API.h"
+
+namespace sdl_rpc_plugin {
+using namespace application_manager;
+namespace commands {
+
+BCGetAppPropertiesRequest::BCGetAppPropertiesRequest(
+ const application_manager::commands::MessageSharedPtr& message,
+ ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler)
+ : RequestFromHMI(message,
+ application_manager,
+ rpc_service,
+ hmi_capabilities,
+ policy_handler) {}
+
+void BCGetAppPropertiesRequest::FillAppProperties(
+ const std::string& policy_app_id,
+ smart_objects::SmartObject& out_properties) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ policy::AppProperties app_properties;
+ const bool result =
+ policy_handler_.GetAppProperties(policy_app_id, app_properties);
+
+ if (!result) {
+ LOG4CXX_DEBUG(
+ logger_,
+ "Failed to get app parameters for policy_app_id: " << policy_app_id);
+ return;
+ }
+
+ out_properties[strings::policy_app_id] = policy_app_id;
+ out_properties[strings::enabled] = app_properties.enabled;
+
+ policy::StringArray nicknames;
+ policy::StringArray app_hmi_types;
+
+ policy_handler_.GetInitialAppData(policy_app_id, &nicknames, &app_hmi_types);
+
+ smart_objects::SmartObject nicknames_array(smart_objects::SmartType_Array);
+ size_t i = 0;
+ for (const auto& nickname : nicknames) {
+ nicknames_array[i++] = nickname;
+ }
+ out_properties[strings::nicknames] = nicknames_array;
+
+ if (!app_properties.auth_token.empty()) {
+ out_properties[strings::auth_token] = app_properties.auth_token;
+ }
+ if (!app_properties.transport_type.empty()) {
+ out_properties[strings::transport_type] = app_properties.transport_type;
+ }
+ if (!app_properties.hybrid_app_preference.empty()) {
+ out_properties[strings::hybrid_app_preference] =
+ app_properties.hybrid_app_preference;
+ }
+ if (!app_properties.endpoint.empty()) {
+ out_properties[strings::endpoint] = app_properties.endpoint;
+ }
+}
+
+void BCGetAppPropertiesRequest::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ const auto& msg_params = (*message_)[strings::msg_params];
+ smart_objects::SmartObject response_params(smart_objects::SmartType_Map);
+
+ if (msg_params.keyExists(strings::policy_app_id)) {
+ const auto policy_app_id = msg_params[strings::policy_app_id].asString();
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ FillAppProperties(policy_app_id, properties);
+ if (!properties.empty()) {
+ response_params[strings::properties][0] = properties;
+ }
+ } else {
+ LOG4CXX_DEBUG(logger_,
+ "policyAppID was absent in request, all apps properties "
+ "will be returned.");
+ const auto app_ids = policy_handler_.GetApplicationPolicyIDs();
+ int i = 0;
+ for (auto& app_id : app_ids) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ FillAppProperties(app_id, properties);
+ response_params[strings::properties][i++] = properties;
+ }
+ }
+
+ if (response_params[strings::properties].empty()) {
+ SendErrorResponse(
+ (*message_)[strings::params][strings::correlation_id].asUInt(),
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::DATA_NOT_AVAILABLE,
+ "Requested data not available",
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ return;
+ }
+
+ SendResponse(true,
+ (*message_)[strings::params][strings::correlation_id].asUInt(),
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::SUCCESS,
+ &response_params);
+}
+
+} // namespace commands
+} // namespace sdl_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_response.cc
new file mode 100644
index 0000000000..57949a949b
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_get_app_properties_response.cc
@@ -0,0 +1,60 @@
+/*
+ Copyright (c) 2020, Ford Motor Company, Livio
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the the copyright holders nor the names of their
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h"
+#include "application_manager/application_impl.h"
+#include "application_manager/event_engine/event.h"
+#include "application_manager/rpc_service.h"
+#include "interfaces/MOBILE_API.h"
+
+namespace sdl_rpc_plugin {
+using namespace application_manager;
+namespace commands {
+
+BCGetAppPropertiesResponse::BCGetAppPropertiesResponse(
+ const application_manager::commands::MessageSharedPtr& message,
+ ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler)
+ : ResponseToHMI(message,
+ application_manager,
+ rpc_service,
+ hmi_capabilities,
+ policy_handler) {}
+
+void BCGetAppPropertiesResponse::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ rpc_service_.SendMessageToHMI(message_);
+}
+} // namespace commands
+} // namespace sdl_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_request.cc
new file mode 100644
index 0000000000..a4c5d6b1b4
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_request.cc
@@ -0,0 +1,114 @@
+/*
+ Copyright (c) 2020, Ford Motor Company, Livio
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the the copyright holders nor the names of their
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h"
+#include "application_manager/message_helper.h"
+#include "application_manager/policies/policy_handler_interface.h"
+#include "application_manager/rpc_service.h"
+#include "interfaces/MOBILE_API.h"
+
+namespace sdl_rpc_plugin {
+using namespace application_manager;
+namespace commands {
+
+BCSetAppPropertiesRequest::BCSetAppPropertiesRequest(
+ const application_manager::commands::MessageSharedPtr& message,
+ ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler)
+ : RequestFromHMI(message,
+ application_manager,
+ rpc_service,
+ hmi_capabilities,
+ policy_handler) {}
+
+void BCSetAppPropertiesRequest::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const auto& properties =
+ (*message_)[strings::msg_params][strings::properties];
+
+ const auto policy_app_id(properties[strings::policy_app_id].asString());
+
+ const auto properties_change_status =
+ policy_handler_.GetAppPropertiesStatus(properties, policy_app_id);
+
+ using AppPropertiesState = policy::PolicyHandlerInterface::AppPropertiesState;
+ const bool are_properties_changed =
+ AppPropertiesState::NO_CHANGES != properties_change_status;
+
+ const bool is_new_app = policy_handler_.IsNewApplication(policy_app_id);
+
+ policy_handler_.OnSetAppProperties(properties);
+ SendResponse(true,
+ (*message_)[strings::params][strings::correlation_id].asUInt(),
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties,
+ hmi_apis::Common_Result::SUCCESS);
+
+ if (are_properties_changed || is_new_app) {
+ const auto notification =
+ MessageHelper::CreateOnAppPropertiesChangeNotification(
+ policy_app_id, application_manager_);
+ application_manager_.GetRPCService().ManageHMICommand(notification);
+ }
+ if (is_new_app) {
+ LOG4CXX_ERROR(logger_,
+ "Message contains unknow policyAppId: "
+ << policy_app_id << ", PTU will be triggered");
+ policy_handler_.OnLocalAppAdded();
+ }
+
+ auto app_enabled = [this]() -> bool {
+ auto& properties = (*message_)[strings::msg_params][strings::properties];
+ if (properties.keyExists(strings::enabled)) {
+ return properties[strings::enabled].asBool();
+ }
+ return false;
+ };
+
+ const bool enable_flag_switch =
+ AppPropertiesState::ENABLED_FLAG_SWITCH == properties_change_status;
+
+ if (app_enabled() && (enable_flag_switch || is_new_app)) {
+ application_manager_.CreatePendingLocalApplication(policy_app_id);
+ application_manager_.SendUpdateAppList();
+ return;
+ }
+
+ if (enable_flag_switch) {
+ application_manager_.RemovePendingApplication(policy_app_id);
+ application_manager_.SendUpdateAppList();
+ }
+}
+
+} // namespace commands
+} // namespace sdl_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_response.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_response.cc
new file mode 100644
index 0000000000..928a17d0f8
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/bc_set_app_properties_response.cc
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2020, Ford Motor Company, Livio
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the the copyright holders nor the names of their
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h"
+#include "application_manager/application_impl.h"
+#include "application_manager/event_engine/event.h"
+#include "application_manager/policies/policy_handler_interface.h"
+#include "application_manager/rpc_service.h"
+#include "interfaces/MOBILE_API.h"
+
+namespace sdl_rpc_plugin {
+using namespace application_manager;
+namespace commands {
+
+BCSetAppPropertiesResponse::BCSetAppPropertiesResponse(
+ const application_manager::commands::MessageSharedPtr& message,
+ ApplicationManager& application_manager,
+ app_mngr::rpc_service::RPCService& rpc_service,
+ app_mngr::HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handler)
+ : ResponseToHMI(message,
+ application_manager,
+ rpc_service,
+ hmi_capabilities,
+ policy_handler) {}
+
+void BCSetAppPropertiesResponse::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ rpc_service_.SendMessageToHMI(message_);
+}
+
+} // namespace commands
+} // namespace sdl_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_app_properties_change_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_app_properties_change_notification.cc
new file mode 100644
index 0000000000..f1fa703bbb
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/hmi/on_app_properties_change_notification.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h"
+
+namespace sdl_rpc_plugin {
+using namespace application_manager;
+
+namespace commands {
+
+OnAppPropertiesChangeNotification::OnAppPropertiesChangeNotification(
+ const application_manager::commands::MessageSharedPtr& message,
+ ApplicationManager& application_manager,
+ rpc_service::RPCService& rpc_service,
+ HMICapabilities& hmi_capabilities,
+ policy::PolicyHandlerInterface& policy_handle)
+ : NotificationToHMI(message,
+ application_manager,
+ rpc_service,
+ hmi_capabilities,
+ policy_handle) {}
+
+void OnAppPropertiesChangeNotification::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ SendNotification();
+}
+
+} // namespace commands
+
+} // namespace sdl_rpc_plugin
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc
index 0b7e611e59..c5e94da378 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/get_cloud_app_properties_request.cc
@@ -33,20 +33,10 @@ void GetCloudAppPropertiesRequest::Run() {
std::string policy_app_id =
(*message_)[strings::msg_params][strings::app_id].asString();
- bool enabled = true;
- std::string endpoint;
- std::string auth_token;
- std::string certificate;
- std::string cloud_transport_type;
- std::string hybrid_app_preference;
-
- bool result = policy_handler_.GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
+ policy::AppProperties app_properties;
+
+ const bool result =
+ policy_handler_.GetAppProperties(policy_app_id, app_properties);
if (!result) {
SendResponse(false,
@@ -70,19 +60,20 @@ void GetCloudAppPropertiesRequest::Run() {
}
properties[strings::nicknames] = nicknames_array;
properties[strings::app_id] = policy_app_id;
- properties[strings::enabled] = enabled;
+ properties[strings::enabled] = app_properties.enabled;
- if (!auth_token.empty()) {
- properties[strings::auth_token] = auth_token;
+ if (!app_properties.auth_token.empty()) {
+ properties[strings::auth_token] = app_properties.auth_token;
}
- if (!cloud_transport_type.empty()) {
- properties[strings::cloud_transport_type] = cloud_transport_type;
+ if (!app_properties.transport_type.empty()) {
+ properties[strings::cloud_transport_type] = app_properties.transport_type;
}
- if (!hybrid_app_preference.empty()) {
- properties[strings::hybrid_app_preference] = hybrid_app_preference;
+ if (!app_properties.hybrid_app_preference.empty()) {
+ properties[strings::hybrid_app_preference] =
+ app_properties.hybrid_app_preference;
}
- if (!endpoint.empty()) {
- properties[strings::endpoint] = endpoint;
+ if (!app_properties.endpoint.empty()) {
+ properties[strings::endpoint] = app_properties.endpoint;
}
response_params[strings::properties] = properties;
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc
index 3bb1e1c107..680429d3b6 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/set_cloud_app_properties_request.cc
@@ -1,4 +1,5 @@
#include "sdl_rpc_plugin/commands/mobile/set_cloud_app_properties_request.h"
+#include "application_manager/message_helper.h"
#include "application_manager/policies/policy_handler_interface.h"
namespace sdl_rpc_plugin {
@@ -30,9 +31,29 @@ void SetCloudAppPropertiesRequest::Run() {
return;
}
- policy_handler_.OnSetCloudAppProperties(*message_);
+ const auto& properties =
+ (*message_)[strings::msg_params][strings::properties];
+
+ const auto app_id(properties[strings::app_id].asString());
+
+ const auto properties_change_status =
+ policy_handler_.GetAppPropertiesStatus(properties, app_id);
+
+ using AppPropertiesState = policy::PolicyHandlerInterface::AppPropertiesState;
+ const bool is_properties_changed =
+ AppPropertiesState::NO_CHANGES != properties_change_status;
+ const bool is_new_app = policy_handler_.IsNewApplication(app_id);
+
+ policy_handler_.OnSetCloudAppProperties(*message_);
SendResponse(true, mobile_apis::Result::SUCCESS);
+
+ if (is_properties_changed || is_new_app) {
+ const auto notification =
+ MessageHelper::CreateOnAppPropertiesChangeNotification(
+ app_id, application_manager_);
+ application_manager_.GetRPCService().ManageHMICommand(notification);
+ }
}
void SetCloudAppPropertiesRequest::on_event(
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/hmi_command_factory.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/hmi_command_factory.cc
index 6a231f8e35..b89a8dbd68 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/hmi_command_factory.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/hmi_command_factory.cc
@@ -256,6 +256,12 @@
#include "sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification.h"
#include "sdl_rpc_plugin/commands/hmi/on_bc_system_capability_updated_notification_from_hmi.h"
+#include "sdl_rpc_plugin/commands/hmi/bc_get_app_properties_request.h"
+#include "sdl_rpc_plugin/commands/hmi/bc_get_app_properties_response.h"
+#include "sdl_rpc_plugin/commands/hmi/bc_set_app_properties_request.h"
+#include "sdl_rpc_plugin/commands/hmi/bc_set_app_properties_response.h"
+#include "sdl_rpc_plugin/commands/hmi/on_app_properties_change_notification.h"
+
namespace sdl_rpc_plugin {
using namespace application_manager;
@@ -904,6 +910,19 @@ CommandCreator& HMICommandFactory::get_creator_factory(
: factory.GetCreator<
commands::OnBCSystemCapabilityUpdatedNotification>();
}
+ case hmi_apis::FunctionID::BasicCommunication_GetAppProperties: {
+ return hmi_apis::messageType::request == message_type
+ ? factory.GetCreator<commands::BCGetAppPropertiesRequest>()
+ : factory.GetCreator<commands::BCGetAppPropertiesResponse>();
+ }
+ case hmi_apis::FunctionID::BasicCommunication_SetAppProperties: {
+ return hmi_apis::messageType::request == message_type
+ ? factory.GetCreator<commands::BCSetAppPropertiesRequest>()
+ : factory.GetCreator<commands::BCSetAppPropertiesResponse>();
+ }
+ case hmi_apis::FunctionID::BasicCommunication_OnAppPropertiesChange: {
+ return factory.GetCreator<commands::OnAppPropertiesChangeNotification>();
+ }
default: { return factory.GetCreator<InvalidCommand>(); }
}
}
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_request_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_request_test.cc
new file mode 100644
index 0000000000..0d70226645
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_request_test.cc
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gtest/gtest.h"
+
+#include "application_manager/commands/command_impl.h"
+#include "application_manager/commands/command_request_test.h"
+#include "application_manager/mock_application.h"
+#include "hmi/bc_get_app_properties_request.h"
+
+namespace test {
+namespace components {
+namespace commands_test {
+namespace hmi_commands_test {
+namespace bc_get_app_properties_request_test {
+
+namespace am = ::application_manager;
+namespace strings = ::application_manager::strings;
+
+using am::commands::CommandImpl;
+using am::commands::MessageSharedPtr;
+using sdl_rpc_plugin::commands::BCGetAppPropertiesRequest;
+
+using testing::DoAll;
+using testing::Return;
+using testing::ReturnRef;
+using testing::SaveArg;
+
+namespace {
+const std::string kPolicyAppId = "00001";
+const uint32_t kCorrelationId = 1u;
+const auto kSource = am::commands::Command::SOURCE_HMI;
+
+const std::string kAuthToken = "auth_token";
+const std::string kCertificate = "certificate";
+const std::string kTransportType = "WS";
+const std::string kHybridAppPreference = "local_app";
+const bool kEnabled = true;
+
+const std::string kNickname1 = "nickname1";
+const std::string kNickname2 = "nickname2";
+} // namespace
+
+bool CompareAppProperties(const smart_objects::SmartObject& app_propersties_so,
+ const policy::AppProperties& app_properties) {
+ return (app_propersties_so[strings::auth_token].asString() ==
+ app_properties.auth_token) &&
+ (app_propersties_so[strings::transport_type].asString() ==
+ app_properties.transport_type) &&
+ (app_propersties_so[strings::hybrid_app_preference].asString() ==
+ app_properties.hybrid_app_preference);
+}
+
+bool CompareNicknames(const smart_objects::SmartObject& nicknames_so,
+ const policy::StringArray& nicknames) {
+ if (nicknames_so.length() != nicknames.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < nicknames_so.length(); ++i) {
+ if (nicknames_so[i].asString() != nicknames[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+ACTION_P(SetTestAppProperties, app_properties) {
+ arg1 = app_properties;
+}
+
+ACTION_P(SetTestNickNames, nicknames) {
+ *arg1 = nicknames;
+}
+
+class BCGetAppPropertiesRequestTest
+ : public CommandRequestTest<CommandsTestMocks::kIsNice> {
+ public:
+ BCGetAppPropertiesRequestTest() : mock_app_(CreateMockApp()) {
+ ON_CALL(app_mngr_, GetRPCService())
+ .WillByDefault(ReturnRef(mock_rpc_service_));
+ }
+
+ MockAppPtr mock_app_;
+};
+
+TEST_F(BCGetAppPropertiesRequestTest, Run_PolicyAppId_Exist_SUCCESS) {
+ auto msg = CreateMessage();
+
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ (*msg)[strings::msg_params][strings::policy_app_id] = kPolicyAppId;
+ auto command = CreateCommand<BCGetAppPropertiesRequest>(msg);
+
+ // Fills app properties with default test values
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(kPolicyAppId, _))
+ .WillOnce(DoAll(
+ SetTestAppProperties(policy::AppProperties("",
+ kCertificate,
+ kEnabled,
+ kAuthToken,
+ kTransportType,
+ kHybridAppPreference)),
+ Return(true)));
+
+ // Fills app nicknames with default test values
+ EXPECT_CALL(mock_policy_handler_, GetInitialAppData(kPolicyAppId, _, _))
+ .WillOnce(
+ DoAll(SetTestNickNames(policy::StringArray{kNickname1, kNickname2}),
+ Return(true)));
+
+ auto message_to_hmi = CreateMessage();
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(
+ HMIMessageParametersAre(
+ kCorrelationId,
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::SUCCESS),
+ kSource))
+ .WillOnce(DoAll(SaveArg<0>(&message_to_hmi), Return(true)));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+
+ const smart_objects::SmartObject& sent_app_properties =
+ (*message_to_hmi)[strings::msg_params][strings::properties][0];
+
+ EXPECT_FALSE(sent_app_properties.empty());
+
+ const std::string auth_token =
+ sent_app_properties[strings::auth_token].asString();
+ const std::string transport_type =
+ sent_app_properties[strings::transport_type].asString();
+ const std::string hybrid_app_preference =
+ sent_app_properties[strings::hybrid_app_preference].asString();
+ // ENDPOINT should be omitted for local application properties.
+ EXPECT_FALSE(sent_app_properties.keyExists(strings::endpoint));
+
+ EXPECT_EQ(kAuthToken, auth_token);
+ EXPECT_EQ(kTransportType, transport_type);
+ EXPECT_EQ(kHybridAppPreference, hybrid_app_preference);
+
+ EXPECT_TRUE(sent_app_properties.keyExists(strings::nicknames));
+
+ const auto nick_names = sent_app_properties[strings::nicknames];
+ EXPECT_EQ(kNickname1, nick_names[0].asString());
+ EXPECT_EQ(kNickname2, nick_names[1].asString());
+}
+
+TEST_F(BCGetAppPropertiesRequestTest,
+ PolicyAppIdExistsInMessage_GetAppPropertiesFailed_UNSUCCESS) {
+ auto msg = CreateMessage();
+
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ (*msg)[strings::msg_params][strings::policy_app_id] = kPolicyAppId;
+ auto command = CreateCommand<BCGetAppPropertiesRequest>(msg);
+
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(kPolicyAppId, _))
+ .WillOnce(Return(false));
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(
+ HMIMessageParametersAre(
+ kCorrelationId,
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::DATA_NOT_AVAILABLE),
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI))
+ .WillOnce(Return(true));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+TEST_F(
+ BCGetAppPropertiesRequestTest,
+ Run_PolicyAppIdIsAbsentInMessage_AppParametersAreAbsent_NickNamesAreAbsent_UNSUCCESS) {
+ auto msg = CreateMessage();
+
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ auto command = CreateCommand<BCGetAppPropertiesRequest>(msg);
+
+ EXPECT_CALL(mock_policy_handler_, GetApplicationPolicyIDs())
+ .WillOnce(Return(policy::StringArray()));
+
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(_, _)).Times(0);
+ EXPECT_CALL(mock_policy_handler_, GetInitialAppData(_, _, _)).Times(0);
+
+ auto message_to_hmi = CreateMessage();
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(
+ HMIMessageParametersAre(
+ kCorrelationId,
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::DATA_NOT_AVAILABLE),
+ Command::SOURCE_SDL_TO_HMI))
+ .WillOnce(DoAll(SaveArg<0>(&message_to_hmi), Return(true)));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+
+ EXPECT_FALSE(
+ (*message_to_hmi)[strings::msg_params].keyExists(strings::properties));
+}
+
+TEST_F(BCGetAppPropertiesRequestTest,
+ Run_PolicyAppIdIsAbsentInMessage_ReturnsAllAppProperties_SUCCESS) {
+ auto msg = CreateMessage();
+
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ auto command = CreateCommand<BCGetAppPropertiesRequest>(msg);
+
+ const std::string test_policy_app_id1 = "test_policy_app_id1";
+ const policy::AppProperties test_app1_properties("",
+ "cert1",
+ true,
+ "auth_token1",
+ "transport_type1",
+ "hybrid_app_preference1");
+ const policy::StringArray test_nicknames1{"nickname1", "nickname2"};
+
+ const std::string test_policy_app_id2 = "test_policy_app_id2";
+ const policy::AppProperties test_app2_properties("",
+ "cert2",
+ false,
+ "auth_token2",
+ "transport_type2",
+ "hybrid_app_preference2");
+ const policy::StringArray test_nicknames2{"nickname3", "nickname4"};
+
+ EXPECT_CALL(mock_policy_handler_, GetApplicationPolicyIDs())
+ .WillOnce(Return(
+ policy::StringArray{test_policy_app_id1, test_policy_app_id2}));
+
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(test_policy_app_id1, _))
+ .WillOnce(
+ DoAll(SetTestAppProperties(test_app1_properties), Return(true)));
+ EXPECT_CALL(mock_policy_handler_,
+ GetInitialAppData(test_policy_app_id1, _, _))
+ .WillOnce(DoAll(SetTestNickNames(test_nicknames1), Return(true)));
+
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(test_policy_app_id2, _))
+ .WillOnce(
+ DoAll(SetTestAppProperties(test_app2_properties), Return(true)));
+ EXPECT_CALL(mock_policy_handler_,
+ GetInitialAppData(test_policy_app_id2, _, _))
+ .WillOnce(DoAll(SetTestNickNames(test_nicknames2), Return(true)));
+
+ auto message_to_hmi = CreateMessage();
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(
+ HMIMessageParametersAre(
+ kCorrelationId,
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::SUCCESS),
+ kSource))
+ .WillOnce(DoAll(SaveArg<0>(&message_to_hmi), Return(true)));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+
+ const auto& sent_app_properties =
+ (*message_to_hmi)[strings::msg_params][strings::properties];
+
+ EXPECT_EQ(2u, sent_app_properties.length());
+
+ // Compare test_app1 app_properties with sent app properties
+ const auto& sent_test_app1_properties = sent_app_properties[0];
+ EXPECT_FALSE(sent_test_app1_properties.keyExists(strings::endpoint));
+ EXPECT_TRUE(
+ CompareAppProperties(sent_test_app1_properties, test_app1_properties));
+
+ const auto& sent_test_app1_nicknames =
+ sent_app_properties[0][strings::nicknames];
+ EXPECT_TRUE(CompareNicknames(sent_test_app1_nicknames, test_nicknames1));
+
+ // Compare test_app2 app_properties with sent app properties
+ const auto& sent_test_app2_properties = sent_app_properties[1];
+ EXPECT_FALSE(sent_test_app2_properties.keyExists(strings::endpoint));
+ EXPECT_TRUE(
+ CompareAppProperties(sent_test_app2_properties, test_app2_properties));
+
+ const auto& sent_test_app2_nicknames =
+ sent_app_properties[1][strings::nicknames];
+ EXPECT_TRUE(CompareNicknames(sent_test_app2_nicknames, test_nicknames2));
+}
+
+TEST_F(BCGetAppPropertiesRequestTest,
+ Run_PolicyAppIdExist_NickNamesAreAbsent_SendEmptyArray_SUCCESS) {
+ auto msg = CreateMessage();
+
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ (*msg)[strings::msg_params][strings::policy_app_id] = kPolicyAppId;
+ auto command = CreateCommand<BCGetAppPropertiesRequest>(msg);
+
+ // Fills app properties with default test values
+ EXPECT_CALL(mock_policy_handler_, GetAppProperties(kPolicyAppId, _))
+ .WillOnce(DoAll(
+ SetTestAppProperties(policy::AppProperties("",
+ kCertificate,
+ kEnabled,
+ kAuthToken,
+ kTransportType,
+ kHybridAppPreference)),
+ Return(true)));
+
+ // In the case when nicknames array is empty, SDL should forward the empty
+ // array to HMI in the app properties
+ EXPECT_CALL(mock_policy_handler_, GetInitialAppData(kPolicyAppId, _, _))
+ .WillOnce(DoAll(SetTestNickNames(policy::StringArray{}), Return(true)));
+
+ auto message_to_hmi = CreateMessage();
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(
+ HMIMessageParametersAre(
+ kCorrelationId,
+ hmi_apis::FunctionID::BasicCommunication_GetAppProperties,
+ hmi_apis::Common_Result::SUCCESS),
+ kSource))
+ .WillOnce(DoAll(SaveArg<0>(&message_to_hmi), Return(true)));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+
+ const auto& sent_app_properties =
+ (*message_to_hmi)[strings::msg_params][strings::properties];
+
+ EXPECT_TRUE(sent_app_properties[0].keyExists(strings::nicknames));
+ EXPECT_TRUE(sent_app_properties[0][strings::nicknames].empty());
+}
+
+} // namespace bc_get_app_properties_request_test
+} // namespace hmi_commands_test
+} // namespace commands_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_response_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_response_test.cc
new file mode 100644
index 0000000000..f9df8db1e3
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_get_app_properties_response_test.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the names of the copyright holders nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hmi/bc_get_app_properties_response.h"
+#include "application_manager/commands/command_impl.h"
+#include "application_manager/commands/commands_test.h"
+#include "gtest/gtest.h"
+#include "smart_objects/smart_object.h"
+
+namespace test {
+namespace components {
+namespace commands_test {
+namespace hmi_commands_test {
+namespace bc_get_app_properties_response {
+
+using sdl_rpc_plugin::commands::BCGetAppPropertiesResponse;
+
+class BCGetAppPropertiesResponseTest
+ : public CommandsTest<CommandsTestMocks::kIsNice> {};
+
+TEST_F(BCGetAppPropertiesResponseTest, RUN_SUCCESS) {
+ MessageSharedPtr msg = CreateMessage();
+
+ std::shared_ptr<BCGetAppPropertiesResponse> command(
+ CreateCommand<BCGetAppPropertiesResponse>(msg));
+
+ EXPECT_CALL(mock_rpc_service_, SendMessageToHMI(msg));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+} // namespace bc_get_app_properties_response
+} // namespace hmi_commands_test
+} // namespace commands_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_request_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_request_test.cc
new file mode 100644
index 0000000000..5804476649
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_request_test.cc
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020 Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the names of the copyright holders nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gtest/gtest.h"
+
+#include "application_manager/policies/policy_handler.h"
+#include "hmi/bc_set_app_properties_request.h"
+
+#include "application_manager/commands/command_request_test.h"
+#include "application_manager/policies/policy_handler.h"
+
+namespace test {
+namespace components {
+namespace commands_test {
+namespace hmi_commands_test {
+namespace bc_set_app_properties_request {
+
+namespace am = ::application_manager;
+namespace strings = am::strings;
+
+using sdl_rpc_plugin::commands::BCSetAppPropertiesRequest;
+using ::testing::_;
+using ::testing::ReturnRef;
+
+namespace {
+const uint32_t kAppId = 1u;
+const std::string kPolicyAppId = "00001";
+const std::string kToken = "TOKEN";
+const uint32_t kHmiAppId = 13u;
+const uint32_t kCorrelationId = 1u;
+const auto kSource = am::commands::Command::SOURCE_HMI;
+} // namespace
+
+typedef std::shared_ptr<BCSetAppPropertiesRequest> BCSetAppPropertiesRequestPtr;
+
+class BCSetAppPropertiesRequestTest
+ : public CommandRequestTest<CommandsTestMocks::kIsNice> {
+ public:
+ BCSetAppPropertiesRequestTest() : mock_app_(CreateMockApp()) {
+ ON_CALL((*mock_app_), app_id()).WillByDefault(Return(kAppId));
+ ON_CALL(app_mngr_, event_dispatcher())
+ .WillByDefault(ReturnRef(event_dispatcher_));
+ ON_CALL(app_mngr_, application(_)).WillByDefault(Return(mock_app_));
+ ON_CALL(app_mngr_, application_by_hmi_app(_))
+ .WillByDefault(Return(mock_app_));
+ ON_CALL(app_mngr_, GetRPCService())
+ .WillByDefault(ReturnRef(mock_rpc_service_));
+ ON_CALL(mock_rpc_service_, ManageHMICommand(_, _))
+ .WillByDefault(Return(true));
+ }
+
+ MessageSharedPtr CreateMessageWithCustomProperties(
+ const smart_objects::SmartObject& properties) {
+ MessageSharedPtr msg = CreateMessage();
+ (*msg)[strings::params][strings::correlation_id] = kCorrelationId;
+ (*msg)[strings::msg_params][strings::app_id] = kAppId;
+ (*msg)[strings::msg_params][strings::properties] = properties;
+ return msg;
+ }
+
+ MockAppPtr mock_app_;
+};
+
+TEST_F(BCSetAppPropertiesRequestTest,
+ Run_NoAppPropertyChanges_AppIsSame_FailToUpdateAppList) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::policy_app_id] = kPolicyAppId;
+
+ MessageSharedPtr msg = CreateMessageWithCustomProperties(properties);
+ auto command = CreateCommand<BCSetAppPropertiesRequest>(msg);
+
+ const auto change_status =
+ policy::PolicyHandler::AppPropertiesState::NO_CHANGES;
+ ON_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId))
+ .WillByDefault(Return(change_status));
+ ON_CALL(mock_policy_handler_, IsNewApplication(kPolicyAppId))
+ .WillByDefault(Return(false));
+
+ MessageSharedPtr notification = CreateMessage();
+ ON_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _))
+ .WillByDefault(Return(notification));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(_, _))
+ .Times(0);
+ EXPECT_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId));
+ EXPECT_CALL(mock_policy_handler_, OnSetAppProperties(properties));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageHMICommand(
+ HMIResultCodeIs(
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties),
+ kSource));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(notification, kSource))
+ .Times(0);
+ EXPECT_CALL(app_mngr_, CreatePendingLocalApplication(kPolicyAppId)).Times(0);
+ EXPECT_CALL(app_mngr_, SendUpdateAppList()).Times(0);
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+TEST_F(BCSetAppPropertiesRequestTest,
+ Run_AppAuthTokenChanged_AppIsSame_NoUpdateAppList) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::auth_token] = kToken;
+ properties[strings::policy_app_id] = kPolicyAppId;
+
+ MessageSharedPtr msg = CreateMessageWithCustomProperties(properties);
+ auto command = CreateCommand<BCSetAppPropertiesRequest>(msg);
+
+ const auto change_status =
+ policy::PolicyHandler::AppPropertiesState::AUTH_TOKEN_CHANGED;
+ ON_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId))
+ .WillByDefault(Return(change_status));
+ ON_CALL(mock_policy_handler_, IsNewApplication(kPolicyAppId))
+ .WillByDefault(Return(false));
+
+ MessageSharedPtr notification = CreateMessage();
+ ON_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _))
+ .WillByDefault(Return(notification));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _));
+ EXPECT_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId));
+ EXPECT_CALL(mock_policy_handler_, OnSetAppProperties(properties));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageHMICommand(
+ HMIResultCodeIs(
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties),
+ kSource));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(notification, kSource));
+ EXPECT_CALL(app_mngr_, CreatePendingLocalApplication(kPolicyAppId)).Times(0);
+ EXPECT_CALL(app_mngr_, SendUpdateAppList()).Times(0);
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+TEST_F(BCSetAppPropertiesRequestTest,
+ Run_NoAppPropetiesChanged_AppIsNewAndEnabled_AppListUpdated) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::policy_app_id] = kPolicyAppId;
+ properties[strings::enabled] = true;
+
+ MessageSharedPtr msg = CreateMessageWithCustomProperties(properties);
+ auto command = CreateCommand<BCSetAppPropertiesRequest>(msg);
+
+ const auto change_status =
+ policy::PolicyHandler::AppPropertiesState::NO_CHANGES;
+ ON_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId))
+ .WillByDefault(Return(change_status));
+ ON_CALL(mock_policy_handler_, IsNewApplication(kPolicyAppId))
+ .WillByDefault(Return(true));
+
+ MessageSharedPtr notification = CreateMessage();
+ ON_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _))
+ .WillByDefault(Return(notification));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _));
+ EXPECT_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId));
+ EXPECT_CALL(mock_policy_handler_, OnSetAppProperties(properties));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageHMICommand(
+ HMIResultCodeIs(
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties),
+ kSource));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(notification, kSource));
+ EXPECT_CALL(app_mngr_, CreatePendingLocalApplication(kPolicyAppId));
+ EXPECT_CALL(app_mngr_, SendUpdateAppList());
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+TEST_F(BCSetAppPropertiesRequestTest,
+ Run_AppEnabledFlagChanged_AppListUpdated) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::policy_app_id] = kPolicyAppId;
+ properties[strings::enabled] = true;
+
+ MessageSharedPtr msg = CreateMessageWithCustomProperties(properties);
+ auto command = CreateCommand<BCSetAppPropertiesRequest>(msg);
+
+ const auto change_status =
+ policy::PolicyHandler::AppPropertiesState::ENABLED_FLAG_SWITCH;
+ ON_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId))
+ .WillByDefault(Return(change_status));
+ ON_CALL(mock_policy_handler_, IsNewApplication(kPolicyAppId))
+ .WillByDefault(Return(false));
+
+ MessageSharedPtr notification = CreateMessage();
+ ON_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _))
+ .WillByDefault(Return(notification));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _));
+ EXPECT_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId));
+ EXPECT_CALL(mock_policy_handler_, OnSetAppProperties(properties));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageHMICommand(
+ HMIResultCodeIs(
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties),
+ kSource));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(notification, kSource));
+ EXPECT_CALL(app_mngr_, CreatePendingLocalApplication(kPolicyAppId));
+ EXPECT_CALL(app_mngr_, SendUpdateAppList());
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+TEST_F(BCSetAppPropertiesRequestTest,
+ Run_AppEnabledFlagChangedToFalse_AppRemoveFromList_AppListUpdated) {
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::policy_app_id] = kPolicyAppId;
+ properties[strings::enabled] = false;
+
+ MessageSharedPtr msg = CreateMessageWithCustomProperties(properties);
+ auto command = CreateCommand<BCSetAppPropertiesRequest>(msg);
+
+ const auto change_status =
+ policy::PolicyHandler::AppPropertiesState::ENABLED_FLAG_SWITCH;
+ ON_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId))
+ .WillByDefault(Return(change_status));
+ ON_CALL(mock_policy_handler_, IsNewApplication(kPolicyAppId))
+ .WillByDefault(Return(false));
+
+ MessageSharedPtr notification = CreateMessage();
+ ON_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _))
+ .WillByDefault(Return(notification));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId, _));
+ EXPECT_CALL(mock_policy_handler_,
+ GetAppPropertiesStatus(properties, kPolicyAppId));
+ EXPECT_CALL(mock_policy_handler_, OnSetAppProperties(properties));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageHMICommand(
+ HMIResultCodeIs(
+ hmi_apis::FunctionID::BasicCommunication_SetAppProperties),
+ kSource));
+ EXPECT_CALL(mock_rpc_service_, ManageHMICommand(notification, kSource));
+ EXPECT_CALL(app_mngr_, CreatePendingLocalApplication(kPolicyAppId)).Times(0);
+ EXPECT_CALL(app_mngr_, RemovePendingApplication(kPolicyAppId));
+ EXPECT_CALL(app_mngr_, SendUpdateAppList());
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+} // namespace bc_set_app_properties_request
+} // namespace hmi_commands_test
+} // namespace commands_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_response_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_response_test.cc
new file mode 100644
index 0000000000..d4b7447d0d
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/bc_set_app_properties_response_test.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the names of the copyright holders nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gtest/gtest.h"
+
+#include "hmi/bc_set_app_properties_response.h"
+
+#include "application_manager/commands/commands_test.h"
+
+namespace test {
+namespace components {
+namespace commands_test {
+namespace hmi_commands_test {
+namespace bc_set_app_properties_response {
+
+using sdl_rpc_plugin::commands::BCSetAppPropertiesResponse;
+
+class BCSetAppPropertiesResponseTest
+ : public CommandsTest<CommandsTestMocks::kIsNice> {};
+
+TEST_F(BCSetAppPropertiesResponseTest, RUN_SUCCESS) {
+ MessageSharedPtr msg = CreateMessage();
+
+ std::shared_ptr<BCSetAppPropertiesResponse> command(
+ CreateCommand<BCSetAppPropertiesResponse>(msg));
+
+ EXPECT_CALL(mock_rpc_service_, SendMessageToHMI(msg));
+
+ ASSERT_TRUE(command->Init());
+ command->Run();
+}
+
+} // namespace bc_set_app_properties_response
+} // namespace hmi_commands_test
+} // namespace commands_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/on_app_properties_change_notification_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/on_app_properties_change_notification_test.cc
new file mode 100644
index 0000000000..0ab0bc5a35
--- /dev/null
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/hmi/on_app_properties_change_notification_test.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+
+#include "application_manager/commands/commands_test.h"
+#include "application_manager/mock_application.h"
+#include "application_manager/mock_application_manager.h"
+#include "application_manager/smart_object_keys.h"
+#include "gtest/gtest.h"
+#include "hmi/on_app_properties_change_notification.h"
+#include "smart_objects/smart_object.h"
+
+namespace test {
+namespace components {
+namespace commands_test {
+namespace hmi_commands_test {
+namespace on_app_properties_change_notification {
+
+using namespace application_manager;
+using sdl_rpc_plugin::commands::OnAppPropertiesChangeNotification;
+
+typedef std::shared_ptr<OnAppPropertiesChangeNotification> NotificationPtr;
+typedef hmi_apis::Common_ServiceType::eType ServiceType;
+typedef hmi_apis::Common_ServiceEvent::eType ServiceEvent;
+
+namespace {
+const uint32_t kConnectionKey = 1232u;
+const uint32_t kHmiAppId = 321u;
+} // namespace
+
+class OnAppPropertiesChangeNotificationTest
+ : public CommandsTest<CommandsTestMocks::kIsNice> {
+ public:
+ OnAppPropertiesChangeNotificationTest()
+ : message_(CreateMessage(smart_objects::SmartType_Map)) {}
+
+ protected:
+ MessageSharedPtr message_;
+ NotificationPtr command_;
+};
+
+TEST_F(OnAppPropertiesChangeNotificationTest, SendNotificationToHMI) {
+ (*message_)[strings::msg_params][strings::app_id] = kConnectionKey;
+ command_ = CreateCommand<OnAppPropertiesChangeNotification>(message_);
+
+ EXPECT_CALL(mock_rpc_service_, SendMessageToHMI(message_)).Times(1);
+
+ auto mock_app = std::make_shared<NiceMock<MockApplication> >();
+
+ ON_CALL(app_mngr_, application(kConnectionKey))
+ .WillByDefault(Return(mock_app));
+
+ ON_CALL(*mock_app, hmi_app_id()).WillByDefault(Return(kHmiAppId));
+
+ ASSERT_TRUE(command_->Init());
+ command_->Run();
+}
+
+} // namespace on_app_properties_change_notification
+} // namespace hmi_commands_test
+} // namespace commands_test
+} // namespace components
+} // namespace test
diff --git a/src/components/application_manager/src/application_manager_impl.cc b/src/components/application_manager/src/application_manager_impl.cc
index 7d7e2b30df..3b586dd5e7 100644
--- a/src/components/application_manager/src/application_manager_impl.cc
+++ b/src/components/application_manager/src/application_manager_impl.cc
@@ -66,6 +66,7 @@
#include <time.h>
#include <boost/filesystem.hpp>
#include "application_manager/application_impl.h"
+#include "encryption/hashing.h"
#include "interfaces/HMI_API_schema.h"
#include "media_manager/media_manager.h"
#include "policy/usage_statistics/counter.h"
@@ -102,7 +103,9 @@ DeviceTypes devicesType = {
std::make_pair(std::string("CARPLAY_WIRELESS_IOS"),
hmi_apis::Common_TransportType::WIFI),
std::make_pair(std::string("CLOUD_WEBSOCKET"),
- hmi_apis::Common_TransportType::CLOUD_WEBSOCKET)};
+ hmi_apis::Common_TransportType::CLOUD_WEBSOCKET),
+ std::make_pair(std::string("WEBENGINE_WEBSOCKET"),
+ hmi_apis::Common_TransportType::WEBENGINE_WEBSOCKET)};
}
/**
@@ -840,6 +843,11 @@ void ApplicationManagerImpl::ConnectToDevice(const std::string& device_mac) {
void ApplicationManagerImpl::OnHMIStartedCooperation() {
LOG4CXX_AUTO_TRACE(logger_);
hmi_cooperating_ = true;
+
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ connection_handler_->CreateWebEngineDevice();
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+
MessageHelper::SendGetSystemInfoRequest(*this);
std::shared_ptr<smart_objects::SmartObject> is_vr_ready(
@@ -946,20 +954,9 @@ void ApplicationManagerImpl::DisconnectCloudApp(ApplicationSharedPtr app) {
LOG4CXX_TRACE(logger_, "Cloud app support is disabled. Exiting function");
return;
#else
- std::string endpoint;
- std::string certificate;
- std::string auth_token;
- std::string cloud_transport_type;
- std::string hybrid_app_preference;
- bool enabled = true;
std::string policy_app_id = app->policy_app_id();
- GetPolicyHandler().GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
+ policy::AppProperties app_properties;
+ GetPolicyHandler().GetAppProperties(policy_app_id, app_properties);
if (app->IsRegistered() && app->is_cloud_app()) {
LOG4CXX_DEBUG(logger_, "Disabled app is registered, unregistering now");
GetRPCService().ManageMobileCommand(
@@ -974,12 +971,12 @@ void ApplicationManagerImpl::DisconnectCloudApp(ApplicationSharedPtr app) {
connection_handler().RemoveCloudAppDevice(app->device());
transport_manager::transport_adapter::CloudAppProperties properties{
- endpoint,
- certificate,
- enabled,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference};
+ app_properties.endpoint,
+ app_properties.certificate,
+ app_properties.enabled,
+ app_properties.auth_token,
+ app_properties.transport_type,
+ app_properties.hybrid_app_preference};
// Create device in pending state
LOG4CXX_DEBUG(logger_, "Re-adding the cloud app device");
connection_handler().AddCloudAppDevice(policy_app_id, properties);
@@ -999,12 +996,6 @@ void ApplicationManagerImpl::RefreshCloudAppInformation() {
GetPolicyHandler().GetEnabledCloudApps(enabled_apps);
std::vector<std::string>::iterator enabled_it = enabled_apps.begin();
std::vector<std::string>::iterator enabled_end = enabled_apps.end();
- std::string endpoint;
- std::string certificate;
- std::string auth_token;
- std::string cloud_transport_type;
- std::string hybrid_app_preference_str;
- bool enabled = true;
// Store old device map and clear the current map
pending_device_map_lock_ptr_->Acquire();
@@ -1012,20 +1003,20 @@ void ApplicationManagerImpl::RefreshCloudAppInformation() {
std::map<std::string, std::string> old_device_map = pending_device_map_;
pending_device_map_ = std::map<std::string, std::string>();
// Create a device for each newly enabled cloud app
+ policy::AppProperties app_properties;
for (; enabled_it != enabled_end; ++enabled_it) {
- GetPolicyHandler().GetCloudAppParameters(*enabled_it,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference_str);
+ GetPolicyHandler().GetAppProperties(*enabled_it, app_properties);
+
+ if (app_properties.endpoint.empty()) {
+ continue;
+ }
mobile_apis::HybridAppPreference::eType hybrid_app_preference =
mobile_apis::HybridAppPreference::INVALID_ENUM;
smart_objects::EnumConversionHelper<
mobile_apis::HybridAppPreference::eType>::
- StringToEnum(hybrid_app_preference_str, &hybrid_app_preference);
+ StringToEnum(app_properties.hybrid_app_preference,
+ &hybrid_app_preference);
auto policy_id = *enabled_it;
policy::StringArray nicknames;
@@ -1057,22 +1048,22 @@ void ApplicationManagerImpl::RefreshCloudAppInformation() {
}
}
- pending_device_map_.insert(
- std::pair<std::string, std::string>(endpoint, policy_id));
+ pending_device_map_.insert(std::pair<std::string, std::string>(
+ app_properties.endpoint, policy_id));
// Determine which endpoints were disabled by erasing all enabled apps from
// the old device list
- auto old_device_it = old_device_map.find(endpoint);
+ auto old_device_it = old_device_map.find(app_properties.endpoint);
if (old_device_it != old_device_map.end()) {
old_device_map.erase(old_device_it);
}
transport_manager::transport_adapter::CloudAppProperties properties{
- endpoint,
- certificate,
- enabled,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference_str};
+ app_properties.endpoint,
+ app_properties.certificate,
+ app_properties.enabled,
+ app_properties.auth_token,
+ app_properties.transport_type,
+ app_properties.hybrid_app_preference};
// If the device was disconnected, this will reinitialize the device
connection_handler().AddCloudAppDevice(policy_id, properties);
@@ -1094,7 +1085,7 @@ void ApplicationManagerImpl::RefreshCloudAppInformation() {
const std::string app_icon_dir(settings_.app_icons_folder());
const std::string full_icon_path(app_icon_dir + "/" + policy_id);
if (!file_system::FileExists(full_icon_path)) {
- AppIconInfo icon_info(endpoint, false);
+ AppIconInfo icon_info(app_properties.endpoint, false);
LOG4CXX_DEBUG(
logger_,
"Inserting cloud app into icon map: " << app_icon_map_.size());
@@ -1158,12 +1149,6 @@ void ApplicationManagerImpl::CreatePendingApplication(
connection_handler::DeviceHandle device_id) {
LOG4CXX_AUTO_TRACE(logger_);
- std::string endpoint;
- std::string certificate;
- std::string auth_token;
- std::string cloud_transport_type;
- std::string hybrid_app_preference_str;
- bool enabled = true;
std::string name = device_info.name();
pending_device_map_lock_ptr_->Acquire();
auto it = pending_device_map_.find(name);
@@ -1207,34 +1192,29 @@ void ApplicationManagerImpl::CreatePendingApplication(
if (file_system::FileExists(full_icon_path)) {
application->set_app_icon_path(full_icon_path);
}
-
- GetPolicyHandler().GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference_str);
+ policy::AppProperties app_properties;
+ GetPolicyHandler().GetAppProperties(policy_app_id, app_properties);
mobile_apis::HybridAppPreference::eType hybrid_app_preference_enum;
- bool convert_result = smart_objects::EnumConversionHelper<
+ const bool convert_result = smart_objects::EnumConversionHelper<
mobile_apis::HybridAppPreference::eType>::
- StringToEnum(hybrid_app_preference_str, &hybrid_app_preference_enum);
+ StringToEnum(app_properties.hybrid_app_preference,
+ &hybrid_app_preference_enum);
- if (!hybrid_app_preference_str.empty() && !convert_result) {
- LOG4CXX_ERROR(
- logger_,
- "Could not convert string to enum: " << hybrid_app_preference_str);
+ if (!app_properties.hybrid_app_preference.empty() && !convert_result) {
+ LOG4CXX_ERROR(logger_,
+ "Could not convert string to enum: "
+ << app_properties.hybrid_app_preference);
return;
}
application->set_hmi_application_id(GenerateNewHMIAppID());
- application->set_cloud_app_endpoint(endpoint);
- application->set_auth_token(auth_token);
- application->set_cloud_app_transport_type(cloud_transport_type);
+ application->set_cloud_app_endpoint(app_properties.endpoint);
+ application->set_auth_token(app_properties.auth_token);
+ application->set_cloud_app_transport_type(app_properties.transport_type);
application->set_hybrid_app_preference(hybrid_app_preference_enum);
- application->set_cloud_app_certificate(certificate);
+ application->set_cloud_app_certificate(app_properties.certificate);
sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_);
LOG4CXX_DEBUG(logger_,
@@ -1246,6 +1226,106 @@ void ApplicationManagerImpl::CreatePendingApplication(
SendUpdateAppList();
}
+void ApplicationManagerImpl::RemovePendingApplication(
+ const std::string& policy_app_id) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_);
+ PolicyAppIdPredicate finder(policy_app_id);
+ auto app_it =
+ std::find_if(apps_to_register_.begin(), apps_to_register_.end(), finder);
+
+ if (apps_to_register_.end() == app_it) {
+ LOG4CXX_WARN(
+ logger_,
+ "Unable to find app to remove (" << policy_app_id << "), skipping");
+ return;
+ }
+
+ apps_to_register_.erase(app_it);
+ LOG4CXX_DEBUG(logger_,
+ "Remove " << policy_app_id
+ << " from apps_to_register_. new size = "
+ << apps_to_register_.size());
+}
+
+void ApplicationManagerImpl::CreatePendingLocalApplication(
+ const std::string& policy_app_id) {
+ policy::StringArray nicknames;
+ policy::StringArray app_hmi_types;
+
+ GetPolicyHandler().GetInitialAppData(
+ policy_app_id, &nicknames, &app_hmi_types);
+
+ if (nicknames.empty()) {
+ LOG4CXX_ERROR(logger_,
+ "Cloud/Web App " << policy_app_id << "missing nickname");
+ return;
+ }
+
+ const std::string display_name = nicknames[0];
+
+ const auto web_engine_device = connection_handler_->GetWebEngineDeviceInfo();
+
+ ApplicationSharedPtr application(
+ new ApplicationImpl(0,
+ policy_app_id,
+ web_engine_device.mac_address(),
+ web_engine_device.device_handle(),
+ custom_str::CustomString(display_name),
+ GetPolicyHandler().GetStatisticManager(),
+ *this));
+
+ const std::string app_icon_dir(settings_.app_icons_folder());
+ const std::string full_icon_path(app_icon_dir + "/" + policy_app_id);
+ if (file_system::FileExists(full_icon_path)) {
+ application->set_app_icon_path(full_icon_path);
+ }
+ policy::AppProperties app_properties;
+ GetPolicyHandler().GetAppProperties(policy_app_id, app_properties);
+
+ mobile_apis::HybridAppPreference::eType hybrid_app_preference_enum;
+ const bool convert_result = smart_objects::EnumConversionHelper<
+ mobile_apis::HybridAppPreference::eType>::
+ StringToEnum(app_properties.hybrid_app_preference,
+ &hybrid_app_preference_enum);
+
+ if (!app_properties.hybrid_app_preference.empty() && !convert_result) {
+ LOG4CXX_ERROR(logger_,
+ "Could not convert string to enum: "
+ << app_properties.hybrid_app_preference);
+ return;
+ }
+
+ application->set_hmi_application_id(GenerateNewHMIAppID());
+ application->set_cloud_app_endpoint(app_properties.endpoint);
+ application->set_auth_token(app_properties.auth_token);
+ application->set_cloud_app_transport_type(app_properties.transport_type);
+ application->set_hybrid_app_preference(hybrid_app_preference_enum);
+ application->set_cloud_app_certificate(app_properties.certificate);
+
+ sync_primitives::AutoLock lock(apps_to_register_list_lock_ptr_);
+ apps_to_register_.insert(application);
+ LOG4CXX_DEBUG(logger_,
+ "Insert " << application->name().c_str()
+ << " to apps_to_register_. new size = "
+ << apps_to_register_.size());
+}
+
+void ApplicationManagerImpl::OnWebEngineDeviceCreated() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const auto enabled_local_apps = policy_handler_->GetEnabledLocalApps();
+
+ if (enabled_local_apps.empty()) {
+ LOG4CXX_DEBUG(logger_, "No enabled local apps present");
+ return;
+ }
+
+ for (auto policy_app_id : enabled_local_apps) {
+ CreatePendingLocalApplication(policy_app_id);
+ }
+ SendUpdateAppList();
+}
+
void ApplicationManagerImpl::SetPendingApplicationState(
const transport_manager::ConnectionUID connection_id,
const transport_manager::DeviceInfo& device_info) {
@@ -3061,18 +3141,24 @@ void ApplicationManagerImpl::UnregisterAllApplications() {
void ApplicationManagerImpl::RemoveAppsWaitingForRegistration(
const connection_handler::DeviceHandle handle) {
+ LOG4CXX_AUTO_TRACE(logger_);
DevicePredicate device_finder(handle);
apps_to_register_list_lock_ptr_->Acquire();
- AppsWaitRegistrationSet::iterator it_app = std::find_if(
- apps_to_register_.begin(), apps_to_register_.end(), device_finder);
-
- while (apps_to_register_.end() != it_app) {
- LOG4CXX_DEBUG(
- logger_,
- "Waiting app: " << (*it_app)->name().c_str() << " is removed.");
- apps_to_register_.erase(it_app);
- it_app = std::find_if(
- apps_to_register_.begin(), apps_to_register_.end(), device_finder);
+ std::vector<ApplicationSharedPtr> apps_to_remove;
+ std::copy_if(apps_to_register_.begin(),
+ apps_to_register_.end(),
+ std::back_inserter(apps_to_remove),
+ device_finder);
+
+ const auto enabled_local_apps = policy_handler_->GetEnabledLocalApps();
+ for (auto app : apps_to_remove) {
+ const bool is_app_enabled =
+ helpers::in_range(enabled_local_apps, app->policy_app_id());
+ if (!is_app_enabled) {
+ LOG4CXX_DEBUG(logger_,
+ "Waiting app: " << app->name().c_str() << " is removed.");
+ apps_to_register_.erase(app);
+ }
}
apps_to_register_list_lock_ptr_->Release();
@@ -3191,6 +3277,14 @@ void ApplicationManagerImpl::UnregisterApplication(
RemoveAppsWaitingForRegistration(handle);
}
}
+ const auto enabled_local_apps = policy_handler_->GetEnabledLocalApps();
+ if (helpers::in_range(enabled_local_apps, app_to_remove->policy_app_id())) {
+ LOG4CXX_DEBUG(logger_,
+ "Enabled local app has been unregistered. Re-create "
+ "pending application");
+ CreatePendingLocalApplication(app_to_remove->policy_app_id());
+ }
+
RefreshCloudAppInformation();
SendUpdateAppList();
}
diff --git a/src/components/application_manager/src/commands/request_from_hmi.cc b/src/components/application_manager/src/commands/request_from_hmi.cc
index 576287286f..1cf5c50cdd 100644
--- a/src/components/application_manager/src/commands/request_from_hmi.cc
+++ b/src/components/application_manager/src/commands/request_from_hmi.cc
@@ -90,13 +90,14 @@ void RequestFromHMI::SendResponse(
FillCommonParametersOfSO(*message, correlation_id, function_id);
(*message)[strings::params][strings::message_type] = MessageType::kResponse;
(*message)[strings::params][hmi_response::code] = result_code;
- (*message)[strings::msg_params][strings::success] = success;
- (*message)[strings::msg_params][strings::result_code] = result_code;
if (response_params) {
(*message)[strings::msg_params] = *response_params;
}
+ (*message)[strings::msg_params][strings::success] = success;
+ (*message)[strings::msg_params][strings::result_code] = result_code;
+
rpc_service_.ManageHMICommand(message, source);
}
diff --git a/src/components/application_manager/src/message_helper/message_helper.cc b/src/components/application_manager/src/message_helper/message_helper.cc
index 48cf1460f9..4a64fdb128 100644
--- a/src/components/application_manager/src/message_helper/message_helper.cc
+++ b/src/components/application_manager/src/message_helper/message_helper.cc
@@ -1817,8 +1817,10 @@ bool MessageHelper::CreateHMIApplicationStruct(
&secondary_device_info);
}
- message[strings::is_cloud_application] = app->is_cloud_app();
- if (app->is_cloud_app()) {
+ const bool is_cloud_app = app->is_cloud_app();
+ message[strings::is_cloud_application] = is_cloud_app;
+
+ if (is_cloud_app) {
message[strings::cloud_connection_status] =
app_mngr.GetCloudAppConnectionStatus(app);
}
@@ -1903,6 +1905,57 @@ void MessageHelper::SendOnAppUnregNotificationToHMI(
app_mngr.GetRPCService().ManageHMICommand(notification);
}
+smart_objects::SmartObjectSPtr
+MessageHelper::CreateOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id, ApplicationManager& app_mngr) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ smart_objects::SmartObjectSPtr notification =
+ std::make_shared<smart_objects::SmartObject>(
+ smart_objects::SmartType_Map);
+
+ smart_objects::SmartObject& message = *notification;
+ message[strings::params][strings::function_id] =
+ hmi_apis::FunctionID::BasicCommunication_OnAppPropertiesChange;
+ message[strings::params][strings::message_type] = MessageType::kNotification;
+
+ policy::AppProperties app_properties;
+ app_mngr.GetPolicyHandler().GetAppProperties(policy_app_id, app_properties);
+
+ policy::StringArray nicknames;
+ policy::StringArray app_hmi_types;
+
+ app_mngr.GetPolicyHandler().GetInitialAppData(
+ policy_app_id, &nicknames, &app_hmi_types);
+
+ smart_objects::SmartObject properties(smart_objects::SmartType_Map);
+ properties[strings::policy_app_id] = policy_app_id;
+ properties[strings::enabled] = app_properties.enabled;
+
+ smart_objects::SmartObject nicknames_array(smart_objects::SmartType_Array);
+ size_t i = 0;
+ for (const auto& nickname : nicknames) {
+ nicknames_array[i++] = nickname;
+ }
+ properties[strings::nicknames] = nicknames_array;
+
+ if (!app_properties.auth_token.empty()) {
+ properties[strings::auth_token] = app_properties.auth_token;
+ }
+ if (!app_properties.transport_type.empty()) {
+ properties[strings::transport_type] = app_properties.transport_type;
+ }
+ if (!app_properties.hybrid_app_preference.empty()) {
+ properties[strings::hybrid_app_preference] =
+ app_properties.hybrid_app_preference;
+ }
+ if (!app_properties.endpoint.empty()) {
+ properties[strings::endpoint] = app_properties.endpoint;
+ }
+
+ message[strings::msg_params][strings::properties] = properties;
+ return notification;
+}
+
smart_objects::SmartObjectSPtr MessageHelper::GetBCActivateAppRequestToHMI(
ApplicationConstSharedPtr app,
const policy::PolicyHandlerInterface& policy_handler,
diff --git a/src/components/application_manager/src/policies/policy_handler.cc b/src/components/application_manager/src/policies/policy_handler.cc
index b70fcfef86..e43281c448 100644
--- a/src/components/application_manager/src/policies/policy_handler.cc
+++ b/src/components/application_manager/src/policies/policy_handler.cc
@@ -548,6 +548,15 @@ void PolicyHandler::SendOnAppPermissionsChanged(
app->app_id(), permissions, application_manager_);
}
+void PolicyHandler::SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const auto notification =
+ MessageHelper::CreateOnAppPropertiesChangeNotification(
+ policy_app_id, application_manager_);
+ application_manager_.GetRPCService().ManageHMICommand(notification);
+}
+
void PolicyHandler::OnPTExchangeNeeded() {
LOG4CXX_AUTO_TRACE(logger_);
POLICY_LIB_CHECK_VOID();
@@ -1984,47 +1993,205 @@ bool PolicyHandler::CheckSystemAction(
return false;
}
+std::vector<std::string> PolicyHandler::GetApplicationPolicyIDs() const {
+ POLICY_LIB_CHECK(std::vector<std::string>());
+ const auto all_policy_ids = policy_manager_->GetApplicationPolicyIDs();
+ std::vector<std::string> policy_app_ids;
+
+ std::copy_if(
+ all_policy_ids.begin(),
+ all_policy_ids.end(),
+ std::back_inserter(policy_app_ids),
+ [](std::string id) {
+ return helpers::Compare<std::string, helpers::NEQ, helpers::ALL>(
+ id, kDefaultId, kPreDataConsentId, kDeviceId);
+ });
+
+ return policy_app_ids;
+}
+
void PolicyHandler::GetEnabledCloudApps(
std::vector<std::string>& enabled_apps) const {
POLICY_LIB_CHECK_VOID();
policy_manager_->GetEnabledCloudApps(enabled_apps);
}
-bool PolicyHandler::GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const {
+bool PolicyHandler::GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const {
POLICY_LIB_CHECK(false);
- return policy_manager_->GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
+ return policy_manager_->GetAppProperties(policy_app_id, out_app_properties);
+}
+
+std::vector<std::string> PolicyHandler::GetEnabledLocalApps() const {
+ POLICY_LIB_CHECK(std::vector<std::string>());
+ return policy_manager_->GetEnabledLocalApps();
}
const bool PolicyHandler::CheckCloudAppEnabled(
const std::string& policy_app_id) const {
POLICY_LIB_CHECK(false);
- bool enabled = false;
- std::string endpoint;
- std::string auth_token;
- std::string certificate;
- std::string cloud_transport_type;
- std::string hybrid_app_preference;
- policy_manager_->GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
- return enabled;
+ AppProperties out_app_properties;
+ policy_manager_->GetAppProperties(policy_app_id, out_app_properties);
+ return out_app_properties.enabled;
+}
+
+PolicyHandler::AppPropertiesState PolicyHandler::GetAppPropertiesStatus(
+ const smart_objects::SmartObject& properties,
+ const std::string& app_id) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ AppProperties app_properties;
+ policy_manager_->GetAppProperties(app_id, app_properties);
+
+ policy::StringArray nicknames;
+ policy::StringArray app_hmi_types;
+ policy_manager_->GetInitialAppData(app_id, &nicknames, &app_hmi_types);
+
+ if (properties.keyExists(strings::enabled) &&
+ app_properties.enabled != properties[strings::enabled].asBool()) {
+ LOG4CXX_DEBUG(logger_,
+ "\"enabled\" was changed from: "
+ << app_properties.enabled
+ << " to: " << properties[strings::enabled].asBool());
+ return AppPropertiesState::ENABLED_FLAG_SWITCH;
+ }
+ if (properties.keyExists(strings::auth_token) &&
+ app_properties.auth_token != properties[strings::auth_token].asString()) {
+ LOG4CXX_DEBUG(logger_,
+ "\"auth_token\" was changed from: "
+ << app_properties.auth_token
+ << " to: " << properties[strings::auth_token].asString());
+ return AppPropertiesState::AUTH_TOKEN_CHANGED;
+ }
+ if (properties.keyExists(strings::transport_type) &&
+ app_properties.transport_type !=
+ properties[strings::transport_type].asString()) {
+ LOG4CXX_DEBUG(logger_,
+ "\"transport_type\" was changed from: "
+ << app_properties.transport_type << " to: "
+ << properties[strings::transport_type].asString());
+ return AppPropertiesState::TRANSPORT_TYPE_CHANGED;
+ }
+
+ if (properties.keyExists(strings::cloud_transport_type) &&
+ app_properties.transport_type !=
+ properties[strings::cloud_transport_type].asString()) {
+ LOG4CXX_DEBUG(logger_,
+ "\"transport_type\" was changed from: "
+ << app_properties.transport_type << " to: "
+ << properties[strings::cloud_transport_type].asString());
+ return AppPropertiesState::TRANSPORT_TYPE_CHANGED;
+ }
+
+ if (properties.keyExists(strings::endpoint) &&
+ app_properties.endpoint != properties[strings::endpoint].asString()) {
+ LOG4CXX_DEBUG(logger_,
+ "\"endpoint\" was changed from: "
+ << app_properties.endpoint
+ << " to: " << properties[strings::endpoint].asString());
+ return AppPropertiesState::ENDPOINT_CHANGED;
+ }
+ if (properties.keyExists(strings::nicknames)) {
+ const smart_objects::SmartArray* nicknames_array =
+ properties[strings::nicknames].asArray();
+
+ if (nicknames_array->empty() && !nicknames.empty()) {
+ return AppPropertiesState::NICKNAMES_CHANGED;
+ }
+
+ smart_objects::SmartArray::const_iterator it_begin =
+ nicknames_array->begin();
+ smart_objects::SmartArray::const_iterator it_end = nicknames_array->end();
+ for (; it_begin != it_end; ++it_begin) {
+ const auto result =
+ std::find(nicknames.begin(), nicknames.end(), (*it_begin).asString());
+ if (nicknames.end() == result) {
+ LOG4CXX_DEBUG(logger_,
+ "\"nicknames\" were changed, new value: "
+ << (*it_begin).asString());
+ return AppPropertiesState::NICKNAMES_CHANGED;
+ }
+ }
+ }
+ if (properties.keyExists(strings::hybrid_app_preference)) {
+ auto value = static_cast<mobile_apis::HybridAppPreference::eType>(
+ properties[strings::hybrid_app_preference].asUInt());
+ std::string hybrid_app_preference_str;
+ smart_objects::EnumConversionHelper<
+ mobile_apis::HybridAppPreference::eType>::
+ EnumToString(value, &hybrid_app_preference_str);
+ if (app_properties.hybrid_app_preference != hybrid_app_preference_str) {
+ LOG4CXX_DEBUG(
+ logger_,
+ "\"hybrid_app_preference\" was changed from: "
+ << app_properties.hybrid_app_preference << " to: "
+ << properties[strings::hybrid_app_preference].asString());
+ return AppPropertiesState::HYBRYD_APP_PROPERTIES_CHANGED;
+ }
+ }
+ return AppPropertiesState::NO_CHANGES;
+}
+
+bool PolicyHandler::IsNewApplication(const std::string& policy_app_id) const {
+ return policy_manager_->IsNewApplication(policy_app_id);
+}
+
+void PolicyHandler::OnSetAppProperties(
+ const smart_objects::SmartObject& properties) {
+ POLICY_LIB_CHECK_VOID();
+
+ const auto policy_app_id(properties[strings::policy_app_id].asString());
+ policy_manager_->InitCloudApp(policy_app_id);
+
+ bool auth_token_update = false;
+ if (properties.keyExists(strings::enabled)) {
+ const bool enabled = properties[strings::enabled].asBool();
+ policy_manager_->SetCloudAppEnabled(policy_app_id, enabled);
+ }
+ if (properties.keyExists(strings::auth_token)) {
+ const std::string auth_token = properties[strings::auth_token].asString();
+ policy_manager_->SetAppAuthToken(policy_app_id, auth_token);
+ auth_token_update = true;
+ }
+ if (properties.keyExists(strings::transport_type)) {
+ policy_manager_->SetAppCloudTransportType(
+ policy_app_id, properties[strings::transport_type].asString());
+ }
+ if (properties.keyExists(strings::endpoint)) {
+ policy_manager_->SetAppEndpoint(policy_app_id,
+ properties[strings::endpoint].asString());
+ }
+ if (properties.keyExists(strings::nicknames)) {
+ StringArray nicknames;
+ const smart_objects::SmartObject& nicknames_array =
+ properties[strings::nicknames];
+ for (size_t i = 0; i < nicknames_array.length(); ++i) {
+ nicknames.push_back(nicknames_array[i].asString());
+ }
+ policy_manager_->SetAppNicknames(policy_app_id, nicknames);
+ }
+ if (properties.keyExists(strings::hybrid_app_preference)) {
+ std::string hybrid_app_preference;
+
+ auto value = static_cast<mobile_apis::HybridAppPreference::eType>(
+ properties[strings::hybrid_app_preference].asUInt());
+ smart_objects::EnumConversionHelper<
+ mobile_apis::HybridAppPreference::eType>::
+ EnumToString(value, &hybrid_app_preference);
+ policy_manager_->SetHybridAppPreference(policy_app_id,
+ hybrid_app_preference);
+ }
+
+ if (auth_token_update) {
+ AppProperties app_properties;
+ if (policy_manager_->GetAppProperties(policy_app_id, app_properties)) {
+ OnAuthTokenUpdated(policy_app_id, app_properties.auth_token);
+ }
+ }
+}
+
+void PolicyHandler::OnLocalAppAdded() {
+ policy_manager_->OnLocalAppAdded();
}
void PolicyHandler::OnSetCloudAppProperties(
@@ -2087,9 +2254,8 @@ void PolicyHandler::OnSetCloudAppProperties(
if (properties.keyExists(strings::hybrid_app_preference)) {
std::string hybrid_app_preference;
- mobile_apis::HybridAppPreference::eType value =
- static_cast<mobile_apis::HybridAppPreference::eType>(
- properties[strings::hybrid_app_preference].asUInt());
+ auto value = static_cast<mobile_apis::HybridAppPreference::eType>(
+ properties[strings::hybrid_app_preference].asUInt());
smart_objects::EnumConversionHelper<
mobile_apis::HybridAppPreference::eType>::
EnumToString(value, &hybrid_app_preference);
@@ -2098,13 +2264,10 @@ void PolicyHandler::OnSetCloudAppProperties(
}
if (auth_token_update) {
- bool enabled;
- std::string end, cert, ctt, hap;
- std::string auth_token;
+ AppProperties app_properties;
- policy_manager_->GetCloudAppParameters(
- policy_app_id, enabled, end, cert, auth_token, ctt, hap);
- OnAuthTokenUpdated(policy_app_id, auth_token);
+ policy_manager_->GetAppProperties(policy_app_id, app_properties);
+ OnAuthTokenUpdated(policy_app_id, app_properties.auth_token);
}
}
diff --git a/src/components/application_manager/test/application_manager_impl_test.cc b/src/components/application_manager/test/application_manager_impl_test.cc
index b5fba2cc54..2c16048e97 100644
--- a/src/components/application_manager/test/application_manager_impl_test.cc
+++ b/src/components/application_manager/test/application_manager_impl_test.cc
@@ -112,6 +112,7 @@ const uint32_t kConnectionKey = 1232u;
const std::string kAppName = "appName";
const WindowID kDefaultWindowId =
mobile_apis::PredefinedWindows::DEFAULT_WINDOW;
+const std::vector<std::string> kEnabledLocalApps = {"localAppId"};
typedef hmi_apis::Common_ServiceStatusUpdateReason::eType
ServiceStatusUpdateReason;
@@ -119,6 +120,12 @@ typedef hmi_apis::Common_ServiceType::eType ServiceType;
typedef hmi_apis::Common_ServiceEvent::eType ServiceEvent;
typedef utils::Optional<ServiceStatusUpdateReason> UpdateReasonOptional;
+const std::string kPolicyAppID = "test policy id";
+transport_manager::DeviceInfo kDeviceInfo(1,
+ "mac",
+ "name",
+ "WEB_ENGINE_DEVICE");
+
#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT)
// Cloud application params
const std::string kEndpoint = "endpoint";
@@ -130,6 +137,12 @@ const mobile_api::HybridAppPreference::eType kHybridAppPreference =
mobile_api::HybridAppPreference::CLOUD;
const std::string kHybridAppPreferenceStr = "CLOUD";
const bool kEnabled = true;
+const policy::AppProperties app_properties(kEndpoint2,
+ kCertificate,
+ kEnabled,
+ kAuthToken,
+ kTransportType,
+ kHybridAppPreferenceStr);
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
} // namespace
@@ -222,6 +235,8 @@ class ApplicationManagerImplTest
smart_objects::SmartType_Map)));
ON_CALL(*mock_policy_handler_, GetStatisticManager())
.WillByDefault(Return(mock_statistics_manager_));
+ ON_CALL(*mock_policy_handler_, GetEnabledLocalApps())
+ .WillByDefault(Return(kEnabledLocalApps));
}
void CreateAppManager() {
@@ -311,6 +326,9 @@ class ApplicationManagerImplTest
void AddCloudAppToPendingDeviceMap();
void CreatePendingApplication();
#endif
+
+ void CreatePendingLocalApplication(const std::string& policy_app_id);
+
uint32_t app_id_;
NiceMock<policy_test::MockPolicySettings> mock_policy_settings_;
std::shared_ptr<NiceMock<resumption_test::MockResumptionData> > mock_storage_;
@@ -1249,7 +1267,9 @@ TEST_F(ApplicationManagerImplTest, UnregisterAnotherAppDuringAudioPassThru) {
EXPECT_CALL(*mock_app_2, device()).WillRepeatedly(Return(0));
EXPECT_CALL(*mock_app_2, mac_address())
.WillRepeatedly(ReturnRef(dummy_mac_address));
- EXPECT_CALL(*mock_app_2, policy_app_id()).WillRepeatedly(Return(""));
+ const std::string app2_policy_id = "app2_policy_id";
+ EXPECT_CALL(*mock_app_2, policy_app_id())
+ .WillRepeatedly(Return(app2_policy_id));
EXPECT_CALL(*mock_app_2, protocol_version())
.WillRepeatedly(
Return(protocol_handler::MajorProtocolVersion::PROTOCOL_VERSION_4));
@@ -1286,6 +1306,9 @@ TEST_F(ApplicationManagerImplTest, UnregisterAnotherAppDuringAudioPassThru) {
audio_type);
}
+ std::vector<std::string> enabled_apps = {app2_policy_id};
+ EXPECT_CALL(*mock_rpc_service_, ManageHMICommand(_, _)).Times(1);
+
// while running APT, app 1 is unregistered
app_manager_impl_->UnregisterApplication(
app_id_1, mobile_apis::Result::SUCCESS, false, true);
@@ -1668,14 +1691,8 @@ void ApplicationManagerImplTest::AddCloudAppToPendingDeviceMap() {
std::vector<std::string> enabled_apps{"1234"};
EXPECT_CALL(*mock_policy_handler_, GetEnabledCloudApps(_))
.WillOnce(SetArgReferee<0>(enabled_apps));
- EXPECT_CALL(*mock_policy_handler_, GetCloudAppParameters(_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<1>(kEnabled),
- SetArgReferee<2>(kEndpoint2),
- SetArgReferee<3>(kCertificate),
- SetArgReferee<4>(kAuthToken),
- SetArgReferee<5>(kTransportType),
- SetArgReferee<6>(kHybridAppPreferenceStr),
- Return(true)));
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
std::vector<std::string> nicknames{"CloudApp"};
EXPECT_CALL(*mock_policy_handler_, GetInitialAppData(_, _, _))
@@ -1700,14 +1717,8 @@ void ApplicationManagerImplTest::CreatePendingApplication() {
EXPECT_CALL(*mock_policy_handler_, GetStatisticManager())
.WillOnce(Return(std::shared_ptr<usage_statistics::StatisticsManager>(
new usage_statistics_test::MockStatisticsManager())));
- EXPECT_CALL(*mock_policy_handler_, GetCloudAppParameters(_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<1>(kEnabled),
- SetArgReferee<2>(kEndpoint2),
- SetArgReferee<3>(kCertificate),
- SetArgReferee<4>(kAuthToken),
- SetArgReferee<5>(kTransportType),
- SetArgReferee<6>(kHybridAppPreferenceStr),
- Return(true)));
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
// Expect Update app list
EXPECT_CALL(*mock_rpc_service_, ManageHMICommand(_, _)).Times(1);
app_manager_impl_->CreatePendingApplication(1, device_info, 1);
@@ -1737,14 +1748,8 @@ TEST_F(ApplicationManagerImplTest, SetPendingState) {
EXPECT_CALL(*mock_policy_handler_, GetEnabledCloudApps(_))
.WillOnce(SetArgReferee<0>(enabled_apps));
- EXPECT_CALL(*mock_policy_handler_, GetCloudAppParameters(_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<1>(kEnabled),
- SetArgReferee<2>(kEndpoint2),
- SetArgReferee<3>(kCertificate),
- SetArgReferee<4>(kAuthToken),
- SetArgReferee<5>(kTransportType),
- SetArgReferee<6>(kHybridAppPreferenceStr),
- Return(true)));
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
std::vector<std::string> nicknames{"CloudApp"};
EXPECT_CALL(*mock_policy_handler_, GetInitialAppData(_, _, _))
@@ -1887,14 +1892,8 @@ TEST_F(ApplicationManagerImplTest, PolicyIDByIconUrl_Success) {
std::vector<std::string> enabled_apps{"1234"};
EXPECT_CALL(*mock_policy_handler_, GetEnabledCloudApps(_))
.WillOnce(SetArgReferee<0>(enabled_apps));
- EXPECT_CALL(*mock_policy_handler_, GetCloudAppParameters(_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<1>(kEnabled),
- SetArgReferee<2>(kEndpoint2),
- SetArgReferee<3>(kCertificate),
- SetArgReferee<4>(kAuthToken),
- SetArgReferee<5>(kTransportType),
- SetArgReferee<6>(kHybridAppPreferenceStr),
- Return(true)));
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
std::vector<std::string> nicknames{"CloudApp"};
EXPECT_CALL(*mock_policy_handler_, GetInitialAppData(_, _, _))
@@ -1936,8 +1935,99 @@ TEST_F(ApplicationManagerImplTest, SetIconFileFromSystemRequest_Success) {
app_manager_impl_->SetIconFileFromSystemRequest("1234");
EXPECT_TRUE(file_system::RemoveDirectory(kDirectoryName, true));
}
-
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
+
+void ApplicationManagerImplTest::CreatePendingLocalApplication(
+ const std::string& policy_app_id) {
+ // CreatePendingApplication
+ std::vector<std::string> nicknames{"PendingApplication"};
+ EXPECT_CALL(*mock_policy_handler_, GetInitialAppData(policy_app_id, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(nicknames), Return(true)));
+ EXPECT_CALL(mock_connection_handler_, GetWebEngineDeviceInfo())
+ .WillOnce(ReturnRef(kDeviceInfo));
+ EXPECT_CALL(*mock_policy_handler_, GetStatisticManager())
+ .WillOnce(Return(std::shared_ptr<usage_statistics::StatisticsManager>(
+ new usage_statistics_test::MockStatisticsManager())));
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
+ // Expect NO Update app list
+ EXPECT_CALL(*mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+ app_manager_impl_->CreatePendingLocalApplication(policy_app_id);
+ AppsWaitRegistrationSet app_list =
+ app_manager_impl_->AppsWaitingForRegistration().GetData();
+ EXPECT_EQ(1u, app_list.size());
+}
+
+TEST_F(ApplicationManagerImplTest, CreatePendingApplicationByPolicyAppID) {
+ CreatePendingLocalApplication(kPolicyAppID);
+}
+
+TEST_F(ApplicationManagerImplTest, RemoveExistingPendingApplication_SUCCESS) {
+ CreatePendingLocalApplication(kPolicyAppID);
+ auto app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ ASSERT_EQ(1u, app_list.size());
+
+ app_manager_impl_->RemovePendingApplication(kPolicyAppID);
+ app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ EXPECT_TRUE(app_list.empty());
+}
+
+TEST_F(ApplicationManagerImplTest,
+ RemovePendingApplicationFromEmptyList_NoAppRemoved_SUCCESS) {
+ auto app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ ASSERT_TRUE(app_list.empty());
+
+ app_manager_impl_->RemovePendingApplication(kPolicyAppID);
+ app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ EXPECT_TRUE(app_list.empty());
+}
+
+TEST_F(
+ ApplicationManagerImplTest,
+ OnWebEngineDeviceCreated_NoEnabledLocalApps_PendingApplicationNotCreatedAndNoUpdateAppList) {
+ std::vector<std::string> enabled_apps;
+ EXPECT_CALL(*mock_policy_handler_, GetEnabledLocalApps())
+ .WillOnce(Return(enabled_apps));
+ EXPECT_CALL(*mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
+
+ app_manager_impl_->OnWebEngineDeviceCreated();
+
+ auto app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ EXPECT_TRUE(app_list.empty());
+}
+
+TEST_F(
+ ApplicationManagerImplTest,
+ OnWebEngineDeviceCreated_PendingApplicationCreatedAndUpdateAppListSentToHMI) {
+ std::vector<std::string> enabled_apps = {"app1"};
+ std::vector<std::string> nicknames{"PendingApplication"};
+
+ EXPECT_CALL(*mock_policy_handler_, GetEnabledLocalApps())
+ .WillOnce(Return(enabled_apps));
+ EXPECT_CALL(*mock_rpc_service_, ManageHMICommand(_, _)).Times(1);
+ EXPECT_CALL(*mock_policy_handler_, GetAppProperties(_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
+ EXPECT_CALL(*mock_policy_handler_, GetInitialAppData(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(nicknames), Return(true)));
+ EXPECT_CALL(mock_connection_handler_, GetWebEngineDeviceInfo())
+ .WillOnce(ReturnRef(kDeviceInfo));
+
+ app_manager_impl_->OnWebEngineDeviceCreated();
+
+ auto app_list = app_manager_impl_->AppsWaitingForRegistration().GetData();
+ EXPECT_EQ(1u, app_list.size());
+}
+
+TEST_F(ApplicationManagerImplTest, AddAndRemoveQueryAppDevice_SUCCESS) {
+ const connection_handler::DeviceHandle device_handle = 1u;
+ ASSERT_FALSE(app_manager_impl_->IsAppsQueriedFrom(device_handle));
+
+ app_manager_impl_->OnQueryAppsRequest(device_handle);
+ EXPECT_TRUE(app_manager_impl_->IsAppsQueriedFrom(device_handle));
+ app_manager_impl_->RemoveDevice(device_handle);
+ EXPECT_FALSE(app_manager_impl_->IsAppsQueriedFrom(device_handle));
+}
+
} // namespace application_manager_test
} // namespace components
} // namespace test
diff --git a/src/components/application_manager/test/include/application_manager/commands/commands_test.h b/src/components/application_manager/test/include/application_manager/commands/commands_test.h
index a047de81b9..fdaef2c716 100644
--- a/src/components/application_manager/test/include/application_manager/commands/commands_test.h
+++ b/src/components/application_manager/test/include/application_manager/commands/commands_test.h
@@ -245,6 +245,21 @@ MATCHER_P(HMIResultCodeIs, result_code, "") {
.asInt());
}
+MATCHER_P3(
+ HMIMessageParametersAre, correlation_id, function_id, result_code, "") {
+ using namespace application_manager;
+
+ const bool corr_ids_eq =
+ correlation_id ==
+ (*arg)[strings::params][strings::correlation_id].asInt();
+ const bool func_ids_eq =
+ (*arg)[strings::params][strings::function_id].asInt() == function_id;
+ const bool res_codes_eq =
+ (*arg)[strings::params][hmi_response::code].asInt() == result_code;
+
+ return corr_ids_eq && func_ids_eq && res_codes_eq;
+}
+
MATCHER_P3(MobileResponseIs, result_code, result_info, result_success, "") {
mobile_apis::Result::eType code = static_cast<mobile_apis::Result::eType>(
(*arg)[am::strings::msg_params][am::strings::result_code].asInt());
diff --git a/src/components/application_manager/test/include/application_manager/mock_message_helper.h b/src/components/application_manager/test/include/application_manager/mock_message_helper.h
index 072199082e..eb3c97bfff 100644
--- a/src/components/application_manager/test/include/application_manager/mock_message_helper.h
+++ b/src/components/application_manager/test/include/application_manager/mock_message_helper.h
@@ -269,6 +269,9 @@ class MockMessageHelper {
void(ApplicationConstSharedPtr app,
const bool is_unexpected_disconnect,
ApplicationManager& app_mngr));
+ MOCK_METHOD2(CreateOnAppPropertiesChangeNotification,
+ smart_objects::SmartObjectSPtr(const std::string& policy_app_id,
+ ApplicationManager& app_mngr));
MOCK_METHOD4(SendLaunchApp,
void(const uint32_t connection_key,
const std::string& urlSchema,
diff --git a/src/components/application_manager/test/mock_message_helper.cc b/src/components/application_manager/test/mock_message_helper.cc
index 628fd97ae8..959bbf5bd0 100755..100644
--- a/src/components/application_manager/test/mock_message_helper.cc
+++ b/src/components/application_manager/test/mock_message_helper.cc
@@ -485,6 +485,13 @@ bool MessageHelper::CreateHMIApplicationStruct(
app, session_observer, policy_handler, output, app_mngr);
}
+smart_objects::SmartObjectSPtr
+MessageHelper::CreateOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id, ApplicationManager& app_mngr) {
+ return MockMessageHelper::message_helper_mock()
+ ->CreateOnAppPropertiesChangeNotification(policy_app_id, app_mngr);
+}
+
void MessageHelper::SendOnAppUnregNotificationToHMI(
ApplicationConstSharedPtr app,
const bool is_unexpected_disconnect,
diff --git a/src/components/application_manager/test/policy_handler_test.cc b/src/components/application_manager/test/policy_handler_test.cc
index 961f338ca4..3f37cec657 100644
--- a/src/components/application_manager/test/policy_handler_test.cc
+++ b/src/components/application_manager/test/policy_handler_test.cc
@@ -72,6 +72,8 @@
#include "policy/usage_statistics/mock_statistics_manager.h"
#include "protocol_handler/mock_session_observer.h"
+#include "smart_objects/enum_schema_item.h"
+
namespace test {
namespace components {
namespace policy_handler_test {
@@ -272,6 +274,19 @@ class PolicyHandlerTest : public ::testing::Test {
hmi_types.push_back(hmi_type);
return hmi_types;
}
+
+ void SetExpectationsAndCheckCloudAppPropertiesStatus(
+ const policy::AppProperties& app_properties,
+ const smart_objects::SmartObject& properties,
+ const policy::PolicyHandlerInterface::AppPropertiesState&
+ app_properties_state) {
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
+ EXPECT_CALL(*mock_policy_manager_, GetInitialAppData(kPolicyAppId_, _, _));
+ EXPECT_EQ(
+ app_properties_state,
+ policy_handler_.GetAppPropertiesStatus(properties, kPolicyAppId_));
+ }
};
namespace {
@@ -2687,6 +2702,12 @@ TEST_F(PolicyHandlerTest, OnSetCloudAppProperties_AllProperties_SUCCESS) {
mobile_apis::HybridAppPreference::CLOUD;
std::string hybrid_app_preference_str = "CLOUD";
std::string endpoint = "anEndpoint";
+ const policy::AppProperties app_properties(endpoint,
+ " ",
+ enabled,
+ auth_token,
+ cloud_transport_type,
+ hybrid_app_preference_str);
StringArray nicknames_vec;
nicknames_vec.push_back(app_name);
@@ -2720,9 +2741,8 @@ TEST_F(PolicyHandlerTest, OnSetCloudAppProperties_AllProperties_SUCCESS) {
EXPECT_CALL(*mock_policy_manager_,
SetHybridAppPreference(kPolicyAppId_, hybrid_app_preference_str));
EXPECT_CALL(*mock_policy_manager_, SetAppEndpoint(kPolicyAppId_, endpoint));
- EXPECT_CALL(*mock_policy_manager_,
- GetCloudAppParameters(kPolicyAppId_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<4>(auth_token), Return(true)));
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
EXPECT_CALL(app_manager_, RefreshCloudAppInformation());
EXPECT_CALL(policy_handler_observer,
OnAuthTokenUpdated(kPolicyAppId_, auth_token));
@@ -2740,38 +2760,370 @@ TEST_F(PolicyHandlerTest, GetCloudAppParameters_AllProperties_SUCCESS) {
std::string hybrid_app_preference_str = "CLOUD";
std::string endpoint = "anEndpoint";
+ const policy::AppProperties app_properties(endpoint,
+ certificate,
+ enabled,
+ auth_token,
+ cloud_transport_type,
+ hybrid_app_preference_str);
+
application_manager_test::MockPolicyHandlerObserver policy_handler_observer;
policy_handler_.add_listener(&policy_handler_observer);
- EXPECT_CALL(*mock_policy_manager_,
- GetCloudAppParameters(kPolicyAppId_, _, _, _, _, _, _))
- .WillOnce(DoAll(SetArgReferee<1>(enabled),
- SetArgReferee<2>(endpoint),
- SetArgReferee<3>(certificate),
- SetArgReferee<4>(auth_token),
- SetArgReferee<5>(cloud_transport_type),
- SetArgReferee<6>(hybrid_app_preference_str),
- Return(true)));
-
- bool enabled_out;
- std::string endpoint_out;
- std::string cert_out;
- std::string auth_token_out;
- std::string ctt_out;
- std::string hap_out;
- EXPECT_TRUE(policy_handler_.GetCloudAppParameters(kPolicyAppId_,
- enabled_out,
- endpoint_out,
- cert_out,
- auth_token_out,
- ctt_out,
- hap_out));
- EXPECT_EQ(enabled, enabled_out);
- EXPECT_EQ(endpoint, endpoint_out);
- EXPECT_EQ(certificate, cert_out);
- EXPECT_EQ(auth_token, auth_token_out);
- EXPECT_EQ(cloud_transport_type, ctt_out);
- EXPECT_EQ(hybrid_app_preference_str, hap_out);
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(app_properties), Return(true)));
+
+ policy::AppProperties out_app_properties;
+ EXPECT_TRUE(
+ policy_handler_.GetAppProperties(kPolicyAppId_, out_app_properties));
+ EXPECT_EQ(app_properties.enabled, out_app_properties.enabled);
+ EXPECT_EQ(app_properties.endpoint, out_app_properties.endpoint);
+ EXPECT_EQ(app_properties.certificate, out_app_properties.certificate);
+ EXPECT_EQ(app_properties.auth_token, out_app_properties.auth_token);
+ EXPECT_EQ(app_properties.transport_type, out_app_properties.transport_type);
+ EXPECT_EQ(app_properties.hybrid_app_preference,
+ out_app_properties.hybrid_app_preference);
+}
+
+TEST_F(PolicyHandlerTest, SendOnAppPropertiesChangeNotification_SUCCESS) {
+ using namespace smart_objects;
+ auto notification = std::make_shared<SmartObject>(SmartType_Null);
+
+ ON_CALL(app_manager_, GetRPCService())
+ .WillByDefault(ReturnRef(mock_rpc_service_));
+
+ EXPECT_CALL(mock_message_helper_,
+ CreateOnAppPropertiesChangeNotification(kPolicyAppId_, _))
+ .WillOnce(Return(notification));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(notification, commands::Command::SOURCE_HMI));
+
+ policy_handler_.SendOnAppPropertiesChangeNotification(kPolicyAppId_);
+}
+
+TEST_F(PolicyHandlerTest, GetApplicationPolicyIDs_GetEmptyIDsVector_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ std::vector<std::string> app_ids_vector;
+ ON_CALL(*mock_policy_manager_, GetApplicationPolicyIDs())
+ .WillByDefault(Return(app_ids_vector));
+
+ EXPECT_CALL(*mock_policy_manager_, GetApplicationPolicyIDs());
+ EXPECT_EQ(app_ids_vector, policy_handler_.GetApplicationPolicyIDs());
+}
+
+TEST_F(PolicyHandlerTest,
+ GetApplicationPolicyIDs_GetIDFromAppIDsVectorWithWrongIDs_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ std::vector<std::string> app_ids_vector = {policy::kDefaultId,
+ policy::kPreDataConsentId,
+ policy::kDeviceId,
+ kPolicyAppId_};
+ ON_CALL(*mock_policy_manager_, GetApplicationPolicyIDs())
+ .WillByDefault(Return(app_ids_vector));
+
+ EXPECT_CALL(*mock_policy_manager_, GetApplicationPolicyIDs());
+
+ auto policy_ids = policy_handler_.GetApplicationPolicyIDs();
+ EXPECT_NE(app_ids_vector, policy_ids);
+ EXPECT_EQ(1u, policy_ids.size());
+ EXPECT_EQ(kPolicyAppId_, policy_ids[0]);
+}
+
+TEST_F(PolicyHandlerTest, CheckCloudAppEnabled_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ policy::AppProperties out_app_properties;
+ out_app_properties.enabled = true;
+
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(DoAll(SetArgReferee<1>(out_app_properties), Return(true)));
+ EXPECT_TRUE(policy_handler_.CheckCloudAppEnabled(kPolicyAppId_));
+}
+
+TEST_F(PolicyHandlerTest, CheckCloudAppNotEnabled_SUCCESS) {
+ ChangePolicyManagerToMock();
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _));
+ EXPECT_FALSE(policy_handler_.CheckCloudAppEnabled(kPolicyAppId_));
+}
+
+TEST_F(PolicyHandlerTest, OnLocalAppAdded_SUCCESS) {
+ ChangePolicyManagerToMock();
+ EXPECT_CALL(*mock_policy_manager_, OnLocalAppAdded());
+ policy_handler_.OnLocalAppAdded();
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_NoPropertiesChanged) {
+ ChangePolicyManagerToMock();
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(Return(false));
+ EXPECT_CALL(*mock_policy_manager_, GetInitialAppData(kPolicyAppId_, _, _))
+ .WillOnce(Return(false));
+ EXPECT_EQ(policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES,
+ policy_handler_.GetAppPropertiesStatus(properties, kPolicyAppId_));
+}
+
+TEST_F(PolicyHandlerTest,
+ GetAppPropertiesStatus_EnableFlagSwitchChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ policy::AppProperties app_properties;
+ app_properties.enabled = false;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::enabled] = !app_properties.enabled;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::ENABLED_FLAG_SWITCH);
+}
+
+TEST_F(PolicyHandlerTest,
+ GetAppPropertiesStatus_EnableFlagSwitchNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ policy::AppProperties app_properties;
+ app_properties.enabled = false;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::enabled] = app_properties.enabled;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_AuthTokenChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentToken = "kCurrentToken";
+ const std::string kNewToken = "kNewToken";
+
+ policy::AppProperties app_properties;
+ app_properties.auth_token = kCurrentToken;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::auth_token] = kNewToken;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::AUTH_TOKEN_CHANGED);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_AuthTokenNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentToken = "kCurrentToken";
+
+ policy::AppProperties app_properties;
+ app_properties.auth_token = kCurrentToken;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::auth_token] = app_properties.auth_token;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_TransportTypeChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentTransportType = "kCurrentTransportType";
+ const std::string kNewTransportType = "kNewTransportType";
+
+ policy::AppProperties app_properties;
+ app_properties.transport_type = kCurrentTransportType;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::cloud_transport_type] = kNewTransportType;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::
+ TRANSPORT_TYPE_CHANGED);
+}
+
+TEST_F(PolicyHandlerTest,
+ GetAppPropertiesStatus_TransportTypeNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentTransportType = "kCurrentTransportType";
+
+ policy::AppProperties app_properties;
+ app_properties.transport_type = kCurrentTransportType;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::cloud_transport_type] = app_properties.transport_type;
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_EndPointChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentEndPoint = "kCurrentEndPoint";
+ const std::string kNewEndPoint = "kNewEndPoint";
+
+ policy::AppProperties app_properties;
+ app_properties.endpoint = kCurrentEndPoint;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::endpoint] = kNewEndPoint;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::ENDPOINT_CHANGED);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_EndPointNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kCurrentEndPoint = "kCurrentEndPoint";
+
+ policy::AppProperties app_properties;
+ app_properties.endpoint = kCurrentEndPoint;
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::endpoint] = app_properties.endpoint;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_NicknameChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kFakeNickname = "fake_nickname";
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::nicknames] =
+ smart_objects::SmartObject(smart_objects::SmartType_Array);
+ properties[strings::nicknames].asArray()->push_back(
+ smart_objects::SmartObject(kFakeNickname));
+
+ std::shared_ptr<policy::StringArray> nicknames =
+ std::make_shared<policy::StringArray>();
+
+ const auto expected_app_properties_state =
+ policy::PolicyHandlerInterface::AppPropertiesState::NICKNAMES_CHANGED;
+
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_policy_manager_, GetInitialAppData(kPolicyAppId_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(*nicknames), Return(true)));
+ EXPECT_EQ(expected_app_properties_state,
+ policy_handler_.GetAppPropertiesStatus(properties, kPolicyAppId_));
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_NicknameNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const std::string kFakeNickname = "fake_nickname";
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::nicknames] =
+ smart_objects::SmartObject(smart_objects::SmartType_Array);
+ properties[strings::nicknames].asArray()->push_back(
+ smart_objects::SmartObject(kFakeNickname));
+
+ std::shared_ptr<policy::StringArray> nicknames =
+ std::make_shared<policy::StringArray>();
+ nicknames->push_back(kFakeNickname);
+
+ const auto expected_app_properties_state =
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES;
+
+ EXPECT_CALL(*mock_policy_manager_, GetAppProperties(kPolicyAppId_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_policy_manager_, GetInitialAppData(kPolicyAppId_, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(*nicknames), Return(true)));
+ EXPECT_EQ(expected_app_properties_state,
+ policy_handler_.GetAppPropertiesStatus(properties, kPolicyAppId_));
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_HybridAppChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const auto kCurrentHybridAppProperties =
+ mobile_apis::HybridAppPreference::eType::CLOUD;
+ const auto kNewHybridAppProperties =
+ mobile_apis::HybridAppPreference::eType::MOBILE;
+
+ policy::AppProperties app_properties;
+ smart_objects::EnumConversionHelper<mobile_apis::HybridAppPreference::eType>::
+ EnumToString(kCurrentHybridAppProperties,
+ &app_properties.hybrid_app_preference);
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::hybrid_app_preference] = kNewHybridAppProperties;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::
+ HYBRYD_APP_PROPERTIES_CHANGED);
+}
+
+TEST_F(PolicyHandlerTest, GetAppPropertiesStatus_HybridAppNotChanged_SUCCESS) {
+ ChangePolicyManagerToMock();
+
+ const auto kCurrentHybridAppProperties =
+ mobile_apis::HybridAppPreference::eType::CLOUD;
+
+ policy::AppProperties app_properties;
+ smart_objects::EnumConversionHelper<mobile_apis::HybridAppPreference::eType>::
+ EnumToString(kCurrentHybridAppProperties,
+ &app_properties.hybrid_app_preference);
+
+ smart_objects::SmartObject properties;
+ properties[strings::app_id] = kPolicyAppId_;
+ properties[strings::hybrid_app_preference] = kCurrentHybridAppProperties;
+
+ SetExpectationsAndCheckCloudAppPropertiesStatus(
+ app_properties,
+ properties,
+ policy::PolicyHandlerInterface::AppPropertiesState::NO_CHANGES);
+}
+
+TEST_F(PolicyHandlerTest, GetEnabledLocalApps_SUCCESS) {
+ ChangePolicyManagerToMock();
+ std::vector<std::string> enabled_local_apps;
+
+ EXPECT_CALL(*mock_policy_manager_, GetEnabledLocalApps())
+ .WillOnce(Return(enabled_local_apps));
+ EXPECT_EQ(enabled_local_apps, policy_handler_.GetEnabledLocalApps());
+
+ enabled_local_apps.push_back("local_app");
+ EXPECT_CALL(*mock_policy_manager_, GetEnabledLocalApps())
+ .WillOnce(Return(enabled_local_apps));
+ EXPECT_EQ(enabled_local_apps, policy_handler_.GetEnabledLocalApps());
}
} // namespace policy_handler_test
diff --git a/src/components/config_profile/include/config_profile/profile.h b/src/components/config_profile/include/config_profile/profile.h
index 5489a962e8..76c66c7c7b 100644
--- a/src/components/config_profile/include/config_profile/profile.h
+++ b/src/components/config_profile/include/config_profile/profile.h
@@ -413,6 +413,40 @@ class Profile : public protocol_handler::ProtocolHandlerSettings,
const std::string& transport_manager_tcp_adapter_network_interface()
const OVERRIDE;
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ /**
+ * @brief Returns websocket server address
+ */
+ const std::string& websocket_server_address() const OVERRIDE;
+
+ /**
+ * @brief Returns port for websocket server
+ */
+ uint16_t websocket_server_port() const OVERRIDE;
+#ifdef ENABLE_SECURITY
+ /**
+ * @brief Returns ws server certificate path to pem file
+ */
+ const std::string& ws_server_cert_path() const OVERRIDE;
+
+ /**
+ * @brief Returns ws server CA certificate path to pem file
+ */
+ const std::string& ws_server_ca_cert_path() const OVERRIDE;
+
+ /**
+ * @brief Returns ws server key path to pem file
+ */
+ const std::string& ws_server_key_path() const OVERRIDE;
+
+ /**
+ * @brief Returns bool flag indicating whether WSS settings were setup
+ * correctly
+ */
+ const bool wss_server_supported() const OVERRIDE;
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+
/**
* @brief Returns retry timeout for cloud app connections
*/
@@ -991,6 +1025,16 @@ class Profile : public protocol_handler::ProtocolHandlerSettings,
std::string system_files_path_;
uint16_t transport_manager_tcp_adapter_port_;
std::string transport_manager_tcp_adapter_network_interface_;
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ std::string websocket_server_address_;
+ uint16_t websocket_server_port_;
+#ifdef ENABLE_SECURITY
+ std::string ws_server_cert_path_;
+ std::string ws_server_ca_cert_path_;
+ std::string ws_server_key_path_;
+ bool is_wss_settings_setup_;
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
uint32_t cloud_app_retry_timeout_;
uint16_t cloud_app_max_retry_attempts_;
std::vector<uint8_t> bluetooth_uuid_;
diff --git a/src/components/config_profile/src/profile.cc b/src/components/config_profile/src/profile.cc
index dd0dc50f44..3037b66fdd 100644
--- a/src/components/config_profile/src/profile.cc
+++ b/src/components/config_profile/src/profile.cc
@@ -157,6 +157,15 @@ const char* kMaxSupportedProtocolVersionKey = "MaxSupportedProtocolVersion";
const char* kUseLastStateKey = "UseLastState";
const char* kTCPAdapterPortKey = "TCPAdapterPort";
const char* kTCPAdapterNetworkInterfaceKey = "TCPAdapterNetworkInterface";
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+const char* kWebSocketServerAddressKey = "WebSocketServerAddress";
+const char* kWebSocketServerPortKey = "WebSocketServerPort";
+#ifdef ENABLE_SECURITY
+const char* kWSServerCertificatePathKey = "WSServerCertificatePath";
+const char* kWSServerCACertificaePathKey = "WSServerCACertificatePath";
+const char* kWSServerKeyPathKey = "WSServerKeyPath";
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
const char* kCloudAppRetryTimeoutKey = "CloudAppRetryTimeout";
const char* kCloudAppMaxRetryAttemptsKey = "CloudAppMaxRetryAttempts";
const char* kServerPortKey = "ServerPort";
@@ -305,6 +314,7 @@ const char* kDefaultPoliciesSnapshotFileName = "sdl_snapshot.json";
const char* kDefaultHmiCapabilitiesFileName = "hmi_capabilities.json";
const char* kDefaultPreloadedPTFileName = "sdl_preloaded_pt.json";
const char* kDefaultServerAddress = "127.0.0.1";
+const char* kDefaultWebsocketServerAddress = "0.0.0.0";
const char* kDefaultAppInfoFileName = "app_info.dat";
const char* kDefaultSystemFilesPath = "/tmp/fs/mp/images/ivsu_cache";
const char* kDefaultPluginsPath = "plugins";
@@ -334,6 +344,7 @@ const uint32_t kDefaultHubProtocolIndex = 0;
const uint32_t kDefaultHeartBeatTimeout = 0;
const uint16_t kDefaultMaxSupportedProtocolVersion = 5;
const uint16_t kDefautTransportManagerTCPPort = 12345;
+const uint16_t kDefaultWebSocketServerPort = 2020;
const uint16_t kDefaultCloudAppRetryTimeout = 1000;
const uint16_t kDefaultCloudAppMaxRetryAttempts = 5;
const uint16_t kDefaultServerPort = 8087;
@@ -495,6 +506,10 @@ Profile::Profile()
, supported_diag_modes_()
, system_files_path_(kDefaultSystemFilesPath)
, transport_manager_tcp_adapter_port_(kDefautTransportManagerTCPPort)
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ , websocket_server_address_(kDefaultWebsocketServerAddress)
+ , websocket_server_port_(kDefaultWebSocketServerPort)
+#endif
, cloud_app_retry_timeout_(kDefaultCloudAppRetryTimeout)
, cloud_app_max_retry_attempts_(kDefaultCloudAppMaxRetryAttempts)
, tts_delimiter_(kDefaultTtsDelimiter)
@@ -831,6 +846,33 @@ const std::string& Profile::transport_manager_tcp_adapter_network_interface()
return transport_manager_tcp_adapter_network_interface_;
}
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+const std::string& Profile::websocket_server_address() const {
+ return websocket_server_address_;
+}
+
+uint16_t Profile::websocket_server_port() const {
+ return websocket_server_port_;
+}
+#ifdef ENABLE_SECURITY
+const std::string& Profile::ws_server_cert_path() const {
+ return ws_server_cert_path_;
+}
+
+const std::string& Profile::ws_server_key_path() const {
+ return ws_server_key_path_;
+}
+
+const std::string& Profile::ws_server_ca_cert_path() const {
+ return ws_server_ca_cert_path_;
+}
+
+const bool Profile::wss_server_supported() const {
+ return is_wss_settings_setup_;
+}
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+
uint32_t Profile::cloud_app_retry_timeout() const {
return cloud_app_retry_timeout_;
}
@@ -1240,6 +1282,7 @@ void Profile::UpdateValues() {
ReadStringValue(
&cert_path_, "", kSecuritySection, kSecurityCertificatePathKey);
+
ReadStringValue(
&ca_cert_path_, "", kSecuritySection, kSecurityCACertificatePathKey);
@@ -1867,6 +1910,58 @@ void Profile::UpdateValues() {
LOG_UPDATED_VALUE(transport_manager_tcp_adapter_network_interface_,
kTCPAdapterNetworkInterfaceKey,
kTransportManagerSection);
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ // Websocket server address
+ ReadStringValue(&websocket_server_address_,
+ kDefaultWebsocketServerAddress,
+ kTransportManagerSection,
+ kWebSocketServerAddressKey);
+
+ LOG_UPDATED_VALUE(websocket_server_address_,
+ kWebSocketServerAddressKey,
+ kTransportManagerSection);
+
+ // Websocket non-secured server port
+ ReadUIntValue(&websocket_server_port_,
+ kDefaultWebSocketServerPort,
+ kTransportManagerSection,
+ kWebSocketServerPortKey);
+
+ LOG_UPDATED_VALUE(websocket_server_port_,
+ kWebSocketServerPortKey,
+ kTransportManagerSection);
+
+#ifdef ENABLE_SECURITY
+ const bool is_ws_server_cert_setup =
+ ReadStringValue(&ws_server_cert_path_,
+ "",
+ kTransportManagerSection,
+ kWSServerCertificatePathKey);
+
+ LOG_UPDATED_VALUE(ws_server_cert_path_,
+ kWSServerCertificatePathKey,
+ kTransportManagerSection);
+
+ const bool is_ws_server_key_setup = ReadStringValue(
+ &ws_server_key_path_, "", kTransportManagerSection, kWSServerKeyPathKey);
+
+ LOG_UPDATED_VALUE(
+ ws_server_key_path_, kWSServerKeyPathKey, kTransportManagerSection);
+
+ const bool is_ws_ca_cert_setup =
+ ReadStringValue(&ws_server_ca_cert_path_,
+ "",
+ kTransportManagerSection,
+ kWSServerCACertificaePathKey);
+
+ LOG_UPDATED_VALUE(ws_server_ca_cert_path_,
+ kWSServerCACertificaePathKey,
+ kTransportManagerSection);
+
+ is_wss_settings_setup_ =
+ is_ws_server_cert_setup && is_ws_server_key_setup && is_ws_ca_cert_setup;
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
ReadUIntValue(&cloud_app_retry_timeout_,
kDefaultCloudAppRetryTimeout,
diff --git a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
index b7b791a5c1..b2b4c5a970 100644
--- a/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
+++ b/src/components/connection_handler/include/connection_handler/connection_handler_impl.h
@@ -606,6 +606,10 @@ class ConnectionHandlerImpl
const transport_manager::ConnectionUID secondary_connection_handle)
OVERRIDE;
+ const transport_manager::DeviceInfo& GetWebEngineDeviceInfo() const OVERRIDE;
+
+ void CreateWebEngineDevice() OVERRIDE;
+
private:
/**
* \brief Disconnect application.
@@ -646,7 +650,7 @@ class ConnectionHandlerImpl
* \brief List of devices
*/
DeviceMap device_list_;
-
+ mutable sync_primitives::RWLock device_list_lock_;
/**
* @brief session/connection map
*/
diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc
index 4a51d00558..c8b4268bf0 100644
--- a/src/components/connection_handler/src/connection_handler_impl.cc
+++ b/src/components/connection_handler/src/connection_handler_impl.cc
@@ -120,6 +120,7 @@ void ConnectionHandlerImpl::OnDeviceListUpdated(
const std::vector<transport_manager::DeviceInfo>&) {
LOG4CXX_AUTO_TRACE(logger_);
sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
+ sync_primitives::AutoReadLock lock(device_list_lock_);
if (connection_handler_observer_) {
connection_handler_observer_->OnDeviceListUpdated(device_list_);
}
@@ -152,14 +153,21 @@ void ConnectionHandlerImpl::OnDeviceAdded(
device_info.mac_address(),
device_info.connection_type());
- auto result = device_list_.insert(std::make_pair(handle, device));
+ {
+ sync_primitives::AutoWriteLock write_lock(device_list_lock_);
+ auto result = device_list_.insert(std::make_pair(handle, device));
- if (!result.second) {
- LOG4CXX_ERROR(logger_,
- "Device with handle " << handle
- << " is known already. "
- "Information won't be updated.");
- return;
+ if (!result.second) {
+ LOG4CXX_ERROR(logger_,
+ "Device with handle " << handle
+ << " is known already. "
+ "Information won't be updated.");
+ return;
+ }
+ }
+ if (device_info.name() ==
+ transport_manager::webengine_constants::kWebEngineDeviceName) {
+ connection_handler_observer_->OnWebEngineDeviceCreated();
}
}
@@ -189,7 +197,10 @@ void ConnectionHandlerImpl::OnDeviceRemoved(
}
sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
- device_list_.erase(device_info.device_handle());
+ {
+ sync_primitives::AutoWriteLock lock(device_list_lock_);
+ device_list_.erase(device_info.device_handle());
+ }
if (connection_handler_observer_) {
connection_handler_observer_->RemoveDevice(device_info.device_handle());
}
@@ -219,6 +230,8 @@ struct DeviceFinder {
void ConnectionHandlerImpl::OnDeviceSwitchingStart(
const std::string& device_uid_from, const std::string& device_uid_to) {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
+
auto device_from =
std::find_if(device_list_.begin(),
device_list_.end(),
@@ -260,10 +273,14 @@ void ConnectionHandlerImpl::OnConnectionPending(
<< device_info.name() << " "
<< device_info.mac_address() << " "
<< device_info.connection_type());
- DeviceMap::iterator it = device_list_.find(device_info.device_handle());
- if (device_list_.end() == it) {
- LOG4CXX_ERROR(logger_, "Unknown device!");
- return;
+ {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
+ auto it = device_list_.find(device_info.device_handle());
+
+ if (device_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown device!");
+ return;
+ }
}
LOG4CXX_DEBUG(logger_,
"Add Pending Connection #" << connection_id << " to the list.");
@@ -310,11 +327,15 @@ void ConnectionHandlerImpl::OnConnectionEstablished(
<< device_info.device_handle() << " " << device_info.name()
<< " " << device_info.mac_address() << " "
<< device_info.connection_type());
- DeviceMap::iterator it = device_list_.find(device_info.device_handle());
- if (device_list_.end() == it) {
- LOG4CXX_ERROR(logger_, "Unknown device!");
- return;
+ {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
+ auto it = device_list_.find(device_info.device_handle());
+ if (device_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown device!");
+ return;
+ }
}
+
LOG4CXX_DEBUG(logger_,
"Add Connection #" << connection_id << " to the list.");
sync_primitives::AutoWriteLock lock(connection_list_lock_);
@@ -413,8 +434,9 @@ void ConnectionHandlerImpl::OnSessionStartedCallback(
// In case this is a Session running on a Secondary Transport, we need to
// find the Sessions's primary transport. In this case, "connection_handle"
- // reflects the secondary transport, which we need for the various callbacks,
- // so they can send appropriate Ack or NAK messages on the correct transport.
+ // reflects the secondary transport, which we need for the various
+ // callbacks, so they can send appropriate Ack or NAK messages on the
+ // correct transport.
transport_manager::ConnectionUID primary_connection_handle =
connection_handle;
SessionTransports st = GetSessionTransports(session_id);
@@ -533,7 +555,8 @@ void ConnectionHandlerImpl::NotifyServiceStartedResult(
start_service_context_map_.erase(it);
}
- // We need the context's primary connection so we can manage its services list
+ // We need the context's primary connection so we can manage its services
+ // list
Connection* connection = NULL;
{
sync_primitives::AutoReadLock lock(connection_list_lock_);
@@ -646,8 +669,9 @@ uint32_t ConnectionHandlerImpl::OnSessionEndedCallback(
// In case this is a Session running on a Secondary Transport, we need to
// find the Sessions's primary transport. In this case, "connection_handle"
- // reflects the secondary transport, which we need for the various callbacks,
- // so they can send appropriate Ack or NAK messages on the correct transport.
+ // reflects the secondary transport, which we need for the various
+ // callbacks, so they can send appropriate Ack or NAK messages on the
+ // correct transport.
transport_manager::ConnectionUID primary_connection_handle =
connection_handle;
if (session_id != 0) {
@@ -841,6 +865,15 @@ void ConnectionHandlerImpl::OnSecondaryTransportEnded(
}
}
+const transport_manager::DeviceInfo&
+ConnectionHandlerImpl::GetWebEngineDeviceInfo() const {
+ return transport_manager_.GetWebEngineDeviceInfo();
+}
+
+void ConnectionHandlerImpl::CreateWebEngineDevice() {
+ transport_manager_.CreateWebEngineDevice();
+}
+
const std::string
ConnectionHandlerImpl::TransportTypeProfileStringFromConnHandle(
transport_manager::ConnectionUID connection_handle) const {
@@ -861,11 +894,14 @@ const std::string
ConnectionHandlerImpl::TransportTypeProfileStringFromDeviceHandle(
DeviceHandle device_handle) const {
std::string connection_type;
- DeviceMap::const_iterator it = device_list_.find(device_handle);
- if (device_list_.end() == it) {
- LOG4CXX_ERROR(logger_, "Device not found!");
- } else {
- connection_type = it->second.connection_type();
+ {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
+ auto it = device_list_.find(device_handle);
+ if (device_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Device not found!");
+ } else {
+ connection_type = it->second.connection_type();
+ }
}
// Caution: this should be in sync with devicesType map in
@@ -1067,9 +1103,10 @@ SessionTransports ConnectionHandlerImpl::SetSecondaryTransportID(
st = it->second;
// The only time we overwrite an existing entry in the map is if the new
- // secondary transport ID is kDisabledSecondary, which effectively DISABLES
- // the secondary transport feature for the session, or if the new secondary
- // transport ID is 0, which means a secondary transport has shut down
+ // secondary transport ID is kDisabledSecondary, which effectively
+ // DISABLES the secondary transport feature for the session, or if the new
+ // secondary transport ID is 0, which means a secondary transport has shut
+ // down
if (st.secondary_transport != 0 &&
secondary_transport_id != kDisabledSecondary &&
secondary_transport_id != 0) {
@@ -1167,6 +1204,7 @@ struct CompareMAC {
bool ConnectionHandlerImpl::GetDeviceID(const std::string& mac_address,
DeviceHandle* device_handle) {
DCHECK_OR_RETURN(device_handle, false);
+ sync_primitives::AutoReadLock lock(device_list_lock_);
DeviceMap::const_iterator it = std::find_if(
device_list_.begin(), device_list_.end(), CompareMAC(mac_address));
if (it != device_list_.end()) {
@@ -1185,7 +1223,10 @@ int32_t ConnectionHandlerImpl::GetDataOnDeviceID(
LOG4CXX_AUTO_TRACE(logger_);
int32_t result = -1;
- DeviceMap::const_iterator it = device_list_.find(device_handle);
+
+ sync_primitives::AutoReadLock lock(device_list_lock_);
+ auto it = device_list_.find(device_handle);
+
if (device_list_.end() == it) {
LOG4CXX_ERROR(logger_, "Device not found for handle " << device_handle);
return result;
@@ -1231,6 +1272,7 @@ void ConnectionHandlerImpl::GetConnectedDevicesMAC(
std::vector<std::string>& device_macs) const {
DeviceMap::const_iterator first = device_list_.begin();
DeviceMap::const_iterator last = device_list_.end();
+ sync_primitives::AutoReadLock lock(device_list_lock_);
while (first != last) {
device_macs.push_back((*first).second.mac_address());
@@ -1328,6 +1370,7 @@ void ConnectionHandlerImpl::StartDevicesDiscovery() {
transport_manager_.SearchDevices();
sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
+ sync_primitives::AutoReadLock lock(device_list_lock_);
if (connection_handler_observer_) {
connection_handler_observer_->OnDeviceListUpdated(device_list_);
}
@@ -1336,6 +1379,7 @@ void ConnectionHandlerImpl::StartDevicesDiscovery() {
void ConnectionHandlerImpl::ConnectToDevice(
connection_handler::DeviceHandle device_handle) {
connection_handler::DeviceMap::const_iterator it_in;
+ sync_primitives::AutoReadLock lock(device_list_lock_);
it_in = device_list_.find(device_handle);
if (device_list_.end() != it_in) {
LOG4CXX_INFO(logger_, "Connecting to device with handle " << device_handle);
@@ -1357,6 +1401,7 @@ transport_manager::ConnectionStatus ConnectionHandlerImpl::GetConnectionStatus(
void ConnectionHandlerImpl::RunAppOnDevice(const std::string& device_mac,
const std::string& bundle_id) const {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
for (DeviceMap::const_iterator i = device_list_.begin();
i != device_list_.end();
++i) {
@@ -1370,6 +1415,7 @@ void ConnectionHandlerImpl::RunAppOnDevice(const std::string& device_mac,
}
void ConnectionHandlerImpl::ConnectToAllDevices() {
+ sync_primitives::AutoReadLock lock(device_list_lock_);
for (DeviceMap::iterator i = device_list_.begin(); i != device_list_.end();
++i) {
connection_handler::DeviceHandle device_handle = i->first;
diff --git a/src/components/include/application_manager/application_manager.h b/src/components/include/application_manager/application_manager.h
index 057f38f78e..31729aad75 100644
--- a/src/components/include/application_manager/application_manager.h
+++ b/src/components/include/application_manager/application_manager.h
@@ -165,6 +165,27 @@ class ApplicationManager {
virtual DataAccessor<ApplicationSet> applications() const = 0;
virtual DataAccessor<AppsWaitRegistrationSet> pending_applications()
const = 0;
+
+ /**
+ * @brief CreatePendingApplication Add applicaiton to pending state
+ * All info mandatory for application will be fetched from policy database.
+ * Application will be stored to internal pending applicaitons list.
+ * UpdateAppList will not be trigerred
+ * Application will be created if app exists in policy database and
+ * nicknames are not empty
+ * @param policy_app_id app id to store
+ */
+ virtual void CreatePendingLocalApplication(
+ const std::string& policy_app_id) = 0;
+
+ /**
+ * @brief RemovePendingApplication Remove applicaiton from pending state
+ * Application will be removed from the internal pending applicaitons list.
+ * UpdateAppList will not be trigerred
+ * @param policy_app_id app id to remove
+ */
+ virtual void RemovePendingApplication(const std::string& policy_app_id) = 0;
+
virtual DataAccessor<ReregisterWaitList> reregister_applications() const = 0;
virtual ApplicationSharedPtr application(uint32_t app_id) const = 0;
diff --git a/src/components/include/application_manager/policies/policy_handler_interface.h b/src/components/include/application_manager/policies/policy_handler_interface.h
index 3af3b770aa..1e9f4d51b3 100644
--- a/src/components/include/application_manager/policies/policy_handler_interface.h
+++ b/src/components/include/application_manager/policies/policy_handler_interface.h
@@ -159,6 +159,13 @@ class PolicyHandlerInterface : public VehicleDataItemProvider {
const std::string& policy_app_id) const = 0;
/**
+ * @brief Send OnAppPropertiesChangeNotification to the HMI
+ * @param policy_app_id policy app id
+ */
+ virtual void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const = 0;
+
+ /**
* @brief CheckSystemAction allows to check whether certain system
* action is enabled.
*
@@ -478,6 +485,13 @@ class PolicyHandlerInterface : public VehicleDataItemProvider {
const std::string& policy_app_id) const = 0;
/**
+ * @brief Get a list of policy app ids
+ * @return apps list filled with the policy app ids of each
+ * application
+ */
+ virtual std::vector<std::string> GetApplicationPolicyIDs() const = 0;
+
+ /**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
* cloud application
@@ -495,29 +509,63 @@ class PolicyHandlerInterface : public VehicleDataItemProvider {
const std::string& policy_app_id) const = 0;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ virtual std::vector<std::string> GetEnabledLocalApps() const = 0;
+
+ /**
+ * @brief Get app policy information, all fields that aren't set for a
* given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const = 0;
+ * @param policy_app_id policy app id
+ * @param out_app_properties application properties
+ * @return true if application presents in database, otherwise - false
+ */
+ virtual bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const = 0;
+
+ /**
+ * @brief Callback for when a BC.SetAppProperties message is
+ * received from the HMI
+ * @param message The BC.SetAppProperties message
+ */
+ virtual void OnSetAppProperties(
+ const smart_objects::SmartObject& properties) = 0;
+
+ enum class AppPropertiesState {
+ NO_CHANGES,
+ ENABLED_FLAG_SWITCH,
+ AUTH_TOKEN_CHANGED,
+ TRANSPORT_TYPE_CHANGED,
+ ENDPOINT_CHANGED,
+ NICKNAMES_CHANGED,
+ HYBRYD_APP_PROPERTIES_CHANGED
+ };
+
+ /**
+ * @brief Checks if the application properties were changed. Compares the
+ * properties received from the HMI with the stored properties in the database
+ * @param properties new app properties
+ * @param app_id application id
+ * @return AppPropertiesState enum value that indicates which property has
+ * been changed
+ */
+ virtual AppPropertiesState GetAppPropertiesStatus(
+ const smart_objects::SmartObject& properties,
+ const std::string& app_id) const = 0;
+
+ /**
+ * @brief Check if certain application already in policy db.
+ * @param policy application id.
+ * @return true if application presents false otherwise.
+ */
+ virtual bool IsNewApplication(const std::string& application_id) const = 0;
+
+ /**
+ * @brief OnLocalAppAdded triggers PTU
+ */
+ virtual void OnLocalAppAdded() = 0;
/**
* @brief Callback for when a SetCloudAppProperties message is received from a
diff --git a/src/components/include/connection_handler/connection_handler.h b/src/components/include/connection_handler/connection_handler.h
index eb92336b4f..e98a78f377 100644
--- a/src/components/include/connection_handler/connection_handler.h
+++ b/src/components/include/connection_handler/connection_handler.h
@@ -312,6 +312,19 @@ class ConnectionHandler {
const transport_manager::ConnectionUID primary_connection_handle,
const transport_manager::ConnectionUID secondary_connection_handle) = 0;
+ /**
+ * @brief GetWebEngineDeviceInfo
+ * @return device info for WebEngine device
+ */
+ virtual const transport_manager::DeviceInfo& GetWebEngineDeviceInfo()
+ const = 0;
+
+ /**
+ * @brief Called when HMI cooperation is started,
+ * creates WebSocketDevice for WebEngine
+ */
+ virtual void CreateWebEngineDevice() = 0;
+
protected:
/**
* \brief Destructor
diff --git a/src/components/include/connection_handler/connection_handler_observer.h b/src/components/include/connection_handler/connection_handler_observer.h
index 48e4263959..7d6664a009 100644
--- a/src/components/include/connection_handler/connection_handler_observer.h
+++ b/src/components/include/connection_handler/connection_handler_observer.h
@@ -172,6 +172,11 @@ class ConnectionHandlerObserver {
const transport_manager::ConnectionUID connection_id,
const transport_manager::DeviceInfo& device_info) = 0;
+ /**
+ *@brief Called when webengine device added
+ */
+ virtual void OnWebEngineDeviceCreated() = 0;
+
protected:
/**
* \brief Destructor
diff --git a/src/components/include/policy/policy_external/policy/policy_listener.h b/src/components/include/policy/policy_external/policy/policy_listener.h
index 8220d05584..c613fdd091 100644
--- a/src/components/include/policy/policy_external/policy/policy_listener.h
+++ b/src/components/include/policy/policy_external/policy/policy_listener.h
@@ -110,6 +110,14 @@ class PolicyListener {
const std::string& policy_app_id) const = 0;
/**
+ * @brief Send OnAppPropertiesChangeNotification to the HMI
+ * @param policy_app_id policy app id
+ */
+
+ virtual void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const = 0;
+
+ /**
* @brief GetAvailableApps allows to obtain list of registered applications.
*/
virtual void GetAvailableApps(std::queue<std::string>&) = 0;
diff --git a/src/components/include/policy/policy_external/policy/policy_manager.h b/src/components/include/policy/policy_external/policy/policy_manager.h
index 22721841aa..935233e92d 100644
--- a/src/components/include/policy/policy_external/policy/policy_manager.h
+++ b/src/components/include/policy/policy_external/policy/policy_manager.h
@@ -602,6 +602,13 @@ class PolicyManager : public usage_statistics::StatisticsManager,
virtual Json::Value GetPolicyTableData() const = 0;
/**
+ * @brief Get a list of policy app ids
+ * @return apps list filled with the policy app ids of each
+ * application
+ */
+ virtual const std::vector<std::string> GetApplicationPolicyIDs() const = 0;
+
+ /**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
* cloud application
@@ -610,29 +617,21 @@ class PolicyManager : public usage_statistics::StatisticsManager,
std::vector<std::string>& enabled_apps) const = 0;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
+ * @brief Get app policy information, all fields that aren't set for a
* given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const = 0;
+ * @param policy_app_id policy app id
+ * @param out_app_properties application properties
+ * @return true if application presents in database, otherwise - false
+ */
+ virtual bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const = 0;
+
+ /**
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ virtual std::vector<std::string> GetEnabledLocalApps() const = 0;
/**
* @ brief Initialize new cloud app in the policy table
@@ -778,6 +777,12 @@ class PolicyManager : public usage_statistics::StatisticsManager,
*/
virtual void SendAppPermissionsChanged(const std::string& device_id,
const std::string& application_id) = 0;
+ /**
+ * @brief Send OnAppPropertiesChangeNotification to the HMI
+ * @param policy_app_id policy app id
+ */
+ virtual void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const = 0;
/**
* @brief Gets all allowed module types
@@ -831,6 +836,18 @@ class PolicyManager : public usage_statistics::StatisticsManager,
virtual ExternalConsentStatus GetExternalConsentStatus() = 0;
/**
+ * @brief OnLocalAppAdded triggers PTU
+ */
+ virtual void OnLocalAppAdded() = 0;
+
+ /**
+ * @brief Check if certain application already in policy db.
+ * @param policy application id.
+ * @return true if application presents false otherwise.
+ */
+ virtual bool IsNewApplication(const std::string& application_id) const = 0;
+
+ /**
* @brief Restart PTU timeout if PTU in UPDATING state
*/
virtual void ResetTimeout() = 0;
diff --git a/src/components/include/policy/policy_regular/policy/policy_listener.h b/src/components/include/policy/policy_regular/policy/policy_listener.h
index bbe220060e..5b8245f6a4 100644
--- a/src/components/include/policy/policy_regular/policy/policy_listener.h
+++ b/src/components/include/policy/policy_regular/policy/policy_listener.h
@@ -108,6 +108,13 @@ class PolicyListener {
const std::string& policy_app_id) const = 0;
/**
+ * @brief Send OnAppPropertiesChangeNotification to the HMI
+ * @param policy_app_id policy app id
+ */
+ virtual void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const = 0;
+
+ /**
* @brief GetAvailableApps allows to obtain list of registered applications.
*/
virtual void GetAvailableApps(std::queue<std::string>&) = 0;
diff --git a/src/components/include/policy/policy_regular/policy/policy_manager.h b/src/components/include/policy/policy_regular/policy/policy_manager.h
index c9143d6bbb..52923a53e2 100644
--- a/src/components/include/policy/policy_regular/policy/policy_manager.h
+++ b/src/components/include/policy/policy_regular/policy/policy_manager.h
@@ -575,6 +575,14 @@ class PolicyManager : public usage_statistics::StatisticsManager,
* @return policy_table as json object
*/
virtual Json::Value GetPolicyTableData() const = 0;
+
+ /**
+ * @brief Get a list of policy app ids
+ * @return apps list filled with the policy app ids of each
+ * application
+ */
+ virtual const std::vector<std::string> GetApplicationPolicyIDs() const = 0;
+
/**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
@@ -584,29 +592,21 @@ class PolicyManager : public usage_statistics::StatisticsManager,
std::vector<std::string>& enabled_apps) const = 0;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ virtual std::vector<std::string> GetEnabledLocalApps() const = 0;
+
+ /**
+ * @brief Get app policy information, all fields that aren't set for a
* given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const = 0;
+ * @param policy_app_id policy app id
+ * @param out_app_properties application properties
+ * @return true if application presents in database, otherwise - false
+ */
+ virtual bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const = 0;
/**
* @ brief Initialize new cloud app in the policy table
@@ -758,6 +758,13 @@ class PolicyManager : public usage_statistics::StatisticsManager,
const std::string& application_id) = 0;
/**
+ * @brief Send OnAppPropertiesChangeNotification to the HMI
+ * @param policy_app_id policy app id
+ */
+ virtual void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const = 0;
+
+ /**
* @brief Gets all allowed module types
* @param policy_app_id unique identifier of application
* @param modules list of allowed module types
@@ -786,6 +793,18 @@ class PolicyManager : public usage_statistics::StatisticsManager,
const EndpointUrls& urls) const = 0;
/**
+ * @brief OnLocalAppAdded triggers PTU
+ */
+ virtual void OnLocalAppAdded() = 0;
+
+ /**
+ * @brief Check if certain application already in policy db.
+ * @param policy application id.
+ * @return true if application presents false otherwise.
+ */
+ virtual bool IsNewApplication(const std::string& application_id) const = 0;
+
+ /**
* @brief Restart PTU timeout if PTU in UPDATING state
*/
virtual void ResetTimeout() = 0;
diff --git a/src/components/include/test/application_manager/mock_application_manager.h b/src/components/include/test/application_manager/mock_application_manager.h
index b2de63252e..5e9b65fec5 100644
--- a/src/components/include/test/application_manager/mock_application_manager.h
+++ b/src/components/include/test/application_manager/mock_application_manager.h
@@ -86,6 +86,10 @@ class MockApplicationManager : public application_manager::ApplicationManager {
DataAccessor<application_manager::AppsWaitRegistrationSet>());
MOCK_CONST_METHOD0(reregister_applications,
DataAccessor<application_manager::ReregisterWaitList>());
+ MOCK_METHOD1(CreatePendingLocalApplication,
+ void(const std::string& policy_app_id));
+ MOCK_METHOD1(RemovePendingApplication,
+ void(const std::string& policy_app_id));
MOCK_CONST_METHOD1(
application, application_manager::ApplicationSharedPtr(uint32_t app_id));
MOCK_CONST_METHOD0(active_application,
@@ -287,6 +291,8 @@ class MockApplicationManager : public application_manager::ApplicationManager {
ApplyFunctorForEachPlugin,
void(std::function<void(application_manager::plugin_manager::RPCPlugin&)>
functor));
+ MOCK_METHOD1(SetVINCode, void(const std::string& vin_code));
+ MOCK_CONST_METHOD0(GetVINCode, const std::string());
MOCK_METHOD1(
GetDeviceTransportType,
hmi_apis::Common_TransportType::eType(const std::string& transport_type));
diff --git a/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h b/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h
index f6e0b3cb0f..a9cb70354a 100644
--- a/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h
+++ b/src/components/include/test/application_manager/policies/mock_policy_handler_interface.h
@@ -206,6 +206,8 @@ class MockPolicyHandlerInterface : public policy::PolicyHandlerInterface {
void(const policy::AppPermissions& permissions,
const std::string& device_id,
const std::string& policy_app_id));
+ MOCK_CONST_METHOD1(SendOnAppPropertiesChangeNotification,
+ void(const std::string& policy_app_id));
MOCK_METHOD0(OnPTExchangeNeeded, void());
MOCK_METHOD1(GetAvailableApps, void(std::queue<std::string>& apps));
MOCK_METHOD3(
@@ -242,18 +244,24 @@ class MockPolicyHandlerInterface : public policy::PolicyHandlerInterface {
const std::vector<std::string>(
const transport_manager::DeviceHandle& device_handle,
const std::string& policy_app_id));
+ MOCK_CONST_METHOD0(GetApplicationPolicyIDs, std::vector<std::string>());
MOCK_CONST_METHOD1(GetEnabledCloudApps,
void(std::vector<std::string>& enabled_apps));
MOCK_CONST_METHOD1(CheckCloudAppEnabled,
const bool(const std::string& policy_app_id));
- MOCK_CONST_METHOD7(GetCloudAppParameters,
+ MOCK_CONST_METHOD0(GetEnabledLocalApps, std::vector<std::string>());
+ MOCK_CONST_METHOD2(GetAppProperties,
bool(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference));
+ policy::AppProperties& out_app_properties));
+
+ MOCK_METHOD1(OnSetAppProperties,
+ void(const smart_objects::SmartObject& message));
+ MOCK_CONST_METHOD2(
+ GetAppPropertiesStatus,
+ AppPropertiesState(const smart_objects::SmartObject& properties,
+ const std::string& app_id));
+ MOCK_CONST_METHOD1(IsNewApplication, bool(const std::string& application_id));
+ MOCK_METHOD0(OnLocalAppAdded, void());
MOCK_METHOD1(OnSetCloudAppProperties,
void(const smart_objects::SmartObject& message));
MOCK_CONST_METHOD2(
diff --git a/src/components/include/test/connection_handler/mock_connection_handler.h b/src/components/include/test/connection_handler/mock_connection_handler.h
index 41c2f04ebb..6acffea0ed 100644
--- a/src/components/include/test/connection_handler/mock_connection_handler.h
+++ b/src/components/include/test/connection_handler/mock_connection_handler.h
@@ -133,6 +133,8 @@ class MockConnectionHandler : public connection_handler::ConnectionHandler {
OnSecondaryTransportEnded,
void(const transport_manager::ConnectionUID primary_connection_handle,
const transport_manager::ConnectionUID secondary_connection_handle));
+ MOCK_METHOD0(CreateWebEngineDevice, void());
+ MOCK_CONST_METHOD0(GetWebEngineDeviceInfo, transport_manager::DeviceInfo&());
};
} // namespace connection_handler_test
diff --git a/src/components/include/test/connection_handler/mock_connection_handler_observer.h b/src/components/include/test/connection_handler/mock_connection_handler_observer.h
index 8f7ec90550..61877daa23 100644
--- a/src/components/include/test/connection_handler/mock_connection_handler_observer.h
+++ b/src/components/include/test/connection_handler/mock_connection_handler_observer.h
@@ -46,6 +46,7 @@ class MockConnectionHandlerObserver
MOCK_METHOD1(OnDeviceListUpdated,
void(const connection_handler::DeviceMap& device_list));
MOCK_METHOD0(OnFindNewApplicationsRequest, void());
+ MOCK_METHOD0(OnWebEngineDeviceCreated, void());
MOCK_METHOD1(RemoveDevice,
void(const connection_handler::DeviceHandle& device_handle));
MOCK_METHOD4(OnServiceStartedCallback,
diff --git a/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h b/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h
index b74ddbd13c..c6eb3416da 100644
--- a/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h
+++ b/src/components/include/test/policy/policy_external/policy/mock_cache_manager.h
@@ -61,6 +61,7 @@ class MockCacheManagerInterface : public ::policy::CacheManagerInterface {
MOCK_METHOD0(IsPTPreloaded, bool());
MOCK_METHOD0(IgnitionCyclesBeforeExchange, int());
MOCK_METHOD1(KilometersBeforeExchange, int(int current));
+ MOCK_CONST_METHOD0(GetEnabledLocalApps, std::vector<std::string>());
MOCK_CONST_METHOD1(GetPermissionsList, bool(StringArray& perm_list));
MOCK_METHOD2(SetCountersPassedForSuccessfulUpdate,
bool(Counters counter, int value));
@@ -83,14 +84,9 @@ class MockCacheManagerInterface : public ::policy::CacheManagerInterface {
std::vector<policy_table::VehicleDataItem>());
MOCK_CONST_METHOD1(GetEnabledCloudApps,
void(std::vector<std::string>& enabled_apps));
- MOCK_CONST_METHOD7(GetCloudAppParameters,
+ MOCK_CONST_METHOD2(GetAppProperties,
bool(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference));
+ AppProperties& out_app_properties));
MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id));
MOCK_METHOD2(SetCloudAppEnabled,
void(const std::string& policy_app_id, const bool enabled));
diff --git a/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h b/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h
index 2eb5b3300b..0060d2299f 100644
--- a/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h
+++ b/src/components/include/test/policy/policy_external/policy/mock_policy_listener.h
@@ -94,6 +94,8 @@ class MockPolicyListener : public ::policy::PolicyListener {
void(const policy::AppPermissions& permissions,
const std::string& device_id,
const std::string& policy_app_id));
+ MOCK_CONST_METHOD1(SendOnAppPropertiesChangeNotification,
+ void(const std::string& policy_app_id));
MOCK_CONST_METHOD1(
GetDevicesIds,
std::vector<std::string>(const std::string& policy_app_id));
diff --git a/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h b/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h
index d2023fd3d4..5adb982410 100644
--- a/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h
+++ b/src/components/include/test/policy/policy_external/policy/mock_policy_manager.h
@@ -194,6 +194,8 @@ class MockPolicyManager : public PolicyManager {
MOCK_METHOD2(SendAppPermissionsChanged,
void(const std::string& device_id,
const std::string& application_id));
+ MOCK_CONST_METHOD1(SendOnAppPropertiesChangeNotification,
+ void(const std::string& application_id));
MOCK_CONST_METHOD2(GetModuleTypes,
bool(const std::string& policy_app_id,
std::vector<std::string>* modules));
@@ -228,14 +230,12 @@ class MockPolicyManager : public PolicyManager {
std::vector<policy_table::VehicleDataItem>());
MOCK_CONST_METHOD1(GetEnabledCloudApps,
void(std::vector<std::string>& enabled_apps));
- MOCK_CONST_METHOD7(GetCloudAppParameters,
+ MOCK_CONST_METHOD2(GetAppProperties,
bool(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference));
+ AppProperties& out_app_properties));
+ MOCK_CONST_METHOD0(GetEnabledLocalApps, std::vector<std::string>());
+ MOCK_CONST_METHOD1(IsNewApplication, bool(const std::string& application_id));
+ MOCK_METHOD0(OnLocalAppAdded, void());
MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id));
MOCK_METHOD2(SetCloudAppEnabled,
void(const std::string& policy_app_id, const bool enabled));
diff --git a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h
index e592caf3bc..7c78eadfc8 100644
--- a/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h
+++ b/src/components/include/test/policy/policy_regular/policy/mock_cache_manager.h
@@ -55,6 +55,7 @@ class MockCacheManagerInterface : public CacheManagerInterface {
MOCK_METHOD0(IsPTPreloaded, bool());
MOCK_METHOD0(IgnitionCyclesBeforeExchange, int());
MOCK_METHOD1(KilometersBeforeExchange, int(int current));
+ MOCK_CONST_METHOD0(GetEnabledLocalApps, std::vector<std::string>());
MOCK_METHOD2(SetCountersPassedForSuccessfulUpdate,
bool(Counters counter, int value));
MOCK_METHOD1(DaysBeforeExchange, int(int current));
@@ -69,14 +70,9 @@ class MockCacheManagerInterface : public CacheManagerInterface {
std::vector<policy_table::VehicleDataItem>());
MOCK_CONST_METHOD1(GetEnabledCloudApps,
void(std::vector<std::string>& enabled_apps));
- MOCK_CONST_METHOD7(GetCloudAppParameters,
+ MOCK_CONST_METHOD2(GetAppProperties,
bool(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference));
+ AppProperties& out_app_properties));
MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id));
MOCK_METHOD2(SetCloudAppEnabled,
void(const std::string& policy_app_id, const bool enabled));
diff --git a/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h b/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h
index 48c549e91b..e5f2321217 100644
--- a/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h
+++ b/src/components/include/test/policy/policy_regular/policy/mock_policy_listener.h
@@ -89,6 +89,8 @@ class MockPolicyListener : public ::policy::PolicyListener {
void(const policy::AppPermissions& permissions,
const std::string& device_id,
const std::string& policy_app_id));
+ MOCK_CONST_METHOD1(SendOnAppPropertiesChangeNotification,
+ void(const std::string& policy_app_id));
MOCK_METHOD3(OnUpdateHMILevel,
void(const std::string& device_id,
const std::string& policy_app_id,
diff --git a/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h b/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h
index da9edb9fe5..a76d61dfe4 100644
--- a/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h
+++ b/src/components/include/test/policy/policy_regular/policy/mock_policy_manager.h
@@ -193,6 +193,8 @@ class MockPolicyManager : public PolicyManager {
MOCK_METHOD2(SendAppPermissionsChanged,
void(const std::string& device_id,
const std::string& application_id));
+ MOCK_CONST_METHOD1(SendOnAppPropertiesChangeNotification,
+ void(const std::string& application_id));
MOCK_CONST_METHOD2(GetModuleTypes,
bool(const std::string& policy_app_id,
std::vector<std::string>* modules));
@@ -223,14 +225,12 @@ class MockPolicyManager : public PolicyManager {
std::vector<policy_table::VehicleDataItem>());
MOCK_CONST_METHOD1(GetEnabledCloudApps,
void(std::vector<std::string>& enabled_apps));
- MOCK_CONST_METHOD7(GetCloudAppParameters,
+ MOCK_CONST_METHOD2(GetAppProperties,
bool(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference));
+ AppProperties& out_app_properties));
+ MOCK_CONST_METHOD0(GetEnabledLocalApps, std::vector<std::string>());
+ MOCK_CONST_METHOD1(IsNewApplication, bool(const std::string& application_id));
+ MOCK_METHOD0(OnLocalAppAdded, void());
MOCK_METHOD1(InitCloudApp, void(const std::string& policy_app_id));
MOCK_METHOD2(SetCloudAppEnabled,
void(const std::string& policy_app_id, const bool enabled));
diff --git a/src/components/include/test/transport_manager/mock_transport_manager.h b/src/components/include/test/transport_manager/mock_transport_manager.h
index c853ceb512..1920af18a3 100644
--- a/src/components/include/test/transport_manager/mock_transport_manager.h
+++ b/src/components/include/test/transport_manager/mock_transport_manager.h
@@ -88,6 +88,8 @@ class MockTransportManager : public ::transport_manager::TransportManager,
MOCK_METHOD1(SetTelemetryObserver,
void(transport_manager::TMTelemetryObserver* observer));
+ MOCK_METHOD0(CreateWebEngineDevice, void());
+ MOCK_CONST_METHOD0(GetWebEngineDeviceInfo, transport_manager::DeviceInfo&());
};
} // namespace transport_manager_test
diff --git a/src/components/include/test/transport_manager/mock_transport_manager_settings.h b/src/components/include/test/transport_manager/mock_transport_manager_settings.h
index 6ed4ac5d51..10320d51ab 100644
--- a/src/components/include/test/transport_manager/mock_transport_manager_settings.h
+++ b/src/components/include/test/transport_manager/mock_transport_manager_settings.h
@@ -63,6 +63,8 @@ class MockTransportManagerSettings
MOCK_CONST_METHOD0(app_transport_change_timer_addition, uint32_t());
MOCK_CONST_METHOD0(transport_manager_tcp_adapter_network_interface,
std::string&());
+ MOCK_CONST_METHOD0(websocket_server_address, const std::string&());
+ MOCK_CONST_METHOD0(websocket_server_port, uint16_t());
MOCK_CONST_METHOD0(cloud_app_retry_timeout, uint32_t());
MOCK_CONST_METHOD0(cloud_app_max_retry_attempts, uint16_t());
MOCK_CONST_METHOD0(bluetooth_uuid, const uint8_t*());
@@ -72,6 +74,10 @@ class MockTransportManagerSettings
MOCK_CONST_METHOD0(aoa_filter_version, const std::string&());
MOCK_CONST_METHOD0(aoa_filter_uri, const std::string&());
MOCK_CONST_METHOD0(aoa_filter_serial_number, const std::string&());
+ MOCK_CONST_METHOD0(ws_server_cert_path, const std::string&());
+ MOCK_CONST_METHOD0(ws_server_key_path, const std::string&());
+ MOCK_CONST_METHOD0(ws_server_ca_cert_path, const std::string&());
+ MOCK_CONST_METHOD0(wss_server_supported, const bool());
};
} // namespace transport_manager_test
diff --git a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h
index a07365f8c0..d4ce0a39c8 100644
--- a/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h
+++ b/src/components/include/test/transport_manager/transport_adapter/mock_transport_adapter.h
@@ -108,6 +108,10 @@ class MockTransportAdapter
transport_manager::transport_adapter::TransportConfig());
MOCK_METHOD1(CreateDevice, void(const std::string& uid));
+ MOCK_METHOD1(AddDevice,
+ transport_manager::transport_adapter::DeviceSptr(
+ transport_manager::transport_adapter::DeviceSptr device));
+
#ifdef TELEMETRY_MONITOR
MOCK_METHOD0(GetTelemetryObserver,
::transport_manager::TMTelemetryObserver*());
diff --git a/src/components/include/transport_manager/common.h b/src/components/include/transport_manager/common.h
index 08f52ae1d0..f8b0cabe2e 100644
--- a/src/components/include/transport_manager/common.h
+++ b/src/components/include/transport_manager/common.h
@@ -69,6 +69,11 @@ enum {
enum ConnectionStatus { INVALID = -1, PENDING, RETRY, CONNECTED, CLOSING };
+namespace webengine_constants {
+const std::string kWebEngineConnectionType("WEBENGINE_WEBSOCKET");
+const std::string kWebEngineDeviceName("Web Engine");
+} // namespace webengine_constants
+
/**
* @brief Type definition for variable that hold handle of device.
*/
diff --git a/src/components/include/transport_manager/transport_adapter/transport_adapter.h b/src/components/include/transport_manager/transport_adapter/transport_adapter.h
index 8b46be253b..e9494b4ced 100644
--- a/src/components/include/transport_manager/transport_adapter/transport_adapter.h
+++ b/src/components/include/transport_manager/transport_adapter/transport_adapter.h
@@ -68,6 +68,7 @@ enum DeviceType {
IOS_USB_HOST_MODE,
IOS_USB_DEVICE_MODE,
IOS_CARPLAY_WIRELESS, // running on iAP over Carplay wireless transport
+ WEBENGINE_WEBSOCKET,
UNKNOWN
};
@@ -225,6 +226,16 @@ class TransportAdapter {
const DeviceUID& device_handle) const = 0;
/**
+ * @brief Add device to the container(map), if container doesn't hold it yet.
+ * in TransportAdapter is used only to add a WebEngine device
+ *
+ * @param device Smart pointer to the device.
+ *
+ * @return Smart pointer to the device.
+ */
+ virtual DeviceSptr AddDevice(DeviceSptr device) = 0;
+
+ /**
* @brief RunAppOnDevice allows to run specific application on the certain
*device.
*
diff --git a/src/components/include/transport_manager/transport_manager.h b/src/components/include/transport_manager/transport_manager.h
index e370e3e4c6..4697bf9982 100644
--- a/src/components/include/transport_manager/transport_manager.h
+++ b/src/components/include/transport_manager/transport_manager.h
@@ -215,6 +215,18 @@ class TransportManager {
*/
virtual int PerformActionOnClients(
const TransportAction required_action) const = 0;
+
+ /**
+ * @brief Called when websocket server transport adapter is available.
+ * Creates WebSocketDevice for WebEngine and add it to the device list
+ */
+ virtual void CreateWebEngineDevice() = 0;
+
+ /**
+ * @brief GetWebEngineDeviceInfo
+ * @return device info for WebEngine device
+ */
+ virtual const DeviceInfo& GetWebEngineDeviceInfo() const = 0;
};
} // namespace transport_manager
#endif // SRC_COMPONENTS_INCLUDE_TRANSPORT_MANAGER_TRANSPORT_MANAGER_H_
diff --git a/src/components/include/transport_manager/transport_manager_settings.h b/src/components/include/transport_manager/transport_manager_settings.h
index 83d0b3e833..fee5b031ed 100644
--- a/src/components/include/transport_manager/transport_manager_settings.h
+++ b/src/components/include/transport_manager/transport_manager_settings.h
@@ -69,7 +69,24 @@ class TransportManagerSettings : public TransportManagerMMESettings {
*/
virtual const std::string& transport_manager_tcp_adapter_network_interface()
const = 0;
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ /**
+ *@brief Returns websocket server address
+ */
+ virtual const std::string& websocket_server_address() const = 0;
+
+ /**
+ * @brief Returns port for websocket server
+ */
+ virtual uint16_t websocket_server_port() const = 0;
+#ifdef ENABLE_SECURITY
+ virtual const std::string& ws_server_cert_path() const = 0;
+ virtual const std::string& ws_server_key_path() const = 0;
+ virtual const std::string& ws_server_ca_cert_path() const = 0;
+ virtual const bool wss_server_supported() const = 0;
+#endif // ENABLE_SECURITY
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
/**
* @brief Returns retry timeout for cloud app connections
*/
diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml
index d105d2e3e8..9e8a32312f 100644
--- a/src/components/interfaces/HMI_API.xml
+++ b/src/components/interfaces/HMI_API.xml
@@ -95,6 +95,7 @@
<element name="USB_AOA"/>
<element name="WIFI"/>
<element name="CLOUD_WEBSOCKET"/>
+ <element name="WEBENGINE_WEBSOCKET"/>
</enum>
<enum name="ButtonName">
@@ -4122,6 +4123,13 @@
<description>Contains information about the locations of each seat</description>
</param>
</struct>
+
+ <enum name="HybridAppPreference">
+ <description>Enumeration for the user's preference of which app type to use when both are available</description>
+ <element name="MOBILE" />
+ <element name="CLOUD" />
+ <element name="BOTH"/>
+ </enum>
</interface>
@@ -4640,7 +4648,102 @@
<param name="appID" type="Integer" mandatory="false">
<description>ID of application that is related to this RPC.</description>
</param>
+ </function>
+
+ <struct name="AppProperties">
+ <param name="nicknames" type="String" minlength="0" maxlength="100" array="true" minsize="0" maxsize="100" mandatory="false">
+ <description>An array of app names an app is allowed to register with. If included in a SetAppProperties request, this value will overwrite the existing "nicknames" field in the app policies section of the policy table.</description>
+ </param>
+ <param name="policyAppID" type="String" maxlength="100" minlength="1" mandatory="true" />
+ <param name="enabled" type="Boolean" mandatory="false">
+ <description>If true, the app will be marked as "available" or "installed" and will be included in HMI RPC UpdateAppList.</description>
+ </param>
+ <param name="authToken" type="String" maxlength="65535" mandatory="false">
+ <description>Used to authenticate connection on app activation</description>
+ </param>
+ <param name="transportType" type="String" maxlength="100" mandatory="false">
+ <description>
+ Specifies the connection type Core should use. The Core role (server or client) is dependent of "endpoint" being specified.
+ See "endpoint" for details.
+ </description>
+ </param>
+ <param name="hybridAppPreference" type="Common.HybridAppPreference" mandatory="false">
+ <description>Specifies the user preference to use one specific app type or all available types</description>
+ </param>
+ <param name="endpoint" type="String" maxlength="65535" mandatory="false">
+ <description>
+ If specified, which Core uses a client implementation of the connection type and attempts to connect to the endpoint when this app is selected (activated).
+ If omitted, Core won't attempt to connect as the app selection (activation) is managed outside of Core. Instead it uses a server implementation of the connection type and expects the app to connect.
+ </description>
+ </param>
+ </struct>
+
+ <function name="SetAppProperties" messagetype="request">
+ <description>
+ HMI >SDL. RPC used to enable/disable an application and set authentication data
+ </description>
+ <param name="properties" type="AppProperties" mandatory="true">
+ <description>The new application properties</description>
+ </param>
</function>
+
+ <function name="SetAppProperties" messagetype="response">
+ <description>The response to SetAppProperties</description>
+ <param name="success" type="Boolean" platform="documentation" mandatory="true">
+ <description>true if successful; false if failed</description>
+ </param>
+ <param name="resultCode" type="Common.Result" platform="documentation" mandatory="true">
+ <description>See Result</description>
+ <element name="SUCCESS"/>
+ <element name="INVALID_DATA"/>
+ <element name="OUT_OF_MEMORY"/>
+ <element name="TOO_MANY_PENDING_REQUESTS"/>
+ <element name="GENERIC_ERROR"/>
+ <element name="DISALLOWED"/>
+ <element name="WARNINGS"/>
+ <element name="DATA_NOT_AVAILABLE"/>
+ </param>
+ </function>
+
+ <function name="GetAppProperties" messagetype="request">
+ <description>
+ HMI >SDL. RPC used to get the current properties of an application
+ </description>
+ <param name="policyAppID" type="String" maxlength="100" mandatory="false">
+ If specified the response will contain the properties of the specified app ID.
+ Otherwise if omitted all app properties will be returned at once.
+ </param>
+ </function>
+
+ <function name="GetAppProperties" messagetype="response">
+ <description>The response to GetAppProperties</description>
+ <param name="properties" type="AppProperties" array="true" minsize="1" mandatory="false">
+ <description>The requested application properties</description>
+ </param>
+ <param name="success" type="Boolean" platform="documentation" mandatory="true">
+ <description>true if successful; false if failed</description>
+ </param>
+ <param name="resultCode" type="Common.Result" platform="documentation" mandatory="true">
+ <description>See Result</description>
+ <element name="SUCCESS"/>
+ <element name="INVALID_DATA"/>
+ <element name="OUT_OF_MEMORY"/>
+ <element name="TOO_MANY_PENDING_REQUESTS"/>
+ <element name="GENERIC_ERROR"/>
+ <element name="DISALLOWED"/>
+ <element name="WARNINGS"/>
+ <element name="DATA_NOT_AVAILABLE"/>
+ </param>
+ </function>
+
+ <function name="OnAppPropertiesChange" messagetype="notification">
+ <description>
+ SDL >HMI. RPC used to inform HMI about app properties change (such as auth token).
+ </description>
+ <param name="properties" type="AppProperties" mandatory="true">
+ <description>The new application properties</description>
+ </param>
+ </function>
</interface>
<interface name="VR" version="1.1.0" date="2017-04-27">
diff --git a/src/components/policy/policy_external/include/policy/cache_manager.h b/src/components/policy/policy_external/include/policy/cache_manager.h
index 5e3cf3dde7..b24e05fb6d 100644
--- a/src/components/policy/policy_external/include/policy/cache_manager.h
+++ b/src/components/policy/policy_external/include/policy/cache_manager.h
@@ -181,32 +181,18 @@ class CacheManager : public CacheManagerInterface {
* @param enabled_apps List filled with the policy app id of each enabled
* cloud application
*/
- virtual void GetEnabledCloudApps(
- std::vector<std::string>& enabled_apps) const;
+ void GetEnabledCloudApps(
+ std::vector<std::string>& enabled_apps) const OVERRIDE;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
- * given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const;
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id
+ * of each enabled local application
+ */
+ std::vector<std::string> GetEnabledLocalApps() const OVERRIDE;
+
+ bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const OVERRIDE;
/**
* Initializes a new cloud application with default policies
diff --git a/src/components/policy/policy_external/include/policy/cache_manager_interface.h b/src/components/policy/policy_external/include/policy/cache_manager_interface.h
index 2cb5f8fe33..8e3f90b64f 100644
--- a/src/components/policy/policy_external/include/policy/cache_manager_interface.h
+++ b/src/components/policy/policy_external/include/policy/cache_manager_interface.h
@@ -190,29 +190,21 @@ class CacheManagerInterface {
std::vector<std::string>& enabled_apps) const = 0;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ virtual std::vector<std::string> GetEnabledLocalApps() const = 0;
+
+ /**
+ * @brief Get app policy information, all fields that aren't set for a
* given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const = 0;
+ * @param policy_app_id policy app id
+ * @param out_app_properties application properties
+ * @return true if application presents in database, otherwise - false
+ */
+ virtual bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const = 0;
/**
* Initializes a new cloud application with default policies
diff --git a/src/components/policy/policy_external/include/policy/policy_helper.h b/src/components/policy/policy_external/include/policy/policy_helper.h
index 2054485ef5..69ba8806d4 100644
--- a/src/components/policy/policy_external/include/policy/policy_helper.h
+++ b/src/components/policy/policy_external/include/policy/policy_helper.h
@@ -231,6 +231,10 @@ struct CheckAppPolicy {
void InsertPermission(const std::string& app_id,
const AppPermissions& permissions_diff);
+ bool IsAppPropertiesChanged(const AppPoliciesValueType& app_policy) const;
+
+ bool IsAppPropertiesProvided(const AppPoliciesValueType& app_policy) const;
+
private:
PolicyManagerImpl* pm_;
const std::shared_ptr<policy_table::Table> update_;
diff --git a/src/components/policy/policy_external/include/policy/policy_manager_impl.h b/src/components/policy/policy_external/include/policy/policy_manager_impl.h
index ce344d576a..57499131f9 100644
--- a/src/components/policy/policy_external/include/policy/policy_manager_impl.h
+++ b/src/components/policy/policy_external/include/policy/policy_manager_impl.h
@@ -667,28 +667,14 @@ class PolicyManagerImpl : public PolicyManager {
std::vector<std::string>& enabled_apps) const OVERRIDE;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
- * given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- bool GetCloudAppParameters(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const OVERRIDE;
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ std::vector<std::string> GetEnabledLocalApps() const OVERRIDE;
+
+ bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const OVERRIDE;
/**
* @ brief Initialize new cloud app in the policy table
@@ -921,6 +907,10 @@ class PolicyManagerImpl : public PolicyManager {
*/
void OnSystemRequestReceived() OVERRIDE;
+ void OnLocalAppAdded() OVERRIDE;
+
+ bool IsNewApplication(const std::string& application_id) const OVERRIDE;
+
protected:
/**
* @brief Parse policy table content and convert to PT object
@@ -1037,13 +1027,6 @@ class PolicyManagerImpl : public PolicyManager {
DeviceConsent device_consent);
/**
- * @brief Check if certain application already in policy db.
- * @param policy application id.
- * @return true if application presents false otherwise.
- */
- bool IsNewApplication(const std::string& application_id) const;
-
- /**
* Checks existing and permissions of AppStorageFolder
* @return true if AppStorageFolder exists and has permissions read/write
*/
@@ -1124,6 +1107,9 @@ class PolicyManagerImpl : public PolicyManager {
void SendAppPermissionsChanged(const std::string& device_id,
const std::string& application_id) OVERRIDE;
+ void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const OVERRIDE;
+
/**
* @brief notify listener of updated auth token for a given policy id
* @param policy_app_id the app id that has an updated auth token
@@ -1341,6 +1327,8 @@ class PolicyManagerImpl : public PolicyManager {
*/
bool send_on_update_sent_out_;
+ std::vector<std::string> app_properties_changed_list_;
+
/**
* @brief Flag for notifying that invalid PTU should be triggered
*/
diff --git a/src/components/policy/policy_external/include/policy/policy_types.h b/src/components/policy/policy_external/include/policy/policy_types.h
index 879eb0aa9b..7e8abd5989 100644
--- a/src/components/policy/policy_external/include/policy/policy_types.h
+++ b/src/components/policy/policy_external/include/policy/policy_types.h
@@ -232,8 +232,11 @@ struct DeviceInfo {
using namespace helpers;
static const std::string bluetooth("BLUETOOTH");
static const std::string wifi("WIFI");
+ static const std::string webengine("WEBENGINE_WEBSOCKET");
if (Compare<std::string, EQ, ONE>(deviceType, bluetooth, wifi)) {
connection_type.assign("BTMAC");
+ } else if (Compare<std::string, EQ, ONE>(deviceType, webengine)) {
+ connection_type.assign("");
}
}
};
@@ -452,11 +455,13 @@ struct ApplicationPolicyActions {
ApplicationPolicyActions()
: is_notify_system(false)
, is_send_permissions_to_app(false)
- , is_consent_needed(false) {}
+ , is_consent_needed(false)
+ , app_properties_changed(false) {}
bool is_notify_system;
bool is_send_permissions_to_app;
bool is_consent_needed;
+ bool app_properties_changed;
};
/**
@@ -517,6 +522,7 @@ enum PermissionsCheckResult {
RESULT_REQUEST_TYPE_CHANGED,
RESULT_REQUEST_SUBTYPE_CHANGED,
RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED,
+ RESULT_APP_PROPERTIES_CHANGED
};
/**
@@ -539,6 +545,68 @@ enum ConsentPriorityType { kUserConsentPrio, kExternalConsentPrio };
*/
enum ConsentProcessingPolicy { kTimestampBased, kExternalConsentBased };
+/**
+ * @brief The AppProperties struct contains application properties
+ */
+struct AppProperties {
+ AppProperties()
+ : endpoint()
+ , certificate()
+ , enabled(false)
+ , auth_token()
+ , transport_type()
+ , hybrid_app_preference() {}
+
+ AppProperties(std::string endpoint,
+ std::string certificate,
+ bool enabled,
+ std::string auth_token,
+ std::string transport_type,
+ std::string hybrid_app_preference)
+ : endpoint(endpoint)
+ , certificate(certificate)
+ , enabled(enabled)
+ , auth_token(auth_token)
+ , transport_type(transport_type)
+ , hybrid_app_preference(hybrid_app_preference) {}
+
+ /**
+ * @brief endpoint Filled with the endpoint used to connect to the cloud
+ * application.
+ * @note should be absent for local applications
+ */
+ std::string endpoint;
+
+ /**
+ * @brief certificate Filled with the certificate used for creation
+ * of a secure connection to the cloud application
+ */
+ std::string certificate;
+
+ /**
+ * @brief enabled Whether or not the app is enabled
+ */
+ bool enabled;
+
+ /**
+ * @brief auth_token Filled with the token used for authentication when
+ * reconnecting to the cloud app
+ */
+ std::string auth_token;
+
+ /**
+ * @brief transport_type Filled with the transport type used by the
+ * cloud/local application (ex. "WSS")
+ */
+ std::string transport_type;
+
+ /**
+ * @brief hybrid_app_preference Filled with the hybrid app preference for the
+ * application set by the user
+ */
+ std::string hybrid_app_preference;
+};
+
} // namespace policy
#endif // SRC_COMPONENTS_POLICY_POLICY_EXTERNAL_INCLUDE_POLICY_POLICY_TYPES_H_
diff --git a/src/components/policy/policy_external/src/cache_manager.cc b/src/components/policy/policy_external/src/cache_manager.cc
index 5bf4bfd658..a49d450a9e 100644
--- a/src/components/policy/policy_external/src/cache_manager.cc
+++ b/src/components/policy/policy_external/src/cache_manager.cc
@@ -1471,40 +1471,60 @@ void CacheManager::GetEnabledCloudApps(
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
}
-bool CacheManager::GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const {
+bool CacheManager::GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const {
const policy_table::ApplicationPolicies& policies =
pt_->policy_table.app_policies_section.apps;
policy_table::ApplicationPolicies::const_iterator policy_iter =
policies.find(policy_app_id);
if (policies.end() != policy_iter) {
auto app_policy = (*policy_iter).second;
- endpoint = app_policy.endpoint.is_initialized() ? *app_policy.endpoint
- : std::string();
- auth_token = app_policy.auth_token.is_initialized() ? *app_policy.auth_token
- : std::string();
- cloud_transport_type = app_policy.cloud_transport_type.is_initialized()
- ? *app_policy.cloud_transport_type
- : std::string();
- certificate = app_policy.certificate.is_initialized()
- ? *app_policy.certificate
- : std::string();
- hybrid_app_preference =
+ out_app_properties.endpoint = app_policy.endpoint.is_initialized()
+ ? *app_policy.endpoint
+ : std::string();
+ out_app_properties.auth_token = app_policy.auth_token.is_initialized()
+ ? *app_policy.auth_token
+ : std::string();
+ out_app_properties.transport_type =
+ app_policy.cloud_transport_type.is_initialized()
+ ? *app_policy.cloud_transport_type
+ : std::string();
+ out_app_properties.certificate = app_policy.certificate.is_initialized()
+ ? *app_policy.certificate
+ : std::string();
+ out_app_properties.hybrid_app_preference =
app_policy.hybrid_app_preference.is_initialized()
? EnumToJsonString(*app_policy.hybrid_app_preference)
: std::string();
- enabled = app_policy.enabled.is_initialized() && *app_policy.enabled;
+ out_app_properties.enabled =
+ app_policy.enabled.is_initialized() && *app_policy.enabled;
return true;
}
return false;
}
+std::vector<std::string> CacheManager::GetEnabledLocalApps() const {
+#if !defined(WEBSOCKET_SERVER_TRANSPORT_SUPPORT)
+ return std::vector<std::string>();
+#else
+ std::vector<std::string> enabled_apps;
+ const policy_table::ApplicationPolicies& app_policies =
+ pt_->policy_table.app_policies_section.apps;
+ for (const auto& app_policies_item : app_policies) {
+ const auto app_policy = app_policies_item.second;
+ // Local (WebEngine) applications
+ // should not have "endpoint" field
+ if (app_policy.endpoint.is_initialized()) {
+ continue;
+ }
+ if (app_policy.enabled.is_initialized() && *app_policy.enabled) {
+ enabled_apps.push_back(app_policies_item.first);
+ }
+ }
+ return enabled_apps;
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+}
+
void CacheManager::InitCloudApp(const std::string& policy_app_id) {
CACHE_MANAGER_CHECK_VOID();
sync_primitives::AutoLock auto_lock(cache_lock_);
diff --git a/src/components/policy/policy_external/src/policy_helper.cc b/src/components/policy/policy_external/src/policy_helper.cc
index 98e5b5b3c1..b8bbb1682c 100644
--- a/src/components/policy/policy_external/src/policy_helper.cc
+++ b/src/components/policy/policy_external/src/policy_helper.cc
@@ -434,6 +434,13 @@ void CheckAppPolicy::InsertPermission(const std::string& app_id,
bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) {
const std::string app_id = app_policy.first;
+
+ const bool app_properties_changed = IsAppPropertiesChanged(app_policy);
+ const bool is_predefined_app = IsPredefinedApp(app_policy);
+ if (!is_predefined_app && app_properties_changed) {
+ AddResult(app_id, RESULT_APP_PROPERTIES_CHANGED);
+ }
+
AppPermissions permissions_diff(app_id);
if (!IsKnownAppication(app_id)) {
LOG4CXX_WARN(logger_,
@@ -668,6 +675,74 @@ bool CheckAppPolicy::IsRequestSubTypeChanged(
return diff.size();
}
+bool CheckAppPolicy::IsAppPropertiesProvided(
+ const AppPoliciesValueType& app_policy) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (app_policy.second.hybrid_app_preference.is_initialized() ||
+ app_policy.second.endpoint.is_initialized() ||
+ app_policy.second.enabled.is_initialized() ||
+ app_policy.second.auth_token.is_initialized() ||
+ app_policy.second.cloud_transport_type.is_initialized() ||
+ app_policy.second.nicknames.is_initialized()) {
+ return true;
+ }
+ return false;
+}
+
+bool CheckAppPolicy::IsAppPropertiesChanged(
+ const AppPoliciesValueType& app_policy) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (!IsAppPropertiesProvided(app_policy)) {
+ return false;
+ }
+
+ if (!IsKnownAppication(app_policy.first)) {
+ LOG4CXX_DEBUG(
+ logger_,
+ "AppProperties provided for new application: " << app_policy.first);
+ return true;
+ }
+
+ policy::AppPoliciesConstItr it =
+ snapshot_->policy_table.app_policies_section.apps.find(app_policy.first);
+ const auto snapshot_properties = *it;
+
+ if (app_policy.second.enabled.is_initialized() &&
+ app_policy.second.enabled != snapshot_properties.second.enabled) {
+ LOG4CXX_DEBUG(logger_, "\"enabled\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.endpoint.is_initialized() &&
+ app_policy.second.endpoint != snapshot_properties.second.endpoint) {
+ LOG4CXX_DEBUG(logger_, "\"endpoint\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.hybrid_app_preference.is_initialized() &&
+ app_policy.second.hybrid_app_preference !=
+ snapshot_properties.second.hybrid_app_preference) {
+ LOG4CXX_DEBUG(logger_, "\"hybrid_app_preference\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.auth_token.is_initialized() &&
+ app_policy.second.auth_token != snapshot_properties.second.auth_token) {
+ LOG4CXX_DEBUG(logger_, "\"auth_token\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.cloud_transport_type.is_initialized() &&
+ app_policy.second.cloud_transport_type !=
+ snapshot_properties.second.cloud_transport_type) {
+ LOG4CXX_DEBUG(logger_, "\"cloud_transport_type\" was changed");
+ return true;
+ }
+
+ return false;
+}
+
bool CheckAppPolicy::IsEncryptionRequiredFlagChanged(
const AppPoliciesValueType& app_policy) const {
LOG4CXX_AUTO_TRACE(logger_);
@@ -778,6 +853,9 @@ void FillActionsForAppPolicies::operator()(
case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED:
actions_[app_id].is_consent_needed = true;
break;
+ case RESULT_APP_PROPERTIES_CHANGED:
+ actions_[app_id].app_properties_changed = true;
+ break;
case RESULT_CONSENT_NOT_REQUIRED:
case RESULT_PERMISSIONS_REVOKED:
case RESULT_REQUEST_TYPE_CHANGED:
diff --git a/src/components/policy/policy_external/src/policy_manager_impl.cc b/src/components/policy/policy_external/src/policy_manager_impl.cc
index 787e65f43a..cd2bd4c2d4 100644
--- a/src/components/policy/policy_external/src/policy_manager_impl.cc
+++ b/src/components/policy/policy_external/src/policy_manager_impl.cc
@@ -622,6 +622,10 @@ void PolicyManagerImpl::ProcessActionsForAppPolicies(
continue;
}
+ if (action.second.app_properties_changed) {
+ app_properties_changed_list_.push_back(app_policy->first);
+ }
+
const auto devices_ids = listener()->GetDevicesIds(app_policy->first);
for (const auto& device_id : devices_ids) {
if (action.second.is_consent_needed) {
@@ -820,21 +824,13 @@ void PolicyManagerImpl::GetEnabledCloudApps(
cache_->GetEnabledCloudApps(enabled_apps);
}
-bool PolicyManagerImpl::GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const {
- return cache_->GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
+std::vector<std::string> PolicyManagerImpl::GetEnabledLocalApps() const {
+ return cache_->GetEnabledLocalApps();
+}
+
+bool PolicyManagerImpl::GetAppProperties(
+ const std::string& policy_app_id, AppProperties& out_app_properties) const {
+ return cache_->GetAppProperties(policy_app_id, out_app_properties);
}
void PolicyManagerImpl::InitCloudApp(const std::string& policy_app_id) {
@@ -1201,6 +1197,12 @@ void PolicyManagerImpl::AddDevice(const std::string& device_id,
}
}
+void PolicyManagerImpl::OnLocalAppAdded() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ update_status_manager_.ScheduleUpdate();
+ StartPTExchange();
+}
+
void PolicyManagerImpl::SetDeviceInfo(const std::string& device_id,
const DeviceInfo& device_info) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -1702,6 +1704,12 @@ void PolicyManagerImpl::UpdateAppConsentWithExternalConsent(
cache_->SetExternalConsentForApp(updated_external_consent_permissions);
}
+void PolicyManagerImpl::SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ listener_->SendOnAppPropertiesChangeNotification(policy_app_id);
+}
+
void PolicyManagerImpl::ResumePendingAppPolicyActions() {
LOG4CXX_AUTO_TRACE(logger_);
@@ -1714,6 +1722,10 @@ void PolicyManagerImpl::ResumePendingAppPolicyActions() {
SendPermissionsToApp(send_permissions_params.first,
send_permissions_params.second);
}
+
+ for (auto& app : app_properties_changed_list_) {
+ SendOnAppPropertiesChangeNotification(app);
+ }
send_permissions_list_.clear();
}
@@ -2318,10 +2330,10 @@ bool PolicyManagerImpl::InitPT(const std::string& file_name,
const bool ret = cache_->Init(file_name, settings);
if (ret) {
RefreshRetrySequence();
- std::vector<std::string> enabled_apps;
- cache_->GetEnabledCloudApps(enabled_apps);
- for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) {
- SendAuthTokenUpdated(*it);
+ std::vector<std::string> enabled_cloud_apps;
+ cache_->GetEnabledCloudApps(enabled_cloud_apps);
+ for (auto app : enabled_cloud_apps) {
+ SendAuthTokenUpdated(app);
}
}
return ret;
@@ -2440,12 +2452,9 @@ void PolicyManagerImpl::SendAppPermissionsChanged(
}
void PolicyManagerImpl::SendAuthTokenUpdated(const std::string policy_app_id) {
- bool enabled = false;
- std::string end, cert, ctt, hap;
- std::string auth_token;
- cache_->GetCloudAppParameters(
- policy_app_id, enabled, end, cert, auth_token, ctt, hap);
- listener_->OnAuthTokenUpdated(policy_app_id, auth_token);
+ AppProperties app_properties;
+ cache_->GetAppProperties(policy_app_id, app_properties);
+ listener_->OnAuthTokenUpdated(policy_app_id, app_properties.auth_token);
}
void PolicyManagerImpl::OnPrimaryGroupsChanged(
diff --git a/src/components/policy/policy_external/test/policy_manager_impl_ptu_test.cc b/src/components/policy/policy_external/test/policy_manager_impl_ptu_test.cc
index 4fbbeaa6aa..920d2e1272 100644
--- a/src/components/policy/policy_external/test/policy_manager_impl_ptu_test.cc
+++ b/src/components/policy/policy_external/test/policy_manager_impl_ptu_test.cc
@@ -146,9 +146,6 @@ TEST_F(PolicyManagerImplTest2, IsAppRevoked_SetRevokedAppID_ExpectAppRevoked) {
// Arrange
CreateLocalPT(preloaded_pt_filename_);
- EXPECT_CALL(listener_, GetDevicesIds(app_id_1_))
- .WillRepeatedly(Return(transport_manager::DeviceList()));
-
policy_manager_->AddApplication(
device_id_1_, app_id_1_, HmiTypes(policy_table::AHT_DEFAULT));
@@ -224,8 +221,10 @@ TEST_F(PolicyManagerImplTest2,
EXPECT_CALL(listener_, OnCurrentDeviceIdUpdateRequired(_, app_id_1_))
.Times(0);
- EXPECT_CALL(listener_, GetDevicesIds(app_id_1_))
- .WillRepeatedly(Return(transport_manager::DeviceList(1, device_id_1_)));
+ ON_CALL(listener_, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
+ ON_CALL(listener_, GetDevicesIds(app_id_1_))
+ .WillByDefault(Return(transport_manager::DeviceList(1, device_id_1_)));
policy_manager_->SetUserConsentForDevice(device_id_1_, true);
// Add app from consented device. App will be assigned with default policies
@@ -289,8 +288,12 @@ TEST_F(PolicyManagerImplTest2,
"Bluetooth"));
EXPECT_CALL(listener_, OnCurrentDeviceIdUpdateRequired(_, application_id_))
.Times(0);
- EXPECT_CALL(listener_, GetDevicesIds(application_id_))
- .WillRepeatedly(Return(transport_manager::DeviceList(1, device_id_1_)));
+
+ ON_CALL(listener_, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
+ ON_CALL(listener_, GetDevicesIds(app_id_1_))
+ .WillByDefault(Return(transport_manager::DeviceList(1, device_id_1_)));
+
policy_manager_->SetUserConsentForDevice(device_id_1_, true);
// Add app from consented device. App will be assigned with default policies
policy_manager_->AddApplication(
diff --git a/src/components/policy/policy_external/test/policy_manager_impl_test_base.cc b/src/components/policy/policy_external/test/policy_manager_impl_test_base.cc
index 9f363a223a..dc1d7a06ef 100644
--- a/src/components/policy/policy_external/test/policy_manager_impl_test_base.cc
+++ b/src/components/policy/policy_external/test/policy_manager_impl_test_base.cc
@@ -257,6 +257,8 @@ void PolicyManagerImplTest2::SetUp() {
ON_CALL(listener_, GetRegisteredLinks(_)).WillByDefault(Return());
ON_CALL(listener_, ptu_retry_handler())
.WillByDefault(ReturnRef(ptu_retry_handler_));
+ ON_CALL(listener_, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
file_system::CreateDirectory(app_storage_folder_);
@@ -675,6 +677,8 @@ PolicyManagerImplTest_RequestTypes::PolicyManagerImplTest_RequestTypes()
void PolicyManagerImplTest_RequestTypes::SetUp() {
ON_CALL(listener_, GetRegisteredLinks(_)).WillByDefault(Return());
+ ON_CALL(listener_, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
file_system::CreateDirectory(app_storage_folder_);
const bool in_memory = true;
diff --git a/src/components/policy/policy_regular/include/policy/cache_manager.h b/src/components/policy/policy_regular/include/policy/cache_manager.h
index 6bd2c4840b..0ad7634382 100644
--- a/src/components/policy/policy_regular/include/policy/cache_manager.h
+++ b/src/components/policy/policy_regular/include/policy/cache_manager.h
@@ -161,6 +161,7 @@ class CacheManager : public CacheManagerInterface {
const boost::optional<std::string> LockScreenDismissalWarningMessage(
const std::string& language) const OVERRIDE;
+
/**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
@@ -170,28 +171,14 @@ class CacheManager : public CacheManagerInterface {
std::vector<std::string>& enabled_apps) const;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
- * given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const;
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ std::vector<std::string> GetEnabledLocalApps() const OVERRIDE;
+
+ bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const OVERRIDE;
/**
* Initializes a new cloud application with default policies
diff --git a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h
index a1b4af0f39..35a61f6597 100644
--- a/src/components/policy/policy_regular/include/policy/cache_manager_interface.h
+++ b/src/components/policy/policy_regular/include/policy/cache_manager_interface.h
@@ -177,29 +177,21 @@ class CacheManagerInterface {
std::vector<std::string>& enabled_apps) const = 0;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ virtual std::vector<std::string> GetEnabledLocalApps() const = 0;
+
+ /**
+ * @brief Get app policy information, all fields that aren't set for a
* given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- virtual bool GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const = 0;
+ * @param policy_app_id policy app id
+ * @param out_app_properties application properties
+ * @return true if application presents in database, otherwise - false
+ */
+ virtual bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const = 0;
/**
* Initializes a new cloud application with default policies
diff --git a/src/components/policy/policy_regular/include/policy/policy_helper.h b/src/components/policy/policy_regular/include/policy/policy_helper.h
index a8cec41715..d5155cf91b 100644
--- a/src/components/policy/policy_regular/include/policy/policy_helper.h
+++ b/src/components/policy/policy_regular/include/policy/policy_helper.h
@@ -131,6 +131,10 @@ struct CheckAppPolicy {
bool IsEncryptionRequiredFlagChanged(
const AppPoliciesValueType& app_policy) const;
+ bool IsAppPropertiesChanged(const AppPoliciesValueType& app_policy) const;
+
+ bool IsAppPropertiesProvided(const AppPoliciesValueType& app_policy) const;
+
private:
PolicyManagerImpl* pm_;
const std::shared_ptr<policy_table::Table> update_;
diff --git a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h
index 192de6cd34..a1a39ff80b 100644
--- a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h
+++ b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h
@@ -671,6 +671,7 @@ class PolicyManagerImpl : public PolicyManager {
* @return policy_table as json object
*/
Json::Value GetPolicyTableData() const OVERRIDE;
+
/**
* @brief Get a list of enabled cloud applications
* @param enabled_apps List filled with the policy app id of each enabled
@@ -680,28 +681,14 @@ class PolicyManagerImpl : public PolicyManager {
std::vector<std::string>& enabled_apps) const OVERRIDE;
/**
- * @brief Get cloud app policy information, all fields that aren't set for a
- * given app will be filled with empty strings
- * @param policy_app_id Unique application id
- * @param enabled Whether or not the app is enabled
- * @param endpoint Filled with the endpoint used to connect to the cloud
- * application
- * @param certificate Filled with the certificate used to for creating a
- * secure connection to the cloud application
- * @param auth_token Filled with the token used for authentication when
- * reconnecting to the cloud app
- * @param cloud_transport_type Filled with the transport type used by the
- * cloud application (ex. "WSS")
- * @param hybrid_app_preference Filled with the hybrid app preference for the
- * cloud application set by the user
- */
- bool GetCloudAppParameters(const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const OVERRIDE;
+ * @brief Get a list of enabled local applications
+ * @return enabled_apps List filled with the policy app id of each enabled
+ * local application
+ */
+ std::vector<std::string> GetEnabledLocalApps() const OVERRIDE;
+
+ bool GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const OVERRIDE;
/**
* @ brief Initialize new cloud app in the policy table
@@ -876,6 +863,10 @@ class PolicyManagerImpl : public PolicyManager {
int32_t timespan_seconds) OVERRIDE;
// Interface StatisticsManager (end)
+ void OnLocalAppAdded() OVERRIDE;
+
+ bool IsNewApplication(const std::string& application_id) const OVERRIDE;
+
void ResetTimeout() OVERRIDE;
protected:
@@ -984,13 +975,6 @@ class PolicyManagerImpl : public PolicyManager {
DeviceConsent device_consent);
/**
- * @brief Check if certain application already in policy db.
- * @param policy application id.
- * @return true if application presents false otherwise.
- */
- bool IsNewApplication(const std::string& application_id) const;
-
- /**
* Checks existing and permissions of AppStorageFolder
* @return true if AppStorageFolder exists and has permissions read/write
*/
@@ -1077,6 +1061,9 @@ class PolicyManagerImpl : public PolicyManager {
void SendAppPermissionsChanged(const std::string& device_id,
const std::string& application_id) OVERRIDE;
+ void SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const OVERRIDE;
+
/**
* @brief notify listener of updated auth token for a given policy id
* @param policy_app_id the app id that has an updated auth token
@@ -1185,6 +1172,11 @@ class PolicyManagerImpl : public PolicyManager {
bool send_on_update_sent_out_;
/**
+ * @brief List of chnaged application properties
+ */
+ std::vector<std::string> app_properties_changed_list_;
+
+ /**
* @brief Flag for notifying that invalid PTU should be triggered
*/
bool trigger_ptu_;
diff --git a/src/components/policy/policy_regular/include/policy/policy_types.h b/src/components/policy/policy_regular/include/policy/policy_types.h
index f8d71ecb13..7f95d9132b 100644
--- a/src/components/policy/policy_regular/include/policy/policy_types.h
+++ b/src/components/policy/policy_regular/include/policy/policy_types.h
@@ -234,8 +234,11 @@ struct DeviceInfo {
using namespace helpers;
static const std::string bluetooth("BLUETOOTH");
static const std::string wifi("WIFI");
+ static const std::string webengine("WEBENGINE_WEBSOCKET");
if (Compare<std::string, EQ, ONE>(deviceType, bluetooth, wifi)) {
connection_type.assign("BTMAC");
+ } else if (Compare<std::string, EQ, ONE>(deviceType, webengine)) {
+ connection_type.assign("");
}
}
};
@@ -444,11 +447,13 @@ struct ApplicationPolicyActions {
ApplicationPolicyActions()
: is_notify_system(false)
, is_send_permissions_to_app(false)
- , is_consent_needed(false) {}
+ , is_consent_needed(false)
+ , app_properties_changed(false) {}
bool is_notify_system;
bool is_send_permissions_to_app;
bool is_consent_needed;
+ bool app_properties_changed;
};
/**
@@ -508,7 +513,8 @@ enum PermissionsCheckResult {
RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED,
RESULT_REQUEST_TYPE_CHANGED,
RESULT_REQUEST_SUBTYPE_CHANGED,
- RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED
+ RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED,
+ RESULT_APP_PROPERTIES_CHANGED
};
/**
@@ -524,6 +530,68 @@ typedef std::set<std::pair<std::string, PermissionsCheckResult> >
*/
typedef std::pair<uint32_t, uint32_t> AppIdURL;
+/**
+ * @brief The AppProperties struct contains application properties
+ */
+struct AppProperties {
+ AppProperties()
+ : endpoint()
+ , certificate()
+ , enabled(false)
+ , auth_token()
+ , transport_type()
+ , hybrid_app_preference() {}
+
+ AppProperties(std::string endpoint,
+ std::string certificate,
+ bool enabled,
+ std::string auth_token,
+ std::string transport_type,
+ std::string hybrid_app_preference)
+ : endpoint(endpoint)
+ , certificate(certificate)
+ , enabled(enabled)
+ , auth_token(auth_token)
+ , transport_type(transport_type)
+ , hybrid_app_preference(hybrid_app_preference) {}
+
+ /**
+ * @brief endpoint Filled with the endpoint used to connect to the cloud
+ * application.
+ * @note should be absent for local applications
+ */
+ std::string endpoint;
+
+ /**
+ * @brief certificate Filled with the certificate used for creation
+ * of a secure connection to the cloud application
+ */
+ std::string certificate;
+
+ /**
+ * @brief enabled Whether or not the app is enabled
+ */
+ bool enabled;
+
+ /**
+ * @brief auth_token Filled with the token used for authentication when
+ * reconnecting to the cloud app
+ */
+ std::string auth_token;
+
+ /**
+ * @brief transport_type Filled with the transport type used by the
+ * cloud/local application (ex. "WSS")
+ */
+ std::string transport_type;
+
+ /**
+ * @brief hybrid_app_preference Filled with the hybrid app preference for the
+ * application set by the user
+ */
+ std::string hybrid_app_preference;
+};
+
} // namespace policy
#endif // SRC_COMPONENTS_POLICY_POLICY_EXTERNAL_INCLUDE_POLICY_POLICY_TYPES_H_
diff --git a/src/components/policy/policy_regular/src/cache_manager.cc b/src/components/policy/policy_regular/src/cache_manager.cc
index 743b9eff6c..7a6f98f536 100644
--- a/src/components/policy/policy_regular/src/cache_manager.cc
+++ b/src/components/policy/policy_regular/src/cache_manager.cc
@@ -766,35 +766,55 @@ void CacheManager::GetEnabledCloudApps(
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
}
-bool CacheManager::GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const {
+std::vector<std::string> CacheManager::GetEnabledLocalApps() const {
+#if !defined(WEBSOCKET_SERVER_TRANSPORT_SUPPORT)
+ return std::vector<std::string>();
+#else
+ std::vector<std::string> enabled_apps;
+ const policy_table::ApplicationPolicies& app_policies =
+ pt_->policy_table.app_policies_section.apps;
+ for (const auto& app_policies_item : app_policies) {
+ const auto app_policy = app_policies_item.second;
+ // Local (WebEngine) applications
+ // should not have "endpoint" field
+ if (app_policy.endpoint.is_initialized()) {
+ continue;
+ }
+ if (app_policy.enabled.is_initialized() && *app_policy.enabled) {
+ enabled_apps.push_back(app_policies_item.first);
+ }
+ }
+ return enabled_apps;
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+}
+
+bool CacheManager::GetAppProperties(const std::string& policy_app_id,
+ AppProperties& out_app_properties) const {
const policy_table::ApplicationPolicies& policies =
pt_->policy_table.app_policies_section.apps;
policy_table::ApplicationPolicies::const_iterator policy_iter =
policies.find(policy_app_id);
if (policies.end() != policy_iter) {
auto app_policy = (*policy_iter).second;
- endpoint = app_policy.endpoint.is_initialized() ? *app_policy.endpoint
- : std::string();
- auth_token = app_policy.auth_token.is_initialized() ? *app_policy.auth_token
- : std::string();
- cloud_transport_type = app_policy.cloud_transport_type.is_initialized()
- ? *app_policy.cloud_transport_type
- : std::string();
- certificate = app_policy.certificate.is_initialized()
- ? *app_policy.certificate
- : std::string();
- hybrid_app_preference =
+ out_app_properties.endpoint = app_policy.endpoint.is_initialized()
+ ? *app_policy.endpoint
+ : std::string();
+ out_app_properties.auth_token = app_policy.auth_token.is_initialized()
+ ? *app_policy.auth_token
+ : std::string();
+ out_app_properties.transport_type =
+ app_policy.cloud_transport_type.is_initialized()
+ ? *app_policy.cloud_transport_type
+ : std::string();
+ out_app_properties.certificate = app_policy.certificate.is_initialized()
+ ? *app_policy.certificate
+ : std::string();
+ out_app_properties.hybrid_app_preference =
app_policy.hybrid_app_preference.is_initialized()
? EnumToJsonString(*app_policy.hybrid_app_preference)
: std::string();
- enabled = app_policy.enabled.is_initialized() && *app_policy.enabled;
+ out_app_properties.enabled =
+ app_policy.enabled.is_initialized() && *app_policy.enabled;
return true;
}
return false;
diff --git a/src/components/policy/policy_regular/src/policy_helper.cc b/src/components/policy/policy_regular/src/policy_helper.cc
index b689ed81ba..08f1fbb177 100644
--- a/src/components/policy/policy_regular/src/policy_helper.cc
+++ b/src/components/policy/policy_regular/src/policy_helper.cc
@@ -388,6 +388,12 @@ void CheckAppPolicy::AddResult(const std::string& app_id,
bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) {
const std::string app_id = app_policy.first;
+ const bool app_properties_changed = IsAppPropertiesChanged(app_policy);
+ const bool is_predefined_app = IsPredefinedApp(app_policy);
+ if (!is_predefined_app && app_properties_changed) {
+ AddResult(app_id, RESULT_APP_PROPERTIES_CHANGED);
+ }
+
if (!IsKnownAppication(app_id)) {
LOG4CXX_WARN(logger_,
"Application:" << app_id << " is not present in snapshot.");
@@ -608,6 +614,74 @@ bool CheckAppPolicy::IsRequestSubTypeChanged(
return diff.size();
}
+bool CheckAppPolicy::IsAppPropertiesProvided(
+ const AppPoliciesValueType& app_policy) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (app_policy.second.hybrid_app_preference.is_initialized() ||
+ app_policy.second.endpoint.is_initialized() ||
+ app_policy.second.enabled.is_initialized() ||
+ app_policy.second.auth_token.is_initialized() ||
+ app_policy.second.cloud_transport_type.is_initialized() ||
+ app_policy.second.nicknames.is_initialized()) {
+ return true;
+ }
+ return false;
+}
+
+bool CheckAppPolicy::IsAppPropertiesChanged(
+ const AppPoliciesValueType& app_policy) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ if (!IsAppPropertiesProvided(app_policy)) {
+ return false;
+ }
+
+ if (!IsKnownAppication(app_policy.first)) {
+ LOG4CXX_DEBUG(
+ logger_,
+ "AppProperties provided for new application: " << app_policy.first);
+ return true;
+ }
+
+ policy::AppPoliciesConstItr it =
+ snapshot_->policy_table.app_policies_section.apps.find(app_policy.first);
+ const auto snapshot_properties = *it;
+
+ if (app_policy.second.enabled.is_initialized() &&
+ app_policy.second.enabled != snapshot_properties.second.enabled) {
+ LOG4CXX_DEBUG(logger_, "\"enabled\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.endpoint.is_initialized() &&
+ app_policy.second.endpoint != snapshot_properties.second.endpoint) {
+ LOG4CXX_DEBUG(logger_, "\"endpoint\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.hybrid_app_preference.is_initialized() &&
+ app_policy.second.hybrid_app_preference !=
+ snapshot_properties.second.hybrid_app_preference) {
+ LOG4CXX_DEBUG(logger_, "\"hybrid_app_preference\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.auth_token.is_initialized() &&
+ app_policy.second.auth_token != snapshot_properties.second.auth_token) {
+ LOG4CXX_DEBUG(logger_, "\"auth_token\" was changed");
+ return true;
+ }
+
+ if (app_policy.second.cloud_transport_type.is_initialized() &&
+ app_policy.second.cloud_transport_type !=
+ snapshot_properties.second.cloud_transport_type) {
+ LOG4CXX_DEBUG(logger_, "\"cloud_transport_type\" was changed");
+ return true;
+ }
+
+ return false;
+}
+
bool CheckAppPolicy::IsEncryptionRequiredFlagChanged(
const AppPoliciesValueType& app_policy) const {
auto get_app_encryption_needed =
@@ -699,7 +773,6 @@ void FillActionsForAppPolicies::operator()(
const policy::CheckAppPolicyResults::value_type& value) {
const std::string app_id = value.first;
const auto app_policy = app_policies_.find(app_id);
-
if (app_policies_.end() == app_policy) {
return;
}
@@ -717,6 +790,9 @@ void FillActionsForAppPolicies::operator()(
case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED:
actions_[app_id].is_consent_needed = true;
break;
+ case RESULT_APP_PROPERTIES_CHANGED:
+ actions_[app_id].app_properties_changed = true;
+ break;
case RESULT_CONSENT_NOT_REQUIRED:
case RESULT_PERMISSIONS_REVOKED:
case RESULT_REQUEST_TYPE_CHANGED:
diff --git a/src/components/policy/policy_regular/src/policy_manager_impl.cc b/src/components/policy/policy_regular/src/policy_manager_impl.cc
index b93850f579..94c1009086 100644
--- a/src/components/policy/policy_regular/src/policy_manager_impl.cc
+++ b/src/components/policy/policy_regular/src/policy_manager_impl.cc
@@ -466,6 +466,10 @@ void PolicyManagerImpl::ProcessActionsForAppPolicies(
continue;
}
+ if (it_actions->second.app_properties_changed) {
+ app_properties_changed_list_.push_back(app_policy->first);
+ }
+
const auto devices_ids = listener()->GetDevicesIds(app_policy->first);
for (const auto& device_id : devices_ids) {
if (it_actions->second.is_consent_needed) {
@@ -493,6 +497,12 @@ void PolicyManagerImpl::ProcessActionsForAppPolicies(
}
}
+void PolicyManagerImpl::SendOnAppPropertiesChangeNotification(
+ const std::string& policy_app_id) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ listener_->SendOnAppPropertiesChangeNotification(policy_app_id);
+}
+
void PolicyManagerImpl::ResumePendingAppPolicyActions() {
LOG4CXX_AUTO_TRACE(logger_);
@@ -505,6 +515,11 @@ void PolicyManagerImpl::ResumePendingAppPolicyActions() {
SendPermissionsToApp(send_permissions_params.first,
send_permissions_params.second);
}
+
+ for (auto& app : app_properties_changed_list_) {
+ SendOnAppPropertiesChangeNotification(app);
+ }
+
send_permissions_list_.clear();
}
@@ -682,6 +697,12 @@ void PolicyManagerImpl::OnAppsSearchCompleted(const bool trigger_ptu) {
}
}
+void PolicyManagerImpl::OnLocalAppAdded() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ update_status_manager_.ScheduleUpdate();
+ StartPTExchange();
+}
+
void PolicyManagerImpl::OnAppRegisteredOnMobile(
const std::string& device_id, const std::string& application_id) {
StartPTExchange();
@@ -738,21 +759,13 @@ void PolicyManagerImpl::GetEnabledCloudApps(
cache_->GetEnabledCloudApps(enabled_apps);
}
-bool PolicyManagerImpl::GetCloudAppParameters(
- const std::string& policy_app_id,
- bool& enabled,
- std::string& endpoint,
- std::string& certificate,
- std::string& auth_token,
- std::string& cloud_transport_type,
- std::string& hybrid_app_preference) const {
- return cache_->GetCloudAppParameters(policy_app_id,
- enabled,
- endpoint,
- certificate,
- auth_token,
- cloud_transport_type,
- hybrid_app_preference);
+std::vector<std::string> PolicyManagerImpl::GetEnabledLocalApps() const {
+ return cache_->GetEnabledLocalApps();
+}
+
+bool PolicyManagerImpl::GetAppProperties(
+ const std::string& policy_app_id, AppProperties& out_app_properties) const {
+ return cache_->GetAppProperties(policy_app_id, out_app_properties);
}
void PolicyManagerImpl::InitCloudApp(const std::string& policy_app_id) {
@@ -1581,10 +1594,10 @@ bool PolicyManagerImpl::InitPT(const std::string& file_name,
if (!certificate_data.empty()) {
listener_->OnCertificateUpdated(certificate_data);
}
- std::vector<std::string> enabled_apps;
- cache_->GetEnabledCloudApps(enabled_apps);
- for (auto it = enabled_apps.begin(); it != enabled_apps.end(); ++it) {
- SendAuthTokenUpdated(*it);
+ std::vector<std::string> enabled_cloud_apps;
+ cache_->GetEnabledCloudApps(enabled_cloud_apps);
+ for (auto app : enabled_cloud_apps) {
+ SendAuthTokenUpdated(app);
}
}
return ret;
@@ -1735,12 +1748,9 @@ void PolicyManagerImpl::SendAppPermissionsChanged(
}
void PolicyManagerImpl::SendAuthTokenUpdated(const std::string policy_app_id) {
- bool enabled = false;
- std::string end, cert, ctt, hap;
- std::string auth_token;
- cache_->GetCloudAppParameters(
- policy_app_id, enabled, end, cert, auth_token, ctt, hap);
- listener_->OnAuthTokenUpdated(policy_app_id, auth_token);
+ AppProperties app_properties;
+ cache_->GetAppProperties(policy_app_id, app_properties);
+ listener_->OnAuthTokenUpdated(policy_app_id, app_properties.auth_token);
}
void PolicyManagerImpl::OnPrimaryGroupsChanged(
diff --git a/src/components/policy/policy_regular/test/policy_manager_impl_test.cc b/src/components/policy/policy_regular/test/policy_manager_impl_test.cc
index abb5901690..08e8dd4023 100644
--- a/src/components/policy/policy_regular/test/policy_manager_impl_test.cc
+++ b/src/components/policy/policy_regular/test/policy_manager_impl_test.cc
@@ -1328,6 +1328,8 @@ TEST_F(
// Arrange
CreateLocalPT("sdl_preloaded_pt.json");
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
+ ON_CALL(listener, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
GetPTU("valid_sdl_pt_update.json");
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
// Try to add existing app
@@ -1342,6 +1344,8 @@ TEST_F(PolicyManagerImplTest2, UpdateApplication_AppServices) {
// Arrange
CreateLocalPT("sdl_preloaded_pt.json");
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
+ ON_CALL(listener, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
GetPTU("valid_sdl_pt_update.json");
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
// Try to add existing app
@@ -1376,6 +1380,8 @@ TEST_F(PolicyManagerImplTest2,
const int kSecondsInDay = 60 * 60 * 24;
int days = date_time::getSecs(current_time) / kSecondsInDay;
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
+ ON_CALL(listener, GetDevicesIds(_))
+ .WillByDefault(Return(transport_manager::DeviceList()));
GetPTU("valid_sdl_pt_update.json");
EXPECT_EQ("UP_TO_DATE", manager->GetPolicyTableStatus());
diff --git a/src/components/transport_manager/CMakeLists.txt b/src/components/transport_manager/CMakeLists.txt
index a539c64578..82cc00baf2 100644
--- a/src/components/transport_manager/CMakeLists.txt
+++ b/src/components/transport_manager/CMakeLists.txt
@@ -106,6 +106,18 @@ else()
)
endif()
+if(NOT BUILD_WEBSOCKET_SERVER_SUPPORT)
+ list(APPEND EXCLUDE_PATHS
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/transport_manager/websocket_server
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/websocket_server
+ )
+elseif(NOT ENABLE_SECURITY)
+ list(APPEND EXCLUDE_PATHS
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/transport_manager/websocket_server/websocket_secure_session.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/websocket_server/websocket_secure_session.cc
+ )
+endif()
+
if(NOT ENABLE_IAP2EMULATION)
list (APPEND EXCLUDE_PATHS
${CMAKE_CURRENT_SOURCE_DIR}/include/iap2_emulation/iap2_transport_adapter.h
diff --git a/src/components/transport_manager/docs/SDL.SDD.WebEngineSupport.dox b/src/components/transport_manager/docs/SDL.SDD.WebEngineSupport.dox
new file mode 100644
index 0000000000..77ab46e247
--- /dev/null
+++ b/src/components/transport_manager/docs/SDL.SDD.WebEngineSupport.dox
@@ -0,0 +1,127 @@
+/**
+\page web_engine_support Web Engine Support Detailed Design
+## Table of contents
+- \subpage wes_intoduction
+ + \ref wes_rationale "1.1 Rationale"
+ + \ref wes_scope "1.2 Scope"
+- \subpage wes_detail_design
+ + \ref wes_design_solutions "2.1 Design solutions"
+ + \ref wes_class_structure "2.2 Class Structure"
+ + \ref wes_sequence_diagram "2.3 Sequence diagram"
+- \subpage wes_data_structures
+ + \ref wes_data_structure "3.1 Data structures"
+- \subpage wes_references_and_history
+ + \ref wes_history "4.1 References"
+*/
+//-----------------------------------------------------------
+/**
+\page wes_intoduction 1 Introduction
+The document is intended to support software developers,
+maintenance and integration engineers with sufficient,
+detailed information concerning the design, development and
+deployment concepts, to accomplish their respective tasks without reliance on the authors.
+
+\anchor wes_rationale
+## 1.1 Rationale
+Boost asio libraries were utilized to enable websocket server connection for web engine.
+To split responsibilities, the following entities were introduces to enable server connections:
+- WebSocketListener
+- WebSocketConnection
+- WebSocketSession
+- WebSocketSecureSession
+
+
+\anchor wes_scope
+## 1.2 Scope
+All aforementioned entities are part of transport_manager namespace
+
+*/
+//-----------------------------------------------------------
+/**
+\page wes_detail_design 2 Component detail design
+\anchor wes_design_solutions
+### 2.1 Design solutions
+
+- WebSocket server was implemented using several layers (e.g. WebSocketConnection, WebSocketSession, WebSocketSecureSession).
+- Utilizing boost::asio library to host a websocket server and establish websocket connections
+- Utilizing asynchronous programming to make all server calls nonblocking
+- CRTP and template specialization to facilitate code reuse.
+
+
+
+#### Design description
+transport_manager::WebSocketListener is an entity that is responsible for creating and listening for connections.
+It includes creating boost library objects to establish a connection, deducing security parameters during its initialization,
+opening a port and accepting new connections.
+The following parameters are used to configure security connection:
+- WSServerCertificatePath (path to websocket server certificate)
+- WSServerKeyPath (path to websocket server private key path)
+- WSServerCACertificatePath (path to CA certificate)
+
+SDL will run in WSS mode only if ALL these parameters are present and have valid values.
+To run SDL as a WS server, one should remove ALL these parameters from smartDeviceLink.ini file (including parameter KEY and VALUE).
+All other cases of parameter configuration (e.g. two of three params are set) are considered to be misconfiguration,
+and SDL will launch with no websocket server transport.
+
+transport_manager::WebSocketConnection is a class that is used as an additional layer between WebSocketListener and WebSocketSession,
+with ability to hadle input/output errors.
+
+transport_manager::WebSocketSession is a class that represents the lowest layer of abstraction in regards of WS server connection. It is used to read
+data from socket to buffer and notifying its observers about connection events.
+
+transport_manager::WebSocketSecureSession is a class that inherits WebSocketSession with an additional role of supporting TLS handshake.
+
+\anchor wes_class_structure
+### 2.2 Class Structure
+The following UML class diagram shows the component structure:
+![Web Engine Support class diagram](WES_classes.png)
+For more information about class diagram follow:
+- http://www.uml-diagrams.org/class-diagrams-overview.htqml
+- https://sourcemaking.com/uml/modeling-it-systems/structural-view/class-diagram
+
+\anchor wes_sequence_diagram
+### 2.3 Sequence diagram
+The following UML sequence diagram shows the component dynamic behavior.
+For more information about sequence diagram follow:
+- http://www.uml-diagrams.org/sequence-diagrams.html
+- https://sourcemaking.com/uml/modeling-it-systems/external-view/use-case-sequence-diagram
+
+Establishing WebSocket connection:
+![WES Basic flow](WES_sequence.png)
+*/
+
+//-----------------------------------------------------------
+/**
+\page wes_data_structures 3 Component data and resources
+\anchor wes_data_structure
+### 3.1 Element Data Structure
+The following data types are used by WebSocketListener:
+ - transport_manager::TransportAdapterController
+ - boost::asio::io_context
+ - boost::ssl::context
+ - boost::asio::tcp::acceptor
+ - boost::asio::tcp::socket
+ - boost::asio::thread_pool
+ - WebSocketConnection
+ - transport_manager::TransportManagerSettings
+
+//-----------------------------------------------------------
+/**
+\page wes_references_and_history 4 References and history
+\anchor wes_history
+### 4.1 Document history
+Document change history
+
+| Version | Date | Author/Editor | Change description |
+|-------------|------------|----------------------------------------|---------------------|
+| 0.1 | 02/03/2020 | [MKed](https://github.com/mked-luxoft) | Initial version from the previous [SDL SDD](https://adc.luxoft.com/confluence/pages/viewpage.action?pageId=279677125) |
+
+Document approve history
+
+| Version | Date | Author/Editor | Change description |
+|-------------|------------|-----------------------------|---------------------|
+| | | | |
+
+For more precise document change history follow github history -
+- https://github.com/smartdevicelink/sdl_core/commits/develop/src/components/transport_manager/docs/SDL.SDD.WebEngineSupport.dox
+*/ \ No newline at end of file
diff --git a/src/components/transport_manager/docs/assets/WES_classes.png b/src/components/transport_manager/docs/assets/WES_classes.png
new file mode 100644
index 0000000000..bbb19b8f02
--- /dev/null
+++ b/src/components/transport_manager/docs/assets/WES_classes.png
Binary files differ
diff --git a/src/components/transport_manager/docs/assets/WES_sequence.png b/src/components/transport_manager/docs/assets/WES_sequence.png
new file mode 100644
index 0000000000..61aa5e35fb
--- /dev/null
+++ b/src/components/transport_manager/docs/assets/WES_sequence.png
Binary files differ
diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h
index 72a67a3087..92a3a2c2f4 100644
--- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h
+++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_controller.h
@@ -225,6 +225,8 @@ class TransportAdapterController {
* @param new_config The new configuration of the transport
*/
virtual void TransportConfigUpdated(const TransportConfig& new_config) = 0;
+
+ virtual DeviceSptr GetWebEngineDevice() const = 0;
};
} // namespace transport_adapter
diff --git a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h
index db9bb03998..f8aa93b4e6 100644
--- a/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h
+++ b/src/components/transport_manager/include/transport_manager/transport_adapter/transport_adapter_impl.h
@@ -283,13 +283,6 @@ class TransportAdapterImpl : public TransportAdapter,
*/
void SearchDeviceFailed(const SearchDeviceError& error) OVERRIDE;
- /**
- * @brief Add device to the container(map), if container doesn't hold it yet.
- *
- * @param device Smart pointer to the device.
- *
- * @return Smart pointer to the device.
- */
DeviceSptr AddDevice(DeviceSptr device) OVERRIDE;
/**
@@ -517,6 +510,12 @@ class TransportAdapterImpl : public TransportAdapter,
TMTelemetryObserver* GetTelemetryObserver() OVERRIDE;
#endif // TELEMETRY_MONITOR
+ /**
+ * @brief GetWebEngineDevice
+ * @return shared pointer to WebEngine device
+ */
+ DeviceSptr GetWebEngineDevice() const OVERRIDE;
+
protected:
/**
* @brief Store adapter state where applicable
diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_default.h b/src/components/transport_manager/include/transport_manager/transport_manager_default.h
index 9d428cf817..81fc92dc38 100644
--- a/src/components/transport_manager/include/transport_manager/transport_manager_default.h
+++ b/src/components/transport_manager/include/transport_manager/transport_manager_default.h
@@ -61,6 +61,10 @@ struct TransportAdapterFactory {
CreatorTA<resumption::LastStateWrapperPtr&, const TransportManagerSettings&>
ta_cloud_creator_;
#endif
+#if defined(WEBSOCKET_SERVER_TRANSPORT_SUPPORT)
+ CreatorTA<resumption::LastStateWrapperPtr&, const TransportManagerSettings&>
+ ta_websocket_server_creator_;
+#endif
};
/**
diff --git a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
index 2fbd592b72..a765bb045a 100644
--- a/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
+++ b/src/components/transport_manager/include/transport_manager/transport_manager_impl.h
@@ -262,6 +262,10 @@ class TransportManagerImpl
int PerformActionOnClients(
const TransportAction required_action) const OVERRIDE;
+ void CreateWebEngineDevice() OVERRIDE;
+
+ const DeviceInfo& GetWebEngineDeviceInfo() const OVERRIDE;
+
/**
* @brief OnDeviceListUpdated updates device list and sends appropriate
* notifications to listeners in case of something is changed
@@ -421,6 +425,8 @@ class TransportManagerImpl
sync_primitives::Lock events_processing_lock_;
sync_primitives::ConditionalVariable events_processing_cond_var_;
+ DeviceInfo web_engine_device_info_;
+
/**
* @brief Adds new incoming connection to connections list
* @param c New connection
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h
new file mode 100644
index 0000000000..fb904d645e
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_connection.h
@@ -0,0 +1,126 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_CONNECTION_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_CONNECTION_H_
+
+#include <memory>
+#include <queue>
+#include "transport_manager/transport_adapter/connection.h"
+#include "utils/message_queue.h"
+#include "utils/threads/thread.h"
+
+#ifdef ENABLE_SECURITY
+#include "transport_manager/websocket_server/websocket_secure_session.h"
+#else
+#include "transport_manager/websocket_server/websocket_session.h"
+#endif // ENABLE_SECURITY
+
+namespace transport_manager {
+namespace transport_adapter {
+
+using ::utils::MessageQueue;
+
+typedef ::protocol_handler::RawMessagePtr Message;
+typedef std::queue<Message> AsyncQueue;
+
+class TransportAdapterController;
+
+template <typename Session = WebSocketSession<> >
+class WebSocketConnection
+ : public std::enable_shared_from_this<WebSocketConnection<Session> >,
+ public Connection {
+ public:
+ WebSocketConnection(const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ boost::asio::ip::tcp::socket socket,
+ TransportAdapterController* controller);
+
+#ifdef ENABLE_SECURITY
+ WebSocketConnection(const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ boost::asio::ip::tcp::socket socket,
+ ssl::context& ctx,
+ TransportAdapterController* controller);
+#endif // ENABLE_SECURITY
+
+ ~WebSocketConnection();
+
+ TransportAdapter::Error Disconnect() OVERRIDE;
+
+ TransportAdapter::Error SendData(
+ protocol_handler::RawMessagePtr message) OVERRIDE;
+
+ void DataReceive(protocol_handler::RawMessagePtr frame);
+ void Run();
+ bool IsShuttingDown();
+
+ protected:
+ void Shutdown();
+ void OnError();
+
+ private:
+ const DeviceUID device_uid_;
+ const ApplicationHandle app_handle_;
+ std::shared_ptr<Session> session_;
+ TransportAdapterController* controller_;
+
+ std::atomic_bool shutdown_;
+
+ MessageQueue<Message, AsyncQueue> message_queue_;
+
+ class LoopThreadDelegate : public threads::ThreadDelegate {
+ public:
+ LoopThreadDelegate(MessageQueue<Message, AsyncQueue>* message_queue,
+ DataWriteCallback data_write,
+ OnIOErrorCallback on_io_error);
+
+ virtual void threadMain() OVERRIDE;
+ virtual void exitThreadMain() OVERRIDE;
+
+ void OnWrite();
+
+ void SetShutdown();
+
+ private:
+ void DrainQueue();
+ MessageQueue<Message, AsyncQueue>& message_queue_;
+ DataWriteCallback data_write_;
+ OnIOErrorCallback on_io_error_;
+ };
+
+ LoopThreadDelegate* thread_delegate_;
+ threads::Thread* thread_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_CONNECTION_H_
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_device.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_device.h
new file mode 100644
index 0000000000..10c6e54424
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_device.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2020, Livio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file websocket_device.h
+ * \brief WebSocketDevice class header file.
+ */
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_DEVICE_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_DEVICE_H_
+
+#include <boost/beast/websocket.hpp>
+#include <string>
+#include "transport_manager/transport_adapter/device.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+using protocol_type = boost::asio::basic_stream_socket<tcp>::protocol_type;
+
+class WebSocketDevice : public Device {
+ public:
+ WebSocketDevice(const std::string& name, const DeviceUID& unique_device_id);
+
+ virtual const std::string& GetHost() const;
+ virtual const std::string& GetPort() const;
+ virtual const std::string GetTarget() const;
+ virtual void AddApplication(const ApplicationHandle& app_handle);
+
+ protected:
+ bool IsSameAs(const Device* other_device) const OVERRIDE;
+ ApplicationList GetApplicationList() const OVERRIDE;
+
+ private:
+ std::string host_;
+ std::string port_;
+ bool is_secure_connect_;
+ protocol_type protocol_;
+ ApplicationList app_list_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_DEVICE_H_
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_listener.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_listener.h
new file mode 100644
index 0000000000..3a0131f087
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_listener.h
@@ -0,0 +1,120 @@
+/*
+ * \file websocket_listener.h
+ * \brief WebSocketListener class header file.
+ *
+ * Copyright (c) 2020
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_LISTENER_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_LISTENER_H_
+
+#include <boost/asio/thread_pool.hpp>
+#include <memory>
+#include <vector>
+#include "transport_manager/transport_adapter/client_connection_listener.h"
+#include "transport_manager/transport_manager_settings.h"
+#include "transport_manager/websocket_server/websocket_connection.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+class TransportAdapterController;
+
+/**
+ * @brief Class responsible for communication over websockets.
+ */
+class WebSocketListener : public ClientConnectionListener {
+ public:
+ /**
+ * @brief Constructor.
+ * @param controller Pointer to the device adapter controller.
+ * @param number of threads for listen incoming connections
+ */
+ WebSocketListener(TransportAdapterController* controller,
+ const TransportManagerSettings& settings,
+ const int num_threads = 1);
+
+ /**
+ * @brief Destructor.
+ */
+ ~WebSocketListener();
+
+ TransportAdapter::Error Init() OVERRIDE;
+ void Terminate() OVERRIDE;
+ bool IsInitialised() const OVERRIDE {
+ return true;
+ }
+ TransportAdapter::Error StartListening() OVERRIDE;
+ TransportAdapter::Error StopListening() OVERRIDE {
+ return TransportAdapter::OK;
+ }
+ TransportAdapter::Error SuspendListening() OVERRIDE {
+ return TransportAdapter::OK;
+ }
+ TransportAdapter::Error ResumeListening() OVERRIDE {
+ return TransportAdapter::OK;
+ }
+
+ protected:
+#ifdef ENABLE_SECURITY
+ TransportAdapter::Error AddCertificateAuthority();
+#endif
+ bool Run();
+ bool WaitForConnection();
+ void StartSession(boost::system::error_code ec);
+ void Shutdown();
+
+ template <typename Connection>
+ void ProcessConnection(std::shared_ptr<Connection> connection,
+ const DeviceSptr,
+ const ApplicationHandle);
+
+ private:
+ TransportAdapterController* controller_;
+ boost::asio::io_context ioc_;
+#ifdef ENABLE_SECURITY
+ ssl::context ctx_;
+ bool start_secure_;
+#endif // ENABLE_SECURITY
+ tcp::acceptor acceptor_;
+ tcp::socket socket_;
+ std::unique_ptr<boost::asio::thread_pool> io_pool_;
+ const int num_threads_;
+ std::atomic_bool shutdown_;
+ std::vector<std::shared_ptr<Connection> > connection_list_;
+ sync_primitives::Lock connection_list_lock;
+ const TransportManagerSettings& settings_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_LISTENER_H_
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h
new file mode 100644
index 0000000000..a3ead8e5a5
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_secure_session.h
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SECURE_SESSION_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SECURE_SESSION_H_
+
+#include <memory>
+#include "transport_manager/websocket_server/websocket_session.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+CREATE_LOGGERPTR_GLOBAL(wss_logger_, "WebSocketSecureSession")
+
+template <typename ExecutorType = ssl::stream<tcp::socket&> >
+class WebSocketSecureSession : public WebSocketSession<ExecutorType> {
+ public:
+ WebSocketSecureSession(tcp::socket,
+ ssl::context& ctx,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_errror);
+
+ void AsyncAccept() OVERRIDE;
+ virtual void AsyncHandshake(boost::system::error_code ec);
+
+ std::shared_ptr<WebSocketSecureSession<ExecutorType> > shared_from_this() {
+ auto base_ptr =
+ static_cast<WebSocketSession<ExecutorType>*>(this)->shared_from_this();
+ return std::static_pointer_cast<WebSocketSecureSession<ExecutorType> >(
+ base_ptr);
+ }
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SECURE_SESSION_H_
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_server_transport_adapter.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_server_transport_adapter.h
new file mode 100644
index 0000000000..23122b2e98
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_server_transport_adapter.h
@@ -0,0 +1,136 @@
+/*
+ * \file websocket_transport_adapter.h
+ * \brief WebSocketTransportAdapter class header file.
+ *
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SERVER_TRANSPORT_ADAPTER_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SERVER_TRANSPORT_ADAPTER_H_
+
+#include <string>
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+/**
+ * @brief Transport adapter that uses WebSocket transport.
+ */
+class WebSocketServerTransportAdapter : public TransportAdapterImpl {
+ public:
+ /**
+ * @brief Constructor.
+ */
+ WebSocketServerTransportAdapter(
+ resumption::LastStateWrapperPtr last_state_wrapper,
+ const TransportManagerSettings& settings);
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~WebSocketServerTransportAdapter();
+
+ /**
+ * @brief Websocket server transport adapter
+ * specific Init() method
+ * @note Perform additional actions required by WS transport adapter
+ * then calls basic class Init()
+ */
+ TransportAdapter::Error Init() OVERRIDE;
+
+ /**
+ * @brief Adds webengine device to internal storage
+ * of related WebSocket transport adapter
+ * @param device webengine device to add
+ * @note webengine device storage required
+ * to be used in Low Voltage conditions
+ */
+ DeviceSptr AddDevice(DeviceSptr device) OVERRIDE;
+
+ /**
+ * @brief Notification that transport's configuration is updated
+ *
+ * @param new_config The new configuration of the transport
+ */
+ void TransportConfigUpdated(const TransportConfig& new_config) OVERRIDE;
+
+ /**
+ * @brief Returns the transport's configuration information
+ */
+ virtual TransportConfig GetTransportConfiguration() const OVERRIDE;
+
+ /**
+ * @brief Store adapter state in last state
+ */
+ void Store() const OVERRIDE;
+
+ /**
+ * @brief Restore adapter state from last state
+ * @return True on success false otherwise
+ */
+ bool Restore() OVERRIDE;
+
+ /**
+ * @brief Get stored device ID
+ * @return stored unique device id, or empty string if no stored device id
+ * present in last saved state
+ */
+ std::string GetStoredDeviceID() const;
+
+ protected:
+ /**
+ * @brief Return type of device.
+ *
+ * @return String with device type.
+ */
+ DeviceType GetDeviceType() const OVERRIDE;
+
+ private:
+ /**
+ * @brief Keeps transport specific configuration
+ *
+ * TCP transport uses following information:
+ * - "enabled": whether the transport is currently enabled or not. Value can
+ * be "true" or "false".
+ * - "tcp_ip_address": string representation of IP address (either IPv4 or
+ * IPv6)
+ * - "tcp_port": string representation of TCP port number (e.g. "12345")
+ */
+ TransportConfig transport_config_;
+ DeviceSptr webengine_device_;
+ std::string webengine_device_id_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SERVER_TRANSPORT_ADAPTER_H_
diff --git a/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h
new file mode 100644
index 0000000000..a8dadc9831
--- /dev/null
+++ b/src/components/transport_manager/include/transport_manager/websocket_server/websocket_session.h
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SESSION_H_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SESSION_H_
+
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include "protocol/raw_message.h"
+#include "transport_manager/transport_adapter/transport_adapter.h"
+#include "utils/logger.h"
+
+#ifdef ENABLE_SECURITY
+#include <boost/beast/websocket/ssl.hpp>
+#endif // ENABLE_SECURITY
+
+namespace transport_manager {
+namespace transport_adapter {
+
+using DataReceiveCallback =
+ std::function<void(protocol_handler::RawMessagePtr)>;
+using DataWriteCallback = std::function<TransportAdapter::Error(
+ protocol_handler::RawMessagePtr message)>;
+using OnIOErrorCallback = std::function<void()>;
+
+using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
+namespace websocket =
+ boost::beast::websocket; // from <boost/beast/websocket.hpp>
+#ifdef ENABLE_SECURITY
+namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
+#endif // ENABLE_SECURITY
+
+CREATE_LOGGERPTR_GLOBAL(ws_logger_, "WebSocketSession")
+
+class TransportAdapterController;
+
+template <typename ExecutorType = tcp::socket&>
+class WebSocketSession
+ : public std::enable_shared_from_this<WebSocketSession<ExecutorType> > {
+ public:
+ WebSocketSession(boost::asio::ip::tcp::socket socket,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_error);
+
+#ifdef ENABLE_SECURITY
+ WebSocketSession(boost::asio::ip::tcp::socket socket,
+ ssl::context& ctx,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_error);
+#endif // ENABLE_SECURITY
+
+ virtual ~WebSocketSession();
+
+ virtual void AsyncAccept();
+
+ virtual void AsyncRead(boost::system::error_code ec);
+
+ virtual TransportAdapter::Error WriteDown(
+ ::protocol_handler::RawMessagePtr message);
+
+ virtual void Read(boost::system::error_code ec,
+ std::size_t bytes_transferred);
+
+ virtual bool Shutdown();
+
+ protected:
+ tcp::socket socket_;
+ websocket::stream<ExecutorType> ws_;
+ boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+ boost::beast::flat_buffer buffer_;
+ DataReceiveCallback data_receive_;
+ OnIOErrorCallback on_io_error_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SESSION_H_
diff --git a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc
index 4e057aee63..fcae508747 100644
--- a/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc
+++ b/src/components/transport_manager/src/transport_adapter/transport_adapter_impl.cc
@@ -40,6 +40,9 @@
#include "transport_manager/transport_adapter/server_connection_factory.h"
#include "transport_manager/transport_adapter/transport_adapter_impl.h"
#include "transport_manager/transport_adapter/transport_adapter_listener.h"
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+#include "transport_manager/websocket_server/websocket_device.h"
+#endif
namespace transport_manager {
namespace transport_adapter {
@@ -62,8 +65,9 @@ DeviceTypes devicesType = {
std::string("USB_IOS_DEVICE_MODE")),
std::make_pair(DeviceType::IOS_CARPLAY_WIRELESS,
std::string("CARPLAY_WIRELESS_IOS")),
- std::make_pair(DeviceType::CLOUD_WEBSOCKET,
- std::string("CLOUD_WEBSOCKET"))};
+ std::make_pair(DeviceType::CLOUD_WEBSOCKET, std::string("CLOUD_WEBSOCKET")),
+ std::make_pair(DeviceType::WEBENGINE_WEBSOCKET,
+ std::string("WEBENGINE_WEBSOCKET"))};
}
TransportAdapterImpl::TransportAdapterImpl(
@@ -373,6 +377,10 @@ TransportAdapter::Error TransportAdapterImpl::DisconnectDevice(
Error error = OK;
DeviceSptr device = FindDevice(device_id);
+ if (!device) {
+ LOG4CXX_WARN(logger_, "Device with id: " << device_id << " Not found");
+ return BAD_PARAM;
+ }
ConnectionStatusUpdated(device, ConnectionStatus::CLOSING);
std::vector<ConnectionInfo> to_disconnect;
@@ -488,6 +496,32 @@ DeviceList TransportAdapterImpl::GetDeviceList() const {
return devices;
}
+DeviceSptr TransportAdapterImpl::GetWebEngineDevice() const {
+#ifndef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ LOG4CXX_TRACE(logger_,
+ "Web engine support is disabled. Device does not exist");
+ return DeviceSptr();
+#else
+ LOG4CXX_AUTO_TRACE(logger_);
+ sync_primitives::AutoLock locker(devices_mutex_);
+
+ auto web_engine_device =
+ std::find_if(devices_.begin(),
+ devices_.end(),
+ [](const std::pair<DeviceUID, DeviceSptr> device) {
+ return webengine_constants::kWebEngineDeviceName ==
+ device.second->name();
+ });
+
+ if (devices_.end() != web_engine_device) {
+ return web_engine_device->second;
+ }
+
+ LOG4CXX_ERROR(logger_, "WebEngine device not found!");
+ return std::make_shared<transport_adapter::WebSocketDevice>("", "");
+#endif
+}
+
DeviceSptr TransportAdapterImpl::AddDevice(DeviceSptr device) {
LOG4CXX_TRACE(logger_, "enter. device: " << device);
DeviceSptr existing_device;
diff --git a/src/components/transport_manager/src/transport_manager_default.cc b/src/components/transport_manager/src/transport_manager_default.cc
index 0cf9e93f40..74c5b9ceee 100644
--- a/src/components/transport_manager/src/transport_manager_default.cc
+++ b/src/components/transport_manager/src/transport_manager_default.cc
@@ -48,6 +48,10 @@
#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+#include "transport_manager/websocket_server/websocket_server_transport_adapter.h"
+#endif
+
#if defined(ENABLE_IAP2EMULATION)
#include "transport_manager/iap2_emulation/iap2_transport_adapter.h"
#endif // ENABLE_IAP2EMULATION
@@ -82,6 +86,15 @@ TransportAdapterFactory::TransportAdapterFactory() {
last_state_wrapper, settings);
};
#endif
+
+#if defined(WEBSOCKET_SERVER_TRANSPORT_SUPPORT)
+ ta_websocket_server_creator_ =
+ [](resumption::LastStateWrapperPtr last_state_wrapper,
+ const TransportManagerSettings& settings) {
+ return new transport_adapter::WebSocketServerTransportAdapter(
+ last_state_wrapper, settings);
+ };
+#endif
}
TransportManagerDefault::TransportManagerDefault(
@@ -143,6 +156,19 @@ int TransportManagerDefault::Init(
AddTransportAdapter(ta_cloud);
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ auto ta_websocket =
+ ta_factory_.ta_websocket_server_creator_(last_state_wrapper, settings);
+
+#ifdef TELEMETRY_MONITOR
+ if (metric_observer_) {
+ ta_websocket->SetTelemetryObserver(metric_observer_);
+ }
+#endif // TELEMETRY_MONITOR
+ AddTransportAdapter(ta_websocket);
+ ta_websocket = NULL;
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+
#if defined ENABLE_IAP2EMULATION
const uint16_t iap2_bt_emu_port = 23456;
transport_adapter::IAP2BluetoothEmulationTransportAdapter*
diff --git a/src/components/transport_manager/src/transport_manager_impl.cc b/src/components/transport_manager/src/transport_manager_impl.cc
index c6fd60a185..9d4f6be316 100644
--- a/src/components/transport_manager/src/transport_manager_impl.cc
+++ b/src/components/transport_manager/src/transport_manager_impl.cc
@@ -54,6 +54,10 @@
#include "transport_manager/transport_adapter/transport_adapter_event.h"
#include "transport_manager/transport_manager_listener.h"
#include "transport_manager/transport_manager_listener_empty.h"
+#ifdef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+#include "transport_manager/websocket_server/websocket_device.h"
+#include "transport_manager/websocket_server/websocket_server_transport_adapter.h"
+#endif
#include "utils/timer_task_impl.h"
using ::transport_manager::transport_adapter::TransportAdapter;
@@ -104,7 +108,11 @@ TransportManagerImpl::TransportManagerImpl(
this, &TransportManagerImpl::ReconnectionTimeout))
, events_processing_is_active_(true)
, events_processing_lock_()
- , events_processing_cond_var_() {
+ , events_processing_cond_var_()
+ , web_engine_device_info_(0,
+ "",
+ webengine_constants::kWebEngineDeviceName,
+ webengine_constants::kWebEngineConnectionType) {
LOG4CXX_TRACE(logger_, "TransportManager has created");
}
@@ -655,6 +663,66 @@ int TransportManagerImpl::PerformActionOnClients(
return E_SUCCESS;
}
+void TransportManagerImpl::CreateWebEngineDevice() {
+#ifndef WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+ LOG4CXX_TRACE(logger_, "Web engine support is disabled. Exiting function");
+#else
+ LOG4CXX_AUTO_TRACE(logger_);
+ auto web_socket_ta_iterator = std::find_if(
+ transport_adapters_.begin(),
+ transport_adapters_.end(),
+ [](const TransportAdapter* ta) {
+ return transport_adapter::DeviceType::WEBENGINE_WEBSOCKET ==
+ ta->GetDeviceType();
+ });
+
+ if (transport_adapters_.end() == web_socket_ta_iterator) {
+ LOG4CXX_WARN(logger_,
+ "WebSocketServerTransportAdapter not found."
+ "Impossible to create WebEngineDevice");
+ return;
+ }
+
+ auto web_socket_ta =
+ dynamic_cast<transport_adapter::WebSocketServerTransportAdapter*>(
+ *web_socket_ta_iterator);
+
+ if (!web_socket_ta) {
+ LOG4CXX_ERROR(logger_,
+ "Unable to cast from Transport Adapter to "
+ "WebSocketServerTransportAdapter."
+ "Impossible to create WebEngineDevice");
+ return;
+ }
+
+ std::string unique_device_id = web_socket_ta->GetStoredDeviceID();
+
+ DeviceHandle device_handle = converter_.UidToHandle(
+ unique_device_id, webengine_constants::kWebEngineConnectionType);
+
+ web_engine_device_info_ =
+ DeviceInfo(device_handle,
+ unique_device_id,
+ webengine_constants::kWebEngineDeviceName,
+ webengine_constants::kWebEngineConnectionType);
+
+ auto ws_device = std::make_shared<transport_adapter::WebSocketDevice>(
+ web_engine_device_info_.name(), web_engine_device_info_.mac_address());
+
+ ws_device->set_keep_on_disconnect(true);
+
+ RaiseEvent(&TransportManagerListener::OnDeviceAdded, web_engine_device_info_);
+ device_list_.push_back(
+ std::make_pair(web_socket_ta, web_engine_device_info_));
+ web_socket_ta->AddDevice(ws_device);
+#endif // WEBSOCKET_SERVER_TRANSPORT_SUPPORT
+}
+
+const DeviceInfo& TransportManagerImpl::GetWebEngineDeviceInfo() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return web_engine_device_info_;
+}
+
void TransportManagerImpl::UpdateDeviceList(TransportAdapter* ta) {
LOG4CXX_TRACE(logger_, "enter. TransportAdapter: " << ta);
std::set<DeviceInfo> old_devices;
@@ -856,9 +924,9 @@ void TransportManagerImpl::TryDeviceSwitch(
IOSBTAdapterFinder());
if (transport_adapters_.end() == ios_bt_adapter) {
- LOG4CXX_WARN(
- logger_,
- "There is no iAP2 Bluetooth adapter found. Switching is not possible.");
+ LOG4CXX_WARN(logger_,
+ "There is no iAP2 Bluetooth adapter found. Switching is not "
+ "possible.");
return;
}
diff --git a/src/components/transport_manager/src/websocket_server/websocket_connection.cc b/src/components/transport_manager/src/websocket_server/websocket_connection.cc
new file mode 100644
index 0000000000..7bcc4baef2
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_connection.cc
@@ -0,0 +1,218 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "transport_manager/websocket_server/websocket_connection.h"
+#include <unistd.h>
+#include "transport_manager/transport_adapter/transport_adapter_controller.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+CREATE_LOGGERPTR_GLOBAL(wsc_logger_, "WebSocketConnection")
+
+using namespace boost::beast::websocket;
+
+template <>
+WebSocketConnection<WebSocketSession<> >::WebSocketConnection(
+ const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ boost::asio::ip::tcp::socket socket,
+ TransportAdapterController* controller)
+ : device_uid_(device_uid)
+ , app_handle_(app_handle)
+ , session_(new WebSocketSession<>(
+ std::move(socket),
+ std::bind(
+ &WebSocketConnection::DataReceive, this, std::placeholders::_1),
+ std::bind(&WebSocketConnection::OnError, this)))
+ , controller_(controller)
+ , shutdown_(false)
+ , thread_delegate_(new LoopThreadDelegate(
+ &message_queue_,
+ std::bind(&WebSocketSession<>::WriteDown,
+ session_.get(),
+ std::placeholders::_1),
+ std::bind(&WebSocketConnection::OnError, this)))
+ , thread_(threads::CreateThread("WS Async Send", thread_delegate_)) {
+ thread_->start(threads::ThreadOptions());
+}
+
+#ifdef ENABLE_SECURITY
+template <>
+WebSocketConnection<WebSocketSecureSession<> >::WebSocketConnection(
+ const DeviceUID& device_uid,
+ const ApplicationHandle& app_handle,
+ boost::asio::ip::tcp::socket socket,
+ ssl::context& ctx,
+ TransportAdapterController* controller)
+ : device_uid_(device_uid)
+ , app_handle_(app_handle)
+ , session_(new WebSocketSecureSession<>(
+ std::move(socket),
+ ctx,
+ std::bind(
+ &WebSocketConnection::DataReceive, this, std::placeholders::_1),
+ std::bind(&WebSocketConnection::OnError, this)))
+ , controller_(controller)
+ , shutdown_(false)
+ , thread_delegate_(new LoopThreadDelegate(
+ &message_queue_,
+ std::bind(&WebSocketSecureSession<>::WriteDown,
+ session_.get(),
+ std::placeholders::_1),
+ std::bind(&WebSocketConnection::OnError, this)))
+ , thread_(threads::CreateThread("WS Async Send", thread_delegate_)) {
+ thread_->start(threads::ThreadOptions());
+}
+template class WebSocketConnection<WebSocketSecureSession<> >;
+#endif // ENABLE_SECURITY
+
+template <typename Session>
+WebSocketConnection<Session>::~WebSocketConnection() {
+ if (!IsShuttingDown()) {
+ Shutdown();
+ }
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::OnError() {
+ LOG4CXX_AUTO_TRACE(wsc_logger_);
+
+ controller_->ConnectionAborted(
+ device_uid_, app_handle_, CommunicationError());
+
+ session_->Shutdown();
+}
+
+template <typename Session>
+TransportAdapter::Error WebSocketConnection<Session>::Disconnect() {
+ LOG4CXX_AUTO_TRACE(wsc_logger_);
+ if (!IsShuttingDown()) {
+ Shutdown();
+ controller_->DisconnectDone(device_uid_, app_handle_);
+ return TransportAdapter::OK;
+ }
+ return TransportAdapter::BAD_STATE;
+}
+
+template <typename Session>
+TransportAdapter::Error WebSocketConnection<Session>::SendData(
+ ::protocol_handler::RawMessagePtr message) {
+ if (IsShuttingDown()) {
+ return TransportAdapter::BAD_STATE;
+ }
+
+ message_queue_.push(message);
+
+ return TransportAdapter::OK;
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::DataReceive(
+ protocol_handler::RawMessagePtr frame) {
+ controller_->DataReceiveDone(device_uid_, app_handle_, frame);
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::Run() {
+ LOG4CXX_AUTO_TRACE(wsc_logger_);
+ session_->AsyncAccept();
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::Shutdown() {
+ LOG4CXX_AUTO_TRACE(wsc_logger_);
+ shutdown_ = true;
+ if (thread_delegate_) {
+ session_->Shutdown();
+ thread_delegate_->SetShutdown();
+ thread_->join();
+ delete thread_delegate_;
+ thread_delegate_ = nullptr;
+ threads::DeleteThread(thread_);
+ thread_ = nullptr;
+ }
+}
+
+template <typename Session>
+bool WebSocketConnection<Session>::IsShuttingDown() {
+ return shutdown_;
+}
+
+template <typename Session>
+WebSocketConnection<Session>::LoopThreadDelegate::LoopThreadDelegate(
+ MessageQueue<Message, AsyncQueue>* message_queue,
+ DataWriteCallback data_write,
+ OnIOErrorCallback on_io_error)
+ : message_queue_(*message_queue)
+ , data_write_(data_write)
+ , on_io_error_(on_io_error) {}
+
+template <typename Session>
+void WebSocketConnection<Session>::LoopThreadDelegate::threadMain() {
+ while (!message_queue_.IsShuttingDown()) {
+ DrainQueue();
+ message_queue_.wait();
+ }
+ DrainQueue();
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::LoopThreadDelegate::exitThreadMain() {
+ if (!message_queue_.IsShuttingDown()) {
+ message_queue_.Shutdown();
+ }
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::LoopThreadDelegate::DrainQueue() {
+ Message message_ptr;
+ while (!message_queue_.IsShuttingDown() && message_queue_.pop(message_ptr)) {
+ auto res = data_write_(message_ptr);
+ if (TransportAdapter::FAIL == res) {
+ LOG4CXX_WARN(wsc_logger_,
+ "Writing to websocket stream failed. Will now close "
+ "websocket connection.");
+ on_io_error_();
+ }
+ }
+}
+
+template <typename Session>
+void WebSocketConnection<Session>::LoopThreadDelegate::SetShutdown() {
+ if (!message_queue_.IsShuttingDown()) {
+ message_queue_.Shutdown();
+ }
+}
+
+template class WebSocketConnection<WebSocketSession<> >;
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/websocket_server/websocket_device.cc b/src/components/transport_manager/src/websocket_server/websocket_device.cc
new file mode 100644
index 0000000000..502daf349b
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_device.cc
@@ -0,0 +1,94 @@
+/*
+ *
+ * Copyright (c) 2020, Livio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "transport_manager/websocket_server/websocket_device.h"
+
+#include "utils/logger.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")
+
+WebSocketDevice::WebSocketDevice(const std::string& name,
+ const DeviceUID& unique_device_id)
+ : Device(name, unique_device_id)
+ , is_secure_connect_(false)
+ , protocol_(boost::asio::ip::tcp::v4()) {}
+
+bool WebSocketDevice::IsSameAs(const Device* other) const {
+ LOG4CXX_TRACE(logger_, "enter. device: " << other);
+
+ const WebSocketDevice* other_websocket_device =
+ dynamic_cast<const WebSocketDevice*>(other);
+
+ if (!other_websocket_device) {
+ return false;
+ }
+
+ if (GetHost() != other_websocket_device->GetHost()) {
+ return false;
+ }
+
+ if (GetPort() != other_websocket_device->GetPort()) {
+ return false;
+ }
+
+ if (GetTarget() != other_websocket_device->GetTarget()) {
+ return false;
+ }
+
+ return true;
+}
+
+ApplicationList WebSocketDevice::GetApplicationList() const {
+ return app_list_;
+}
+
+const std::string& WebSocketDevice::GetHost() const {
+ return host_;
+}
+
+const std::string& WebSocketDevice::GetPort() const {
+ return port_;
+}
+
+const std::string WebSocketDevice::GetTarget() const {
+ return host_ + port_ + name();
+}
+
+void WebSocketDevice::AddApplication(const ApplicationHandle& app_handle) {
+ app_list_.push_back(app_handle);
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/websocket_server/websocket_listener.cc b/src/components/transport_manager/src/websocket_server/websocket_listener.cc
new file mode 100644
index 0000000000..87fff3acbc
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_listener.cc
@@ -0,0 +1,299 @@
+#include "transport_manager/websocket_server/websocket_listener.h"
+#include "transport_manager/transport_adapter/transport_adapter_controller.h"
+#include "transport_manager/websocket_server/websocket_device.h"
+#include "utils/file_system.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+CREATE_LOGGERPTR_GLOBAL(logger_, "WebSocketListener")
+
+WebSocketListener::WebSocketListener(TransportAdapterController* controller,
+ const TransportManagerSettings& settings,
+ const int num_threads)
+ : controller_(controller)
+ , ioc_(num_threads)
+#ifdef ENABLE_SECURITY
+ , ctx_(ssl::context::sslv23)
+ , start_secure_(false)
+#endif // ENABLE_SECURITY
+ , acceptor_(ioc_)
+ , socket_(ioc_)
+ , io_pool_(new boost::asio::thread_pool(num_threads))
+ , num_threads_(num_threads)
+ , shutdown_(false)
+ , settings_(settings) {
+}
+
+WebSocketListener::~WebSocketListener() {
+ Terminate();
+}
+
+TransportAdapter::Error WebSocketListener::Init() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const auto old_shutdown_value = shutdown_.exchange(false);
+ if (old_shutdown_value) {
+ ioc_.restart();
+ io_pool_.reset(new boost::asio::thread_pool(num_threads_));
+ }
+ return StartListening();
+}
+
+void WebSocketListener::Terminate() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ Shutdown();
+}
+
+TransportAdapter::Error WebSocketListener::StartListening() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (acceptor_.is_open()) {
+ return TransportAdapter::OK;
+ }
+
+#ifdef ENABLE_SECURITY
+ auto const ta_error = AddCertificateAuthority();
+ if (TransportAdapter::OK != ta_error) {
+ return ta_error;
+ }
+#endif
+
+ auto const address =
+ boost::asio::ip::make_address(settings_.websocket_server_address());
+ tcp::endpoint endpoint = {address, settings_.websocket_server_port()};
+
+ // Open the acceptor
+ boost::system::error_code ec;
+ acceptor_.open(endpoint.protocol(), ec);
+ if (ec) {
+ auto str_err = "ErrorOpen: " + ec.message();
+ LOG4CXX_ERROR(logger_,
+ str_err << " host/port: " << endpoint.address().to_string()
+ << "/" << endpoint.port());
+ return TransportAdapter::FAIL;
+ }
+
+ acceptor_.set_option(boost::asio::socket_base::reuse_address(true), ec);
+ if (ec) {
+ std::string str_err = "ErrorSetOption: " + ec.message();
+ LOG4CXX_ERROR(logger_,
+ str_err << " host/port: " << endpoint.address().to_string()
+ << "/" << endpoint.port());
+ return TransportAdapter::FAIL;
+ }
+
+ // Bind to the server address
+ acceptor_.bind(endpoint, ec);
+ if (ec) {
+ std::string str_err = "ErrorBind: " + ec.message();
+ LOG4CXX_ERROR(logger_,
+ str_err << " host/port: " << endpoint.address().to_string()
+ << "/" << endpoint.port());
+ return TransportAdapter::FAIL;
+ }
+
+ // Start listening for connections
+ acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
+ if (ec) {
+ std::string str_err = "ErrorListen: " + ec.message();
+ LOG4CXX_ERROR(logger_,
+ str_err << " host/port: " << endpoint.address().to_string()
+ << "/" << endpoint.port());
+ return TransportAdapter::FAIL;
+ }
+
+ if (false == Run()) {
+ return TransportAdapter::FAIL;
+ }
+
+ return TransportAdapter::OK;
+}
+
+#ifdef ENABLE_SECURITY
+TransportAdapter::Error WebSocketListener::AddCertificateAuthority() {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ const auto cert_path = settings_.ws_server_cert_path();
+ LOG4CXX_DEBUG(logger_, "Path to certificate : " << cert_path);
+ const auto key_path = settings_.ws_server_key_path();
+ LOG4CXX_DEBUG(logger_, "Path to key : " << key_path);
+ const auto ca_cert_path = settings_.ws_server_ca_cert_path();
+ LOG4CXX_DEBUG(logger_, "Path to ca cert : " << ca_cert_path);
+ start_secure_ = settings_.wss_server_supported();
+
+ if (start_secure_ && (!file_system::FileExists(cert_path) ||
+ !file_system::FileExists(key_path) ||
+ !file_system::FileExists(ca_cert_path))) {
+ LOG4CXX_ERROR(logger_, "Certificate or key file not found");
+ return TransportAdapter::FAIL;
+ }
+
+ if (!start_secure_) {
+ auto check_config = [](const std::string& config,
+ const std::string config_name) {
+ bool start_unsecure = config.empty();
+ if (!start_unsecure) {
+ LOG4CXX_ERROR(logger_,
+ "Configuration for secure WS is incomplete. "
+ << config_name
+ << " config is "
+ "present, meanwhile others may be missing. Please "
+ "check INI file");
+ }
+ return start_unsecure;
+ };
+ if (!check_config(cert_path, "Server cert") ||
+ !check_config(key_path, "Server key") ||
+ !check_config(ca_cert_path, "CA cert")) {
+ return TransportAdapter::FAIL;
+ }
+ } else {
+ LOG4CXX_INFO(logger_, "WebSocket server will start secure connection");
+ ctx_.add_verify_path(cert_path);
+ ctx_.set_options(boost::asio::ssl::context::default_workarounds);
+ using context = boost::asio::ssl::context_base;
+ ctx_.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert);
+ boost::system::error_code sec_ec;
+ ctx_.use_certificate_chain_file(cert_path, sec_ec);
+ ctx_.load_verify_file(ca_cert_path);
+ if (sec_ec) {
+ LOG4CXX_ERROR(
+ logger_,
+ "Loading WS server certificate failed: " << sec_ec.message());
+ return TransportAdapter::FAIL;
+ }
+ sec_ec.clear();
+ ctx_.use_private_key_file(key_path, context::pem, sec_ec);
+ if (sec_ec) {
+ LOG4CXX_ERROR(logger_,
+ "Loading WS server key failed: " << sec_ec.message());
+ return TransportAdapter::FAIL;
+ }
+ }
+
+ return TransportAdapter::OK;
+}
+#endif // ENABLE_SECURITY
+
+bool WebSocketListener::Run() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const bool is_connection_open = WaitForConnection();
+ if (is_connection_open) {
+ boost::asio::post(*io_pool_.get(), [&]() { ioc_.run(); });
+ } else {
+ LOG4CXX_ERROR(logger_, "Connection is shutdown or acceptor isn't open");
+ }
+
+ return is_connection_open;
+}
+
+bool WebSocketListener::WaitForConnection() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (!shutdown_ && acceptor_.is_open()) {
+ acceptor_.async_accept(
+ socket_,
+ std::bind(
+ &WebSocketListener::StartSession, this, std::placeholders::_1));
+ return true;
+ }
+ return false;
+}
+
+template <>
+void WebSocketListener::ProcessConnection(
+ std::shared_ptr<WebSocketConnection<WebSocketSession<> > > connection,
+ const DeviceSptr device,
+ const ApplicationHandle app_handle) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ controller_->ConnectionCreated(
+ connection, device->unique_device_id(), app_handle);
+
+ controller_->ConnectDone(device->unique_device_id(), app_handle);
+
+ connection->Run();
+
+ connection_list_lock.Acquire();
+ connection_list_.push_back(connection);
+ connection_list_lock.Release();
+
+ WaitForConnection();
+}
+
+#ifdef ENABLE_SECURITY
+template <>
+void WebSocketListener::ProcessConnection(
+ std::shared_ptr<WebSocketConnection<WebSocketSecureSession<> > > connection,
+ const DeviceSptr device,
+ const ApplicationHandle app_handle) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ controller_->ConnectionCreated(
+ connection, device->unique_device_id(), app_handle);
+
+ controller_->ConnectDone(device->unique_device_id(), app_handle);
+
+ connection->Run();
+
+ connection_list_lock.Acquire();
+ connection_list_.push_back(connection);
+ connection_list_lock.Release();
+
+ WaitForConnection();
+}
+#endif // ENABLE_SECURITY
+
+void WebSocketListener::StartSession(boost::system::error_code ec) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (ec) {
+ std::string str_err = "ErrorAccept: " + ec.message();
+ LOG4CXX_ERROR(logger_, str_err);
+ return;
+ }
+
+ if (shutdown_) {
+ return;
+ }
+
+ const ApplicationHandle app_handle = socket_.native_handle();
+
+ std::shared_ptr<WebSocketDevice> device =
+ std::static_pointer_cast<WebSocketDevice>(
+ controller_->GetWebEngineDevice());
+
+ LOG4CXX_INFO(logger_, "Connected client: " << app_handle);
+
+#ifdef ENABLE_SECURITY
+ if (start_secure_) {
+ auto connection =
+ std::make_shared<WebSocketConnection<WebSocketSecureSession<> > >(
+ device->unique_device_id(),
+ app_handle,
+ std::move(socket_),
+ ctx_,
+ controller_);
+ ProcessConnection(connection, device, app_handle);
+ return;
+ }
+#endif // ENABLE_SECURITY
+
+ auto connection = std::make_shared<WebSocketConnection<WebSocketSession<> > >(
+ device->unique_device_id(), app_handle, std::move(socket_), controller_);
+ ProcessConnection(connection, device, app_handle);
+}
+
+void WebSocketListener::Shutdown() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (false == shutdown_.exchange(true)) {
+ ioc_.stop();
+ socket_.close();
+ boost::system::error_code ec;
+ acceptor_.close(ec);
+
+ if (ec) {
+ LOG4CXX_ERROR(logger_, "Acceptor closed with error: " << ec);
+ }
+
+ io_pool_->stop();
+ io_pool_->join();
+ }
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc b/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc
new file mode 100644
index 0000000000..9be94119b6
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_secure_session.cc
@@ -0,0 +1,79 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "transport_manager/websocket_server/websocket_secure_session.h"
+#include <unistd.h>
+#include "transport_manager/transport_adapter/transport_adapter_controller.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+using namespace boost::beast::websocket;
+
+template <typename ExecutorType>
+WebSocketSecureSession<ExecutorType>::WebSocketSecureSession(
+ tcp::socket socket,
+ ssl::context& ctx,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_error)
+ : WebSocketSession<ExecutorType>(
+ std::move(socket), ctx, data_receive, on_error) {}
+
+template <typename ExecutorType>
+void WebSocketSecureSession<ExecutorType>::AsyncAccept() {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ // Perform the SSL handshake
+ WebSocketSecureSession<ExecutorType>::ws_.next_layer().async_handshake(
+ ssl::stream_base::server,
+ boost::asio::bind_executor(
+ WebSocketSecureSession<ExecutorType>::strand_,
+ std::bind(&WebSocketSecureSession::AsyncHandshake,
+ this->shared_from_this(),
+ std::placeholders::_1)));
+}
+
+template <typename ExecutorType>
+void WebSocketSecureSession<ExecutorType>::AsyncHandshake(
+ boost::system::error_code ec) {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ if (ec) {
+ auto str_err = "ErrorMessage: " + ec.message();
+ LOG4CXX_ERROR(ws_logger_, str_err);
+ WebSocketSession<ExecutorType>::on_io_error_();
+ return;
+ }
+
+ WebSocketSession<ExecutorType>::AsyncAccept();
+}
+
+template class WebSocketSecureSession<ssl::stream<tcp::socket&> >;
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/websocket_server/websocket_server_transport_adapter.cc b/src/components/transport_manager/src/websocket_server/websocket_server_transport_adapter.cc
new file mode 100644
index 0000000000..ac8789eee8
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_server_transport_adapter.cc
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "transport_manager/websocket_server/websocket_server_transport_adapter.h"
+
+#include <errno.h>
+#include <memory.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <cstdlib>
+#include <sstream>
+
+#include "transport_manager/websocket_server/websocket_listener.h"
+#include "utils/gen_hash.h"
+#include "utils/logger.h"
+#include "utils/threads/thread_delegate.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "WebSocketTransportAdapter")
+
+WebSocketServerTransportAdapter::WebSocketServerTransportAdapter(
+ resumption::LastStateWrapperPtr last_state_wrapper,
+ const TransportManagerSettings& settings)
+ : TransportAdapterImpl(nullptr,
+ nullptr,
+ new WebSocketListener(this, settings),
+ last_state_wrapper,
+ settings) {}
+
+WebSocketServerTransportAdapter::~WebSocketServerTransportAdapter() {}
+
+void WebSocketServerTransportAdapter::TransportConfigUpdated(
+ const TransportConfig& new_config) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ transport_config_ = new_config;
+
+ // call the method of parent class to trigger OnTransportConfigUpdated() for
+ // the listeners
+ TransportAdapterImpl::TransportConfigUpdated(new_config);
+}
+
+TransportConfig WebSocketServerTransportAdapter::GetTransportConfiguration()
+ const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return transport_config_;
+}
+
+DeviceType WebSocketServerTransportAdapter::GetDeviceType() const {
+ return WEBENGINE_WEBSOCKET;
+}
+
+DeviceSptr WebSocketServerTransportAdapter::AddDevice(DeviceSptr device) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ webengine_device_ = device;
+ Store();
+ return TransportAdapterImpl::AddDevice(webengine_device_);
+}
+
+TransportAdapter::Error WebSocketServerTransportAdapter::Init() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (webengine_device_) {
+ AddDevice(webengine_device_);
+ }
+ return TransportAdapterImpl::Init();
+}
+
+void WebSocketServerTransportAdapter::Store() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ if (webengine_device_) {
+ Json::Value& dictionary = last_state().get_dictionary();
+ if (dictionary["TransportManager"].isMember("WebsocketServerAdapter")) {
+ LOG4CXX_DEBUG(
+ logger_, "WebsocketServerAdapter already exists. Storing is skipped");
+ return;
+ }
+
+ Json::Value device_dictionary;
+ device_dictionary["unique_id"] = webengine_device_->unique_device_id();
+
+ Json::Value ws_adapter_dictionary;
+ ws_adapter_dictionary["device"] = device_dictionary;
+ dictionary["TransportManager"]["WebsocketServerAdapter"] =
+ ws_adapter_dictionary;
+ }
+}
+
+bool WebSocketServerTransportAdapter::Restore() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ const Json::Value& dictionary = last_state().get_dictionary();
+ const Json::Value ws_adapter_dictionary =
+ dictionary["TransportManager"]["WebsocketServerAdapter"];
+ webengine_device_id_ =
+ ws_adapter_dictionary["device"]["unique_id"].asString();
+ if (webengine_device_id_.empty()) {
+ srand(time(0));
+ const size_t device_id_length = 64u;
+ webengine_device_id_ = utils::gen_hash(device_id_length);
+ }
+ return true;
+}
+
+std::string WebSocketServerTransportAdapter::GetStoredDeviceID() const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ return webengine_device_id_;
+}
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/src/websocket_server/websocket_session.cc b/src/components/transport_manager/src/websocket_server/websocket_session.cc
new file mode 100644
index 0000000000..ab62530963
--- /dev/null
+++ b/src/components/transport_manager/src/websocket_server/websocket_session.cc
@@ -0,0 +1,162 @@
+/*
+Copyright (c) 2020 Livio, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of SmartDeviceLink Consortium, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "transport_manager/websocket_server/websocket_session.h"
+#include <unistd.h>
+#include "transport_manager/transport_adapter/transport_adapter_controller.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+using namespace boost::beast::websocket;
+
+template <>
+WebSocketSession<tcp::socket&>::WebSocketSession(
+ boost::asio::ip::tcp::socket socket,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_error)
+ : socket_(std::move(socket))
+ , ws_(socket_)
+ , strand_(ws_.get_executor())
+ , data_receive_(data_receive)
+ , on_io_error_(on_error) {
+ ws_.binary(true);
+}
+
+#ifdef ENABLE_SECURITY
+template <>
+WebSocketSession<ssl::stream<tcp::socket&> >::WebSocketSession(
+ boost::asio::ip::tcp::socket socket,
+ ssl::context& ctx,
+ DataReceiveCallback data_receive,
+ OnIOErrorCallback on_error)
+ : socket_(std::move(socket))
+ , ws_(socket_, ctx)
+ , strand_(ws_.get_executor())
+ , data_receive_(data_receive)
+ , on_io_error_(on_error) {
+ ws_.binary(true);
+}
+template class WebSocketSession<ssl::stream<tcp::socket&> >;
+#endif // ENABLE_SECURITY
+
+template <typename ExecutorType>
+WebSocketSession<ExecutorType>::~WebSocketSession() {}
+
+template <typename ExecutorType>
+void WebSocketSession<ExecutorType>::AsyncAccept() {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ ws_.async_accept(
+ boost::asio::bind_executor(strand_,
+ std::bind(&WebSocketSession::AsyncRead,
+ this->shared_from_this(),
+ std::placeholders::_1)));
+}
+
+template <typename ExecutorType>
+void WebSocketSession<ExecutorType>::AsyncRead(boost::system::error_code ec) {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ if (ec) {
+ auto str_err = "ErrorMessage: " + ec.message();
+ LOG4CXX_ERROR(ws_logger_, str_err);
+ return;
+ }
+
+ ws_.async_read(buffer_,
+ boost::asio::bind_executor(strand_,
+ std::bind(&WebSocketSession::Read,
+ this->shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2)));
+}
+
+template <typename ExecutorType>
+TransportAdapter::Error WebSocketSession<ExecutorType>::WriteDown(
+ ::protocol_handler::RawMessagePtr message) {
+ boost::system::error_code ec;
+ ws_.write(boost::asio::buffer(message->data(), message->data_size()), ec);
+
+ if (ec) {
+ LOG4CXX_ERROR(ws_logger_, "A system error has occurred: " << ec.message());
+ return TransportAdapter::FAIL;
+ }
+
+ return TransportAdapter::OK;
+}
+
+template <typename ExecutorType>
+void WebSocketSession<ExecutorType>::Read(boost::system::error_code ec,
+ std::size_t bytes_transferred) {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ boost::ignore_unused(bytes_transferred);
+ if (ec) {
+ LOG4CXX_ERROR(ws_logger_, ec.message());
+ buffer_.consume(buffer_.size());
+ on_io_error_();
+ return;
+ }
+
+ auto size = buffer_.size();
+ const auto data = boost::asio::buffer_cast<const uint8_t*>(
+ boost::beast::buffers_front(buffer_.data()));
+
+ LOG4CXX_DEBUG(ws_logger_,
+ "Msg: " << boost::beast::buffers_to_string(buffer_.data())
+ << " Size: " << size;);
+
+ ::protocol_handler::RawMessagePtr frame(
+ new protocol_handler::RawMessage(0, 0, data, size, false));
+
+ data_receive_(frame);
+
+ buffer_.consume(buffer_.size());
+ AsyncRead(ec);
+}
+
+template <typename ExecutorType>
+bool WebSocketSession<ExecutorType>::Shutdown() {
+ LOG4CXX_AUTO_TRACE(ws_logger_);
+ boost::system::error_code ec;
+ if (socket_.is_open()) {
+ socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
+ socket_.close();
+ }
+ buffer_.consume(buffer_.size());
+ if (ec) {
+ LOG4CXX_ERROR(ws_logger_, ec.message());
+ return false;
+ }
+ return true;
+}
+
+template class WebSocketSession<tcp::socket&>;
+
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/test/CMakeLists.txt b/src/components/transport_manager/test/CMakeLists.txt
index f6e1212b36..76680b2fad 100644
--- a/src/components/transport_manager/test/CMakeLists.txt
+++ b/src/components/transport_manager/test/CMakeLists.txt
@@ -48,11 +48,18 @@ set(EXCLUDE_PATHS
if (NOT BUILD_CLOUD_APP_SUPPORT)
list(APPEND EXCLUDE_PATHS
- ${CMAKE_CURRENT_SOURCE_DIR}/websocket_connection_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/sample_websocket_server.cc
)
endif()
+if (NOT BUILD_WEBSOCKET_SERVER_SUPPORT)
+ list(APPEND EXCLUDE_PATHS
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_client_connection_test.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_connection_test.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/websocket_server_listener_test.cc
+ )
+endif()
+
collect_sources(SOURCES "${CMAKE_CURRENT_SOURCE_DIR}" "${EXCLUDE_PATHS}")
set(PLATFORM_DEPENDENT_SOURCES)
@@ -90,3 +97,4 @@ endif()
create_test("transport_manager_test" "${SOURCES}" "${LIBRARIES}")
file(COPY smartDeviceLink_test.ini DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+file(COPY "test_certs/" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test_certs)
diff --git a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
index 1de5eac702..7ddb84001c 100644
--- a/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
+++ b/src/components/transport_manager/test/include/transport_manager/transport_adapter/mock_transport_adapter_controller.h
@@ -45,56 +45,66 @@ using namespace ::transport_manager::transport_adapter;
class MockTransportAdapterController : public TransportAdapterController {
public:
MOCK_METHOD1(AddDevice, DeviceSptr(DeviceSptr device));
- MOCK_METHOD1(SearchDeviceDone, void(DeviceVector device));
+ MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& device));
MOCK_METHOD1(ApplicationListUpdated,
- ApplicationListUpdated(const DeviceUID& device_handle));
+ void(const transport_manager::DeviceUID& device_handle));
MOCK_METHOD0(FindNewApplicationsRequest, void());
- MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error));
- MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle));
- MOCK_CONST_METHOD3(FindDevice,
- void(ConnectionSPtr connection,
- const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_CONST_METHOD2(FindPendingConnection,
- ConnectionSPtr(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ MOCK_METHOD1(SearchDeviceFailed,
+ void(const transport_manager::SearchDeviceError& error));
+ MOCK_CONST_METHOD1(
+ FindDevice,
+ DeviceSptr(const transport_manager::DeviceUID& device_handle));
+ MOCK_CONST_METHOD2(
+ FindPendingConnection,
+ ConnectionSPtr(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
+ MOCK_METHOD3(ConnectionCreated,
+ void(ConnectionSPtr connection,
+ const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
+ MOCK_METHOD2(ConnectPending,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD2(ConnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(ConnectFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ConnectError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::ConnectError& error));
MOCK_METHOD2(ConnectionFinished,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(ConnectionAborted,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const CommunicationError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::CommunicationError& error));
MOCK_METHOD2(DeviceDisconnected,
- void(const DeviceUID& device_handle,
- const DisconnectDeviceError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::DisconnectDeviceError& error));
MOCK_METHOD2(DisconnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle));
MOCK_METHOD3(DataReceiveDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message));
MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const DataReceiveError& error));
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
+ const transport_manager::DataReceiveError& error));
MOCK_METHOD3(DataSendDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message));
- MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
+
+ MOCK_METHOD4(DataSendFailed,
+ void(const transport_manager::DeviceUID& device_handle,
+ const transport_manager::ApplicationHandle& app_handle,
::protocol_handler::RawMessagePtr message,
- const DataSendError& error));
+ const transport_manager::DataSendError&));
+ MOCK_METHOD1(TransportConfigUpdated, void(const TransportConfig& new_config));
+ MOCK_CONST_METHOD0(GetWebEngineDevice, DeviceSptr());
};
} // namespace transport_manager_test
diff --git a/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h b/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h
new file mode 100644
index 0000000000..138502e02c
--- /dev/null
+++ b/src/components/transport_manager/test/include/transport_manager/websocket_server/websocket_sample_client.h
@@ -0,0 +1,117 @@
+/*
+ * \file websocket_listener.h
+ * \brief WebSocketListener class header file.
+ *
+ * Copyright (c) 2020
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
+#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
+
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/connect.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/thread_pool.hpp>
+#include <boost/beast/core.hpp>
+#include <boost/beast/websocket.hpp>
+#include <boost/beast/websocket/ssl.hpp>
+#include <boost/beast/websocket/stream.hpp>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <string>
+
+namespace transport_manager {
+namespace transport_adapter {
+
+namespace beast = boost::beast;
+namespace http = beast::http;
+namespace websocket = beast::websocket;
+namespace asio = boost::asio;
+namespace ssl = boost::asio::ssl;
+using tcp = boost::asio::ip::tcp;
+
+using WS = websocket::stream<tcp::socket>;
+using WSS = websocket::stream<ssl::stream<tcp::socket> >;
+
+struct SecurityParams {
+ std::string ca_cert_;
+ std::string client_cert_;
+ std::string client_key_;
+};
+
+template <typename Stream = WS>
+class WSSampleClient
+ : public std::enable_shared_from_this<WSSampleClient<Stream> > {
+ public:
+ WSSampleClient(const std::string& host, const std::string& port);
+ WSSampleClient(const std::string& host,
+ const std::string& port,
+ const SecurityParams& params);
+ ~WSSampleClient() {}
+
+ /**
+ * @brief Inside a Run(), functions are invoked from the boost (connection,
+ * handshake, message) which are blocking calls
+ * @return true if Run() did without errors
+ **/
+ bool Run();
+
+ void OnRead(beast::error_code ec, std::size_t bytes_transferred);
+
+ bool Connect(tcp::resolver::results_type& results);
+
+ bool Handshake(const std::string& host, const std::string& target);
+
+ void OnHandshakeTimeout();
+
+ bool IsHandshakeSuccessful() const;
+
+ void Stop();
+
+ private:
+ asio::io_context ioc_;
+ tcp::resolver resolver_;
+ ssl::context ctx_;
+ std::unique_ptr<Stream> ws_;
+ boost::asio::thread_pool io_pool_;
+ beast::flat_buffer buffer_;
+ std::string host_;
+ std::string port_;
+ std::atomic_bool handshake_successful_;
+};
+
+} // namespace transport_adapter
+} // namespace transport_manager
+
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_WEBSOCKET_SERVER_WEBSOCKET_SAMPLE_CLIENT_
diff --git a/src/components/transport_manager/test/tcp_client_listener_test.cc b/src/components/transport_manager/test/tcp_client_listener_test.cc
index d524b3eb6a..dbd7799b62 100644
--- a/src/components/transport_manager/test/tcp_client_listener_test.cc
+++ b/src/components/transport_manager/test/tcp_client_listener_test.cc
@@ -42,6 +42,7 @@
#include "transport_manager/tcp/tcp_client_listener.h"
#include "transport_manager/transport_adapter/mock_device.h"
#include "transport_manager/transport_adapter/mock_transport_adapter.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
#include "transport_manager/transport_adapter/transport_adapter_controller.h"
#include "utils/test_async_waiter.h"
@@ -62,67 +63,6 @@ const long kThreadStartWaitMsec = 10;
const uint32_t kConnectionCreatedTimeoutMsec = 200;
} // namespace
-class MockTransportAdapterController : public TransportAdapterController {
- public:
- MOCK_METHOD1(AddDevice, DeviceSptr(DeviceSptr device));
- MOCK_METHOD0(AckDevices, void());
- MOCK_METHOD1(SearchDeviceDone, void(const DeviceVector& devices));
- MOCK_METHOD1(SearchDeviceFailed, void(const SearchDeviceError& error));
- MOCK_CONST_METHOD1(FindDevice, DeviceSptr(const DeviceUID& device_handle));
- MOCK_CONST_METHOD2(FindPendingConnection,
- ConnectionSPtr(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectionCreated,
- void(ConnectionSPtr connection,
- const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD2(ConnectPending,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD2(ConnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ConnectError& error));
- MOCK_METHOD2(ConnectionFinished,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(ConnectionAborted,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const CommunicationError& error));
- MOCK_METHOD2(DisconnectDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle));
- MOCK_METHOD3(DataReceiveDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message));
- MOCK_METHOD3(DataReceiveFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const DataReceiveError& error));
- MOCK_METHOD3(DataSendDone,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message));
- MOCK_METHOD4(DataSendFailed,
- void(const DeviceUID& device_handle,
- const ApplicationHandle& app_handle,
- const ::protocol_handler::RawMessagePtr message,
- const DataSendError& error));
- MOCK_METHOD0(FindNewApplicationsRequest, void());
- MOCK_METHOD1(ApplicationListUpdated, void(const DeviceUID& device_handle));
- MOCK_METHOD2(DeviceDisconnected,
- void(const DeviceUID& device_handle,
- const DisconnectDeviceError& error));
- MOCK_METHOD1(TransportConfigUpdated,
- void(const transport_manager::transport_adapter::TransportConfig&
- new_config));
-};
-
class MockNetworkInterfaceListener : public NetworkInterfaceListener {
public:
MOCK_METHOD0(Init, bool());
diff --git a/src/components/transport_manager/test/test_certs/ca-cert.pem b/src/components/transport_manager/test/test_certs/ca-cert.pem
new file mode 100644
index 0000000000..e28684043c
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/ca-cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDyzCCArOgAwIBAgIJAM6Tk4KJmUgsMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNV
+BAYTAlVBMQ8wDQYDVQQIDAZPZGVzc2ExDzANBgNVBAcMBk9kZXNzYTEPMA0GA1UE
+CgwGTHV4b2Z0MQ0wCwYDVQQLDARGVENOMQ8wDQYDVQQDDAZMdXgtQ0ExGjAYBgkq
+hkiG9w0BCQEWC2NhQGZ0Y24uY29tMB4XDTIwMDExMDE0MzA1OFoXDTIyMTAwNjE0
+MzA1OFowfDELMAkGA1UEBhMCVUExDzANBgNVBAgMBk9kZXNzYTEPMA0GA1UEBwwG
+T2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTALBgNVBAsMBEZUQ04xDzANBgNVBAMM
+Bkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FAZnRjbi5jb20wggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDWEz7yGIAEs6w/7CdMjkZ5J0O9IghL0f9wZVFO
+ficeREJglClInPrD7BwG7MG1tydPULbrf1rXgxi1NdDY+lsJLFmkxrGVlgJUJl55
+cGpWGliTUepfPz/6CgIabRw2fEMx/eIUlcE+WjY+f4uowVyRYjmNj7IydlQ5UjcL
+wWhjg1QMcjgmDzh8Jdx8I+JHYuOP9CtEEfFZy5DjVPFDSlTYhhnNclfw+4NkOYcs
+hp+EcMBr6egfxpG2dZbdCJtGw6QqHGG7kqqtLr+9wM5VFhuvebus5waM1G18dIME
+SgZmDdgvHO3bbylR+DRmAjJVn4DaDW6uszK9MSPsk53idOUXAgMBAAGjUDBOMB0G
+A1UdDgQWBBSSRwc4sGpz6V1kb0H371ZqhDuQDzAfBgNVHSMEGDAWgBSSRwc4sGpz
+6V1kb0H371ZqhDuQDzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCb
+ZYtM2nrokFL1D34bhozrLu0MxWwDF+gQrUsRr45s63Y5Pv7BVvuS6gF2MubMXskw
+mVeCerFw2vQHJKqe7leTy69hwIydPxPQWWno7MamwBDm3VQThr+b18rEpcjbmBMm
+p50usYzU9nxEEbIaiSbxfuZNvInLNmvMhKnKO/CIazJnYin9TGdOj9vZnh0UkWF3
+780mMBisycfxG+VwPXQZz5OzWWFB1uMiYrRVdwU6Y5umc2Oce7+ykWy+fXeefMhb
+lLJXHZK584qY/krmW0Ec6ZWSbiWcLW5SjGh756n05gBGLDBwijHnfEHNaqn+KlnZ
+qqIAImNTA9F+DlMQ7BV3
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/client-cert.pem b/src/components/transport_manager/test/test_certs/client-cert.pem
new file mode 100644
index 0000000000..47e85876c8
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/client-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDeDCCAmACAQIwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVUExDzANBgNV
+BAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTAL
+BgNVBAsMBEZUQ04xDzANBgNVBAMMBkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FA
+ZnRjbi5jb20wHhcNMjAwMTEwMTQzODQxWhcNMjIxMDA2MTQzODQxWjCBhzELMAkG
+A1UEBhMCVUExDTALBgNVBAgMBEt5aXYxDTALBgNVBAcMBEt5aXYxDzANBgNVBAoM
+Bkx1eG9mdDEVMBMGA1UECwwMQXBwc0VueXdoZXJlMRIwEAYDVQQDDAlsb2NhbGhv
+c3QxHjAcBgkqhkiG9w0BCQEWD2NsaWVudEBmdGNuLmNvbTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALV4qI/gRvVip3u5JtT+n+7j7gUsUVW5DtwHruIy
+drzNvQbG1Ukd3EXvU69HTG4BtoDRubqlSe/sjvO5Ypmg/UvpzV36IbjrA46s98uR
+T6fKpJU/Zl2zwAHH++iWpFo3mqIDmu7i0KVBieKaGpz+Ft0zh7wHAztS7b6Mjns4
+QynpjDO+iaLIaHqBjc1hLn8dIBXNolOtLu8F8CL7RLRpWP2I2Fk2k0+Q5YKajbil
+gptA53Uu55wCBVLTOfUYzTarGwS00+7txLY06g2x20FHD8UQxfCK7kSAeZwSNkbt
+SUhXc9OWUvT1uggb2/wBHJN3fwj7y6pvzUJy7p09212hw7UCAwEAATANBgkqhkiG
+9w0BAQsFAAOCAQEAjfASZwfJMTPKk45XVbvuNqdlbiI20SNV7pQQ/FqTBKbFmh4g
+ndNCvECmBEUH5YdZegiGaONQlsQujmtIkguu3HnA0+2pO2SncmK6D1DLzJv1IFDC
+25tTStA6806hWcTK31sxEbi5/aPdy7FMmsRfyhRr/yew0TqlWCVOfJRwgDSc3NKH
+/AXgDBrqHzSBegnWe9v3xL8NxehFp41dJG2fyUab03cHzmNtR9v7/NrBglSdK9VS
+AU4BCmjmvYlbvmvhZai23y+uLqzlWZ9OtK3qhEWkg6QHor11iBvxBQFeYKp1ZjMl
+sQuTxyBLmXOZ/u3hkqLcKvasx9W4DmmPjG2T8Q==
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/client-key.pem b/src/components/transport_manager/test/test_certs/client-key.pem
new file mode 100644
index 0000000000..b286854bd5
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/client-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1eKiP4Eb1Yqd7
+uSbU/p/u4+4FLFFVuQ7cB67iMna8zb0GxtVJHdxF71OvR0xuAbaA0bm6pUnv7I7z
+uWKZoP1L6c1d+iG46wOOrPfLkU+nyqSVP2Zds8ABx/volqRaN5qiA5ru4tClQYni
+mhqc/hbdM4e8BwM7Uu2+jI57OEMp6YwzvomiyGh6gY3NYS5/HSAVzaJTrS7vBfAi
++0S0aVj9iNhZNpNPkOWCmo24pYKbQOd1LuecAgVS0zn1GM02qxsEtNPu7cS2NOoN
+sdtBRw/FEMXwiu5EgHmcEjZG7UlIV3PTllL09boIG9v8ARyTd38I+8uqb81Ccu6d
+PdtdocO1AgMBAAECggEALiPCf+pfQE7YFJ4L4IXo9h1fzFLrTydhPtJ5RavdAr4w
+vINbgV6lPebO2TcAmMu4smIgnfMerHDyG8fb6QHExUNp4uYRIuomGmWiD1Ef9qKQ
+XB4lkdd9Dzbgts9udD3FBEJ0Zx6mPA5A16uk7puwBofukAEccj3wks08ANpaQVJh
+LoYQdVY9Q2QHUucED9uO2hOv66bDM5aunk0x4Q/b0gIOAnJyqk0xXnmnU76FbkgI
+bU3YQ73ZEJKTFLF8B2JaE9REASmHyLQChYqGA9SPdObVhgxJ8gz5AWp5yHgMmYjf
+Dp66tCsyGnmfgTlG4Wi13HInxLpRWDWT2JWIy9cUlQKBgQDshRq/rTj4tuVW09hX
+bWlAEV2IDn7JOWEZqPagnxew0atqow44VORW+OoUZ5760aOVjvmXeyGXpWCJk5ch
+qsFRL9rLRzIy9oC6C/chkJQAprcaOBOSXvj3HnFHVChjbIBENf4dvtsYZHOW42h2
+br0kszv1bbBzVIyTTY0OvGsBUwKBgQDEauIuC6RiDN+qFAf4/lHkUx7wG6DPhvDm
+EhpkiVEHYVjH5vm132/cc12y9CvsFS4MJPK4KQR9P+HFhEu/uH3uLa1vvKY+69iU
+dZ1bfe4UrEm/bwBepDSbqlQk58WC6NyJ6fwMq0BYJVvx593znEbU2wLVUTm8H7l2
+yzyxQwXd1wKBgBkYvo/cJ5FshsVB0VDlkSd1MEGBmD5t0jnQzeqZNwBSHyg/iQC9
+MUVxQBVOMXZXzE3QT/ec3yGiMK4odP7jiYO92i97rH3v3hTftCdhmfK/veoQTTNY
+1H4UQtzYtzhliO6z8/TgDYt3DTTTiIAYnAVK52/RZcm3DPuMXQ1VPN11AoGBAIN5
+eASSTmpDa8OQvPVyZqaK7P6Tv8Sp8r5OB9ScBd0G0EKe3S9cbKgHoQSUZIIWe0gt
+wzp6WkLsa9emgn3GpKS1do6AnFcpz0MwpzACz0aPPJ4jUwAGsiAwlzpM2eySqmy2
+brycNOnLuAvoxKy4QsFgCDl5sUe3hJF74RhWYKrpAoGAUrJMF5IaAAsv367nD8CX
+CfDsDlez54H/sZD7iKj8LhyuspAQBU3vQ3xKfaKRi4px8bgnty3stOMZxEC7I6BC
+jHH1hQK8l9nqRhOjPvoViUM6aOpabCkVsOZjWKD+OCz3X9+MmlGkMuNd22GRdwlb
+Emb3yEoFr5vDbez0IQNxnLs=
+-----END PRIVATE KEY-----
diff --git a/src/components/transport_manager/test/test_certs/invalid_cert.pem b/src/components/transport_manager/test/test_certs/invalid_cert.pem
new file mode 100644
index 0000000000..70d124c2b7
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/invalid_cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnwCCQDIe7AwFpWRlDANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMC
+UlUxEzARBgNVBAgMClNvbWUtU3RhdGUxGTAXBgNVBAcMEFNhaW50LVBldGVyc2J1
+cmcxDzANBgNVBAoMBkx1eG9mdDEXMBUGA1UEAwwORG1pdHJ5IENobWVyZXYxIjAg
+BgkqhkiG9w0BCQEWE2RjaG1lcmV2QGx1eG9mdC5jb20wHhcNMTQwMjI1MDkxODUz
+WhcNMTYxMTIyMDkxODUzWjCBizELMAkGA1UEBhMCUlUxEzARBgNVBAgMClNvbWUt
+U3RhdGUxGTAXBgNVBAcMEFNhaW50LVBldGVyc2J1cmcxDzANBgNVBAoMBkx1eG9m
+dDEXMBUGA1UEAwwORG1pdHJ5IENobWVyZXYxIjAgBgkqhkiG9w0BCQEWE2RjaG1l
+cmV2QGx1eG9mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCn
+Mu9wNmXKaKOnefSv5iT8G2ESLjq+eYlxys/XAnDfkmnlgGYAcPno+XMhRj/lNV/c
+3A0L/R4631GFJA8vaM8m9Bn47FrPP4AXIHEQh9acA4qXiLfhhA8+9PPt4xVkjQYj
+bmexBLqDvRgT3MJwwFecUn/UABBlVZRCspn+6DkjiodbgmBOqyi1p0ng8BFeUbEH
++fLQVILCX3pjnMiP2bBtvq/7njgZT2luVtAAcOdRwRTuZT0YbgaXrHYsOa6VYDl1
+I0uOcdD8qENBXtBnykEqH+jZtKu6Rej1DsGOYWqz3AAaGiR1GJauNBxh+4v+i/eB
+0aCIA8T8qUqyuVVg48S/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBACliraOJYijK
+yS+Sl6S6pFRqdF/evPdYF6zDJlM3P+/9qHoEy751vbBTzRkVbC/azyiZLwQMuyED
+6oCpkI7MqnrRip1ZelGx9K7ChaHOpX/QRN+3eqiDhzvMTGd2nPJf9np4xi8SJpGP
+UUROYI5fToIY5MaOKuOIR2a6c8xIuLWMG1XKJxXrRetLJZDgBqQPkuqaZIjYCY+q
+HQRjNUFNX4Mc453tKd90gFLGI3fxs1fJDIRSGfKJsj0qc+amSz4Sgiz4QUBcUQKd
+hJxUpStYhliZGZchEopLsShtIGfKKFaaPCIOTpVAwSr1oIDm9lpkdxeuQfedKT5f
+ZZmkez2pAF8=
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/invalid_key.pem b/src/components/transport_manager/test/test_certs/invalid_key.pem
new file mode 100644
index 0000000000..d2aacc1638
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/invalid_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEApzLvcDZlymijp3n0r+Yk/BthEi46vnmJccrP1wJw35Jp5YBm
+AHD56PlzIUY/5TVf3NwNC/0eOt9RhSQPL2jPJvQZ+Oxazz+AFyBxEIfWnAOKl4i3
+4YQPPvTz7eMVZI0GI25nsQS6g70YE9zCcMBXnFJ/1AAQZVWUQrKZ/ug5I4qHW4Jg
+TqsotadJ4PARXlGxB/ny0FSCwl96Y5zIj9mwbb6v+544GU9pblbQAHDnUcEU7mU9
+GG4Gl6x2LDmulWA5dSNLjnHQ/KhDQV7QZ8pBKh/o2bSrukXo9Q7BjmFqs9wAGhok
+dRiWrjQcYfuL/ov3gdGgiAPE/KlKsrlVYOPEvwIDAQABAoIBAQCAjkNXzhuZ87bR
+UI34qUYKqaqLZgw45A3v9naz5OaQoGzXz0+eSz98CECjdvYt8EoS8Qb/DtGthoOR
+kVYzp6yPUOSfZmu0Kij8ny8P/MHgF0D6nl50ASwPxhu/7vhF5cCwgXUswGwAWuYm
+b3j5ZIp4YV5zzNDOeWyTk+uf+UHltqFD7Ae4M9z58r17/OWhva5mtusTuuEYjzC6
+AE/fsOC0gLNSM4+SfclfCkHpH+GikzNMSQ2H0hlXllPmR73BoC6N6aoY5hQWBLV7
+LxtYbJqx7TAqRyypBQekjJe36roRetXtzy3i6V/y69045td5kk70cVjmFhl79475
+82rnRLHBAoGBANgq4axr5OotTUmPkGd0afoaWSRPJfiTTdNeMkqTzM6zIcVLSKhB
+78ERwdDD9FOu+Bgivg4DlpmH7ArWn8QNDtdkhmPfKYfTqX6qH7AK4cybvYICMlct
+EdW4TvKm/ZB3mrVOP9JVPjdyFMp+Je6N+qp1w+ui9mxX8pWnrC/+DfTvAoGBAMYC
+GFjnw/O9hjF2Mb00qUarmM+reJZMXv/pVik+cm0eAiYvgGvKbAYkIXwdb7rLBw9k
+baJmxP0PrAoXy5TpPdfROqPwrRCyReKymKkEZeTpONgD0s8MbX167ovZu1OQVKQo
+IyJeUzWa0kpglnbL2lLVu49x8jWHDJdYhmkDNE0xAoGAR4ux07qGMoe5693rYoJi
+TRgJZv4XSDWg7ZNgu9Q9VjBtvfoT2zSvoMw6xNkGdegUTxC4rLS9VKVrF48/o8ja
+n6my3T1QZpdEoxq1kDOZ1nm5eF03wii1nXH6F0/z3qvndZingPsbs4g7n2WvMkyl
+qWN+6++s9eEJ9kRftia1AdsCgYAUnU05nE97RcT9y0dcYmopMF5FaJ2yUBsn23wb
+6SNylsg0f4eIMVfTv9k4mbvzH4YJpTQAz2A81G/d0SJhy3Kj0GWhgcIS1eyOsHdS
+SWHuVhWT77n30lxnzu+c4bst9P3K5V7bCiTxlL/F/I5NqeV98ECJq5xC1F+MNiww
+LKQ6UQKBgC2zL59Vf8QnRkRN0gOUfs3ejrLcxFRzTXvcKqcHtbaqzCs3qSNC6UvV
+wjBazEwQCo1wnM81X8uT5fLhnjXebWtnYexQo5P38PiaqTQDgrbAdhP5P8NwRCXM
+G3SNEz0XeL27jmWjf0VJdwD0LuHXYhcwAWq4alhJ024rjgVHwOze
+-----END RSA PRIVATE KEY-----
+
diff --git a/src/components/transport_manager/test/test_certs/server-cert.pem b/src/components/transport_manager/test/test_certs/server-cert.pem
new file mode 100644
index 0000000000..d2b1cf0ec8
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/server-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdDCCAlwCAQEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVUExDzANBgNV
+BAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYDVQQKDAZMdXhvZnQxDTAL
+BgNVBAsMBEZUQ04xDzANBgNVBAMMBkx1eC1DQTEaMBgGCSqGSIb3DQEJARYLY2FA
+ZnRjbi5jb20wHhcNMjAwMTEwMTQzMzM2WhcNMjIxMDA2MTQzMzM2WjCBgzELMAkG
+A1UEBhMCVUExDzANBgNVBAgMBk9kZXNzYTEPMA0GA1UEBwwGT2Rlc3NhMQ8wDQYD
+VQQKDAZMdXhvZnQxDTALBgNVBAsMBEZUQ04xEjAQBgNVBAMMCWxvY2FsaG9zdDEe
+MBwGCSqGSIb3DQEJARYPc2VydmVyQGZ0Y24uY29tMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEApnW3zyWadWiD1eMPszMM0Hyzm3Zd6mr21LMtQMwqw10p
+PxMpZLo0rgCkJevVRxO/y4J+TcE9LtralzzsWK+DD/i2Gf8CfAOapcDETJ8b68jM
+rUMwmN3tdiEBqimHBKEKIgDOiJt2Y08Jw2AWR41LuyjtD+IWSWo1kqJF3rxpsfz0
+SfTQWkvHVXg1c0qbfsp2i82Nvt5HzvDdk0jzX+GNHSmkUECcE0GIhK8GHxAFYugk
+siRU/tgY/wzP9iUkj7UbPWb5k+d8Z3sqUFpVAa4dXhIzx5L0l5peXvhunYqr7Vk+
+cfBAHIQZKJa7coBBahA7gjBylz+BbIOadGYYoYZVBQIDAQABMA0GCSqGSIb3DQEB
+CwUAA4IBAQDNUMIv6X9scvVN8II/PbvvQzWAxi0qzDejnEF579PA9MCNt6JY20lj
+JTscUN5lWNuLGJtkUuscBMBYe21ePtGeS855Q6csoUe6m0fnY+ybKVYIKk+SL5Hx
+1vurBIsHOyX6097e8VIzWyxcWW1074oTYLpYfEWr0vECrGodoXGtPdEeyB0+QdbI
+H0Pcngqu5yLoWxoWwuAj94YG7eX3sJv6PXOW71i4yMmT8ToYNXFwqTK/xq/pl6H2
+KH150zDNOaE2Z5+u21Elau+3qWPWQ6C9KpxhmJ/iDftRe+hgMISSygYK0nwk0zk4
+rmNODAeuTvsrh9bNsYQfjERsh0VYaG24
+-----END CERTIFICATE-----
diff --git a/src/components/transport_manager/test/test_certs/server-key.pem b/src/components/transport_manager/test/test_certs/server-key.pem
new file mode 100644
index 0000000000..6ff13eaf28
--- /dev/null
+++ b/src/components/transport_manager/test/test_certs/server-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmdbfPJZp1aIPV
+4w+zMwzQfLObdl3qavbUsy1AzCrDXSk/EylkujSuAKQl69VHE7/Lgn5NwT0u2tqX
+POxYr4MP+LYZ/wJ8A5qlwMRMnxvryMytQzCY3e12IQGqKYcEoQoiAM6Im3ZjTwnD
+YBZHjUu7KO0P4hZJajWSokXevGmx/PRJ9NBaS8dVeDVzSpt+ynaLzY2+3kfO8N2T
+SPNf4Y0dKaRQQJwTQYiErwYfEAVi6CSyJFT+2Bj/DM/2JSSPtRs9ZvmT53xneypQ
+WlUBrh1eEjPHkvSXml5e+G6diqvtWT5x8EAchBkolrtygEFqEDuCMHKXP4Fsg5p0
+ZhihhlUFAgMBAAECggEBAJ35UfuxACk0iwlNd/TlGeAyuHFtoCt8X8v0T5oTKPJH
+U4GcucfyP1RzH1Utvza5M2f768n2/g2dfZ3SH6r6xjM+IfQB42W2NengS2s8BM97
+vWMhRNmOpHFbWa0XxB9MhcVHZrqWb4BH3kggxIQbQCfa60ALnIMH3NfQUObVgKl8
+khPU3fWx5zH2fbLNiLbImr5U5ViNoOKw592cmAEocIgIE33SDf2LHuuByikb38/r
+98bAp6IdNhRb7qY/Jllq3fu06fLubGQusVT01vu3sp//G2gCzFwp0O/qX2M1JBPS
+JYKKGXrNxeaQNzzD6cEcSkADpZvIG/CmmnR9u/FjIXECgYEA2palcAJKXPWsnwLb
+QtDd7MQ6sG3qvkCaiiDsn5BAGkxn1rZ3NRGMxBx4Fb9oiIl6SBpQ/YdMkd7tMkLX
+MEmbPyOcHPnsxcCqeFGsiTejpx1OyPSUAtxtpxGc/D63wCPhHGO3xNdQ2FiYb5K3
+jG8cslE39gH+/9XSN8kS2gZZ4d8CgYEAwvMUbXSBYx01I+jjqsjSI9afk3w9VwKM
+vuW9MgUBYLP5ryadNqt2cuHydT5KJiZ7YUQSLNztZ++g5WR7yamWpLzoGFmrSyWb
+304xA9jdLRJHMsBM0V32abdfTV5+EW+24309UmcaUtsQoUTxXOSqwDaHF4Mq1zLg
+jwb2phYlzZsCgYEAtz5q2gdRh7R8TaD7ZnvqTz4BZT3/+BX4d6s6MlmfI2zB8AFu
+1ZIsy4qCMNkRLMTzOda15pOx4OddOTFHbDeIadnUWYY6s1zci5kMZsu56bJsBZLj
+MbLQSao+TEfXir+JS19dAyrtnzBGOeJo9NWA3QuxOg5aUuZRIGrz3spMN0kCgYB3
+ZLnpAwZO9k9aS8JLESypqEMY52kFxdj+/OKvJKOgXvkWzPZRyhcD6t878McmsEC1
+5COheDipg/etJaouan+JKuyWJSykHEdnLpMUQRfMB7q1GVKykvJb8mMaljltYlbG
+4ifRNLXJcsKvkfKkKqNsjriTrNBq9YzT67bZJw1F6wKBgGlEd9O+qWY4dSPKN60N
+khG1Splz+eBbbsqcISeFGZepEc4HaEIcYgIHTh8nw5ycYxh8A1UBdaBZmU9UHdfl
+j9M2u0htKZ27ntVVNZJCLeSgufaPUDIfvnK4o5q630NGhKJmVcYD3WeggIrPfca3
+fP8WaHq9fx5k4YZokD2VHOJb
+-----END PRIVATE KEY-----
diff --git a/src/components/transport_manager/test/transport_manager_default_test.cc b/src/components/transport_manager/test/transport_manager_default_test.cc
index bedc1634cc..67b4a0a8ba 100644
--- a/src/components/transport_manager/test/transport_manager_default_test.cc
+++ b/src/components/transport_manager/test/transport_manager_default_test.cc
@@ -65,6 +65,12 @@ const std::string kTransportManager = "TransportManager";
const std::string kTcpAdapter = "TcpAdapter";
const std::string kBluetoothAdapter = "BluetoothAdapter";
const std::string kDevices = "devices";
+const uint16_t kPort = 12345u;
+const std::string kAddress = "127.0.0.1";
+const std::string kServerCertPath = "server_certificate.crt";
+const std::string kServerCACertPath = "ca-certificate.crt";
+const std::string kWSServerKeyPathKey = "WSServerKeyPath";
+const std::string kWSServerCACertPath = "WSServerCACertificatePath";
std::vector<uint8_t> kBTUUID = {0x93,
0x6D,
0xA0,
@@ -180,7 +186,7 @@ void TestTransportManagerDefault::ExpectationsSettings_TM(
// Arrange TM Settings expectations
Json::Value tcp_device;
tcp_device[kDeviceName] = unique_tcp_dev_name_;
- tcp_device[kDeviceAddress] = "127.0.0.1";
+ tcp_device[kDeviceAddress] = kAddress;
tcp_device[kDeviceApplications][0][kApplicationPort] = "1";
Json::Value bluetooth_device;
@@ -192,16 +198,29 @@ void TestTransportManagerDefault::ExpectationsSettings_TM(
custom_dictionary_[kTransportManager][kTcpAdapter][kDevices][0] = tcp_device;
custom_dictionary_[kTransportManager][kBluetoothAdapter][kDevices][0] =
bluetooth_device;
+ ON_CALL(transport_manager_settings_, websocket_server_port())
+ .WillByDefault(Return(kPort));
+ ON_CALL(transport_manager_settings_, websocket_server_address())
+ .WillByDefault(ReturnRef(kAddress));
+ ON_CALL(transport_manager_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kServerCertPath));
+ ON_CALL(transport_manager_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kWSServerKeyPathKey));
+ ON_CALL(transport_manager_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kWSServerCACertPath));
ON_CALL(*mock_last_state_, dictionary())
.WillByDefault(Return(custom_dictionary_));
ON_CALL(*mock_last_state_, get_dictionary())
.WillByDefault(ReturnRef(custom_dictionary_));
+
EXPECT_CALL(transport_manager_settings_, use_last_state())
.WillRepeatedly(Return(use_last_state));
EXPECT_CALL(transport_manager_settings_, transport_manager_tcp_adapter_port())
.WillRepeatedly(Return(tcp_adapter_port_));
+
EXPECT_CALL(transport_manager_settings_, bluetooth_uuid())
.WillRepeatedly(Return(kBTUUID.data()));
+
EXPECT_CALL(transport_manager_settings_, aoa_filter_manufacturer())
.WillRepeatedly(ReturnRef(dummy_parameter_));
EXPECT_CALL(transport_manager_settings_, aoa_filter_model_name())
diff --git a/src/components/transport_manager/test/websocket_client_connection_test.cc b/src/components/transport_manager/test/websocket_client_connection_test.cc
new file mode 100644
index 0000000000..b9aa6f7c7e
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_client_connection_test.cc
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "transport_manager/cloud/websocket_client_connection.h"
+#include "gtest/gtest.h"
+#include "resumption/last_state_impl.h"
+#include "resumption/last_state_wrapper_impl.h"
+#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
+#include "transport_manager/cloud/sample_websocket_server.h"
+#include "transport_manager/transport_adapter/connection.h"
+#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+
+#include "transport_manager/mock_transport_manager_settings.h"
+
+namespace test {
+namespace components {
+namespace transport_manager_test {
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using namespace ::transport_manager;
+using namespace ::transport_manager::transport_adapter;
+namespace websocket = sample::websocket;
+
+class WebsocketConnectionTest : public ::testing::Test {
+ public:
+ struct WebsocketClient {
+ std::shared_ptr<CloudWebsocketTransportAdapter> adapter;
+ std::shared_ptr<WebsocketClientConnection> connection;
+ };
+
+ void InitWebsocketClient(
+ const transport_manager::transport_adapter::CloudAppProperties&
+ properties,
+ WebsocketClient& client_out) {
+ uniq_id = dev_id = properties.endpoint;
+
+ client_out =
+ WebsocketClient{std::make_shared<CloudWebsocketTransportAdapter>(
+ last_state_wrapper_, transport_manager_settings),
+ nullptr};
+ client_out.adapter->SetAppCloudTransportConfig(uniq_id, properties);
+
+ TransportAdapterImpl* ta_cloud =
+ dynamic_cast<TransportAdapterImpl*>(client_out.adapter.get());
+ ta_cloud->CreateDevice(uniq_id);
+
+ auto connection = client_out.adapter->FindPendingConnection(dev_id, 0);
+
+ ASSERT_NE(connection, nullptr);
+
+ client_out.connection =
+ std::dynamic_pointer_cast<WebsocketClientConnection>(connection);
+
+ ASSERT_NE(client_out.connection.use_count(), 0);
+ }
+
+ void StartWSServer(std::string path) {
+ ws_session = std::make_shared<websocket::WSSession>(kHost, kPort);
+ ws_session->AddRoute(path);
+ ws_session->Run();
+ }
+
+ void StartWSSServer(std::string path) {
+ wss_session = std::make_shared<websocket::WSSSession>(
+ kHost, kPort, kCertificate, kPrivateKey);
+ wss_session->AddRoute(path);
+ wss_session->Run();
+ }
+
+ protected:
+ WebsocketConnectionTest()
+ : last_state_(std::make_shared<resumption::LastStateImpl>(
+ "app_storage_folder", "app_info_storage"))
+ , last_state_wrapper_(
+ std::make_shared<resumption::LastStateWrapperImpl>(last_state_)) {}
+
+ ~WebsocketConnectionTest() {}
+
+ void SetUp() OVERRIDE {
+ ON_CALL(transport_manager_settings, use_last_state())
+ .WillByDefault(Return(true));
+ }
+
+ NiceMock<MockTransportManagerSettings> transport_manager_settings;
+ std::shared_ptr<resumption::LastStateImpl> last_state_;
+ std::shared_ptr<resumption::LastStateWrapperImpl> last_state_wrapper_;
+ std::string dev_id;
+ std::string uniq_id;
+ std::shared_ptr<websocket::WSSession> ws_session;
+ std::shared_ptr<websocket::WSSSession> wss_session;
+ WebsocketClient ws_client;
+ std::string kHost = "127.0.0.1";
+ uint16_t kPort = 8080;
+ std::string kPath = "/folder/file.html/";
+ std::string kQuery = "?eventId=2345&eventName='Test'&expectedResult=true";
+ std::string kFragment = "#section_1";
+
+ // Sample certificate for localhost
+ std::string kCertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----\nMIIDqTCCApECCQC/"
+ "5LlQ+"
+ "GLgqTANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAwx\nMjcuMC4wLjEgQ0EwIBcNMTkwNTA"
+ "2MTkzMjM2WhgPMjExOTA0MTIxOTMyMzZaMBQx\nEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiIwD"
+ "QYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBALbeIoAHFaFeNqbMnhtAO5QTgRd0X9qxpB0"
+ "d4M0dEeog2l/+inNA/eu+CCvm\nJj2I8+6MWH2TUrl/"
+ "2xfhHjzsMrtISCdpNcjaNzCnvi8ZcspFi3evknvs3+uo2/"
+ "wn\nyNZ04jp0oQ0k1cZ6WBpLTYV7WgmueemiWEiAfw+YE+wtRg+"
+ "0H7rksrbpeNPnxQHX\nBDDkWqwvfkD15Sd0XFQkW27K72/"
+ "et2uKuAcJHCIUbsA4iZyJw4Uu4eusy7W5kddX\nThE7Y1WqTXyA4j/"
+ "ZCYigXmsHbWrikPLVXbORhiMF4/60u8RDs0jI8xtgRQhLR9Vp\n3xys7/"
+ "5tHZX00s6x6OVy8aMSZIIVS0eWoVN8bGd9B4+fDMOcNT0YODeQA10w/"
+ "85P\nEiZDQ8AxneQkh8H3qjD2+"
+ "G9oHZaTk0zHTyaKRg3xGP3N9C96onaJX4Rm6nNvApO8\nU7lQ+xHkLwjKCQke39W+"
+ "r3FHwwQvUDeoJBXf6iVkIMFoUPAHNZqKf9Db6KKIEp8i\nDgIhbBxiB4MSn36Zly4SOMojyM"
+ "ZFri+"
+ "HzMbuHFlm8e8QRWGmM4UM2rHIpl4OJolg\nejesDqO8YZR5mZXV0FJRiPgLo2Q4OTtb3tEHJ"
+ "ZLmlT+"
+ "f42bge4ZCZmGPrkNfr68Y\nDEnJ6z4ksOVkMefOp2SNYLYYGPYyiKwa9qVkH9Obkect1omNA"
+ "gMBAAEwDQYJKoZI\nhvcNAQELBQADggEBABFJQtOTftrzbLBA5Vm6aPkbUyxhcaOpz+d+"
+ "Ljd6pIs4H+"
+ "Eb\nXkoHhmay4stZkDc2HVSKESZloI3Ylup8z3aRJjfOexJqHlYzk2vraYryWm8odgID\n5V"
+ "B0Zle8ofpHTJw1LCOXHkzKt1G6vdQpuq/"
+ "4OKpmggaIqqEC1bfOYZt5t6vIx3OF\nxjPz91NTR9gZ4lKrho1+sfS+"
+ "jbSjKkqVAhE4yTpKLPHRshQnBFEhvATXNvdZGftF\n+tXxqKsBZ9aX0/"
+ "YmPFIXFcjdjSSiuq1F1DjiqIZo88qfa9jlTg6VJdayyQ/"
+ "cu41C\nBucY8YTF0Ui8ccIS55h2UTzPy5/4PbrwI4P+Zgo=\n-----END "
+ "CERTIFICATE-----\n";
+ // Sample private key
+ std::string kPrivateKey =
+ "-----BEGIN RSA PRIVATE "
+ "KEY-----\nMIIJKAIBAAKCAgEAtt4igAcVoV42psyeG0A7lBOBF3Rf2rGkHR3gzR0R6iDaX/"
+ "6K\nc0D9674IK+YmPYjz7oxYfZNSuX/"
+ "bF+EePOwyu0hIJ2k1yNo3MKe+LxlyykWLd6+S\ne+zf66jb/"
+ "CfI1nTiOnShDSTVxnpYGktNhXtaCa556aJYSIB/"
+ "D5gT7C1GD7QfuuSy\ntul40+fFAdcEMORarC9+"
+ "QPXlJ3RcVCRbbsrvb963a4q4BwkcIhRuwDiJnInDhS7h\n66zLtbmR11dOETtjVapNfIDiP9"
+ "kJiKBeawdtauKQ8tVds5GGIwXj/rS7xEOzSMjz\nG2BFCEtH1WnfHKzv/"
+ "m0dlfTSzrHo5XLxoxJkghVLR5ahU3xsZ30Hj58Mw5w1PRg4\nN5ADXTD/"
+ "zk8SJkNDwDGd5CSHwfeqMPb4b2gdlpOTTMdPJopGDfEY/"
+ "c30L3qidolf\nhGbqc28Ck7xTuVD7EeQvCMoJCR7f1b6vcUfDBC9QN6gkFd/"
+ "qJWQgwWhQ8Ac1mop/"
+ "\n0NvooogSnyIOAiFsHGIHgxKffpmXLhI4yiPIxkWuL4fMxu4cWWbx7xBFYaYzhQza\nscim"
+ "Xg4miWB6N6wOo7xhlHmZldXQUlGI+AujZDg5O1ve0QclkuaVP5/"
+ "jZuB7hkJm\nYY+uQ1+"
+ "vrxgMScnrPiSw5WQx586nZI1gthgY9jKIrBr2pWQf05uR5y3WiY0CAwEA\nAQKCAgBGSDGyS"
+ "wbBMliG2vWZO6KqUqS2wv9kKgoNNsKDkryj42SKqGXFziDJTgwN\n8zKXS9+Uu1P3T3vn13/"
+ "5OYhJme4VlL5Gh2UogNXdWVr69yjrHLdxlIUUJAIbrJZ/"
+ "\n3zqNUfbwyIptZs7SrYrW8EInHzWHqwsoBEEx/"
+ "FDZSXW+u9fFiVD4n5UgP7M0nktV\nXbI6qElBDC/V/"
+ "6vG8i3aGO8bMdu8fzi3mGUKLzIk1v2J2zDofPosYcxqq8rPWTb4\nMJHMhaqz7fRB+"
+ "bb7GwtS+2/Oathe0B0td1u//Bo1s7ng1s2jrPFm8/"
+ "SbfPCLM4O0\nPjCF8OF8Q6uvSp0K283LAdZk+liuDztc/"
+ "Ed8mcnCZQhBp86mJQi0Jj3Mje7prOAY\nXojMroYj7r2igCJvcwGb1y6zZWSj3jXuHze3bLy"
+ "fv7pCD+hkiZR7mZhQpOhQRZaU\ntdFGc+"
+ "DuykxKPqVjAPy7iVQXYnMjpo36SGIWoZLuepQto3GvU6czyOwhK0/"
+ "Mwbwd\nZpYpLH3L9IetY8GcPefmUR5wQUlUTrpxgGElIzkkWW8zmUWBXwrGbAtN1HJWpJdN"
+ "\neVshKod2fo03IQMPywSdENCJVeSrgRMuwPyFaOM+"
+ "CVrBJwD66K9YWn4cVRUIZsTq\nAXhQ8DzF+WCOZshhMUbCJX+KpcOFI8nxOrPp+"
+ "J1s1YpLLvdmcQKCAQEA7bwvOiCD\nHvaqpYg1jJak6l/"
+ "iY3QIOOpFyjfYrQXS0BNRmmxK8Lzevi/"
+ "NPTqu146QKDaIGvzu\n+"
+ "bXnuV1LmZqnOm5J6Kdx0Mk4Fb88akRtS9gOdzU7WWMYIGkeF1oih0ZrhHuIey6e\nCeLSmJh"
+ "UDaTIWcCirALRHcLWUS6BTGGuE+up5QG7djIW/"
+ "LD17lhGE6fXPlbYXb7l\nPbYwL1Yr0urIp9Un+zrExw+77TTGK7T37T1ZJv46qnro0/"
+ "HK8XxZ+"
+ "JNc18F763O4\nPmwu8KWrx4qnyPYAuB1rbVntK6UxYks9jvk93XecCUP6HHp0I0tV/"
+ "kBNd2+"
+ "18zux\n033xFEVKrUksmwKCAQEAxOrPGyBVFp29V4gQsMQdmafkDAgCLREgjQTOamFsYL5+"
+ "\nZWq+6VhT/"
+ "B650sIoRdX0N8timnSLBfjeqaBG5VVhhyKZhP5hulfRjALhdbGBOYvf\n0gLSffImwWdYQfx"
+ "jtCSO+"
+ "XCLVdAJGOOWeBVVKzH18ZvCFQwUr3Yrp7KmKWKAqgf7\n6rYovWh8T5LLYS0NzXCEwf9nJ0N"
+ "JMOy7I9B7EtF8Cs6tK3aaHVqDz7zufwosS7gI\n3aI51Qh4a5D1p95+"
+ "YU09beWjWGYnPiCKk4D47zaeOe7OQINaWugExlelHtJh9unO\nnhOFXhziav2Kxq1CICAuXl"
+ "Vx3A+gn/cU3niNHz2A9wKCAQEAws+aw78ws4bef5cG\nipZHveek1GqY8krHtdXdsKs8/"
+ "VVXYXusTWn3/VGelbYo4GrqpolJLxRloCr4IGXb\nNZwNvUvzNLtCAR1i4C89irdX+Paro/"
+ "PzFmSluKlrByfNc5y5Lm8sgATLbL56ZKEu\n/58wrpu0sc/"
+ "9HK40gYHiYn0I8ToElqy8uTaCr78zSIT9p826DFOOKgPsRo2tHp02\nfDf5Bc8eXDjkV1sFX"
+ "HQKkHZTVA0ZqWJbIKhncoaJDyofcBsR0ZuzuFWzfTOZo4mf\nInz00TEFldpF1e4C8+"
+ "kCdtHBOA/2Ki2Bp/YUVpHh6aoqZZa75Euehhs8tVpW242M\njEOSUQKCAQAM64sjMH/kt/"
+ "zQXXEa6AM5LbbcwznBUzpbhlE00aeWwWjxpotYLB92\nj12J4otZ6avYbVPO5o6omaeiYY3F"
+ "RlDb2P1RqI8o9tIc6aN5YWglKnRJBz5gXR8F\n2Y4E5lZ0X2GyJBxASSIPq/"
+ "8Xae7ooqKMc7fMQbqpuIssuaAFXx0qCtQQllsd8lkV\nr4AApEAflp5fTC6seNG4kA/"
+ "HTcqFdZE59E2QaHu8KVA0tSTA2R4G6dBLGnXI8IFW\nLXCwzvxjzfmV2FdbWXiBrwjonLG4o"
+ "FDJZE3MFdI73LVTfjSrTQp4dObFoGpDvols\nk64jUwLfsLzaG6kY0z2qwT9xSV+"
+ "ZCSQJAoIBADsSBeyELc5KnmOhT0Xue2o0bkAS\n8KcGWdAoQlaLCIs3vtdlC7DXDXO1l8FkT"
+ "Qrd+GwP3eWDq6ymtO4vkJ3m4cZ1PEsv\n6Qet7qtkVhUfa+"
+ "FYKtDzSMRuSaFPW3Ro1PesFa1H3y+sw5HL36vhRaSK+T4Wy5k2\nf7EwNZIf/"
+ "ZZeA+"
+ "sEtqj33obOBIiuU9htAjN81Kz4a0Xlh6jc4q6iwYKL8nZ76JYV\n8hXWIz6OXxLXE158+"
+ "QtJSZaRCvdr6L5UtWfMPKSMqgfhXfTYViPDleQCkJ132mIS\nH28UoET0Y5wI8M6pMkWpSqW"
+ "WcKPFGwyLInvHdxgnTAsutowkldA7qFwoRz4=\n-----END RSA PRIVATE KEY-----\n";
+ // Sample CA certificate(used to sign the server certificate)
+ std::string kCACertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----"
+ "\nMIIDBjCCAe6gAwIBAgIJAPyCrKRDl3SWMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV\nBAMM"
+ "DDEyNy4wLjAuMSBDQTAgFw0xOTA1MDYxOTMyMzZaGA8yMTE5MDQxMjE5MzIz\nNlowFzEVMB"
+ "MGA1UEAwwMMTI3LjAuMC4xIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA"
+ "xrNHoY5+"
+ "JCgnyvEdG2dvvOaZ3sg6uhuF5Ssb5snyo9ixrxO5\nZkDGWwUqFO9PiYuO5ovNeq9LZtPG6s"
+ "K8zsCS062ChZX/7tZHndf4MKCUDzv/"
+ "LPHe\nnROoPi9n2FAiOPctY5hpgpIJDPI5Ofx0el2KPeFGeUO/"
+ "W3yqnfol1ZqzZ2h3uErR\noHkgT2Ja4K+5gnPkr/"
+ "RluJIu3AmWYw4eKi8i3+"
+ "PoThGmCFvoGfcWvRoctgnOHYHE\n4bDRirXL9nGkZ5FMzOVDeoIAEAShOqJwL08VcY+Pg/"
+ "qFQjzRrTmiKgm6QsHNnm0q\nzg70XaD88VJimiGYZOuJHNZpX8o0W+1Ls/"
+ "NbawIDAQABo1MwUTAdBgNVHQ4EFgQU\nkW3hgFWYMpVUkq9AlzGlI3awTGEwHwYDVR0jBBgw"
+ "FoAUkW3hgFWYMpVUkq9AlzGl\nI3awTGEwDwYDVR0TAQH/BAUwAwEB/"
+ "zANBgkqhkiG9w0BAQsFAAOCAQEAZeMkILiG\neEcELWb8cktP3LzvS47O8hys9+"
+ "6TFmftuO7kjDBd9YH2v8iQ7qCcUvMJ7bqL5RP1\nQssKfNOHZtw/"
+ "MMcKE6E3nl4yQSKc8ymivvYSVu5SYtQCedcgfRLb5zvVxXw8JmCp\nGNS3/"
+ "OlIYZAamh76GxkKSaV3tv0XZB6n3rUVQZShncFbMpyJRW0XWxReGWrhXv4s\nNxMeC1r07EE"
+ "WIDecv8KKf1F8uT4UF48HnC0VBpXiOyDGvn35NiKp+"
+ "Q5k7QV6jdCS\ngPRcnZhs6jiU0jnV8C9A1A+"
+ "3pXSSPrAed7tvECOgHCfS10CLsLWsLuSjc93BE5Vt\nav7kmxSwrdvQ2A==\n-----END "
+ "CERTIFICATE-----\n";
+ std::string kIncorrectCertificate =
+ "-----BEGIN "
+ "CERTIFICATE-----\nMIIC/"
+ "jCCAeagAwIBAgIJAIZjLucUID1mMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV\nBAMMCTEyNy4"
+ "wLjAuMTAeFw0xOTA1MDYxNDA1MzdaFw0yOjA1MDZxNDA1MzdaMBQx\nEjAQBgNVBAMMCTEyN"
+ "y4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBALfE5Qhc2mHTIux30l7"
+ "eHFjFLdzYeXE8vcaXKodalCG8EkRxojDOfUv+y2DV\nJzHAMiGxMFAEcSz71k+"
+ "jFZwhNG8PLY0b36ChnUsrGkOSJWq3OKUFrg8KxO9At9dL\nJsa+"
+ "R0N0D1bMoPYdpCi3m0b0q2ITHe56qKuTLTrIPia+"
+ "qXGEVD7EoEhU9tnwlcwE\npsUURMXCn2+FhHyqN9wjFkldmu4k8U3OJOK4385L+"
+ "4RJoIV8dsYawAMAf+"
+ "WuxyWq\niPQTPxr8q33ZZm6z0XrgsgxHYCCsryx8L9Ub9Zwu0mie7eL63rYdr86gULvnF1bY"
+ "\ncOunKFc71rBYFalbD6YYsre733kCAwEAAaNTMFEwHQYDVR0OBBYEFKW9ByUNG84Z\nYiSc"
+ "hUrB7KV9FinZMB8GA1UdIwQYMBaAFKW9ByUNG84ZYiSchUrB7KV9FinZMA8G\nA1UdEwEB/"
+ "wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYROS1EL2qnrwmAsR6c\nqo8yrk8qzLKt4os"
+ "41nv7QMUQFIO+QLPE8SbH4fK1YOMMUJ4ppARQBDaIIR3UEhp1\nZHT/"
+ "wGjK9qxcuQ1EXLyHOY0rxS5q57dYGxOyQo4v6IoLVMZ1ij+RJGPYI/"
+ "2fDXs0\nbDldeJyC1voHmG6lqTN5nLG7Y3j9j6rtSqJyRz5muaecQNiFPQOM2OTp0rC4VeAF"
+ "\ndejmTmLhUFVuHMzLF+"
+ "bpzsN76GnnQquJy2jexzFoWgbEfFVLKuyhTHQAalRb4ccq\nXCIx1hecNDYRY3Sc2Gzv5qxk"
+ "kWF8zqltT/0d5tx0JwN3k5nP4SlaEldFvD6BELxy\nVkU=\n-----END "
+ "CERTIFICATE-----\n";
+};
+
+TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort),
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer(kPath);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + kPath,
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer((kPath + kQuery + kFragment));
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+#ifdef ENABLE_SECURITY
+TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer(kPath);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kIncorrectCertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ StartWSSServer("/");
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+}
+#endif // ENABLE_SECURITY
+} // namespace transport_manager_test
+} // namespace components
+} // namespace test
diff --git a/src/components/transport_manager/test/websocket_connection_test.cc b/src/components/transport_manager/test/websocket_connection_test.cc
index a7ddb820a0..306bdc4784 100644
--- a/src/components/transport_manager/test/websocket_connection_test.cc
+++ b/src/components/transport_manager/test/websocket_connection_test.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Ford Motor Company
+ * Copyright (c) 2020, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,15 +31,26 @@
*/
#include "gtest/gtest.h"
+
+#include <memory>
+#include <string>
+
#include "resumption/last_state_impl.h"
-#include "resumption/last_state_wrapper_impl.h"
-#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
-#include "transport_manager/cloud/sample_websocket_server.h"
-#include "transport_manager/cloud/websocket_client_connection.h"
-#include "transport_manager/transport_adapter/connection.h"
-#include "transport_manager/transport_adapter/transport_adapter_impl.h"
+#include "transport_manager/websocket_server/websocket_connection.h"
+#include "transport_manager/websocket_server/websocket_session.h"
#include "transport_manager/mock_transport_manager_settings.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
+
+namespace {
+const std::string kHost = "127.0.0.1";
+const uint16_t kPort = 8080;
+const std::string kPath = "/folder/file.html/";
+const std::uint32_t kConnectionKey = 1u;
+const std::uint32_t kProtocolVersion = 5u;
+const std::string kDeviceUid_ = "deviceUID";
+const transport_manager::ApplicationHandle kAppHandle = 12345u;
+} // namespace
namespace test {
namespace components {
@@ -48,433 +59,112 @@ namespace transport_manager_test {
using ::testing::_;
using ::testing::NiceMock;
using ::testing::Return;
+
+using protocol_handler::RawMessagePtr;
+using protocol_handler::ServiceType;
+
using namespace ::transport_manager;
using namespace ::transport_manager::transport_adapter;
-namespace websocket = sample::websocket;
-class WebsocketConnectionTest : public ::testing::Test {
+class WebsocketNotSecureSessionConnectionTest : public testing::Test {
public:
- struct WebsocketClient {
- std::shared_ptr<CloudWebsocketTransportAdapter> adapter;
- std::shared_ptr<WebsocketClientConnection> connection;
- };
+ WebsocketNotSecureSessionConnectionTest()
+ : websocket_connection_(
+ std::make_shared<WebSocketConnection<WebSocketSession<> > >(
+ kDeviceUid_,
+ kAppHandle,
+ boost::asio::ip::tcp::socket(i_co_),
+ &mock_transport_adapter_ctrl_))
- void InitWebsocketClient(
- const transport_manager::transport_adapter::CloudAppProperties&
- properties,
- WebsocketClient& client_out) {
- uniq_id = dev_id = properties.endpoint;
+ , last_state_("test_app_folder", "test_app_info_storage") {}
- client_out =
- WebsocketClient{std::make_shared<CloudWebsocketTransportAdapter>(
- last_state_, transport_manager_settings),
- nullptr};
- client_out.adapter->SetAppCloudTransportConfig(uniq_id, properties);
-
- TransportAdapterImpl* ta_cloud =
- dynamic_cast<TransportAdapterImpl*>(client_out.adapter.get());
- ta_cloud->CreateDevice(uniq_id);
+ void SetUp() OVERRIDE {
+ ON_CALL(mock_transport_manager_settings_, use_last_state())
+ .WillByDefault(Return(true));
+ }
- auto connection = client_out.adapter->FindPendingConnection(dev_id, 0);
+ RawMessagePtr CreateDefaultRawMessage() {
+ const uint32_t data_sending_size = 3u;
+ unsigned char data_sending[data_sending_size] = {0x20, 0x07, 0x01};
+ RawMessagePtr raw_message_ptr(
+ new ::protocol_handler::RawMessage(kConnectionKey,
+ kProtocolVersion,
+ data_sending,
+ data_sending_size,
+ false,
+ ServiceType::kAudio));
+ return raw_message_ptr;
+ }
- ASSERT_NE(connection, nullptr);
+ protected:
+ boost::asio::io_context i_co_;
+ std::shared_ptr<WebSocketConnection<WebSocketSession<> > >
+ websocket_connection_;
+ NiceMock<MockTransportAdapterController> mock_transport_adapter_ctrl_;
+ NiceMock<MockTransportManagerSettings> mock_transport_manager_settings_;
+ resumption::LastStateImpl last_state_;
+};
- client_out.connection =
- std::dynamic_pointer_cast<WebsocketClientConnection>(connection);
+TEST_F(WebsocketNotSecureSessionConnectionTest, Disconnect_SUCCESS) {
+ websocket_connection_->Run();
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(1);
- ASSERT_NE(client_out.connection.use_count(), 0);
- }
+ auto error = websocket_connection_->Disconnect();
- void StartWSServer(std::string path) {
- ws_session = std::make_shared<websocket::WSSession>(kHost, kPort);
- ws_session->AddRoute(path);
- ws_session->Run();
- }
+ ASSERT_EQ(TransportAdapter::Error::OK, error);
+}
- void StartWSSServer(std::string path) {
- wss_session = std::make_shared<websocket::WSSSession>(
- kHost, kPort, kCertificate, kPrivateKey);
- wss_session->AddRoute(path);
- wss_session->Run();
- }
+TEST_F(WebsocketNotSecureSessionConnectionTest, SecondDisconnect_UNSUCCESS) {
+ websocket_connection_->Run();
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(1);
- protected:
- WebsocketConnectionTest()
- : last_state_(std::make_shared<resumption::LastStateWrapperImpl>(
- std::make_shared<resumption::LastStateImpl>("app_storage_folder",
- "app_info_storage"))) {}
+ auto result_error = websocket_connection_->Disconnect();
- ~WebsocketConnectionTest() {}
+ ASSERT_EQ(TransportAdapter::Error::OK, result_error);
- void SetUp() OVERRIDE {
- ON_CALL(transport_manager_settings, use_last_state())
- .WillByDefault(Return(true));
- }
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DisconnectDone(kDeviceUid_, kAppHandle))
+ .Times(0);
- NiceMock<MockTransportManagerSettings> transport_manager_settings;
- resumption::LastStateWrapperPtr last_state_;
- std::string dev_id;
- std::string uniq_id;
- std::shared_ptr<websocket::WSSession> ws_session;
- std::shared_ptr<websocket::WSSSession> wss_session;
- WebsocketClient ws_client;
- std::string kHost = "127.0.0.1";
- uint16_t kPort = 8080;
- std::string kPath = "/folder/file.html/";
- std::string kQuery = "?eventId=2345&eventName='Test'&expectedResult=true";
- std::string kFragment = "#section_1";
-
- // Sample certificate for localhost
- std::string kCertificate =
- "-----BEGIN "
- "CERTIFICATE-----\nMIIDqTCCApECCQC/"
- "5LlQ+"
- "GLgqTANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAwx\nMjcuMC4wLjEgQ0EwIBcNMTkwNTA"
- "2MTkzMjM2WhgPMjExOTA0MTIxOTMyMzZaMBQx\nEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiIwD"
- "QYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBALbeIoAHFaFeNqbMnhtAO5QTgRd0X9qxpB0"
- "d4M0dEeog2l/+inNA/eu+CCvm\nJj2I8+6MWH2TUrl/"
- "2xfhHjzsMrtISCdpNcjaNzCnvi8ZcspFi3evknvs3+uo2/"
- "wn\nyNZ04jp0oQ0k1cZ6WBpLTYV7WgmueemiWEiAfw+YE+wtRg+"
- "0H7rksrbpeNPnxQHX\nBDDkWqwvfkD15Sd0XFQkW27K72/"
- "et2uKuAcJHCIUbsA4iZyJw4Uu4eusy7W5kddX\nThE7Y1WqTXyA4j/"
- "ZCYigXmsHbWrikPLVXbORhiMF4/60u8RDs0jI8xtgRQhLR9Vp\n3xys7/"
- "5tHZX00s6x6OVy8aMSZIIVS0eWoVN8bGd9B4+fDMOcNT0YODeQA10w/"
- "85P\nEiZDQ8AxneQkh8H3qjD2+"
- "G9oHZaTk0zHTyaKRg3xGP3N9C96onaJX4Rm6nNvApO8\nU7lQ+xHkLwjKCQke39W+"
- "r3FHwwQvUDeoJBXf6iVkIMFoUPAHNZqKf9Db6KKIEp8i\nDgIhbBxiB4MSn36Zly4SOMojyM"
- "ZFri+"
- "HzMbuHFlm8e8QRWGmM4UM2rHIpl4OJolg\nejesDqO8YZR5mZXV0FJRiPgLo2Q4OTtb3tEHJ"
- "ZLmlT+"
- "f42bge4ZCZmGPrkNfr68Y\nDEnJ6z4ksOVkMefOp2SNYLYYGPYyiKwa9qVkH9Obkect1omNA"
- "gMBAAEwDQYJKoZI\nhvcNAQELBQADggEBABFJQtOTftrzbLBA5Vm6aPkbUyxhcaOpz+d+"
- "Ljd6pIs4H+"
- "Eb\nXkoHhmay4stZkDc2HVSKESZloI3Ylup8z3aRJjfOexJqHlYzk2vraYryWm8odgID\n5V"
- "B0Zle8ofpHTJw1LCOXHkzKt1G6vdQpuq/"
- "4OKpmggaIqqEC1bfOYZt5t6vIx3OF\nxjPz91NTR9gZ4lKrho1+sfS+"
- "jbSjKkqVAhE4yTpKLPHRshQnBFEhvATXNvdZGftF\n+tXxqKsBZ9aX0/"
- "YmPFIXFcjdjSSiuq1F1DjiqIZo88qfa9jlTg6VJdayyQ/"
- "cu41C\nBucY8YTF0Ui8ccIS55h2UTzPy5/4PbrwI4P+Zgo=\n-----END "
- "CERTIFICATE-----\n";
- // Sample private key
- std::string kPrivateKey =
- "-----BEGIN RSA PRIVATE "
- "KEY-----\nMIIJKAIBAAKCAgEAtt4igAcVoV42psyeG0A7lBOBF3Rf2rGkHR3gzR0R6iDaX/"
- "6K\nc0D9674IK+YmPYjz7oxYfZNSuX/"
- "bF+EePOwyu0hIJ2k1yNo3MKe+LxlyykWLd6+S\ne+zf66jb/"
- "CfI1nTiOnShDSTVxnpYGktNhXtaCa556aJYSIB/"
- "D5gT7C1GD7QfuuSy\ntul40+fFAdcEMORarC9+"
- "QPXlJ3RcVCRbbsrvb963a4q4BwkcIhRuwDiJnInDhS7h\n66zLtbmR11dOETtjVapNfIDiP9"
- "kJiKBeawdtauKQ8tVds5GGIwXj/rS7xEOzSMjz\nG2BFCEtH1WnfHKzv/"
- "m0dlfTSzrHo5XLxoxJkghVLR5ahU3xsZ30Hj58Mw5w1PRg4\nN5ADXTD/"
- "zk8SJkNDwDGd5CSHwfeqMPb4b2gdlpOTTMdPJopGDfEY/"
- "c30L3qidolf\nhGbqc28Ck7xTuVD7EeQvCMoJCR7f1b6vcUfDBC9QN6gkFd/"
- "qJWQgwWhQ8Ac1mop/"
- "\n0NvooogSnyIOAiFsHGIHgxKffpmXLhI4yiPIxkWuL4fMxu4cWWbx7xBFYaYzhQza\nscim"
- "Xg4miWB6N6wOo7xhlHmZldXQUlGI+AujZDg5O1ve0QclkuaVP5/"
- "jZuB7hkJm\nYY+uQ1+"
- "vrxgMScnrPiSw5WQx586nZI1gthgY9jKIrBr2pWQf05uR5y3WiY0CAwEA\nAQKCAgBGSDGyS"
- "wbBMliG2vWZO6KqUqS2wv9kKgoNNsKDkryj42SKqGXFziDJTgwN\n8zKXS9+Uu1P3T3vn13/"
- "5OYhJme4VlL5Gh2UogNXdWVr69yjrHLdxlIUUJAIbrJZ/"
- "\n3zqNUfbwyIptZs7SrYrW8EInHzWHqwsoBEEx/"
- "FDZSXW+u9fFiVD4n5UgP7M0nktV\nXbI6qElBDC/V/"
- "6vG8i3aGO8bMdu8fzi3mGUKLzIk1v2J2zDofPosYcxqq8rPWTb4\nMJHMhaqz7fRB+"
- "bb7GwtS+2/Oathe0B0td1u//Bo1s7ng1s2jrPFm8/"
- "SbfPCLM4O0\nPjCF8OF8Q6uvSp0K283LAdZk+liuDztc/"
- "Ed8mcnCZQhBp86mJQi0Jj3Mje7prOAY\nXojMroYj7r2igCJvcwGb1y6zZWSj3jXuHze3bLy"
- "fv7pCD+hkiZR7mZhQpOhQRZaU\ntdFGc+"
- "DuykxKPqVjAPy7iVQXYnMjpo36SGIWoZLuepQto3GvU6czyOwhK0/"
- "Mwbwd\nZpYpLH3L9IetY8GcPefmUR5wQUlUTrpxgGElIzkkWW8zmUWBXwrGbAtN1HJWpJdN"
- "\neVshKod2fo03IQMPywSdENCJVeSrgRMuwPyFaOM+"
- "CVrBJwD66K9YWn4cVRUIZsTq\nAXhQ8DzF+WCOZshhMUbCJX+KpcOFI8nxOrPp+"
- "J1s1YpLLvdmcQKCAQEA7bwvOiCD\nHvaqpYg1jJak6l/"
- "iY3QIOOpFyjfYrQXS0BNRmmxK8Lzevi/"
- "NPTqu146QKDaIGvzu\n+"
- "bXnuV1LmZqnOm5J6Kdx0Mk4Fb88akRtS9gOdzU7WWMYIGkeF1oih0ZrhHuIey6e\nCeLSmJh"
- "UDaTIWcCirALRHcLWUS6BTGGuE+up5QG7djIW/"
- "LD17lhGE6fXPlbYXb7l\nPbYwL1Yr0urIp9Un+zrExw+77TTGK7T37T1ZJv46qnro0/"
- "HK8XxZ+"
- "JNc18F763O4\nPmwu8KWrx4qnyPYAuB1rbVntK6UxYks9jvk93XecCUP6HHp0I0tV/"
- "kBNd2+"
- "18zux\n033xFEVKrUksmwKCAQEAxOrPGyBVFp29V4gQsMQdmafkDAgCLREgjQTOamFsYL5+"
- "\nZWq+6VhT/"
- "B650sIoRdX0N8timnSLBfjeqaBG5VVhhyKZhP5hulfRjALhdbGBOYvf\n0gLSffImwWdYQfx"
- "jtCSO+"
- "XCLVdAJGOOWeBVVKzH18ZvCFQwUr3Yrp7KmKWKAqgf7\n6rYovWh8T5LLYS0NzXCEwf9nJ0N"
- "JMOy7I9B7EtF8Cs6tK3aaHVqDz7zufwosS7gI\n3aI51Qh4a5D1p95+"
- "YU09beWjWGYnPiCKk4D47zaeOe7OQINaWugExlelHtJh9unO\nnhOFXhziav2Kxq1CICAuXl"
- "Vx3A+gn/cU3niNHz2A9wKCAQEAws+aw78ws4bef5cG\nipZHveek1GqY8krHtdXdsKs8/"
- "VVXYXusTWn3/VGelbYo4GrqpolJLxRloCr4IGXb\nNZwNvUvzNLtCAR1i4C89irdX+Paro/"
- "PzFmSluKlrByfNc5y5Lm8sgATLbL56ZKEu\n/58wrpu0sc/"
- "9HK40gYHiYn0I8ToElqy8uTaCr78zSIT9p826DFOOKgPsRo2tHp02\nfDf5Bc8eXDjkV1sFX"
- "HQKkHZTVA0ZqWJbIKhncoaJDyofcBsR0ZuzuFWzfTOZo4mf\nInz00TEFldpF1e4C8+"
- "kCdtHBOA/2Ki2Bp/YUVpHh6aoqZZa75Euehhs8tVpW242M\njEOSUQKCAQAM64sjMH/kt/"
- "zQXXEa6AM5LbbcwznBUzpbhlE00aeWwWjxpotYLB92\nj12J4otZ6avYbVPO5o6omaeiYY3F"
- "RlDb2P1RqI8o9tIc6aN5YWglKnRJBz5gXR8F\n2Y4E5lZ0X2GyJBxASSIPq/"
- "8Xae7ooqKMc7fMQbqpuIssuaAFXx0qCtQQllsd8lkV\nr4AApEAflp5fTC6seNG4kA/"
- "HTcqFdZE59E2QaHu8KVA0tSTA2R4G6dBLGnXI8IFW\nLXCwzvxjzfmV2FdbWXiBrwjonLG4o"
- "FDJZE3MFdI73LVTfjSrTQp4dObFoGpDvols\nk64jUwLfsLzaG6kY0z2qwT9xSV+"
- "ZCSQJAoIBADsSBeyELc5KnmOhT0Xue2o0bkAS\n8KcGWdAoQlaLCIs3vtdlC7DXDXO1l8FkT"
- "Qrd+GwP3eWDq6ymtO4vkJ3m4cZ1PEsv\n6Qet7qtkVhUfa+"
- "FYKtDzSMRuSaFPW3Ro1PesFa1H3y+sw5HL36vhRaSK+T4Wy5k2\nf7EwNZIf/"
- "ZZeA+"
- "sEtqj33obOBIiuU9htAjN81Kz4a0Xlh6jc4q6iwYKL8nZ76JYV\n8hXWIz6OXxLXE158+"
- "QtJSZaRCvdr6L5UtWfMPKSMqgfhXfTYViPDleQCkJ132mIS\nH28UoET0Y5wI8M6pMkWpSqW"
- "WcKPFGwyLInvHdxgnTAsutowkldA7qFwoRz4=\n-----END RSA PRIVATE KEY-----\n";
- // Sample CA certificate(used to sign the server certificate)
- std::string kCACertificate =
- "-----BEGIN "
- "CERTIFICATE-----"
- "\nMIIDBjCCAe6gAwIBAgIJAPyCrKRDl3SWMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNV\nBAMM"
- "DDEyNy4wLjAuMSBDQTAgFw0xOTA1MDYxOTMyMzZaGA8yMTE5MDQxMjE5MzIz\nNlowFzEVMB"
- "MGA1UEAwwMMTI3LjAuMC4xIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA"
- "xrNHoY5+"
- "JCgnyvEdG2dvvOaZ3sg6uhuF5Ssb5snyo9ixrxO5\nZkDGWwUqFO9PiYuO5ovNeq9LZtPG6s"
- "K8zsCS062ChZX/7tZHndf4MKCUDzv/"
- "LPHe\nnROoPi9n2FAiOPctY5hpgpIJDPI5Ofx0el2KPeFGeUO/"
- "W3yqnfol1ZqzZ2h3uErR\noHkgT2Ja4K+5gnPkr/"
- "RluJIu3AmWYw4eKi8i3+"
- "PoThGmCFvoGfcWvRoctgnOHYHE\n4bDRirXL9nGkZ5FMzOVDeoIAEAShOqJwL08VcY+Pg/"
- "qFQjzRrTmiKgm6QsHNnm0q\nzg70XaD88VJimiGYZOuJHNZpX8o0W+1Ls/"
- "NbawIDAQABo1MwUTAdBgNVHQ4EFgQU\nkW3hgFWYMpVUkq9AlzGlI3awTGEwHwYDVR0jBBgw"
- "FoAUkW3hgFWYMpVUkq9AlzGl\nI3awTGEwDwYDVR0TAQH/BAUwAwEB/"
- "zANBgkqhkiG9w0BAQsFAAOCAQEAZeMkILiG\neEcELWb8cktP3LzvS47O8hys9+"
- "6TFmftuO7kjDBd9YH2v8iQ7qCcUvMJ7bqL5RP1\nQssKfNOHZtw/"
- "MMcKE6E3nl4yQSKc8ymivvYSVu5SYtQCedcgfRLb5zvVxXw8JmCp\nGNS3/"
- "OlIYZAamh76GxkKSaV3tv0XZB6n3rUVQZShncFbMpyJRW0XWxReGWrhXv4s\nNxMeC1r07EE"
- "WIDecv8KKf1F8uT4UF48HnC0VBpXiOyDGvn35NiKp+"
- "Q5k7QV6jdCS\ngPRcnZhs6jiU0jnV8C9A1A+"
- "3pXSSPrAed7tvECOgHCfS10CLsLWsLuSjc93BE5Vt\nav7kmxSwrdvQ2A==\n-----END "
- "CERTIFICATE-----\n";
- std::string kIncorrectCertificate =
- "-----BEGIN "
- "CERTIFICATE-----\nMIIC/"
- "jCCAeagAwIBAgIJAIZjLucUID1mMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV\nBAMMCTEyNy4"
- "wLjAuMTAeFw0xOTA1MDYxNDA1MzdaFw0yOjA1MDZxNDA1MzdaMBQx\nEjAQBgNVBAMMCTEyN"
- "y4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBALfE5Qhc2mHTIux30l7"
- "eHFjFLdzYeXE8vcaXKodalCG8EkRxojDOfUv+y2DV\nJzHAMiGxMFAEcSz71k+"
- "jFZwhNG8PLY0b36ChnUsrGkOSJWq3OKUFrg8KxO9At9dL\nJsa+"
- "R0N0D1bMoPYdpCi3m0b0q2ITHe56qKuTLTrIPia+"
- "qXGEVD7EoEhU9tnwlcwE\npsUURMXCn2+FhHyqN9wjFkldmu4k8U3OJOK4385L+"
- "4RJoIV8dsYawAMAf+"
- "WuxyWq\niPQTPxr8q33ZZm6z0XrgsgxHYCCsryx8L9Ub9Zwu0mie7eL63rYdr86gULvnF1bY"
- "\ncOunKFc71rBYFalbD6YYsre733kCAwEAAaNTMFEwHQYDVR0OBBYEFKW9ByUNG84Z\nYiSc"
- "hUrB7KV9FinZMB8GA1UdIwQYMBaAFKW9ByUNG84ZYiSchUrB7KV9FinZMA8G\nA1UdEwEB/"
- "wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYROS1EL2qnrwmAsR6c\nqo8yrk8qzLKt4os"
- "41nv7QMUQFIO+QLPE8SbH4fK1YOMMUJ4ppARQBDaIIR3UEhp1\nZHT/"
- "wGjK9qxcuQ1EXLyHOY0rxS5q57dYGxOyQo4v6IoLVMZ1ij+RJGPYI/"
- "2fDXs0\nbDldeJyC1voHmG6lqTN5nLG7Y3j9j6rtSqJyRz5muaecQNiFPQOM2OTp0rC4VeAF"
- "\ndejmTmLhUFVuHMzLF+"
- "bpzsN76GnnQquJy2jexzFoWgbEfFVLKuyhTHQAalRb4ccq\nXCIx1hecNDYRY3Sc2Gzv5qxk"
- "kWF8zqltT/0d5tx0JwN3k5nP4SlaEldFvD6BELxy\nVkU=\n-----END "
- "CERTIFICATE-----\n";
-};
+ result_error = websocket_connection_->Disconnect();
-TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort),
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::BAD_STATE, result_error);
}
-TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
- kQuery + kFragment,
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer(kPath);
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
-}
+TEST_F(WebsocketNotSecureSessionConnectionTest, SUCCESS_SendData) {
+ auto message = CreateDefaultRawMessage();
-TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
- kQuery + kFragment,
- .certificate = "no cert",
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> ws_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = ws_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = ws_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- ws_session->Stop();
-}
+ auto error = websocket_connection_->SendData(message);
-TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::OK, error);
}
-TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + kPath,
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer((kPath + kQuery + kFragment));
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
-}
+TEST_F(WebsocketNotSecureSessionConnectionTest, UNSUCCESS_SendData_BAD_STATE) {
+ websocket_connection_->Run();
+ auto message = CreateDefaultRawMessage();
+
+ auto disconnect_error = websocket_connection_->Disconnect();
+
+ auto send_data_error = websocket_connection_->SendData(message);
-#ifdef ENABLE_SECURITY
-TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kCACertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer(kPath);
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+ ASSERT_EQ(TransportAdapter::Error::OK, disconnect_error);
+ ASSERT_EQ(TransportAdapter::Error::BAD_STATE, send_data_error);
}
-TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
- transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
- .certificate = kIncorrectCertificate,
- .enabled = true,
- .auth_token = "auth_token",
- .cloud_transport_type = "WSS",
- .hybrid_app_preference = "CLOUD"};
-
- // Start server
- StartWSSServer("/");
-
- // Start client
- InitWebsocketClient(properties, ws_client);
- std::shared_ptr<WebsocketClientConnection> wss_connection =
- ws_client.connection;
-
- // Check websocket connection
- TransportAdapter::Error ret_code = wss_connection->Start();
- EXPECT_EQ(TransportAdapter::FAIL, ret_code);
-
- // Stop client
- ret_code = wss_connection->Disconnect();
- EXPECT_EQ(TransportAdapter::OK, ret_code);
-
- // Stop server thread
- wss_session->Stop();
+TEST_F(WebsocketNotSecureSessionConnectionTest, DataReceive_SUCCESS) {
+ auto message = CreateDefaultRawMessage();
+
+ EXPECT_CALL(mock_transport_adapter_ctrl_,
+ DataReceiveDone(kDeviceUid_, kAppHandle, _))
+ .Times(1);
+
+ websocket_connection_->DataReceive(message);
}
-#endif // ENABLE_SECURITY
+
} // namespace transport_manager_test
} // namespace components
} // namespace test
diff --git a/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc b/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc
new file mode 100644
index 0000000000..88525ad29d
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_sample_client/websocket_sample_client.cc
@@ -0,0 +1,193 @@
+/*
+ * \file websocket_listener.h
+ * \brief WebSocketListener class header file.
+ *
+ * Copyright (c) 2020
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "transport_manager/websocket_server/websocket_sample_client.h"
+
+namespace transport_manager {
+namespace transport_adapter {
+
+template <>
+WSSampleClient<websocket::stream<ssl::stream<tcp::socket> > >::WSSampleClient(
+ const std::string& host,
+ const std::string& port,
+ const SecurityParams& params)
+ : resolver_(ioc_)
+ , ctx_(ssl::context::sslv23_client)
+ , ws_(nullptr)
+ , io_pool_(1)
+ , host_(host)
+ , port_(port)
+ , handshake_successful_(false) {
+ ctx_.set_verify_mode(ssl::context::verify_peer);
+ ctx_.load_verify_file(params.ca_cert_);
+ ctx_.use_certificate_chain_file(params.client_cert_);
+ ctx_.use_private_key_file(params.client_key_, boost::asio::ssl::context::pem);
+ ws_.reset(new WSS(ioc_, ctx_));
+}
+
+template <>
+WSSampleClient<WS>::WSSampleClient(const std::string& host,
+ const std::string& port)
+ : resolver_(ioc_)
+ , ctx_(ssl::context::sslv23_client)
+ , ws_(new WS(ioc_))
+ , host_(host)
+ , port_(port) {}
+
+template <typename Stream>
+bool WSSampleClient<Stream>::Run() {
+ boost::system::error_code ec;
+ ctx_.set_verify_mode(ssl::verify_none);
+
+ auto results = resolver_.resolve(host_, port_, ec);
+ if (ec) {
+ std::cout << "ErrorMessage: " + ec.message() << std::endl;
+ return false;
+ }
+
+ if (!Connect(results)) {
+ return false;
+ }
+
+ if (!Handshake(host_, "/")) {
+ return false;
+ }
+
+ ws_->async_read(buffer_,
+ std::bind(&WSSampleClient::OnRead,
+ this->shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2));
+ boost::asio::post(io_pool_, [&]() { ioc_.run(); });
+ return true;
+}
+
+template <typename Stream>
+void WSSampleClient<Stream>::OnRead(beast::error_code ec,
+ std::size_t bytes_transferred) {
+ boost::ignore_unused(bytes_transferred);
+}
+
+template <>
+bool WSSampleClient<WS>::Connect(tcp::resolver::results_type& results) {
+ boost::system::error_code ec;
+ boost::asio::connect(ws_->next_layer(), results.begin(), results.end(), ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+bool WSSampleClient<WSS>::Connect(tcp::resolver::results_type& results) {
+ boost::system::error_code ec;
+ boost::asio::connect(ws_->lowest_layer(), results.begin(), results.end(), ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+bool WSSampleClient<WS>::Handshake(const std::string& host,
+ const std::string& target) {
+ boost::system::error_code ec;
+ ws_->handshake(host, target, ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+ return true;
+}
+
+template <>
+void WSSampleClient<WS>::Stop() {
+ ioc_.stop();
+ ws_->lowest_layer().close();
+
+ io_pool_.stop();
+ io_pool_.join();
+}
+
+template <>
+bool WSSampleClient<WSS>::Handshake(const std::string& host,
+ const std::string& target) {
+ boost::system::error_code ec;
+
+ ws_->next_layer().handshake(ssl::stream_base::client, ec);
+ if (ec) {
+ std::cout << "ErrorMessage: " + ec.message() << std::endl;
+ return false;
+ }
+
+ ws_->handshake(host, target, ec);
+ if (ec) {
+ std::string str_err = "ErrorMessage: " + ec.message();
+ return false;
+ }
+
+ handshake_successful_ = true;
+ return true;
+}
+
+template <>
+void WSSampleClient<WSS>::Stop() {
+ ioc_.stop();
+ ws_->next_layer().next_layer().shutdown(
+ boost::asio::ip::tcp::socket::shutdown_both);
+ ws_->lowest_layer().close();
+
+ io_pool_.stop();
+ io_pool_.join();
+}
+
+template <>
+void WSSampleClient<WSS>::OnHandshakeTimeout() {
+ if (!handshake_successful_) {
+ Stop();
+ }
+}
+
+template <>
+bool WSSampleClient<WSS>::IsHandshakeSuccessful() const {
+ return handshake_successful_;
+}
+
+template class WSSampleClient<WS>;
+template class WSSampleClient<WSS>;
+} // namespace transport_adapter
+} // namespace transport_manager
diff --git a/src/components/transport_manager/test/websocket_server_listener_test.cc b/src/components/transport_manager/test/websocket_server_listener_test.cc
new file mode 100644
index 0000000000..7991c6f1cb
--- /dev/null
+++ b/src/components/transport_manager/test/websocket_server_listener_test.cc
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2020, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "transport_manager/mock_transport_manager_settings.h"
+#include "transport_manager/transport_adapter/mock_transport_adapter_controller.h"
+#include "transport_manager/websocket_server/websocket_device.h"
+#include "transport_manager/websocket_server/websocket_listener.h"
+#include "utils/timer.h"
+#include "utils/timer_task_impl.h"
+
+#include <thread>
+#include "transport_manager/websocket_server/websocket_sample_client.h"
+
+namespace test {
+namespace components {
+namespace transport_manager_test {
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnArg;
+using ::testing::ReturnPointee;
+using ::testing::ReturnRef;
+using namespace ::transport_manager;
+using namespace ::transport_manager::transport_adapter;
+
+namespace {
+const std::string kDefaultAddress = "127.0.0.1";
+const std::string kDefaultCertPath = "";
+const std::string kDefaultKeyPath = "";
+const std::string kDefaultCACertPath = "";
+const uint32_t kDefaultPort = 2021;
+const std::string kDefaultPortStr = "2021";
+const uint32_t kWrongPort = 1000;
+const std::string kCACertPath = "./test_certs/ca-cert.pem";
+const std::string kClientCertPath = "./test_certs/client-cert.pem";
+const std::string kClientKeyPath = "./test_certs/client-key.pem";
+const std::string kServerCert = "./test_certs/server-cert.pem";
+const std::string kServerKey = "./test_certs/server-key.pem";
+const std::string kCACert = "./test_certs/ca-cert.pem";
+const std::string kDefaultDeviceName = "Web Engine";
+const int kNumThreads = 2;
+} // namespace
+
+class WebSocketListenerTest : public ::testing::Test {
+ protected:
+ MockTransportAdapterController mock_ta_controller_;
+ MockTransportManagerSettings mock_tm_settings_;
+
+ public:
+ WebSocketListenerTest() {}
+ ~WebSocketListenerTest() {}
+
+ void SetUp() OVERRIDE {
+ ON_CALL(mock_tm_settings_, websocket_server_address())
+ .WillByDefault(ReturnRef(kDefaultAddress));
+ ON_CALL(mock_tm_settings_, websocket_server_port())
+ .WillByDefault(Return(kDefaultPort));
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kServerCert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kServerKey));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kCACert));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(true));
+ }
+
+ std::shared_ptr<WebSocketDevice> CreateDevice(const bool secure_connection) {
+ return std::make_shared<WebSocketDevice>(kDefaultDeviceName,
+ kDefaultDeviceName);
+ }
+};
+
+TEST_F(WebSocketListenerTest, StartListening_ClientConnect_SUCCESS) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCACertPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(false)));
+
+ ws_listener->StartListening();
+ EXPECT_TRUE(ws_client->Run());
+ ws_client->Stop();
+}
+
+TEST_F(WebSocketListenerTest, StartListening_ClientConnectSecure_SUCCESS) {
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const SecurityParams params{kCACertPath, kClientCertPath, kClientKeyPath};
+ const auto wss_client = std::make_shared<WSSampleClient<WSS> >(
+ kDefaultAddress, kDefaultPortStr, params);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(true)));
+
+ ws_listener->StartListening();
+ EXPECT_TRUE(wss_client->Run());
+ wss_client->Stop();
+}
+
+TEST_F(WebSocketListenerTest,
+ StartListening_ClientConnectSecureInvalidCert_FAIL) {
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const SecurityParams params{kCACertPath,
+ "./test_certs/invalid_cert.pem",
+ "./test_certs/invalid_key.pem"};
+ const auto wss_client = std::make_shared<WSSampleClient<WSS> >(
+ kDefaultAddress, kDefaultPortStr, params);
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(true)));
+ EXPECT_CALL(mock_ta_controller_, ConnectionAborted(_, _, _));
+
+ ws_listener->StartListening();
+ timer::Timer handshake_timer(
+ "HandshakeTimer",
+ new ::timer::TimerTaskImpl<WSSampleClient<WSS> >(
+ wss_client.get(), &WSSampleClient<WSS>::OnHandshakeTimeout));
+ handshake_timer.Start(3000, timer::kSingleShot);
+ wss_client->Run();
+ EXPECT_EQ(wss_client->IsHandshakeSuccessful(), false);
+}
+
+TEST_F(WebSocketListenerTest, StartListening_CertificateNotFound_Fail) {
+ const std::string server_cert = "./test_certs/server-cert.pem";
+ const std::string server_key = "./test_certs/server-key.pem";
+ const std::string ca_cert = "./not_valid_path/ca-cert.pem";
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(server_cert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(server_key));
+ ON_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillByDefault(ReturnRef(ca_cert));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_WrongConfig_FAIL) {
+ const std::string server_cert = "./test_certs/server-cert.pem";
+
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(server_cert));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_BindToTheServerAddress_FAIL) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+ EXPECT_CALL(mock_tm_settings_, websocket_server_port())
+ .WillOnce(Return(kWrongPort));
+
+ const auto ws_listener_ = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client_ =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ EXPECT_EQ(TransportAdapter::Error::FAIL, ws_listener_->StartListening());
+}
+
+TEST_F(WebSocketListenerTest, StartListening_AcceptorIsOpen_SUCCESS) {
+ ON_CALL(mock_tm_settings_, ws_server_cert_path())
+ .WillByDefault(ReturnRef(kDefaultCertPath));
+ ON_CALL(mock_tm_settings_, ws_server_key_path())
+ .WillByDefault(ReturnRef(kDefaultKeyPath));
+ ON_CALL(mock_tm_settings_, wss_server_supported())
+ .WillByDefault(Return(false));
+
+ EXPECT_CALL(mock_ta_controller_, ConnectDone(_, _));
+ EXPECT_CALL(mock_ta_controller_, ConnectionCreated(_, _, _));
+ EXPECT_CALL(mock_ta_controller_, GetWebEngineDevice())
+ .WillOnce(Return(CreateDevice(false)));
+
+ EXPECT_CALL(mock_tm_settings_, ws_server_ca_cert_path())
+ .WillOnce(ReturnRef(kDefaultCACertPath));
+
+ const auto ws_listener = std::make_shared<WebSocketListener>(
+ &mock_ta_controller_, mock_tm_settings_, kNumThreads);
+ const auto ws_client =
+ std::make_shared<WSSampleClient<WS> >(kDefaultAddress, kDefaultPortStr);
+
+ ws_listener->StartListening();
+ ws_client->Run();
+ EXPECT_EQ(TransportAdapter::Error::OK, ws_listener->StartListening());
+ ws_client->Stop();
+}
+
+} // namespace transport_manager_test
+} // namespace components
+} // namespace test