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