• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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