• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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