• 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 
ArrayIntArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)112 static bool ArrayIntArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
113 {
114     std::vector<int32_t> intArrValue;
115     bool isIntArr = ParseIntArray(env, intArrValue, argv);
116     if (!isIntArr) {
117         return false;
118     }
119     data.WriteInt32Vector(intArrValue);
120     return true;
121 }
122 
BooleanArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)123 static bool BooleanArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
124 {
125     bool blValue = false;
126     bool isBool = ParseBool(env, blValue, argv);
127     if (!isBool) {
128         return false;
129     }
130     data.WriteBool(blValue);
131     return true;
132 }
133 
Int32ArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)134 static bool Int32ArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
135 {
136     int32_t int32Value = 0;
137     bool isUint = ParseInt(env, int32Value, argv);
138     if (!isUint) {
139         return false;
140     }
141     data.WriteInt32(int32Value);
142     return true;
143 }
144 
Int64ArgToData(napi_env env,napi_value argv,MessageParcel & data,const AddonMethodSign & methodSign)145 static bool Int64ArgToData(napi_env env, napi_value argv, MessageParcel &data, const AddonMethodSign &methodSign)
146 {
147     int64_t int64Value = 0;
148     bool isUint = ParseLong(env, int64Value, argv);
149     if (!isUint) {
150         return false;
151     }
152     data.WriteInt64(int64Value);
153     return true;
154 }
155 
UserIdArgToData(napi_env env,napi_value * argv,const AddonMethodSign & methodSign,MessageParcel & data,std::string & errorStr)156 static bool UserIdArgToData(napi_env env, napi_value *argv, const AddonMethodSign &methodSign,
157     MessageParcel &data, std::string &errorStr)
158 {
159     auto it = std::find(methodSign.argsType.begin(), methodSign.argsType.end(), EdmAddonCommonType::USERID);
160     if (it != methodSign.argsType.end()) {
161         int32_t index = it - methodSign.argsType.begin();
162         JsArgToData argConvert = methodSign.argsConvert[index];
163         std::ostringstream errorMsg;
164         errorMsg << "The " << index << "th parameter must be number.";
165         if (argConvert == nullptr) {
166             uint32_t userIdValue = 0;
167             bool isUint = ParseUint(env, userIdValue, argv[index]);
168             if (!isUint) {
169                 errorStr = errorMsg.str();
170                 return false;
171             }
172             data.WriteUint32(HAS_USERID);
173             data.WriteUint32(userIdValue);
174         } else {
175             bool convertResult = argConvert(env, argv[index], data, methodSign);
176             if (!convertResult) {
177                 errorStr = errorMsg.str();
178                 return false;
179             }
180         }
181     } else {
182         if (methodSign.methodAttribute != MethodAttribute::OPERATE_ADMIN) {
183             data.WriteUint32(WITHOUT_USERID);
184         }
185     }
186     return true;
187 }
188 
EdmAddonCommonType2String(EdmAddonCommonType argType)189 static std::string EdmAddonCommonType2String(EdmAddonCommonType argType)
190 {
191     switch (argType) {
192         case EdmAddonCommonType::ELEMENT_NULL:
193             return "want or null";
194         case EdmAddonCommonType::ELEMENT:
195             return "want";
196         case EdmAddonCommonType::UINT32:
197             return "number";
198         case EdmAddonCommonType::STRING:
199             return "string";
200         case EdmAddonCommonType::ARRAY_STRING:
201             return "string array";
202         case EdmAddonCommonType::BOOLEAN:
203             return "bool";
204         case EdmAddonCommonType::INT32:
205             return "number";
206         case EdmAddonCommonType::ARRAY_INT32:
207             return "number array";
208         case EdmAddonCommonType::CUSTOM:
209             /* use custom convert */
210             [[fallthrough]];
211         default:
212             return "object";
213     }
214 }
215 
JsParamsToData(napi_env env,napi_value * argv,size_t argc,const AddonMethodSign & methodSign,MessageParcel & data)216 static napi_value JsParamsToData(napi_env env, napi_value *argv, size_t argc,
217     const AddonMethodSign &methodSign, MessageParcel &data)
218 {
219     std::map<EdmAddonCommonType, JsArgToData> funcMap = {
220         {EdmAddonCommonType::ELEMENT_NULL, ElementNullArgToData},
221         {EdmAddonCommonType::ELEMENT, ElementArgToData},
222         {EdmAddonCommonType::UINT32, Uint32ArgToData},
223         {EdmAddonCommonType::STRING, StringArgToData},
224         {EdmAddonCommonType::ARRAY_STRING, ArrayStringArgToData},
225         {EdmAddonCommonType::BOOLEAN, BooleanArgToData},
226         {EdmAddonCommonType::INT32, Int32ArgToData},
227         {EdmAddonCommonType::INT64, Int64ArgToData},
228         {EdmAddonCommonType::ARRAY_INT32, ArrayIntArgToData},
229     };
230 
231     for (size_t i = 0; i < methodSign.argsType.size(); i++) {
232         // The value cannot exceed the actual length. Default parameters may exist.
233         if (i >= argc) {
234             break;
235         }
236         EdmAddonCommonType argType = methodSign.argsType[i];
237         JsArgToData argConvert = nullptr;
238         if (methodSign.argsConvert.size() > 0) {
239             argConvert = methodSign.argsConvert[i];
240         }
241         std::ostringstream errorMsg;
242         errorMsg << "The " << i << "th parameter must be ";
243         errorMsg << EdmAddonCommonType2String(argType) << ".";
244         if (argConvert == nullptr) {
245             auto it = funcMap.find(argType);
246             if (it == funcMap.end()) {
247                 continue;
248             }
249             bool res = it->second(env, argv[i], data, methodSign);
250             if (!res) {
251                 return CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorMsg.str());
252             }
253         } else {
254             bool result = argConvert(env, argv[i], data, methodSign);
255             if (!result) {
256                 return CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorMsg.str());
257             }
258         }
259     }
260     return nullptr;
261 }
262 
JsObjectToData(napi_env env,napi_callback_info info,const AddonMethodSign & methodSign,AdapterAddonData * addonData,bool isAsync)263 napi_value JsObjectToData(napi_env env, napi_callback_info info, const AddonMethodSign &methodSign,
264     AdapterAddonData *addonData, bool isAsync)
265 {
266     napi_status status;
267     size_t argc = ARGS_SIZE_FIVE;
268     napi_value argv[ARGS_SIZE_FIVE];
269     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
270     // The size can meet the minimum length
271     size_t minSize = methodSign.argsType.size() - methodSign.defaultArgSize;
272     ASSERT_AND_THROW_PARAM_ERROR(env, argc >= minSize, "parameter count error");
273     EDMLOGI("AddonMethodAdapter JsObjectToData argc:%{public}zu.", argc);
274     if (isAsync && argc > methodSign.argsType.size()) {
275         bool isCallBack = MatchValueType(env, argv[methodSign.argsType.size()], napi_function);
276         std::ostringstream errorMsg;
277         /* If a callback exists, there must be no default parameter.
278 		overloading of callback and default parameter types cannot be supported. */
279         errorMsg << "The " << methodSign.argsType.size() << "th parameter must be callback";
280         ASSERT_AND_THROW_PARAM_ERROR(env, isCallBack, errorMsg.str());
281     }
282     if (!methodSign.argsType.empty() && !methodSign.argsConvert.empty() &&
283         methodSign.argsType.size() != methodSign.argsConvert.size()) {
284         napi_throw(env, CreateError(env, EdmReturnErrCode::PARAM_ERROR));
285         return nullptr;
286     }
287     addonData->data.WriteInterfaceToken(DESCRIPTOR);
288 
289     std::string errorStr;
290     bool convertUserIdRes = UserIdArgToData(env, argv, methodSign, addonData->data, errorStr);
291     if (!convertUserIdRes) {
292         napi_throw(env, CreateError(env, EdmReturnErrCode::PARAM_ERROR, errorStr));
293         return nullptr;
294     }
295 
296     napi_value errorRes = JsParamsToData(env, argv, argc, methodSign, addonData->data);
297     if (errorRes != nullptr) {
298         napi_throw(env, errorRes);
299         return nullptr;
300     }
301 
302     if (argc > methodSign.argsType.size()) {
303         // Assign a value to callback
304         status = napi_create_reference(env, argv[methodSign.argsType.size()], NAPI_RETURN_ONE, &addonData->callback);
305         std::ostringstream errorMsg;
306         errorMsg << "The " << methodSign.argsType.size() << "th parameter must be callback.";
307         ASSERT_AND_THROW_PARAM_ERROR(env, status == napi_ok, errorMsg.str());
308     }
309     napi_value result = nullptr;
310     napi_get_undefined(env, &result);
311     EDMLOGI("AddonMethodAdapter %{public}s JsObjectToData exec success.", methodSign.name.c_str());
312     addonData->policyCode = methodSign.policyCode;
313     return result;
314 }
315 
AddonMethodAdapter(napi_env env,napi_callback_info info,const AddonMethodSign & methodSign,napi_async_execute_callback execute,napi_async_complete_callback complete)316 napi_value AddonMethodAdapter(napi_env env, napi_callback_info info, const AddonMethodSign &methodSign,
317     napi_async_execute_callback execute, napi_async_complete_callback complete)
318 {
319     auto adapterAddonData = new (std::nothrow) AdapterAddonData();
320     if (adapterAddonData == nullptr) {
321         return nullptr;
322     }
323     std::unique_ptr<AdapterAddonData> adapterAddonDataPtr {adapterAddonData};
324     napi_value result = JsObjectToData(env, info, methodSign, adapterAddonData, true);
325     if (result == nullptr) {
326         EDMLOGE("AddonMethodAdapter JsObjectToData exec fail.");
327         return nullptr;
328     }
329     napi_value asyncWorkReturn = HandleAsyncWork(env, adapterAddonData, methodSign.name,
330         execute, complete);
331     adapterAddonDataPtr.release();
332     return asyncWorkReturn;
333 }
334 } // namespace EDM
335 } // namespace OHOS