From 422fe41731821f77e94ee0d468efd8fbb90eba6f Mon Sep 17 00:00:00 2001 From: Pawel Wasowski Date: Mon, 5 Nov 2018 10:27:50 +0100 Subject: [PATCH] [Application] Refactor app_control_h construction. Fix minor bugs. ApplicationUtils::ApplicationControlToService() function did not set launch_mode in an app_control_h object. As a result, methods using the function had to set launch_mode. Now the function sets the launch mode. Apart from that change, this commit introduces minor fixes: * error codes returned by native functions in ApplicationUtils::ApplicationControlToService() and ApplicationUtils::ApplicationControlDataToServiceExtraData() are now tested * log messages in modified functions are more informative * ApplicationManager::LaunchAppControl() no longer sets launch_mode of an app_control_h object [Verification] TCT pass rate: 100% Change-Id: Ibc4c2625ce795c872560d13454895671777c6f2b Signed-off-by: Pawel Wasowski --- src/application/application_manager.cc | 22 --- src/application/application_utils.cc | 250 ++++++++++++++++++++----- src/application/application_utils.h | 2 + 3 files changed, 202 insertions(+), 72 deletions(-) diff --git a/src/application/application_manager.cc b/src/application/application_manager.cc index 23025be5..837dd138 100644 --- a/src/application/application_manager.cc +++ b/src/application/application_manager.cc @@ -520,28 +520,6 @@ void ApplicationManager::LaunchAppControl(const picojson::value& args) { } } - if (!launch_mode_str.empty()) { - app_control_launch_mode_e launch_mode; - - if ("SINGLE" == launch_mode_str) { - launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE; - } else if ("GROUP" == launch_mode_str) { - launch_mode = APP_CONTROL_LAUNCH_MODE_GROUP; - } else { - ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), - &response->get()); - return; - } - - int ret = app_control_set_launch_mode(app_control_ptr.get(), launch_mode); - if (APP_CONTROL_ERROR_NONE != ret) { - LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Setting launch mode failed."), - &response->get(), - ("Setting launch mode failed: %d (%s)", ret, get_error_message(ret))); - return; - } - } - app_control_reply_cb callback = nullptr; struct ReplayCallbackData { ApplicationInstance* app_instance; diff --git a/src/application/application_utils.cc b/src/application/application_utils.cc index 4a0098af..c1c44726 100644 --- a/src/application/application_utils.cc +++ b/src/application/application_utils.cc @@ -183,64 +183,176 @@ void ApplicationUtils::CreateApplicationMetaData(const char* key, const char* va app_meta_data->insert(std::make_pair("value", picojson::value(value))); } +namespace { + +const std::string kOperationAppControlField = "operation"; +const std::string kURIAppControlField = "uri"; +const std::string kMIMEAppControlField = "mime"; +const std::string kCategoryAppControlField = "category"; +const std::string kLaunchModeAppControlField = "launchMode"; +const std::string kDataAppControlField = "data"; + +const std::string kGroupLaunchMode = "GROUP"; +const std::string kSingleLaunchMode = "SINGLE"; + +using AppControlTextFieldSetter = std::function; +// clang-format off +const std::map AppControlTextFieldSetters = { + { kOperationAppControlField, app_control_set_operation }, + { kURIAppControlField, app_control_set_uri }, + { kMIMEAppControlField, app_control_set_mime }, + { kCategoryAppControlField, app_control_set_category } +}; // clang-format on + +PlatformResult SetAppControlTextField(app_control_h app_control, const std::string& field_name, + const std::string& value) { + ScopeLogger("Field: %s, value: %s", field_name.c_str(), value.c_str()); + + auto setter_it = AppControlTextFieldSetters.find(field_name); + if (AppControlTextFieldSetters.end() == setter_it) { + return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."); + } + auto setter = setter_it->second; + + auto result = setter(app_control, value.c_str()); + auto result_translated = + ApplicationUtils::TranslateAppControlError(static_cast(result)); + + if (result_translated.IsError()) { + LoggerD("Setting app_control's %s field failed: %s", field_name.c_str(), + result_translated.message().c_str()); + } + + return result_translated; +} + +app_control_launch_mode_e LaunchModeStringToEnum(const std::string& launch_mode) { + ScopeLogger(); + + return launch_mode == kGroupLaunchMode ? APP_CONTROL_LAUNCH_MODE_GROUP : APP_CONTROL_LAUNCH_MODE_SINGLE; +} + +bool LaunchModeIsInvalid(const std::string& launch_mode) { + ScopeLogger(); + + auto is_valid = launch_mode == kSingleLaunchMode || launch_mode == kGroupLaunchMode; + LoggerD("Launch mode: %s (%s)", launch_mode.c_str(), is_valid ? "valid" : "invalid"); + + return !is_valid; +} + +PlatformResult SetAppControlLaunchModeField(app_control_h app_control, + const std::string& launch_mode_str) { + ScopeLogger(); + + if (LaunchModeIsInvalid(launch_mode_str)) { + LoggerD("Invalid launchMode value: %s", launch_mode_str.c_str()); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, + "Invalid launchMode value: " + launch_mode_str); + } + + auto result = app_control_set_launch_mode(app_control, LaunchModeStringToEnum(launch_mode_str)); + return ApplicationUtils::TranslateAppControlError(static_cast(result)); +} + +PlatformResult SetAppControlDataField(app_control_h app_control, const picojson::array& data) { + ScopeLogger(); + + for (auto iter = data.begin(); iter != data.end(); ++iter) { + if (iter->is()) { + PlatformResult ret = ApplicationUtils::ApplicationControlDataToServiceExtraData( + iter->get(), app_control); + if (ret.IsError()) { + return ret; + } + } else { + LoggerD("Invalid data value: not an object"); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid data type: not an object"); + } + } + + return PlatformResult{ErrorCode::NO_ERROR}; +} + +PlatformResult SetAppControlFieldIfValueSpecified( + app_control_h app_control, const std::string& field_name, + const picojson::object::const_iterator& iterator) { + ScopeLogger(); + + if (iterator->second.is()) { + if (field_name != kLaunchModeAppControlField) { + return SetAppControlTextField(app_control, field_name, iterator->second.get()); + } + return SetAppControlLaunchModeField(app_control, iterator->second.get()); + } else if (iterator->second.is() && kDataAppControlField == field_name) { + return SetAppControlDataField(app_control, iterator->second.get()); + } + + return PlatformResult{ErrorCode::NO_ERROR}; +} + +} // namespace + PlatformResult ApplicationUtils::ApplicationControlToService( const picojson::object& app_control_obj, app_control_h* app_control) { ScopeLogger(); - const auto it_operation = app_control_obj.find("operation"); - const auto it_uri = app_control_obj.find("uri"); - const auto it_mime = app_control_obj.find("mime"); - const auto it_category = app_control_obj.find("category"); - const auto it_data = app_control_obj.find("data"); + + const auto it_operation = app_control_obj.find(kOperationAppControlField); + const auto it_uri = app_control_obj.find(kURIAppControlField); + const auto it_mime = app_control_obj.find(kMIMEAppControlField); + const auto it_category = app_control_obj.find(kCategoryAppControlField); + const auto it_data = app_control_obj.find(kDataAppControlField); + const auto it_launch_mode = app_control_obj.find(kLaunchModeAppControlField); const auto it_app_control_end = app_control_obj.end(); if (it_operation == it_app_control_end || it_uri == it_app_control_end || it_mime == it_app_control_end || it_category == it_app_control_end || it_data == it_app_control_end || !it_operation->second.is() || - !it_data->second.is()) { + !it_data->second.is() || it_launch_mode == it_app_control_end) { return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed."); } app_control_h app_control_tmp = nullptr; int result = app_control_create(&app_control_tmp); - if (APP_CONTROL_ERROR_NONE != result) { - return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creation AppControl failed.", - ("Problem with create handle.")); + LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result)); + return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."); } std::unique_ptr::type, int (*)(app_control_h)> app_control_ptr( app_control_tmp, &app_control_destroy); - // operation - app_control_set_operation(app_control_tmp, it_operation->second.get().c_str()); + auto set_field_result = PlatformResult(ErrorCode::UNKNOWN_ERR); - // uri - if (it_uri->second.is()) { - app_control_set_uri(app_control_tmp, it_uri->second.get().c_str()); + set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kOperationAppControlField, it_operation); + if (set_field_result.IsError()) { + return set_field_result; } - // mime - if (it_mime->second.is()) { - app_control_set_mime(app_control_tmp, it_mime->second.get().c_str()); + set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kURIAppControlField, it_uri); + if (set_field_result.IsError()) { + return set_field_result; } - // category - if (it_category->second.is()) { - app_control_set_category(app_control_tmp, it_category->second.get().c_str()); + set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kMIMEAppControlField, it_mime); + if (set_field_result.IsError()) { + return set_field_result; } - // ApplicationControlData - const picojson::array& data = it_data->second.get(); + set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kCategoryAppControlField, it_category); + if (set_field_result.IsError()) { + return set_field_result; + } - for (auto iter = data.begin(); iter != data.end(); ++iter) { - if (iter->is()) { - PlatformResult ret = - ApplicationControlDataToServiceExtraData(iter->get(), app_control_tmp); - if (ret.IsError()) { - LoggerE("Failed ApplicationControlDataToServiceExtraData()"); - return ret; - } - } + set_field_result = + SetAppControlFieldIfValueSpecified(app_control_tmp, kLaunchModeAppControlField, it_launch_mode); + if (set_field_result.IsError()) { + return set_field_result; + } + + set_field_result = SetAppControlFieldIfValueSpecified(app_control_tmp, kDataAppControlField, it_data); + if (set_field_result.IsError()) { + return set_field_result; } *app_control = app_control_ptr.release(); @@ -259,27 +371,34 @@ PlatformResult ApplicationUtils::ApplicationControlDataToServiceExtraData( if (it_key == it_app_control_data_end || it_value == it_app_control_data_end || !it_key->second.is() || !it_value->second.is()) { return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed.", - ("Problem with key or value.")); + ("Invalid key or value.")); } const std::string& key = it_key->second.get(); const picojson::array& value = it_value->second.get(); - const size_t size = value.size(); - const char** arr = new const char*[size]; - size_t i = 0; + std::vector value_data; - for (auto iter = value.begin(); iter != value.end(); ++iter, ++i) { - arr[i] = iter->get().c_str(); + for (auto& v : value) { + value_data.push_back(v.get().c_str()); } - if (1 == size) { - app_control_add_extra_data(app_control, key.c_str(), arr[0]); - } else { - app_control_add_extra_data_array(app_control, key.c_str(), arr, size); + auto result = app_control_add_extra_data_array(app_control, key.c_str(), value_data.data(), + value_data.size()); + if (APP_CONTROL_ERROR_INVALID_PARAMETER == result) { + if (0 == key.length()) { + LoggerD("app_control_add_extra_data_array failed: zero-length key"); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, + "Invalid AppControlData key: key length is 0."); + } + LoggerD("app_control_add_extra_data_array failed: invalid parameter passed"); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, + "Invalid AppControlData value, associated with key: " + key); + } else if (APP_CONTROL_ERROR_KEY_REJECTED == result) { + LoggerD("app_control_add_extra_data_array failed: key rejected"); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid AppControlData's key: " + key); } - delete[] arr; return PlatformResult(ErrorCode::NO_ERROR); } @@ -299,7 +418,7 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control, LoggerE("Get operation failed: %d (%s)", ret, get_error_message(ret)); } else if (tmp_str) { LoggerD("operation: %s", tmp_str); - app_control_obj->insert(std::make_pair("operation", picojson::value(std::string(tmp_str)))); + app_control_obj->insert(std::make_pair(kOperationAppControlField, picojson::value(std::string(tmp_str)))); } else { LoggerD("operation field is empty"); } @@ -310,7 +429,7 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control, LoggerE("Get URI failed: %d (%s)", ret, get_error_message(ret)); } else if (tmp_str) { LoggerD("URI: %s", tmp_str); - app_control_obj->insert(std::make_pair("uri", picojson::value(std::string(tmp_str)))); + app_control_obj->insert(std::make_pair(kURIAppControlField, picojson::value(std::string(tmp_str)))); } else { LoggerD("URI field is empty"); } @@ -321,7 +440,7 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control, LoggerE("Get MIME failed: %d (%s)", ret, get_error_message(ret)); } else if (tmp_str) { LoggerD("MIME: %s", tmp_str); - app_control_obj->insert(std::make_pair("mime", picojson::value(std::string(tmp_str)))); + app_control_obj->insert(std::make_pair(kMIMEAppControlField, picojson::value(std::string(tmp_str)))); } else { LoggerD("MIME field is empty"); } @@ -332,7 +451,7 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control, LoggerE("Get category failed: %d (%s)", ret, get_error_message(ret)); } else if (tmp_str) { LoggerD("category: %s", tmp_str); - app_control_obj->insert(std::make_pair("category", picojson::value(std::string(tmp_str)))); + app_control_obj->insert(std::make_pair(kCategoryAppControlField, picojson::value(std::string(tmp_str)))); } else { LoggerD("category field is empty"); } @@ -343,14 +462,15 @@ void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control, if (APP_CONTROL_ERROR_NONE != ret) { LoggerE("Get launch mode failed: %d (%s)", ret, get_error_message(ret)); } else { - std::string launch_mode_str = launch_mode == APP_CONTROL_LAUNCH_MODE_SINGLE ? "SINGLE" : "GROUP"; + std::string launch_mode_str = + launch_mode == APP_CONTROL_LAUNCH_MODE_SINGLE ? kSingleLaunchMode : kGroupLaunchMode; LoggerD("launch mode: %s", launch_mode_str.c_str()); - app_control_obj->insert(std::make_pair("launchMode", picojson::value(launch_mode_str))); + app_control_obj->insert(std::make_pair(kLaunchModeAppControlField, picojson::value(launch_mode_str))); } - app_control_obj->insert(std::make_pair("data", picojson::value(picojson::array()))); + app_control_obj->insert(std::make_pair(kDataAppControlField, picojson::value(picojson::array()))); ServiceToApplicationControlDataArray( - app_control, &app_control_obj->find("data")->second.get()); + app_control, &app_control_obj->find(kDataAppControlField)->second.get()); } void ApplicationUtils::ServiceExtraDataToApplicationControlData( @@ -411,6 +531,36 @@ bool ApplicationUtils::ServiceToApplicationControlDataArray(app_control_h app_co return APP_CONTROL_ERROR_NONE == ret; } +PlatformResult ApplicationUtils::TranslateAppControlError(app_control_error_e return_code) { + ScopeLogger("Return code: %d (%s)", static_cast(return_code), + get_error_message(static_cast(return_code))); + + switch (return_code) { + case APP_CONTROL_ERROR_NONE: + return PlatformResult(ErrorCode::NO_ERROR); + + case APP_CONTROL_ERROR_INVALID_PARAMETER: + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."); + + case APP_CONTROL_ERROR_APP_NOT_FOUND: + return PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."); + + case APP_CONTROL_ERROR_PERMISSION_DENIED: + return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied."); + + case APP_CONTROL_ERROR_OUT_OF_MEMORY: + case APP_CONTROL_ERROR_KEY_NOT_FOUND: + case APP_CONTROL_ERROR_KEY_REJECTED: + case APP_CONTROL_ERROR_INVALID_DATA_TYPE: + case APP_CONTROL_ERROR_LAUNCH_REJECTED: + case APP_CONTROL_ERROR_LAUNCH_FAILED: + case APP_CONTROL_ERROR_TIMED_OUT: + case APP_CONTROL_ERROR_IO_ERROR: + default: + return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."); + } +} + bool ApplicationUtils::ServiceExtraDataCallback(app_control_h app_control, const char* key, void* user_data) { ScopeLogger(); diff --git a/src/application/application_utils.h b/src/application/application_utils.h index 455f1977..308827be 100644 --- a/src/application/application_utils.h +++ b/src/application/application_utils.h @@ -59,6 +59,8 @@ class ApplicationUtils { static bool ServiceToApplicationControlDataArray(app_control_h app_control, picojson::array* data); + static common::PlatformResult TranslateAppControlError(app_control_error_e error_code); + private: static bool ServiceExtraDataCallback(app_control_h app_control, const char* key, void* user_data); }; -- 2.34.1