summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYevhenii Dementieiev (GitHub) <57259850+ydementieiev@users.noreply.github.com>2020-03-03 12:20:22 +0200
committerGitHub <noreply@github.com>2020-03-03 12:20:22 +0200
commit73adc9f21f92fbb144945d0790f87c46d11da7f0 (patch)
treedcc7c09f50ad08997c10e840df198c865b9e3368
parentece258838a44a5461d718c5eeae380ad11a3769b (diff)
parent546d496240502bd3d2c60881603959ff66ad87fb (diff)
downloadsdl_core-feature/fuel_info_related_vehicle_date.tar.gz
Merge pull request #3245 from smartdevicelink/impl/fuel_info_related_vehicle_datefeature/fuel_info_related_vehicle_date
Updated HMI and MOBILE api for refactoring fuel information
-rw-r--r--.github/CONTRIBUTING.md2
-rw-r--r--CMakeLists.txt19
-rw-r--r--Doxyfile3
-rw-r--r--README.md151
-rw-r--r--src/3rd_party/CMakeLists.txt57
-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/on_system_request_notification.cc15
-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.xml173
-rw-r--r--src/components/interfaces/MOBILE_API.xml155
-rw-r--r--src/components/interfaces/MOBILE_API.xsd1
-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.h73
-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/src/status.cc3
-rw-r--r--src/components/policy/policy_external/src/update_status_manager.cc3
-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.h75
-rw-r--r--src/components/policy/policy_regular/include/policy/status.h34
-rw-r--r--src/components/policy/policy_regular/include/policy/update_status_manager.h6
-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.cc61
-rw-r--r--src/components/policy/policy_regular/src/status.cc33
-rw-r--r--src/components/policy/policy_regular/src/update_status_manager.cc10
-rw-r--r--src/components/policy/policy_regular/test/policy_manager_impl_test.cc6
-rw-r--r--src/components/protocol_handler/src/protocol_handler_impl.cc3
-rw-r--r--src/components/transport_manager/CMakeLists.txt16
-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/tcp/tcp_device.h2
-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/tcp/tcp_client_listener.cc4
-rw-r--r--src/components/transport_manager/src/tcp/tcp_device.cc4
-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.cc34
-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
-rw-r--r--third_party.md13
138 files changed, 7666 insertions, 1367 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 672768add7..1da30fbf62 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -4,8 +4,8 @@ Third party contributions are essential for making SDL great. However, we do hav
## Environment
Currently supported:
-* Ubuntu Linux 14.04 with GCC 4.9.x
* Ubuntu Linux 16.04 with GCC 5.4.x
+* Ubuntu Linux 18.04 with GCC 7.3.x
* [C++11 standard](https://github.com/smartdevicelink/sdl_evolution/issues/132)
### Issues
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 351bfb4ab6..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)
@@ -52,6 +53,7 @@ option(ENABLE_GCOV "gcov code coverage feature" OFF)
option(ENABLE_SANITIZE "Sanitize tool" OFF)
option(ENABLE_SECURITY "Security Ford protocol protection" ON)
option(ENABLE_HMI_PTU_DECRYPTION "Policy table update parsed by hmi" ON)
+option(ENABLE_IAP2EMULATION "IAP2 emulation via tcp" OFF)
option(USE_COTIRE "Use Cotire to speed up build (currently only for commands tests)" ON)
option(USE_GOLD_LD "Use gold linker intead of GNU linker" ON)
option(USE_CCACHE "Turn on ccache usage" ON)
@@ -208,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 .
@@ -322,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")
@@ -422,6 +436,11 @@ if(ENABLE_HMI_PTU_DECRYPTION)
message(STATUS "HMI PTU decription enabled")
endif()
+if(ENABLE_IAP2EMULATION)
+ add_definitions(-DENABLE_IAP2EMULATION)
+ message(STATUS "IAP2 emulation enabled")
+endif()
+
set(RTLIB rt)
if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(RTLIB )
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/README.md b/README.md
index 6166a51344..9b98c6267a 100644
--- a/README.md
+++ b/README.md
@@ -1,149 +1,50 @@
[![Slack Status](http://sdlslack.herokuapp.com/badge.svg)](http://slack.smartdevicelink.com)
-[![codecov.io](https://codecov.io/github/smartdevicelink/sdl_core/coverage.svg?branch=develop)](https://codecov.io/github/smartdevicelink/sdl_core?branch=develop)
[![Build Status](http://opensdl-jenkins.luxoft.com:8080/view/develop/job/develop_nightly_coverage/badge/icon)](http://opensdl-jenkins.luxoft.com:8080/view/develop/job/develop_nightly_coverage/)
# SmartDeviceLink (SDL)
SmartDeviceLink (SDL) is a standard set of protocols and messages that connect applications on a smartphone to a vehicle head unit. This messaging enables a consumer to interact with their application using common in-vehicle interfaces such as a touch screen display, embedded voice recognition, steering wheel controls and various vehicle knobs and buttons. There are three main components that make up the SDL ecosystem.
- * The [Core](https://github.com/smartdevicelink/sdl_core) component is the software which Vehicle Manufacturers (OEMs) implement in their vehicle head units. Integrating this component into their head unit and HMI based on a set of guidelines and templates enables access to various smartphone applications.
+ * The [Core](https://github.com/smartdevicelink/sdl_core) component is the software which Vehicle Manufacturers (OEMs) include in their vehicle head units. Integrating this component into their head unit and HMI based on a set of guidelines and templates enables access to various smartphone applications.
* The optional [SDL Server](https://github.com/smartdevicelink/sdl_server) can be used by Vehicle OEMs to update application policies and gather usage information for connected applications.
* The [iOS](https://github.com/smartdevicelink/sdl_ios) and [Android](https://github.com/smartdevicelink/sdl_android) libraries are implemented by app developers into their applications to enable command and control via the connected head unit.
+## SDL Core
+
+The Core component of SDL runs on a vehicle's computing system (head unit). Core’s primary responsibility is to route messages between connected smartphone applications and the vehicle HMI. It can connect a smartphone to a vehicle's head unit via a variety of transport protocols such as Bluetooth, USB, Android AOA, and TCP. Once a connection is established, Core discovers compatible applications and displays them to the driver for interaction via voice or display. The Core component is configured to follow a set of policies defined in its local policy database and updated by a [policy server](https://www.github.com/smartdevicelink/sdl_server). The messaging between a connected application and SDL Core is defined by the [Mobile API](https://github.com/smartdevicelink/sdl_core/blob/master/src/components/interfaces/MOBILE_API.xml) and the messaging between SDL Core and the vehicle is defined by the [HMI API](https://github.com/smartdevicelink/sdl_core/blob/master/src/components/interfaces/HMI_API.xml).
+
Pull Requests Welcome!
-## Documentation
+## Environment
+Currently supported:
+* Ubuntu Linux 16.04 with GCC 5.4.x
+* Ubuntu Linux 18.04 with GCC 7.3.x
+* [C++11 standard](https://github.com/smartdevicelink/sdl_evolution/issues/132)
- * [Software Architecture Document](https://smartdevicelink.com/en/docs/sdl-core/master/software-architecture-document/table-of-contents/)
- * [Transport Manager Programming Guide](https://smartdevicelink.com/en/guides/core/transport-manager-programming/)
- * [Software Detailed Design](https://app.box.com/s/ohgrvemtx39f8hfea1ab676xxrzvyx1y)
- * [Integration Guidelines](https://smartdevicelink.com/en/docs/hmi/master/overview/)
- * [Evolution Proposals versus Issues](https://github.com/smartdevicelink/sdl_evolution/blob/master/proposals_versus_issues.md)
+## Getting Started
+See the [Getting Started](https://smartdevicelink.com/en/guides/core/getting-started/) guide in the developer portal for instructions on how to build and start SDL Core.
-## SDL Core
+## Connect a Web HMI
+After setting up SDL Core, you will need to connect it to an external HMI. The HMI component of SDL needs to be developed separately from this project, and should be tailored to your specific head unit. Several sample browser-based HMIs are available for testing purposes:
-The Core component of SDL runs on a vehicle's computing system (head unit). Core’s primary responsibility is to pass messages between connected smartphone applications and the vehicle HMI, and pass notifications from the vehicle to those applications. It can connect a smartphone to a vehicle's head unit via a variety of transport protocols such as Bluetooth, USB, Android AOA, and TCP. Once a connection is established, Core discovers compatible applications and displays them to the driver for interaction via voice or display. The core component is implemented into the vehicle HMI based on the integration guidelines above. The core component is configured to follow a set of policies defined in a policy database and updated by a [policy server](https://www.github.com/smartdevicelink/sdl_server). The messaging between a connected application and core is defined by the [Mobile API](https://github.com/smartdevicelink/sdl_core/blob/master/src/components/interfaces/MOBILE_API.xml) and the messaging between sdl core and the vehicle is defined by the [HMI API](https://github.com/smartdevicelink/sdl_core/blob/master/src/components/interfaces/HMI_API.xml).
-
-## Project Status
-We're ramping up our efforts to get SmartDeviceLink developed and maintained directly in the open. For the Mobile libraries, we're expecting better integration soon, SDL Core is slightly more complicated. We are currently working on generating documentation, creating a developer portal, an open forum, Mobile validation, and everything else that we've been asked for to renew the community's interest in this project. From a technical standpoint, SDL is stable, and the most work is being put into making it a more robust solution for app connectivity. We are, however, definitely looking for and interested in other people and company's contributions to SDL whether it be feature based, bug fixes, healthy conversation, or even just suggestions for improvement.
-
-# Getting Started
-A quick guide to installing, configuring, and running an instance of the SDL Core on a linux OS.
-
- 1. Clone this repository
- 2. Create a folder for your build outside of the source folder and run `cmake {path_to_sdl_core_source_folder}` from the build folder you created
- 3. If there are any dependency issues, install missing dependencies
- 4. Run the following commands to compile and install smartdevicelink
-
-
-
-```
-%make
-%make install
-```
-
-## Start SDL Core
-Once SDL Core is compiled and installed you can start it from the executable in the bin folder
-
-```
-%cd bin/
-%./start.sh
-```
-
-## Start WEB HMI
-Web HMI is separated from SDL Core and located in another repository. So to make it workable please do next steps.
-
- 1. Clone http://github.com/smartdevicelink/sdl_hmi.git
- 2. Follow the instruction from readme file in sdl_hmi repository.
-
-
-## A quick note about dependencies
-The dependencies for SDL Core vary based on the configuration. You can change SDL Core's configuration in the top level CMakeLists.txt. We have defaulted this file to a configuration which we believe is common for people who are interested in getting up and running quickly, generally on a Linux VM.
-
-### Dependencies list
-
-| Flag | Description | Dependencies |
-|------|-------------|--------------|
-|Web HMI|Use HTML5 HMI|chromium-browser|
-|EXTENDED_MEDIA_MODE|Support Video and Audio Streaming|Opengl es2, gstreamer1.0*|
-|Bluetooth|Enable bluetooth transport adapter|libbluetooth3, libbluetooth-dev, bluez-tools|
-|USB|Enable USB transport adapter|libusb-dev|
-|Testing framework|Needed to support running unit tests|libgtest-dev|
-|Cmake|Needed to configure SDL prior to compilation|cmake|
-
-#### Sample Policy Manager
-The included sample policy manager (for use with `EXTERNAL_PROPRIETARY` policy mode) requires the following packages:
- - python-pip
- - python-dev
-
-### Known Dependency Issues
- * log4cxx - We know that the version of log4cxx on a linux machine can conflict with the one used, which is why it is provided in the repository. To avoid the conflict, we recommend removing liblog4cxx*.
- * cmake - on some versions of linux, the included cmake package doesn't have the right version. If apt-get is your package manager, you can find the correct version using
-```
-sudo apt-get install cmake
-sudo add-apt-repository ppa:kalakris/cmake
-sudo apt-get update
-sudo apt-get upgrade
-```
-
-## Required RPCs
-There are several RPCs that are "required" to be implemented in order for SDL to work across vehicle manufacturers and applications, listed below. The RPC specification can be found in the [Mobile API Spec](src/components/interfaces/MOBILE_API.xml).
-
- * RegisterAppInterface
- * UnregisterAppInterface
- * SetGlobalProperties
- * ResetGlobalProperties
- * AddCommand
- * DeleteCommand
- * AddSubMenu
- * DeleteSubMenu
- * ShowAppMenu
- * CreateInteractionChoiceSet
- * PerformInteraction
- * DeleteInteractionChoiceSet
- * Alert
- * Show
- * SetMediaClockTimer
- * SubscribeButton
- * UnsubscribeButton
- * ChangeRegistration
- * GenericResponse
- * SystemRequest
- * OnHMIStatus
- * OnAppInterfaceUnregistered
- * OnButtonEvent
- * OnButtonPress
- * OnCommand
- * OnDriverDistraction
- * OnPermissionsChange
- * OnLanguageChange
- * OnSystemRequest
- * Speak
+ 1. The [Generic HMI](https://github.com/smartdevicelink/generic_hmi) (preferred) is a reference implementation for an SDL-connected HMI, including examples of many of the UI elements and templates available to SDL applications.
+ 2. The [SDL HMI](https://github.com/smartdevicelink/sdl_hmi) emulates a full infotainment system which includes a simplified SDL component.
-## Frequently Asked Questions
+See the [HMI Development Guide](https://smartdevicelink.com/en/guides/core/integrating-your-hmi/sdl-core-and-hmi-communication/) for more information on building your own HMI.
-If you have any questions regarding the setup of SDL Core or regarding the integration of SDL into an infotainment system, first visit our [SDL Core FAQ](https://smartdevicelink.com/en/guides/core/faq/). If you still have questions, you can post a question in the `core-help` channel of our Slack group (sign up [here](http://slack.smartdevicelink.com/))
+## Manticore
+If you are just developing an SDL-connected application and simply want an environment to test it in, it is not necessary to build SDL Core from scratch. You can use our [Manticore](https://smartdevicelink.com/resources/manticore/) project first, which creates a testing environment in the cloud using SDL Core and the Generic HMI.
-## Test Coverage
-### Used technologies
- * GCOV - test coverage program.
- * LCOV - graphical front-end for GCC's coverage testing tool for gcov.
- * codecov.io - service for assembling code coverage and representing it in a clear for reading form.
+## Frequently Asked Questions
-### Excluded folders
-_We test only sources written by us and we don`t need to test external sources(open source libraries)._
- * '/usr/\*' - local libraries shouldn`t be covered by tests.
- * '\*/test/\*' - we don`t need to cover tests.
- * '\*/src/3rd\*' - open source libraries shouldn`t be covered by tests.
+If you have any questions regarding the setup of SDL Core or regarding the integration of SDL into a head unit, first visit our [SDL Core FAQ](https://smartdevicelink.com/en/guides/core/faq/). If you still have questions, you can post a question in the `core-help` channel of our Slack group (sign up [here](http://slack.smartdevicelink.com/)).
-### Current test coverage
-You can find it in [Coverage report](https://codecov.io/gh/smartdevicelink/sdl_core/branch/develop)
+## Additional References
-### How to get Test Coverage locally
- 1. Build project with enabled flag _-DBUILD_TESTS=on_
- 2. Execute command 'make test'
- 3. Execute './tools/Utils/collect_coverage.sh <path_to_build_directory>'
+ * [Transport Manager Programming Guide](https://smartdevicelink.com/en/guides/core/transport-manager-programming/)
+ * [HMI API Documentation](https://smartdevicelink.com/en/docs/hmi/master/overview/)
+ * [Evolution Proposals versus Issues](https://github.com/smartdevicelink/sdl_evolution/blob/master/proposals_versus_issues.md)
## Contributions
-Conversation regarding the design and development of SmartDeviceLink technology should be directed at the [GENIVI mailing list](https://lists.genivi.org/mailman/listinfo/genivi-smartdevicelink), which anyone can join. Public conference calls regarding the SmartDeviceLink technology will be announced to the GENIVI mailing list, we expect to have conversations every other week. We also encourage interested parties to write issues against our software, and submit pull requests right here in the GitHub repository.
+Conversation regarding the design and development of SmartDeviceLink technology is managed via the [SDL Evolution Process](https://github.com/smartdevicelink/sdl_evolution/blob/master/process.md). We also encourage interested parties to write issues and submit pull requests right here in the GitHub repository. If you choose to do so, please read our [Contributing Guide](https://github.com/smartdevicelink/sdl_core/blob/master/.github/CONTRIBUTING.md) beforehand.
diff --git a/src/3rd_party/CMakeLists.txt b/src/3rd_party/CMakeLists.txt
index 951c437e59..4415a1bd7b 100644
--- a/src/3rd_party/CMakeLists.txt
+++ b/src/3rd_party/CMakeLists.txt
@@ -41,9 +41,9 @@ endif()
if(FORCE_3RD_PARTY)
if(NO_REBUILD_3RD_PARTY)
- message(FATAL_ERROR "Please don't turn on both FORCE_3RD_PARTY and NO_REBUILD_3RD_PARTY at the same time.")
+ message(FATAL_ERROR "Please don't turn on both FORCE_3RD_PARTY and NO_REBUILD_3RD_PARTY at the same time.")
else()
- set(FORCE_3RD_PARTY_LOGGER ON)
+ set(FORCE_3RD_PARTY_LOGGER ON)
endif()
endif()
@@ -55,13 +55,18 @@ if(ENABLE_LOG)
if(NO_REBUILD_3RD_PARTY_LOGGER)
message(STATUS "Not rebuilding logger.")
else()
+ set(LOGGER_INSTALL_COMMAND make install)
+ if (${USE_DEFAULT_3RD_PARTY_PATH} STREQUAL "true")
+ set(LOGGER_INSTALL_COMMAND sudo make install)
+ endif()
if(FORCE_3RD_PARTY_LOGGER)
message(STATUS "Force to rebuild logger.")
#build logger
add_custom_target(3rd_party_logger
make
- WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}
+ DEPENDS apr-util
+ WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake
)
#install logger
@@ -71,12 +76,15 @@ if(ENABLE_LOG)
COMMAND /bin/bash -c \"USE_DEFAULT_3RD_PARTY_PATH=${USE_DEFAULT_3RD_PARTY_PATH}\;
if [ \\$$USE_DEFAULT_3RD_PARTY_PATH == "true" ]\; then
sudo -k \;
- sudo make install\;
- else
- make install\;
- fi\"
+ fi\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-util-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\"
DEPENDS 3rd_party_logger
- WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}
+ WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake
)
else()
#build logger
@@ -94,17 +102,18 @@ if(ENABLE_LOG)
fi\;
if [ \\$$VAR1 != \\$$VAR2 ]\; then
echo " Need to rebuild logger. " \;
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake\;
make\;
else
echo " Logger is actual. " \;
fi\;
else
echo " Need to build logger. " \;
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake\;
make\;
fi\"
- WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}
+ DEPENDS apr-util
+ WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-build
)
#install logger
@@ -125,27 +134,29 @@ if(ENABLE_LOG)
if [ \\$$VAR1 != \\$$VAR2 ]\; then
USE_DEFAULT_3RD_PARTY_PATH=${USE_DEFAULT_3RD_PARTY_PATH}\;
if [ \\$$USE_DEFAULT_3RD_PARTY_PATH == "true" ]\; then
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
sudo -k \;
- sudo make install\;
- else
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
- make install\;
fi\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-util-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
fi\;
else
USE_DEFAULT_3RD_PARTY_PATH=${USE_DEFAULT_3RD_PARTY_PATH}\;
if [ \\$$USE_DEFAULT_3RD_PARTY_PATH == "true" ]\; then
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
sudo -k \;
- sudo make install\;
- else
- cd ${3RD_PARTY_BINARY_DIRECTORY}\;
- make install\;
fi\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apr-util-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
+ cd ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-cmake\;
+ ${LOGGER_INSTALL_COMMAND}\;
fi\"
DEPENDS 3rd_party_logger
- WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}
+ WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}/apache-log4cxx-build
)
endif()
@@ -238,8 +249,8 @@ add_custom_target(Boost) # empty target, Boost is already installed
endif()
add_custom_target(install-3rd_party
- DEPENDS ${install-3rd_party_logger_var}
DEPENDS libbson
DEPENDS Boost
+ DEPENDS ${install-3rd_party_logger_var}
WORKING_DIRECTORY ${3RD_PARTY_BINARY_DIRECTORY}
)
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/on_system_request_notification.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_request_notification.cc
index fc99bb323c..b340055c50 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_request_notification.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/on_system_request_notification.cc
@@ -126,9 +126,7 @@ void OnSystemRequestNotification::Run() {
if (mobile_apis::RequestType::OEM_SPECIFIC == request_type) {
(*message_)[strings::params][strings::binary_data] = binary_data;
- }
-
- if (mobile_apis::RequestType::PROPRIETARY == request_type) {
+ } else if (mobile_apis::RequestType::PROPRIETARY == request_type) {
/* According to requirements:
"If the requestType = PROPRIETARY, add to mobile API fileType = JSON
If the requestType = HTTP, add to mobile API fileType = BINARY"
@@ -144,14 +142,19 @@ void OnSystemRequestNotification::Run() {
#endif // PROPRIETARY_MODE
(*message_)[strings::msg_params][strings::file_type] = FileType::JSON;
- }
-
- if (mobile_apis::RequestType::HTTP == request_type) {
+ } else if (mobile_apis::RequestType::HTTP == request_type) {
(*message_)[strings::msg_params][strings::file_type] = FileType::BINARY;
if ((*message_)[strings::msg_params].keyExists(strings::url)) {
(*message_)[strings::msg_params][strings::timeout] =
policy_handler.TimeoutExchangeSec();
}
+ } else if (mobile_apis::RequestType::LOCK_SCREEN_ICON_URL == request_type) {
+ if (!(*message_)[strings::msg_params].keyExists(strings::url) ||
+ (*message_)[strings::msg_params][strings::url].empty()) {
+ LOG4CXX_ERROR(logger_,
+ "discarding LOCK_SCREEN_ICON_URL request without URL");
+ return;
+ }
}
SendNotification();
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..f4a5b17045 100644
--- a/src/components/interfaces/HMI_API.xml
+++ b/src/components/interfaces/HMI_API.xml
@@ -79,6 +79,12 @@
</element>
</enum>
+<enum name="CapacityUnit">
+ <element name="LITERS" />
+ <element name="KILOWATTHOURS" />
+ <element name="KILOGRAMS" />
+</enum>
+
<enum name="PredefinedWindows">
<element name="DEFAULT_WINDOW" value="0">
<description>The default window is a main window pre-created on behalf of the app.</description>
@@ -95,6 +101,7 @@
<element name="USB_AOA"/>
<element name="WIFI"/>
<element name="CLOUD_WEBSOCKET"/>
+ <element name="WEBENGINE_WEBSOCKET"/>
</enum>
<enum name="ButtonName">
@@ -855,14 +862,6 @@
</element>
</enum>
-<struct name="FuelRange">
- <param name="type" type="Common.FuelType" mandatory="false"/>
- <param name="range" type="Float" minvalue="0" maxvalue="10000" mandatory="false">
- <description>
- The estimate range in KM the vehicle can travel based on fuel level and consumption.
- </description>
- </param>
-</struct>
<enum name="ComponentVolumeStatus">
<description>The volume status of a vehicle component.</description>
@@ -886,6 +885,27 @@
</element>
</enum>
+<struct name="FuelRange">
+ <param name="type" type="Common.FuelType" mandatory="false"/>
+ <param name="range" type="Float" minvalue="0" maxvalue="10000" mandatory="false">
+ <description>
+ The estimate range in KM the vehicle can travel based on fuel level and consumption.
+ </description>
+ </param>
+ <param name="level" type="Float" minvalue="-6" maxvalue="1000000" mandatory="false">
+ <description>The relative remaining capacity of this fuel type (percentage).</description>
+ </param>
+ <param name="levelState" type="ComponentVolumeStatus" mandatory="false">
+ <description>The fuel level state</description>
+ </param>
+ <param name="capacity" type="Float" minvalue="0" maxvalue="1000000" mandatory="false">
+ <description>The absolute capacity of this fuel type.</description>
+ </param>
+ <param name="capacityUnit" type="Common.CapacityUnit" mandatory="false">
+ <description>The unit of the capacity of this fuel type such as liters for gasoline or kWh for batteries.</description>
+ </param>
+</struct>
+
<enum name="TPMS">
<element name="UNKNOWN">
<description>If set the status of the tire is not known.</description>
@@ -4122,6 +4142,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 +4667,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">
@@ -5920,7 +6042,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6013,7 +6138,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Common.VehicleDataResult" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Common.VehicleDataResult" mandatory="false">
<description>The external temperature in degrees celsius.</description>
@@ -6112,7 +6240,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius.</description>
@@ -6205,7 +6336,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Common.VehicleDataResult" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Common.VehicleDataResult" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6299,7 +6433,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6395,7 +6532,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Common.FuelRange" minsize="0" maxsize="100" array="true" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Float" minvalue="-40" maxvalue="100" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6492,7 +6632,10 @@
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Common.FuelRange" minsize="0" maxsize="100" array="true" mandatory="false">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Float" minvalue="-40" maxvalue="100" mandatory="false">
<description>The external temperature in degrees celsius</description>
diff --git a/src/components/interfaces/MOBILE_API.xml b/src/components/interfaces/MOBILE_API.xml
index 2a09cc6b57..947105882a 100644
--- a/src/components/interfaces/MOBILE_API.xml
+++ b/src/components/interfaces/MOBILE_API.xml
@@ -540,8 +540,8 @@
</element>
<element name="VEHICLEDATA_SPEED" />
<element name="VEHICLEDATA_RPM" />
- <element name="VEHICLEDATA_FUELLEVEL" />
- <element name="VEHICLEDATA_FUELLEVEL_STATE" />
+ <element name="VEHICLEDATA_FUELLEVEL" until="6.0"/>
+ <element name="VEHICLEDATA_FUELLEVEL_STATE" until="6.0"/>
<element name="VEHICLEDATA_FUELCONSUMPTION" />
<element name="VEHICLEDATA_EXTERNTEMP" />
<element name="VEHICLEDATA_VIN" />
@@ -578,6 +578,12 @@
<element name="BOTH" />
</enum>
+ <enum name="CapacityUnit" since="6.0">
+ <element name="LITERS" />
+ <element name="KILOWATTHOURS" />
+ <element name="KILOGRAMS" />
+ </enum>
+
<struct name="CloudAppProperties" since="5.1">
<param name="nicknames" type="String" minlength="0" maxlength="100" array="true" minsize="0" maxsize="100" mandatory="false">
<description>An array of app names a cloud app is allowed to register with. If included in a SetCloudAppProperties request, this value will overwrite the existing "nicknames" field in the app policies section of the policy table.</description>
@@ -1299,6 +1305,18 @@
The estimate range in KM the vehicle can travel based on fuel level and consumption.
</description>
</param>
+ <param name="level" type="Float" minvalue="-6" maxvalue="1000000" mandatory="false" since="6.0">
+ <description>The relative remaining capacity of this fuel type (percentage).</description>
+ </param>
+ <param name="levelState" type="ComponentVolumeStatus" mandatory="false" since="6.0">
+ <description>The fuel level state</description>
+ </param>
+ <param name="capacity" type="Float" minvalue="0" maxvalue="1000000" mandatory="false" since="6.0">
+ <description>The absolute capacity of this fuel type.</description>
+ </param>
+ <param name="capacityUnit" type="CapacityUnit" mandatory="false" since="6.0">
+ <description>The unit of the capacity of this fuel type such as liters for gasoline or kWh for batteries.</description>
+ </param>
</struct>
<enum name="ElectronicParkBrakeStatus" since="5.0">
@@ -5829,17 +5847,26 @@
<param name="rpm" type="Boolean" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="Boolean" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="Boolean" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="Boolean" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -5942,17 +5969,26 @@
<param name="rpm" type="VehicleDataResult" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="VehicleDataResult" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="VehicleDataResult" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="VehicleDataResult" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="VehicleDataResult" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="VehicleDataResult" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="VehicleDataResult" mandatory="false">
<description>The external temperature in degrees celsius.</description>
@@ -6034,17 +6070,26 @@
<param name="rpm" type="Boolean" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="Boolean" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="Boolean" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="Boolean" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius.</description>
@@ -6146,17 +6191,26 @@
<param name="rpm" type="VehicleDataResult" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="VehicleDataResult" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="VehicleDataResult" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="VehicleDataResult" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="VehicleDataResult" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="VehicleDataResult" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="VehicleDataResult" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="VehicleDataResult" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6238,17 +6292,26 @@
<param name="rpm" type="Boolean" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="Boolean" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="Boolean" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="Boolean" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="Boolean" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="Boolean" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Boolean" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -6354,17 +6417,26 @@
<param name="rpm" type="Integer" minvalue="0" maxvalue="20000" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="Float" minvalue="0" maxvalue="25575" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="FuelRange" minsize="0" maxsize="100" array="true" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Float" minvalue="-40" maxvalue="100" mandatory="false">
<description>The external temperature in degrees celsius</description>
@@ -8052,17 +8124,26 @@
<param name="rpm" type="Integer" minvalue="0" maxvalue="20000" mandatory="false">
<description>The number of revolutions per minute of the engine</description>
</param>
- <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false">
- <description>The fuel level in the tank (percentage)</description>
+ <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level in the tank (percentage). This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel" type="Float" minvalue="-6" maxvalue="106" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
- <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false">
- <description>The fuel level state</description>
+ <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false" deprecated="true" since="6.0">
+ <description>The fuel level state. This parameter is deprecated starting RPC Spec 6.0.x, please see fuelRange.</description>
+ <history>
+ <param name="fuelLevel_State" type="ComponentVolumeStatus" mandatory="false" since="1.0" until="6.0"/>
+ </history>
</param>
<param name="instantFuelConsumption" type="Float" minvalue="0" maxvalue="25575" mandatory="false">
<description>The instantaneous fuel consumption in microlitres</description>
</param>
<param name="fuelRange" type="FuelRange" minsize="0" maxsize="100" array="true" mandatory="false" since="5.0">
- <description>The estimate range in KM the vehicle can travel based on fuel level and consumption</description>
+ <description>
+ The fuel type, estimated range in KM, fuel level/capacity and fuel level state for the vehicle.
+ See struct FuelRange for details.
+ </description>
</param>
<param name="externalTemperature" type="Float" minvalue="-40" maxvalue="100" mandatory="false">
<description>The external temperature in degrees celsius</description>
diff --git a/src/components/interfaces/MOBILE_API.xsd b/src/components/interfaces/MOBILE_API.xsd
index f1b96b3f92..71d37a7955 100644
--- a/src/components/interfaces/MOBILE_API.xsd
+++ b/src/components/interfaces/MOBILE_API.xsd
@@ -32,6 +32,7 @@
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="optional"/>
<xs:attribute type="xs:float" name="since" use="optional"/>
+ <xs:attribute type="xs:float" name="until" use="optional"/>
<xs:attribute type="xs:string" name="internal_name" use="optional"/>
<xs:attribute type="xs:int" name="value" use="optional"/>
<xs:attribute type="xs:string" name="rootscreen" use="optional"/>
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 ee2d806ba5..7e8abd5989 100644
--- a/src/components/policy/policy_external/include/policy/policy_types.h
+++ b/src/components/policy/policy_external/include/policy/policy_types.h
@@ -75,7 +75,8 @@ enum PolicyTableStatus {
StatusUpToDate = 0,
StatusUpdatePending,
StatusUpdateRequired,
- StatusUnknown
+ StatusUnknown,
+ StatusProcessingSnapshot
};
// Code generator uses String class name, so this typedef was renamed to PTSring
@@ -231,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("");
}
}
};
@@ -451,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;
};
/**
@@ -516,6 +522,7 @@ enum PermissionsCheckResult {
RESULT_REQUEST_TYPE_CHANGED,
RESULT_REQUEST_SUBTYPE_CHANGED,
RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED,
+ RESULT_APP_PROPERTIES_CHANGED
};
/**
@@ -538,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/src/status.cc b/src/components/policy/policy_external/src/status.cc
index 687bea1c3f..f605a51a98 100644
--- a/src/components/policy/policy_external/src/status.cc
+++ b/src/components/policy/policy_external/src/status.cc
@@ -83,7 +83,8 @@ bool policy::UpdateNeededStatus::IsUpdateRequired() const {
}
policy::UpdatePendingStatus::UpdatePendingStatus()
- : Status(kUpdateNeeded, policy::PolicyTableStatus::StatusUpdatePending) {}
+ : Status(kUpdateNeeded,
+ policy::PolicyTableStatus::StatusProcessingSnapshot) {}
void policy::UpdatePendingStatus::ProcessEvent(
policy::UpdateStatusManager* manager, policy::UpdateEvent event) {
diff --git a/src/components/policy/policy_external/src/update_status_manager.cc b/src/components/policy/policy_external/src/update_status_manager.cc
index 3653983c8f..cfbd2fe32b 100644
--- a/src/components/policy/policy_external/src/update_status_manager.cc
+++ b/src/components/policy/policy_external/src/update_status_manager.cc
@@ -217,8 +217,7 @@ void UpdateStatusManager::DoTransition() {
next_status_.reset();
const bool is_update_pending =
- (policy::kUpdateNeeded == current_status_->get_status_string() &&
- policy::StatusUpdatePending == current_status_->get_status());
+ policy::StatusProcessingSnapshot == current_status_->get_status();
if (last_processed_event_ != kScheduleManualUpdate && !is_update_pending) {
listener_->OnUpdateStatusChanged(current_status_->get_status_string());
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 9fddb9761b..7f95d9132b 100644
--- a/src/components/policy/policy_regular/include/policy/policy_types.h
+++ b/src/components/policy/policy_regular/include/policy/policy_types.h
@@ -75,7 +75,8 @@ enum PolicyTableStatus {
StatusUpToDate = 0,
StatusUpdatePending,
StatusUpdateRequired,
- StatusUnknown
+ StatusUnknown,
+ StatusProcessingSnapshot
};
enum class PTUIterationType { DefaultIteration = 0, RetryIteration };
@@ -233,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("");
}
}
};
@@ -443,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;
};
/**
@@ -507,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
};
/**
@@ -523,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/include/policy/status.h b/src/components/policy/policy_regular/include/policy/status.h
index 8fd3ff559e..4d8bc47dae 100644
--- a/src/components/policy/policy_regular/include/policy/status.h
+++ b/src/components/policy/policy_regular/include/policy/status.h
@@ -52,6 +52,7 @@ enum UpdateEvent {
kOnResetPolicyTableRequireUpdate,
kOnResetPolicyTableNoUpdate,
kScheduleUpdate,
+ kPendingUpdate,
kScheduleManualUpdate,
kOnResetRetrySequence,
kNoEvent
@@ -118,6 +119,39 @@ class Status {
};
/**
+ * @brief The UpdatePendingStatus class represents cases when SDL knows that an
+ * update is required but before the snapshot is sent to the HMI
+ */
+class UpdatePendingStatus : public Status {
+ public:
+ /**
+ * @brief Constructor
+ */
+ UpdatePendingStatus();
+
+ /**
+ * @brief Process event by setting next status in case event can affect
+ * current status or ignores the event
+ * @param manager Status manager pointer
+ * @param event Event which needs to be processed
+ */
+ void ProcessEvent(UpdateStatusManagerInterface* manager,
+ UpdateEvent event) OVERRIDE;
+
+ /**
+ * @brief Check whether update is required in terms of status
+ * @return True if update is required, otherwise - false
+ */
+ bool IsUpdateRequired() const OVERRIDE;
+
+ /**
+ * @brief Check whether update is pending in terms of status
+ * @return True if update is pending, otherwise - false
+ */
+ bool IsUpdatePending() const OVERRIDE;
+};
+
+/**
* @brief The UpToDateStatus class represents 'up-to-date' status
*/
class UpToDateStatus : public Status {
diff --git a/src/components/policy/policy_regular/include/policy/update_status_manager.h b/src/components/policy/policy_regular/include/policy/update_status_manager.h
index 0c79bf0ba4..fb679ac10b 100644
--- a/src/components/policy/policy_regular/include/policy/update_status_manager.h
+++ b/src/components/policy/policy_regular/include/policy/update_status_manager.h
@@ -149,6 +149,12 @@ class UpdateStatusManager : public UpdateStatusManagerInterface {
void ScheduleUpdate();
/**
+ * @brief PendingUpdate will change state from Update_Needed
+ * to Update_Pending
+ */
+ void PendingUpdate();
+
+ /**
* @brief ScheduleUpdate allows to schedule next update.
* It will change state to Update_Needed, that's is
* and will not send any notifications about updating to HMI
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 22205763a9..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();
}
@@ -650,6 +665,7 @@ void PolicyManagerImpl::StartPTExchange() {
}
if (update_status_manager_.IsUpdateRequired()) {
+ update_status_manager_.PendingUpdate();
if (RequestPTUpdate(PTUIterationType::DefaultIteration) &&
!timer_retry_sequence_.is_running()) {
// Start retry sequency
@@ -681,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();
@@ -737,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) {
@@ -1580,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;
@@ -1734,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/src/status.cc b/src/components/policy/policy_regular/src/status.cc
index 114ecb9f97..29d1bbf6b7 100644
--- a/src/components/policy/policy_regular/src/status.cc
+++ b/src/components/policy/policy_regular/src/status.cc
@@ -67,6 +67,9 @@ void policy::UpdateNeededStatus::ProcessEvent(
case kOnResetPolicyTableNoUpdate:
manager->SetNextStatus(std::make_shared<UpToDateStatus>());
break;
+ case kPendingUpdate:
+ manager->SetNextStatus(std::make_shared<UpdatePendingStatus>());
+ break;
case kOnNewAppRegistered:
manager->SetNextStatus(std::make_shared<UpdateNeededStatus>());
break;
@@ -79,6 +82,36 @@ bool policy::UpdateNeededStatus::IsUpdateRequired() const {
return true;
}
+policy::UpdatePendingStatus::UpdatePendingStatus()
+ : Status(kUpdateNeeded,
+ policy::PolicyTableStatus::StatusProcessingSnapshot) {}
+
+void policy::UpdatePendingStatus::ProcessEvent(
+ policy::UpdateStatusManagerInterface* manager, policy::UpdateEvent event) {
+ switch (event) {
+ case kOnUpdateSentOut:
+ manager->SetNextStatus(std::make_shared<UpdatingStatus>());
+ break;
+ case kOnResetPolicyTableRequireUpdate:
+ manager->SetNextStatus(std::make_shared<UpToDateStatus>());
+ manager->SetPostponedStatus(std::make_shared<UpdateNeededStatus>());
+ break;
+ case kOnResetPolicyTableNoUpdate:
+ manager->SetNextStatus(std::make_shared<UpToDateStatus>());
+ break;
+ default:
+ break;
+ }
+}
+
+bool policy::UpdatePendingStatus::IsUpdatePending() const {
+ return true;
+}
+
+bool policy::UpdatePendingStatus::IsUpdateRequired() const {
+ return true;
+}
+
policy::UpdatingStatus::UpdatingStatus()
: Status("UPDATING", policy::PolicyTableStatus::StatusUpdatePending) {}
diff --git a/src/components/policy/policy_regular/src/update_status_manager.cc b/src/components/policy/policy_regular/src/update_status_manager.cc
index c37f8bbadc..aa8d8cb3a2 100644
--- a/src/components/policy/policy_regular/src/update_status_manager.cc
+++ b/src/components/policy/policy_regular/src/update_status_manager.cc
@@ -54,6 +54,11 @@ void UpdateStatusManager::ProcessEvent(UpdateEvent event) {
DoTransition();
}
+void UpdateStatusManager::PendingUpdate() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ ProcessEvent(kPendingUpdate);
+}
+
void UpdateStatusManager::SetNextStatus(std::shared_ptr<Status> status) {
next_status_ = status;
}
@@ -173,7 +178,10 @@ void UpdateStatusManager::DoTransition() {
current_status_ = next_status_;
next_status_.reset();
LOG4CXX_DEBUG(logger_, "last_processed_event_ = " << last_processed_event_);
- if (last_processed_event_ != kScheduleManualUpdate) {
+ const bool is_update_pending =
+ policy::StatusProcessingSnapshot == current_status_->get_status();
+
+ if (last_processed_event_ != kScheduleManualUpdate && !is_update_pending) {
listener_->OnUpdateStatusChanged(current_status_->get_status_string());
}
if (!postponed_status_) {
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/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc
index 3b216c273c..04c1529573 100644
--- a/src/components/protocol_handler/src/protocol_handler_impl.cc
+++ b/src/components/protocol_handler/src/protocol_handler_impl.cc
@@ -1586,7 +1586,8 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndSession(
<< " type.");
if (packet.protocol_version() >= PROTOCOL_VERSION_5) {
std::vector<std::string> rejectedParams;
- if (hash_id == protocol_handler::HASH_ID_WRONG) {
+ if (hash_id == protocol_handler::HASH_ID_WRONG &&
+ packet.service_type() == kRpc) {
rejectedParams.push_back(std::string(strings::hash_id));
}
SendEndSessionNAck(connection_id,
diff --git a/src/components/transport_manager/CMakeLists.txt b/src/components/transport_manager/CMakeLists.txt
index 11986ee9fa..82cc00baf2 100644
--- a/src/components/transport_manager/CMakeLists.txt
+++ b/src/components/transport_manager/CMakeLists.txt
@@ -106,8 +106,20 @@ else()
)
endif()
-if(NOT BUILD_TESTS)
- list (APPEND EXCLUDE_PATH
+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
${CMAKE_CURRENT_SOURCE_DIR}/src/iap2_emulation/iap2_transport_adapter.cc
)
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/tcp/tcp_device.h b/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h
index 6e7a306879..5b746662f1 100644
--- a/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h
+++ b/src/components/transport_manager/include/transport_manager/tcp/tcp_device.h
@@ -66,7 +66,7 @@ class TcpDevice : public Device {
**/
TcpDevice(const in_addr_t& in_addr, const std::string& name);
-#if defined(BUILD_TESTS)
+#if defined(ENABLE_IAP2EMULATION)
/**
* @brief TcpDevice
* @param in_addr IP address of device
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/tcp/tcp_client_listener.cc b/src/components/transport_manager/src/tcp/tcp_client_listener.cc
index d29ffeb144..c2cbac4e13 100644
--- a/src/components/transport_manager/src/tcp/tcp_client_listener.cc
+++ b/src/components/transport_manager/src/tcp/tcp_client_listener.cc
@@ -300,13 +300,13 @@ void TcpClientListener::Loop() {
const auto device_uid =
device_name + std::string(":") + std::to_string(port_);
-#if defined(BUILD_TESTS)
+#if defined(ENABLE_IAP2EMULATION)
auto tcp_device = std::make_shared<TcpDevice>(
client_address.sin_addr.s_addr, device_uid, device_name);
#else
auto tcp_device = std::make_shared<TcpDevice>(
client_address.sin_addr.s_addr, device_uid);
-#endif // BUILD_TESTS
+#endif // ENABLE_IAP2EMULATION
DeviceSptr device = controller_->AddDevice(tcp_device);
auto tcp_device_raw = static_cast<TcpDevice*>(device.get());
diff --git a/src/components/transport_manager/src/tcp/tcp_device.cc b/src/components/transport_manager/src/tcp/tcp_device.cc
index 4542f76c1d..16abdfc22d 100644
--- a/src/components/transport_manager/src/tcp/tcp_device.cc
+++ b/src/components/transport_manager/src/tcp/tcp_device.cc
@@ -46,7 +46,7 @@ TcpDevice::TcpDevice(const in_addr_t& in_addr, const std::string& name)
LOG4CXX_AUTO_TRACE(logger_);
}
-#if defined(BUILD_TESTS)
+#if defined(ENABLE_IAP2EMULATION)
TcpDevice::TcpDevice(const in_addr_t& in_addr,
const std::string& device_uid,
const std::string& transport_switch_id)
@@ -61,7 +61,7 @@ TcpDevice::TcpDevice(const in_addr_t& in_addr,
logger_,
"Device parameters: " << device_uid << " / " << transport_switch_id);
}
-#endif // BUILD_TESTS
+#endif // ENABLE_IAP2EMULATION
bool TcpDevice::IsSameAs(const Device* other) const {
LOG4CXX_AUTO_TRACE(logger_);
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 868fcc3f15..74c5b9ceee 100644
--- a/src/components/transport_manager/src/transport_manager_default.cc
+++ b/src/components/transport_manager/src/transport_manager_default.cc
@@ -48,9 +48,13 @@
#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
-#if defined(BUILD_TESTS)
+#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 // BUILD_TEST
+#endif // ENABLE_IAP2EMULATION
namespace transport_manager {
CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")
@@ -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,7 +156,20 @@ int TransportManagerDefault::Init(
AddTransportAdapter(ta_cloud);
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
-#if defined BUILD_TESTS
+#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*
iap2_bt_emu_adapter =
@@ -158,7 +184,7 @@ int TransportManagerDefault::Init(
iap2_usb_emu_port, last_state_wrapper, settings);
AddTransportAdapter(iap2_usb_emu_adapter);
-#endif // BUILD_TEST
+#endif // ENABLE_IAP2EMULATION
LOG4CXX_TRACE(logger_, "exit with E_SUCCESS");
return E_SUCCESS;
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
diff --git a/third_party.md b/third_party.md
index 249d58fade..0737d7a657 100644
--- a/third_party.md
+++ b/third_party.md
@@ -1,9 +1,9 @@
### SDL CORE
-Copyright (C) 2018 SmartDeviceLink Consortium, Inc.
+Copyright (C) 2018 - 2020, SmartDeviceLink Consortium, Inc.
#### License
-Copyright (c) 2017 - 2018, SmartDeviceLink Consortium, Inc.
+Copyright (c) 2017 - 2020, SmartDeviceLink Consortium, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -41,12 +41,11 @@ The third party software included and used by this project is:
* The library is included in the Google Mock class generator
* See [https://github.com/google/googletest/tree/master/googlemock](https://github.com/google/googletest/tree/master/googlemock)
-**json-cpp 0.6.0 rc2**
+**json-cpp 1.9.2**
-* Copyright (c) 2007-2010 Baptiste Lepilleur
-* Licensed under MIT License
-* The library is included in jsoncpp 3rd party static src folder
-* See [https://github.com/open-source-parsers/jsoncpp/releases/tag/svn-release-0.6.0-rc2](https://github.com/open-source-parsers/jsoncpp/releases/tag/svn-release-0.6.0-rc2)
+* Any copyright is dedicated to the Public Domain
+* The library is included as a git submodule in jsoncpp 3rd party static src folder
+* See [https://github.com/open-source-parsers/jsoncpp/releases/tag/1.9.2](https://github.com/open-source-parsers/jsoncpp/releases/tag/1.9.2)
**Apache log4cxx 0.10.0**