diff options
author | agaliuzov <agaliuzov@luxoft.com> | 2016-04-06 17:33:34 +0300 |
---|---|---|
committer | agaliuzov <agaliuzov@luxoft.com> | 2016-04-06 17:33:34 +0300 |
commit | c73c5976a96046d7ce2a5053362a5eef6e8a2b95 (patch) | |
tree | 6d44d23a5095b8efc7bfa6d86fd946decae36490 /src | |
parent | 5d116a9286bd5b4d43b95de185fb81aa6a7e7f93 (diff) | |
parent | 6808a52562978f1e01899573d77b47ad33dccff3 (diff) | |
download | sdl_core-c73c5976a96046d7ce2a5053362a5eef6e8a2b95.tar.gz |
Merge remote-tracking branch 'upstream/master' into develop
Diffstat (limited to 'src')
8 files changed, 420 insertions, 66 deletions
diff --git a/src/components/application_manager/CMakeLists.txt b/src/components/application_manager/CMakeLists.txt index 963899e809..775ed7f349 100644 --- a/src/components/application_manager/CMakeLists.txt +++ b/src/components/application_manager/CMakeLists.txt @@ -297,6 +297,7 @@ file (GLOB MOBILE_COMMANDS_SOURCES ${AM_SOURCE_DIR}/src/commands/hmi/dial_number_request.cc ${AM_SOURCE_DIR}/src/commands/hmi/dial_number_response.cc ${AM_SOURCE_DIR}/src/commands/hmi/on_event_changed_notification.cc + ${AM_SOURCE_DIR}/src/commands/hmi/on_phone_call_notification.cc ) set (HMI_COMMANDS_SOURCES_JSON diff --git a/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h b/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h index 0c046362e7..c2ed6ee4ff 100644 --- a/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h +++ b/src/components/application_manager/include/application_manager/commands/mobile/dial_number_request.h @@ -1,6 +1,5 @@ /* - - Copyright (c) 2013, Ford Motor Company + Copyright (c) 2016, Ford Motor Company All rights reserved. Redistribution and use in source and binary forms, with or without @@ -54,7 +53,12 @@ class DialNumberRequest : public CommandRequestImpl { /** * \brief DialNumberRequest class destructor **/ - virtual ~DialNumberRequest(); + ~DialNumberRequest() OVERRIDE; + + /** + * @brief Initialize request params + **/ + bool Init() OVERRIDE; /** * @brief Initialize request params @@ -64,7 +68,14 @@ class DialNumberRequest : public CommandRequestImpl { /** * @brief Execute command **/ - virtual void Run(); + void Run() OVERRIDE; + + /** + * @brief Interface method that is called whenever new event received + * + * @param event The received event + */ + void on_event(const event_engine::Event& event); /** * @brief Interface method that is called whenever new event received diff --git a/src/components/application_manager/src/commands/mobile/dial_number_request.cc b/src/components/application_manager/src/commands/mobile/dial_number_request.cc index 5c1cf18cf8..6e8f5e15ad 100644 --- a/src/components/application_manager/src/commands/mobile/dial_number_request.cc +++ b/src/components/application_manager/src/commands/mobile/dial_number_request.cc @@ -1,5 +1,4 @@ /* - Copyright (c) 2016, Ford Motor Company All rights reserved. @@ -131,7 +130,7 @@ void DialNumberRequest::on_event(const event_engine::Event& event) { void DialNumberRequest::StripNumberParam(std::string& number) { std::size_t found = 0; while (std::string::npos != - (found = number.find_first_not_of("+0123456789"))) { + (found = number.find_first_not_of("+*#,;0123456789"))) { number.erase(number.begin() + found); } (*message_)[strings::msg_params][strings::number] = number; diff --git a/src/components/application_manager/src/commands/mobile/dial_number_response.cc b/src/components/application_manager/src/commands/mobile/dial_number_response.cc index 3eba98fb96..1daab5a4e1 100644 --- a/src/components/application_manager/src/commands/mobile/dial_number_response.cc +++ b/src/components/application_manager/src/commands/mobile/dial_number_response.cc @@ -1,6 +1,5 @@ /* - - Copyright (c) 2013, Ford Motor Company + Copyright (c) 2016, Ford Motor Company All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/components/application_manager/src/commands/mobile/system_request.cc b/src/components/application_manager/src/commands/mobile/system_request.cc index 3720b98c02..bede5b3f3b 100644 --- a/src/components/application_manager/src/commands/mobile/system_request.cc +++ b/src/components/application_manager/src/commands/mobile/system_request.cc @@ -33,7 +33,8 @@ Copyright (c) 2013, Ford Motor Company #include <vector> #include <string> -#include <stdio.h> +#include <map> +#include <set> #include "application_manager/commands/mobile/system_request.h" #include "application_manager/application_manager_impl.h" #include "application_manager/application_impl.h" @@ -47,6 +48,368 @@ Copyright (c) 2013, Ford Motor Company namespace application_manager { +namespace { + +CREATE_LOGGERPTR_LOCAL(logger_, "ApplicationManager") + +const char* kQueryAppsValidationFailedPrefix = + ":QUERY_APPS_VALIDATION_FAILED: "; + +const unsigned int kVrSynonymLengthMax = 40U; +const unsigned int kVrSynonymLengthMin = 1U; +const unsigned int kTtsNameLengthMax = 500U; +const unsigned int kVrArraySizeMax = 100U; +const unsigned int kVrArraySizeMin = 1U; +const unsigned int kUrlSchemaLengthMax = 255U; +const unsigned int kPackageNameLengthMax = 255U; +const unsigned int kAppIdLengthMax = 40U; +const unsigned int kAppNameLengthMax = 100U; +const unsigned int kLanguageArraySizeMax = 100U; + +class QueryAppsDataValidator { + public: + typedef std::set<std::string> SynonymsSet; + typedef std::map<std::string, SynonymsSet> SynonymsMap; + + QueryAppsDataValidator(const smart_objects::SmartObject& object, + const ApplicationManagerImpl& manager) + : data_(object), manager_(manager) {} + + bool Validate() const { + LOG4CXX_AUTO_TRACE(logger_); + if (!data_.isValid()) { + LOG4CXX_ERROR(logger_, + kQueryAppsValidationFailedPrefix + << "QueryApps response is not valid."); + return false; + } + if (!HasResponseKey()) { + return false; + } + return ValidateAppDataAndOsAndLanguagesData(); + } + + private: + bool HasResponseKey() const { + if (!data_.keyExists(json::response)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "QueryApps response does not contain '" + << json::response << "' parameter."); + return false; + } + return true; + } + + bool ValidateAppDataAndOsAndLanguagesData() const { + const smart_objects::SmartArray* objects_array = + data_[json::response].asArray(); + if (!objects_array) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "QueryApps response is not array."); + return false; + } + const std::size_t arr_size(objects_array->size()); + SynonymsMap synonyms_map; + for (std::size_t idx = 0; idx < arr_size; ++idx) { + const smart_objects::SmartObject& app_data = (*objects_array)[idx]; + + if (!app_data.isValid()) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Wrong application data in json file."); + return false; + } + std::set<std::string> app_ids_set; + if (!ValidateAppIdAndAppName(app_data, app_ids_set)) { + return false; + } + // Verify os and dependent languages data + std::string os_type; + if (app_data.keyExists(json::ios)) { + os_type = json::ios; + if (!app_data[os_type].keyExists(json::urlScheme)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Can't find URL scheme in json file."); + return false; + } + if (app_data[os_type][json::urlScheme].asString().length() > + kUrlSchemaLengthMax) { + LOG4CXX_WARN( + logger_, + kQueryAppsValidationFailedPrefix + << "An urlscheme length exceeds maximum allowed [" + << app_data[os_type][json::urlScheme].asString().length() + << "]>[" << kUrlSchemaLengthMax << "]"); + return false; + } + } + if (os_type.empty()) { + if (app_data.keyExists(json::android)) { + os_type = json::android; + if (!app_data[os_type].keyExists(json::packageName)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Can't find package name in json file."); + return false; + } + if (app_data[json::android][json::packageName].asString().length() > + kPackageNameLengthMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Package name length [" + << app_data[json::android][json::packageName] + .asString() + .length() << "] exceeds max length [" + << kPackageNameLengthMax << "]in json file."); + return false; + } + } + } + + if (os_type.empty()) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Can't find mobile OS type in json file."); + return false; + } + + // Languages verification + if (!app_data[os_type].keyExists(json::languages)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "'languages' doesn't exist"); + return false; + } + if (!ValidateLanguages(app_data[os_type][json::languages], + synonyms_map)) { + return false; + } + } + return true; + } + + bool ValidateAppIdAndAppName(const smart_objects::SmartObject& app_data, + std::set<std::string>& app_ids_set) const { + // Verify appid + if (!app_data.keyExists(json::appId)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Can't find app ID in json file."); + return false; + } + // Verify appid length + const std::string app_id(app_data[json::appId].asString()); + if (app_id.length() > kAppIdLengthMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "An Object ID length exceeds maximum allowed [" + << app_id.length() << "]>[" << kAppIdLengthMax << "]"); + return false; + } + + // Verify that appid is unique + if (app_ids_set.find(app_id) != app_ids_set.end()) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "An Object ID is not unigue [" << app_id << "]"); + return false; + } + app_ids_set.insert(app_id); + + // Verify that app is not registered yet + ApplicationSharedPtr registered_app = + manager_.application_by_policy_id(app_id); + if (registered_app) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Application with the same id: " << app_id + << " is registered already."); + return false; + } + // Verify app name exist + if (!app_data.keyExists(json::name)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Can't find app name in json file."); + return false; + } + // And app name length + const std::string appName(app_data[json::name].asString()); + if (appName.length() > kAppNameLengthMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "Name of application exceeds maximum allowed [" + << appName.length() << "]>[" << kAppNameLengthMax + << "]."); + return false; + } + return true; + } + + bool ValidateLanguages(const smart_objects::SmartObject& languages, + SynonymsMap& synonyms_map) const { + bool default_language_found = false; + const size_t languages_array_size = languages.length(); + if (languages_array_size > kLanguageArraySizeMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "'languages' array exceeds max size [" + << languages_array_size << "]>[" << kLanguageArraySizeMax + << "]"); + return false; + } + // Every language has ttsname string and vrsynonyms array + for (size_t idx = 0; idx < languages_array_size; ++idx) { + const smart_objects::SmartObject& language = languages.getElement(idx); + if (smart_objects::SmartType_Map != language.getType()) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "language is not a map."); + return false; + } + if (language.length() != 1) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "language map size is not equal 1."); + return false; + } + const std::string language_name = (*language.map_begin()).first; + if (!language_name.length()) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "language name is empty"); + return false; + } + // Verify default language defined + if (!(language_name).compare(json::default_)) { + default_language_found = true; + } + // Add set for synonyms' duplicates validation + if (synonyms_map.find(language_name) == synonyms_map.end()) { + synonyms_map[language_name] = SynonymsSet(); + } + // ttsName verification + if (!language[language_name].keyExists(json::ttsName)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "'languages.ttsName' doesn't exist"); + return false; + } + const smart_objects::SmartObject& ttsNameObject = + language[language_name][json::ttsName]; + // ttsName is string + if (smart_objects::SmartType_String == ttsNameObject.getType()) { + const std::string ttsName = + language[language_name][json::ttsName].asString(); + if (ttsName.length() > kTtsNameLengthMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "ttsName string exceeds max length [" + << ttsName.length() << "]>[" << kTtsNameLengthMax + << "]"); + return false; + } + } else { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "ttsName is not the string type."); + return false; + } + + if (!ValidateSynonymsAtLanguage(language, language_name, synonyms_map)) { + return false; + } + } + if (!default_language_found) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << " 'languages'.default' doesn't exist"); + return false; + } + return true; + } + + bool ValidateSynonymsAtLanguage(const smart_objects::SmartObject& language, + const std::string& language_name, + SynonymsMap& synonyms_map) const { + if (!language[language_name].keyExists(json::vrSynonyms)) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "'languages.vrSynonyms' doesn't exist"); + return false; + } + const smart_objects::SmartArray* synonyms_array = + language[language_name][json::vrSynonyms].asArray(); + if (!synonyms_array) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSynonyms is not array."); + return false; + } + const size_t synonyms_array_size = synonyms_array->size(); + if (synonyms_array_size < kVrArraySizeMin) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSynomyms array has [" << synonyms_array_size + << "] size < allowed min size [" << kVrArraySizeMin + << "]"); + return false; + } + if (synonyms_array_size > kVrArraySizeMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSynomyms array size [" << synonyms_array_size + << "] exceeds maximum allowed size [" << kVrArraySizeMax + << "]"); + return false; + } + + for (std::size_t idx = 0; idx < synonyms_array_size; ++idx) { + const smart_objects::SmartObject& synonym = (*synonyms_array)[idx]; + const std::string vrSynonym = synonym.asString(); + if (vrSynonym.length() > kVrSynonymLengthMax) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSYnomym item [" << idx + << "] exceeds max length [" << vrSynonym.length() + << "]>[" << kVrSynonymLengthMax << "]"); + return false; + } + if (vrSynonym.length() < kVrSynonymLengthMin) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSYnomym item [" << idx << "] length [" + << vrSynonym.length() << "] is less then min length [" + << kVrSynonymLengthMin << "] allowed."); + return false; + } + // Verify duplicates + SynonymsMap::iterator synonyms_map_iter = + synonyms_map.find(language_name); + if (synonyms_map_iter != synonyms_map.end()) { + if (!(*synonyms_map_iter).second.insert(vrSynonym).second) { + LOG4CXX_WARN(logger_, + kQueryAppsValidationFailedPrefix + << "vrSYnomym item already defined [" + << vrSynonym.c_str() << "] for language [" + << language_name << "]"); + return false; + } + } + } + return true; + } + + const smart_objects::SmartObject& data_; + const ApplicationManagerImpl& manager_; + + DISALLOW_COPY_AND_ASSIGN(QueryAppsDataValidator); +}; +} + namespace commands { uint32_t SystemRequest::index = 0; @@ -174,9 +537,8 @@ void SystemRequest::Run() { } CFormatterJsonBase::jsonValueToObj(root, sm_object); - if (!ValidateQueryAppData(sm_object)) { - SendResponse(false, mobile_apis::Result::INVALID_DATA); + SendResponse(false, mobile_apis::Result::GENERIC_ERROR); return; } @@ -246,61 +608,23 @@ void SystemRequest::on_event(const event_engine::Event& event) { bool SystemRequest::ValidateQueryAppData( const smart_objects::SmartObject& data) const { if (!data.isValid()) { - LOG4CXX_ERROR(logger_, "QueryApps response is not valid."); + LOG4CXX_ERROR(logger_, + kQueryAppsValidationFailedPrefix + << "QueryApps response is not valid."); return false; } if (!data.keyExists(json::response)) { LOG4CXX_ERROR(logger_, - "QueryApps response does not contain '" << json::response - << "' parameter."); + kQueryAppsValidationFailedPrefix + << "QueryApps response does not contain '" + << json::response << "' parameter."); return false; } - smart_objects::SmartArray* obj_array = data[json::response].asArray(); - if (NULL == obj_array) { - return false; - } - - const std::size_t arr_size(obj_array->size()); - for (std::size_t idx = 0; idx < arr_size; ++idx) { - const smart_objects::SmartObject& app_data = (*obj_array)[idx]; - if (!app_data.isValid()) { - LOG4CXX_ERROR(logger_, "Wrong application data in json file."); - continue; - } - std::string os_type; - if (app_data.keyExists(json::ios)) { - os_type = json::ios; - if (!app_data[os_type].keyExists(json::urlScheme)) { - LOG4CXX_ERROR(logger_, "Can't find URL scheme in json file."); - continue; - } - } else if (app_data.keyExists(json::android)) { - os_type = json::android; - if (!app_data[os_type].keyExists(json::packageName)) { - LOG4CXX_ERROR(logger_, "Can't find package name in json file."); - continue; - } - } - - if (os_type.empty()) { - LOG4CXX_ERROR(logger_, "Can't find mobile OS type in json file."); - continue; - } - - if (!app_data.keyExists(json::appId)) { - LOG4CXX_ERROR(logger_, "Can't find app ID in json file."); - continue; - } - - if (!app_data.keyExists(json::name)) { - LOG4CXX_ERROR(logger_, "Can't find app name in json file."); - continue; - } - - return true; - } + ApplicationManagerImpl* manager = ApplicationManagerImpl::instance(); + DCHECK(manager); - return false; + QueryAppsDataValidator validator(data, *manager); + return validator.Validate(); } } // namespace commands diff --git a/src/components/application_manager/src/hmi_command_factory.cc b/src/components/application_manager/src/hmi_command_factory.cc index 5701c67b4a..31c8923790 100644 --- a/src/components/application_manager/src/hmi_command_factory.cc +++ b/src/components/application_manager/src/hmi_command_factory.cc @@ -262,13 +262,14 @@ #include "application_manager/commands/hmi/navi_send_location_request.h" #include "application_manager/commands/hmi/navi_send_location_response.h" #include "application_manager/commands/hmi/on_tts_reset_timeout_notification.h" +#include "application_manager/commands/hmi/on_phone_call_notification.h" #include "application_manager/commands/hmi/dial_number_request.h" #include "application_manager/commands/hmi/dial_number_response.h" -CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager") - namespace application_manager { +CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager") + CommandSharedPtr HMICommandFactory::CreateCommand( const commands::MessageSharedPtr& message) { const int function_id = (*message)[strings::params][strings::function_id] @@ -2048,6 +2049,10 @@ CommandSharedPtr HMICommandFactory::CreateCommand( command.reset(new commands::hmi::OnTTSResetTimeoutNotification(message)); break; } + case hmi_apis::FunctionID::BasicCommunication_OnEventChanged: { + command.reset(new commands::OnEventChangedNotification(message)); + break; + } case hmi_apis::FunctionID::BasicCommunication_DialNumber: { if (is_response) { command.reset(new commands::hmi::DialNumberResponse(message)); @@ -2056,10 +2061,6 @@ CommandSharedPtr HMICommandFactory::CreateCommand( } break; } - case hmi_apis::FunctionID::BasicCommunication_OnEventChanged: { - command.reset(new commands::OnEventChangedNotification(message)); - break; - } } return command; diff --git a/src/components/application_manager/src/mobile_command_factory.cc b/src/components/application_manager/src/mobile_command_factory.cc index ff2d4fd49e..3399ec2667 100644 --- a/src/components/application_manager/src/mobile_command_factory.cc +++ b/src/components/application_manager/src/mobile_command_factory.cc @@ -489,6 +489,15 @@ CommandSharedPtr MobileCommandFactory::CreateCommand( } break; } + case mobile_apis::FunctionID::DialNumberID: { + if ((*message)[strings::params][strings::message_type] + == static_cast<int>(application_manager::MessageType::kResponse)) { + return new commands::DialNumberResponse(message); + } else { + return new commands::DialNumberRequest(message); + } + break; + } case mobile_apis::FunctionID::OnButtonEventID: { command = utils::MakeShared<commands::mobile::OnButtonEventNotification>(message); break; diff --git a/src/components/interfaces/HMI_API.xml b/src/components/interfaces/HMI_API.xml index f16dc972dc..1762018e98 100644 --- a/src/components/interfaces/HMI_API.xml +++ b/src/components/interfaces/HMI_API.xml @@ -2205,10 +2205,20 @@ <description>ID of application that concerns this RPC.</description> </param> </function> + <function name="DialNumber" messagetype="request"> + <description>Request from SDL to call a specific number.</description> + <param name="number" type="String" maxlength="40"> + <description>Phone number is a string, which can be up to 40 chars. + All characters shall be stripped from string except digits 0-9 and * # , ; + + </description> + </param> + <param name="appID" type="Integer" mandatory="true"> + <description>ID of application that concerns this RPC.</description> + </param> + </function> <function name="DialNumber" messagetype="response"> </function> - <!-- Policies --> <!-- SyncP RPC--> |