• 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::GetUndefinedValue(env);
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{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
96                 asyncContext->errorCode, asyncContext->message };
97             napi_value result = 0;
98             napi_get_null(env, &result);
99             NapiUtils::ReturnCallbackPromise(env, info, result);
100             napi_delete_async_work(env, asyncContext->work);
101             delete asyncContext;
102         },
103         (void *)asyncContext, &asyncContext->work);
104     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
105     if (asyncContext->isCallback) {
106         return NapiUtils::NapiGetNull(env);
107     } else {
108         return promise;
109     }
110 }
111 
JSSystemTimeSetTimeZone(napi_env env,napi_callback_info info)112 napi_value JSSystemTimeSetTimeZone(napi_env env, napi_callback_info info)
113 {
114     size_t argc = SET_TIMEZONE_MAX_PARA;
115     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
116     napi_value thisVar = nullptr;
117     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
118     std::string timezoneId;
119     napi_ref callback = nullptr;
120     if (NapiUtils::ParseParametersBySetTimezone(env, argv, argc, timezoneId, callback) == nullptr) {
121         return NapiUtils::GetUndefinedValue(env);
122     }
123     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env, .timeZone = timezoneId };
124     if (!asyncContext) {
125         return NapiUtils::JSParaError(env, callback);
126     }
127     napi_value promise = nullptr;
128     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
129     napi_value resource = nullptr;
130     napi_create_string_utf8(env, "JSSystemTimeSetTimeZone", NAPI_AUTO_LENGTH, &resource);
131     napi_create_async_work(
132         env, nullptr, resource,
133         [](napi_env env, void *data) {
134             AsyncContext *asyncContext = (AsyncContext *)data;
135             int32_t errorCode = E_TIME_OK;
136             asyncContext->isOK = TimeServiceClient::GetInstance()->SetTimeZone(asyncContext->timeZone, errorCode);
137             if (!asyncContext->isOK) {
138                 auto jsErrorCode = NapiUtils::ConvertErrorCode(errorCode);
139                 asyncContext->message = NapiUtils::GetErrorMessage(jsErrorCode).c_str();
140                 asyncContext->errorCode = JsErrorCode::ERROR;
141             }
142         },
143         [](napi_env env, napi_status status, void *data) {
144             AsyncContext *asyncContext = (AsyncContext *)data;
145             if (asyncContext == nullptr) {
146                 return;
147             }
148             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
149                 asyncContext->errorCode, asyncContext->message };
150             napi_value result = 0;
151             napi_get_null(env, &result);
152             NapiUtils::ReturnCallbackPromise(env, info, result);
153             napi_delete_async_work(env, asyncContext->work);
154             delete asyncContext;
155         },
156         (void *)asyncContext, &asyncContext->work);
157     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
158     if (asyncContext->isCallback) {
159         return NapiUtils::NapiGetNull(env);
160     } else {
161         return promise;
162     }
163 }
164 
JSSystemTimeGetCurrentTime(napi_env env,napi_callback_info info)165 napi_value JSSystemTimeGetCurrentTime(napi_env env, napi_callback_info info)
166 {
167     size_t argc = SET_TIMEZONE_MAX_PARA;
168     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
169     napi_value thisVar = nullptr;
170     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
171     napi_ref callback = nullptr;
172     bool isNano = false;
173     if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
174         return NapiUtils::GetUndefinedValue(env);
175     }
176     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
177     if (!asyncContext) {
178         return NapiUtils::JSParaError(env, callback);
179     }
180     napi_value promise = nullptr;
181     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
182     asyncContext->isNano = isNano;
183     napi_value resource = nullptr;
184     napi_create_string_utf8(env, "JSSystemTimeGetCurrentTime", NAPI_AUTO_LENGTH, &resource);
185     napi_create_async_work(
186         env, nullptr, resource,
187         [](napi_env env, void *data) {
188             AsyncContext *asyncContext = (AsyncContext *)data;
189             if (asyncContext->isNano) {
190                 asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeNs();
191             } else {
192                 asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeMs();
193             }
194         },
195         [](napi_env env, napi_status status, void *data) {
196             AsyncContext *asyncContext = (AsyncContext *)data;
197             if (asyncContext == nullptr) {
198                 return;
199             }
200             if (asyncContext->time < 0) {
201                 asyncContext->errorCode = JsErrorCode::ERROR;
202             }
203             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
204                 asyncContext->errorCode, asyncContext->message };
205             napi_value result = nullptr;
206             napi_create_int64(env, asyncContext->time, &result);
207             NapiUtils::ReturnCallbackPromise(env, info, result);
208             napi_delete_async_work(env, asyncContext->work);
209             delete asyncContext;
210         },
211         (void *)asyncContext, &asyncContext->work);
212     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
213     if (asyncContext->isCallback) {
214         return NapiUtils::NapiGetNull(env);
215     } else {
216         return promise;
217     }
218 }
219 
JSSystemTimeGetRealActiveTime(napi_env env,napi_callback_info info)220 napi_value JSSystemTimeGetRealActiveTime(napi_env env, napi_callback_info info)
221 {
222     size_t argc = SET_TIMEZONE_MAX_PARA;
223     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
224     napi_value thisVar = nullptr;
225     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
226     napi_ref callback = nullptr;
227     bool isNano = false;
228     if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
229         return NapiUtils::GetUndefinedValue(env);
230     }
231     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
232     if (!asyncContext) {
233         return NapiUtils::JSParaError(env, callback);
234     }
235     napi_value promise = nullptr;
236     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
237     asyncContext->isNano = isNano;
238     napi_value resource = nullptr;
239     napi_create_string_utf8(env, "JSSystemTimeGetRealActiveTime", NAPI_AUTO_LENGTH, &resource);
240     napi_create_async_work(
241         env, nullptr, resource,
242         [](napi_env env, void *data) {
243             AsyncContext *asyncContext = (AsyncContext *)data;
244             if (asyncContext->isNano) {
245                 asyncContext->time = TimeServiceClient::GetInstance()->GetMonotonicTimeNs();
246             } else {
247                 asyncContext->time = TimeServiceClient::GetInstance()->GetMonotonicTimeMs();
248             }
249         },
250         [](napi_env env, napi_status status, void *data) {
251             AsyncContext *asyncContext = (AsyncContext *)data;
252             if (asyncContext == nullptr) {
253                 return;
254             }
255             if (asyncContext->time < 0) {
256                 asyncContext->errorCode = JsErrorCode::ERROR;
257             }
258             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
259                 asyncContext->errorCode, asyncContext->message };
260             napi_value result = nullptr;
261             napi_create_int64(env, asyncContext->time, &result);
262             NapiUtils::ReturnCallbackPromise(env, info, result);
263             napi_delete_async_work(env, asyncContext->work);
264             delete asyncContext;
265         },
266         (void *)asyncContext, &asyncContext->work);
267     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
268     if (asyncContext->isCallback) {
269         return NapiUtils::NapiGetNull(env);
270     } else {
271         return promise;
272     }
273 }
274 
JSSystemTimeGetRealTime(napi_env env,napi_callback_info info)275 napi_value JSSystemTimeGetRealTime(napi_env env, napi_callback_info info)
276 {
277     size_t argc = SET_TIMEZONE_MAX_PARA;
278     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
279     napi_value thisVar = nullptr;
280     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
281     napi_ref callback = nullptr;
282     bool isNano = false;
283     if (NapiUtils::ParseParametersGetNA(env, argv, argc, callback, &isNano) == nullptr) {
284         return NapiUtils::GetUndefinedValue(env);
285     }
286     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
287     if (!asyncContext) {
288         return NapiUtils::JSParaError(env, callback);
289     }
290     napi_value promise = nullptr;
291     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
292     asyncContext->isNano = isNano;
293     napi_value resource = nullptr;
294     napi_create_string_utf8(env, "JSSystemTimeGetRealTime", NAPI_AUTO_LENGTH, &resource);
295     napi_create_async_work(
296         env, nullptr, resource,
297         [](napi_env env, void *data) {
298             AsyncContext *asyncContext = (AsyncContext *)data;
299             if (asyncContext->isNano) {
300                 asyncContext->time = TimeServiceClient::GetInstance()->GetBootTimeNs();
301             } else {
302                 asyncContext->time = TimeServiceClient::GetInstance()->GetBootTimeMs();
303             }
304         },
305         [](napi_env env, napi_status status, void *data) {
306             AsyncContext *asyncContext = (AsyncContext *)data;
307             if (asyncContext == nullptr) {
308                 return;
309             }
310             if (asyncContext->time < 0) {
311                 asyncContext->errorCode = JsErrorCode::ERROR;
312             }
313             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
314                 asyncContext->errorCode, asyncContext->message };
315             napi_value result = nullptr;
316             napi_create_int64(env, asyncContext->time, &result);
317             NapiUtils::ReturnCallbackPromise(env, info, result);
318             napi_delete_async_work(env, asyncContext->work);
319             delete asyncContext;
320         },
321         (void *)asyncContext, &asyncContext->work);
322     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
323     if (asyncContext->isCallback) {
324         return NapiUtils::NapiGetNull(env);
325     } else {
326         return promise;
327     }
328 }
329 
JSSystemTimeGetDate(napi_env env,napi_callback_info info)330 napi_value JSSystemTimeGetDate(napi_env env, napi_callback_info info)
331 {
332     size_t argc = SET_TIMEZONE_MAX_PARA;
333     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
334     napi_value thisVar = nullptr;
335     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
336     napi_ref callback = nullptr;
337     if (NapiUtils::ParseParametersGet(env, argv, argc, callback) == nullptr) {
338         return NapiUtils::GetUndefinedValue(env);
339     }
340     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
341     if (!asyncContext) {
342         return NapiUtils::JSParaError(env, callback);
343     }
344     napi_value promise = nullptr;
345     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
346     napi_value resource = nullptr;
347     napi_create_string_utf8(env, "JSSystemTimeGetDate", NAPI_AUTO_LENGTH, &resource);
348     napi_create_async_work(
349         env, nullptr, resource,
350         [](napi_env env, void *data) {
351             AsyncContext *asyncContext = (AsyncContext *)data;
352             asyncContext->time = TimeServiceClient::GetInstance()->GetWallTimeMs();
353         },
354         [](napi_env env, napi_status status, void *data) {
355             AsyncContext *asyncContext = (AsyncContext *)data;
356             if (asyncContext == nullptr) {
357                 return;
358             }
359             if (asyncContext->time < 0) {
360                 asyncContext->errorCode = JsErrorCode::ERROR;
361             }
362             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
363                 asyncContext->errorCode, asyncContext->message };
364             napi_value result = nullptr;
365             napi_create_date(env, asyncContext->time, &result);
366             NapiUtils::ReturnCallbackPromise(env, info, result);
367             napi_delete_async_work(env, asyncContext->work);
368             delete asyncContext;
369         },
370         (void *)asyncContext, &asyncContext->work);
371     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
372     if (asyncContext->isCallback) {
373         return NapiUtils::NapiGetNull(env);
374     } else {
375         return promise;
376     }
377 }
378 
JSSystemTimeGetTimeZone(napi_env env,napi_callback_info info)379 napi_value JSSystemTimeGetTimeZone(napi_env env, napi_callback_info info)
380 {
381     size_t argc = SET_TIMEZONE_MAX_PARA;
382     napi_value argv[SET_TIMEZONE_MAX_PARA] = { 0 };
383     napi_value thisVar = nullptr;
384     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
385     napi_ref callback = nullptr;
386     if (NapiUtils::ParseParametersGet(env, argv, argc, callback) == nullptr) {
387         return NapiUtils::GetUndefinedValue(env);
388     }
389     AsyncContext *asyncContext = new (std::nothrow) AsyncContext{ .env = env };
390     if (!asyncContext) {
391         return NapiUtils::JSParaError(env, callback);
392     }
393     TIME_HILOGI(TIME_MODULE_JS_NAPI, " jsgetTimezone start==");
394     napi_value promise = nullptr;
395     TimePaddingAsyncCallbackInfo(env, asyncContext, callback, promise);
396     napi_value resource = nullptr;
397     napi_create_string_utf8(env, "JSSystemTimeGetTimeZone", NAPI_AUTO_LENGTH, &resource);
398     napi_create_async_work(
399         env, nullptr, resource,
400         [](napi_env env, void *data) {
401             AsyncContext *asyncContext = (AsyncContext *)data;
402             asyncContext->timeZone = TimeServiceClient::GetInstance()->GetTimeZone();
403         },
404         [](napi_env env, napi_status status, void *data) {
405             AsyncContext *asyncContext = (AsyncContext *)data;
406             if (asyncContext == nullptr) {
407                 return;
408             }
409             if (asyncContext->timeZone == "") {
410                 asyncContext->errorCode = JsErrorCode::ERROR;
411             }
412             CallbackPromiseInfo info{ asyncContext->callbackRef, asyncContext->deferred, asyncContext->isCallback,
413                 asyncContext->errorCode, asyncContext->message };
414             napi_value result = nullptr;
415             napi_create_string_utf8(env, asyncContext->timeZone.c_str(), asyncContext->timeZone.length(), &result);
416             NapiUtils::ReturnCallbackPromise(env, info, result);
417             napi_delete_async_work(env, asyncContext->work);
418             delete asyncContext;
419         },
420         (void *)asyncContext, &asyncContext->work);
421     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
422     if (asyncContext->isCallback) {
423         return NapiUtils::NapiGetNull(env);
424     } else {
425         return promise;
426     }
427 }
428 
429 EXTERN_C_START
SystemTimeExport(napi_env env,napi_value exports)430 napi_value SystemTimeExport(napi_env env, napi_value exports)
431 {
432     static napi_property_descriptor desc[] = {
433         DECLARE_NAPI_FUNCTION("setTime", JSSystemTimeSetTime),
434         DECLARE_NAPI_FUNCTION("setDate", JSSystemTimeSetTime),
435         DECLARE_NAPI_FUNCTION("setTimezone", JSSystemTimeSetTimeZone),
436         DECLARE_NAPI_FUNCTION("getCurrentTime", JSSystemTimeGetCurrentTime),
437         DECLARE_NAPI_FUNCTION("getRealActiveTime", JSSystemTimeGetRealActiveTime),
438         DECLARE_NAPI_FUNCTION("getRealTime", JSSystemTimeGetRealTime),
439         DECLARE_NAPI_FUNCTION("getDate", JSSystemTimeGetDate),
440         DECLARE_NAPI_FUNCTION("getTimezone", JSSystemTimeGetTimeZone),
441     };
442     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
443     return exports;
444 }
445 EXTERN_C_END
446 
447 static napi_module system_time_module = { .nm_version = 1,
448     .nm_flags = 0,
449     .nm_filename = nullptr,
450     .nm_register_func = SystemTimeExport,
451     .nm_modname = "systemTime",
452     .nm_priv = ((void *)0),
453     .reserved = { 0 } };
454 
SystemTimeRegister()455 extern "C" __attribute__((constructor)) void SystemTimeRegister()
456 {
457     napi_module_register(&system_time_module);
458 }
459 } // namespace MiscServicesNapi
460 } // namespace OHOS