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 "securec.h"
17
18 static constexpr int MAX_LENGTH = 128;
19 static constexpr int ARGC_NUMBER = 2;
20 static constexpr int ARGC_THREE_NUMBER = 3;
21 static constexpr int BUF_LENGTH = 256;
22
23 using StorageAsyncContext = struct StorageAsyncContext {
24 napi_env env = nullptr;
25 napi_async_work work = nullptr;
26
27 char key[BUF_LENGTH] = { 0 };
28 size_t keyLen = 0;
29 char value[BUF_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
SetCallbackWork(napi_env env,StorageAsyncContextPtr asyncContext)40 static void SetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext)
41 {
42 napi_value resource = nullptr;
43 napi_create_string_utf8(env, "JSStartupSet", NAPI_AUTO_LENGTH, &resource);
44 napi_create_async_work(
45 env, nullptr, resource,
46 [](napi_env env, void *data) {
47 StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
48 asyncContext->status = SetParameter(asyncContext->key, asyncContext->value);
49 PARAM_JS_LOGV("JSApp set::asyncContext-> status = %d, asyncContext->key = %s, asyncContext->value = %s.",
50 asyncContext->status, asyncContext->key, asyncContext->value);
51 },
52 [](napi_env env, napi_status status, void *data) {
53 StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
54 napi_value result[ARGC_NUMBER] = { 0 };
55 if (asyncContext->status == 0) {
56 napi_get_undefined(env, &result[0]);
57 napi_get_undefined(env, &result[1]);
58 } else {
59 napi_value value = nullptr;
60 napi_create_object(env, &result[0]);
61 napi_create_int32(env, asyncContext->status, &value);
62 napi_set_named_property(env, result[0], "code", value);
63 napi_get_undefined(env, &result[1]);
64 }
65
66 if (asyncContext->deferred) {
67 if (asyncContext->status == 0) {
68 napi_resolve_deferred(env, asyncContext->deferred, result[1]);
69 } else {
70 napi_reject_deferred(env, asyncContext->deferred, result[0]);
71 }
72 } else {
73 napi_value callback = nullptr;
74 napi_value callResult = nullptr;
75 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
76 napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult);
77 napi_delete_reference(env, asyncContext->callbackRef);
78 }
79 napi_delete_async_work(env, asyncContext->work);
80 delete asyncContext;
81 },
82 reinterpret_cast<void *>(asyncContext), &asyncContext->work);
83 napi_queue_async_work(env, asyncContext->work);
84 }
85
Set(napi_env env,napi_callback_info info)86 static napi_value Set(napi_env env, napi_callback_info info)
87 {
88 size_t argc = ARGC_THREE_NUMBER;
89 napi_value argv[ARGC_THREE_NUMBER] = { nullptr };
90 napi_value thisVar = nullptr;
91 void *data = nullptr;
92 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
93 NAPI_ASSERT(env, argc >= ARGC_NUMBER, "requires 2 parameter");
94 StorageAsyncContextPtr asyncContext = new StorageAsyncContext();
95 asyncContext->env = env;
96 for (size_t i = 0; i < argc; i++) {
97 napi_valuetype valueType = napi_null;
98 napi_typeof(env, argv[i], &valueType);
99
100 if (i == 0 && valueType == napi_string) {
101 napi_get_value_string_utf8(env, argv[i], asyncContext->key,
102 BUF_LENGTH - 1, &asyncContext->keyLen);
103 } else if (i == 1 && valueType == napi_string) {
104 napi_get_value_string_utf8(env, argv[i], asyncContext->value,
105 BUF_LENGTH - 1, &asyncContext->valueLen);
106 } else if (i == ARGC_NUMBER && valueType == napi_function) {
107 napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
108 } else {
109 delete asyncContext;
110 NAPI_ASSERT(env, false, "type mismatch");
111 }
112 }
113
114 napi_value result = nullptr;
115 if (asyncContext->callbackRef == nullptr) {
116 napi_create_promise(env, &asyncContext->deferred, &result);
117 } else {
118 napi_get_undefined(env, &result);
119 }
120
121 SetCallbackWork(env, asyncContext);
122 return result;
123 }
124
SetSync(napi_env env,napi_callback_info info)125 static napi_value SetSync(napi_env env, napi_callback_info info)
126 {
127 size_t argc = ARGC_NUMBER;
128 napi_value args[ARGC_NUMBER] = { nullptr };
129 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
130 NAPI_ASSERT(env, argc == ARGC_NUMBER, "Wrong number of arguments");
131 napi_valuetype valuetype0 = napi_null;
132 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
133 napi_valuetype valuetype1 = napi_null;
134 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
135 NAPI_ASSERT(env, valuetype0 == napi_string && valuetype1 == napi_string, "Wrong argument type. string expected.");
136
137 char keyBuf[BUF_LENGTH] = { 0 };
138 size_t keySize = 0;
139 NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], keyBuf, BUF_LENGTH - 1, &keySize));
140 if (keySize >= MAX_LENGTH) {
141 return nullptr;
142 }
143
144 char valueBuf[BUF_LENGTH] = { 0 };
145 size_t valueSize = 0;
146 NAPI_CALL(env, napi_get_value_string_utf8(env, args[1], valueBuf, BUF_LENGTH - 1, &valueSize));
147 if (valueSize >= MAX_LENGTH) {
148 return nullptr;
149 }
150
151 std::string keyStr = keyBuf;
152 std::string valueStr = valueBuf;
153 int setResult = SetParameter(keyStr.c_str(), valueStr.c_str());
154 PARAM_JS_LOGV("JSApp SetSync::setResult = %d, input keyBuf = %s.", setResult, keyBuf);
155
156 napi_value napiValue = nullptr;
157 if (setResult != 0) { // set failed
158 std::stringstream ss;
159 ss << "set: " << keyStr << " failed, error code: " << setResult;
160 napi_throw_error((env), nullptr, ss.str().c_str());
161 } else {
162 napi_get_undefined(env, &napiValue);
163 }
164 return napiValue;
165 }
166
GetSync(napi_env env,napi_callback_info info)167 static napi_value GetSync(napi_env env, napi_callback_info info)
168 {
169 size_t argc = ARGC_NUMBER;
170 napi_value args[ARGC_NUMBER] = { nullptr };
171 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
172 NAPI_ASSERT(env, argc == 1 || argc == ARGC_NUMBER, "Wrong number of arguments");
173 napi_valuetype valuetype0 = napi_null;
174 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
175 NAPI_ASSERT(env, valuetype0 == napi_string, "Wrong argument type. Numbers expected.");
176
177 napi_valuetype valuetype1 = napi_null;
178 if (argc == ARGC_NUMBER) {
179 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
180 NAPI_ASSERT(env, (valuetype1 == napi_string) || (valuetype1 == napi_undefined),
181 "Wrong argument type. string expected.");
182 }
183
184 char keyBuf[BUF_LENGTH] = { 0 };
185 size_t keySize = 0;
186 NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], keyBuf, BUF_LENGTH - 1, &keySize));
187 if (keySize >= MAX_LENGTH) {
188 return nullptr;
189 }
190
191 std::string keyStr = keyBuf;
192 std::string valueStr = "";
193 std::string getValue = "";
194 if (argc == ARGC_NUMBER) {
195 char valueBuf[BUF_LENGTH] = { 0 };
196 size_t valueSize = 0;
197 if (valuetype1 == napi_undefined) {
198 valueStr = "";
199 } else {
200 NAPI_CALL(env, napi_get_value_string_utf8(env, args[1], valueBuf, BUF_LENGTH - 1, &valueSize));
201 if (valueSize >= MAX_LENGTH) {
202 return nullptr;
203 }
204 valueStr = valueBuf;
205 }
206 }
207 int ret = OHOS::system::GetStringParameter(keyStr, getValue, valueStr);
208 PARAM_JS_LOGV("JSApp GetSync::getValue = %s, input keyStr = %s.", getValue.c_str(), keyBuf);
209
210 napi_value napiValue = nullptr;
211 if (ret == 0) {
212 NAPI_CALL(env, napi_create_string_utf8(env, getValue.c_str(), strlen(getValue.c_str()), &napiValue));
213 }
214 return napiValue;
215 }
216
GetCallbackWork(napi_env env,StorageAsyncContextPtr asyncContext)217 static void GetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext)
218 {
219 napi_value resource = nullptr;
220 napi_create_string_utf8(env, "JSStartupGet", NAPI_AUTO_LENGTH, &resource);
221 napi_create_async_work(
222 env, nullptr, resource,
223 [](napi_env env, void *data) {
224 StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
225 asyncContext->status =
226 OHOS::system::GetStringParameter(asyncContext->key, asyncContext->getValue, asyncContext->value);
227 PARAM_JS_LOGV("JSApp get status = %d, asyncContext->getValue = %s, asyncContext->key = %s, value = %s.",
228 asyncContext->status, asyncContext->getValue.c_str(), asyncContext->key, asyncContext->value);
229 },
230 [](napi_env env, napi_status status, void *data) {
231 StorageAsyncContext *asyncContext = reinterpret_cast<StorageAsyncContext *>(data);
232 napi_value result[ARGC_NUMBER] = { 0 };
233 if (asyncContext->status == 0) {
234 napi_get_undefined(env, &result[0]);
235 napi_create_string_utf8(env, asyncContext->getValue.c_str(), strlen(asyncContext->getValue.c_str()),
236 &result[1]);
237 } else {
238 napi_value message = nullptr;
239 napi_create_object(env, &result[0]);
240 napi_create_int32(env, asyncContext->status, &message);
241 napi_set_named_property(env, result[0], "code", message);
242 napi_get_undefined(env, &result[1]);
243 }
244
245 if (asyncContext->deferred) {
246 if (asyncContext->status == 0) {
247 napi_resolve_deferred(env, asyncContext->deferred, result[1]);
248 } else {
249 napi_reject_deferred(env, asyncContext->deferred, result[0]);
250 }
251 } else {
252 napi_value callback = nullptr;
253 napi_value callResult = nullptr;
254 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
255 napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult);
256 napi_delete_reference(env, asyncContext->callbackRef);
257 }
258 napi_delete_async_work(env, asyncContext->work);
259 delete asyncContext;
260 },
261 reinterpret_cast<void *>(asyncContext), &asyncContext->work);
262 napi_queue_async_work(env, asyncContext->work);
263 }
264
Get(napi_env env,napi_callback_info info)265 static napi_value Get(napi_env env, napi_callback_info info)
266 {
267 size_t argc = ARGC_THREE_NUMBER;
268 napi_value argv[ARGC_THREE_NUMBER] = { nullptr };
269 napi_value thisVar = nullptr;
270 void *data = nullptr;
271 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
272 NAPI_ASSERT(env, argc >= 1, "requires 1 parameter");
273 StorageAsyncContextPtr asyncContext = new StorageAsyncContext();
274 asyncContext->env = env;
275 for (size_t i = 0; i < argc; i++) {
276 napi_valuetype valueType = napi_null;
277 napi_typeof(env, argv[i], &valueType);
278
279 if (i == 0 && valueType == napi_string) {
280 napi_get_value_string_utf8(env, argv[i], asyncContext->key,
281 BUF_LENGTH - 1, &asyncContext->keyLen);
282 } else if (i == 1 && valueType == napi_string) {
283 napi_get_value_string_utf8(env, argv[i], asyncContext->value,
284 BUF_LENGTH - 1, &asyncContext->valueLen);
285 } else if (i == 1 && valueType == napi_undefined) {
286 strcpy_s(asyncContext->value, BUF_LENGTH, "\0");
287 } else if (i == 1 && valueType == napi_function) {
288 napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
289 break;
290 } else if (i == ARGC_NUMBER && valueType == napi_function) {
291 napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
292 } else {
293 delete asyncContext;
294 NAPI_ASSERT(env, false, "type mismatch");
295 }
296 }
297
298 napi_value result = nullptr;
299 if (asyncContext->callbackRef == nullptr) {
300 napi_create_promise(env, &asyncContext->deferred, &result);
301 } else {
302 napi_get_undefined(env, &result);
303 }
304
305 GetCallbackWork(env, asyncContext);
306 return result;
307 }
308
309 EXTERN_C_START
310 /*
311 * Module init
312 */
Init(napi_env env,napi_value exports)313 static napi_value Init(napi_env env, napi_value exports)
314 {
315 /*
316 * Attribute definition
317 */
318 napi_property_descriptor desc[] = {
319 DECLARE_NAPI_FUNCTION("set", Set),
320 DECLARE_NAPI_FUNCTION("setSync", SetSync),
321 DECLARE_NAPI_FUNCTION("get", Get),
322 DECLARE_NAPI_FUNCTION("getSync", GetSync),
323 DECLARE_NAPI_FUNCTION("wait", ParamWait),
324 DECLARE_NAPI_FUNCTION("getWatcher", GetWatcher)
325 };
326 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
327 return RegisterWatcher(env, exports);
328 }
329 EXTERN_C_END
330
331 /*
332 * Module definition
333 */
334 static napi_module _module = {
335 .nm_version = 1,
336 .nm_flags = 0,
337 .nm_filename = NULL,
338 .nm_register_func = Init,
339 .nm_modname = "systemparameter",
340 .nm_priv = ((void *)0),
341 .reserved = { 0 }
342 };
343
344 /*
345 * Module registration function
346 */
RegisterModule(void)347 extern "C" __attribute__((constructor)) void RegisterModule(void)
348 {
349 napi_module_register(&_module);
350 }
351