1 /*
2 * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "distributed_bundle.h"
16
17 #include "app_log_wrapper.h"
18 #include "appexecfwk_errors.h"
19 #include "bundle_constants.h"
20 #include "bundle_errors.h"
21 #include "business_error.h"
22 #include "common_func.h"
23 #include "distributed_bms_interface.h"
24 #include "distributed_bms_proxy.h"
25 #include "distributed_helper.h"
26 #include "if_system_ability_manager.h"
27 #include "ipc_skeleton.h"
28 #include "iservice_registry.h"
29 #include "napi_arg.h"
30 #include "napi_constants.h"
31 #include "napi/native_api.h"
32 #include "napi/native_common.h"
33 #include "napi/native_node_api.h"
34 #include "securec.h"
35 #include "system_ability_definition.h"
36
37 namespace OHOS {
38 namespace AppExecFwk {
39
ConvertElementName(napi_env env,napi_value objElementName,const ElementName & elementName)40 static void ConvertElementName(napi_env env, napi_value objElementName, const ElementName &elementName)
41 {
42 napi_value nDeviceId;
43 NAPI_CALL_RETURN_VOID(
44 env, napi_create_string_utf8(env, elementName.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
45 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "deviceId", nDeviceId));
46
47 napi_value nBundleName;
48 NAPI_CALL_RETURN_VOID(
49 env, napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &nBundleName));
50 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "bundleName", nBundleName));
51
52 napi_value nModuleName;
53 NAPI_CALL_RETURN_VOID(
54 env, napi_create_string_utf8(env, elementName.GetModuleName().c_str(), NAPI_AUTO_LENGTH, &nModuleName));
55 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "moduleName", nModuleName));
56
57 napi_value nAbilityName;
58 NAPI_CALL_RETURN_VOID(
59 env, napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &nAbilityName));
60 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "abilityName", nAbilityName));
61 }
62
ConvertRemoteAbilityInfo(napi_env env,const RemoteAbilityInfo & remoteAbilityInfo,napi_value objRemoteAbilityInfo)63 static void ConvertRemoteAbilityInfo(
64 napi_env env, const RemoteAbilityInfo &remoteAbilityInfo, napi_value objRemoteAbilityInfo)
65 {
66 napi_value objElementName;
67 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objElementName));
68 ConvertElementName(env, objElementName, remoteAbilityInfo.elementName);
69 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "elementName", objElementName));
70
71 napi_value nLabel;
72 NAPI_CALL_RETURN_VOID(
73 env, napi_create_string_utf8(env, remoteAbilityInfo.label.c_str(), NAPI_AUTO_LENGTH, &nLabel));
74 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "label", nLabel));
75
76 napi_value nIcon;
77 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, remoteAbilityInfo.icon.c_str(), NAPI_AUTO_LENGTH, &nIcon));
78 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "icon", nIcon));
79 }
80
ConvertRemoteAbilityInfos(napi_env env,const std::vector<RemoteAbilityInfo> & remoteAbilityInfos,napi_value objRemoteAbilityInfos)81 static void ConvertRemoteAbilityInfos(
82 napi_env env, const std::vector<RemoteAbilityInfo> &remoteAbilityInfos, napi_value objRemoteAbilityInfos)
83 {
84 if (remoteAbilityInfos.size() == 0) {
85 APP_LOGE("ConvertRemoteAbilityInfos remoteAbilityInfos is empty");
86 return;
87 }
88 size_t index = 0;
89 for (const auto &remoteAbilityInfo : remoteAbilityInfos) {
90 APP_LOGD("remoteAbilityInfo bundleName:%{public}s, abilityName:%{public}s, label:%{public}s",
91 remoteAbilityInfo.elementName.GetBundleName().c_str(),
92 remoteAbilityInfo.elementName.GetAbilityName().c_str(),
93 remoteAbilityInfo.label.c_str());
94 napi_value objRemoteAbilityInfo = nullptr;
95 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRemoteAbilityInfo));
96 ConvertRemoteAbilityInfo(env, remoteAbilityInfo, objRemoteAbilityInfo);
97 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRemoteAbilityInfos, index, objRemoteAbilityInfo));
98 index++;
99 }
100 }
101
ParseElementName(napi_env env,napi_value args,OHOS::AppExecFwk::ElementName & elementName)102 static bool ParseElementName(napi_env env, napi_value args, OHOS::AppExecFwk::ElementName &elementName)
103 {
104 APP_LOGD("begin to parse ElementName");
105 napi_valuetype valueType;
106 napi_status status = napi_typeof(env, args, &valueType);
107 if ((status != napi_ok)|| (valueType != napi_object)) {
108 APP_LOGE("args not object type");
109 return false;
110 }
111 std::string deviceId;
112 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "deviceId", true, deviceId)) {
113 APP_LOGE("begin to parse ElementName deviceId failed");
114 return false;
115 }
116 elementName.SetDeviceID(deviceId);
117
118 std::string bundleName;
119 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "bundleName", true, bundleName)) {
120 APP_LOGE("begin to parse ElementName bundleName failed");
121 return false;
122 }
123 elementName.SetBundleName(bundleName);
124
125 std::string abilityName;
126 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "abilityName", true, abilityName)) {
127 APP_LOGE("begin to parse ElementName abilityName failed");
128 return false;
129 }
130 elementName.SetAbilityName(abilityName);
131
132 std::string moduleName;
133 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "moduleName", false, moduleName)) {
134 APP_LOGE("begin to parse ElementName moduleName failed");
135 return false;
136 }
137 elementName.SetModuleName(moduleName);
138 APP_LOGD("parse ElementName end");
139 return true;
140 }
141
ParseElementNames(napi_env env,napi_value args,bool & isArray,std::vector<ElementName> & elementNames)142 static bool ParseElementNames(napi_env env, napi_value args, bool &isArray, std::vector<ElementName> &elementNames)
143 {
144 APP_LOGD("begin to parse ElementNames");
145 NAPI_CALL_BASE(env, napi_is_array(env, args, &isArray), false);
146 if (!isArray) {
147 APP_LOGD("parseElementNames args not array");
148 ElementName elementName;
149 if (ParseElementName(env, args, elementName)) {
150 elementNames.push_back(elementName);
151 return true;
152 }
153 return false;
154 }
155 uint32_t arrayLength = 0;
156 NAPI_CALL_BASE(env, napi_get_array_length(env, args, &arrayLength), false);
157 APP_LOGD("arrayLength:%{public}d", arrayLength);
158 if (arrayLength == 0) {
159 APP_LOGE("error: ElementNames is empty");
160 return false;
161 }
162 for (uint32_t i = 0; i < arrayLength; i++) {
163 napi_value value = nullptr;
164 NAPI_CALL_BASE(env, napi_get_element(env, args, i, &value), false);
165 napi_valuetype valueType = napi_undefined;
166 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
167 if (valueType != napi_object) {
168 APP_LOGE("array inside not object type");
169 elementNames.clear();
170 return false;
171 }
172 ElementName elementName;
173 if (!ParseElementName(env, value, elementName)) {
174 APP_LOGE("elementNames parse elementName failed");
175 return false;
176 }
177 elementNames.push_back(elementName);
178 }
179 return true;
180 }
181
GetRemoteAbilityInfoExec(napi_env env,void * data)182 void GetRemoteAbilityInfoExec(napi_env env, void *data)
183 {
184 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo = reinterpret_cast<GetRemoteAbilityInfoCallbackInfo*>(data);
185 if (asyncCallbackInfo == nullptr) {
186 APP_LOGE("asyncCallbackInfo is null");
187 return;
188 }
189 asyncCallbackInfo->err = DistributedHelper::InnerGetRemoteAbilityInfo(asyncCallbackInfo->elementNames,
190 asyncCallbackInfo->locale, asyncCallbackInfo->isArray, asyncCallbackInfo->remoteAbilityInfos);
191 }
192
GetRemoteAbilityInfoComplete(napi_env env,napi_status status,void * data)193 void GetRemoteAbilityInfoComplete(napi_env env, napi_status status, void *data)
194 {
195 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo = reinterpret_cast<GetRemoteAbilityInfoCallbackInfo*>(data);
196 if (asyncCallbackInfo == nullptr) {
197 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
198 return;
199 }
200 std::unique_ptr<GetRemoteAbilityInfoCallbackInfo> callbackPtr {asyncCallbackInfo};
201 napi_value result[ARGS_SIZE_TWO] = {0};
202 if ((asyncCallbackInfo->err == SUCCESS) && !asyncCallbackInfo->remoteAbilityInfos.empty()) {
203 NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &result[0]));
204 if (callbackPtr->isArray) {
205 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result[ARGS_SIZE_ONE]));
206 ConvertRemoteAbilityInfos(env, asyncCallbackInfo->remoteAbilityInfos, result[ARGS_SIZE_ONE]);
207 } else {
208 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[ARGS_SIZE_ONE]));
209 ConvertRemoteAbilityInfo(env, asyncCallbackInfo->remoteAbilityInfos[0], result[ARGS_SIZE_ONE]);
210 }
211 } else {
212 result[0] = BusinessError::CreateCommonError(env, asyncCallbackInfo->err,
213 RESOURCE_NAME_GET_REMOTE_ABILITY_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
214 }
215 if (asyncCallbackInfo->deferred) {
216 if (asyncCallbackInfo->err == SUCCESS) {
217 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[ARGS_SIZE_ONE]));
218 } else {
219 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
220 }
221 } else {
222 napi_value callback = nullptr;
223 napi_value placeHolder = nullptr;
224 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
225 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
226 sizeof(result) / sizeof(result[0]), result, &placeHolder));
227 }
228 }
229
GetRemoteAbilityInfo(napi_env env,napi_callback_info info)230 napi_value GetRemoteAbilityInfo(napi_env env, napi_callback_info info)
231 {
232 APP_LOGD("begin to GetRemoteAbilityInfo");
233 NapiArg args(env, info);
234 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo =
235 new (std::nothrow) GetRemoteAbilityInfoCallbackInfo(env);
236 if (asyncCallbackInfo == nullptr) {
237 return nullptr;
238 }
239 std::unique_ptr<GetRemoteAbilityInfoCallbackInfo> callbackPtr {asyncCallbackInfo};
240 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_THREE)) {
241 APP_LOGE("param count invalid.");
242 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
243 return nullptr;
244 }
245 for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
246 napi_valuetype valueType = napi_undefined;
247 napi_typeof(env, args[i], &valueType);
248 if ((i == ARGS_POS_ZERO) && (!ParseElementNames(env, args[i], asyncCallbackInfo->isArray,
249 asyncCallbackInfo->elementNames))) {
250 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR,
251 PARAMETER_ELEMENT_NAME, TYPE_OBJECT);
252 return nullptr;
253 } else if (((i == ARGS_POS_ONE) && (valueType == napi_function)) ||
254 ((i == ARGS_POS_TWO) && (valueType == napi_function))) {
255 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callback));
256 break;
257 } else if ((i == ARGS_POS_ONE) && !CommonFunc::ParseString(env, args[i], asyncCallbackInfo->locale)) {
258 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETER_LOCALE, TYPE_STRING);
259 return nullptr;
260 }
261 }
262 if (asyncCallbackInfo->elementNames.size() > GET_REMOTE_ABILITY_INFO_MAX_SIZE) {
263 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR,
264 "BusinessError 401: The number of ElementNames is greater than 10");
265 return nullptr;
266 }
267 auto promise = CommonFunc::AsyncCallNativeMethod<GetRemoteAbilityInfoCallbackInfo>(env, asyncCallbackInfo,
268 RESOURCE_NAME_GET_REMOTE_ABILITY_INFO, GetRemoteAbilityInfoExec, GetRemoteAbilityInfoComplete);
269 callbackPtr.release();
270 APP_LOGD("GetRemoteAbilityInfo end");
271 return promise;
272 }
273 } // namespace AppExecFwk
274 } // namespace OHOS
275