1/*
2 * Copyright (c) 2023 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 "common.h"
17
18#include "standby_service_log.h"
19
20namespace OHOS {
21namespace DevStandbyMgr {
22namespace {
23const uint32_t ASYNC_CALLBACK_PARAM_NUM = 2;
24const uint32_t STRING_MAX_SIZE = 128;
25}
26
27AsyncWorkData::AsyncWorkData(napi_env napiEnv)
28{
29    env = napiEnv;
30}
31
32AsyncWorkData::~AsyncWorkData()
33{
34    if (callback) {
35        STANDBYSERVICE_LOGD("AsyncWorkData::~AsyncWorkData delete callback");
36        napi_delete_reference(env, callback);
37        callback = nullptr;
38    }
39    if (asyncWork) {
40        STANDBYSERVICE_LOGD("AsyncWorkData::~AsyncWorkData delete asyncWork");
41        napi_delete_async_work(env, asyncWork);
42        asyncWork = nullptr;
43    }
44}
45
46napi_value Common::NapiGetNull(napi_env env)
47{
48    napi_value result = nullptr;
49    napi_get_null(env, &result);
50    return result;
51}
52
53void Common::PaddingAsyncWorkData(
54    const napi_env& env, const napi_ref& callback, AsyncWorkData& info, napi_value& promise)
55{
56    if (callback) {
57        info.callback = callback;
58        info.isCallback = true;
59    } else {
60        napi_deferred deferred = nullptr;
61        NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
62        info.deferred = deferred;
63        info.isCallback = false;
64    }
65}
66
67void Common::ReturnCallbackPromise(const napi_env& env, const AsyncWorkData& info, const napi_value& result)
68{
69    if (info.isCallback) {
70        SetCallback(env, info.callback, info.errCode, result);
71    } else {
72        SetPromise(env, info, result);
73    }
74}
75
76void Common::SetCallback(
77    const napi_env& env, const napi_ref& callbackIn, const int32_t& errCode, const napi_value& result)
78{
79    napi_value undefined = nullptr;
80    napi_get_undefined(env, &undefined);
81
82    napi_value callback = nullptr;
83    napi_value resultout = nullptr;
84    napi_get_reference_value(env, callbackIn, &callback);
85    napi_value results[ASYNC_CALLBACK_PARAM_NUM] = {nullptr};
86    if (errCode == ERR_OK) {
87        results[0] = NapiGetNull(env);
88    } else {
89        int32_t errCodeInfo = FindErrCode(env, errCode);
90        std::string errMsg = FindErrMsg(env, errCode);
91        results[0] = GetCallbackErrorValue(env, errCodeInfo, errMsg);
92    }
93    results[1] = result;
94    NAPI_CALL_RETURN_VOID(env,
95        napi_call_function(env, undefined, callback, ASYNC_CALLBACK_PARAM_NUM, &results[0], &resultout));
96}
97
98napi_value Common::SetPromise(
99    const napi_env& env, const AsyncWorkData& info, const napi_value& result)
100{
101    if (info.errCode == ERR_OK) {
102        napi_resolve_deferred(env, info.deferred, result);
103    } else {
104        int32_t errCodeInfo = FindErrCode(env, info.errCode);
105        std::string errMsg = FindErrMsg(env, info.errCode);
106        napi_value error = nullptr;
107        napi_value eCode = nullptr;
108        napi_value eMsg = nullptr;
109        NAPI_CALL(env, napi_create_int32(env, errCodeInfo, &eCode));
110        NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
111            errMsg.length(), &eMsg));
112        NAPI_CALL(env, napi_create_object(env, &error));
113        NAPI_CALL(env, napi_set_named_property(env, error, "data", eCode));
114        NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
115        NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
116        napi_reject_deferred(env, info.deferred, error);
117    }
118    return result;
119}
120
121napi_value Common::GetCallbackErrorValue(napi_env env, const int32_t errCode, const std::string errMsg)
122{
123    if (errCode == ERR_OK) {
124        return NapiGetNull(env);
125    }
126    napi_value error = nullptr;
127    napi_value eCode = nullptr;
128    napi_value eMsg = nullptr;
129    NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
130    NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
131        errMsg.length(), &eMsg));
132    NAPI_CALL(env, napi_create_object(env, &error));
133    NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
134    NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
135    return error;
136}
137
138void Common::HandleErrCode(const napi_env &env, int32_t errCode)
139{
140    STANDBYSERVICE_LOGI("HandleErrCode errCode = %{public}d", errCode);
141    if (errCode == ERR_OK) {
142        return;
143    }
144    std::string errMsg = FindErrMsg(env, errCode);
145    int32_t errCodeInfo = FindErrCode(env, errCode);
146    if (errMsg != "") {
147        napi_throw_error(env, std::to_string(errCodeInfo).c_str(), errMsg.c_str());
148    }
149}
150
151std::string Common::FindErrMsg(const napi_env& env, const int32_t errCode)
152{
153    if (errCode == ERR_OK) {
154        return "";
155    }
156    auto iter = saErrCodeMsgMap.find(errCode);
157    if (iter != saErrCodeMsgMap.end()) {
158        std::string errMessage = "BussinessError ";
159        int32_t errCodeInfo = FindErrCode(env, errCode);
160        errMessage.append(std::to_string(errCodeInfo)).append(": ").append(iter->second);
161        return errMessage;
162    }
163    iter = paramErrCodeMsgMap.find(errCode);
164    if (iter != paramErrCodeMsgMap.end()) {
165        std::string errMessage = "BussinessError 401: Parameter error. ";
166        errMessage.append(paramErrCodeMsgMap[errCode]);
167        return errMessage;
168    }
169    return "Inner error.";
170}
171
172int32_t Common::FindErrCode(const napi_env& env, const int32_t errCodeIn)
173{
174    auto iter = paramErrCodeMsgMap.find(errCodeIn);
175    if (iter != paramErrCodeMsgMap.end()) {
176        return ERR_STANDBY_INVALID_PARAM;
177    }
178    return errCodeIn > THRESHOLD ? errCodeIn / OFFSET : errCodeIn;
179}
180
181bool Common::HandleParamErr(const napi_env& env, int32_t errCode)
182{
183    STANDBYSERVICE_LOGI("HandleParamErr errCode = %{public}d, isThrow = true", errCode);
184    if (errCode == ERR_OK) {
185        return false;
186    }
187    auto iter = paramErrCodeMsgMap.find(errCode);
188    if (iter != paramErrCodeMsgMap.end()) {
189        std::string errMessage = "BussinessError 401: Parameter error. ";
190        errMessage.append(paramErrCodeMsgMap[errCode]);
191        napi_throw_error(env, std::to_string(ERR_STANDBY_INVALID_PARAM).c_str(), errMessage.c_str());
192        return true;
193    }
194    return false;
195}
196
197void Common::SetInt32Value(const napi_env& env, const std::string& fieldStr, const int32_t intValue, napi_value& result)
198{
199    napi_value value = nullptr;
200    napi_create_int32(env, intValue, &value);
201    napi_set_named_property(env, result, fieldStr.c_str(), value);
202}
203
204void Common::SetUint32Value(const napi_env& env, const std::string& fieldStr,
205    const uint32_t uintValue, napi_value& result)
206{
207    napi_value value = nullptr;
208    napi_create_uint32(env, uintValue, &value);
209    napi_set_named_property(env, result, fieldStr.c_str(), value);
210}
211
212napi_value Common::GetStringValue(const napi_env &env, const napi_value &value, std::string &result)
213{
214    napi_valuetype valuetype = napi_undefined;
215    NAPI_CALL(env, napi_typeof(env, value, &valuetype));
216    if (valuetype != napi_string) {
217        return nullptr;
218    }
219
220    char str[STRING_MAX_SIZE] = {0};
221    size_t strLen = 0;
222    napi_status status = napi_get_value_string_utf8(env, value, str, STRING_MAX_SIZE - 1, &strLen);
223    if (status != napi_ok) {
224        return nullptr;
225    }
226    result = std::string(str);
227    STANDBYSERVICE_LOGD("GetStringValue result: %{public}s", result.c_str());
228    return Common::NapiGetNull(env);
229}
230
231void Common::SetStringValue(const napi_env& env, const std::string& fieldStr,
232    const std::string& stringValue, napi_value& result)
233{
234    napi_value value = nullptr;
235    napi_create_string_utf8(env, stringValue.c_str(), stringValue.length(), &value);
236    napi_set_named_property(env, result, fieldStr.c_str(), value);
237}
238
239napi_value Common::GetUint32Value(const napi_env& env, const napi_value& value, uint32_t& result)
240{
241    napi_valuetype valuetype = napi_undefined;
242    NAPI_CALL(env, napi_typeof(env, value, &valuetype));
243    if (valuetype != napi_number) {
244        return nullptr;
245    }
246    NAPI_CALL(env, napi_get_value_uint32(env, value, &result));
247    STANDBYSERVICE_LOGI("GetUint32Value result: %{public}d", static_cast<int32_t>(result));
248
249    return Common::NapiGetNull(env);
250}
251
252napi_value Common::GetInt32Value(const napi_env& env, const napi_value& value, int32_t& result)
253{
254    napi_valuetype valuetype = napi_undefined;
255    NAPI_CALL(env, napi_typeof(env, value, &valuetype));
256    if (valuetype != napi_number) {
257        return nullptr;
258    }
259    NAPI_CALL(env, napi_get_value_int32(env, value, &result));
260    STANDBYSERVICE_LOGI("GetInt32Value result: %{public}d", static_cast<int32_t>(result));
261
262    return Common::NapiGetNull(env);
263}
264
265napi_value Common::GetNamedInt32Value(const napi_env &env, napi_value &object, const char* utf8name,
266    int32_t& result)
267{
268    bool hasNamedProperty = false;
269    napi_value intValue = nullptr;
270    if (napi_has_named_property(env, object, utf8name, &hasNamedProperty) != napi_ok || !hasNamedProperty) {
271        STANDBYSERVICE_LOGE("GetNamedInt32Value failed, %{public}s not exist, is nullptr", utf8name);
272        return nullptr;
273    }
274    NAPI_CALL(env, napi_get_named_property(env, object, utf8name, &intValue));
275    if (!Common::GetInt32Value(env, intValue, result)) {
276        STANDBYSERVICE_LOGE("GetNamedInt32Value failed, %{public}s is nullptr", utf8name);
277        return nullptr;
278    }
279    STANDBYSERVICE_LOGD("GetNamedInt32Value: %{public}s is %{public}d", utf8name, result);
280    return Common::NapiGetNull(env);
281}
282
283napi_value Common::GetNamedStringValue(const napi_env &env, napi_value &object, const char* utf8name,
284    std::string& result)
285{
286    bool hasNamedProperty = false;
287    napi_value stringValue = nullptr;
288    if (napi_has_named_property(env, object, utf8name, &hasNamedProperty) != napi_ok || !hasNamedProperty) {
289        STANDBYSERVICE_LOGE("GetNamedStringValue failed, string not exist, is nullptr");
290        return nullptr;
291    }
292    NAPI_CALL(env, napi_get_named_property(env, object, utf8name, &stringValue));
293    if (!Common::GetStringValue(env, stringValue, result)) {
294        STANDBYSERVICE_LOGE("GetStringValue failed, the string is nullptr");
295        return nullptr;
296    }
297    STANDBYSERVICE_LOGD("GetNamedStringValue: result is %{public}s", result.c_str());
298    return Common::NapiGetNull(env);
299}
300}  // namespace DevStandbyMgr
301}  // namespace OHOS