mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 22:21:36 -04:00
!18767 merge feat/register-agent-card-3 into master
feat: register/update/delete AgentCard part 3 Created-by: yangxuguang-huawei Commit-by: yangxuguang-huawei Merged-by: openharmony_ci Description: **IssueNo**: https://gitcode.com/openharmony/ability_ability_runtime/issues/14824 **Description**: **稳定性自检:** | 自检项 | 自检结果 | | ------------------------------------------------------------ | -------- | | 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发 | ok| | 成员变量进行赋值或创建需要排查并发 | ok| | 谨慎在lambda表达式中使用引用捕获 | ok| | 谨慎在未经拷贝的情况下使用外部传入的string、C字符串 | ok| | map\vector\list\set等stl模板类使用时需要排查并发 | ok| | 谨慎考虑加锁范围 | ok| | 在IPC通信中谨慎使用同步通信方式 | ok| | 禁止传递this指针至其他模块或线程(特别是eventhandler任务) | ok| | 禁止将外部传入的裸指针在内部直接构造智能指针 | ok| | 禁止多个独立创建的智能指针管理同一地址 | ok| | 禁止在析构函数中抛异步任务 | ok| | 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁 | ok| | 禁止在对外接口中未经判空直接使用外部传入的指针 | ok| | 禁止接口返回局部变量引用 | ok| | 禁止在信号函数中加锁 | ok| | 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作 | ok| | 禁止将同一个cpp编译在不同的so中 | ok| **安全编码自检:** | 自检项 | 自检结果 | | -------------------------------------------------------------- | -------- | | 裸指针避免通过隐式转换构造为sptr | ok| | json对象在取值之前必须先判断类型,避免类型不匹配 | ok| | 序列化时必须对传入的数组大小进行校验,避免出现超大数组 | ok | | 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型 | ok| | 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 | ok | | 指针变量、表示资源描述符的变量、bool变量必须赋初值 | ok| | readParcelable获取的对象使用前需要判空 | ok| | 分配和释放内存的函数需要成对出现 | ok| | 申请内存后异常退出前需要及时进行内存释放 | ok | | 内存申请前必须对内存大小进行合法性校验 | ok| | 内存分配后必须判断是否成功 | ok| | 禁止使用realloc、alloca函数 | ok| | 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰 | ok| | 禁止打印内存地址 | ok| | 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 | ok| | 禁止对有符号整数进行位操作符运算 | ok| | 禁止对指针进行逻辑或位运算 | ok| | 循环次数如果收外部数据控制,需要检验其合法性 | ok| | 禁止使用内存操作类危险函数,需要使用安全函数 | ok| | 谨慎使用不可重入函数 | ok| | 必须检查安全函数的返回值,并进行正确处理 | ok| | 禁止仅通过TokenType类型判断绕过权限校验 | ok| **TDD Result**: 已验证OK **XTS Result**: 已验证OK ### 是否已执行L0用例 - [x] 已验证 - [ ] 不涉及。如不涉及,请写明理由 See merge request: openharmony/ability_ability_runtime!18767
This commit is contained in:
@@ -16,6 +16,7 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni")
|
||||
|
||||
group("agent_runtime_napi_packages") {
|
||||
deps = [
|
||||
"${agent_runtime_framework_path}/frameworks/js/napi/agent_constant:agentconstant_napi",
|
||||
"${agent_runtime_framework_path}/frameworks/js/napi/agent_extension_ability:agentextensionability",
|
||||
"${agent_runtime_framework_path}/frameworks/js/napi/agent_extension_ability:js_agent_extension",
|
||||
"${agent_runtime_framework_path}/frameworks/js/napi/agent_extension_context:agentextensioncontext_napi",
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("//foundation/ability/ability_runtime/ability_runtime.gni")
|
||||
|
||||
ohos_shared_library("agentconstant_napi") {
|
||||
sanitize = {
|
||||
integer_overflow = true
|
||||
ubsan = true
|
||||
boundary_sanitize = true
|
||||
cfi = true
|
||||
cfi_cross_dso = true
|
||||
cfi_vcall_icall_only = true
|
||||
debug = false
|
||||
}
|
||||
branch_protector_ret = "pac_ret"
|
||||
|
||||
include_dirs = [ "${agent_runtime_framework_path}/interfaces/inner_api/include" ]
|
||||
|
||||
sources = [ "agent_constant_module.cpp" ]
|
||||
|
||||
deps = [ "${agent_runtime_framework_path}/interfaces/inner_api:agent_fwk" ]
|
||||
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"json:nlohmann_json_static",
|
||||
"napi:ace_napi",
|
||||
]
|
||||
|
||||
relative_install_dir = "module/app/agent"
|
||||
subsystem_name = "ability"
|
||||
part_name = "ability_runtime"
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "agent_card.h"
|
||||
#include "napi/native_api.h"
|
||||
#include "napi/native_common.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AgentRuntime {
|
||||
namespace {
|
||||
static napi_status SetEnumItem(napi_env env, napi_value object, const char *name, int32_t value)
|
||||
{
|
||||
napi_status status;
|
||||
napi_value itemName = nullptr;
|
||||
napi_value itemValue = nullptr;
|
||||
|
||||
NAPI_CALL_BASE(env, status = napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName), status);
|
||||
NAPI_CALL_BASE(env, status = napi_create_int32(env, value, &itemValue), status);
|
||||
NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemName, itemValue), status);
|
||||
NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemValue, itemName), status);
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
static napi_value InitAgentCardTypeObject(napi_env env)
|
||||
{
|
||||
napi_value object = nullptr;
|
||||
NAPI_CALL(env, napi_create_object(env, &object));
|
||||
NAPI_CALL(env, SetEnumItem(env, object, "APP", static_cast<int32_t>(AgentCardType::APP)));
|
||||
NAPI_CALL(env, SetEnumItem(env, object, "LOW_CODE", static_cast<int32_t>(AgentCardType::LOW_CODE)));
|
||||
NAPI_CALL(env, SetEnumItem(env, object, "ATOMIC_SERVICE", static_cast<int32_t>(AgentCardType::ATOMIC_SERVICE)));
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
static napi_value AgentConstantInit(napi_env env, napi_value exports)
|
||||
{
|
||||
napi_value agentCardType = InitAgentCardTypeObject(env);
|
||||
NAPI_ASSERT(env, agentCardType != nullptr, "failed to create AgentCardType object");
|
||||
|
||||
napi_property_descriptor exportObjs[] = {
|
||||
DECLARE_NAPI_PROPERTY("AgentCardType", agentCardType),
|
||||
};
|
||||
|
||||
napi_status status = napi_define_properties(env, exports, sizeof(exportObjs) / sizeof(exportObjs[0]), exportObjs);
|
||||
NAPI_ASSERT(env, status == napi_ok, "failed to define properties for exports");
|
||||
return exports;
|
||||
}
|
||||
|
||||
static napi_module _module = {
|
||||
.nm_version = 1,
|
||||
.nm_flags = 0,
|
||||
.nm_filename = nullptr,
|
||||
.nm_register_func = AgentConstantInit,
|
||||
.nm_modname = "app.agent.agentConstant",
|
||||
.nm_priv = (static_cast<void *>(0)),
|
||||
.reserved = {0}
|
||||
};
|
||||
|
||||
extern "C" __attribute__((constructor)) void RegisterModule(void)
|
||||
{
|
||||
napi_module_register(&_module);
|
||||
}
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
@@ -79,6 +79,12 @@ public:
|
||||
*/
|
||||
static napi_value GetAgentCardByAgentId(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value RegisterAgentCard(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value UpdateAgentCard(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value DeleteAgentCard(napi_env env, napi_callback_info info);
|
||||
|
||||
/**
|
||||
* @brief Native method for connecting to an agent extension.
|
||||
*
|
||||
@@ -128,6 +134,12 @@ private:
|
||||
*/
|
||||
napi_value OnGetAgentCardByAgentId(napi_env env, size_t argc, napi_value *argv);
|
||||
|
||||
napi_value OnRegisterAgentCard(napi_env env, size_t argc, napi_value *argv);
|
||||
|
||||
napi_value OnUpdateAgentCard(napi_env env, size_t argc, napi_value *argv);
|
||||
|
||||
napi_value OnDeleteAgentCard(napi_env env, size_t argc, napi_value *argv);
|
||||
|
||||
/**
|
||||
* @brief Implementation for connecting to an agent extension.
|
||||
*
|
||||
|
||||
+6
@@ -30,6 +30,12 @@ JS_AGENT_MANAGER_UTILS_EXPORT napi_value CreateJsAgentSkillArray(
|
||||
napi_env env, const std::vector<std::shared_ptr<AgentSkill>> &skills);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT napi_value CreateJsAgentCard(napi_env env, const AgentCard &card);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT napi_value CreateJsAgentCardArray(napi_env env, const std::vector<AgentCard> &cards);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT bool ParseJsAgentProvider(napi_env env, napi_value value, AgentProvider &provider);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT bool ParseJsAgentCapabilities(
|
||||
napi_env env, napi_value value, AgentCapabilities &capabilities);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT bool ParseJsAgentSkill(napi_env env, napi_value value, AgentSkill &skill);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT bool ParseJsAgentAppInfo(napi_env env, napi_value value, AgentAppInfo &appInfo);
|
||||
JS_AGENT_MANAGER_UTILS_EXPORT bool ParseJsAgentCard(napi_env env, napi_value value, AgentCard &card);
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_AGENT_RUNTIME_JS_AGENT_MANAGER_UTILS_H
|
||||
|
||||
@@ -123,6 +123,21 @@ napi_value JsAgentManager::GetAgentCardByAgentId(napi_env env, napi_callback_inf
|
||||
GET_CB_INFO_AND_CALL(env, info, JsAgentManager, OnGetAgentCardByAgentId);
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::RegisterAgentCard(napi_env env, napi_callback_info info)
|
||||
{
|
||||
GET_CB_INFO_AND_CALL(env, info, JsAgentManager, OnRegisterAgentCard);
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::UpdateAgentCard(napi_env env, napi_callback_info info)
|
||||
{
|
||||
GET_CB_INFO_AND_CALL(env, info, JsAgentManager, OnUpdateAgentCard);
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::DeleteAgentCard(napi_env env, napi_callback_info info)
|
||||
{
|
||||
GET_CB_INFO_AND_CALL(env, info, JsAgentManager, OnDeleteAgentCard);
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::ConnectAgentExtensionAbility(napi_env env, napi_callback_info info)
|
||||
{
|
||||
GET_CB_INFO_AND_CALL(env, info, JsAgentManager, OnConnectAgentExtensionAbility);
|
||||
@@ -234,6 +249,115 @@ napi_value JsAgentManager::OnGetAgentCardByAgentId(napi_env env, size_t argc, na
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::OnRegisterAgentCard(napi_env env, size_t argc, napi_value *argv)
|
||||
{
|
||||
if (argc < ARGC_ONE) {
|
||||
ThrowTooFewParametersError(env);
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
auto card = std::make_shared<AgentCard>();
|
||||
if (!ParseJsAgentCard(env, argv[ARG_INDEX_0], *card)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "parse card failed");
|
||||
ThrowInvalidParamError(env, "Parse param card failed.");
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
auto innerErrorCode = std::make_shared<int32_t>(ERR_OK);
|
||||
NapiAsyncTask::ExecuteCallback execute = [card, innerErrorCode]() {
|
||||
*innerErrorCode = AgentManagerClient::GetInstance().RegisterAgentCard(*card);
|
||||
};
|
||||
|
||||
NapiAsyncTask::CompleteCallback complete = [innerErrorCode](napi_env env, NapiAsyncTask &task, int32_t status) {
|
||||
if (*innerErrorCode != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "error: %{public}d", *innerErrorCode);
|
||||
task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrorCode));
|
||||
return;
|
||||
}
|
||||
task.ResolveWithNoError(env, CreateJsUndefined(env));
|
||||
};
|
||||
|
||||
napi_value result = nullptr;
|
||||
NapiAsyncTask::Schedule("JsAgentManager::OnRegisterAgentCard", env,
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::OnUpdateAgentCard(napi_env env, size_t argc, napi_value *argv)
|
||||
{
|
||||
if (argc < ARGC_ONE) {
|
||||
ThrowTooFewParametersError(env);
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
auto card = std::make_shared<AgentCard>();
|
||||
if (!ParseJsAgentCard(env, argv[ARG_INDEX_0], *card)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "parse card failed");
|
||||
ThrowInvalidParamError(env, "Parse param card failed.");
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
auto innerErrorCode = std::make_shared<int32_t>(ERR_OK);
|
||||
NapiAsyncTask::ExecuteCallback execute = [card, innerErrorCode]() {
|
||||
*innerErrorCode = AgentManagerClient::GetInstance().UpdateAgentCard(*card);
|
||||
};
|
||||
|
||||
NapiAsyncTask::CompleteCallback complete = [innerErrorCode](napi_env env, NapiAsyncTask &task, int32_t status) {
|
||||
if (*innerErrorCode != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "error: %{public}d", *innerErrorCode);
|
||||
task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrorCode));
|
||||
return;
|
||||
}
|
||||
task.ResolveWithNoError(env, CreateJsUndefined(env));
|
||||
};
|
||||
|
||||
napi_value result = nullptr;
|
||||
NapiAsyncTask::Schedule("JsAgentManager::OnUpdateAgentCard", env,
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::OnDeleteAgentCard(napi_env env, size_t argc, napi_value *argv)
|
||||
{
|
||||
if (argc < ARGC_TWO) {
|
||||
ThrowTooFewParametersError(env);
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
std::string bundleName;
|
||||
if (!ConvertFromJsValue(env, argv[ARG_INDEX_0], bundleName)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bundleName not string");
|
||||
ThrowInvalidParamError(env, "Parse param bundleName failed, must be a string.");
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
std::string agentId;
|
||||
if (!ConvertFromJsValue(env, argv[ARG_INDEX_1], agentId)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "agentId not string");
|
||||
ThrowInvalidParamError(env, "Parse param agentId failed, must be a string.");
|
||||
return CreateJsUndefined(env);
|
||||
}
|
||||
|
||||
auto innerErrorCode = std::make_shared<int32_t>(ERR_OK);
|
||||
NapiAsyncTask::ExecuteCallback execute = [bundleName, agentId, innerErrorCode]() {
|
||||
*innerErrorCode = AgentManagerClient::GetInstance().DeleteAgentCard(bundleName, agentId);
|
||||
};
|
||||
|
||||
NapiAsyncTask::CompleteCallback complete = [innerErrorCode](napi_env env, NapiAsyncTask &task, int32_t status) {
|
||||
if (*innerErrorCode != ERR_OK) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "error: %{public}d", *innerErrorCode);
|
||||
task.Reject(env, CreateJsErrorByNativeErr(env, *innerErrorCode));
|
||||
return;
|
||||
}
|
||||
task.ResolveWithNoError(env, CreateJsUndefined(env));
|
||||
};
|
||||
|
||||
napi_value result = nullptr;
|
||||
NapiAsyncTask::Schedule("JsAgentManager::OnDeleteAgentCard", env,
|
||||
CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value JsAgentManager::OnConnectAgentExtensionAbility(napi_env env, size_t argc, napi_value *argv)
|
||||
{
|
||||
// 1. Validate parameters and extract want, agentId, callback
|
||||
@@ -441,6 +565,9 @@ napi_value JsAgentManagerInit(napi_env env, napi_value exportObj)
|
||||
BindNativeFunction(env, exportObj, "getAgentCardsByBundleName", moduleName,
|
||||
JsAgentManager::GetAgentCardsByBundleName);
|
||||
BindNativeFunction(env, exportObj, "getAgentCardByAgentId", moduleName, JsAgentManager::GetAgentCardByAgentId);
|
||||
BindNativeFunction(env, exportObj, "registerAgentCard", moduleName, JsAgentManager::RegisterAgentCard);
|
||||
BindNativeFunction(env, exportObj, "updateAgentCard", moduleName, JsAgentManager::UpdateAgentCard);
|
||||
BindNativeFunction(env, exportObj, "deleteAgentCard", moduleName, JsAgentManager::DeleteAgentCard);
|
||||
BindNativeFunction(env, exportObj, "connectAgentExtensionAbility", moduleName,
|
||||
JsAgentManager::ConnectAgentExtensionAbility);
|
||||
BindNativeFunction(env, exportObj, "disconnectAgentExtensionAbility", moduleName,
|
||||
|
||||
+368
@@ -16,6 +16,7 @@
|
||||
#include "js_agent_manager_utils.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "hilog_tag_wrapper.h"
|
||||
#include "js_runtime_utils.h"
|
||||
@@ -24,6 +25,139 @@ using namespace OHOS::AbilityRuntime;
|
||||
|
||||
namespace OHOS {
|
||||
namespace AgentRuntime {
|
||||
namespace {
|
||||
bool IsValidAgentCardTypeValue(int32_t type)
|
||||
{
|
||||
return type >= static_cast<int32_t>(AgentCardType::APP) &&
|
||||
type <= static_cast<int32_t>(AgentCardType::ATOMIC_SERVICE);
|
||||
}
|
||||
|
||||
bool IsObject(napi_env env, napi_value value)
|
||||
{
|
||||
if (value == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "null value");
|
||||
return false;
|
||||
}
|
||||
napi_valuetype type = napi_undefined;
|
||||
if (napi_typeof(env, value, &type) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "typeof failed");
|
||||
return false;
|
||||
}
|
||||
if (type != napi_object) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "not object");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNamedProperty(napi_env env, napi_value object, const char *name, napi_value &value)
|
||||
{
|
||||
bool hasProperty = false;
|
||||
if (napi_has_named_property(env, object, name, &hasProperty) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "has %{public}s failed", name);
|
||||
return false;
|
||||
}
|
||||
if (!hasProperty) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "missing %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
if (napi_get_named_property(env, object, name, &value) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get %{public}s failed", name);
|
||||
return false;
|
||||
}
|
||||
if (value == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "%{public}s is null", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseRequiredStringProperty(napi_env env, napi_value object, const char *name, std::string &value)
|
||||
{
|
||||
napi_value property = nullptr;
|
||||
if (!GetNamedProperty(env, object, name, property)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get %{public}s failed", name);
|
||||
return false;
|
||||
}
|
||||
if (!ConvertFromJsValue(env, property, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
if (value.empty()) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "empty %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseOptionalStringProperty(napi_env env, napi_value object, const char *name, std::string &value)
|
||||
{
|
||||
napi_value property = nullptr;
|
||||
if (!GetNamedProperty(env, object, name, property)) {
|
||||
return true;
|
||||
}
|
||||
if (!ConvertFromJsValue(env, property, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseOptionalBoolProperty(napi_env env, napi_value object, const char *name, bool &value)
|
||||
{
|
||||
napi_value property = nullptr;
|
||||
if (!GetNamedProperty(env, object, name, property)) {
|
||||
return true;
|
||||
}
|
||||
if (!ConvertFromJsValue(env, property, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseOptionalInt32Property(napi_env env, napi_value object, const char *name, int32_t &value)
|
||||
{
|
||||
napi_value property = nullptr;
|
||||
if (!GetNamedProperty(env, object, name, property)) {
|
||||
return true;
|
||||
}
|
||||
if (!ConvertFromJsValue(env, property, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad %{public}s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseStringArray(napi_env env, napi_value value, std::vector<std::string> &out)
|
||||
{
|
||||
bool isArray = false;
|
||||
if (napi_is_array(env, value, &isArray) != napi_ok || !isArray) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "not array");
|
||||
return false;
|
||||
}
|
||||
uint32_t length = 0;
|
||||
if (napi_get_array_length(env, value, &length) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get length failed");
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
napi_value element = nullptr;
|
||||
if (napi_get_element(env, value, i, &element) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get item %{public}u failed", i);
|
||||
return false;
|
||||
}
|
||||
std::string item;
|
||||
if (!ConvertFromJsValue(env, element, item) || item.empty()) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad item %{public}u", i);
|
||||
return false;
|
||||
}
|
||||
out.emplace_back(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
napi_value CreateJsAgentProvider(napi_env env, const AgentProvider &provider)
|
||||
{
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "create provider");
|
||||
@@ -141,6 +275,7 @@ napi_value CreateJsAgentCard(napi_env env, const AgentCard &card)
|
||||
return nullptr;
|
||||
}
|
||||
napi_set_named_property(env, object, "agentId", CreateJsValue(env, card.agentId));
|
||||
napi_set_named_property(env, object, "type", CreateJsValue(env, static_cast<int32_t>(card.type)));
|
||||
napi_set_named_property(env, object, "name", CreateJsValue(env, card.name));
|
||||
napi_set_named_property(env, object, "description", CreateJsValue(env, card.description));
|
||||
napi_set_named_property(env, object, "version", CreateJsValue(env, card.version));
|
||||
@@ -189,5 +324,238 @@ napi_value CreateJsAgentCardArray(napi_env env, const std::vector<AgentCard> &ca
|
||||
TAG_LOGD(AAFwkTag::SER_ROUTER, "end");
|
||||
return object;
|
||||
}
|
||||
|
||||
bool ParseJsAgentProvider(napi_env env, napi_value value, AgentProvider &provider)
|
||||
{
|
||||
if (!IsObject(env, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "provider not object");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "organization", provider.organization)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad provider.organization");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "url", provider.url)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad provider.url");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseJsAgentCapabilities(napi_env env, napi_value value, AgentCapabilities &capabilities)
|
||||
{
|
||||
if (!IsObject(env, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "capabilities not object");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalBoolProperty(env, value, "streaming", capabilities.streaming)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad capabilities.streaming");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalBoolProperty(env, value, "pushNotifications", capabilities.pushNotifications)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad capabilities.pushNotifications");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalBoolProperty(env, value, "stateTransitionHistory", capabilities.stateTransitionHistory)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad capabilities.stateTransitionHistory");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalBoolProperty(env, value, "extendedAgentCard", capabilities.extendedAgentCard)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad capabilities.extendedAgentCard");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalStringProperty(env, value, "extension", capabilities.extension)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad capabilities.extension");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseJsAgentSkill(napi_env env, napi_value value, AgentSkill &skill)
|
||||
{
|
||||
if (!IsObject(env, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "skill not object");
|
||||
return false;
|
||||
}
|
||||
|
||||
napi_value property = nullptr;
|
||||
if (!ParseRequiredStringProperty(env, value, "id", skill.id)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.id");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "name", skill.name)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.name");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "description", skill.description)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.description");
|
||||
return false;
|
||||
}
|
||||
if (!GetNamedProperty(env, value, "tags", property) || !ParseStringArray(env, property, skill.tags)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.tags");
|
||||
return false;
|
||||
}
|
||||
if (GetNamedProperty(env, value, "examples", property) && !ParseStringArray(env, property, skill.examples)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.examples");
|
||||
return false;
|
||||
}
|
||||
if (GetNamedProperty(env, value, "inputModes", property) && !ParseStringArray(env, property, skill.inputModes)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.inputModes");
|
||||
return false;
|
||||
}
|
||||
if (GetNamedProperty(env, value, "outputModes", property) &&
|
||||
!ParseStringArray(env, property, skill.outputModes)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.outputModes");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalStringProperty(env, value, "extension", skill.extension)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill.extension");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseJsAgentAppInfo(napi_env env, napi_value value, AgentAppInfo &appInfo)
|
||||
{
|
||||
if (!IsObject(env, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "appInfo not object");
|
||||
return false;
|
||||
}
|
||||
|
||||
napi_value property = nullptr;
|
||||
if (!ParseRequiredStringProperty(env, value, "bundleName", appInfo.bundleName)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad appInfo.bundleName");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "abilityName", appInfo.abilityName)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad appInfo.abilityName");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalStringProperty(env, value, "moduleName", appInfo.moduleName)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad appInfo.moduleName");
|
||||
return false;
|
||||
}
|
||||
if (!ParseOptionalStringProperty(env, value, "minAppVersion", appInfo.minAppVersion)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad appInfo.minAppVersion");
|
||||
return false;
|
||||
}
|
||||
if (GetNamedProperty(env, value, "deviceTypes", property) &&
|
||||
!ParseStringArray(env, property, appInfo.deviceTypes)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad appInfo.deviceTypes");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseJsAgentCard(napi_env env, napi_value value, AgentCard &card)
|
||||
{
|
||||
if (!IsObject(env, value)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "card not object");
|
||||
return false;
|
||||
}
|
||||
|
||||
napi_value property = nullptr;
|
||||
if (!ParseRequiredStringProperty(env, value, "agentId", card.agentId)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.agentId");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "name", card.name)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.name");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "description", card.description)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.description");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "version", card.version)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.version");
|
||||
return false;
|
||||
}
|
||||
if (!ParseRequiredStringProperty(env, value, "category", card.category)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.category");
|
||||
return false;
|
||||
}
|
||||
int32_t typeValue = static_cast<int32_t>(AgentCardType::APP);
|
||||
if (!ParseOptionalInt32Property(env, value, "type", typeValue)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.type");
|
||||
return false;
|
||||
}
|
||||
if (!IsValidAgentCardTypeValue(typeValue)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "invalid card.type %{public}d", typeValue);
|
||||
return false;
|
||||
}
|
||||
card.type = static_cast<AgentCardType>(typeValue);
|
||||
if (!GetNamedProperty(env, value, "defaultInputModes", property) ||
|
||||
!ParseStringArray(env, property, card.defaultInputModes)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.defaultInputModes");
|
||||
return false;
|
||||
}
|
||||
if (!GetNamedProperty(env, value, "defaultOutputModes", property) ||
|
||||
!ParseStringArray(env, property, card.defaultOutputModes)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.defaultOutputModes");
|
||||
return false;
|
||||
}
|
||||
if (!GetNamedProperty(env, value, "skills", property)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "missing card.skills");
|
||||
return false;
|
||||
}
|
||||
bool isArray = false;
|
||||
if (napi_is_array(env, property, &isArray) != napi_ok || !isArray) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "card.skills not array");
|
||||
return false;
|
||||
}
|
||||
uint32_t length = 0;
|
||||
if (napi_get_array_length(env, property, &length) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get card.skills length failed");
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
napi_value skillValue = nullptr;
|
||||
if (napi_get_element(env, property, i, &skillValue) != napi_ok) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "get skill %{public}u failed", i);
|
||||
return false;
|
||||
}
|
||||
auto skill = std::make_shared<AgentSkill>();
|
||||
if (!ParseJsAgentSkill(env, skillValue, *skill)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad skill %{public}u", i);
|
||||
return false;
|
||||
}
|
||||
card.skills.emplace_back(skill);
|
||||
}
|
||||
|
||||
if (GetNamedProperty(env, value, "provider", property)) {
|
||||
auto provider = std::make_shared<AgentProvider>();
|
||||
if (!ParseJsAgentProvider(env, property, *provider)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.provider");
|
||||
return false;
|
||||
}
|
||||
card.provider = provider;
|
||||
}
|
||||
if (GetNamedProperty(env, value, "capabilities", property)) {
|
||||
auto capabilities = std::make_shared<AgentCapabilities>();
|
||||
if (!ParseJsAgentCapabilities(env, property, *capabilities)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.capabilities");
|
||||
return false;
|
||||
}
|
||||
card.capabilities = capabilities;
|
||||
}
|
||||
if (!ParseOptionalStringProperty(env, value, "documentationUrl", card.documentationUrl) ||
|
||||
!ParseOptionalStringProperty(env, value, "iconUrl", card.iconUrl) ||
|
||||
!ParseOptionalStringProperty(env, value, "extension", card.extension)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card optional string");
|
||||
return false;
|
||||
}
|
||||
if (!GetNamedProperty(env, value, "appInfo", property)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "missing card.appInfo");
|
||||
return false;
|
||||
}
|
||||
auto appInfo = std::make_shared<AgentAppInfo>();
|
||||
if (!ParseJsAgentAppInfo(env, property, *appInfo)) {
|
||||
TAG_LOGE(AAFwkTag::SER_ROUTER, "bad card.appInfo");
|
||||
return false;
|
||||
}
|
||||
card.appInfo = appInfo;
|
||||
return true;
|
||||
}
|
||||
} // namespace AgentRuntime
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -113,6 +113,12 @@ constexpr const char* ERROR_MSG_CALLER_NOT_ATOMIC_SERVICE =
|
||||
"The caller is not an atomic service.";
|
||||
constexpr const char* ERROR_MSG_AGENT_ID_NOT_EXIST =
|
||||
"The specified agentId does not exist.";
|
||||
constexpr const char* ERROR_MSG_AGENT_CARD_VERSION_TOO_OLD =
|
||||
"The specified agent card version is older than the existing version.";
|
||||
constexpr const char* ERROR_MSG_AGENT_CARD_VERSION_INVALID =
|
||||
"The specified agent card version is invalid.";
|
||||
constexpr const char* ERROR_MSG_AGENT_CARD_DUPLICATE_REGISTER =
|
||||
"The specified agent card has already been registered. Use updateAgentCard instead.";
|
||||
constexpr const char* ERROR_MSG_MAX_CONNECTIONS_REACHED =
|
||||
"Maximum connections from the same caller have been reached. "
|
||||
"Please disconnect at least one agent extension beforehand.";
|
||||
@@ -241,6 +247,9 @@ static std::unordered_map<AbilityErrorCode, const char*> ERR_CODE_MAP = {
|
||||
{ AbilityErrorCode::ERROR_CODE_TARGET_NOT_STARTED, ERROR_TARGET_NOT_STARTED},
|
||||
{ AbilityErrorCode::ERROR_CODE_CALLER_NOT_ATOMIC_SERVICE, ERROR_MSG_CALLER_NOT_ATOMIC_SERVICE},
|
||||
{ AbilityErrorCode::ERROR_CODE_AGENT_ID_NOT_EXIST, ERROR_MSG_AGENT_ID_NOT_EXIST},
|
||||
{ AbilityErrorCode::ERROR_CODE_AGENT_CARD_VERSION_TOO_OLD, ERROR_MSG_AGENT_CARD_VERSION_TOO_OLD},
|
||||
{ AbilityErrorCode::ERROR_CODE_AGENT_CARD_VERSION_INVALID, ERROR_MSG_AGENT_CARD_VERSION_INVALID},
|
||||
{ AbilityErrorCode::ERROR_CODE_AGENT_CARD_DUPLICATE_REGISTER, ERROR_MSG_AGENT_CARD_DUPLICATE_REGISTER},
|
||||
{ AbilityErrorCode::ERROR_CODE_MAX_CONNECTIONS_REACHED, ERROR_MSG_MAX_CONNECTIONS_REACHED },
|
||||
{ AbilityErrorCode::ERROR_CODE_NOT_UI_ABILITY_CONTEXT, ERROR_MSG_NOT_UI_ABILITY_CONTEXT},
|
||||
{ AbilityErrorCode::ERROR_CODE_INVALID_MAIN_ELEMENT_TYPE, ERROR_MSG_INVALID_MAIN_ELEMENT_TYPE},
|
||||
@@ -357,6 +366,9 @@ static std::unordered_map<int32_t, AbilityErrorCode> INNER_TO_JS_ERROR_CODE_MAP
|
||||
{ERR_CALLER_NOT_ATOMIC_SERVICE, AbilityErrorCode::ERROR_CODE_CALLER_NOT_ATOMIC_SERVICE},
|
||||
{ERR_INVALID_AGENT_CARD_ID, AbilityErrorCode::ERROR_CODE_AGENT_ID_NOT_EXIST},
|
||||
{ERR_MAX_AGENT_CONNECTIONS_REACHED, AbilityErrorCode::ERROR_CODE_MAX_CONNECTIONS_REACHED},
|
||||
{ERR_AGENT_CARD_VERSION_TOO_OLD, AbilityErrorCode::ERROR_CODE_AGENT_CARD_VERSION_TOO_OLD},
|
||||
{ERR_INVALID_AGENT_CARD_VERSION, AbilityErrorCode::ERROR_CODE_AGENT_CARD_VERSION_INVALID},
|
||||
{ERR_AGENT_CARD_DUPLICATE_REGISTER, AbilityErrorCode::ERROR_CODE_AGENT_CARD_DUPLICATE_REGISTER},
|
||||
{ERR_INVALID_MAIN_ELEMENT_TYPE, AbilityErrorCode::ERROR_CODE_INVALID_MAIN_ELEMENT_TYPE},
|
||||
{ERR_CHANGE_KEEP_ALIVE, AbilityErrorCode::ERROR_CODE_CHANGE_KEEP_ALIVE},
|
||||
{ERR_NO_U1, AbilityErrorCode::ERROR_CODE_NO_U1},
|
||||
|
||||
@@ -221,6 +221,15 @@ enum class AbilityErrorCode {
|
||||
// Maximum connections from the same caller have been reached.
|
||||
ERROR_CODE_MAX_CONNECTIONS_REACHED = 35600003,
|
||||
|
||||
// The specified agent card version is older than the existing version.
|
||||
ERROR_CODE_AGENT_CARD_VERSION_TOO_OLD = 35600004,
|
||||
|
||||
// The specified agent card version is invalid.
|
||||
ERROR_CODE_AGENT_CARD_VERSION_INVALID = 35600005,
|
||||
|
||||
// The specified agent card has already been registered.
|
||||
ERROR_CODE_AGENT_CARD_DUPLICATE_REGISTER = 35600006,
|
||||
|
||||
// invalid caller.
|
||||
ERROR_CODE_INVALID_CALLER = 16200001,
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ HWTEST_F(AbilityBusinessErrorTest, GetJsErrorCodeByNativeError_0100, TestSize.Le
|
||||
|
||||
result = GetJsErrorCodeByNativeError(AAFwk::ERR_MAX_AGENT_CONNECTIONS_REACHED);
|
||||
EXPECT_TRUE(result == AbilityErrorCode::ERROR_CODE_MAX_CONNECTIONS_REACHED);
|
||||
|
||||
result = GetJsErrorCodeByNativeError(OHOS::AAFwk::ERR_INVALID_AGENT_CARD_VERSION);
|
||||
EXPECT_TRUE(result == AbilityErrorCode::ERROR_CODE_AGENT_CARD_VERSION_INVALID);
|
||||
|
||||
result = GetJsErrorCodeByNativeError(OHOS::AAFwk::ERR_AGENT_CARD_DUPLICATE_REGISTER);
|
||||
EXPECT_TRUE(result == AbilityErrorCode::ERROR_CODE_AGENT_CARD_DUPLICATE_REGISTER);
|
||||
}
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
|
||||
Reference in New Issue
Block a user