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