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 ¶m, 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