• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "native_parameters_js.h"
16 #include "sysparam_errno.h"
17 
18 static constexpr int ARGC_NUMBER = 2;
19 static constexpr int ARGC_THREE_NUMBER = 3;
20 static constexpr int MAX_NAME_LENGTH = 128;
21 static constexpr int MAX_VALUE_LENGTH = PARAM_CONST_VALUE_LEN_MAX;
22 
23 using StorageAsyncContext = struct StorageAsyncContext {
24     napi_env env = nullptr;
25     napi_async_work work = nullptr;
26 
27     char key[MAX_NAME_LENGTH] = { 0 };
28     size_t keyLen = 0;
29     char value[MAX_VALUE_LENGTH] = { 0 };
30     size_t valueLen = 0;
31     napi_deferred deferred = nullptr;
32     napi_ref callbackRef = nullptr;
33 
34     int status = -1;
35     std::string getValue;
36 };
37 
38 using StorageAsyncContextPtr = StorageAsyncContext *;
39 
GetErrorInfo(int status,std::string & errMsg)40 static int GetErrorInfo(int status, std::string &errMsg)
41 {
42     switch (status) {
43         case EC_FAILURE:
44         case EC_SYSTEM_ERR:
45         case SYSPARAM_SYSTEM_ERROR:
46             errMsg = "System internal error including out of memory, deadlock etc";
47             return -SYSPARAM_SYSTEM_ERROR;
48         case EC_INVALID:
49         case SYSPARAM_INVALID_INPUT:
50             errMsg = "Input parameter is missing or invalid";
51             return -SYSPARAM_INVALID_INPUT;
52         case SYSPARAM_PERMISSION_DENIED:
53             errMsg = "System permission operation permission denied";
54             return -SYSPARAM_PERMISSION_DENIED;
55         case SYSPARAM_NOT_FOUND:
56             errMsg = "System parameter can not be found";
57             return -SYSPARAM_NOT_FOUND;
58         case SYSPARAM_INVALID_VALUE:
59             errMsg = "System parameter value is invalid";
60             return -SYSPARAM_INVALID_VALUE;
61         default:
62             errMsg = "System internal error including out of memory, deadlock etc";
63             return -SYSPARAM_SYSTEM_ERROR;
64     }
65     return 0;
66 }
67 
BusinessErrorCreate(napi_env env,int status)68 static napi_value BusinessErrorCreate(napi_env env, int status)
69 {
70     std::string errMsg = "";
71     int ret = GetErrorInfo(status, errMsg);
72     PARAM_JS_LOGV("BusinessErrorCreate status %d err %d msg: %s", status, ret, errMsg.c_str());
73     napi_value code = nullptr;
74     napi_create_int32(env, ret, &code);
75     napi_value msg = nullptr;
76     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msg);
77     napi_value businessError = nullptr;
78     napi_create_error(env, nullptr, msg, &businessError);
79     napi_set_named_property(env, businessError, "code", code);
80     return businessError;
81 }
82 
83 #define PARAM_NAPI_ASSERT(env, assertion, result, info)         \
84     do {                                                        \
85         if (!(assertion)) {                                     \
86             napi_value d_err = BusinessErrorCreate(env, result);   \
87             napi_throw(env, d_err);                             \
88             return nullptr;                                     \
89         }                                                       \
90     } while (0)
91 
GetParamString(napi_env env,napi_value arg,char * buffer,size_t maxBuff,size_t * keySize)92 static int GetParamString(napi_env env, napi_value arg, char *buffer, size_t maxBuff, size_t *keySize)
93 {
94     (void)napi_get_value_string_utf8(env, arg, nullptr, maxBuff - 1, keySize);
95     if (*keySize >= maxBuff || *keySize == 0) {
96         return SYSPARAM_INVALID_INPUT;
97     }
98     (void)napi_get_value_string_utf8(env, arg, buffer, maxBuff - 1, keySize);
99     return 0;
100 }
101 
SetCallbackWork(napi_env env,StorageAsyncContextPtr asyncContext)102 static void SetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext)
103 {
104     napi_value resource = nullptr;
105     napi_create_string_utf8(env, "JSStartupSet", NAPI_AUTO_LENGTH, &resource);
106     napi_create_async_work(
107         env, nullptr, resource,
108         [](napi_env env, void *data) {
109             StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
110             asyncContext->status = SetParameter(asyncContext->key, asyncContext->value);
111             PARAM_JS_LOGV("JSApp set status: %d, key: '%s', value: '%s'.",
112                 asyncContext->status, asyncContext->key, asyncContext->value);
113         },
114         [](napi_env env, napi_status status, void *data) {
115             StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
116             napi_value result[ARGC_NUMBER] = { 0 };
117             if (asyncContext->status == 0) {
118                 napi_get_undefined(env, &result[0]);
119                 napi_get_undefined(env, &result[1]);
120             } else {
121                 result[0] = BusinessErrorCreate(env, asyncContext->status);
122                 napi_get_undefined(env, &result[1]);
123             }
124 
125             if (asyncContext->deferred) {
126                 if (asyncContext->status == 0) {
127                     napi_resolve_deferred(env, asyncContext->deferred, result[1]);
128                 } else {
129                     napi_reject_deferred(env, asyncContext->deferred, result[0]);
130                 }
131             } else {
132                 napi_value callback = nullptr;
133                 napi_value callResult = nullptr;
134                 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
135                 napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult);
136                 napi_delete_reference(env, asyncContext->callbackRef);
137             }
138             napi_delete_async_work(env, asyncContext->work);
139             delete asyncContext;
140         },
141         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
142     napi_queue_async_work(env, asyncContext->work);
143 }
144 
Set(napi_env env,napi_callback_info info)145 static napi_value Set(napi_env env, napi_callback_info info)
146 {
147     size_t argc = ARGC_THREE_NUMBER;
148     napi_value argv[ARGC_THREE_NUMBER] = { nullptr };
149     napi_value thisVar = nullptr;
150     void *data = nullptr;
151     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
152     PARAM_NAPI_ASSERT(env, argc >= ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "requires 2 parameter");
153     StorageAsyncContextPtr asyncContext = new StorageAsyncContext();
154     asyncContext->env = env;
155     for (size_t i = 0; i < argc; i++) {
156         napi_valuetype valueType = napi_null;
157         napi_typeof(env, argv[i], &valueType);
158         int ret = 0;
159         if (i == 0 && valueType == napi_string) {
160             ret = GetParamString(env, argv[i], asyncContext->key, MAX_NAME_LENGTH, &asyncContext->keyLen);
161         } else if (i == 1 && valueType == napi_string) {
162             ret = GetParamString(env, argv[i], asyncContext->value, MAX_VALUE_LENGTH, &asyncContext->valueLen);
163         } else if (i == ARGC_NUMBER && valueType == napi_function) {
164             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
165         } else {
166             ret = SYSPARAM_INVALID_INPUT;
167         }
168         if (ret != 0) {
169             delete asyncContext;
170             ret = (i == 1) ? SYSPARAM_INVALID_VALUE : ret;
171             napi_value err = BusinessErrorCreate(env, ret);
172             napi_throw(env, err);
173             return nullptr;
174         }
175     }
176     PARAM_JS_LOGV("JSApp set key: %s(%d), value: %s(%d).",
177         asyncContext->key, asyncContext->keyLen, asyncContext->value, asyncContext->valueLen);
178 
179     napi_value result = nullptr;
180     if (asyncContext->callbackRef == nullptr) {
181         napi_create_promise(env, &asyncContext->deferred, &result);
182     } else {
183         napi_get_undefined(env, &result);
184     }
185 
186     SetCallbackWork(env, asyncContext);
187     return result;
188 }
189 
SetSync(napi_env env,napi_callback_info info)190 static napi_value SetSync(napi_env env, napi_callback_info info)
191 {
192     size_t argc = ARGC_NUMBER;
193     napi_value args[ARGC_NUMBER] = { nullptr };
194     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
195     PARAM_NAPI_ASSERT(env, argc == ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "Wrong number of arguments");
196     napi_valuetype valuetype0 = napi_null;
197     NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
198     napi_valuetype valuetype1 = napi_null;
199     NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
200     PARAM_NAPI_ASSERT(env, valuetype0 == napi_string && valuetype1 == napi_string,
201         SYSPARAM_INVALID_INPUT, "Wrong argument type. string expected.");
202 
203     size_t keySize = 0;
204     std::vector<char> keyBuf(MAX_NAME_LENGTH, 0);
205     int ret = GetParamString(env, args[0], keyBuf.data(), MAX_NAME_LENGTH, &keySize);
206     if (ret != 0) {
207         napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT);
208         napi_throw(env, err);
209         return nullptr;
210     }
211     std::vector<char> value(MAX_VALUE_LENGTH, 0);
212     size_t valueSize = 0;
213     ret = GetParamString(env, args[1], value.data(), MAX_VALUE_LENGTH, &valueSize);
214     if (ret != 0) {
215         napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_VALUE);
216         napi_throw(env, err);
217         return nullptr;
218     }
219     ret = SetParameter(keyBuf.data(), value.data());
220     PARAM_JS_LOGV("JSApp SetSync result:%d, key: '%s'.", ret, keyBuf.data());
221     napi_value napiValue = nullptr;
222     if (ret != 0) { // set failed
223         napi_value err = BusinessErrorCreate(env, ret);
224         napi_throw(env, err);
225     } else {
226         napi_get_undefined(env, &napiValue);
227     }
228     return napiValue;
229 }
230 
GetSync(napi_env env,napi_callback_info info)231 static napi_value GetSync(napi_env env, napi_callback_info info)
232 {
233     size_t argc = ARGC_NUMBER;
234     napi_value args[ARGC_NUMBER] = { nullptr };
235     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
236     PARAM_NAPI_ASSERT(env, argc == 1 || argc == ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "Wrong number of arguments");
237     napi_valuetype valuetype0 = napi_null;
238     NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
239     PARAM_NAPI_ASSERT(env, valuetype0 == napi_string,
240         SYSPARAM_INVALID_INPUT, "Wrong argument type. Numbers expected.");
241     if (argc == ARGC_NUMBER) {
242         napi_valuetype valuetype1 = napi_null;
243         NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
244         PARAM_NAPI_ASSERT(env, valuetype1 == napi_string,
245             SYSPARAM_INVALID_INPUT, "Wrong argument type. string expected.");
246     }
247 
248     size_t keySize = 0;
249     std::vector<char> keyBuf(MAX_NAME_LENGTH, 0);
250     int ret = GetParamString(env, args[0], keyBuf.data(), MAX_NAME_LENGTH, &keySize);
251     if (ret != 0) {
252         napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT);
253         napi_throw(env, err);
254         return nullptr;
255     }
256     std::vector<char> defValue(MAX_VALUE_LENGTH, 0);
257     size_t valueSize = 0;
258     if (argc == ARGC_NUMBER) {
259         ret = GetParamString(env, args[1], defValue.data(), MAX_VALUE_LENGTH, &valueSize);
260         if (ret != 0) {
261             napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT);
262             napi_throw(env, err);
263             return nullptr;
264         }
265     }
266     std::vector<char> value(MAX_VALUE_LENGTH, 0);
267     ret = GetParameter(keyBuf.data(), (valueSize == 0) ? nullptr : defValue.data(), value.data(), MAX_VALUE_LENGTH);
268     PARAM_JS_LOGV("JSApp get status: %d, key: '%s', value: '%s', defValue: '%s'.",
269         ret, keyBuf.data(), value.data(), defValue.data());
270     if (ret < 0) {
271         napi_value err = BusinessErrorCreate(env, ret);
272         napi_throw(env, err);
273         return nullptr;
274     }
275     napi_value napiValue = nullptr;
276     NAPI_CALL(env, napi_create_string_utf8(env, value.data(), strlen(value.data()), &napiValue));
277     return napiValue;
278 }
279 
GetCallbackWork(napi_env env,StorageAsyncContextPtr asyncContext)280 static void GetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext)
281 {
282     napi_value resource = nullptr;
283     napi_create_string_utf8(env, "JSStartupGet", NAPI_AUTO_LENGTH, &resource);
284     napi_create_async_work(
285         env, nullptr, resource,
286         [](napi_env env, void *data) {
287             StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
288             std::vector<char> value(MAX_VALUE_LENGTH, 0);
289             asyncContext->status = GetParameter(asyncContext->key,
290                 (asyncContext->valueLen == 0) ? nullptr : asyncContext->value, value.data(), MAX_VALUE_LENGTH);
291             asyncContext->getValue = std::string(value.begin(), value.end());
292             PARAM_JS_LOGV("JSApp get asyncContext status: %d, key: '%s', value: '%s', defValue: '%s'.",
293                 asyncContext->status, asyncContext->key, asyncContext->getValue.c_str(), asyncContext->value);
294         },
295         [](napi_env env, napi_status status, void *data) {
296             StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
297             napi_value result[ARGC_NUMBER] = { 0 };
298             if (asyncContext->status > 0) {
299                 napi_get_undefined(env, &result[0]);
300                 napi_create_string_utf8(env,
301                     asyncContext->getValue.c_str(), strlen(asyncContext->getValue.c_str()), &result[1]);
302             } else {
303                 result[0] = BusinessErrorCreate(env, asyncContext->status);
304                 napi_get_undefined(env, &result[1]);
305             }
306 
307             if (asyncContext->deferred) {
308                 if (asyncContext->status > 0) {
309                     napi_resolve_deferred(env, asyncContext->deferred, result[1]);
310                 } else {
311                     napi_reject_deferred(env, asyncContext->deferred, result[0]);
312                 }
313             } else {
314                 napi_value callback = nullptr;
315                 napi_value callResult = nullptr;
316                 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
317                 napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult);
318                 napi_delete_reference(env, asyncContext->callbackRef);
319             }
320             napi_delete_async_work(env, asyncContext->work);
321             delete asyncContext;
322         },
323         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
324     napi_queue_async_work(env, asyncContext->work);
325 }
326 
Get(napi_env env,napi_callback_info info)327 static napi_value Get(napi_env env, napi_callback_info info)
328 {
329     size_t argc = ARGC_THREE_NUMBER;
330     napi_value argv[ARGC_THREE_NUMBER] = { nullptr };
331     napi_value thisVar = nullptr;
332     void *data = nullptr;
333     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
334     PARAM_NAPI_ASSERT(env, argc >= 1, SYSPARAM_INVALID_INPUT, "requires 1 parameter");
335     StorageAsyncContextPtr asyncContext = new StorageAsyncContext();
336     asyncContext->env = env;
337     for (size_t i = 0; i < argc; i++) {
338         napi_valuetype valueType = napi_null;
339         napi_typeof(env, argv[i], &valueType);
340 
341         int ret = 0;
342         if (i == 0 && valueType == napi_string) {
343             ret = GetParamString(env, argv[i], asyncContext->key, MAX_NAME_LENGTH, &asyncContext->keyLen);
344         } else if (i == 1 && valueType == napi_string) {
345             ret = GetParamString(env, argv[i], asyncContext->value, MAX_VALUE_LENGTH, &asyncContext->valueLen);
346         } else if (i == 1 && valueType == napi_function) {
347             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
348             break;
349         } else if (i == ARGC_NUMBER && valueType == napi_function) {
350             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
351         } else {
352             ret = SYSPARAM_INVALID_INPUT;
353         }
354         if (ret != 0) {
355             delete asyncContext;
356             ret = (i == 1) ? SYSPARAM_INVALID_VALUE : ret;
357             napi_value err = BusinessErrorCreate(env, ret);
358             napi_throw(env, err);
359             return nullptr;
360         }
361     }
362     PARAM_JS_LOGV("JSApp Get key: '%s'(%d), def value: '%s'(%d).",
363         asyncContext->key, asyncContext->keyLen, asyncContext->value, asyncContext->valueLen);
364 
365     napi_value result = nullptr;
366     if (asyncContext->callbackRef == nullptr) {
367         napi_create_promise(env, &asyncContext->deferred, &result);
368     } else {
369         napi_get_undefined(env, &result);
370     }
371 
372     GetCallbackWork(env, asyncContext);
373     return result;
374 }
375 
376 EXTERN_C_START
377 /*
378  * Module init
379  */
Init(napi_env env,napi_value exports)380 static napi_value Init(napi_env env, napi_value exports)
381 {
382     /*
383      * Attribute definition
384      */
385     const napi_property_descriptor desc[] = {
386         DECLARE_NAPI_FUNCTION("set", Set),
387         DECLARE_NAPI_FUNCTION("setSync", SetSync),
388         DECLARE_NAPI_FUNCTION("get", Get),
389         DECLARE_NAPI_FUNCTION("getSync", GetSync),
390 #ifdef PARAM_SUPPORT_WAIT
391         DECLARE_NAPI_FUNCTION("wait", ParamWait),
392         DECLARE_NAPI_FUNCTION("getWatcher", GetWatcher)
393 #endif
394     };
395     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
396 #ifdef PARAM_SUPPORT_WAIT
397     return RegisterWatcher(env, exports);
398 #else
399     return exports;
400 #endif
401 }
402 EXTERN_C_END
403 
404 /*
405  * Module definition
406  */
407 static napi_module _module_old = {
408     .nm_version = 1,
409     .nm_flags = 0,
410     .nm_filename = NULL,
411     .nm_register_func = Init,
412     .nm_modname = "systemParameterV9",
413     .nm_priv = ((void *)0),
414     .reserved = { 0 }
415 };
416 
417 static napi_module _module = {
418     .nm_version = 1,
419     .nm_flags = 0,
420     .nm_filename = NULL,
421     .nm_register_func = Init,
422     .nm_modname = "systemParameterEnhance",
423     .nm_priv = ((void *)0),
424     .reserved = { 0 }
425 };
426 
427 /*
428  * Module registration function
429  */
RegisterModule(void)430 extern "C" __attribute__((constructor)) void RegisterModule(void)
431 {
432     napi_module_register(&_module);
433     napi_module_register(&_module_old);
434 }
435