1 /*
2 * Copyright (c) 2022 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 "if_system_ability_manager.h"
26 #include "ipc_skeleton.h"
27 #include "iservice_registry.h"
28 #include "napi_arg.h"
29 #include "napi_constants.h"
30 #include "napi/native_api.h"
31 #include "napi/native_common.h"
32 #include "napi/native_node_api.h"
33 #include "securec.h"
34 #include "system_ability_definition.h"
35
36 namespace OHOS {
37 namespace AppExecFwk {
38 namespace {
39 constexpr int32_t GET_REMOTE_ABILITY_INFO_MAX_SIZE = 10;
40 const std::string RESOURCE_NAME_GET_REMOTE_ABILITY_INFO = "GetRemoteAbilityInfo";
41 const std::string PARAMETER_ELEMENT_NAME = "elementName";
42 const std::string PARAMETER_LOCALE = "locale";
43 }
44
GetDistributedBundleMgr()45 static OHOS::sptr<OHOS::AppExecFwk::IDistributedBms> GetDistributedBundleMgr()
46 {
47 APP_LOGD("GetDistributedBundleMgr start");
48 auto samgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
49 if (samgr == nullptr) {
50 APP_LOGE("GetDistributedBundleMgr samgr is nullptr");
51 return nullptr;
52 }
53 auto remoteObject = samgr->GetSystemAbility(OHOS::DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
54 if (remoteObject == nullptr) {
55 APP_LOGE("GetDistributedBundleMgr remoteObject is nullptr");
56 return nullptr;
57 }
58 auto distributeBundleMgr = OHOS::iface_cast<IDistributedBms>(remoteObject);
59 if (distributeBundleMgr == nullptr) {
60 APP_LOGE("GetDistributedBundleMgr distributeBundleMgr is nullptr");
61 return nullptr;
62 }
63 return distributeBundleMgr;
64 }
65
ConvertElementName(napi_env env,napi_value objElementName,const ElementName & elementName)66 static void ConvertElementName(napi_env env, napi_value objElementName, const ElementName &elementName)
67 {
68 napi_value nDeviceId;
69 NAPI_CALL_RETURN_VOID(
70 env, napi_create_string_utf8(env, elementName.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
71 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "deviceId", nDeviceId));
72
73 napi_value nBundleName;
74 NAPI_CALL_RETURN_VOID(
75 env, napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &nBundleName));
76 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "bundleName", nBundleName));
77
78 napi_value nModuleName;
79 NAPI_CALL_RETURN_VOID(
80 env, napi_create_string_utf8(env, elementName.GetModuleName().c_str(), NAPI_AUTO_LENGTH, &nModuleName));
81 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "moduleName", nModuleName));
82
83 napi_value nAbilityName;
84 NAPI_CALL_RETURN_VOID(
85 env, napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &nAbilityName));
86 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "abilityName", nAbilityName));
87 }
88
ConvertRemoteAbilityInfo(napi_env env,const RemoteAbilityInfo & remoteAbilityInfo,napi_value objRemoteAbilityInfo)89 static void ConvertRemoteAbilityInfo(
90 napi_env env, const RemoteAbilityInfo &remoteAbilityInfo, napi_value objRemoteAbilityInfo)
91 {
92 napi_value objElementName;
93 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objElementName));
94 ConvertElementName(env, objElementName, remoteAbilityInfo.elementName);
95 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "elementName", objElementName));
96
97 napi_value nLabel;
98 NAPI_CALL_RETURN_VOID(
99 env, napi_create_string_utf8(env, remoteAbilityInfo.label.c_str(), NAPI_AUTO_LENGTH, &nLabel));
100 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "label", nLabel));
101
102 napi_value nIcon;
103 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, remoteAbilityInfo.icon.c_str(), NAPI_AUTO_LENGTH, &nIcon));
104 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "icon", nIcon));
105 }
106
ConvertRemoteAbilityInfos(napi_env env,const std::vector<RemoteAbilityInfo> & remoteAbilityInfos,napi_value objRemoteAbilityInfos)107 static void ConvertRemoteAbilityInfos(
108 napi_env env, const std::vector<RemoteAbilityInfo> &remoteAbilityInfos, napi_value objRemoteAbilityInfos)
109 {
110 if (remoteAbilityInfos.size() == 0) {
111 APP_LOGE("ConvertRemoteAbilityInfos remoteAbilityInfos is empty");
112 return;
113 }
114 size_t index = 0;
115 for (const auto &remoteAbilityInfo : remoteAbilityInfos) {
116 APP_LOGD("remoteAbilityInfo bundleName:%{public}s, abilityName:%{public}s, label:%{public}s",
117 remoteAbilityInfo.elementName.GetBundleName().c_str(),
118 remoteAbilityInfo.elementName.GetAbilityName().c_str(),
119 remoteAbilityInfo.label.c_str());
120 napi_value objRemoteAbilityInfo = nullptr;
121 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRemoteAbilityInfo));
122 ConvertRemoteAbilityInfo(env, remoteAbilityInfo, objRemoteAbilityInfo);
123 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRemoteAbilityInfos, index, objRemoteAbilityInfo));
124 index++;
125 }
126 }
127
ParseElementName(napi_env env,napi_value args,OHOS::AppExecFwk::ElementName & elementName)128 static bool ParseElementName(napi_env env, napi_value args, OHOS::AppExecFwk::ElementName &elementName)
129 {
130 APP_LOGD("begin to parse ElementName");
131 napi_valuetype valueType;
132 napi_status status = napi_typeof(env, args, &valueType);
133 if ((status != napi_ok)|| (valueType != napi_object)) {
134 APP_LOGE("args not object type");
135 return false;
136 }
137 std::string deviceId;
138 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "deviceId", true, deviceId)) {
139 APP_LOGE("begin to parse ElementName deviceId failed");
140 return false;
141 }
142 elementName.SetDeviceID(deviceId);
143
144 std::string bundleName;
145 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "bundleName", true, bundleName)) {
146 APP_LOGE("begin to parse ElementName bundleName failed");
147 return false;
148 }
149 elementName.SetBundleName(bundleName);
150
151 std::string abilityName;
152 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "abilityName", true, abilityName)) {
153 APP_LOGE("begin to parse ElementName abilityName failed");
154 return false;
155 }
156 elementName.SetAbilityName(abilityName);
157
158 std::string moduleName;
159 if (!CommonFunc::ParseStringPropertyFromObject(env, args, "moduleName", false, moduleName)) {
160 APP_LOGE("begin to parse ElementName moduleName failed");
161 return false;
162 }
163 elementName.SetModuleName(moduleName);
164 APP_LOGD("parse ElementName end");
165 return true;
166 }
167
ParseElementNames(napi_env env,napi_value args,bool & isArray,std::vector<ElementName> & elementNames)168 static bool ParseElementNames(napi_env env, napi_value args, bool &isArray, std::vector<ElementName> &elementNames)
169 {
170 APP_LOGD("begin to parse ElementNames");
171 NAPI_CALL_BASE(env, napi_is_array(env, args, &isArray), false);
172 if (!isArray) {
173 APP_LOGD("parseElementNames args not array");
174 ElementName elementName;
175 if (ParseElementName(env, args, elementName)) {
176 elementNames.push_back(elementName);
177 return true;
178 }
179 return false;
180 }
181 uint32_t arrayLength = 0;
182 NAPI_CALL_BASE(env, napi_get_array_length(env, args, &arrayLength), false);
183 APP_LOGD("arrayLength:%{public}d", arrayLength);
184 if (arrayLength == 0) {
185 APP_LOGE("error: ElementNames is empty");
186 return false;
187 }
188 for (uint32_t i = 0; i < arrayLength; i++) {
189 napi_value value = nullptr;
190 NAPI_CALL_BASE(env, napi_get_element(env, args, i, &value), false);
191 napi_valuetype valueType = napi_undefined;
192 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
193 if (valueType != napi_object) {
194 APP_LOGE("array inside not object type");
195 elementNames.clear();
196 return false;
197 }
198 ElementName elementName;
199 if (!ParseElementName(env, value, elementName)) {
200 APP_LOGE("elementNames parse elementName failed");
201 return false;
202 }
203 elementNames.push_back(elementName);
204 }
205 return true;
206 }
207
InnerGetRemoteAbilityInfo(const std::vector<ElementName> & elementNames,const std::string & locale,bool isArray,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)208 int32_t InnerGetRemoteAbilityInfo(const std::vector<ElementName> &elementNames, const std::string &locale,
209 bool isArray, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
210 {
211 if (elementNames.size() == 0) {
212 APP_LOGE("InnerGetRemoteAbilityInfos elementNames is empty");
213 return ERROR_BUNDLE_SERVICE_EXCEPTION;
214 }
215 auto iDistBundleMgr = GetDistributedBundleMgr();
216 if (iDistBundleMgr == nullptr) {
217 APP_LOGE("can not get iDistBundleMgr");
218 return ERROR_DISTRIBUTED_SERVICE_NOT_RUNNING;
219 }
220 int32_t result;
221 if (isArray) {
222 result = iDistBundleMgr->GetRemoteAbilityInfos(elementNames, locale, remoteAbilityInfos);
223 } else {
224 RemoteAbilityInfo remoteAbilityInfo;
225 result = iDistBundleMgr->GetRemoteAbilityInfo(elementNames[0], locale, remoteAbilityInfo);
226 remoteAbilityInfos.push_back(remoteAbilityInfo);
227 }
228 if (result != 0) {
229 APP_LOGE("InnerGetRemoteAbilityInfo failed");
230 }
231 return CommonFunc::ConvertErrCode(result);
232 }
233
GetRemoteAbilityInfoExec(napi_env env,void * data)234 void GetRemoteAbilityInfoExec(napi_env env, void *data)
235 {
236 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo = reinterpret_cast<GetRemoteAbilityInfoCallbackInfo*>(data);
237 if (asyncCallbackInfo == nullptr) {
238 APP_LOGE("asyncCallbackInfo is null");
239 return;
240 }
241 asyncCallbackInfo->err = InnerGetRemoteAbilityInfo(asyncCallbackInfo->elementNames,
242 asyncCallbackInfo->locale, asyncCallbackInfo->isArray, asyncCallbackInfo->remoteAbilityInfos);
243 }
244
GetRemoteAbilityInfoComplete(napi_env env,napi_status status,void * data)245 void GetRemoteAbilityInfoComplete(napi_env env, napi_status status, void *data)
246 {
247 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo = reinterpret_cast<GetRemoteAbilityInfoCallbackInfo*>(data);
248 if (asyncCallbackInfo == nullptr) {
249 APP_LOGE("asyncCallbackInfo is null in %{public}s", __func__);
250 return;
251 }
252 std::unique_ptr<GetRemoteAbilityInfoCallbackInfo> callbackPtr {asyncCallbackInfo};
253 napi_value result[ARGS_SIZE_TWO] = {0};
254 if ((asyncCallbackInfo->err == SUCCESS) && !asyncCallbackInfo->remoteAbilityInfos.empty()) {
255 NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &result[0]));
256 if (callbackPtr->isArray) {
257 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result[ARGS_SIZE_ONE]));
258 ConvertRemoteAbilityInfos(env, asyncCallbackInfo->remoteAbilityInfos, result[ARGS_SIZE_ONE]);
259 } else {
260 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[ARGS_SIZE_ONE]));
261 ConvertRemoteAbilityInfo(env, asyncCallbackInfo->remoteAbilityInfos[0], result[ARGS_SIZE_ONE]);
262 }
263 } else {
264 result[0] = BusinessError::CreateCommonError(env, asyncCallbackInfo->err,
265 RESOURCE_NAME_GET_REMOTE_ABILITY_INFO, Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED);
266 }
267 if (asyncCallbackInfo->deferred) {
268 if (asyncCallbackInfo->err == SUCCESS) {
269 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[ARGS_SIZE_ONE]));
270 } else {
271 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
272 }
273 } else {
274 napi_value callback = nullptr;
275 napi_value placeHolder = nullptr;
276 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callback, &callback));
277 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback,
278 sizeof(result) / sizeof(result[0]), result, &placeHolder));
279 }
280 }
281
GetRemoteAbilityInfo(napi_env env,napi_callback_info info)282 napi_value GetRemoteAbilityInfo(napi_env env, napi_callback_info info)
283 {
284 APP_LOGD("begin to GetRemoteAbilityInfo");
285 NapiArg args(env, info);
286 GetRemoteAbilityInfoCallbackInfo *asyncCallbackInfo =
287 new (std::nothrow) GetRemoteAbilityInfoCallbackInfo(env);
288 if (asyncCallbackInfo == nullptr) {
289 return nullptr;
290 }
291 std::unique_ptr<GetRemoteAbilityInfoCallbackInfo> callbackPtr {asyncCallbackInfo};
292 if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_THREE)) {
293 APP_LOGE("param count invalid.");
294 BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
295 return nullptr;
296 }
297 for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
298 napi_valuetype valueType = napi_undefined;
299 napi_typeof(env, args[i], &valueType);
300 if ((i == ARGS_POS_ZERO) && (!ParseElementNames(env, args[i], asyncCallbackInfo->isArray,
301 asyncCallbackInfo->elementNames))) {
302 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR,
303 PARAMETER_ELEMENT_NAME, TYPE_OBJECT);
304 return nullptr;
305 } else if (((i == ARGS_POS_ONE) && (valueType == napi_function)) ||
306 ((i == ARGS_POS_TWO) && (valueType == napi_function))) {
307 NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callback));
308 break;
309 } else if ((i == ARGS_POS_ONE) && !CommonFunc::ParseString(env, args[i], asyncCallbackInfo->locale)) {
310 BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, PARAMETER_LOCALE, TYPE_STRING);
311 return nullptr;
312 }
313 }
314 if (asyncCallbackInfo->elementNames.size() > GET_REMOTE_ABILITY_INFO_MAX_SIZE) {
315 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR,
316 "BusinessError 401: The number of ElementNames is greater than 10");
317 return nullptr;
318 }
319 auto promise = CommonFunc::AsyncCallNativeMethod<GetRemoteAbilityInfoCallbackInfo>(env, asyncCallbackInfo,
320 RESOURCE_NAME_GET_REMOTE_ABILITY_INFO, GetRemoteAbilityInfoExec, GetRemoteAbilityInfoComplete);
321 callbackPtr.release();
322 APP_LOGD("GetRemoteAbilityInfo end");
323 return promise;
324 }
325 } // namespace AppExecFwk
326 } // namespace OHOS
327