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