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 18static constexpr int MAX_LENGTH = 128; 19static constexpr int ARGC_NUMBER = 2; 20static constexpr int ARGC_THREE_NUMBER = 3; 21static constexpr int BUF_LENGTH = 256; 22 23using 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 38using StorageAsyncContextPtr = StorageAsyncContext *; 39 40static 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 86static 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 125static 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 167static 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 217static 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 265static 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 309EXTERN_C_START 310/* 311 * Module init 312 */ 313static 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} 329EXTERN_C_END 330 331/* 332 * Module definition 333 */ 334static 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 */ 347extern "C" __attribute__((constructor)) void RegisterModule(void) 348{ 349 napi_module_register(&_module); 350} 351