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 #include <initializer_list>
16 #include <string>
17
18 #include "napi_utils.h"
19 #include "time_service_client.h"
20
21 namespace OHOS {
22 namespace MiscServicesNapi {
23 using namespace OHOS::MiscServices;
24 using namespace OHOS::MiscServices::Time;
25 typedef struct AsyncContext {
~AsyncContextOHOS::MiscServicesNapi::AsyncContext26 ~AsyncContext()
27 {
28 if (callbackRef != nullptr) {
29 napi_delete_reference(env, callbackRef);
30 }
31 }
32 napi_env env = nullptr;
33 napi_async_work work = nullptr;
34 int64_t time = INVALID_TIME;
35 std::string timeZone = "";
36 napi_deferred deferred = nullptr;
37 napi_ref callbackRef = nullptr;
38 bool isCallback = false;
39 bool isOK = false;
40 bool isNano = false;
41 int32_t errorCode = E_TIME_OK;
42 std::string message = "system error";
43 } AsyncContext;
44
TimePaddingAsyncCallbackInfo(const napi_env & env,AsyncContext * & asynccallbackinfo,const napi_ref & callback,napi_value & promise)45 void TimePaddingAsyncCallbackInfo(const napi_env &env, AsyncContext *&asynccallbackinfo, const napi_ref &callback,
46 napi_value &promise)
47 {
48 if (callback) {
49 asynccallbackinfo->callbackRef = callback;
50 asynccallbackinfo->isCallback = true;
51 } else {
52 napi_deferred deferred = nullptr;
53 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
54 asynccallbackinfo->deferred = deferred;
55 asynccallbackinfo->isCallback = false;
56 }
57 }
58
JSSystemTimeSetTime(napi_env env,napi_callback_info info)59 napi_value JSSystemTimeSetTime(napi_env env, napi_callback_info info)
60 {
61 size_t argc = SET_TIME_MAX_PARA;
62 napi_value argv[SET_TIME_MAX_PARA] = { 0 };
63 napi_value thisVar = nullptr;
64 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
65 int64_t times = INVALID_TIME;
66 napi_ref callback = nullptr;
67 if (NapiUtils::ParseParametersBySetTime(env, argv, argc, times, callback) == nullptr) {
68 return NapiUtils::JSParaError(env, callback);
69 }
70 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env, .time = times };
71 if (!asyncContext) {
72 return NapiUtils::JSParaError(env, callback);
73 }
74 napi_value promise = nullptr;
75 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
76 napi_value resource = nullptr;
77 napi_create_string_utf8(env, "JSSystemTimeSetTime", NAPI_AUTO_LENGTH, &resource);
78 napi_create_async_work(
79 env, nullptr, resource,
80 [](napi_env env, void *data) {
81 AsyncContext *asyncContext = (AsyncContext *)data;
82 int32_t errorCode = E_TIME_OK;
83 asyncContext->isOK = TimeServiceClient::GetInstance()->SetTime(asyncContext->time, errorCode);
84 if (!asyncContext->isOK) {
85 auto jsErrorCode = NapiUtils::ConvertErrorCode(errorCode);
86 asyncContext->message = NapiUtils::GetErrorMessage(jsErrorCode);
87 asyncContext->errorCode = JsErrorCode::ERROR;
88 }
89 },
90 [](napi_env env, napi_status status, void *data) {
91 AsyncContext *asyncContext = (AsyncContext *)data;
92 if (asyncContext == nullptr) {
93 return;
94 }
95 CallbackPromiseInfo info;
96 info.isCallback = asyncContext->isCallback;
97 info.callback = asyncContext->callbackRef;
98 info.deferred = asyncContext->deferred;
99 info.errorCode = asyncContext->errorCode;
100 info.message = asyncContext->message;
101 napi_value result = 0;
102 napi_get_null(env, &result);
103 NapiUtils::ReturnCallbackPromise(env, info, result);
104 napi_delete_async_work(env, asyncContext->work);
105 delete asyncContext;
106 },
107 (void *)asyncContext, &asyncContext->work);
108 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
109 if (asyncContext->isCallback) {
110 return NapiUtils::NapiGetNull(env);
111 } else {
112 return promise;
113 }
114 }
115
JSSystemTimeSetTimeZone(napi_env env,napi_callback_info info)116 napi_value JSSystemTimeSetTimeZone(napi_env env, napi_callback_info info)
117 {
118 size_t argc = SET_TIMEZONE_MAX_PARA;
119 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
120 napi_value thisVar = nullptr;
121 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
122 std::string timezoneId;
123 napi_ref callback = nullptr;
124 if (NapiUtils::ParseParametersBySetTimezone(env, argv, argc, timezoneId, callback) == nullptr) {
125 return NapiUtils::JSParaError(env, callback);
126 }
127 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env, .timeZone = timezoneId };
128 if (!asyncContext) {
129 return NapiUtils::JSParaError(env, callback);
130 }
131 napi_value promise = nullptr;
132 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
133 napi_value resource = nullptr;
134 napi_create_string_utf8(env, "JSSystemTimeSetTimeZone", NAPI_AUTO_LENGTH, &resource);
135 napi_create_async_work(
136 env, nullptr, resource,
137 [](napi_env env, void *data) {
138 AsyncContext *asyncContext = (AsyncContext *)data;
139 int32_t errorCode = E_TIME_OK;
140 asyncContext->isOK = TimeServiceClient::GetInstance()->SetTimeZone(asyncContext->timeZone, errorCode);
141 if (!asyncContext->isOK) {
142 auto jsErrorCode = NapiUtils::ConvertErrorCode(errorCode);
143 asyncContext->message = NapiUtils::GetErrorMessage(jsErrorCode).c_str();
144 asyncContext->errorCode = JsErrorCode::ERROR;
145 }
146 },
147 [](napi_env env, napi_status status, void *data) {
148 AsyncContext *asyncContext = (AsyncContext *)data;
149 if (asyncContext == nullptr) {
150 return;
151 }
152 CallbackPromiseInfo info;
153 info.isCallback = asyncContext->isCallback;
154 info.callback = asyncContext->callbackRef;
155 info.deferred = asyncContext->deferred;
156 info.errorCode = asyncContext->errorCode;
157 info.message = asyncContext->message;
158 napi_value result = 0;
159 napi_get_null(env, &result);
160 NapiUtils::ReturnCallbackPromise(env, info, result);
161 napi_delete_async_work(env, asyncContext->work);
162 delete asyncContext;
163 },
164 (void *)asyncContext, &asyncContext->work);
165 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
166 if (asyncContext->isCallback) {
167 return NapiUtils::NapiGetNull(env);
168 } else {
169 return promise;
170 }
171 }
172
JSSystemTimeGetCurrentTime(napi_env env,napi_callback_info info)173 napi_value JSSystemTimeGetCurrentTime(napi_env env, napi_callback_info info)
174 {
175 size_t argc = SET_TIMEZONE_MAX_PARA;
176 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
177 napi_value thisVar = nullptr;
178 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
179 napi_ref callback = nullptr;
180 bool isNano = false;
181 if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
182 return NapiUtils::JSParaError(env, callback);
183 }
184 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
185 if (!asyncContext) {
186 return NapiUtils::JSParaError(env, callback);
187 }
188 napi_value promise = nullptr;
189 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
190 asyncContext->isNano = isNano;
191 napi_value resource = nullptr;
192 napi_create_string_utf8(env, "JSSystemTimeGetCurrentTime", NAPI_AUTO_LENGTH, &resource);
193 napi_create_async_work(
194 env, nullptr, resource,
195 [](napi_env env, void *data) {
196 AsyncContext *asyncContext = (AsyncContext *)data;
197 if (asyncContext->isNano) {
198 asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeNs();
199 } else {
200 asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeMs();
201 }
202 },
203 [](napi_env env, napi_status status, void *data) {
204 AsyncContext *asyncContext = (AsyncContext *)data;
205 if (asyncContext == nullptr) {
206 return;
207 }
208 if (asyncContext->time < 0) {
209 asyncContext->errorCode = JsErrorCode::ERROR;
210 }
211 CallbackPromiseInfo info;
212 info.isCallback = asyncContext->isCallback;
213 info.callback = asyncContext->callbackRef;
214 info.deferred = asyncContext->deferred;
215 info.errorCode = asyncContext->errorCode;
216 info.message = asyncContext->message;
217 napi_value result = nullptr;
218 napi_create_int64(env, asyncContext->time, &result);
219 NapiUtils::ReturnCallbackPromise(env, info, result);
220 napi_delete_async_work(env, asyncContext->work);
221 delete asyncContext;
222 },
223 (void *)asyncContext, &asyncContext->work);
224 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
225 if (asyncContext->isCallback) {
226 return NapiUtils::NapiGetNull(env);
227 } else {
228 return promise;
229 }
230 }
231
JSSystemTimeGetRealActiveTime(napi_env env,napi_callback_info info)232 napi_value JSSystemTimeGetRealActiveTime(napi_env env, napi_callback_info info)
233 {
234 size_t argc = SET_TIMEZONE_MAX_PARA;
235 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
236 napi_value thisVar = nullptr;
237 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
238 napi_ref callback = nullptr;
239 bool isNano = false;
240 if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
241 return NapiUtils::JSParaError(env, callback);
242 }
243 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
244 if (!asyncContext) {
245 return NapiUtils::JSParaError(env, callback);
246 }
247 napi_value promise = nullptr;
248 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
249 asyncContext->isNano = isNano;
250 napi_value resource = nullptr;
251 napi_create_string_utf8(env, "JSSystemTimeGetRealActiveTime", NAPI_AUTO_LENGTH, &resource);
252 napi_create_async_work(
253 env, nullptr, resource,
254 [](napi_env env, void *data) {
255 AsyncContext *asyncContext = (AsyncContext *)data;
256 if (asyncContext->isNano) {
257 asyncContext->time = TimeServiceClient::GetInstance()->GetMonotonicTimeNs();
258 } else {
259 asyncContext->time = TimeServiceClient::GetInstance()->GetMonotonicTimeMs();
260 }
261 },
262 [](napi_env env, napi_status status, void *data) {
263 AsyncContext *asyncContext = (AsyncContext *)data;
264 if (asyncContext == nullptr) {
265 return;
266 }
267 if (asyncContext->time < 0) {
268 asyncContext->errorCode = JsErrorCode::ERROR;
269 }
270 CallbackPromiseInfo info;
271 info.isCallback = asyncContext->isCallback;
272 info.callback = asyncContext->callbackRef;
273 info.deferred = asyncContext->deferred;
274 info.errorCode = asyncContext->errorCode;
275 info.message = asyncContext->message;
276 napi_value result = nullptr;
277 napi_create_int64(env, asyncContext->time, &result);
278 NapiUtils::ReturnCallbackPromise(env, info, result);
279 napi_delete_async_work(env, asyncContext->work);
280 delete asyncContext;
281 },
282 (void *)asyncContext, &asyncContext->work);
283 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
284 if (asyncContext->isCallback) {
285 return NapiUtils::NapiGetNull(env);
286 } else {
287 return promise;
288 }
289 }
290
JSSystemTimeGetRealTime(napi_env env,napi_callback_info info)291 napi_value JSSystemTimeGetRealTime(napi_env env, napi_callback_info info)
292 {
293 size_t argc = SET_TIMEZONE_MAX_PARA;
294 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
295 napi_value thisVar = nullptr;
296 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
297 napi_ref callback = nullptr;
298 bool isNano = false;
299 if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
300 return NapiUtils::JSParaError(env, callback);
301 }
302 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
303 if (!asyncContext) {
304 return NapiUtils::JSParaError(env, callback);
305 }
306 napi_value promise = nullptr;
307 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
308 asyncContext->isNano = isNano;
309 napi_value resource = nullptr;
310 napi_create_string_utf8(env, "JSSystemTimeGetRealTime", NAPI_AUTO_LENGTH, &resource);
311 napi_create_async_work(
312 env, nullptr, resource,
313 [](napi_env env, void *data) {
314 AsyncContext *asyncContext = (AsyncContext *)data;
315 if (asyncContext->isNano) {
316 asyncContext->time = TimeServiceClient::GetInstance()->GetBootTimeNs();
317 } else {
318 asyncContext->time = TimeServiceClient::GetInstance()->GetBootTimeMs();
319 }
320 },
321 [](napi_env env, napi_status status, void *data) {
322 AsyncContext *asyncContext = (AsyncContext *)data;
323 if (asyncContext == nullptr) {
324 return;
325 }
326 if (asyncContext->time < 0) {
327 asyncContext->errorCode = JsErrorCode::ERROR;
328 }
329 CallbackPromiseInfo info;
330 info.isCallback = asyncContext->isCallback;
331 info.callback = asyncContext->callbackRef;
332 info.deferred = asyncContext->deferred;
333 info.errorCode = asyncContext->errorCode;
334 info.message = asyncContext->message;
335 napi_value result = nullptr;
336 napi_create_int64(env, asyncContext->time, &result);
337 NapiUtils::ReturnCallbackPromise(env, info, result);
338 napi_delete_async_work(env, asyncContext->work);
339 delete asyncContext;
340 },
341 (void *)asyncContext, &asyncContext->work);
342 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
343 if (asyncContext->isCallback) {
344 return NapiUtils::NapiGetNull(env);
345 } else {
346 return promise;
347 }
348 }
349
JSSystemTimeGetDate(napi_env env,napi_callback_info info)350 napi_value JSSystemTimeGetDate(napi_env env, napi_callback_info info)
351 {
352 size_t argc = SET_TIMEZONE_MAX_PARA;
353 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
354 napi_value thisVar = nullptr;
355 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
356 napi_ref callback = nullptr;
357 if (NapiUtils::ParseParametersGet(env, argv, argc, callback) == nullptr) {
358 return NapiUtils::JSParaError(env, callback);
359 }
360 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
361 if (!asyncContext) {
362 return NapiUtils::JSParaError(env, callback);
363 }
364 napi_value promise = nullptr;
365 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
366 napi_value resource = nullptr;
367 napi_create_string_utf8(env, "JSSystemTimeGetDate", NAPI_AUTO_LENGTH, &resource);
368 napi_create_async_work(
369 env, nullptr, resource,
370 [](napi_env env, void *data) {
371 AsyncContext *asyncContext = (AsyncContext *)data;
372 asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeMs();
373 },
374 [](napi_env env, napi_status status, void *data) {
375 AsyncContext *asyncContext = (AsyncContext *)data;
376 if (asyncContext == nullptr) {
377 return;
378 }
379 if (asyncContext->time < 0) {
380 asyncContext->errorCode = JsErrorCode::ERROR;
381 }
382 CallbackPromiseInfo info;
383 info.isCallback = asyncContext->isCallback;
384 info.callback = asyncContext->callbackRef;
385 info.deferred = asyncContext->deferred;
386 info.errorCode = asyncContext->errorCode;
387 info.message = asyncContext->message;
388 napi_value result = nullptr;
389 napi_create_date(env, asyncContext->time, &result);
390 NapiUtils::ReturnCallbackPromise(env, info, result);
391 napi_delete_async_work(env, asyncContext->work);
392 delete asyncContext;
393 },
394 (void *)asyncContext, &asyncContext->work);
395 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
396 if (asyncContext->isCallback) {
397 return NapiUtils::NapiGetNull(env);
398 } else {
399 return promise;
400 }
401 }
402
JSSystemTimeGetTimeZone(napi_env env,napi_callback_info info)403 napi_value JSSystemTimeGetTimeZone(napi_env env, napi_callback_info info)
404 {
405 size_t argc = SET_TIMEZONE_MAX_PARA;
406 napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
407 napi_value thisVar = nullptr;
408 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
409 napi_ref callback = nullptr;
410 if (NapiUtils::ParseParametersGet(env, argv, argc, callback) == nullptr) {
411 return NapiUtils::JSParaError(env, callback);
412 }
413 AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
414 if (!asyncContext) {
415 return NapiUtils::JSParaError(env, callback);
416 }
417 TIME_HILOGI(TIME_MODULE_JS_NAPI, " jsgetTimezone start==");
418 napi_value promise = nullptr;
419 TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
420 napi_value resource = nullptr;
421 napi_create_string_utf8(env, "JSSystemTimeGetTimeZone", NAPI_AUTO_LENGTH, &resource);
422 napi_create_async_work(
423 env, nullptr, resource,
424 [](napi_env env, void *data) {
425 AsyncContext *asyncContext = (AsyncContext *)data;
426 asyncContext->timeZone = TimeServiceClient::GetInstance()->GetTimeZone();
427 },
428 [](napi_env env, napi_status status, void *data) {
429 AsyncContext *asyncContext = (AsyncContext *)data;
430 if (asyncContext == nullptr) {
431 return;
432 }
433 if (asyncContext->timeZone == "") {
434 asyncContext->errorCode = JsErrorCode::ERROR;
435 }
436 CallbackPromiseInfo info;
437 info.isCallback = asyncContext->isCallback;
438 info.callback = asyncContext->callbackRef;
439 info.deferred = asyncContext->deferred;
440 info.errorCode = asyncContext->errorCode;
441 info.message = asyncContext->message;
442 napi_value result = nullptr;
443 napi_create_string_utf8(env, asyncContext->timeZone.c_str(), asyncContext->timeZone.length(), &result);
444 NapiUtils::ReturnCallbackPromise(env, info, result);
445 napi_delete_async_work(env, asyncContext->work);
446 delete asyncContext;
447 },
448 (void *)asyncContext, &asyncContext->work);
449 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
450 if (asyncContext->isCallback) {
451 return NapiUtils::NapiGetNull(env);
452 } else {
453 return promise;
454 }
455 }
456
457 EXTERN_C_START
SystemTimeExport(napi_env env,napi_value exports)458 napi_value SystemTimeExport(napi_env env, napi_value exports)
459 {
460 static napi_property_descriptor desc[] = {
461 DECLARE_NAPI_FUNCTION("setTime", JSSystemTimeSetTime),
462 DECLARE_NAPI_FUNCTION("setDate", JSSystemTimeSetTime),
463 DECLARE_NAPI_FUNCTION("setTimezone", JSSystemTimeSetTimeZone),
464 DECLARE_NAPI_FUNCTION("getCurrentTime", JSSystemTimeGetCurrentTime),
465 DECLARE_NAPI_FUNCTION("getRealActiveTime", JSSystemTimeGetRealActiveTime),
466 DECLARE_NAPI_FUNCTION("getRealTime", JSSystemTimeGetRealTime),
467 DECLARE_NAPI_FUNCTION("getDate", JSSystemTimeGetDate),
468 DECLARE_NAPI_FUNCTION("getTimezone", JSSystemTimeGetTimeZone),
469 };
470 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
471 return exports;
472 }
473 EXTERN_C_END
474
475 static napi_module system_time_module = { .nm_version = 1,
476 .nm_flags = 0,
477 .nm_filename = nullptr,
478 .nm_register_func = SystemTimeExport,
479 .nm_modname = "systemTime",
480 .nm_priv = ((void *)0),
481 .reserved = { 0 } };
482
SystemTimeRegister()483 extern "C" __attribute__((constructor)) void SystemTimeRegister()
484 {
485 napi_module_register(&system_time_module);
486 }
487 } // namespace MiscServicesNapi
488 } // namespace OHOS