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 "napi_storage_helper.h"
16 
17 #include <linux/limits.h>
18 
19 #include <string>
20 
21 #include "js_common_utils.h"
22 #include "napi_async_call.h"
23 #include "napi_storage.h"
24 #include "preferences.h"
25 #include "preferences_errno.h"
26 
27 using namespace OHOS::NativePreferences;
28 using namespace OHOS::PreferencesJsKit;
29 
30 namespace OHOS {
31 namespace StorageJsKit {
32 struct HelperAysncContext : public BaseContext {
33     std::string path;
HelperAysncContextOHOS::StorageJsKit::HelperAysncContext34     HelperAysncContext()
35     {
36     }
~HelperAysncContextOHOS::StorageJsKit::HelperAysncContext37     virtual ~HelperAysncContext(){};
38 };
39 
GetStorageSync(napi_env env,napi_callback_info info)40 napi_value GetStorageSync(napi_env env, napi_callback_info info)
41 {
42     size_t argc = 1;
43     napi_value args[1] = { 0 };
44     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
45     LOG_DEBUG("getPreferences %{public}zu", argc);
46     napi_value instance = nullptr;
47     NAPI_CALL(env, StorageProxy::NewInstance(env, args[0], &instance));
48     LOG_DEBUG("getPreferences end");
49     return instance;
50 }
51 
ParseString(const napi_env env,const napi_value value,std::shared_ptr<HelperAysncContext> asyncContext)52 int ParseString(const napi_env env, const napi_value value, std::shared_ptr<HelperAysncContext> asyncContext)
53 {
54     if (asyncContext == nullptr) {
55         LOG_WARN("error input");
56         return ERR;
57     }
58     char *path = new (std::nothrow) char[PATH_MAX];
59     if (path == nullptr) {
60         LOG_ERROR("ParseString new failed, path is nullptr");
61         return ERR;
62     }
63     size_t pathLen = 0;
64     napi_get_value_string_utf8(env, value, path, PATH_MAX, &pathLen);
65     asyncContext->path = path;
66     delete[] path;
67     return OK;
68 }
69 
GetStorage(napi_env env,napi_callback_info info)70 napi_value GetStorage(napi_env env, napi_callback_info info)
71 {
72     LOG_DEBUG("GetStorage start");
73     auto context = std::make_shared<HelperAysncContext>();
74     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
75         PRE_CHECK_RETURN_VOID_SET(argc == 1, std::make_shared<ParamNumError>("1 or 2"));
76         PRE_CHECK_RETURN_VOID(ParseString(env, argv[0], context) == OK);
77     };
78     auto exec = [context]() -> int {
79         int errCode = E_OK;
80         OHOS::NativePreferences::PreferencesHelper::GetPreferences(context->path, errCode);
81         LOG_DEBUG("GetPreferences return %{public}d", errCode);
82         return errCode;
83     };
84     auto output = [context](napi_env env, napi_value &result) {
85         napi_value path = nullptr;
86         napi_create_string_utf8(env, context->path.c_str(), NAPI_AUTO_LENGTH, &path);
87         auto ret = StorageProxy::NewInstance(env, path, &result);
88         PRE_CHECK_RETURN_VOID_SET(ret == napi_ok,
89             std::make_shared<InnerError>("Failed to get instance when getting storage."));
90         LOG_DEBUG("GetPreferences end.");
91     };
92     context->SetAction(env, info, input, exec, output);
93 
94     PRE_CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
95     return AsyncCall::Call(env, context, "GetStorage");
96 }
97 
GetInputPath(napi_env env,napi_callback_info info,std::string & pathString)98 napi_status GetInputPath(napi_env env, napi_callback_info info, std::string &pathString)
99 {
100     size_t argc = 1;
101     napi_value args[1] = { 0 };
102     napi_status ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
103     if (ret != napi_ok) {
104         return ret;
105     }
106 
107     napi_valuetype valueType;
108     ret = napi_typeof(env, args[0], &valueType);
109     if (ret != napi_ok || valueType != napi_string) {
110         return napi_invalid_arg;
111     }
112 
113     char *path = new (std::nothrow) char[PATH_MAX];
114     if (path == nullptr) {
115         LOG_ERROR("GetInputPath new failed, path is nullptr");
116         return napi_arraybuffer_expected;
117     }
118     size_t pathLen = 0;
119     ret = napi_get_value_string_utf8(env, args[0], path, PATH_MAX, &pathLen);
120     pathString = path;
121     delete[] path;
122     return ret;
123 }
124 
DeleteStorageSync(napi_env env,napi_callback_info info)125 napi_value DeleteStorageSync(napi_env env, napi_callback_info info)
126 {
127     std::string path;
128     napi_status ret = GetInputPath(env, info, path);
129     if (ret != napi_ok) {
130         napi_throw_error(env, nullptr, "Input path error");
131         return nullptr;
132     }
133     int errCode = PreferencesHelper::DeletePreferences(path);
134     if (errCode != E_OK) {
135         LOG_ERROR("deleteStorage failed %{public}d", errCode);
136         napi_throw_error(env, std::to_string(errCode).c_str(), "deleteStorage failed");
137     }
138     LOG_DEBUG("deleteStorage end");
139 
140     return nullptr;
141 }
142 
DeleteStorage(napi_env env,napi_callback_info info)143 napi_value DeleteStorage(napi_env env, napi_callback_info info)
144 {
145     LOG_DEBUG("DeletePreferences start");
146     auto context = std::make_shared<HelperAysncContext>();
147     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
148         PRE_CHECK_RETURN_VOID_SET(argc == 1, std::make_shared<ParamNumError>("1 or 2"));
149         PRE_CHECK_RETURN_VOID(ParseString(env, argv[0], context) == OK);
150     };
151     auto exec = [context]() -> int {
152         int errCode = PreferencesHelper::DeletePreferences(context->path);
153         LOG_DEBUG("DeletePreferences execfunction return %{public}d", errCode);
154         PRE_CHECK_RETURN_ERR_SET(errCode == E_OK,
155             std::make_shared<InnerError>("Failed to delete preferences when deleting storage."));
156         return OK;
157     };
158     auto output = [context](napi_env env, napi_value &result) {
159         napi_status status = napi_get_undefined(env, &result);
160         PRE_CHECK_RETURN_VOID_SET(status == napi_ok,
161             std::make_shared<InnerError>("Failed to get undefined when deleting storage."));
162         LOG_DEBUG("DeletePreferences end.");
163     };
164     context->SetAction(env, info, input, exec, output);
165 
166     PRE_CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
167     return AsyncCall::Call(env, context, "DeleteStorage");
168 }
169 
RemoveStorageFromCacheSync(napi_env env,napi_callback_info info)170 napi_value RemoveStorageFromCacheSync(napi_env env, napi_callback_info info)
171 {
172     std::string path;
173     napi_status ret = GetInputPath(env, info, path);
174     if (ret != napi_ok) {
175         napi_throw_error(env, nullptr, "Input path error");
176         return nullptr;
177     }
178 
179     int errCode = PreferencesHelper::RemovePreferencesFromCache(path);
180     if (errCode != E_OK) {
181         LOG_ERROR("removeStorageFromCache failed %{public}d", errCode);
182         napi_throw_error(env, std::to_string(errCode).c_str(), "removeStorageFromCache failed");
183     }
184     LOG_DEBUG("removeStorageFromCache end");
185 
186     return nullptr;
187 }
188 
RemoveStorageFromCache(napi_env env,napi_callback_info info)189 napi_value RemoveStorageFromCache(napi_env env, napi_callback_info info)
190 {
191     LOG_DEBUG("RemovePreferencesFromCache start");
192     auto context = std::make_shared<HelperAysncContext>();
193     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) {
194         PRE_CHECK_RETURN_VOID_SET(argc == 1, std::make_shared<ParamNumError>("1 or 2"));
195         PRE_CHECK_RETURN_VOID(ParseString(env, argv[0], context) == OK);
196     };
197     auto exec = [context]() -> int {
198         int errCode = PreferencesHelper::RemovePreferencesFromCache(context->path);
199         LOG_DEBUG("RemovePreferencesFromCache return %{public}d", errCode);
200         return (errCode == E_OK) ? OK : ERR;
201     };
202     auto output = [context](napi_env env, napi_value &result) {
203         napi_status status = napi_get_undefined(env, &result);
204         PRE_CHECK_RETURN_VOID_SET(status == napi_ok,
205             std::make_shared<InnerError>("Failed to get undefined when removing storage."));
206         LOG_DEBUG("RemovePreferencesFromCache end.");
207     };
208     context->SetAction(env, info, input, exec, output);
209 
210     PRE_CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK);
211     return AsyncCall::Call(env, context, "RemoveStorageFromCache");
212 }
213 
InitPreferenceHelper(napi_env env,napi_value exports)214 napi_value InitPreferenceHelper(napi_env env, napi_value exports)
215 {
216     napi_property_descriptor properties[] = {
217         DECLARE_NAPI_FUNCTION("getStorage", GetStorage),
218         DECLARE_NAPI_FUNCTION("getStorageSync", GetStorageSync),
219         DECLARE_NAPI_FUNCTION("deleteStorage", DeleteStorage),
220         DECLARE_NAPI_FUNCTION("deleteStorageSync", DeleteStorageSync),
221         DECLARE_NAPI_FUNCTION("removeStorageFromCache", RemoveStorageFromCache),
222         DECLARE_NAPI_FUNCTION("removeStorageFromCacheSync", RemoveStorageFromCacheSync),
223         DECLARE_NAPI_PROPERTY("MAX_KEY_LENGTH", JSUtils::Convert2JSValue(env, Preferences::MAX_KEY_LENGTH)),
224         DECLARE_NAPI_PROPERTY("MAX_VALUE_LENGTH", JSUtils::Convert2JSValue(env, Preferences::MAX_VALUE_LENGTH)),
225     };
226     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
227     return exports;
228 }
229 } // namespace StorageJsKit
230 } // namespace OHOS
231