• 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 "request_suspend_delay.h"
17 
18 #include <uv.h>
19 
20 #include "singleton.h"
21 
22 #include "background_task_manager.h"
23 #include "transient_task_log.h"
24 
25 namespace OHOS {
26 namespace BackgroundTaskMgr {
27 static const int32_t REQUEST_SUSPEND_DELAY_PARAMS = 2;
28 
29 struct CallbackReceiveDataWorker {
30     napi_env env = nullptr;
31     napi_ref ref = nullptr;
32 };
33 
CallbackInstance()34 CallbackInstance::CallbackInstance() {}
35 
~CallbackInstance()36 CallbackInstance::~CallbackInstance()
37 {
38     if (expiredCallbackInfo_.ref != nullptr) {
39         napi_delete_reference(expiredCallbackInfo_.env, expiredCallbackInfo_.ref);
40     }
41 }
42 
UvQueueWorkOnExpired(uv_work_t * work,int status)43 void UvQueueWorkOnExpired(uv_work_t *work, int status)
44 {
45     BGTASK_LOGI("OnExpired uv_work_t start");
46 
47     if (work == nullptr) {
48         BGTASK_LOGE("work is null");
49         return;
50     }
51 
52     CallbackReceiveDataWorker *dataWorkerData = (CallbackReceiveDataWorker *)work->data;
53     if (dataWorkerData == nullptr) {
54         BGTASK_LOGE("dataWorkerData is null");
55         delete work;
56         work = nullptr;
57         return;
58     }
59 
60     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
61 
62     delete dataWorkerData;
63     dataWorkerData = nullptr;
64     delete work;
65     work = nullptr;
66 }
67 
OnExpired()68 void CallbackInstance::OnExpired()
69 {
70     BGTASK_LOGI("enter");
71 
72     if (expiredCallbackInfo_.ref == nullptr) {
73         BGTASK_LOGE("expired callback unset");
74         return;
75     }
76 
77     uv_loop_s *loop = nullptr;
78     napi_get_uv_event_loop(expiredCallbackInfo_.env, &loop);
79     if (loop == nullptr) {
80         BGTASK_LOGE("loop instance is nullptr");
81         return;
82     }
83 
84     CallbackReceiveDataWorker *dataWorker = new (std::nothrow) CallbackReceiveDataWorker();
85     if (dataWorker == nullptr) {
86         BGTASK_LOGE("new dataWorker failed");
87         return;
88     }
89 
90     dataWorker->env = expiredCallbackInfo_.env;
91     dataWorker->ref = expiredCallbackInfo_.ref;
92 
93     uv_work_t *work = new (std::nothrow) uv_work_t;
94     if (work == nullptr) {
95         BGTASK_LOGE("new work failed");
96         delete dataWorker;
97         dataWorker = nullptr;
98         return;
99     }
100 
101     work->data = (void *)dataWorker;
102 
103     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnExpired);
104     if (ret != 0) {
105         delete dataWorker;
106         dataWorker = nullptr;
107         delete work;
108         work = nullptr;
109     }
110 }
111 
SetCallbackInfo(const napi_env & env,const napi_ref & ref)112 void CallbackInstance::SetCallbackInfo(const napi_env &env, const napi_ref &ref)
113 {
114     expiredCallbackInfo_.env = env;
115     expiredCallbackInfo_.ref = ref;
116 }
117 
GetExpiredCallback(const napi_env & env,const napi_value & value,CallbackInstancesInfo & callbcakInfo)118 napi_value GetExpiredCallback(
119     const napi_env &env, const napi_value &value, CallbackInstancesInfo &callbcakInfo)
120 {
121     napi_ref result = nullptr;
122 
123     callbcakInfo.callback = new (std::nothrow) CallbackInstance();
124     if (callbcakInfo.callback == nullptr) {
125         BGTASK_LOGE("callback is null");
126         return nullptr;
127     }
128 
129     napi_create_reference(env, value, 1, &result);
130     callbcakInfo.callback->SetCallbackInfo(env, result);
131 
132     return Common::NapiGetNull(env);
133 }
134 
ParseParameters(const napi_env & env,const napi_callback_info & info,std::u16string & reason,CallbackInstance * & callback)135 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
136     std::u16string &reason, CallbackInstance *&callback)
137 {
138     size_t argc = REQUEST_SUSPEND_DELAY_PARAMS;
139     napi_value argv[REQUEST_SUSPEND_DELAY_PARAMS] = {nullptr};
140     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
141     NAPI_ASSERT(env, argc == REQUEST_SUSPEND_DELAY_PARAMS, "Wrong number of arguments");
142 
143     // argv[0] : reason
144     if (Common::GetU16StringValue(env, argv[0], reason) == nullptr) {
145         BGTASK_LOGE("ParseParameters failed, reason is nullptr ");
146         return nullptr;
147     }
148 
149     // arg[1] : callback
150     napi_valuetype valuetype = napi_undefined;
151     NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
152     NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Object expected.");
153 
154     CallbackInstancesInfo callbackInstancesInfo;
155     if (GetExpiredCallback(env, argv[1], callbackInstancesInfo) == nullptr) {
156         BGTASK_LOGE("CallbackInstancesInfo parse failed");
157         return nullptr;
158     }
159     callback = callbackInstancesInfo.callback;
160     return Common::NapiGetNull(env);
161 }
162 
RequestSuspendDelay(napi_env env,napi_callback_info info)163 napi_value RequestSuspendDelay(napi_env env, napi_callback_info info)
164 {
165     CallbackInstance *objectInfo = nullptr;
166     std::u16string reason;
167     if (ParseParameters(env, info, reason, objectInfo) == nullptr) {
168         if (objectInfo) {
169             delete objectInfo;
170             objectInfo = nullptr;
171         }
172         return Common::NapiGetNull(env);
173     }
174 
175     std::shared_ptr<DelaySuspendInfo> delaySuspendInfo;
176     DelayedSingleton<BackgroundTaskManager>::GetInstance()->
177         RequestSuspendDelay(reason, *objectInfo, delaySuspendInfo);
178 
179     napi_value result = nullptr;
180     napi_create_object(env, &result);
181     if (!Common::SetDelaySuspendInfo(env, delaySuspendInfo, result)) {
182         BGTASK_LOGW("Set DelaySuspendInfo object failed");
183     }
184     return result;
185 }
186 }  // namespace BackgroundTaskMgr
187 }  // namespace OHOS