1 /*
2 * Copyright (c) 2021 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 <uv.h>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 #include "timer_type.h"
21 #include "want_agent_helper.h"
22 #include "securec.h"
23 #include "system_timer.h"
24
25 namespace OHOS {
26 namespace MiscServicesNapi {
27 namespace {
28 const int NO_ERROR = 0;
29 const int ERROR = -1;
30 const int CREATE_MAX_PARA = 2;
31 const int START_MAX_PARA = 3;
32 const int STOP_MAX_PARA = 2;
33 const int DESTROY_MAX_PARA = 2;
34 const int ARGS_TWO = 2;
35 const int PARAM0 = 0;
36 const int PARAM1 = 1;
37 }
38
39 struct CallbackPromiseInfo {
40 napi_ref callback = nullptr;
41 napi_deferred deferred = nullptr;
42 bool isCallback = false;
43 int errorCode = 0;
44 };
45
46 struct ReceiveDataWorker {
47 napi_env env = nullptr;
48 napi_ref ref = 0;
49 };
50
51 struct AsyncCallbackInfoCreate {
~AsyncCallbackInfoCreateOHOS::MiscServicesNapi::AsyncCallbackInfoCreate52 ~AsyncCallbackInfoCreate()
53 {
54 if (callback != nullptr) {
55 napi_delete_reference(env, callback);
56 }
57 }
58 napi_env env = nullptr;
59 napi_async_work asyncWork = nullptr;
60 napi_ref callback = nullptr;
61 napi_deferred deferred = nullptr;
62 std::shared_ptr<ITimerInfoInstance> iTimerInfoInstance = nullptr;
63 uint64_t timerId = 0;
64 bool isCallback = false;
65 int errorCode = NO_ERROR;
66 };
67
68 struct AsyncCallbackInfoStart {
~AsyncCallbackInfoStartOHOS::MiscServicesNapi::AsyncCallbackInfoStart69 ~AsyncCallbackInfoStart()
70 {
71 if (callback != nullptr) {
72 napi_delete_reference(env, callback);
73 }
74 }
75 napi_env env = nullptr;
76 napi_async_work asyncWork = nullptr;
77 napi_ref callback = nullptr;
78 napi_deferred deferred = nullptr;
79 uint64_t timerId = 0;
80 uint64_t triggerTime = 0;
81 bool isOK = false;
82 bool isCallback = false;
83 int errorCode = NO_ERROR;
84 };
85
86 struct AsyncCallbackInfoStop {
~AsyncCallbackInfoStopOHOS::MiscServicesNapi::AsyncCallbackInfoStop87 ~AsyncCallbackInfoStop()
88 {
89 if (callback != nullptr) {
90 napi_delete_reference(env, callback);
91 }
92 }
93 napi_env env = nullptr;
94 napi_async_work asyncWork = nullptr;
95 napi_ref callback = nullptr;
96 napi_deferred deferred = nullptr;
97 uint64_t timerId = 0;
98 bool isOK = false;
99 bool isCallback = false;
100 int errorCode = NO_ERROR;
101 };
102
103 struct AsyncCallbackInfoDestroy {
~AsyncCallbackInfoDestroyOHOS::MiscServicesNapi::AsyncCallbackInfoDestroy104 ~AsyncCallbackInfoDestroy()
105 {
106 if (callback != nullptr) {
107 napi_delete_reference(env, callback);
108 }
109 }
110 napi_env env = nullptr;
111 napi_async_work asyncWork = nullptr;
112 napi_ref callback = nullptr;
113 napi_deferred deferred = nullptr;
114 uint64_t timerId = 0;
115 bool isOK = false;
116 bool isCallback = false;
117 int errorCode = NO_ERROR;
118 };
119
120 static std::vector<AsyncCallbackInfoCreate *> asyncCallbackInfoCreateInfo;
121
NapiGetNull(napi_env env)122 napi_value NapiGetNull(napi_env env)
123 {
124 napi_value result = nullptr;
125 napi_get_null(env, &result);
126 return result;
127 }
128
GetCallbackErrorValue(napi_env env,int errCode)129 napi_value GetCallbackErrorValue(napi_env env, int errCode)
130 {
131 napi_value result = nullptr;
132 napi_value eCode = nullptr;
133 NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
134 NAPI_CALL(env, napi_create_object(env, &result));
135 NAPI_CALL(env, napi_set_named_property(env, result, "code", eCode));
136 return result;
137 }
138
SetPromise(const napi_env & env,const napi_deferred & deferred,const int & errorCode,const napi_value & result)139 void SetPromise(const napi_env &env, const napi_deferred &deferred, const int &errorCode, const napi_value &result)
140 {
141 if (errorCode == NO_ERROR) {
142 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
143 return;
144 }
145 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, result));
146 }
147
SetCallback(const napi_env & env,const napi_ref & callbackIn,const int & errorCode,const napi_value & result)148 void SetCallback(const napi_env &env, const napi_ref &callbackIn, const int &errorCode, const napi_value &result)
149 {
150 napi_value undefined = nullptr;
151 napi_get_undefined(env, &undefined);
152
153 napi_value callback = nullptr;
154 napi_value resultout = nullptr;
155 napi_get_reference_value(env, callbackIn, &callback);
156 napi_value results[ARGS_TWO] = {0};
157 results[PARAM0] = GetCallbackErrorValue(env, errorCode);
158 results[PARAM1] = result;
159 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, undefined, callback, ARGS_TWO, &results[PARAM0], &resultout));
160 }
161
JSParaError(const napi_env & env,const napi_ref & callback)162 napi_value JSParaError(const napi_env &env, const napi_ref &callback)
163 {
164 if (callback) {
165 return NapiGetNull(env);
166 } else {
167 napi_value promise = nullptr;
168 napi_deferred deferred = nullptr;
169 napi_create_promise(env, &deferred, &promise);
170 SetPromise(env, deferred, ERROR, NapiGetNull(env));
171 return promise;
172 }
173 }
174
ReturnCallbackPromise(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result)175 void ReturnCallbackPromise(const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result)
176 {
177 if (info.isCallback) {
178 SetCallback(env, info.callback, info.errorCode, result);
179 } else {
180 SetPromise(env, info.deferred, info.errorCode, result);
181 }
182 }
183
ITimerInfoInstance()184 ITimerInfoInstance::ITimerInfoInstance()
185 : callbackInfo_ {}
186 {}
187
~ITimerInfoInstance()188 ITimerInfoInstance::~ITimerInfoInstance()
189 {}
190
OnTrigger()191 void ITimerInfoInstance::OnTrigger()
192 {
193 if (callbackInfo_.ref == nullptr) {
194 return;
195 }
196
197 uv_loop_s *loop = nullptr;
198 #if NAPI_VERSION >= 2
199 napi_get_uv_event_loop(callbackInfo_.env, &loop);
200 #endif // NAPI_VERSION >= 2
201
202 ReceiveDataWorker *dataWorker = new (std::nothrow) ReceiveDataWorker();
203 if (!dataWorker) {
204 return;
205 }
206 dataWorker->env = callbackInfo_.env;
207 dataWorker->ref = callbackInfo_.ref;
208
209 uv_work_t *work = new (std::nothrow) uv_work_t;
210 if (!work) {
211 delete dataWorker;
212 return;
213 }
214 if (!loop) {
215 delete dataWorker;
216 delete work;
217 return;
218 }
219 work->data = (void *)dataWorker;
220 uv_queue_work(loop,
221 work,
222 [](uv_work_t *work) {},
223 [](uv_work_t *work, int status) {
224 ReceiveDataWorker *dataWorkerData = (ReceiveDataWorker *)work->data;
225 if (dataWorkerData == nullptr) {
226 return;
227 }
228 napi_handle_scope scope = nullptr;
229 napi_open_handle_scope(dataWorkerData->env, &scope);
230 if (scope == nullptr) {
231 return;
232 }
233 SetCallback(dataWorkerData->env,
234 dataWorkerData->ref,
235 NO_ERROR,
236 NapiGetNull(dataWorkerData->env));
237 napi_close_handle_scope(dataWorkerData->env, scope);
238 delete dataWorkerData;
239 dataWorkerData = nullptr;
240 delete work;
241 work = nullptr;
242 });
243 }
244
SetCallbackInfo(const napi_env & env,const napi_ref & ref)245 void ITimerInfoInstance::SetCallbackInfo(const napi_env &env, const napi_ref &ref)
246 {
247 callbackInfo_.env = env;
248 callbackInfo_.ref = ref;
249 }
250
SetType(const int & _type)251 void ITimerInfoInstance::SetType(const int &_type)
252 {
253 type = _type;
254 }
255
SetRepeat(bool _repeat)256 void ITimerInfoInstance::SetRepeat(bool _repeat)
257 {
258 repeat = _repeat;
259 }
SetInterval(const uint64_t & _interval)260 void ITimerInfoInstance::SetInterval(const uint64_t &_interval)
261 {
262 interval = _interval;
263 }
SetWantAgent(std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> _wantAgent)264 void ITimerInfoInstance::SetWantAgent(std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> _wantAgent)
265 {
266 wantAgent = _wantAgent;
267 }
268
GetTimerOptions(const napi_env & env,const napi_value & value,std::shared_ptr<ITimerInfoInstance> & iTimerInfoInstance)269 napi_value GetTimerOptions(const napi_env &env, const napi_value &value,
270 std::shared_ptr<ITimerInfoInstance> &iTimerInfoInstance)
271 {
272 napi_valuetype valuetype = napi_undefined;
273 napi_value result = nullptr;
274 OHOS::AbilityRuntime::WantAgent::WantAgent *wantAgent = nullptr;
275 bool hasProperty = false;
276
277 // type: number
278 int type = 0;
279 NAPI_CALL(env, napi_has_named_property(env, value, "type", &hasProperty));
280 NAPI_ASSERT(env, hasProperty, "type expected.");
281 napi_get_named_property(env, value, "type", &result);
282 NAPI_CALL(env, napi_typeof(env, result, &valuetype));
283 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
284 napi_get_value_int32(env, result, &type);
285 iTimerInfoInstance->SetType(type);
286
287 // repeat: boolean
288 bool repeat = false;
289 NAPI_CALL(env, napi_has_named_property(env, value, "repeat", &hasProperty));
290 NAPI_ASSERT(env, hasProperty, "repeat expected.");
291 napi_get_named_property(env, value, "repeat", &result);
292 NAPI_CALL(env, napi_typeof(env, result, &valuetype));
293 NAPI_ASSERT(env, valuetype == napi_boolean, "Wrong argument type. Bool expected.");
294 napi_get_value_bool(env, result, &repeat);
295 iTimerInfoInstance->SetRepeat(repeat);
296
297 // interval?: number
298 int64_t interval = 0;
299 NAPI_CALL(env, napi_has_named_property(env, value, "interval", &hasProperty));
300 if (hasProperty) {
301 napi_get_named_property(env, value, "interval", &result);
302 NAPI_CALL(env, napi_typeof(env, result, &valuetype));
303 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
304 napi_get_value_int64(env, result, &interval);
305 NAPI_ASSERT(env, interval >= 0, "Wrong argument number. Positive number expected.");
306 iTimerInfoInstance->SetInterval((uint64_t)interval);
307 }
308
309 // wantAgent?: WantAgent
310 NAPI_CALL(env, napi_has_named_property(env, value, "wantAgent", &hasProperty));
311 if (hasProperty) {
312 napi_get_named_property(env, value, "wantAgent", &result);
313 NAPI_CALL(env, napi_typeof(env, result, &valuetype));
314 NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type. Object expected.");
315 napi_unwrap(env, result, (void **)&wantAgent);
316 if (wantAgent == nullptr) {
317 return nullptr;
318 }
319 std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> sWantAgent =
320 std::make_shared<OHOS::AbilityRuntime::WantAgent::WantAgent>(*wantAgent);
321 iTimerInfoInstance->SetWantAgent(sWantAgent);
322 }
323
324 // callback?: () => void
325 NAPI_CALL(env, napi_has_named_property(env, value, "callback", &hasProperty));
326 if (hasProperty) {
327 napi_get_named_property(env, value, "callback", &result);
328 NAPI_CALL(env, napi_typeof(env, result, &valuetype));
329 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
330 napi_ref onTriggerCallback;
331 napi_create_reference(env, result, 1, &onTriggerCallback);
332 iTimerInfoInstance->SetCallbackInfo(env, onTriggerCallback);
333 }
334 return NapiGetNull(env);
335 }
336
ParseParametersByCreateTimer(const napi_env & env,const napi_value (& argv)[CREATE_MAX_PARA],const size_t & argc,std::shared_ptr<ITimerInfoInstance> & iTimerInfoInstance,napi_ref & callback)337 napi_value ParseParametersByCreateTimer(const napi_env &env, const napi_value (&argv)[CREATE_MAX_PARA],
338 const size_t &argc, std::shared_ptr<ITimerInfoInstance> &iTimerInfoInstance, napi_ref &callback)
339 {
340 NAPI_ASSERT(env, argc >= CREATE_MAX_PARA - 1, "Wrong number of arguments");
341 napi_valuetype valuetype = napi_undefined;
342
343 // argv[0]: TimerOptions
344 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
345 NAPI_ASSERT(env, valuetype == napi_object, "Wrong argument type. Object expected.");
346 if (GetTimerOptions(env, argv[0], iTimerInfoInstance) == nullptr) {
347 return nullptr;
348 }
349
350 // argv[1]:callback
351 if (argc >= CREATE_MAX_PARA) {
352 NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
353 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
354 napi_create_reference(env, argv[1], 1, &callback);
355 }
356
357 return NapiGetNull(env);
358 }
359
PaddingAsyncCallbackInfoIsByCreateTimer(const napi_env & env,AsyncCallbackInfoCreate * & asynccallbackinfo,const napi_ref & callback,napi_value & promise)360 void PaddingAsyncCallbackInfoIsByCreateTimer(
361 const napi_env &env, AsyncCallbackInfoCreate *&asynccallbackinfo, const napi_ref &callback, napi_value &promise)
362 {
363 if (callback) {
364 asynccallbackinfo->callback = callback;
365 asynccallbackinfo->isCallback = true;
366 } else {
367 napi_deferred deferred = nullptr;
368 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
369 asynccallbackinfo->deferred = deferred;
370 asynccallbackinfo->isCallback = false;
371 }
372 }
373
CreateTimer(napi_env env,napi_callback_info info)374 napi_value CreateTimer(napi_env env, napi_callback_info info)
375 {
376 size_t argc = CREATE_MAX_PARA;
377 napi_value argv[CREATE_MAX_PARA] = {0};
378 napi_value thisVar = nullptr;
379 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
380 std::shared_ptr<ITimerInfoInstance> iTimerInfoInstance = std::make_shared<ITimerInfoInstance>();
381 napi_ref callback = nullptr;
382 if (ParseParametersByCreateTimer(env, argv, argc, iTimerInfoInstance, callback) == nullptr) {
383 return JSParaError(env, callback);
384 }
385 AsyncCallbackInfoCreate *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoCreate {
386 .env = env,
387 .asyncWork = nullptr,
388 .iTimerInfoInstance = iTimerInfoInstance
389 };
390 if (!asynccallbackinfo) {
391 return JSParaError(env, callback);
392 }
393 napi_value promise = nullptr;
394 PaddingAsyncCallbackInfoIsByCreateTimer(env, asynccallbackinfo, callback, promise);
395 napi_value resourceName = nullptr;
396 napi_create_string_latin1(env, "createTimer", NAPI_AUTO_LENGTH, &resourceName);
397 napi_create_async_work(env,
398 nullptr,
399 resourceName,
400 [](napi_env env, void *data) {
401 AsyncCallbackInfoCreate *asynccallbackinfo = (AsyncCallbackInfoCreate *)data;
402 asynccallbackinfo->timerId =
403 TimeServiceClient::GetInstance()->CreateTimer(asynccallbackinfo->iTimerInfoInstance);
404 if (asynccallbackinfo->timerId > 0) {
405 asyncCallbackInfoCreateInfo.emplace_back(asynccallbackinfo);
406 }
407 },
408 [](napi_env env, napi_status status, void *data) {
409 AsyncCallbackInfoCreate *asynccallbackinfo = (AsyncCallbackInfoCreate *)data;
410 CallbackPromiseInfo info;
411 info.isCallback = asynccallbackinfo->isCallback;
412 info.callback = asynccallbackinfo->callback;
413 info.deferred = asynccallbackinfo->deferred;
414 info.errorCode = asynccallbackinfo->errorCode;
415 napi_value result = nullptr;
416 napi_create_int64(env, asynccallbackinfo->timerId, &result);
417 ReturnCallbackPromise(env, info, result);
418 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
419 if (asynccallbackinfo) {
420 delete asynccallbackinfo;
421 asynccallbackinfo = nullptr;
422 }
423 },
424 (void *)asynccallbackinfo,
425 &asynccallbackinfo->asyncWork);
426 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
427 if (asynccallbackinfo->isCallback) {
428 return NapiGetNull(env);
429 } else {
430 return promise;
431 }
432 }
433
ParseParametersByStartTimer(const napi_env & env,const napi_value (& argv)[START_MAX_PARA],const size_t & argc,uint64_t & uintTimerId,uint64_t & uintTriggerTime,napi_ref & callback)434 napi_value ParseParametersByStartTimer(const napi_env &env, const napi_value (&argv)[START_MAX_PARA],
435 const size_t &argc, uint64_t &uintTimerId, uint64_t &uintTriggerTime, napi_ref &callback)
436 {
437 NAPI_ASSERT(env, argc >= START_MAX_PARA - 1, "Wrong number of arguments");
438 napi_valuetype valuetype = napi_undefined;
439
440 // argv[0]: timer
441 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
442 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
443 int64_t timerId = 0;
444 napi_get_value_int64(env, argv[0], &timerId);
445 NAPI_ASSERT(env, timerId >= 0, "Wrong argument timer. Positive number expected.");
446 uintTimerId = static_cast<uint64_t>(timerId);
447
448 // argv[1]: triggerTime
449 NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
450 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
451 int64_t triggerTime = 0;
452 napi_get_value_int64(env, argv[1], &triggerTime);
453 NAPI_ASSERT(env, triggerTime >= 0, "Wrong argument triggerTime. Positive number expected.");
454 uintTriggerTime = static_cast<uint64_t>(triggerTime);
455
456 // argv[2]:callback
457 if (argc >= START_MAX_PARA) {
458 NAPI_CALL(env, napi_typeof(env, argv[TWO_PARAMETERS], &valuetype));
459 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
460 napi_create_reference(env, argv[TWO_PARAMETERS], 1, &callback);
461 }
462
463 return NapiGetNull(env);
464 }
465
PaddingAsyncCallbackInfoIsByStartTimer(const napi_env & env,AsyncCallbackInfoStart * & asynccallbackinfo,const napi_ref & callback,napi_value & promise)466 void PaddingAsyncCallbackInfoIsByStartTimer(const napi_env &env,
467 AsyncCallbackInfoStart *&asynccallbackinfo,
468 const napi_ref &callback,
469 napi_value &promise)
470 {
471 if (callback) {
472 asynccallbackinfo->callback = callback;
473 asynccallbackinfo->isCallback = true;
474 } else {
475 napi_deferred deferred = nullptr;
476 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
477 asynccallbackinfo->deferred = deferred;
478 asynccallbackinfo->isCallback = false;
479 }
480 }
481
StartTimer(napi_env env,napi_callback_info info)482 napi_value StartTimer(napi_env env, napi_callback_info info)
483 {
484 size_t argc = START_MAX_PARA;
485 napi_value argv[START_MAX_PARA] = {0};
486 napi_value thisVar = nullptr;
487 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
488
489 uint64_t timerId;
490 uint64_t triggerTime;
491 napi_ref callback = nullptr;
492 if (ParseParametersByStartTimer(env, argv, argc, timerId, triggerTime, callback) == nullptr) {
493 return JSParaError(env, callback);
494 }
495
496 AsyncCallbackInfoStart *asynccallbackinfo = new (std::nothrow)AsyncCallbackInfoStart {
497 .env = env,
498 .asyncWork = nullptr,
499 .timerId = timerId,
500 .triggerTime = triggerTime
501 };
502 if (!asynccallbackinfo) {
503 return JSParaError(env, callback);
504 }
505
506 napi_value promise = nullptr;
507 PaddingAsyncCallbackInfoIsByStartTimer(env, asynccallbackinfo, callback, promise);
508
509 napi_value resourceName = nullptr;
510 napi_create_string_latin1(env, "startTimer", NAPI_AUTO_LENGTH, &resourceName);
511 // Asynchronous function call
512 napi_create_async_work(env,
513 nullptr,
514 resourceName,
515 [](napi_env env, void *data) {
516 AsyncCallbackInfoStart *asynccallbackinfo = (AsyncCallbackInfoStart *)data;
517
518 asynccallbackinfo->isOK = TimeServiceClient::GetInstance()->StartTimer(
519 asynccallbackinfo->timerId, asynccallbackinfo->triggerTime);
520 },
521 [](napi_env env, napi_status status, void *data) {
522 AsyncCallbackInfoStart *asynccallbackinfo = (AsyncCallbackInfoStart *)data;
523
524 if (!asynccallbackinfo->isOK) {
525 asynccallbackinfo->errorCode = ERROR;
526 }
527 CallbackPromiseInfo info;
528 info.isCallback = asynccallbackinfo->isCallback;
529 info.callback = asynccallbackinfo->callback;
530 info.deferred = asynccallbackinfo->deferred;
531 info.errorCode = asynccallbackinfo->errorCode;
532
533 // result: void
534 napi_value result = 0;
535 napi_get_null(env, &result);
536 ReturnCallbackPromise(env, info, result);
537
538 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
539 if (asynccallbackinfo) {
540 delete asynccallbackinfo;
541 asynccallbackinfo = nullptr;
542 }
543 },
544 (void *)asynccallbackinfo,
545 &asynccallbackinfo->asyncWork);
546
547 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
548
549 if (asynccallbackinfo->isCallback) {
550 return NapiGetNull(env);
551 } else {
552 return promise;
553 }
554 }
555
ParseParametersByStopTimer(const napi_env & env,const napi_value (& argv)[STOP_MAX_PARA],const size_t & argc,uint64_t & uintTimerId,napi_ref & callback)556 napi_value ParseParametersByStopTimer(const napi_env &env, const napi_value (&argv)[STOP_MAX_PARA], const size_t &argc,
557 uint64_t &uintTimerId, napi_ref &callback)
558 {
559 NAPI_ASSERT(env, argc >= STOP_MAX_PARA - 1, "Wrong number of arguments");
560 napi_valuetype valuetype = napi_undefined;
561
562 // argv[0]: timer
563 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
564 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
565 int64_t timerId = 0;
566 napi_get_value_int64(env, argv[0], &timerId);
567 NAPI_ASSERT(env, timerId >= 0, "Wrong argument timer. Positive number expected.");
568 uintTimerId = static_cast<uint64_t>(timerId);
569
570 // argv[1]:callback
571 if (argc >= STOP_MAX_PARA) {
572 NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
573 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
574 napi_create_reference(env, argv[1], 1, &callback);
575 }
576
577 return NapiGetNull(env);
578 }
579
PaddingAsyncCallbackInfoIsByStopTimer(const napi_env & env,AsyncCallbackInfoStop * & asynccallbackinfo,const napi_ref & callback,napi_value & promise)580 void PaddingAsyncCallbackInfoIsByStopTimer(const napi_env &env,
581 AsyncCallbackInfoStop *&asynccallbackinfo,
582 const napi_ref &callback,
583 napi_value &promise)
584 {
585 if (callback) {
586 asynccallbackinfo->callback = callback;
587 asynccallbackinfo->isCallback = true;
588 } else {
589 napi_deferred deferred = nullptr;
590 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
591 asynccallbackinfo->deferred = deferred;
592 asynccallbackinfo->isCallback = false;
593 }
594 }
595
StopTimer(napi_env env,napi_callback_info info)596 napi_value StopTimer(napi_env env, napi_callback_info info)
597 {
598 size_t argc = STOP_MAX_PARA;
599 napi_value argv[STOP_MAX_PARA] = {0};
600 napi_value thisVar = nullptr;
601 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
602
603 uint64_t timerId;
604 napi_ref callback = nullptr;
605 if (ParseParametersByStopTimer(env, argv, argc, timerId, callback) == nullptr) {
606 return JSParaError(env, callback);
607 }
608
609 AsyncCallbackInfoStop *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoStop {
610 .env = env,
611 .asyncWork = nullptr,
612 .timerId = timerId
613 };
614 if (!asynccallbackinfo) {
615 return JSParaError(env, callback);
616 }
617
618 napi_value promise = nullptr;
619 PaddingAsyncCallbackInfoIsByStopTimer(env, asynccallbackinfo, callback, promise);
620
621 napi_value resourceName = nullptr;
622 napi_create_string_latin1(env, "stopTimer", NAPI_AUTO_LENGTH, &resourceName);
623 // Asynchronous function call
624 napi_create_async_work(env,
625 nullptr,
626 resourceName,
627 [](napi_env env, void *data) {
628 AsyncCallbackInfoStop *asynccallbackinfo = (AsyncCallbackInfoStop *)data;
629 asynccallbackinfo->isOK = TimeServiceClient::GetInstance()->StopTimer(asynccallbackinfo->timerId);
630 },
631 [](napi_env env, napi_status status, void *data) {
632 AsyncCallbackInfoStop *asynccallbackinfo = (AsyncCallbackInfoStop *)data;
633
634 if (!asynccallbackinfo->isOK) {
635 asynccallbackinfo->errorCode = ERROR;
636 }
637 CallbackPromiseInfo info;
638 info.isCallback = asynccallbackinfo->isCallback;
639 info.callback = asynccallbackinfo->callback;
640 info.deferred = asynccallbackinfo->deferred;
641 info.errorCode = asynccallbackinfo->errorCode;
642
643 // result: void
644 napi_value result = 0;
645 napi_get_null(env, &result);
646 ReturnCallbackPromise(env, info, result);
647
648 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
649 if (asynccallbackinfo) {
650 delete asynccallbackinfo;
651 asynccallbackinfo = nullptr;
652 }
653 },
654 (void *)asynccallbackinfo,
655 &asynccallbackinfo->asyncWork);
656
657 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
658
659 if (asynccallbackinfo->isCallback) {
660 return NapiGetNull(env);
661 } else {
662 return promise;
663 }
664 }
665
ParseParametersByDestroyTimer(const napi_env & env,const napi_value (& argv)[DESTROY_MAX_PARA],const size_t & argc,uint64_t & uintTimerId,napi_ref & callback)666 napi_value ParseParametersByDestroyTimer(const napi_env &env, const napi_value (&argv)[DESTROY_MAX_PARA],
667 const size_t &argc, uint64_t &uintTimerId, napi_ref &callback)
668 {
669 NAPI_ASSERT(env, argc >= DESTROY_MAX_PARA - 1, "Wrong number of arguments");
670 napi_valuetype valuetype = napi_undefined;
671
672 // argv[0]: timer
673 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
674 NAPI_ASSERT(env, valuetype == napi_number, "Wrong argument type. Number expected.");
675 int64_t timerId = 0;
676 napi_get_value_int64(env, argv[0], &timerId);
677 NAPI_ASSERT(env, timerId >= 0, "Wrong argument timer. Positive number expected.");
678 uintTimerId = (uint64_t)timerId;
679
680 // argv[1]:callback
681 if (argc >= DESTROY_MAX_PARA) {
682 NAPI_CALL(env, napi_typeof(env, argv[1], &valuetype));
683 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected.");
684 napi_create_reference(env, argv[1], 1, &callback);
685 }
686
687 return NapiGetNull(env);
688 }
689
PaddingAsyncCallbackInfoIsByDestroyTimer(const napi_env & env,AsyncCallbackInfoDestroy * & asynccallbackinfo,const napi_ref & callback,napi_value & promise)690 void PaddingAsyncCallbackInfoIsByDestroyTimer(
691 const napi_env &env, AsyncCallbackInfoDestroy *&asynccallbackinfo, const napi_ref &callback, napi_value &promise)
692 {
693 if (callback) {
694 asynccallbackinfo->callback = callback;
695 asynccallbackinfo->isCallback = true;
696 } else {
697 napi_deferred deferred = nullptr;
698 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
699 asynccallbackinfo->deferred = deferred;
700 asynccallbackinfo->isCallback = false;
701 }
702 }
703
DestroyTimer(napi_env env,napi_callback_info info)704 napi_value DestroyTimer(napi_env env, napi_callback_info info)
705 {
706 size_t argc = DESTROY_MAX_PARA;
707 napi_value argv[DESTROY_MAX_PARA] = {0};
708 napi_value thisVar = nullptr;
709 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
710
711 uint64_t timerId;
712 napi_ref callback = nullptr;
713 if (ParseParametersByDestroyTimer(env, argv, argc, timerId, callback) == nullptr) {
714 return JSParaError(env, callback);
715 }
716
717 AsyncCallbackInfoDestroy *asynccallbackinfo =
718 new (std::nothrow) AsyncCallbackInfoDestroy {.env = env, .asyncWork = nullptr, .timerId = timerId};
719 if (!asynccallbackinfo) {
720 return JSParaError(env, callback);
721 }
722
723 napi_value promise = nullptr;
724 PaddingAsyncCallbackInfoIsByDestroyTimer(env, asynccallbackinfo, callback, promise);
725
726 napi_value resourceName = nullptr;
727 napi_create_string_latin1(env, "destroyTimer", NAPI_AUTO_LENGTH, &resourceName);
728 // Asynchronous function call
729 napi_create_async_work(env,
730 nullptr,
731 resourceName,
732 [](napi_env env, void *data) {
733 AsyncCallbackInfoDestroy *asynccallbackinfo = (AsyncCallbackInfoDestroy *)data;
734 asynccallbackinfo->isOK = TimeServiceClient::GetInstance()->DestroyTimer(asynccallbackinfo->timerId);
735 },
736 [](napi_env env, napi_status status, void *data) {
737 AsyncCallbackInfoDestroy *asynccallbackinfo = (AsyncCallbackInfoDestroy *)data;
738
739 if (asynccallbackinfo->isOK) {
740 for (auto it = asyncCallbackInfoCreateInfo.begin(); it != asyncCallbackInfoCreateInfo.end(); it++) {
741 if ((*it)->timerId == asynccallbackinfo->timerId) {
742 it = asyncCallbackInfoCreateInfo.erase(it);
743 delete (*it);
744 *it = nullptr;
745 }
746 }
747 } else {
748 asynccallbackinfo->errorCode = ERROR;
749 }
750 CallbackPromiseInfo info;
751 info.isCallback = asynccallbackinfo->isCallback;
752 info.callback = asynccallbackinfo->callback;
753 info.deferred = asynccallbackinfo->deferred;
754 info.errorCode = asynccallbackinfo->errorCode;
755
756 // result: void
757 napi_value result = 0;
758 napi_get_null(env, &result);
759 ReturnCallbackPromise(env, info, result);
760
761 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
762 if (asynccallbackinfo) {
763 delete asynccallbackinfo;
764 asynccallbackinfo = nullptr;
765 }
766 },
767 (void *)asynccallbackinfo,
768 &asynccallbackinfo->asyncWork);
769
770 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
771
772 if (asynccallbackinfo->isCallback) {
773 return NapiGetNull(env);
774 } else {
775 return promise;
776 }
777 }
778
CreateNapiNumber(napi_env env,int32_t objName)779 napi_value CreateNapiNumber(napi_env env, int32_t objName)
780 {
781 napi_value prop = nullptr;
782 napi_create_int32(env, objName, &prop);
783 return prop;
784 }
785
SystemtimerInit(napi_env env,napi_value exports)786 napi_value SystemtimerInit(napi_env env, napi_value exports)
787 {
788 napi_property_descriptor desc[] = {
789 DECLARE_NAPI_FUNCTION("createTimer", CreateTimer),
790 DECLARE_NAPI_FUNCTION("startTimer", StartTimer),
791 DECLARE_NAPI_FUNCTION("stopTimer", StopTimer),
792 DECLARE_NAPI_FUNCTION("destroyTimer", DestroyTimer),
793 DECLARE_NAPI_PROPERTY("TIMER_TYPE_REALTIME", CreateNapiNumber(env, 1 << TIMER_TYPE_REALTIME)),
794 DECLARE_NAPI_PROPERTY("TIMER_TYPE_WAKEUP", CreateNapiNumber(env, 1 << TIMER_TYPE_WAKEUP)),
795 DECLARE_NAPI_PROPERTY("TIMER_TYPE_EXACT", CreateNapiNumber(env, 1 << TIMER_TYPE_EXACT)),
796 DECLARE_NAPI_PROPERTY("TIMER_TYPE_IDLE", CreateNapiNumber(env, 1 << TIMER_TYPE_IDLE)),
797 };
798
799 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
800 return exports;
801 }
802 } // namespace MiscServicesNapi
803 } // namespace OHOS