• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 <cstdint>
17 #include <memory>
18 #include <string>
19 
20 #include "interfaces/napi/kits/utils/napi_utils.h"
21 #include "js_native_api.h"
22 #include "js_native_api_types.h"
23 #include "napi/native_api.h"
24 #include "napi/native_engine/native_value.h"
25 #include "napi/native_node_api.h"
26 
27 #include "core/common/ace_engine.h"
28 #include "frameworks/base/log/log.h"
29 #include "frameworks/bridge/common/utils/engine_helper.h"
30 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
31 
32 namespace OHOS::Ace::Napi {
33 const char EN_ALERT_APPROVE[] = "enableAlertBeforeBackPage:ok";
34 const char EN_ALERT_REJECT[] = "enableAlertBeforeBackPage:fail cancel";
35 const char DIS_ALERT_SUCCESS[] = "disableAlertBeforeBackPage:ok";
36 
37 static constexpr size_t ARGC_WITH_MODE = 2;
38 static constexpr size_t ARGC_WITH_MODE_AND_CALLBACK = 3;
39 static constexpr uint32_t STANDARD = 0;
40 static constexpr uint32_t SINGLE = 1;
41 static constexpr uint32_t INVALID = 2;
42 
ParseUri(napi_env env,napi_value uriNApi,std::string & uriString)43 static void ParseUri(napi_env env, napi_value uriNApi, std::string& uriString)
44 {
45     if (uriNApi != nullptr) {
46         size_t uriLen = 0;
47         napi_get_value_string_utf8(env, uriNApi, nullptr, 0, &uriLen);
48         std::unique_ptr<char[]> uri = std::make_unique<char[]>(uriLen + 1);
49         napi_get_value_string_utf8(env, uriNApi, uri.get(), uriLen + 1, &uriLen);
50         uriString = uri.get();
51     }
52 }
53 
ParseParams(napi_env env,napi_value params,std::string & paramsString)54 static void ParseParams(napi_env env, napi_value params, std::string& paramsString)
55 {
56     // TODO: Save the original data instead of making the serial number.
57     if (params == nullptr) {
58         return;
59     }
60     napi_value globalValue;
61     napi_get_global(env, &globalValue);
62     napi_value jsonValue;
63     napi_get_named_property(env, globalValue, "JSON", &jsonValue);
64     napi_value stringifyValue;
65     napi_get_named_property(env, jsonValue, "stringify", &stringifyValue);
66     napi_value funcArgv[1] = { params };
67     napi_value returnValue;
68     napi_call_function(env, jsonValue, stringifyValue, 1, funcArgv, &returnValue);
69     size_t len = 0;
70     napi_get_value_string_utf8(env, returnValue, nullptr, 0, &len);
71     std::unique_ptr<char[]> paramsChar = std::make_unique<char[]>(len + 1);
72     napi_get_value_string_utf8(env, returnValue, paramsChar.get(), len + 1, &len);
73     paramsString = paramsChar.get();
74 }
75 
76 struct RouterAsyncContext {
77     napi_env env = nullptr;
78     napi_ref callbackSuccess = nullptr;
79     napi_ref callbackFail = nullptr;
80     napi_ref callbackComplete = nullptr;
81     int32_t callbackType = 0;
82     std::string keyForUrl;
83     std::string paramsString;
84     std::string uriString;
85     uint32_t mode = STANDARD;
86     napi_deferred deferred = nullptr;
87     napi_ref callbackRef = nullptr;
88     int32_t callbackCode = 0;
89     std::string callbackMsg;
90     int32_t instanceId = -1;
~RouterAsyncContextOHOS::Ace::Napi::RouterAsyncContext91     ~RouterAsyncContext()
92     {
93         if (callbackRef) {
94             napi_delete_reference(env, callbackRef);
95         }
96         if (callbackSuccess) {
97             napi_delete_reference(env, callbackSuccess);
98         }
99         if (callbackFail) {
100             napi_delete_reference(env, callbackFail);
101         }
102         if (callbackComplete) {
103             napi_delete_reference(env, callbackComplete);
104         }
105     }
106 };
107 
108 using RouterFunc = std::function<void(const std::string&, const std::string&, int32_t)>;
109 
CommonRouterProcess(napi_env env,napi_callback_info info,const RouterFunc & callback)110 static void CommonRouterProcess(napi_env env, napi_callback_info info, const RouterFunc& callback)
111 {
112     size_t requireArgc = 1;
113     size_t argc = ARGC_WITH_MODE;
114     napi_value argv[ARGC_WITH_MODE] = { 0 };
115     napi_value thisVar = nullptr;
116     void* data = nullptr;
117     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
118     if (argc < requireArgc) {
119         LOGE("params number err");
120         return;
121     }
122     napi_value uriNApi = nullptr;
123     napi_value params = nullptr;
124     napi_valuetype valueType = napi_undefined;
125     napi_typeof(env, argv[0], &valueType);
126     if (valueType == napi_object) {
127         napi_get_named_property(env, argv[0], "url", &uriNApi);
128         napi_typeof(env, uriNApi, &valueType);
129         if (valueType != napi_string) {
130             LOGE("url is invalid");
131             return;
132         }
133         napi_get_named_property(env, argv[0], "params", &params);
134     }
135     std::string paramsString;
136     ParseParams(env, params, paramsString);
137     std::string uriString;
138     napi_typeof(env, uriNApi, &valueType);
139     if (valueType == napi_string) {
140         ParseUri(env, uriNApi, uriString);
141     } else {
142         LOGW("The parameter type is incorrect.");
143     }
144 
145     uint32_t mode = INVALID;
146     napi_typeof(env, argv[1], &valueType);
147     if (argc == ARGC_WITH_MODE && valueType == napi_number) {
148         LOGI("router mode with single");
149         napi_get_value_uint32(env, argv[1], &mode);
150     }
151     callback(uriString, paramsString, mode);
152 }
153 
JSRouterPush(napi_env env,napi_callback_info info)154 static napi_value JSRouterPush(napi_env env, napi_callback_info info)
155 {
156     LOGI("NAPI router push called");
157     auto callback = [](const std::string& uri, const std::string& params, uint32_t mode) {
158         auto delegate = EngineHelper::GetCurrentDelegate();
159         if (!delegate) {
160             LOGE("can not get delegate.");
161             return;
162         }
163         if (mode == INVALID) {
164             delegate->Push(uri, params);
165         } else {
166             delegate->PushWithMode(uri, params, mode);
167         }
168     };
169     CommonRouterProcess(env, info, callback);
170     return nullptr;
171 }
172 
JSRouterReplace(napi_env env,napi_callback_info info)173 static napi_value JSRouterReplace(napi_env env, napi_callback_info info)
174 {
175     LOGI("NAPI router replace called");
176     auto callback = [](const std::string& uri, const std::string& params, uint32_t mode) {
177         auto delegate = EngineHelper::GetCurrentDelegate();
178         if (!delegate) {
179             LOGE("can not get delegate.");
180             return;
181         }
182         if (mode == INVALID) {
183             delegate->Replace(uri, params);
184         } else {
185             delegate->ReplaceWithMode(uri, params, mode);
186         }
187     };
188     CommonRouterProcess(env, info, callback);
189     return nullptr;
190 }
191 
ParseParamWithCallback(napi_env env,std::shared_ptr<RouterAsyncContext> asyncContext,const size_t argc,napi_value * argv,napi_value * result)192 bool ParseParamWithCallback(napi_env env, std::shared_ptr<RouterAsyncContext> asyncContext, const size_t argc,
193     napi_value* argv, napi_value* result)
194 {
195     asyncContext->env = env;
196     for (size_t i = 0; i < argc; i++) {
197         napi_valuetype valueType = napi_undefined;
198         napi_typeof(env, argv[i], &valueType);
199         if (i == 0) {
200             if (valueType != napi_object) {
201                 NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
202                 return false;
203             }
204             napi_value uriNApi = nullptr;
205             napi_value params = nullptr;
206             napi_get_named_property(env, argv[i], asyncContext->keyForUrl.c_str(), &uriNApi);
207             napi_typeof(env, uriNApi, &valueType);
208             if (valueType != napi_string) {
209                 LOGW("url is invalid");
210                 NapiThrow(env, "The type of the url parameter is not string.", Framework::ERROR_CODE_PARAM_INVALID);
211                 return false;
212             }
213             ParseUri(env, uriNApi, asyncContext->uriString);
214             napi_get_named_property(env, argv[i], "params", &params);
215             ParseParams(env, params, asyncContext->paramsString);
216         } else if (valueType == napi_number) {
217             LOGI("router mode with single");
218             napi_get_value_uint32(env, argv[i], &asyncContext->mode);
219         } else if (valueType == napi_function) {
220             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
221         } else {
222             NapiThrow(env, "The type of parameters is incorrect.", Framework::ERROR_CODE_PARAM_INVALID);
223             return false;
224         }
225     }
226 
227     if (asyncContext->callbackRef == nullptr) {
228         if (argc > ARGC_WITH_MODE) {
229             NapiThrow(env, "The largest number of parameters is 2 in Promise.", Framework::ERROR_CODE_PARAM_INVALID);
230             return false;
231         }
232         napi_create_promise(env, &asyncContext->deferred, result);
233     }
234     return true;
235 }
236 
TriggerCallback(std::shared_ptr<RouterAsyncContext> asyncContext)237 void TriggerCallback(std::shared_ptr<RouterAsyncContext> asyncContext)
238 {
239     LOGI("trigger callback start");
240     napi_handle_scope scope = nullptr;
241     napi_open_handle_scope(asyncContext->env, &scope);
242     if (scope == nullptr) {
243         return;
244     }
245 
246     if (asyncContext->callbackCode == Framework::ERROR_CODE_NO_ERROR) {
247         napi_value result = nullptr;
248         napi_get_undefined(asyncContext->env, &result);
249         if (asyncContext->deferred) {
250             napi_resolve_deferred(asyncContext->env, asyncContext->deferred, result);
251         } else {
252             napi_value callback = nullptr;
253             napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
254             napi_value ret;
255             napi_call_function(asyncContext->env, nullptr, callback, 1, &result, &ret);
256         }
257     } else {
258         napi_value code = nullptr;
259         std::string strCode = std::to_string(asyncContext->callbackCode);
260         napi_create_string_utf8(asyncContext->env, strCode.c_str(), strCode.length(), &code);
261 
262         napi_value msg = nullptr;
263         std::string strMsg = ErrorToMessage(asyncContext->callbackCode) + asyncContext->callbackMsg;
264         LOGE("napi throw errCode %{public}d strMsg %{public}s", asyncContext->callbackCode, strMsg.c_str());
265         napi_create_string_utf8(asyncContext->env, strMsg.c_str(), strMsg.length(), &msg);
266 
267         napi_value error = nullptr;
268         napi_create_error(asyncContext->env, code, msg, &error);
269         if (asyncContext->deferred) {
270             napi_reject_deferred(asyncContext->env, asyncContext->deferred, error);
271         } else {
272             napi_value callback = nullptr;
273             napi_get_reference_value(asyncContext->env, asyncContext->callbackRef, &callback);
274             napi_value ret;
275             napi_call_function(asyncContext->env, nullptr, callback, 1, &error, &ret);
276         }
277     }
278     napi_close_handle_scope(asyncContext->env, scope);
279 }
280 
281 using ErrorCallback = std::function<void(const std::string&, int32_t)>;
282 using RouterWithCallbackFunc = std::function<void(std::shared_ptr<RouterAsyncContext>, const ErrorCallback&)>;
283 
CommonRouterWithCallbackProcess(napi_env env,napi_callback_info info,const RouterWithCallbackFunc & callback,const std::string & keyForUrl)284 static napi_value CommonRouterWithCallbackProcess(
285     napi_env env, napi_callback_info info, const RouterWithCallbackFunc& callback, const std::string& keyForUrl)
286 {
287     napi_value result = nullptr;
288     napi_get_undefined(env, &result);
289     size_t requireArgc = 1;
290     size_t argc = ARGC_WITH_MODE_AND_CALLBACK;
291     napi_value argv[ARGC_WITH_MODE_AND_CALLBACK] = { 0 };
292     napi_value thisVar = nullptr;
293     void* data = nullptr;
294     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
295     if (argc < requireArgc) {
296         LOGW("params number err");
297         NapiThrow(
298             env, "The number of parameters must be greater than or equal to 1.", Framework::ERROR_CODE_PARAM_INVALID);
299         return result;
300     } else if (argc > ARGC_WITH_MODE_AND_CALLBACK) {
301         LOGW("params number err");
302         NapiThrow(env, "The largest number of parameters is 3.", Framework::ERROR_CODE_PARAM_INVALID);
303         return result;
304     }
305 
306     auto asyncContext = std::make_shared<RouterAsyncContext>();
307     asyncContext->keyForUrl = keyForUrl;
308     if (!ParseParamWithCallback(env, asyncContext, argc, argv, &result)) {
309         LOGW("parse params failed");
310         return result;
311     }
312 
313     auto errorCallback = [asyncContext](const std::string& message, int32_t errCode) mutable {
314         if (!asyncContext) {
315             return;
316         }
317         asyncContext->callbackCode = errCode;
318         asyncContext->callbackMsg = message;
319         TriggerCallback(asyncContext);
320         asyncContext = nullptr;
321     };
322     callback(asyncContext, errorCallback);
323     return result;
324 }
325 
JSRouterPushWithCallback(napi_env env,napi_callback_info info)326 static napi_value JSRouterPushWithCallback(napi_env env, napi_callback_info info)
327 {
328     LOGI("NAPI router push with callback called");
329     auto callback = [](std::shared_ptr<RouterAsyncContext> context, const ErrorCallback& errorCallback) {
330         auto delegate = EngineHelper::GetCurrentDelegate();
331         if (!delegate) {
332             NapiThrow(context->env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
333             return;
334         }
335         delegate->PushWithCallback(context->uriString, context->paramsString, errorCallback, context->mode);
336     };
337     return CommonRouterWithCallbackProcess(env, info, callback, "url");
338 }
339 
JSRouterReplaceWithCallback(napi_env env,napi_callback_info info)340 static napi_value JSRouterReplaceWithCallback(napi_env env, napi_callback_info info)
341 {
342     LOGI("NAPI router replace with callback called");
343     auto callback = [](std::shared_ptr<RouterAsyncContext> context, const ErrorCallback& errorCallback) {
344         auto delegate = EngineHelper::GetCurrentDelegate();
345         if (!delegate) {
346             NapiThrow(context->env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
347             return;
348         }
349         delegate->ReplaceWithCallback(context->uriString, context->paramsString, errorCallback, context->mode);
350     };
351     return CommonRouterWithCallbackProcess(env, info, callback, "url");
352 }
353 
JSPushNamedRoute(napi_env env,napi_callback_info info)354 static napi_value JSPushNamedRoute(napi_env env, napi_callback_info info)
355 {
356     LOGI("NAPI router push named route called");
357     auto callback = [](std::shared_ptr<RouterAsyncContext> context, const ErrorCallback& errorCallback) {
358         auto delegate = EngineHelper::GetCurrentDelegate();
359         if (!delegate) {
360             NapiThrow(context->env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
361             return;
362         }
363         delegate->PushNamedRoute(context->uriString, context->paramsString, errorCallback, context->mode);
364     };
365     return CommonRouterWithCallbackProcess(env, info, callback, "name");
366 }
367 
JSReplaceNamedRoute(napi_env env,napi_callback_info info)368 static napi_value JSReplaceNamedRoute(napi_env env, napi_callback_info info)
369 {
370     LOGI("NAPI router replace named route called");
371     auto callback = [](std::shared_ptr<RouterAsyncContext> context, const ErrorCallback& errorCallback) {
372         auto delegate = EngineHelper::GetCurrentDelegate();
373         if (!delegate) {
374             NapiThrow(context->env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
375             return;
376         }
377         delegate->ReplaceNamedRoute(context->uriString, context->paramsString, errorCallback, context->mode);
378     };
379     return CommonRouterWithCallbackProcess(env, info, callback, "name");
380 }
381 
JSRouterBack(napi_env env,napi_callback_info info)382 static napi_value JSRouterBack(napi_env env, napi_callback_info info)
383 {
384     size_t argc = 1;
385     napi_value argv = nullptr;
386     napi_value thisVar = nullptr;
387     void* data = nullptr;
388     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
389 
390     auto delegate = EngineHelper::GetCurrentDelegate();
391     if (!delegate) {
392         LOGE("can not get delegate.");
393         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
394         return nullptr;
395     }
396     std::string uriString = "";
397     std::string paramsString = "";
398     napi_value uriNApi = nullptr;
399     napi_value params = nullptr;
400     napi_valuetype valueType = napi_undefined;
401     napi_typeof(env, argv, &valueType);
402     if (valueType == napi_object) {
403         napi_get_named_property(env, argv, "url", &uriNApi);
404         napi_typeof(env, uriNApi, &valueType);
405         if (valueType == napi_undefined) {
406             napi_get_named_property(env, argv, "path", &uriNApi);
407             napi_typeof(env, uriNApi, &valueType);
408         }
409         if (valueType == napi_string) {
410             ParseUri(env, uriNApi, uriString);
411         } else {
412             LOGW("the url and path is all invalid");
413         }
414 
415         napi_get_named_property(env, argv, "params", &params);
416         napi_typeof(env, params, &valueType);
417         if (valueType == napi_object) {
418             ParseParams(env, params, paramsString);
419         } else {
420             LOGW("The parameter type is incorrect.");
421         }
422     }
423     delegate->Back(uriString, paramsString);
424     return nullptr;
425 }
426 
JSRouterClear(napi_env env,napi_callback_info info)427 static napi_value JSRouterClear(napi_env env, napi_callback_info info)
428 {
429     auto delegate = EngineHelper::GetCurrentDelegate();
430     if (!delegate) {
431         LOGE("can not get delegate.");
432         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
433         return nullptr;
434     }
435     delegate->Clear();
436     return nullptr;
437 }
438 
JSRouterGetLength(napi_env env,napi_callback_info info)439 static napi_value JSRouterGetLength(napi_env env, napi_callback_info info)
440 {
441     auto delegate = EngineHelper::GetCurrentDelegate();
442     if (!delegate) {
443         LOGE("can not get delegate.");
444         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
445         return nullptr;
446     }
447     int32_t routeNumber = delegate->GetStackSize();
448     napi_value routeNApiNum = nullptr;
449     napi_create_int32(env, routeNumber, &routeNApiNum);
450     napi_value result = nullptr;
451     napi_coerce_to_string(env, routeNApiNum, &result);
452     return result;
453 }
454 
JSRouterGetState(napi_env env,napi_callback_info info)455 static napi_value JSRouterGetState(napi_env env, napi_callback_info info)
456 {
457     int32_t routeIndex = 0;
458     std::string routeName;
459     std::string routePath;
460     auto delegate = EngineHelper::GetCurrentDelegate();
461     if (!delegate) {
462         LOGE("can not get delegate.");
463         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
464         return nullptr;
465     }
466     delegate->GetState(routeIndex, routeName, routePath);
467     size_t routeNameLen = routeName.length();
468     size_t routePathLen = routePath.length();
469 
470     napi_value resultArray[3] = { 0 };
471     napi_create_int32(env, routeIndex, &resultArray[0]);
472     napi_create_string_utf8(env, routeName.c_str(), routeNameLen, &resultArray[1]);
473     napi_create_string_utf8(env, routePath.c_str(), routePathLen, &resultArray[2]);
474 
475     napi_value result = nullptr;
476     napi_create_object(env, &result);
477     napi_set_named_property(env, result, "index", resultArray[0]);
478     napi_set_named_property(env, result, "name", resultArray[1]);
479     napi_set_named_property(env, result, "path", resultArray[2]);
480     return result;
481 }
482 
CallBackToJSTread(std::shared_ptr<RouterAsyncContext> context)483 void CallBackToJSTread(std::shared_ptr<RouterAsyncContext> context)
484 {
485     auto container = AceEngine::Get().GetContainer(context->instanceId);
486     if (!container) {
487         LOGW("container is null. %{public}d", context->instanceId);
488         return;
489     }
490 
491     auto taskExecutor = container->GetTaskExecutor();
492     if (!taskExecutor) {
493         LOGW("taskExecutor is null.");
494         return;
495     }
496     taskExecutor->PostTask(
497         [context]() {
498             napi_handle_scope scope = nullptr;
499             napi_open_handle_scope(context->env, &scope);
500             if (scope == nullptr) {
501                 return;
502             }
503 
504             napi_value result = nullptr;
505             napi_value callback = nullptr;
506             napi_value ret = nullptr;
507             if (Framework::AlertState(context->callbackType) == Framework::AlertState::USER_CONFIRM) {
508                 if (context->callbackSuccess) {
509                     napi_create_string_utf8(context->env, EN_ALERT_APPROVE, NAPI_AUTO_LENGTH, &result);
510                     napi_value argv[1] = { result };
511                     napi_get_reference_value(context->env, context->callbackSuccess, &callback);
512                     napi_call_function(context->env, nullptr, callback, 1, argv, &ret);
513                 }
514                 if (context->callbackComplete) {
515                     napi_get_reference_value(context->env, context->callbackComplete, &callback);
516                     napi_call_function(context->env, nullptr, callback, 0, nullptr, &ret);
517                 }
518             }
519             if (Framework::AlertState(context->callbackType) == Framework::AlertState::USER_CANCEL) {
520                 if (context->callbackFail) {
521                     napi_create_string_utf8(context->env, EN_ALERT_REJECT, NAPI_AUTO_LENGTH, &result);
522                     napi_value argv[1] = { result };
523                     napi_get_reference_value(context->env, context->callbackFail, &callback);
524                     napi_call_function(context->env, nullptr, callback, 1, argv, &ret);
525                 }
526                 if (context->callbackComplete) {
527                     napi_get_reference_value(context->env, context->callbackComplete, &callback);
528                     napi_call_function(context->env, nullptr, callback, 0, nullptr, &ret);
529                 }
530             }
531 
532             napi_close_handle_scope(context->env, scope);
533         },
534         TaskExecutor::TaskType::JS);
535 }
536 
JSRouterEnableAlertBeforeBackPage(napi_env env,napi_callback_info info)537 static napi_value JSRouterEnableAlertBeforeBackPage(napi_env env, napi_callback_info info)
538 {
539     size_t argc = 1;
540     napi_value argv = nullptr;
541     napi_value thisVar = nullptr;
542     void* data = nullptr;
543     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
544 
545     napi_valuetype valueType = napi_undefined;
546     napi_typeof(env, argv, &valueType);
547     if (valueType != napi_object) {
548         LOGW("EnableAlertBeforeBackPage: params is null");
549         NapiThrow(env, "The type of the parameter is not object.", Framework::ERROR_CODE_PARAM_INVALID);
550         return nullptr;
551     }
552 
553     napi_value messageNapi = nullptr;
554     std::unique_ptr<char[]> messageChar;
555     napi_get_named_property(env, argv, "message", &messageNapi);
556     napi_typeof(env, messageNapi, &valueType);
557     if (valueType == napi_string) {
558         size_t length = 0;
559         napi_get_value_string_utf8(env, messageNapi, nullptr, 0, &length);
560         messageChar = std::make_unique<char[]>(length + 1);
561         napi_get_value_string_utf8(env, messageNapi, messageChar.get(), length + 1, &length);
562     } else {
563         LOGW("EnableAlertBeforeBackPage: message is null");
564         NapiThrow(env, "The type of the message is not string.", Framework::ERROR_CODE_PARAM_INVALID);
565         return nullptr;
566     }
567 
568     auto delegate = EngineHelper::GetCurrentDelegate();
569     if (!delegate) {
570         LOGW("EnableAlertBeforeBackPage: delegate is null");
571         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
572         return nullptr;
573     }
574 
575     auto context = std::make_shared<RouterAsyncContext>();
576     context->env = env;
577     context->instanceId = Container::CurrentId();
578     napi_value successFunc = nullptr;
579     napi_value failFunc = nullptr;
580     napi_value completeFunc = nullptr;
581     napi_get_named_property(env, argv, "success", &successFunc);
582     napi_get_named_property(env, argv, "cancel", &failFunc);
583     napi_get_named_property(env, argv, "complete", &completeFunc);
584     bool isNeedCallBack = false;
585     napi_typeof(env, successFunc, &valueType);
586     if (valueType == napi_function) {
587         napi_create_reference(env, successFunc, 1, &context->callbackSuccess);
588         isNeedCallBack = true;
589     }
590 
591     napi_typeof(env, failFunc, &valueType);
592     if (valueType == napi_function) {
593         napi_create_reference(env, failFunc, 1, &context->callbackFail);
594         isNeedCallBack = true;
595     }
596     napi_typeof(env, completeFunc, &valueType);
597     if (valueType == napi_function) {
598         napi_create_reference(env, completeFunc, 1, &context->callbackComplete);
599         isNeedCallBack = true;
600     }
601 
602     auto dilogCallback = [context, isNeedCallBack](int32_t callbackType) mutable {
603         LOGI("callback after dialog click, callbackType = %{public}d", callbackType);
604         if (context && isNeedCallBack) {
605             if (Framework::AlertState(callbackType) == Framework::AlertState::RECOVERY) {
606                 context = nullptr;
607                 return;
608             }
609             context->callbackType = callbackType;
610             CallBackToJSTread(context);
611         }
612     };
613     delegate->EnableAlertBeforeBackPage(messageChar.get(), std::move(dilogCallback));
614 
615     return nullptr;
616 }
617 
JSRouterDisableAlertBeforeBackPage(napi_env env,napi_callback_info info)618 static napi_value JSRouterDisableAlertBeforeBackPage(napi_env env, napi_callback_info info)
619 {
620     auto delegate = EngineHelper::GetCurrentDelegate();
621     if (delegate) {
622         delegate->DisableAlertBeforeBackPage();
623     } else {
624         LOGW("DisableAlertBeforeBackPage: delegate is null");
625         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
626         return nullptr;
627     }
628 
629     size_t argc = 1;
630     napi_value argv = nullptr;
631     napi_value thisVar = nullptr;
632     void* data = nullptr;
633     napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
634     napi_valuetype valueType = napi_undefined;
635     napi_typeof(env, argv, &valueType);
636     if (valueType == napi_object) {
637         napi_value successFunc = nullptr;
638         napi_value completeFunc = nullptr;
639         napi_get_named_property(env, argv, "success", &successFunc);
640         napi_get_named_property(env, argv, "complete", &completeFunc);
641 
642         napi_value result = nullptr;
643         napi_value ret = nullptr;
644         napi_create_string_utf8(env, DIS_ALERT_SUCCESS, NAPI_AUTO_LENGTH, &result);
645         napi_value argv[1] = { result };
646 
647         napi_typeof(env, successFunc, &valueType);
648         if (valueType == napi_function) {
649             napi_call_function(env, nullptr, successFunc, 1, argv, &ret);
650         }
651         napi_typeof(env, completeFunc, &valueType);
652         if (valueType == napi_function) {
653             napi_call_function(env, nullptr, completeFunc, 1, argv, &ret);
654         }
655     }
656     return nullptr;
657 }
658 
JSRouterGetParams(napi_env env,napi_callback_info info)659 static napi_value JSRouterGetParams(napi_env env, napi_callback_info info)
660 {
661     auto delegate = EngineHelper::GetCurrentDelegate();
662     if (!delegate) {
663         LOGE("can not get delegate.");
664         NapiThrow(env, "UI execution context not found.", Framework::ERROR_CODE_INTERNAL_ERROR);
665         return nullptr;
666     }
667     std::string paramsStr = delegate->GetParams();
668     if (paramsStr.empty()) {
669         LOGI("PageGetParams params is null");
670         return nullptr;
671     }
672     napi_value globalValue;
673     napi_get_global(env, &globalValue);
674     napi_value jsonValue;
675     napi_get_named_property(env, globalValue, "JSON", &jsonValue);
676     napi_value parseValue;
677     napi_get_named_property(env, jsonValue, "parse", &parseValue);
678     napi_value routerParamsNApi;
679     napi_create_string_utf8(env, paramsStr.c_str(), NAPI_AUTO_LENGTH, &routerParamsNApi);
680     napi_value funcArgv[1] = { routerParamsNApi };
681     napi_value result;
682     napi_call_function(env, jsonValue, parseValue, 1, funcArgv, &result);
683     napi_valuetype valueType = napi_undefined;
684     napi_typeof(env, result, &valueType);
685     if (valueType != napi_object) {
686         LOGE("parse result fail");
687         return nullptr;
688     }
689     return result;
690 }
691 
RouterExport(napi_env env,napi_value exports)692 static napi_value RouterExport(napi_env env, napi_value exports)
693 {
694     napi_value routerMode = nullptr;
695     napi_create_object(env, &routerMode);
696     napi_value prop = nullptr;
697     napi_create_uint32(env, STANDARD, &prop);
698     napi_set_named_property(env, routerMode, "Standard", prop);
699     napi_create_uint32(env, SINGLE, &prop);
700     napi_set_named_property(env, routerMode, "Single", prop);
701 
702     napi_property_descriptor routerDesc[] = {
703         DECLARE_NAPI_FUNCTION("push", JSRouterPush),
704         DECLARE_NAPI_FUNCTION("pushUrl", JSRouterPushWithCallback),
705         DECLARE_NAPI_FUNCTION("replace", JSRouterReplace),
706         DECLARE_NAPI_FUNCTION("replaceUrl", JSRouterReplaceWithCallback),
707         DECLARE_NAPI_FUNCTION("back", JSRouterBack),
708         DECLARE_NAPI_FUNCTION("clear", JSRouterClear),
709         DECLARE_NAPI_FUNCTION("getLength", JSRouterGetLength),
710         DECLARE_NAPI_FUNCTION("getState", JSRouterGetState),
711         DECLARE_NAPI_FUNCTION("enableAlertBeforeBackPage", JSRouterEnableAlertBeforeBackPage),
712         DECLARE_NAPI_FUNCTION("enableBackPageAlert", JSRouterEnableAlertBeforeBackPage),
713         DECLARE_NAPI_FUNCTION("showAlertBeforeBackPage", JSRouterEnableAlertBeforeBackPage),
714         DECLARE_NAPI_FUNCTION("disableAlertBeforeBackPage", JSRouterDisableAlertBeforeBackPage),
715         DECLARE_NAPI_FUNCTION("hideAlertBeforeBackPage", JSRouterDisableAlertBeforeBackPage),
716         DECLARE_NAPI_FUNCTION("getParams", JSRouterGetParams),
717         DECLARE_NAPI_FUNCTION("pushNamedRoute", JSPushNamedRoute),
718         DECLARE_NAPI_FUNCTION("replaceNamedRoute", JSReplaceNamedRoute),
719         DECLARE_NAPI_PROPERTY("RouterMode", routerMode),
720     };
721     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(routerDesc) / sizeof(routerDesc[0]), routerDesc));
722 
723     return exports;
724 }
725 
726 static napi_module routerModule = {
727     .nm_version = 1,
728     .nm_flags = 0,
729     .nm_filename = nullptr,
730     .nm_register_func = RouterExport,
731     .nm_modname = "router",
732     .nm_priv = ((void*)0),
733     .reserved = { 0 },
734 };
735 
RouterRegister()736 extern "C" __attribute__((constructor)) void RouterRegister()
737 {
738     napi_module_register(&routerModule);
739 }
740 
741 } // namespace OHOS::Ace::Napi
742