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