From: Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics
Date: Thu, 5 Dec 2019 14:18:12 +0000 (+0100)
Subject: Merge branch 'tizen_4.0' into tizen_5.0
X-Git-Tag: submit/tizen_5.0/20200225.093921~4
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a512ea92f1623ab2a9353d2b2ed0cc050e8c5f17;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git
Merge branch 'tizen_4.0' into tizen_5.0
Change-Id: I6272ee91b469df02a70c0ddea192ef9cc46b0123
---
a512ea92f1623ab2a9353d2b2ed0cc050e8c5f17
diff --cc packaging/webapi-plugins.spec
index 8614f0b,11ce4ce..46a3a04
--- a/packaging/webapi-plugins.spec
+++ b/packaging/webapi-plugins.spec
@@@ -8,7 -8,7 +8,7 @@@
%define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
Name: webapi-plugins
- Version: 2.43
-Version: 2.39
++Version: 2.44
Release: 0
License: Apache-2.0 and BSD-3-Clause and MIT
Group: Development/Libraries
diff --cc src/application/application_manager.cc
index 840faaf,69e2a55..a4b3057
--- a/src/application/application_manager.cc
+++ b/src/application/application_manager.cc
@@@ -480,182 -534,111 +480,183 @@@ void ApplicationManager::LaunchAppContr
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;
+ 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 (!ApplicationUtils::ServiceToApplicationControlDataArray(
+ reply, &return_value_obj.find("data")->second.get())) {
+ return_value_obj.erase("data");
+ }
+ ReportSuccess(return_value_obj);
+ } else {
+ ReportError(return_value_obj);
}
- }
- app_control_reply_cb callback = nullptr;
- struct ReplayCallbackData {
- ApplicationInstance* app_instance;
- std::string reply_callback;
+ Instance::PostMessage(callback_data->instance, return_value.serialize().c_str());
+ delete callback_data;
};
+ }
- ReplayCallbackData* user_data = nullptr;
-
- if (!reply_callback.empty()) {
- user_data = new ReplayCallbackData();
- user_data->app_instance = &this->instance_;
- user_data->reply_callback = reply_callback;
-
- callback = [](app_control_h request, app_control_h reply, app_control_result_e result,
- void* user_data) {
- LoggerD("send_launch_request callback");
-
- picojson::value return_value = picojson::value(picojson::object());
- picojson::object& return_value_obj = return_value.get();
- ReplayCallbackData* reply_callback = static_cast(user_data);
-
- 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);
- }
+ app_control_result_cb result_callback = [](app_control_h launch_request,
+ app_control_error_e launch_result, void* user_data) {
+ ScopeLogger("LaunchAppControl result_callback");
- 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;
- };
+ LaunchAppControlCallbackData* callback_data =
+ static_cast(user_data);
+
+ auto result = ApplicationUtils::TranslateAppControlError(launch_result);
+
+ if (result.IsError()) {
+ LogAndReportError(result, &(callback_data->response->get()));
+ } else {
+ ReportSuccess(callback_data->response->get());
}
- const int retry_count = 3;
+ Instance::PostMessage(callback_data->instance, callback_data->response->serialize().c_str());
- int retry = 0;
- int ret = 0;
+ if (result.IsError() || (callback_data->reply_callback_id).empty()) {
+ delete callback_data;
+ }
+ };
- while (retry < retry_count) {
- LoggerD("Calling launch request. Attempt number: %d", retry);
+ /*
+ * 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 =
- ApplicationUtils::TranslateAppControlError(static_cast(app_control_send_launch_request_async(
++ auto launch_result = ApplicationUtils::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");
+ }
+}
- 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;
- }
+namespace {
- // delay 300ms for each retry
- struct timespec sleep_time = {0, 300L * 1000L * 1000L};
- nanosleep(&sleep_time, nullptr);
- ++retry;
- }
+PlatformResult TranslateLaunchError(app_control_error_e return_code) {
+ ScopeLogger();
+
+ auto result = ApplicationUtils::TranslateAppControlError(return_code);
+ if (ErrorCode::SECURITY_ERR == result.error_code()) {
+ result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
+ }
+
+ 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_launch_request_async(
- app_control_ptr.get(), result_callback, nullptr, launch_user_data)));
++ auto launch_result =
++ TranslateLaunchError(static_cast(app_control_send_launch_request_async(
++ app_control_ptr.get(), result_callback, nullptr, 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
diff --cc src/application/application_utils.cc
index 3fbeeba,596d292..27dfa61
--- a/src/application/application_utils.cc
+++ b/src/application/application_utils.cc
@@@ -383,37 -265,21 +383,38 @@@ PlatformResult ApplicationUtils::Applic
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]);
+ int result = APP_CONTROL_ERROR_NONE;
+ /*
+ * Native applications handle single extra data objects and arrays in a different ways,
+ * hence they have to be packed with different native API functions.
+ */
+ if (1 == value_data.size()) {
+ result = app_control_add_extra_data(app_control, key.c_str(), value_data[0]);
} else {
- result = app_control_add_extra_data_array(app_control, key.c_str(), value_data.data(), value_data.size());
- app_control_add_extra_data_array(app_control, key.c_str(), arr, size);
++ 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);
}
diff --cc src/common/platform_enum.h
index 6c62695,0000000..a7e22ca
mode 100644,000000..100644
--- a/src/common/platform_enum.h
+++ b/src/common/platform_enum.h
@@@ -1,81 -1,0 +1,77 @@@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMMON_PLATFORM_ENUM_H_
+#define COMMON_PLATFORM_ENUM_H_
+
+#include "platform_result.h"
+
- #include
++#include
+#include