• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 namespace OHOS {
25 namespace Customization {
26 namespace ConfigPolicy {
27 using namespace OHOS::HiviewDFX;
28 
29 static constexpr size_t ARGS_SIZE_ONE = 1;
30 static constexpr size_t ARGS_SIZE_TWO = 2;
31 static constexpr int32_t ARR_INDEX_ZERO = 0;
32 static constexpr int32_t ARR_INDEX_ONE = 1;
33 static constexpr int32_t NAPI_RETURN_ZERO = 0;
34 static constexpr int32_t NAPI_RETURN_ONE = 1;
35 // Param Error Code
36 static constexpr int32_t PARAM_ERROR = 401;
37 static constexpr HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "ConfigPolicyJs" };
38 
Init(napi_env env,napi_value exports)39 napi_value ConfigPolicyNapi::Init(napi_env env, napi_value exports)
40 {
41     napi_property_descriptor property[] = {
42         DECLARE_NAPI_FUNCTION("getOneCfgFile", ConfigPolicyNapi::NAPIGetOneCfgFile),
43         DECLARE_NAPI_FUNCTION("getCfgFiles", ConfigPolicyNapi::NAPIGetCfgFiles),
44         DECLARE_NAPI_FUNCTION("getCfgDirList", ConfigPolicyNapi::NAPIGetCfgDirList)
45     };
46     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(property) / sizeof(property[0]), property));
47     return exports;
48 }
49 
NAPIGetOneCfgFile(napi_env env,napi_callback_info info)50 napi_value ConfigPolicyNapi::NAPIGetOneCfgFile(napi_env env, napi_callback_info info)
51 {
52     size_t argc = ARGS_SIZE_TWO;
53     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
54     napi_value thisVar = nullptr;
55     void *data = nullptr;
56     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
57     if (argc < ARGS_SIZE_ONE) {
58         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The number of parameters is incorrect.");
59     }
60 
61     auto asyncContext = std::make_unique<ConfigAsyncContext>();
62     ParseRelPath(env, asyncContext->relPath_, argv[ARR_INDEX_ZERO]);
63     if (argc == ARGS_SIZE_TWO) {
64         bool matchFlag = MatchValueType(env, argv[ARR_INDEX_ONE], napi_function);
65         if (!matchFlag) {
66             return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The second parameter must be Callback.");
67         }
68         napi_create_reference(env, argv[ARR_INDEX_ONE], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
69     }
70     return HandleAsyncWork(env, asyncContext.release(), "NAPIGetOneCfgFile", NativeGetOneCfgFile,
71         NativeCallbackComplete);
72 }
73 
NAPIGetCfgFiles(napi_env env,napi_callback_info info)74 napi_value ConfigPolicyNapi::NAPIGetCfgFiles(napi_env env, napi_callback_info info)
75 {
76     size_t argc = ARGS_SIZE_TWO;
77     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
78     napi_value thisVar = nullptr;
79     void *data = nullptr;
80     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
81     if (argc < ARGS_SIZE_ONE) {
82         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The number of parameters is incorrect.");
83     }
84 
85     auto asyncContext = std::make_unique<ConfigAsyncContext>();
86     ParseRelPath(env, asyncContext->relPath_, argv[ARR_INDEX_ZERO]);
87     if (argc == ARGS_SIZE_TWO) {
88         bool matchFlag = MatchValueType(env, argv[ARR_INDEX_ONE], napi_function);
89         if (!matchFlag) {
90             return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The second parameter must be Callback.");
91         }
92         napi_create_reference(env, argv[ARR_INDEX_ONE], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
93     }
94     return HandleAsyncWork(env, asyncContext.release(), "NAPIGetCfgFiles", NativeGetCfgFiles, NativeCallbackComplete);
95 }
96 
NAPIGetCfgDirList(napi_env env,napi_callback_info info)97 napi_value ConfigPolicyNapi::NAPIGetCfgDirList(napi_env env, napi_callback_info info)
98 {
99     size_t argc = ARGS_SIZE_ONE;
100     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
101     napi_value thisVar = nullptr;
102     void *data = nullptr;
103     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
104 
105     auto asyncContext = std::make_unique<ConfigAsyncContext>();
106     if (argc == ARGS_SIZE_ONE) {
107         bool matchFlag = MatchValueType(env, argv[ARR_INDEX_ZERO], napi_function);
108         if (!matchFlag) {
109             return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The first parameter must be Callback.");
110         }
111         napi_create_reference(env, argv[ARR_INDEX_ZERO], NAPI_RETURN_ONE, &asyncContext->callbackRef_);
112     }
113     return HandleAsyncWork(env, asyncContext.release(), "NAPIGetCfgDirList", NativeGetCfgDirList,
114         NativeCallbackComplete);
115 }
116 
CreateUndefined(napi_env env)117 napi_value ConfigPolicyNapi::CreateUndefined(napi_env env)
118 {
119     napi_value result = nullptr;
120     napi_get_undefined(env, &result);
121     return result;
122 }
123 
GetStringFromNAPI(napi_env env,napi_value value)124 std::string ConfigPolicyNapi::GetStringFromNAPI(napi_env env, napi_value value)
125 {
126     std::string result;
127     size_t size = 0;
128 
129     if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) {
130         HiLog::Error(LABEL, "can not get string size.");
131         return "";
132     }
133     result.reserve(size + NAPI_RETURN_ONE);
134     result.resize(size);
135     if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) {
136         HiLog::Error(LABEL, "can not get string value.");
137         return "";
138     }
139     return result;
140 }
141 
HandleAsyncWork(napi_env env,ConfigAsyncContext * context,std::string workName,napi_async_execute_callback execute,napi_async_complete_callback complete)142 napi_value ConfigPolicyNapi::HandleAsyncWork(napi_env env, ConfigAsyncContext *context, std::string workName,
143     napi_async_execute_callback execute, napi_async_complete_callback complete)
144 {
145     if (context == nullptr) {
146         HiLog::Error(LABEL, "context is nullptr");
147         return nullptr;
148     }
149 
150     napi_value result = nullptr;
151     if (context->callbackRef_ == nullptr) {
152         napi_create_promise(env, &context->deferred_, &result);
153     } else {
154         napi_get_undefined(env, &result);
155     }
156     napi_value resource = CreateUndefined(env);
157     napi_value resourceName = nullptr;
158     napi_create_string_utf8(env, workName.data(), NAPI_AUTO_LENGTH, &resourceName);
159     napi_create_async_work(env, resource, resourceName, execute, complete, static_cast<void *>(context),
160         &context->work_);
161     napi_queue_async_work_with_qos(env, context->work_, napi_qos_default);
162     return result;
163 }
164 
MatchValueType(napi_env env,napi_value value,napi_valuetype targetType)165 bool ConfigPolicyNapi::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
166 {
167     napi_valuetype valueType = napi_undefined;
168     napi_typeof(env, value, &valueType);
169     return valueType == targetType;
170 }
171 
NativeGetOneCfgFile(napi_env env,void * data)172 void ConfigPolicyNapi::NativeGetOneCfgFile(napi_env env, void *data)
173 {
174     if (data == nullptr) {
175         HiLog::Error(LABEL, "data is nullptr");
176         return;
177     }
178     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
179     char outBuf[MAX_PATH_LEN] = {0};
180     GetOneCfgFile(asyncCallbackInfo->relPath_.c_str(), outBuf, MAX_PATH_LEN);
181     asyncCallbackInfo->pathValue_ = std::string(outBuf);
182     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getOneCfgFile", "");
183     asyncCallbackInfo->createValueFunc_ = [](napi_env env, ConfigAsyncContext &context) -> napi_value {
184         napi_value result;
185         NAPI_CALL(env, napi_create_string_utf8(env, context.pathValue_.c_str(), NAPI_AUTO_LENGTH, &result));
186         return result;
187     };
188 }
189 
NativeGetCfgFiles(napi_env env,void * data)190 void ConfigPolicyNapi::NativeGetCfgFiles(napi_env env, void *data)
191 {
192     if (data == nullptr) {
193         HiLog::Error(LABEL, "data is nullptr");
194         return;
195     }
196 
197     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
198     CfgFiles *cfgFiles = GetCfgFiles(asyncCallbackInfo->relPath_.c_str());
199     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
200         if (cfgFiles != nullptr && cfgFiles->paths[i] != nullptr) {
201             asyncCallbackInfo->paths_.push_back(cfgFiles->paths[i]);
202         }
203     }
204     FreeCfgFiles(cfgFiles);
205     CreateArraysValueFunc(*asyncCallbackInfo);
206     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgFiles", "");
207 }
208 
NativeGetCfgDirList(napi_env env,void * data)209 void ConfigPolicyNapi::NativeGetCfgDirList(napi_env env, void *data)
210 {
211     if (data == nullptr) {
212         HiLog::Error(LABEL, "data is nullptr.");
213         return;
214     }
215 
216     ConfigAsyncContext *asyncCallbackInfo = static_cast<ConfigAsyncContext *>(data);
217     CfgDir *cfgDir = GetCfgDirList();
218     for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
219         if (cfgDir != nullptr && cfgDir->paths[i] != nullptr) {
220             asyncCallbackInfo->paths_.push_back(cfgDir->paths[i]);
221         }
222     }
223     FreeCfgDirList(cfgDir);
224     CreateArraysValueFunc(*asyncCallbackInfo);
225     ReportConfigPolicyEvent(ReportType::CONFIG_POLICY_EVENT, "getCfgDirList", "");
226 }
227 
CreateArraysValueFunc(ConfigAsyncContext & asyncCallbackInfo)228 void ConfigPolicyNapi::CreateArraysValueFunc(ConfigAsyncContext &asyncCallbackInfo)
229 {
230     asyncCallbackInfo.createValueFunc_ = [](napi_env env, ConfigAsyncContext &context) -> napi_value {
231         napi_value result = nullptr;
232         NAPI_CALL(env, napi_create_array_with_length(env, context.paths_.size(), &result));
233         for (size_t i = 0; i < context.paths_.size(); i++) {
234             napi_value element = nullptr;
235             NAPI_CALL(env, napi_create_string_utf8(env, context.paths_[i].c_str(), NAPI_AUTO_LENGTH, &element));
236             NAPI_CALL(env, napi_set_element(env, result, i, element));
237         }
238         return result;
239     };
240 }
241 
NativeCallbackComplete(napi_env env,napi_status status,void * data)242 void ConfigPolicyNapi::NativeCallbackComplete(napi_env env, napi_status status, void *data)
243 {
244     if (data == nullptr) {
245         HiLog::Error(LABEL, "data is nullptr");
246         return;
247     }
248 
249     napi_value finalResult = nullptr;
250     ConfigAsyncContext *asyncContext = static_cast<ConfigAsyncContext *>(data);
251     if (asyncContext->createValueFunc_ != nullptr) {
252         finalResult = asyncContext->createValueFunc_(env, *asyncContext);
253     }
254 
255     napi_value result[] = { nullptr, nullptr };
256     napi_get_null(env, &result[0]);
257     result[1] = finalResult;
258 
259     if (asyncContext->deferred_ != nullptr) {
260         napi_resolve_deferred(env, asyncContext->deferred_, result[1]);
261     } else {
262         napi_value callback = nullptr;
263         napi_value userRet = nullptr;
264         napi_get_reference_value(env, asyncContext->callbackRef_, &callback);
265         napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(napi_value), result, &userRet);
266         napi_delete_reference(env, asyncContext->callbackRef_);
267     }
268     napi_delete_async_work(env, asyncContext->work_);
269     delete asyncContext;
270 }
271 
ParseRelPath(napi_env env,std::string & param,napi_value args)272 napi_value ConfigPolicyNapi::ParseRelPath(napi_env env, std::string &param, napi_value args)
273 {
274     bool matchFlag = MatchValueType(env, args, napi_string);
275     if (!matchFlag) {
276         return ThrowNapiError(env, PARAM_ERROR, "Parameter error. The type of relPath must be string.");
277     }
278     param = GetStringFromNAPI(env, args);
279     napi_value result = nullptr;
280     NAPI_CALL(env, napi_create_int32(env, NAPI_RETURN_ONE, &result));
281     return result;
282 }
283 
ThrowNapiError(napi_env env,int32_t errCode,const std::string & errMessage)284 napi_value ConfigPolicyNapi::ThrowNapiError(napi_env env, int32_t errCode, const std::string &errMessage)
285 {
286     napi_throw_error(env, std::to_string(errCode).c_str(), errMessage.c_str());
287     return nullptr;
288 }
289 
ConfigPolicyInit(napi_env env,napi_value exports)290 static napi_value ConfigPolicyInit(napi_env env, napi_value exports)
291 {
292     return ConfigPolicyNapi::Init(env, exports);
293 }
294 
295 static napi_module g_configPolicyModule = {
296     .nm_version = 1,
297     .nm_flags = 0,
298     .nm_filename = nullptr,
299     .nm_register_func = ConfigPolicyInit,
300     .nm_modname = "configPolicy",
301     .nm_priv = ((void *)0),
302     .reserved = { 0 }
303 };
304 
ConfigPolicyRegister()305 extern "C" __attribute__((constructor)) void ConfigPolicyRegister()
306 {
307     napi_module_register(&g_configPolicyModule);
308 }
309 } // namespace ConfigPolicy
310 } // namespace Customization
311 } // namespace OHOS
312