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