1 /*
2  * Copyright (c) 2022-2023 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 "config_policy_napi.h"
17 
18 #include <vector>
19 
20 #include "hilog/log.h"
21 #include "config_policy_utils.h"
22 #include "hisysevent_adapter.h"
23 
24 #undef LOG_DOMAIN
25 #define LOG_DOMAIN 0xD001E00
26 
27 #undef LOG_TAG
28 #define LOG_TAG "ConfigPolicyJs"
29 
30 namespace OHOS {
31 namespace Customization {
32 namespace ConfigPolicy {
33 using namespace OHOS::HiviewDFX;
34 
35 static constexpr size_t ARGS_SIZE_ONE = 1;
36 static constexpr size_t ARGS_SIZE_TWO = 2;
37 static constexpr size_t ARGS_SIZE_THREE = 3;
38 static constexpr size_t ARGS_SIZE_FOUR = 4;
39 static constexpr int32_t ARR_INDEX_ZERO = 0;
40 static constexpr int32_t ARR_INDEX_ONE = 1;
41 static constexpr int32_t ARR_INDEX_TWO = 2;
42 static constexpr int32_t ARR_INDEX_THREE = 3;
43 static constexpr int32_t NAPI_RETURN_ZERO = 0;
44 static constexpr int32_t NAPI_RETURN_ONE = 1;
45 // Param Error Code
46 static constexpr int32_t PARAM_ERROR = 401;
47 
Init(napi_env env,napi_value exports)48 napi_value ConfigPolicyNapi::Init(napi_env env, napi_value exports)
49 {
50     napi_value nFollowXMode = nullptr;
51     NAPI_CALL(env, napi_create_object(env, &nFollowXMode));
52     CreateFollowXModeObject(env, nFollowXMode);
53 
54     napi_property_descriptor property[] = {
55         DECLARE_NAPI_FUNCTION("getOneCfgFile", ConfigPolicyNapi::NAPIGetOneCfgFile),
56         DECLARE_NAPI_FUNCTION("getOneCfgFileSync", ConfigPolicyNapi::NAPIGetOneCfgFileSync),
57         DECLARE_NAPI_FUNCTION("getCfgFiles", ConfigPolicyNapi::NAPIGetCfgFiles),
58         DECLARE_NAPI_FUNCTION("getCfgFilesSync", ConfigPolicyNapi::NAPIGetCfgFilesSync),
59         DECLARE_NAPI_FUNCTION("getCfgDirList", ConfigPolicyNapi::NAPIGetCfgDirList),
60         DECLARE_NAPI_FUNCTION("getCfgDirListSync", ConfigPolicyNapi::NAPIGetCfgDirListSync),
61 
62         DECLARE_NAPI_PROPERTY("FollowXMode", nFollowXMode)
63     };
64     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(property) / sizeof(property[0]), property));
65     return exports;
66 }
67 
CreateFollowXModeObject(napi_env env,napi_value value)68 void ConfigPolicyNapi::CreateFollowXModeObject(napi_env env, napi_value value)
69 {
70     napi_value nDefaultMode;
71     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_DEFAULT), &nDefaultMode));
72     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "DEFAULT", nDefaultMode));
73     napi_value nNoFollowMode;
74     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_NO_RULE_FOLLOWED),
75                           &nNoFollowMode));
76     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "NO_RULE_FOLLOWED", nNoFollowMode));
77     napi_value nSimDefaultMode;
78     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_SIM_DEFAULT),
79         &nSimDefaultMode));
80     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "SIM_DEFAULT", nSimDefaultMode));
81     napi_value nSim1Mode;
82     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_SIM_1), &nSim1Mode));
83     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "SIM_1", nSim1Mode));
84     napi_value nSim2Mode;
85     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_SIM_2), &nSim2Mode));
86     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "SIM_2", nSim2Mode));
87     napi_value nUserDefineMode;
88     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, static_cast<int32_t>(FOLLOWX_MODE_USER_DEFINED),
89         &nUserDefineMode));
90     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, value, "USER_DEFINED", nUserDefineMode));
91 }
92 
NAPIGetOneCfgFile(napi_env env,napi_callback_info info)93 napi_value ConfigPolicyNapi::NAPIGetOneCfgFile(napi_env env, napi_callback_info info)
94 {
95     HILOG_DEBUG(LOG_CORE, "NAPIGetOneCfgFile start.");
96     return GetOneCfgFileOrAllCfgFiles(env, info, "NAPIGetOneCfgFile", NativeGetOneCfgFile);
97 }
98 
NAPIGetOneCfgFileSync(napi_env env,napi_callback_info info)99 napi_value ConfigPolicyNapi::NAPIGetOneCfgFileSync(napi_env env, napi_callback_info info)
100 {
101     HILOG_DEBUG(LOG_CORE, "NAPIGetOneCfgFileSync start.");
102     return GetOneCfgFileOrAllCfgFilesSync(env, info, NativeGetOneCfgFileSync);
103 }
104 
GetOneCfgFileOrAllCfgFilesSync(napi_env env,napi_callback_info info,NapiFunction func)105 napi_value ConfigPolicyNapi::GetOneCfgFileOrAllCfgFilesSync(napi_env env, napi_callback_info info, NapiFunction func)
106 {
107     size_t argc = ARGS_SIZE_THREE;
108     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
109     napi_value thisVar = nullptr;
110     void *data = nullptr;
111     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
112     if (argc < ARGS_SIZE_ONE) {
113         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The number of parameters is incorrect.");
114     }
115 
116     auto asyncContext = std::make_shared<ConfigAsyncContext>();
117     asyncContext->followMode_ = FOLLOWX_MODE_DEFAULT;
118     bool hasExtra = false;
119     if (ParseRelPath(env, asyncContext->relPath_, argv[ARR_INDEX_ZERO]) == nullptr) {
120         return nullptr;
121     }
122 
123     if (argc == ARGS_SIZE_TWO) {
124         if (ParseFollowMode(env, asyncContext->followMode_, argv[ARR_INDEX_ONE], hasExtra) == nullptr) {
125             return nullptr;
126         }
127     }
128     if (argc >= ARGS_SIZE_THREE) {
129         hasExtra = true;
130         if (ParseFollowMode(env, asyncContext->followMode_, argv[ARR_INDEX_ONE], hasExtra) == nullptr ||
131             ParseExtra(env, asyncContext->extra_, argv[ARR_INDEX_TWO]) == nullptr) {
132             return nullptr;
133         }
134     }
135     return func(env, asyncContext);
136 }
137 
GetOneCfgFileOrAllCfgFiles(napi_env env,napi_callback_info info,const std::string & workName,napi_async_execute_callback execute)138 napi_value ConfigPolicyNapi::GetOneCfgFileOrAllCfgFiles(napi_env env, napi_callback_info info,
139     const std::string &workName, napi_async_execute_callback execute)
140 {
141     size_t argc = ARGS_SIZE_FOUR;
142     napi_value argv[ARGS_SIZE_FOUR] = {nullptr};
143     napi_value thisVar = nullptr;
144     void *data = nullptr;
145     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
146     if (argc < ARGS_SIZE_ONE) {
147         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The number of parameters is incorrect.");
148     }
149 
150     auto asyncContext = std::make_unique<ConfigAsyncContext>();
151     asyncContext->followMode_ = FOLLOWX_MODE_DEFAULT;
152     bool hasExtra = false;
153     if (ParseRelPath(env, asyncContext->relPath_, argv[ARR_INDEX_ZERO]) == nullptr) {
154         return nullptr;
155     }
156     if (argc == ARGS_SIZE_TWO) {
157         if (MatchValueType(env, argv[ARR_INDEX_ONE], napi_function)) {
158             napi_create_reference(env, argv[ARR_INDEX_ONE], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
159         } else {
160             if (ParseFollowMode(env, asyncContext->followMode_, argv[ARR_INDEX_ONE], hasExtra) == nullptr) {
161                 return nullptr;
162             }
163         }
164     }
165 
166     if (argc == ARGS_SIZE_THREE) {
167         if (MatchValueType(env, argv[ARR_INDEX_TWO], napi_function)) {
168             napi_create_reference(env, argv[ARR_INDEX_TWO], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
169         } else {
170             if (ParseExtra(env, asyncContext->extra_, argv[ARR_INDEX_TWO]) == nullptr) {
171                 return nullptr;
172             }
173             hasExtra = true;
174         }
175         if (ParseFollowMode(env, asyncContext->followMode_, argv[ARR_INDEX_ONE], hasExtra) == nullptr) {
176             return nullptr;
177         }
178     }
179 
180     if (argc == ARGS_SIZE_FOUR) {
181         hasExtra = true;
182         if (ParseFollowMode(env, asyncContext->followMode_, argv[ARR_INDEX_ONE], hasExtra) == nullptr ||
183             ParseExtra(env, asyncContext->extra_, argv[ARR_INDEX_TWO]) == nullptr) {
184             return nullptr;
185         }
186         if (!MatchValueType(env, argv[ARR_INDEX_THREE], napi_function)) {
187             return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of callback must be AsyncCallback.");
188         }
189         napi_create_reference(env, argv[ARR_INDEX_THREE], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
190     }
191     return HandleAsyncWork(env, asyncContext.release(), workName, execute, NativeCallbackComplete);
192 }
193 
NAPIGetCfgFiles(napi_env env,napi_callback_info info)194 napi_value ConfigPolicyNapi::NAPIGetCfgFiles(napi_env env, napi_callback_info info)
195 {
196     HILOG_DEBUG(LOG_CORE, "NAPIGetCfgFiles start.");
197     return GetOneCfgFileOrAllCfgFiles(env, info, "NAPIGetCfgFiles", NativeGetCfgFiles);
198 }
199 
NAPIGetCfgFilesSync(napi_env env,napi_callback_info info)200 napi_value ConfigPolicyNapi::NAPIGetCfgFilesSync(napi_env env, napi_callback_info info)
201 {
202     HILOG_DEBUG(LOG_CORE, "NAPIGetCfgFilesSync start.");
203     return GetOneCfgFileOrAllCfgFilesSync(env, info, NativeGetCfgFilesSync);
204 }
205 
NAPIGetCfgDirList(napi_env env,napi_callback_info info)206 napi_value ConfigPolicyNapi::NAPIGetCfgDirList(napi_env env, napi_callback_info info)
207 {
208     size_t argc = ARGS_SIZE_ONE;
209     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
210     napi_value thisVar = nullptr;
211     void *data = nullptr;
212     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
213 
214     auto asyncContext = std::make_unique<ConfigAsyncContext>();
215     if (argc == ARGS_SIZE_ONE) {
216         bool matchFlag = MatchValueType(env, argv[ARR_INDEX_ZERO], napi_function);
217         if (!matchFlag) {
218             return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of callback must be AsyncCallback.");
219         }
220         napi_create_reference(env, argv[ARR_INDEX_ZERO], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
221     }
222     return HandleAsyncWork(env, asyncContext.release(), "NAPIGetCfgDirList", NativeGetCfgDirList,
223         NativeCallbackComplete);
224 }
225 
NAPIGetCfgDirListSync(napi_env env,napi_callback_info info)226 napi_value ConfigPolicyNapi::NAPIGetCfgDirListSync(napi_env env, napi_callback_info info)
227 {
228     auto asyncContext = std::make_shared<ConfigAsyncContext>();
229     return NativeGetCfgDirListSync(env, asyncContext);
230 }
231 
CreateUndefined(napi_env env)232 napi_value ConfigPolicyNapi::CreateUndefined(napi_env env)
233 {
234     napi_value result = nullptr;
235     napi_get_undefined(env, &result);
236     return result;
237 }
238 
GetStringFromNAPI(napi_env env,napi_value value)239 std::string ConfigPolicyNapi::GetStringFromNAPI(napi_env env, napi_value value)
240 {
241     std::string result;
242     size_t size = 0;
243 
244     if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) {
245         HILOG_ERROR(LOG_CORE, "can not get string size.");
246         return "";
247     }
248     result.reserve(size + NAPI_RETURN_ONE);
249     result.resize(size);
250     if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) {
251         HILOG_ERROR(LOG_CORE, "can not get string value.");
252         return "";
253     }
254     return result;
255 }
256 
HandleAsyncWork(napi_env env,ConfigAsyncContext * context,std::string workName,napi_async_execute_callback execute,napi_async_complete_callback complete)257 napi_value ConfigPolicyNapi::HandleAsyncWork(napi_env env, ConfigAsyncContext *context, std::string workName,
258     napi_async_execute_callback execute, napi_async_complete_callback complete)
259 {
260     HILOG_DEBUG(LOG_CORE, "HandleAsyncWork start.");
261     if (context == nullptr) {
262         HILOG_ERROR(LOG_CORE, "context is nullptr");
263         return nullptr;
264     }
265 
266     napi_value result = nullptr;
267     if (context->callbackRef_ == nullptr) {
268         napi_create_promise(env, &context->deferred_, &result);
269     } else {
270         napi_get_undefined(env, &result);
271     }
272     napi_value resource = CreateUndefined(env);
273     napi_value resourceName = nullptr;
274     napi_create_string_utf8(env, workName.data(), NAPI_AUTO_LENGTH, &resourceName);
275     napi_create_async_work(env, resource, resourceName, execute, complete, static_cast<void *>(context),
276         &context->work_);
277     napi_queue_async_work_with_qos(env, context->work_, napi_qos_user_initiated);
278     HILOG_DEBUG(LOG_CORE, "HandleAsyncWork end.");
279     return result;
280 }
281 
MatchValueType(napi_env env,napi_value value,napi_valuetype targetType)282 bool ConfigPolicyNapi::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
283 {
284     napi_valuetype valueType = napi_undefined;
285     napi_typeof(env, value, &valueType);
286     return valueType == targetType;
287 }
288 
NativeGetOneCfgFile(napi_env env,void * data)289 void ConfigPolicyNapi::NativeGetOneCfgFile(napi_env env, void *data)
290 {
291     HILOG_DEBUG(LOG_CORE, "NativeGetOneCfgFile start.");
292     if (data == nullptr) {
293         HILOG_ERROR(LOG_CORE, "data is nullptr");
294         return;
295     }
296     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
297     char outBuf[MAX_PATH_LEN] = {0};
298     char *filePath = GetOneCfgFileEx(asyncCallbackInfo->relPath_.c_str(), outBuf, MAX_PATH_LEN,
299                                      asyncCallbackInfo->followMode_, asyncCallbackInfo->extra_.c_str());
300     if (filePath == nullptr) {
301         HILOG_DEBUG(LOG_CORE, "GetOneCfgFileEx result is nullptr.");
302     } else {
303         asyncCallbackInfo->pathValue_ = std::string(filePath);
304     }
305     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getOneCfgFile", "");
306     asyncCallbackInfo->createValueFunc_ = [](napi_env env, ConfigAsyncContext &context) -> napi_value {
307         napi_value result;
308         NAPI_CALL(env, napi_create_string_utf8(env, context.pathValue_.c_str(), NAPI_AUTO_LENGTH, &result));
309         return result;
310     };
311 }
312 
NativeGetOneCfgFileSync(napi_env env,std::shared_ptr<ConfigAsyncContext> context)313 napi_value ConfigPolicyNapi::NativeGetOneCfgFileSync(napi_env env, std::shared_ptr<ConfigAsyncContext> context)
314 {
315     HILOG_DEBUG(LOG_CORE, "NativeGetOneCfgFileSync start.");
316     char outBuf[MAX_PATH_LEN] = {0};
317     char *filePath = GetOneCfgFileEx(context->relPath_.c_str(), outBuf, MAX_PATH_LEN,
318                                      context->followMode_, context->extra_.c_str());
319     if (filePath == nullptr) {
320         HILOG_DEBUG(LOG_CORE, "GetOneCfgFileEx result is nullptr.");
321     } else {
322         context->pathValue_ = std::string(filePath);
323     }
324     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getOneCfgFileSync", "");
325     napi_value result = nullptr;
326     NAPI_CALL(env, napi_create_string_utf8(env, context->pathValue_.c_str(), NAPI_AUTO_LENGTH, &result));
327     return result;
328 }
329 
NativeGetCfgFiles(napi_env env,void * data)330 void ConfigPolicyNapi::NativeGetCfgFiles(napi_env env, void *data)
331 {
332     HILOG_DEBUG(LOG_CORE, "NativeGetCfgFiles start.");
333     if (data == nullptr) {
334         HILOG_ERROR(LOG_CORE, "data is nullptr");
335         return;
336     }
337 
338     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
339     CfgFiles *cfgFiles = GetCfgFilesEx(asyncCallbackInfo->relPath_.c_str(), asyncCallbackInfo->followMode_,
340                                        asyncCallbackInfo->extra_.c_str());
341     if (cfgFiles != nullptr) {
342         for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
343             if (cfgFiles->paths[i] != nullptr) {
344                 asyncCallbackInfo->paths_.push_back(cfgFiles->paths[i]);
345             }
346         }
347         FreeCfgFiles(cfgFiles);
348     }
349     CreateArraysValueFunc(*asyncCallbackInfo);
350     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgFiles", "");
351 }
352 
NativeGetCfgFilesSync(napi_env env,std::shared_ptr<ConfigAsyncContext> context)353 napi_value ConfigPolicyNapi::NativeGetCfgFilesSync(napi_env env, std::shared_ptr<ConfigAsyncContext> context)
354 {
355     HILOG_DEBUG(LOG_CORE, "NativeGetCfgFiles start.");
356     CfgFiles *cfgFiles = GetCfgFilesEx(context->relPath_.c_str(), context->followMode_,
357                                        context->extra_.c_str());
358     if (cfgFiles != nullptr) {
359         for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
360             if (cfgFiles->paths[i] != nullptr) {
361                 context->paths_.push_back(cfgFiles->paths[i]);
362             }
363         }
364         FreeCfgFiles(cfgFiles);
365     }
366     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgFilesSync", "");
367     return CreateArraysValue(env, context);
368 }
369 
NativeGetCfgDirList(napi_env env,void * data)370 void ConfigPolicyNapi::NativeGetCfgDirList(napi_env env, void *data)
371 {
372     HILOG_DEBUG(LOG_CORE, "NativeGetCfgDirList start.");
373     if (data == nullptr) {
374         HILOG_ERROR(LOG_CORE, "data is nullptr.");
375         return;
376     }
377 
378     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
379     CfgDir *cfgDir = GetCfgDirList();
380     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
381         if (cfgDir != nullptr && cfgDir->paths[i] != nullptr) {
382             asyncCallbackInfo->paths_.push_back(cfgDir->paths[i]);
383         }
384     }
385     FreeCfgDirList(cfgDir);
386     CreateArraysValueFunc(*asyncCallbackInfo);
387     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgDirList", "");
388 }
389 
NativeGetCfgDirListSync(napi_env env,std::shared_ptr<ConfigAsyncContext> context)390 napi_value ConfigPolicyNapi::NativeGetCfgDirListSync(napi_env env, std::shared_ptr<ConfigAsyncContext> context)
391 {
392     HILOG_DEBUG(LOG_CORE, "NativeGetCfgDirListSync start.");
393     CfgDir *cfgDir = GetCfgDirList();
394     if (cfgDir != nullptr) {
395         for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
396             if (cfgDir->paths[i] != nullptr) {
397                 context->paths_.push_back(cfgDir->paths[i]);
398             }
399         }
400         FreeCfgDirList(cfgDir);
401     }
402     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgDirListSync", "");
403     return CreateArraysValue(env, context);
404 }
405 
CreateArraysValue(napi_env env,std::shared_ptr<ConfigAsyncContext> context)406 napi_value ConfigPolicyNapi::CreateArraysValue(napi_env env, std::shared_ptr<ConfigAsyncContext> context)
407 {
408     napi_value result = nullptr;
409     NAPI_CALL(env, napi_create_array_with_length(env, context->paths_.size(), &result));
410     for (size_t i = 0; i < context->paths_.size(); i++) {
411         napi_value element = nullptr;
412         NAPI_CALL(env, napi_create_string_utf8(env, context->paths_[i].c_str(), NAPI_AUTO_LENGTH, &element));
413         NAPI_CALL(env, napi_set_element(env, result, i, element));
414     }
415     return result;
416 }
417 
CreateArraysValueFunc(ConfigAsyncContext & asyncCallbackInfo)418 void ConfigPolicyNapi::CreateArraysValueFunc(ConfigAsyncContext &asyncCallbackInfo)
419 {
420     asyncCallbackInfo.createValueFunc_ = [](napi_env env, ConfigAsyncContext &context) -> napi_value {
421         napi_value result = nullptr;
422         NAPI_CALL(env, napi_create_array_with_length(env, context.paths_.size(), &result));
423         for (size_t i = 0; i < context.paths_.size(); i++) {
424             napi_value element = nullptr;
425             NAPI_CALL(env, napi_create_string_utf8(env, context.paths_[i].c_str(), NAPI_AUTO_LENGTH, &element));
426             NAPI_CALL(env, napi_set_element(env, result, i, element));
427         }
428         return result;
429     };
430 }
431 
NativeCallbackComplete(napi_env env,napi_status status,void * data)432 void ConfigPolicyNapi::NativeCallbackComplete(napi_env env, napi_status status, void *data)
433 {
434     HILOG_DEBUG(LOG_CORE, "NativeCallbackComplete start.");
435     if (data == nullptr) {
436         HILOG_ERROR(LOG_CORE, "data is nullptr");
437         return;
438     }
439 
440     napi_value finalResult = nullptr;
441     ConfigAsyncContext *asyncContext = static_cast<ConfigAsyncContext *>(data);
442     if (asyncContext->createValueFunc_ != nullptr) {
443         finalResult = asyncContext->createValueFunc_(env, *asyncContext);
444     }
445 
446     napi_value result[] = { nullptr, nullptr };
447     napi_get_null(env, &result[0]);
448     result[1] = finalResult;
449 
450     if (asyncContext->deferred_ != nullptr) {
451         napi_resolve_deferred(env, asyncContext->deferred_, result[1]);
452     } else {
453         napi_value callback = nullptr;
454         napi_value userRet = nullptr;
455         napi_get_reference_value(env, asyncContext->callbackRef_, &callback);
456         napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(napi_value), result, &userRet);
457         napi_delete_reference(env, asyncContext->callbackRef_);
458     }
459     napi_delete_async_work(env, asyncContext->work_);
460     delete asyncContext;
461     HILOG_DEBUG(LOG_CORE, "NativeCallbackComplete end.");
462 }
463 
ParseRelPath(napi_env env,std::string & param,napi_value args)464 napi_value ConfigPolicyNapi::ParseRelPath(napi_env env, std::string &param, napi_value args)
465 {
466     bool matchFlag = MatchValueType(env, args, napi_string);
467     if (!matchFlag) {
468         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of relPath must be string.");
469     }
470     param = GetStringFromNAPI(env, args);
471     napi_value result = nullptr;
472     NAPI_CALL(env, napi_create_int32(env, NAPI_RETURN_ONE, &result));
473     return result;
474 }
475 
ParseExtra(napi_env env,std::string & param,napi_value args)476 napi_value ConfigPolicyNapi::ParseExtra(napi_env env, std::string &param, napi_value args)
477 {
478     bool matchFlag = MatchValueType(env, args, napi_string);
479     if (!matchFlag) {
480         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of extra must be string.");
481     }
482     param = GetStringFromNAPI(env, args);
483     napi_value result = nullptr;
484     NAPI_CALL(env, napi_create_int32(env, NAPI_RETURN_ONE, &result));
485     return result;
486 }
487 
ParseFollowMode(napi_env env,int32_t & param,napi_value args,bool hasExtra)488 napi_value ConfigPolicyNapi::ParseFollowMode(napi_env env, int32_t &param, napi_value args, bool hasExtra)
489 {
490     bool matchFlag = MatchValueType(env, args, napi_number);
491     if (!matchFlag) {
492         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of followMode must be number.");
493     }
494     NAPI_CALL(env, napi_get_value_int32(env, args, &param));
495     switch (param) {
496         case FOLLOWX_MODE_DEFAULT:
497             [[fallthrough]];
498         case FOLLOWX_MODE_NO_RULE_FOLLOWED:
499             [[fallthrough]];
500         case FOLLOWX_MODE_SIM_DEFAULT:
501             [[fallthrough]];
502         case FOLLOWX_MODE_SIM_1:
503             [[fallthrough]];
504         case FOLLOWX_MODE_SIM_2:
505             break;
506         case FOLLOWX_MODE_USER_DEFINED:
507             if (!hasExtra) {
508                 return ThrowNapiError(env, PARAM_ERROR,
509                     "Parameter error. The followMode is USER_DEFINED, extra must be set.");
510             }
511             break;
512         default:
513             return ThrowNapiError(env, PARAM_ERROR,
514                 "Parameter error. The value of followMode should be in the enumeration value of FollowXMode.");
515     }
516 
517     napi_value result = nullptr;
518     NAPI_CALL(env, napi_create_int32(env, NAPI_RETURN_ONE, &result));
519     return result;
520 }
521 
ThrowNapiError(napi_env env,int32_t errCode,const std::string & errMessage)522 napi_value ConfigPolicyNapi::ThrowNapiError(napi_env env, int32_t errCode, const std::string &errMessage)
523 {
524     napi_throw_error(env, std::to_string(errCode).c_str(), errMessage.c_str());
525     return nullptr;
526 }
527 
ConfigPolicyInit(napi_env env,napi_value exports)528 static napi_value ConfigPolicyInit(napi_env env, napi_value exports)
529 {
530     return ConfigPolicyNapi::Init(env, exports);
531 }
532 
533 static napi_module g_configPolicyModule = {
534     .nm_version = 1,
535     .nm_flags = 0,
536     .nm_filename = nullptr,
537     .nm_register_func = ConfigPolicyInit,
538     .nm_modname = "configPolicy",
539     .nm_priv = ((void *)0),
540     .reserved = { 0 }
541 };
542 
ConfigPolicyRegister()543 extern "C" __attribute__((constructor)) void ConfigPolicyRegister()
544 {
545     napi_module_register(&g_configPolicyModule);
546 }
547 } // namespace ConfigPolicy
548 } // namespace Customization
549 } // namespace OHOS
550