• 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 
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