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 const std::map<int32_t, std::string> SA_ERRCODE_MSG_MAP = {
27 {ERR_BGTASK_PERMISSION_DENIED, "Permission denied."},
28 {ERR_BGTASK_NOT_SYSTEM_APP,
29 "System API verification failed. Only system application can apply."},
30 {ERR_BGTASK_NO_MEMORY, "Memory operation failed. Failed to allocate the memory."},
31 {ERR_BGTASK_SYS_NOT_READY, "System service operation failed. The system service is not ready."},
32 {ERR_BGTASK_SERVICE_NOT_CONNECTED, "System service operation failed. The system service is not connected."},
33 {ERR_BGTASK_PARCELABLE_FAILED, "Parcel operation failed."},
34 {ERR_BGTASK_TRANSACT_FAILED, "Internal transaction failed."},
35 {ERR_BGTASK_OBJECT_EXISTS,
36 "Continuous Task verification failed. The application has applied for a continuous task."},
37 {ERR_BGTASK_OBJECT_NOT_EXIST,
38 "Continuous Task verification failed. The application has not applied for a continuous task."},
39 {ERR_BGTASK_KEEPING_TASK_VERIFY_ERR,
40 "Continuous Task verification failed. TASK_KEEPING background mode only supported in particular device."},
41 {ERR_BGTASK_INVALID_BGMODE, "Continuous Task verification failed. The bgMode is invalid."},
42 {ERR_BGTASK_NOTIFICATION_VERIFY_FAILED, "Notification verification failed for a continuous task."
43 " The title or text of the notification cannot be empty."},
44 {ERR_BGTASK_NOTIFICATION_ERR, "Notification verification failed. Failed to send or cancel the notification."},
45 {ERR_BGTASK_CREATE_FILE_ERR, "Continuous task storage failed. Failed to create the storage task file."},
46 {ERR_BGTASK_GET_ACTUAL_FILE_ERR, "Task storage failed. Failed to get the actual storage task file."},
47 {ERR_BGTASK_OPEN_FILE_ERR, "Task storage failed. Failed to open the file."},
48 {ERR_BGTASK_INVALID_PID_OR_UID,
49 "Caller information verification failed for a transient task. Invalid pid or uid."},
50 {ERR_BGTASK_INVALID_BUNDLE_NAME,
51 "Caller information verification failed for a transient task. The bundleName cannot be found."},
52 {ERR_BGTASK_INVALID_REQUEST_ID,
53 "Caller information verification failed for a transient task. Invalid requestId."},
54 {ERR_BGTASK_INVALID_CALLBACK,
55 "Transient task verification failed. The callback cannot be empty."},
56 {ERR_BGTASK_CALLBACK_EXISTS, "Transient task verification failed. The callback already exists."},
57 {ERR_BGTASK_CALLBACK_NOT_EXIST, "Transient task verification failed. The callback does not exist."},
58 {ERR_BGTASK_NOT_IN_PRESET_TIME,
59 "Transient task verification failed. Request is not allow after the preset time of entering background."},
60 {ERR_BGTASK_EXCEEDS_THRESHOLD, "Transient task verification failed. The number of request exceeds the threshold."},
61 {ERR_BGTASK_TIME_INSUFFICIENT,
62 "Transient task verification failed. The remaining time to run transient task is insufficient."},
63 {ERR_BGTASK_RESOURCES_EXCEEDS_MAX, "Caller information verification failed for an energy"
64 " resource request. The number of resources applied exceeds maximun."},
65 {ERR_BGTASK_SERVICE_INNER_ERROR, "Service inner error."},
66 {ERR_BGTASK_NOREQUEST_TASK, "Transient task verification failed. application no request transient task."},
67 {ERR_BGTASK_FOREGROUND, "Transient task verification failed. application is foreground."},
68 {ERR_BGTASK_INVALID_PROCESS_NAME, "Transient task verification failed. caller process name invaild."},
69 };
70
71 const std::map<int32_t, std::string> PARAM_ERRCODE_MSG_MAP = {
72 {ERR_PARAM_NUMBER_ERR, "The number of arguments is wrong."},
73 {ERR_REASON_NULL_OR_TYPE_ERR, "The reason cannot be null and its type must be string."},
74 {ERR_CALLBACK_NULL_OR_TYPE_ERR, "The callback cannot be null and its type must be function."},
75 {ERR_REQUESTID_NULL_OR_ID_TYPE_ERR, "The requestId cannot be null and its type must be integer."},
76 {ERR_REQUESTID_ILLEGAL, "The requestId must be greater than 0."},
77 {ERR_CONTEXT_NULL_OR_TYPE_ERR, "The context cannot be null and its type must be Context."},
78 {ERR_BGMODE_NULL_OR_TYPE_ERR, "The bgMode cannot be null and its type must be BackgroundMode object."},
79 {ERR_WANTAGENT_NULL_OR_TYPE_ERR, "The wantAgent cannot be null and its type must be WantAgent object."},
80 {ERR_ABILITY_INFO_EMPTY, "The abilityInfo of context cannot be null."},
81 {ERR_GET_TOKEN_ERR, "The token of context cannot be null."},
82 {ERR_BGMODE_RANGE_ERR, "The value of bgMode ranges from BG_MODE_ID_BEGIN to BG_MODE_ID_END."},
83 {ERR_APP_NAME_EMPTY, "The app name of abilityInfo in context cannot be null."},
84 {ERR_RESOURCE_TYPES_INVALID, "The resourcesType cannot be null and must be integer greater than 0."},
85 {ERR_ISAPPLY_NULL_OR_TYPE_ERR, "The isApply cannot be null and its type must be boolean."},
86 {ERR_TIMEOUT_INVALID, "The timeOut cannot be null and must be integer greater than 0."},
87 {ERR_ISPERSIST_NULL_OR_TYPE_ERR, "The isPersist cannot be null and must be boolean."},
88 {ERR_ISPROCESS_NULL_OR_TYPE_ERR, "The isProcess cannot be null and must be boolean."},
89 {ERR_BGTASK_INVALID_PARAM, "The input param is invalid."}
90 };
91
AsyncWorkData(napi_env napiEnv)92 AsyncWorkData::AsyncWorkData(napi_env napiEnv)
93 {
94 env = napiEnv;
95 }
96
~AsyncWorkData()97 AsyncWorkData::~AsyncWorkData()
98 {
99 if (callback) {
100 BGTASK_LOGD("AsyncWorkData::~AsyncWorkData delete callback");
101 napi_delete_reference(env, callback);
102 callback = nullptr;
103 }
104 if (asyncWork) {
105 BGTASK_LOGD("AsyncWorkData::~AsyncWorkData delete asyncWork");
106 napi_delete_async_work(env, asyncWork);
107 asyncWork = nullptr;
108 }
109 }
110
NapiGetboolean(const napi_env & env,const bool isValue)111 napi_value Common::NapiGetboolean(const napi_env &env, const bool isValue)
112 {
113 napi_value result = nullptr;
114 NAPI_CALL(env, napi_get_boolean(env, isValue, &result));
115 return result;
116 }
117
NapiGetNull(napi_env env)118 napi_value Common::NapiGetNull(napi_env env)
119 {
120 napi_value result = nullptr;
121 napi_get_null(env, &result);
122 return result;
123 }
124
GetCallbackErrorValue(napi_env env,const int32_t errCode,const std::string errMsg)125 napi_value Common::GetCallbackErrorValue(napi_env env, const int32_t errCode, const std::string errMsg)
126 {
127 if (errCode == ERR_OK) {
128 return NapiGetNull(env);
129 }
130 napi_value error = nullptr;
131 napi_value eCode = nullptr;
132 napi_value eMsg = nullptr;
133 NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
134 NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
135 errMsg.length(), &eMsg));
136 NAPI_CALL(env, napi_create_object(env, &error));
137 NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
138 NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
139 return error;
140 }
141
GetExpireCallbackValue(napi_env env,int32_t errCode,const napi_value & value)142 napi_value Common::GetExpireCallbackValue(napi_env env, int32_t errCode, const napi_value &value)
143 {
144 napi_value result = nullptr;
145 napi_value eCode = nullptr;
146 NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
147 NAPI_CALL(env, napi_create_object(env, &result));
148 NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
149 NAPI_CALL(env, napi_set_named_property(env, result, "data", value));
150 return result;
151 }
152
SetCallback(const napi_env & env,const napi_ref & callbackIn,const napi_value & result)153 void Common::SetCallback(const napi_env &env, const napi_ref &callbackIn, const napi_value &result)
154 {
155 napi_value undefined = nullptr;
156 napi_get_undefined(env, &undefined);
157
158 napi_value callback = nullptr;
159 napi_value resultout = nullptr;
160 napi_value res = nullptr;
161 res = GetExpireCallbackValue(env, 0, result);
162 napi_get_reference_value(env, callbackIn, &callback);
163 NAPI_CALL_RETURN_VOID(env,
164 napi_call_function(env, undefined, callback, EXPIRE_CALLBACK_PARAM_NUM, &res, &resultout));
165 }
166
SetCallback(const napi_env & env,const napi_ref & callbackIn,const int32_t & errCode,const napi_value & result)167 void Common::SetCallback(
168 const napi_env &env, const napi_ref &callbackIn, const int32_t &errCode, const napi_value &result)
169 {
170 napi_value undefined = nullptr;
171 napi_get_undefined(env, &undefined);
172
173 napi_value callback = nullptr;
174 napi_value resultout = nullptr;
175 napi_get_reference_value(env, callbackIn, &callback);
176 napi_value results[ASYNC_CALLBACK_PARAM_NUM] = {nullptr};
177 if (errCode == ERR_OK) {
178 results[0] = NapiGetNull(env);
179 } else {
180 int32_t errCodeInfo = FindErrCode(env, errCode);
181 std::string errMsg = FindErrMsg(env, errCode);
182 results[0] = GetCallbackErrorValue(env, errCodeInfo, errMsg);
183 }
184 results[1] = result;
185 NAPI_CALL_RETURN_VOID(env,
186 napi_call_function(env, undefined, callback, ASYNC_CALLBACK_PARAM_NUM, &results[0], &resultout));
187 }
188
SetPromise(const napi_env & env,const AsyncWorkData & info,const napi_value & result)189 napi_value Common::SetPromise(
190 const napi_env &env, const AsyncWorkData &info, const napi_value &result)
191 {
192 if (info.errCode == ERR_OK) {
193 napi_resolve_deferred(env, info.deferred, result);
194 } else {
195 int32_t errCodeInfo = FindErrCode(env, info.errCode);
196 std::string errMsg = FindErrMsg(env, info.errCode);
197 napi_value error = nullptr;
198 napi_value eCode = nullptr;
199 napi_value eMsg = nullptr;
200 NAPI_CALL(env, napi_create_int32(env, errCodeInfo, &eCode));
201 NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
202 errMsg.length(), &eMsg));
203 NAPI_CALL(env, napi_create_object(env, &error));
204 NAPI_CALL(env, napi_set_named_property(env, error, "data", eCode));
205 NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
206 NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
207 napi_reject_deferred(env, info.deferred, error);
208 }
209 return result;
210 }
211
ReturnCallbackPromise(const napi_env & env,const AsyncWorkData & info,const napi_value & result)212 void Common::ReturnCallbackPromise(const napi_env &env, const AsyncWorkData &info, const napi_value &result)
213 {
214 if (info.isCallback) {
215 SetCallback(env, info.callback, info.errCode, result);
216 } else {
217 SetPromise(env, info, result);
218 }
219 }
220
JSParaError(const napi_env & env,const napi_ref & callback)221 napi_value Common::JSParaError(const napi_env &env, const napi_ref &callback)
222 {
223 if (callback) {
224 SetCallback(env, callback, ERR_BGTASK_INVALID_PARAM, nullptr);
225 return Common::NapiGetNull(env);
226 } else {
227 napi_value promise = nullptr;
228 napi_deferred deferred = nullptr;
229 napi_create_promise(env, &deferred, &promise);
230
231 napi_value res = nullptr;
232 napi_value eCode = nullptr;
233 napi_value eMsg = nullptr;
234 std::string errMsg = FindErrMsg(env, ERR_BGTASK_INVALID_PARAM);
235 NAPI_CALL(env, napi_create_int32(env, ERR_BGTASK_INVALID_PARAM, &eCode));
236 NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
237 errMsg.length(), &eMsg));
238 NAPI_CALL(env, napi_create_object(env, &res));
239 NAPI_CALL(env, napi_set_named_property(env, res, "data", eCode));
240 NAPI_CALL(env, napi_set_named_property(env, res, "code", eCode));
241 NAPI_CALL(env, napi_set_named_property(env, res, "message", eMsg));
242 napi_reject_deferred(env, deferred, res);
243 return promise;
244 }
245 }
246
GetU16StringValue(const napi_env & env,const napi_value & value,std::u16string & result)247 napi_value Common::GetU16StringValue(const napi_env &env, const napi_value &value, std::u16string &result)
248 {
249 napi_valuetype valuetype = napi_undefined;
250
251 NAPI_CALL(env, napi_typeof(env, value, &valuetype));
252 if (valuetype == napi_string) {
253 char str[STR_MAX_SIZE] = {0};
254 size_t strLen = 0;
255 NAPI_CALL(env, napi_get_value_string_utf8(env, value, str, STR_MAX_SIZE - 1, &strLen));
256
257 result = Str8ToStr16((std::string)str);
258 BGTASK_LOGD("GetU16StringValue result: %{public}s", Str16ToStr8(result).c_str());
259 } else {
260 BGTASK_LOGE("valuetype is not stringU16");
261 return nullptr;
262 }
263
264 return Common::NapiGetNull(env);
265 }
266
GetInt32NumberValue(const napi_env & env,const napi_value & value,int32_t & result)267 napi_value Common::GetInt32NumberValue(const napi_env &env, const napi_value &value, int32_t &result)
268 {
269 napi_valuetype valuetype = napi_undefined;
270 BGTASK_NAPI_CALL(env, napi_typeof(env, value, &valuetype));
271 if (valuetype != napi_number) {
272 BGTASK_LOGE("valuetype is not number");
273 return nullptr;
274 }
275 BGTASK_NAPI_CALL(env, napi_get_value_int32(env, value, &result));
276 BGTASK_LOGD("GetInt32NumberValue result: %{public}d", result);
277 return Common::NapiGetNull(env);
278 }
279
PaddingAsyncWorkData(const napi_env & env,const napi_ref & callback,AsyncWorkData & info,napi_value & promise)280 void Common::PaddingAsyncWorkData(
281 const napi_env &env, const napi_ref &callback, AsyncWorkData &info, napi_value &promise)
282 {
283 if (callback) {
284 info.callback = callback;
285 info.isCallback = true;
286 } else {
287 napi_deferred deferred = nullptr;
288 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
289 info.deferred = deferred;
290 info.isCallback = false;
291 }
292 }
293
SetDelaySuspendInfo(const napi_env & env,std::shared_ptr<DelaySuspendInfo> & delaySuspendInfo,napi_value & result)294 napi_value Common::SetDelaySuspendInfo(
295 const napi_env &env, std::shared_ptr<DelaySuspendInfo>& delaySuspendInfo, napi_value &result)
296 {
297 if (delaySuspendInfo == nullptr) {
298 BGTASK_LOGI("delaySuspendInfo is nullptr");
299 return NapiGetboolean(env, false);
300 }
301 napi_value value = nullptr;
302
303 // readonly requestId?: number
304 napi_create_int32(env, delaySuspendInfo->GetRequestId(), &value);
305 napi_set_named_property(env, result, "requestId", value);
306
307 // readonly actualDelayTime?: number
308 napi_create_int32(env, delaySuspendInfo->GetActualDelayTime(), &value);
309 napi_set_named_property(env, result, "actualDelayTime", value);
310
311 return NapiGetboolean(env, true);
312 }
313
GetStringValue(const napi_env & env,const napi_value & value,std::string & result)314 napi_value Common::GetStringValue(const napi_env &env, const napi_value &value, std::string &result)
315 {
316 napi_valuetype valuetype = napi_undefined;
317 BGTASK_NAPI_CALL(env, napi_typeof(env, value, &valuetype));
318 if (valuetype != napi_string) {
319 BGTASK_LOGE("valuetype is not string");
320 return nullptr;
321 }
322
323 char str[STR_MAX_SIZE] = {0};
324 size_t strLen = 0;
325 napi_status status = napi_get_value_string_utf8(env, value, str, STR_MAX_SIZE - 1, &strLen);
326 if (status != napi_ok) {
327 BGTASK_LOGE("get value string utf8 failed");
328 return nullptr;
329 }
330 result = std::string(str);
331 BGTASK_LOGD("GetStringValue result: %{public}s", result.c_str());
332 return Common::NapiGetNull(env);
333 }
334
HandleErrCode(const napi_env & env,int32_t errCode,bool isThrow)335 void Common::HandleErrCode(const napi_env &env, int32_t errCode, bool isThrow)
336 {
337 BGTASK_LOGD("HandleErrCode errCode = %{public}d, isThrow = %{public}d", errCode, isThrow);
338 if (!isThrow || errCode == ERR_OK) {
339 return;
340 }
341 std::string errMsg = FindErrMsg(env, errCode);
342 int32_t errCodeInfo = FindErrCode(env, errCode);
343 if (errMsg != "") {
344 napi_throw_error(env, std::to_string(errCodeInfo).c_str(), errMsg.c_str());
345 }
346 }
347
HandleParamErr(const napi_env & env,int32_t errCode,bool isThrow)348 bool Common::HandleParamErr(const napi_env &env, int32_t errCode, bool isThrow)
349 {
350 BGTASK_LOGD("HandleParamErr errCode = %{public}d, isThrow = %{public}d", errCode, isThrow);
351 if (!isThrow || errCode == ERR_OK) {
352 return false;
353 }
354 auto iter = PARAM_ERRCODE_MSG_MAP.find(errCode);
355 if (iter != PARAM_ERRCODE_MSG_MAP.end()) {
356 std::string errMessage = "BussinessError 401: Parameter error. ";
357 errMessage.append(iter->second);
358 napi_throw_error(env, std::to_string(ERR_BGTASK_INVALID_PARAM).c_str(), errMessage.c_str());
359 return true;
360 }
361 return false;
362 }
363
FindErrMsg(const napi_env & env,const int32_t errCode)364 std::string Common::FindErrMsg(const napi_env &env, const int32_t errCode)
365 {
366 if (errCode == ERR_OK) {
367 return "";
368 }
369 auto iter = SA_ERRCODE_MSG_MAP.find(errCode);
370 if (iter != SA_ERRCODE_MSG_MAP.end()) {
371 std::string errMessage = "BussinessError ";
372 int32_t errCodeInfo = FindErrCode(env, errCode);
373 errMessage.append(std::to_string(errCodeInfo)).append(": ").append(iter->second);
374 return errMessage;
375 }
376 iter = PARAM_ERRCODE_MSG_MAP.find(errCode);
377 if (iter != PARAM_ERRCODE_MSG_MAP.end()) {
378 std::string errMessage = "BussinessError 401: Parameter error. ";
379 errMessage.append(iter->second);
380 return errMessage;
381 }
382 return "Inner error.";
383 }
384
FindErrCode(const napi_env & env,const int32_t errCodeIn)385 int32_t Common::FindErrCode(const napi_env &env, const int32_t errCodeIn)
386 {
387 auto iter = PARAM_ERRCODE_MSG_MAP.find(errCodeIn);
388 if (iter != PARAM_ERRCODE_MSG_MAP.end()) {
389 return ERR_BGTASK_INVALID_PARAM;
390 }
391 return errCodeIn > THRESHOLD ? errCodeIn / OFFSET : errCodeIn;
392 }
393
GetBooleanValue(const napi_env & env,const napi_value & value,bool & result)394 napi_value Common::GetBooleanValue(const napi_env &env, const napi_value &value, bool &result)
395 {
396 napi_valuetype valuetype = napi_undefined;
397 BGTASK_NAPI_CALL(env, napi_typeof(env, value, &valuetype));
398 if (valuetype != napi_boolean) {
399 BGTASK_LOGE("valuetype is not boolean");
400 return nullptr;
401 }
402 BGTASK_NAPI_CALL(env, napi_get_value_bool(env, value, &result));
403 BGTASK_LOGD("GetBooleanValue result: %{public}d", result);
404
405 return Common::NapiGetNull(env);
406 }
407 } // namespace BackgroundTaskMgr
408 } // namespace OHOS
409