From: Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics Date: Tue, 25 Feb 2020 08:22:45 +0000 (+0100) Subject: Merge branch 'tizen_5.0' into tizen_5.5 X-Git-Tag: submit/tizen/20200225.093834^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=830b09f59cbb6f33f55d76cf16dac67db4b73ca1;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git Merge branch 'tizen_5.0' into tizen_5.5 Change-Id: I87da3bb68de8658d2330fe09dcd736acc5d809dd --- 830b09f59cbb6f33f55d76cf16dac67db4b73ca1 diff --cc packaging/webapi-plugins.spec index 98fbaee1,25edbf0c..0d4abbc3 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@@ -6,11 -6,9 +6,11 @@@ %define crosswalk_extensions tizen-extensions-crosswalk %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} +%define tizen_ut_build 0 + Name: webapi-plugins - Version: 2.59 -Version: 2.47 ++Version: 2.60 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries diff --cc src/application/application_manager.cc index ad218599,74273f77..864639ca --- a/src/application/application_manager.cc +++ b/src/application/application_manager.cc @@@ -443,220 -492,132 +443,219 @@@ void ApplicationManager::LaunchAppContr return; } - std::string app_id; - const auto& id = args.get("id"); - if (id.is()) { - app_id = id.get(); - } + std::unique_ptr::type, decltype(&app_control_destroy)> + app_control_ptr(app_control, &app_control_destroy); - std::string reply_callback; + std::string reply_callback_id; const auto& reply = args.get("replyCallback"); if (reply.is()) { - reply_callback = reply.get(); + reply_callback_id = reply.get(); } - auto launch = [this, app_control_ptr, app_id, launch_mode_str, - reply_callback](const std::shared_ptr& response) -> void { - ScopeLogger("Entered into asynchronous function, launch"); + struct LaunchAppControlCallbackData { + ApplicationInstance* instance; + std::shared_ptr response; + std::string reply_callback_id; + }* launch_app_user_data = new (std::nothrow) + LaunchAppControlCallbackData{&this->instance_, response, reply_callback_id}; + + if (!launch_app_user_data) { + LoggerE("Memory allocation fail!"); + AsyncResponse(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response); + return; + } - if (!app_id.empty()) { - LoggerD("app_id: %s", app_id.c_str()); + app_control_reply_cb reply_callback = nullptr; + if (!reply_callback_id.empty()) { + launch_app_user_data->reply_callback_id = reply_callback_id; - int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str()); + reply_callback = [](app_control_h request, app_control_h reply, app_control_result_e result, + void* user_data) { + ScopeLogger("reply_callback"); - if (APP_CONTROL_ERROR_NONE != ret) { - LogAndReportError( - PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), - &response->get(), - ("Failed to set app id: %d (%s)", ret, get_error_message(ret))); + LaunchAppControlCallbackData* callback_data = + static_cast(user_data); + if (!callback_data) { + LoggerD("reply_callback failed: user_data is nullptr"); return; } - } - app_control_reply_cb callback = nullptr; - struct ReplayCallbackData { - ApplicationInstance* app_instance; - std::string reply_callback; + picojson::value return_value = picojson::value(picojson::object()); + picojson::object& return_value_obj = return_value.get(); + return_value_obj.insert( + std::make_pair(kListenerId, picojson::value(callback_data->reply_callback_id))); + + if (APP_CONTROL_RESULT_SUCCEEDED == result) { + LoggerD("App started"); + return_value_obj.insert(std::make_pair("data", picojson::value(picojson::array()))); + if (!utils::ServiceToApplicationControlDataArray( + reply, &return_value_obj.find("data")->second.get())) { + return_value_obj.erase("data"); + } + ReportSuccess(return_value_obj); + } else { + ReportError(return_value_obj); + } + + Instance::PostMessage(callback_data->instance, return_value.serialize().c_str()); + delete callback_data; }; + } - ReplayCallbackData* user_data = nullptr; + app_control_result_cb result_callback = [](app_control_h launch_request, + app_control_error_e launch_result, void* user_data) { + ScopeLogger("LaunchAppControl result_callback"); - if (!reply_callback.empty()) { - user_data = new ReplayCallbackData(); - user_data->app_instance = &this->instance_; - user_data->reply_callback = reply_callback; + LaunchAppControlCallbackData* callback_data = + static_cast(user_data); - callback = [](app_control_h request, app_control_h reply, app_control_result_e result, - void* user_data) { - LoggerD("send_launch_request callback"); + auto result = utils::TranslateAppControlError(launch_result); - picojson::value return_value = picojson::value(picojson::object()); - picojson::object& return_value_obj = return_value.get(); - ReplayCallbackData* reply_callback = static_cast(user_data); + if (result.IsError()) { + LogAndReportError(result, &(callback_data->response->get())); + } else { + ReportSuccess(callback_data->response->get()); + } - if (APP_CONTROL_RESULT_SUCCEEDED == result) { - const std::string data = "data"; - return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array()))); - if (!ApplicationUtils::ServiceToApplicationControlDataArray( - reply, &return_value_obj.find(data)->second.get())) { - return_value_obj.erase(data); - } - ReportSuccess(return_value_obj); - } else { - ReportError(return_value_obj); - } + Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str()); - return_value_obj.insert( - std::make_pair("listenerId", picojson::value(reply_callback->reply_callback))); - Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str()); - delete reply_callback; - }; + if (result.IsError() || (callback_data->reply_callback_id).empty()) { + delete callback_data; } + }; - const int retry_count = 3; + /* + * TODO: Observe how often app_control_send_launch_request_async tries to launch the application. + * Previous implementation, using synchronous app_control_send_launch_request, + * tries to launch the application 3 times, before reporting an error. + * New implementation, using app_control_send_launch_request_async makes only one attempt. + * If problems, such as failed application start occur, multiple attempts may solve the problem. + */ + auto launch_result = utils::TranslateAppControlError( + static_cast(app_control_send_launch_request_async( + app_control_ptr.get(), result_callback, reply_callback, launch_app_user_data))); + + if (launch_result.IsError()) { + delete launch_app_user_data; + AsyncResponse(launch_result, &response); + } else { + LoggerD("App launched"); + } +} - int retry = 0; - int ret = 0; +namespace { - while (retry < retry_count) { - LoggerD("Calling launch request. Attempt number: %d", retry); +PlatformResult TranslateLaunchError(app_control_error_e return_code) { + ScopeLogger(); - ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data); - LoggerD("App control launch request returned: %d, %s", ret, get_error_message(ret)); - if (APP_CONTROL_ERROR_NONE == ret) { - break; - } + auto result = utils::TranslateAppControlError(return_code); + if (ErrorCode::SECURITY_ERR == result.error_code()) { + result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."); + } - // delay 300ms for each retry - struct timespec sleep_time = {0, 300L * 1000L * 1000L}; - nanosleep(&sleep_time, nullptr); - ++retry; - } + return result; +} + +PlatformResult PrepareAppControlForLaunch(const picojson::value& args, app_control_h* app_control) { + ScopeLogger(); + + const auto& app_id = args.get("id"); + if (!app_id.is()) { + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."); + } + const auto app_id_str = app_id.get(); + + app_control_h tmp_app_control = nullptr; + int result = app_control_create(&tmp_app_control); + if (APP_CONTROL_ERROR_NONE != result) { + LoggerD("app_control_create() failed: %d (%s)", result, get_error_message(result)); + return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."); + } + + std::unique_ptr::type, decltype(&app_control_destroy)> + app_control_ptr(tmp_app_control, &app_control_destroy); + + if (!app_id_str.empty()) { + LoggerD("app_id: %s", app_id_str.c_str()); + + int ret = app_control_set_app_id(app_control_ptr.get(), app_id_str.c_str()); if (APP_CONTROL_ERROR_NONE != ret) { - delete user_data; - - switch (ret) { - case APP_CONTROL_ERROR_INVALID_PARAMETER: - LogAndReportError( - PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."), - &response->get(), - ("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER")); - return; - case APP_CONTROL_ERROR_OUT_OF_MEMORY: - LogAndReportError( - PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."), - &response->get(), - ("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY")); - return; - case APP_CONTROL_ERROR_LAUNCH_REJECTED: - case APP_CONTROL_ERROR_APP_NOT_FOUND: - LogAndReportError( - PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."), - &response->get(), - ("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND")); - return; - default: - LogAndReportError( - PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), - &response->get(), - ("app_control_send_launch_request returns: %d (%s)", ret, get_error_message(ret))); - return; - } + LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret)); + return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."); } - ReportSuccess(response->get()); + } + + *app_control = app_control_ptr.release(); + + return PlatformResult(ErrorCode::NO_ERROR); +} + +} // namespace +void ApplicationManager::Launch(const picojson::value& args) { + ScopeLogger(); + + int callback_id = -1; + const auto& callback = args.get(kCallbackId); + if (callback.is()) { + callback_id = static_cast(callback.get()); + } + + std::shared_ptr response(new picojson::value(picojson::object())); + picojson::object& response_obj = response->get(); + response_obj.insert( + std::make_pair(kCallbackId, picojson::value(static_cast(callback_id)))); + + app_control_h app_control = nullptr; + auto prepare_app_control_result = PrepareAppControlForLaunch(args, &app_control); + if (prepare_app_control_result.IsError()) { + AsyncResponse(LogAndCreateResult(prepare_app_control_result), &response); + return; + } + + std::unique_ptr::type, decltype(&app_control_destroy)> + app_control_ptr(app_control, &app_control_destroy); + + struct LaunchCallbackData { + ApplicationInstance* instance; + std::shared_ptr response; + }* launch_user_data = new (std::nothrow) LaunchCallbackData{&this->instance_, response}; + + app_control_result_cb result_callback = [](app_control_h launch_request, + app_control_error_e launch_result, void* user_data) { + ScopeLogger("Launch result_callback"); + + LaunchCallbackData* callback_data = static_cast(user_data); + + auto result = TranslateLaunchError(launch_result); + + if (result.IsError()) { + LogAndReportError(result, &(callback_data->response->get())); + } else { + ReportSuccess(callback_data->response->get()); + } + + Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str()); + + delete callback_data; }; - launch(response); - Instance::PostMessage(&this->instance_, response->serialize().c_str()); + /* + * TODO: Observe how often app_control_send_launch_request_async tries to launch the application. + * Previous implementation, using synchronous app_control_send_launch_request, + * tries to launch the application 3 times, before reporting an error. + * New implementation, using app_control_send_launch_request_async makes only one attempt. + * If problems, such as failed application start occur, multiple attempts may solve the problem. + */ - auto launch_result = - TranslateLaunchError(static_cast(app_control_send_resume_request( - app_control_ptr.get(), result_callback, launch_user_data))); ++ auto launch_result = TranslateLaunchError(static_cast( ++ app_control_send_resume_request(app_control_ptr.get(), result_callback, launch_user_data))); + + if (launch_result.IsError()) { + delete launch_user_data; + AsyncResponse(launch_result, &response); + } else { + LoggerD("App launched"); + } } // internal impl of app_control_foreach_app_matched() for handling APP_CONTROL_ERROR_APP_NOT_FOUND