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