1 /*
2 * Copyright (c) 2020 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
16 #include "nativeapi_kv.h"
17 #include <securec.h>
18 #include <new>
19 #include "ability_env.h"
20 #include "js_async_work.h"
21 #include "nativeapi_common.h"
22 #include "nativeapi_config.h"
23 #include "nativeapi_kv_impl.h"
24
25 namespace OHOS {
26 namespace ACELite {
27 namespace {
28 char g_kvFullPath[FILE_NAME_MAX_LEN + 1] = {0};
29
IsValidKey(const char * key)30 bool IsValidKey(const char* key)
31 {
32 if (key == nullptr) {
33 return false;
34 }
35 size_t keyLen = strnlen(key, KEY_MAX_LEN + 1);
36 if ((keyLen == 0) || (keyLen > KEY_MAX_LEN)) {
37 return false;
38 }
39 if (strpbrk(key, "/\\\"*+,:;<=>\?[]|\x7F")) {
40 return false;
41 }
42 return true;
43 }
44
GetFullPath(const char * dataPath,const char * key)45 int GetFullPath(const char* dataPath, const char* key)
46 {
47 if (!IsValidKey(key) || (dataPath == nullptr)) {
48 return ERROR_CODE_PARAM;
49 }
50 if (memset_s(g_kvFullPath, sizeof(g_kvFullPath), 0x0, sizeof(g_kvFullPath)) != EOK) {
51 return ERROR_CODE_GENERAL;
52 }
53 if (sprintf_s(g_kvFullPath, sizeof(g_kvFullPath), "%s/%s/%s", dataPath, DEFAULT_FOLDER_PATH, key) < 0) {
54 return ERROR_CODE_GENERAL;
55 }
56 return NATIVE_SUCCESS;
57 }
58
GetDefault(const JSIValue thisVal,const JSIValue args)59 void GetDefault(const JSIValue thisVal, const JSIValue args)
60 {
61 char* defaultValue = JSI::GetStringProperty(args, DEFAULT);
62 JSIValue result;
63 if (defaultValue == nullptr) {
64 result = JSI::CreateString("");
65 } else {
66 result = JSI::CreateString(defaultValue);
67 }
68 JSI::ReleaseString(defaultValue);
69 NativeapiCommon::SuccessCallBack(thisVal, args, result);
70 JSI::ReleaseValue(result);
71 }
72
GetValueInner(const char * dataPath,const char * key,char * value)73 int GetValueInner(const char* dataPath, const char* key, char* value)
74 {
75 int ret = GetFullPath(dataPath, key);
76 if (ret != NATIVE_SUCCESS) {
77 return ret;
78 }
79 return GetValue(g_kvFullPath, value);
80 }
81
SetValueInner(const char * dataPath,const char * key,const char * value)82 int SetValueInner(const char* dataPath, const char* key, const char* value)
83 {
84 int ret = GetFullPath(dataPath, key);
85 if (ret != NATIVE_SUCCESS) {
86 return ret;
87 }
88 return SetValue(g_kvFullPath, value);
89 }
90
DeleteValueInner(const char * dataPath,const char * key)91 int DeleteValueInner(const char* dataPath, const char* key)
92 {
93 int ret = GetFullPath(dataPath, key);
94 if (ret != NATIVE_SUCCESS) {
95 return ret;
96 }
97 return DeleteValue(g_kvFullPath);
98 }
99
ExecuteAsyncWork(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum,AsyncWorkHandler ExecuteFunc,bool flag)100 JSIValue ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args,
101 uint8_t argsNum, AsyncWorkHandler ExecuteFunc, bool flag)
102 {
103 JSIValue undefValue = JSI::CreateUndefined();
104 if (!NativeapiCommon::IsValidJSIValue(args, argsNum)) {
105 return undefValue;
106 }
107 FuncParams* params = new(std::nothrow) FuncParams();
108 if (params == nullptr) {
109 return undefValue;
110 }
111 params->thisVal = JSI::AcquireValue(thisVal);
112 params->args = JSI::AcquireValue(args[0]);
113 params->flag = flag;
114 JsAsyncWork::DispatchAsyncWork(ExecuteFunc, reinterpret_cast<void *>(params));
115 return undefValue;
116 }
117
ExecuteGet(void * data)118 void ExecuteGet(void* data)
119 {
120 FuncParams* params = reinterpret_cast<FuncParams *>(data);
121 if (params == nullptr) {
122 return;
123 }
124 JSIValue args = params->args;
125 JSIValue thisVal = params->thisVal;
126 char* key = JSI::GetStringProperty(args, KV_KEY);
127 const char* dataPath = GetDataPath();
128 JSIValue result = JSI::CreateUndefined();
129 int ret = ERROR_CODE_GENERAL;
130 char* value = reinterpret_cast<char *>(malloc(VALUE_MAX_LEN + 1));
131 if (value == nullptr) {
132 NativeapiCommon::FailCallBack(thisVal, args, ret);
133 goto EXIT;
134 }
135 ret = InitKv(dataPath);
136 if (ret != NATIVE_SUCCESS) {
137 NativeapiCommon::FailCallBack(thisVal, args, ret);
138 goto EXIT;
139 }
140 ret = GetValueInner(dataPath, key, value);
141 if (ret == ERROR_FR_NO_FILE) {
142 GetDefault(thisVal, args);
143 goto EXIT;
144 }
145 if (ret != NATIVE_SUCCESS) {
146 NativeapiCommon::FailCallBack(thisVal, args, ret);
147 goto EXIT;
148 }
149 result = JSI::CreateString(value);
150 NativeapiCommon::SuccessCallBack(thisVal, args, result);
151 EXIT:
152 free(value);
153 JSI::ReleaseString(key);
154 JSI::ReleaseValueList(args, thisVal, result, ARGS_END);
155 delete params;
156 }
157
ExecuteSet(void * data)158 void ExecuteSet(void* data)
159 {
160 FuncParams* params = reinterpret_cast<FuncParams *>(data);
161 if (params == nullptr) {
162 return;
163 }
164 JSIValue args = params->args;
165 JSIValue thisVal = params->thisVal;
166 char* key = JSI::GetStringProperty(args, KV_KEY);
167 char* value = JSI::GetStringProperty(args, KV_VALUE);
168 const char* dataPath = GetDataPath();
169 int ret = InitKv(dataPath);
170 if (ret != NATIVE_SUCCESS) {
171 NativeapiCommon::FailCallBack(thisVal, args, ret);
172 goto EXIT;
173 }
174 if ((key == nullptr) || !strlen(key)) {
175 NativeapiCommon::FailCallBack(thisVal, args, ERROR_CODE_PARAM);
176 goto EXIT;
177 }
178 if ((value == nullptr) || !strlen(value)) {
179 DeleteValueInner(dataPath, key);
180 NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
181 goto EXIT;
182 }
183 ret = SetValueInner(dataPath, key, value);
184 if (ret != NATIVE_SUCCESS) {
185 NativeapiCommon::FailCallBack(thisVal, args, ret);
186 goto EXIT;
187 }
188 NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
189 EXIT:
190 JSI::ReleaseString(key);
191 JSI::ReleaseString(value);
192 JSI::ReleaseValueList(args, thisVal, ARGS_END);
193 delete params;
194 }
195
ExecuteDelete(void * data)196 void ExecuteDelete(void* data)
197 {
198 FuncParams* params = reinterpret_cast<FuncParams *>(data);
199 if (params == nullptr) {
200 return;
201 }
202 JSIValue args = params->args;
203 JSIValue thisVal = params->thisVal;
204 const char* dataPath = GetDataPath();
205 int ret = InitKv(dataPath);
206 if (ret != NATIVE_SUCCESS) {
207 NativeapiCommon::FailCallBack(thisVal, args, ret);
208 JSI::ReleaseValueList(args, thisVal, ARGS_END);
209 delete params;
210 return;
211 }
212 char* key = JSI::GetStringProperty(args, KV_KEY);
213 ret = DeleteValueInner(dataPath, key);
214 JSI::ReleaseString(key);
215 if ((ret < 0) && (ret != ERROR_FR_NO_FILE)) {
216 NativeapiCommon::FailCallBack(thisVal, args, ret);
217 JSI::ReleaseValueList(args, thisVal, ARGS_END);
218 delete params;
219 return;
220 }
221 NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
222 JSI::ReleaseValueList(args, thisVal, ARGS_END);
223 delete params;
224 }
225
ExecuteClear(void * data)226 void ExecuteClear(void* data)
227 {
228 FuncParams* params = reinterpret_cast<FuncParams *>(data);
229 if (params == nullptr) {
230 return;
231 }
232 JSIValue args = params->args;
233 JSIValue thisVal = params->thisVal;
234 const char* dataPath = GetDataPath();
235 int ret = InitKv(dataPath);
236 if (ret != NATIVE_SUCCESS) {
237 NativeapiCommon::FailCallBack(thisVal, args, ret);
238 JSI::ReleaseValueList(args, thisVal, ARGS_END);
239 delete params;
240 return;
241 }
242 ret = ClearKVStore(dataPath);
243 if (ret != NATIVE_SUCCESS) {
244 NativeapiCommon::FailCallBack(thisVal, args, ret);
245 JSI::ReleaseValueList(args, thisVal, ARGS_END);
246 delete params;
247 return;
248 }
249 NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
250 JSI::ReleaseValueList(args, thisVal, ARGS_END);
251 delete params;
252 }
253 }
254
InitNativeApiKv(JSIValue exports)255 void InitNativeApiKv(JSIValue exports)
256 {
257 JSI::SetModuleAPI(exports, "get", NativeapiKv::Get);
258 JSI::SetModuleAPI(exports, "set", NativeapiKv::Set);
259 JSI::SetModuleAPI(exports, "delete", NativeapiKv::Delete);
260 JSI::SetModuleAPI(exports, "clear", NativeapiKv::Clear);
261 }
262
Get(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)263 JSIValue NativeapiKv::Get(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
264 {
265 return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGet, false);
266 }
267
Set(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)268 JSIValue NativeapiKv::Set(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
269 {
270 return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteSet, false);
271 }
272
Delete(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)273 JSIValue NativeapiKv::Delete(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
274 {
275 return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteDelete, false);
276 }
277
Clear(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)278 JSIValue NativeapiKv::Clear(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
279 {
280 JSIValue undefValue = JSI::CreateUndefined();
281 FuncParams* params = new(std::nothrow) FuncParams();
282 if (params == nullptr) {
283 return undefValue;
284 }
285 params->thisVal = JSI::AcquireValue(thisVal);
286 if (NativeapiCommon::IsValidJSIValue(args, argsNum)) {
287 params->args = JSI::AcquireValue(args[0]);
288 }
289 JsAsyncWork::DispatchAsyncWork(reinterpret_cast<AsyncWorkHandler>(ExecuteClear), reinterpret_cast<void *>(params));
290 return undefValue;
291 }
292 } // ACELite
293 } // OHOS
294