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