• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include "napi_edm_adapter.h"
17 
18 #include <sstream>
19 
20 #include "edm_log.h"
21 #include "napi_edm_common.h"
22 #include "napi_edm_error.h"
23 
24 namespace OHOS {
25 namespace EDM {
26 namespace {
27 constexpr int32_t HAS_ADMIN = 0;
28 constexpr int32_t WITHOUT_ADMIN = 1;
29 constexpr int32_t WITHOUT_USERID = 0;
30 constexpr int32_t HAS_USERID = 1;
31 const std::u16string DESCRIPTOR = u"ohos.edm.IEnterpriseDeviceMgr";
32 }
33 
ElementNullArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)34 static bool ElementNullArgToData(napi_env env, napi_value argv, MessageParcel &data,
35     const AddonMethodSign &methodSign)
36 {
37     if (methodSign.methodAttribute == MethodAttribute::GET) {
38         data.WriteString(methodSign.apiVersionTag);
39     }
40     OHOS::AppExecFwk::ElementName elementName;
41     bool isElement = ParseElementName(env, elementName, argv);
42     bool isNull = MatchValueType(env, argv, napi_null);
43     if (!isElement && !isNull) {
44         return false;
45     }
46     if (isNull) {
47         data.WriteInt32(WITHOUT_ADMIN);
48     } else {
49         data.WriteInt32(HAS_ADMIN);
50         data.WriteParcelable(&elementName);
51     }
52     if (methodSign.methodAttribute == MethodAttribute::HANDLE) {
53         data.WriteString(methodSign.apiVersionTag);
54     }
55     return true;
56 }
57 
ElementArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)58 static bool ElementArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
59 {
60     if (methodSign.methodAttribute == MethodAttribute::GET) {
61         data.WriteString(methodSign.apiVersionTag);
62     }
63     OHOS::AppExecFwk::ElementName elementName;
64     bool isElement = ParseElementName(env, elementName, argv);
65     if (!isElement) {
66         return false;
67     }
68     if (methodSign.methodAttribute == MethodAttribute::GET) {
69         data.WriteInt32(HAS_ADMIN);
70     }
71     data.WriteParcelable(&elementName);
72     if (methodSign.methodAttribute == MethodAttribute::HANDLE) {
73         data.WriteString(methodSign.apiVersionTag);
74     }
75     return true;
76 }
77 
Uint32ArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)78 static bool Uint32ArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
79 {
80     uint32_t uintValue = 0;
81     bool isUint = ParseUint(env, uintValue, argv);
82     if (!isUint) {
83         return false;
84     }
85     data.WriteUint32(uintValue);
86     return true;
87 }
88 
StringArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)89 static bool StringArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
90 {
91     std::string strValue;
92     bool isString = ParseString(env, strValue, argv);
93     if (!isString) {
94         return false;
95     }
96     data.WriteString(strValue);
97     return true;
98 }
99 
ArrayStringArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)100 static bool ArrayStringArgToData(napi_env env, napi_value argv, MessageParcel &data,
101     const AddonMethodSign &methodSign)
102 {
103     std::vector<std::string> strArrValue;
104     bool isStringArr = ParseStringArray(env, strArrValue, argv);
105     if (!isStringArr) {
106         return false;
107     }
108     data.WriteStringVector(strArrValue);
109     return true;
110 }
111 
BooleanArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)112 static bool BooleanArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
113 {
114     bool blValue = false;
115     bool isBool = ParseBool(env, blValue, argv);
116     if (!isBool) {
117         return false;
118     }
119     data.WriteBool(blValue);
120     return true;
121 }
122 
Int32ArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)123 static bool Int32ArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
124 {
125     int32_t int32Value = 0;
126     bool isUint = ParseInt(env, int32Value, argv);
127     if (!isUint) {
128         return false;
129     }
130     data.WriteInt32(int32Value);
131     return true;
132 }
133 
Int64ArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)134 static bool Int64ArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
135 {
136     int64_t int64Value = 0;
137     bool isUint = ParseLong(env, int64Value, argv);
138     if (!isUint) {
139         return false;
140     }
141     data.WriteInt64(int64Value);
142     return true;
143 }
144 
UserIdArgToData(napi_env env,napi_value * argv,const AddonMethodSign & methodSign,MessageParcel & data,std::string & errorStr)145 static bool UserIdArgToData(napi_env env, napi_value *argv, const AddonMethodSign &methodSign,
146     MessageParcel &data, std::string &errorStr)
147 {
148     auto it = std::find(methodSign.argsType.begin(), methodSign.argsType.end(), EdmAddonCommonType::USERID);
149     if (it != methodSign.argsType.end()) {
150         int32_t index = it - methodSign.argsType.begin();
151         JsArgToData argConvert = methodSign.argsConvert[index];
152         std::ostringstream errorMsg;
153         errorMsg << "The " << index << "th parameter must be number.";
154         if (argConvert == nullptr) {
155             uint32_t userIdValue = 0;
156             bool isUint = ParseUint(env, userIdValue, argv[index]);
157             if (!isUint) {
158                 errorStr = errorMsg.str();
159                 return false;
160             }
161             data.WriteUint32(HAS_USERID);
162             data.WriteUint32(userIdValue);
163         } else {
164             bool convertResult = argConvert(env, argv[index], data, methodSign);
165             if (!convertResult) {
166                 errorStr = errorMsg.str();
167                 return false;
168             }
169         }
170     } else {
171         if (methodSign.methodAttribute != MethodAttribute::OPERATE_ADMIN) {
172             data.WriteUint32(WITHOUT_USERID);
173         }
174     }
175     return true;
176 }
177 
EdmAddonCommonType2String(EdmAddonCommonType argType)178 static std::string EdmAddonCommonType2String(EdmAddonCommonType argType)
179 {
180     switch (argType) {
181         case EdmAddonCommonType::ELEMENT_NULL:
182             return "want or null";
183         case EdmAddonCommonType::ELEMENT:
184             return "want";
185         case EdmAddonCommonType::UINT32:
186             return "number";
187         case EdmAddonCommonType::STRING:
188             return "string";
189         case EdmAddonCommonType::ARRAY_STRING:
190             return "string array";
191         case EdmAddonCommonType::BOOLEAN:
192             return "bool";
193         case EdmAddonCommonType::INT32:
194             return "number";
195         case EdmAddonCommonType::CUSTOM:
196             /* use custom convert */
197             [[fallthrough]];
198         default:
199             return "object";
200     }
201 }
202 
JsParamsToData(napi_env env,napi_value * argv,size_t argc,const AddonMethodSign & methodSign,MessageParcel & data)203 static napi_value JsParamsToData(napi_env env, napi_value *argv, size_t argc,
204     const AddonMethodSign &methodSign, MessageParcel &data)
205 {
206     std::map<EdmAddonCommonType, JsArgToData> funcMap = {
207         {EdmAddonCommonType::ELEMENT_NULL, ElementNullArgToData},
208         {EdmAddonCommonType::ELEMENT, ElementArgToData},
209         {EdmAddonCommonType::UINT32, Uint32ArgToData},
210         {EdmAddonCommonType::STRING, StringArgToData},
211         {EdmAddonCommonType::ARRAY_STRING, ArrayStringArgToData},
212         {EdmAddonCommonType::BOOLEAN, BooleanArgToData},
213         {EdmAddonCommonType::INT32, Int32ArgToData},
214         {EdmAddonCommonType::INT64, Int64ArgToData}
215     };
216 
217     for (size_t i = 0; i < methodSign.argsType.size(); i++) {
218         // The value cannot exceed the actual length. Default parameters may exist.
219         if (i >= argc) {
220             break;
221         }
222         EdmAddonCommonType argType = methodSign.argsType[i];
223         JsArgToData argConvert = nullptr;
224         if (methodSign.argsConvert.size() > 0) {
225             argConvert = methodSign.argsConvert[i];
226         }
227         std::ostringstream errorMsg;
228         errorMsg << "The " << i << "th parameter must be ";
229         errorMsg << EdmAddonCommonType2String(argType) << ".";
230         if (argConvert == nullptr) {
231             auto it = funcMap.find(argType);
232             if (it == funcMap.end()) {
233                 continue;
234             }
235             bool res = it->second(env, argv[i], data, methodSign);
236             if (!res) {
237                 return CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorMsg.str());
238             }
239         } else {
240             bool result = argConvert(env, argv[i], data, methodSign);
241             if (!result) {
242                 return CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorMsg.str());
243             }
244         }
245     }
246     return nullptr;
247 }
248 
JsObjectToData(napi_env env,napi_callback_info info,const AddonMethodSign & methodSign,AdapterAddonData * addonData)249 napi_value JsObjectToData(napi_env env, napi_callback_info info, const AddonMethodSign &methodSign,
250     AdapterAddonData *addonData)
251 {
252     napi_status status;
253     size_t argc = ARGS_SIZE_FIVE;
254     napi_value argv[ARGS_SIZE_FIVE];
255     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
256     // The size can meet the minimum length
257     size_t minSize = methodSign.argsType.size() - methodSign.defaultArgSize;
258     ASSERT_AND_THROW_PARAM_ERROR(env, argc >= minSize, "parameter count error");
259     EDMLOGI("AddonMethodAdapter JsObjectToData argc:%{public}zu.", argc);
260     if (argc > methodSign.argsType.size()) {
261         bool isCallBack = MatchValueType(env, argv[methodSign.argsType.size()], napi_function);
262         std::ostringstream errorMsg;
263         /* If a callback exists, there must be no default parameter.
264 		overloading of callback and default parameter types cannot be supported. */
265         errorMsg << "The " << methodSign.argsType.size() << "th parameter must be callback";
266         ASSERT_AND_THROW_PARAM_ERROR(env, isCallBack, errorMsg.str());
267     }
268     if (!methodSign.argsType.empty() && !methodSign.argsConvert.empty() &&
269         methodSign.argsType.size() != methodSign.argsConvert.size()) {
270         napi_throw(env, CreateError(env, EdmReturnErrCode::PARAM_ERROR));
271         return nullptr;
272     }
273     addonData->data.WriteInterfaceToken(DESCRIPTOR);
274 
275     std::string errorStr;
276     bool convertUserIdRes = UserIdArgToData(env, argv, methodSign, addonData->data, errorStr);
277     if (!convertUserIdRes) {
278         napi_throw(env, CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorStr));
279         return nullptr;
280     }
281 
282     napi_value errorRes = JsParamsToData(env, argv, argc, methodSign, addonData->data);
283     if (errorRes != nullptr) {
284         napi_throw(env, errorRes);
285         return nullptr;
286     }
287 
288     if (argc > methodSign.argsType.size()) {
289         // Assign a value to callback
290         status = napi_create_reference(env, argv[methodSign.argsType.size()], NAPI_RETURN_ONE, &addonData->callback);
291         std::ostringstream errorMsg;
292         errorMsg << "The " << methodSign.argsType.size() << "th parameter must be callback.";
293         ASSERT_AND_THROW_PARAM_ERROR(env, status == napi_ok, errorMsg.str());
294     }
295     napi_value result = nullptr;
296     napi_get_undefined(env, &result);
297     EDMLOGI("AddonMethodAdapter %{public}s JsObjectToData exec success.", methodSign.name.c_str());
298     addonData->policyCode = methodSign.policyCode;
299     return result;
300 }
301 
AddonMethodAdapter(napi_env env,napi_callback_info info,const AddonMethodSign & methodSign,napi_async_execute_callback execute,napi_async_complete_callback complete)302 napi_value AddonMethodAdapter(napi_env env, napi_callback_info info, const AddonMethodSign &methodSign,
303     napi_async_execute_callback execute, napi_async_complete_callback complete)
304 {
305     auto adapterAddonData = new (std::nothrow) AdapterAddonData();
306     if (adapterAddonData == nullptr) {
307         return nullptr;
308     }
309     std::unique_ptr<AdapterAddonData> adapterAddonDataPtr {adapterAddonData};
310     napi_value result = JsObjectToData(env, info, methodSign, adapterAddonData);
311     if (result == nullptr) {
312         EDMLOGE("AddonMethodAdapter JsObjectToData exec fail.");
313         return nullptr;
314     }
315     napi_value asyncWorkReturn = HandleAsyncWork(env, adapterAddonData, methodSign.name,
316         execute, complete);
317     adapterAddonDataPtr.release();
318     return asyncWorkReturn;
319 }
320 } // namespace EDM
321 } // namespace OHOS