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