• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "bridge/cj_frontend/frontend/cj_page_router_ng.h"
17 
18 #include "securec.h"
19 
20 #include "base/i18n/localization.h"
21 #include "bridge/cj_frontend/frontend/cj_frontend_abstract.h"
22 #include "bridge/cj_frontend/frontend/cj_page_loader.h"
23 #include "bridge/cj_frontend/runtime/cj_runtime_delegate.h"
24 #include "core/components_ng/base/view_advanced_register.h"
25 #include "core/components_ng/pattern/stage/page_pattern.h"
26 
27 using namespace OHOS::Ace::NG;
28 
29 namespace OHOS::Ace::Framework {
30 constexpr int PAGE_SIZE_TWO = 2;
31 
UpdateCjPageLifeCycleFuncs(RefPtr<NG::PagePattern> pagePattern,OHOS::wptr<NativeView> weakView,RefPtr<NG::FrameNode> pageNode)32 void UpdateCjPageLifeCycleFuncs(
33     RefPtr<NG::PagePattern> pagePattern, OHOS::wptr<NativeView> weakView, RefPtr<NG::FrameNode> pageNode)
34 {
35     CHECK_NULL_VOID(pagePattern);
36     pagePattern->SetOnPageShow([weakView]() {
37         auto view = weakView.promote();
38         CHECK_NULL_VOID(view);
39         view->FireOnShow();
40     });
41     pagePattern->SetOnPageHide([weakView]() {
42         auto view = weakView.promote();
43         CHECK_NULL_VOID(view);
44         view->FireOnHide();
45     });
46     pagePattern->SetOnBackPressed([weakView]() {
47         auto view = weakView.promote();
48         CHECK_NULL_RETURN(view, false);
49         return view->FireOnBackPress();
50     });
51     pagePattern->SetPageTransitionFunc([weakView, weakPage = WeakPtr<NG::FrameNode>(pageNode)]() {
52         auto view = weakView.promote();
53         CHECK_NULL_VOID(view);
54         NG::ScopedViewStackProcessor scopedViewStackProcessor;
55         NG::ViewStackProcessor::GetInstance()->SetPageNode(weakPage.Upgrade());
56         view->FireOnTransition();
57         NG::ViewStackProcessor::GetInstance()->SetPageNode(nullptr);
58     });
59 }
60 
LoadNativeViewNG(NativeView * view)61 bool LoadNativeViewNG(NativeView* view)
62 {
63     LOGI("LoadNativeView start");
64     auto currentObj = Container::Current();
65     if (!currentObj) {
66         LOGE("loadCJView fail, Container is null");
67         return false;
68     }
69     auto frontend = AceType::DynamicCast<CJFrontendAbstract>(currentObj->GetFrontend());
70     if (!frontend) {
71         LOGE("loadCJView fail, frontend is not CJFrontendAbstract");
72         return false;
73     }
74     auto pageRouterManager = AceType::DynamicCast<CJPageRouterNG>(frontend->GetPageRouterManager());
75     if (!pageRouterManager) {
76         LOGE("loadCJView fail, pageRouter not exist");
77         return false;
78     }
79     auto pageNode = pageRouterManager->GetCurrentPageNode();
80     if (!pageNode) {
81         LOGE("loadCJView fail, page node not exist");
82         return false;
83     }
84     Container::SetCurrentUsePartialUpdate(!view->IsFullUpdate());
85     if (!pageNode->GetChildren().empty()) {
86         LOGI("the page has view already, start cleanup");
87         auto oldChild = AceType::DynamicCast<NG::CustomNode>(pageNode->GetChildren().front());
88         if (oldChild) {
89             oldChild->Reset();
90         }
91         pageNode->Clean();
92     }
93     auto pageRootNode = AceType::DynamicCast<NG::UINode>(view->CreateUI());
94     if (!pageRootNode) {
95         LOGE("loadCJView fail, created rootNode is null");
96         return false;
97     }
98     pageRootNode->MountToParent(pageNode);
99     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
100     CHECK_NULL_RETURN(pagePattern, false);
101     OHOS::wptr<NativeView> weak = view;
102     view->SetRenderDoneCallback([pagePattern] { pagePattern->MarkRenderDone(); });
103     UpdateCjPageLifeCycleFuncs(pagePattern, weak, pageNode);
104     pageRouterManager->AddView(view->GetID());
105     LOGI("OHOSAceFrameworkNGLoadCJView end.");
106     return true;
107 }
108 
109 namespace {
ExitToDesktop()110 void ExitToDesktop()
111 {
112     auto currentObj = Container::Current();
113     CHECK_NULL_VOID(currentObj);
114     auto taskExecutor = currentObj->GetTaskExecutor();
115     CHECK_NULL_VOID(taskExecutor);
116     taskExecutor->PostTask(
117         [] {
118             auto pipeline = NG::PipelineContext::GetCurrentContext();
119             CHECK_NULL_VOID(pipeline);
120             pipeline->Finish(false);
121         },
122         TaskExecutor::TaskType::UI, "CJExitToDesktop");
123 }
124 } // namespace
125 
OnShowCurrent()126 void CJPageRouterNG::OnShowCurrent()
127 {
128     auto pageNode = GetCurrentPageNode();
129     if (!pageNode) {
130         LOGE("CJFrontendNG::OnShow no current page");
131         return;
132     }
133     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
134     if (!pagePattern) {
135         LOGE("CJFrontendNG::OnShow current page has no pattern");
136         return;
137     }
138     pagePattern->OnShow();
139 }
140 
OnHideCurrent()141 void CJPageRouterNG::OnHideCurrent()
142 {
143     auto pageNode = GetCurrentPageNode();
144     if (!pageNode) {
145         LOGE("CJFrontendNG::OnHide no current page");
146         return;
147     }
148     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
149     if (!pagePattern) {
150         LOGE("CJFrontendNG::OnHide current page has no pattern");
151         return;
152     }
153     pagePattern->OnHide();
154 }
155 
PopWithExitCheck()156 bool CJPageRouterNG::PopWithExitCheck()
157 {
158     auto pageNode = GetCurrentPageNode();
159     CHECK_NULL_RETURN(pageNode, false);
160     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
161     CHECK_NULL_RETURN(pagePattern, false);
162     if (pagePattern->OnBackPressed()) {
163         return true;
164     }
165     return Pop();
166 }
167 
AllowPopLastPage()168 bool CJPageRouterNG::AllowPopLastPage()
169 {
170     auto currentPage = pageRouterStack_.back().Upgrade();
171     CHECK_NULL_RETURN(currentPage, true);
172     auto pagePattern = currentPage->GetPattern<PagePattern>();
173     CHECK_NULL_RETURN(pagePattern, true);
174     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
175     CHECK_NULL_RETURN(pageInfo, true);
176     if (pageInfo->GetAlertCallback()) {
177         auto pipelineContext = NG::PipelineContext::GetCurrentContext();
178         auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
179         CHECK_NULL_RETURN(overlayManager, true);
180         overlayManager->ShowDialog(
181             pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
182         return false;
183     }
184 
185     return true;
186 }
187 
EnableAlertBeforeBackPage(const std::string & message,std::function<void (int32_t)> callback)188 void CJPageRouterNG::EnableAlertBeforeBackPage(const std::string& message, std::function<void(int32_t)> callback)
189 {
190     auto currentPage = pageRouterStack_.back().Upgrade();
191     CHECK_NULL_VOID(currentPage);
192     auto pagePattern = currentPage->GetPattern<PagePattern>();
193     CHECK_NULL_VOID(pagePattern);
194     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
195     CHECK_NULL_VOID(pageInfo);
196     ClearAlertCallback(pageInfo);
197 
198     DialogProperties dialogProperties = {
199         .content = message,
200         .autoCancel = false,
201         .buttons = { { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"), .textColor = "" },
202             { .text = Localization::GetInstance()->GetEntryLetters("common.ok"), .textColor = "" } },
203         .onSuccess =
204             [weak = AceType::WeakClaim(this), callback](int32_t successType, int32_t successIndex) {
205                 LOGI("showDialog successType: %{public}d, successIndex: %{public}d", successType, successIndex);
206                 if (!successType) {
207                     callback(successIndex);
208                     if (successIndex) {
209                         auto router = weak.Upgrade();
210                         CHECK_NULL_VOID(router);
211                         if (router->ngBackIndex_ > 0) {
212                             router->StartBackIndex(router->ngBackIndex_, router->backParam_);
213                         } else {
214                             router->StartBack(router->ngBackUri_, router->backParam_);
215                         }
216                     }
217                 }
218             },
219     };
220 
221     pageInfo->SetDialogProperties(dialogProperties);
222     pageInfo->SetAlertCallback(std::move(callback));
223 }
224 
DisableAlertBeforeBackPage()225 void CJPageRouterNG::DisableAlertBeforeBackPage()
226 {
227     auto currentPage = pageRouterStack_.back().Upgrade();
228     CHECK_NULL_VOID(currentPage);
229     auto pagePattern = currentPage->GetPattern<PagePattern>();
230     CHECK_NULL_VOID(pagePattern);
231     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
232     CHECK_NULL_VOID(pageInfo);
233     ClearAlertCallback(pageInfo);
234     pageInfo->SetAlertCallback(nullptr);
235 }
236 
ClearAlertCallback(const RefPtr<PageInfo> & pageInfo)237 void CJPageRouterNG::ClearAlertCallback(const RefPtr<PageInfo>& pageInfo)
238 {
239     if (pageInfo->GetAlertCallback()) {
240         // notify to clear js reference
241         auto alertCallback = pageInfo->GetAlertCallback();
242         alertCallback(static_cast<int32_t>(Framework::AlertState::RECOVERY));
243         pageInfo->SetAlertCallback(nullptr);
244     }
245 }
246 
StartClean()247 void CJPageRouterNG::StartClean()
248 {
249     ProcessGuard guard(this);
250     if (pageRouterStack_.size() <= 1) {
251         LOGW("current page stack can not clean, %{public}d", static_cast<int32_t>(pageRouterStack_.size()));
252         return;
253     }
254     UpdateSrcPage();
255     std::list<WeakPtr<FrameNode>> temp;
256     std::swap(temp, pageRouterStack_);
257     pageRouterStack_.emplace_back(temp.back());
258     if (!OnCleanPageStack()) {
259         LOGE("fail to clean page");
260         std::swap(temp, pageRouterStack_);
261     }
262 }
263 
StartPop()264 bool CJPageRouterNG::StartPop()
265 {
266     ProcessGuard guard(this);
267     if (pageRouterStack_.size() <= 1 || viewStack_.size() <= 1) {
268         // the last page.
269         return false;
270     }
271     UpdateSrcPage();
272     auto topNode = pageRouterStack_.back();
273     auto topView = viewStack_.back();
274     pageRouterStack_.pop_back();
275     viewStack_.pop_back();
276     if (!OnPopPage(true, true)) {
277         LOGE("fail to pop page.");
278         pageRouterStack_.emplace_back(topNode);
279         viewStack_.emplace_back(topView);
280         return false;
281     }
282     return true;
283 }
284 
GetStackSize() const285 int32_t CJPageRouterNG::GetStackSize() const
286 {
287     return static_cast<int32_t>(pageRouterStack_.size());
288 }
289 
GetParams() const290 std::string CJPageRouterNG::GetParams() const
291 {
292     if (pageRouterStack_.empty()) {
293         LOGE("fail to get page param due to stack is null");
294         return "";
295     }
296     auto pageNode = pageRouterStack_.back().Upgrade();
297     CHECK_NULL_RETURN(pageNode, "");
298     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
299     CHECK_NULL_RETURN(pagePattern, "");
300     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
301     CHECK_NULL_RETURN(pageInfo, "");
302     return pageInfo->GetPageParams();
303 }
304 
GetCurrentPageUrl()305 std::string CJPageRouterNG::GetCurrentPageUrl()
306 {
307     if (pageRouterStack_.empty()) {
308         LOGW("current page stack is empty");
309         return "";
310     }
311     auto pageNode = pageRouterStack_.back().Upgrade();
312     CHECK_NULL_RETURN(pageNode, "");
313     auto pagePattern = pageNode->GetPattern<PagePattern>();
314     CHECK_NULL_RETURN(pagePattern, "");
315     auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
316     CHECK_NULL_RETURN(entryPageInfo, "");
317     return entryPageInfo->GetPagePath();
318 }
319 
FindPageInStack(const std::string & url)320 std::pair<int32_t, RefPtr<FrameNode>> CJPageRouterNG::FindPageInStack(const std::string& url)
321 {
322     auto iter = std::find_if(pageRouterStack_.rbegin(), pageRouterStack_.rend(), [url](const WeakPtr<FrameNode>& item) {
323         auto pageNode = item.Upgrade();
324         CHECK_NULL_RETURN(pageNode, false);
325         auto pagePattern = pageNode->GetPattern<PagePattern>();
326         CHECK_NULL_RETURN(pagePattern, false);
327         auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
328         CHECK_NULL_RETURN(entryPageInfo, false);
329         return entryPageInfo->GetPageUrl() == url;
330     });
331     if (iter == pageRouterStack_.rend()) {
332         return { -1, nullptr };
333     }
334     // Returns to the forward position.
335     return { std::distance(iter, pageRouterStack_.rend()) - 1, iter->Upgrade() };
336 }
337 
StartPush(const RouterPageInfo & target,const std::string & params,RouterMode mode)338 void CJPageRouterNG::StartPush(const RouterPageInfo& target, const std::string& params, RouterMode mode)
339 {
340     ProcessGuard guard(this);
341     if (target.url.empty()) {
342         LOGE("router.Push uri is empty");
343         return;
344     }
345     UpdateSrcPage();
346     if (mode == RouterMode::SINGLE) {
347         auto pageInfo = FindPageInStack(target.url);
348         if (pageInfo.second) {
349             // find page in stack, move postion and update params.
350             MovePageToFront(pageInfo.first, pageInfo.second, params, false);
351             return;
352         }
353     }
354 
355     LoadPage(GenerateNextPageId(), target, params);
356 }
357 
StartReplace(const RouterPageInfo & target,const std::string & params,RouterMode mode)358 void CJPageRouterNG::StartReplace(const RouterPageInfo& target, const std::string& params, RouterMode mode)
359 {
360     ProcessGuard guard(this);
361     if (target.url.empty()) {
362         LOGE("router.Push uri is empty");
363         return;
364     }
365     UpdateSrcPage();
366     std::string url = target.url;
367 
368     PopPage("", false, false);
369 
370     if (mode == RouterMode::SINGLE) {
371         auto pageInfo = FindPageInStack(url);
372         if (pageInfo.second) {
373             // find page in stack, move postion and update params.
374             MovePageToFront(pageInfo.first, pageInfo.second, params, false, true, false);
375             return;
376         }
377     }
378 
379     RouterPageInfo info { url };
380     LoadPage(GenerateNextPageId(), info, params, false, false, false);
381 }
382 
StartBack(const RouterPageInfo & target,const std::string & params)383 void CJPageRouterNG::StartBack(const RouterPageInfo& target, const std::string& params)
384 {
385     if (target.url.empty()) {
386         std::string pagePath;
387         size_t pageRouteSize = pageRouterStack_.size();
388         if (pageRouteSize < PAGE_SIZE_TWO) {
389             LOGI("router stack is only one, back to desktop");
390             ExitToDesktop();
391             return;
392         }
393         UpdateSrcPage();
394         PopPage(params, true, true);
395         return;
396     }
397     UpdateSrcPage();
398     std::string url = target.url;
399     auto pageInfo = FindPageInStack(url);
400     if (pageInfo.second) {
401         // find page in stack, pop to specified index.
402         PopPageToIndex(pageInfo.first, params, true, true);
403         return;
404     }
405     LOGI("fail to find specified page to pop");
406 }
407 
BackCheckAlert(const RouterPageInfo & target,const std::string & params)408 void CJPageRouterNG::BackCheckAlert(const RouterPageInfo& target, const std::string& params)
409 {
410     ProcessGuard guard(this);
411     if (pageRouterStack_.empty()) {
412         LOGI("page route stack is empty");
413         return;
414     }
415     auto currentPage = pageRouterStack_.back().Upgrade();
416     CHECK_NULL_VOID(currentPage);
417     auto pagePattern = currentPage->GetPattern<PagePattern>();
418     CHECK_NULL_VOID(pagePattern);
419     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
420     CHECK_NULL_VOID(pageInfo);
421     if (pageInfo->GetAlertCallback()) {
422         ngBackUri_ = target;
423         backParam_ = params;
424 
425         auto pipelineContext = NG::PipelineContext::GetCurrentContext();
426         auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
427         CHECK_NULL_VOID(overlayManager);
428         overlayManager->ShowDialog(
429             pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
430         return;
431     }
432 
433     StartBack(target, params);
434 }
435 
LoadPage(int32_t pageId,const RouterPageInfo & target,const std::string & params,bool isRestore,bool needHideLast,bool needTransition)436 void CJPageRouterNG::LoadPage(int32_t pageId, const RouterPageInfo& target, const std::string& params, bool isRestore,
437     bool needHideLast, bool needTransition)
438 {
439     LOGI("PageRouterManager LoadPage[%{public}d]: %{public}s.", pageId, target.url.c_str());
440 
441     auto pipeline = GetCurrentPipeline(false);
442     CHECK_NULL_VOID(pipeline);
443     if (!pipeline->GetStageManager()) {
444         LOGE("StageManager is null, waiting...");
445         auto frontend = frontend_.Upgrade();
446         CHECK_NULL_VOID(frontend);
447         auto taskExecutor = frontend->GetTaskExecutor();
448         CHECK_NULL_VOID(taskExecutor);
449         taskExecutor->PostTask(
450             [weak = WeakClaim(this), pageId, target, params, isRestore, needHideLast, needTransition] {
451                 auto self = weak.Upgrade();
452                 CHECK_NULL_VOID(self);
453                 self->LoadPage(pageId, target, params, isRestore, needHideLast, needTransition);
454             },
455             TaskExecutor::TaskType::UI, "CJLoadPage");
456         return;
457     }
458 
459     auto entryPageInfo = AceType::MakeRefPtr<NG::EntryPageInfo>(pageId, target.url, target.path, params);
460     auto pagePattern = AceType::MakeRefPtr<NG::PagePattern>(entryPageInfo);
461     auto pageNode = NG::FrameNode::CreateFrameNode("page", ElementRegister::GetInstance()->MakeUniqueId(), pagePattern);
462     pageNode->SetHostPageId(pageId);
463 
464     pageRouterStack_.emplace_back(pageNode);
465 
466     if (!target.url.empty() && !CJRuntimeDelegate::GetInstance()->LoadAppEntry(target.url)) {
467         LOGE("Run CJ Page fail: %{public}s", target.url.c_str());
468         if (target.callback != nullptr) {
469             target.callback(ERROR_CODE_URI_ERROR);
470         }
471         pageRouterStack_.pop_back();
472         return;
473     }
474 
475     if (!OnPageReady(pageNode, needHideLast, needTransition)) {
476         LOGE("fail to mount page");
477         pageRouterStack_.pop_back();
478         return;
479     }
480     LOGI("CJPageRouter LoadPage[%{public}d]: %{public}s. success", pageId, target.url.c_str());
481 }
482 
MovePageToFront(int32_t index,const RefPtr<FrameNode> & pageNode,const std::string & params,bool needHideLast,bool forceShowCurrent,bool needTransition)483 void CJPageRouterNG::MovePageToFront(int32_t index, const RefPtr<FrameNode>& pageNode, const std::string& params,
484     bool needHideLast, bool forceShowCurrent, bool needTransition)
485 {
486     LOGD("MovePageToFront to index: %{public}d", index);
487     // update param first.
488     CHECK_NULL_VOID(pageNode);
489     auto pagePattern = pageNode->GetPattern<PagePattern>();
490     CHECK_NULL_VOID(pagePattern);
491     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
492     CHECK_NULL_VOID(pageInfo);
493 
494     if (index == static_cast<int32_t>(pageRouterStack_.size() - 1)) {
495         LOGD("already on the top");
496         if (!params.empty()) {
497             pageInfo->ReplacePageParams(params);
498         }
499         if (forceShowCurrent) {
500             StageManager::FirePageShow(pageNode, PageTransitionType::NONE);
501         }
502         return;
503     }
504     CHECK_NULL_VOID(pageNode);
505     auto currentObj = Container::Current();
506     CHECK_NULL_VOID(currentObj);
507     auto pipeline = currentObj->GetPipelineContext();
508     CHECK_NULL_VOID(pipeline);
509     auto context = DynamicCast<NG::PipelineContext>(pipeline);
510     auto stageManager = context ? context->GetStageManager() : nullptr;
511     CHECK_NULL_VOID(stageManager);
512 
513     // clean pageNode on index position.
514     auto iter = pageRouterStack_.begin();
515     std::advance(iter, index);
516     auto last = pageRouterStack_.erase(iter);
517     // push pageNode to top.
518     pageRouterStack_.emplace_back(pageNode);
519     std::string tempParam;
520     if (!params.empty()) {
521         tempParam = pageInfo->ReplacePageParams(params);
522     }
523     if (!stageManager->MovePageToFront(pageNode, needHideLast, needTransition)) {
524         LOGE("fail to move page to front");
525         // restore position and param.
526         pageRouterStack_.pop_back();
527         pageRouterStack_.insert(last, pageNode);
528         if (!tempParam.empty()) {
529             pageInfo->ReplacePageParams(tempParam);
530         }
531     }
532 }
533 
PopPage(const std::string & params,bool needShowNext,bool needTransition)534 void CJPageRouterNG::PopPage(const std::string& params, bool needShowNext, bool needTransition)
535 {
536     if (pageRouterStack_.empty() || viewStack_.empty()) {
537         LOGE("page router stack size is illegal.");
538         return;
539     }
540     if (needShowNext && (pageRouterStack_.size() == 1)) {
541         LOGE("page router stack size is only one, can not show next.");
542         return;
543     }
544     auto topNode = pageRouterStack_.back();
545     auto topView = viewStack_.back();
546     pageRouterStack_.pop_back();
547     viewStack_.pop_back();
548     if (params.empty()) {
549         if (!OnPopPage(needShowNext, needTransition)) {
550             LOGE("fail to pop page.");
551             pageRouterStack_.emplace_back(topNode);
552             viewStack_.emplace_back(topView);
553         }
554         return;
555     }
556 
557     // update param first.
558     auto nextNode = pageRouterStack_.back().Upgrade();
559     CHECK_NULL_VOID(nextNode);
560     auto pagePattern = nextNode->GetPattern<PagePattern>();
561     CHECK_NULL_VOID(pagePattern);
562     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
563     CHECK_NULL_VOID(pageInfo);
564     auto temp = pageInfo->ReplacePageParams(params);
565 
566     if (OnPopPage(needShowNext, needTransition)) {
567         return;
568     }
569     LOGE("fail to pop page");
570     // restore stack and pageParam.
571     pageRouterStack_.emplace_back(topNode);
572     viewStack_.emplace_back(topView);
573     pageInfo->ReplacePageParams(temp);
574 }
575 
PopPageToIndex(int32_t index,const std::string & params,bool needShowNext,bool needTransition)576 void CJPageRouterNG::PopPageToIndex(int32_t index, const std::string& params, bool needShowNext, bool needTransition)
577 {
578     LOGD("PopPageToIndex to index: %{public}d", index);
579     std::list<WeakPtr<FrameNode>> temp;
580     std::swap(temp, pageRouterStack_);
581     auto iter = temp.begin();
582     for (int32_t current = 0; current <= index; ++current) {
583         pageRouterStack_.emplace_back(*iter);
584         iter++;
585     }
586     if (params.empty()) {
587         if (!OnPopPageToIndex(index, needShowNext, needTransition)) {
588             LOGE("fail to pop page to index.");
589             std::swap(temp, pageRouterStack_);
590         }
591         return;
592     }
593 
594     // update param first.
595     auto nextNode = pageRouterStack_.back().Upgrade();
596     CHECK_NULL_VOID(nextNode);
597     auto pagePattern = nextNode->GetPattern<PagePattern>();
598     CHECK_NULL_VOID(pagePattern);
599     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
600     CHECK_NULL_VOID(pageInfo);
601     auto tempParam = pageInfo->ReplacePageParams(params);
602 
603     if (OnPopPageToIndex(index, needShowNext, needTransition)) {
604         return;
605     }
606     LOGE("fail to pop page to index");
607     // restore stack and pageParam.
608     std::swap(temp, pageRouterStack_);
609     pageInfo->ReplacePageParams(tempParam);
610 }
611 
GetCurrentPipeline(bool isCardRouter,uint64_t cardId)612 RefPtr<NG::PipelineContext> CJPageRouterNG::GetCurrentPipeline(bool isCardRouter, uint64_t cardId)
613 {
614     auto currentObj = Container::Current();
615     CHECK_NULL_RETURN(currentObj, nullptr);
616     RefPtr<PipelineBase> pipeline;
617     if (isCardRouter) {
618         auto weak = currentObj->GetCardPipeline(cardId);
619         pipeline = weak.Upgrade();
620         CHECK_NULL_RETURN(pipeline, nullptr);
621     } else {
622         pipeline = currentObj->GetPipelineContext();
623         CHECK_NULL_RETURN(pipeline, nullptr);
624     }
625 
626     return DynamicCast<NG::PipelineContext>(pipeline);
627 }
628 
OnPageReady(const RefPtr<FrameNode> & pageNode,bool needHideLast,bool needTransition,bool isCardRouter,uint64_t cardId)629 bool CJPageRouterNG::OnPageReady(
630     const RefPtr<FrameNode>& pageNode, bool needHideLast, bool needTransition, bool isCardRouter, uint64_t cardId)
631 {
632     auto context = GetCurrentPipeline(isCardRouter, cardId);
633     if (!context) {
634         LOGE("fail to push page due to pipeline context is not NG");
635         return false;
636     }
637     auto stageManager = context->GetStageManager();
638     if (!stageManager) {
639         LOGE("fail to push page due to stage manager is nullptr");
640         return false;
641     }
642     return stageManager->PushPage(pageNode, needHideLast, needTransition);
643 }
644 
OnPopPage(bool needShowNext,bool needTransition)645 bool CJPageRouterNG::OnPopPage(bool needShowNext, bool needTransition)
646 {
647     auto currentObj = Container::Current();
648     CHECK_NULL_RETURN(currentObj, false);
649     auto pipeline = currentObj->GetPipelineContext();
650     CHECK_NULL_RETURN(pipeline, false);
651     auto context = DynamicCast<NG::PipelineContext>(pipeline);
652     auto stageManager = context ? context->GetStageManager() : nullptr;
653     if (stageManager) {
654         auto inPageNode = GetCurrentPageNode();
655         return stageManager->PopPage(inPageNode, needShowNext, needTransition);
656     }
657     LOGE("fail to pop page due to stage manager is nullptr");
658     return false;
659 }
660 
OnPopPageToIndex(int32_t index,bool needShowNext,bool needTransition)661 bool CJPageRouterNG::OnPopPageToIndex(int32_t index, bool needShowNext, bool needTransition)
662 {
663     auto currentObj = Container::Current();
664     CHECK_NULL_RETURN(currentObj, false);
665     auto pipeline = currentObj->GetPipelineContext();
666     CHECK_NULL_RETURN(pipeline, false);
667     auto context = DynamicCast<NG::PipelineContext>(pipeline);
668     auto stageManager = context ? context->GetStageManager() : nullptr;
669     if (stageManager) {
670         return stageManager->PopPageToIndex(index, needShowNext, needTransition);
671     }
672     LOGE("fail to pop page to index due to stage manager is nullptr");
673     return false;
674 }
675 
OnCleanPageStack()676 bool CJPageRouterNG::OnCleanPageStack()
677 {
678     auto currentObj = Container::Current();
679     CHECK_NULL_RETURN(currentObj, false);
680     auto pipeline = currentObj->GetPipelineContext();
681     CHECK_NULL_RETURN(pipeline, false);
682     auto context = DynamicCast<NG::PipelineContext>(pipeline);
683     auto stageManager = context ? context->GetStageManager() : nullptr;
684     if (stageManager) {
685         return stageManager->CleanPageStack();
686     }
687     LOGE("fail to pop page to index due to stage manager is nullptr");
688     return false;
689 }
690 
FlushReload()691 void CJPageRouterNG::FlushReload()
692 {
693     for (const auto& viewId : viewStack_) {
694         auto view = FFI::FFIData::GetData<NativeView>(viewId);
695         if (view == nullptr) {
696             continue;
697         }
698         view->MarkNeedUpdate();
699     }
700 }
701 
UpdateSrcPage()702 void CJPageRouterNG::UpdateSrcPage()
703 {
704     auto currentObj = Container::Current();
705     CHECK_NULL_VOID(currentObj);
706     auto context = AceType::DynamicCast<NG::PipelineContext>(currentObj->GetPipelineContext());
707     auto stageManager = context->GetStageManager();
708     CHECK_NULL_VOID(stageManager);
709     stageManager->SetSrcPage(GetCurrentPageNode());
710 }
GetState(int32_t & index,std::string & name,std::string & path,std::string & params)711 void CJPageRouterNG::GetState(int32_t& index, std::string& name, std::string& path, std::string& params)
712 {
713     if (pageRouterStack_.empty()) {
714         LOGE("fail to get page state due to stack is null");
715         return;
716     }
717     index = static_cast<int32_t>(pageRouterStack_.size());
718     auto pageNode = pageRouterStack_.back().Upgrade();
719     CHECK_NULL_VOID(pageNode);
720     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
721     CHECK_NULL_VOID(pagePattern);
722     auto pageInfo = pagePattern->GetPageInfo();
723     CHECK_NULL_VOID(pageInfo);
724     name = pageInfo->GetPageUrl();
725     path = pageInfo->GetPagePath();
726     params = GetParams();
727 }
FindPageByIndex(int32_t & index)728 RefPtr<NG::FrameNode> CJPageRouterNG::FindPageByIndex(int32_t& index)
729 {
730     auto it = pageRouterStack_.begin();
731     std::advance(it, index - 1);
732     return it->Upgrade();
733 }
GetStateByIndex(int32_t & index,std::string & name,std::string & path,std::string & params)734 void CJPageRouterNG::GetStateByIndex(int32_t& index, std::string& name, std::string& path, std::string& params)
735 {
736     if (pageRouterStack_.empty() || static_cast<int32_t>(pageRouterStack_.size()) < index) {
737         LOGE("fail to get page state due to stack is null");
738         index = 0;
739         return;
740     }
741     auto pageNode = pageRouterStack_.back().Upgrade();
742     CHECK_NULL_VOID(pageNode);
743     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
744     CHECK_NULL_VOID(pagePattern);
745     auto pageInfo = pagePattern->GetPageInfo();
746     CHECK_NULL_VOID(pageInfo);
747     name = pageInfo->GetPageUrl();
748     path = pageInfo->GetPagePath();
749     params = GetParams();
750 }
CopyStr(const std::string & str)751 static char* CopyStr(const std::string& str)
752 {
753     char* newStr = new (std::nothrow) char[str.length() + 1];
754     if (newStr == nullptr) {
755         return nullptr;
756     }
757 
758     int err = strcpy_s(newStr, str.length() + 1, str.c_str());
759     if (err != 0) {
760         delete[] newStr;
761         return nullptr;
762     }
763 
764     return newStr;
765 }
GetStateByUrl(const std::string & url)766 std::vector<CJPageRouterAbstract::RouterState> CJPageRouterNG::GetStateByUrl(const std::string& url)
767 {
768     std::vector<CJPageRouterAbstract::RouterState> ret;
769     if (pageRouterStack_.empty()) {
770         LOGE("fail to get page state due to stack is null");
771         return ret;
772     }
773     int64_t index = 0;
774     for (auto it = pageRouterStack_.begin(); it != pageRouterStack_.end(); ++it) {
775         std::string name = "";
776         std::string path = "";
777         std::string params = "";
778         auto pageNode = it->Upgrade();
779         if (!pageNode)
780             return ret;
781         auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
782         if (!pagePattern)
783             return ret;
784         auto pageInfo = pagePattern->GetPageInfo();
785         if (!pageInfo)
786             return ret;
787         name = pageInfo->GetPageUrl();
788         if (name == url) {
789             path = pageInfo->GetPagePath();
790             params = GetParams();
791             ret.push_back({ index + 1, CopyStr(name), CopyStr(path), CopyStr(params) });
792         }
793         index++;
794     }
795     return ret;
796 }
StartBackIndex(int32_t & index,const std::string & params)797 void CJPageRouterNG::StartBackIndex(int32_t& index, const std::string& params)
798 {
799     std::string pagePath;
800     int32_t pageRouterSize = static_cast<int32_t>(pageRouterStack_.size());
801     if (pageRouterSize < index) {
802         return;
803     }
804     if (pageRouterSize < PAGE_SIZE_TWO) {
805         LOGI("router stack is only one, back to desktop");
806         ExitToDesktop();
807         return;
808     }
809     UpdateSrcPage();
810     PopPageToIndex(index, params, true, true);
811 }
812 
StartPushPageWithCallback(const RouterPageInfo & target,const std::string & params)813 void CJPageRouterNG::StartPushPageWithCallback(const RouterPageInfo& target, const std::string& params)
814 {
815     ProcessGuard guard(this);
816     if (target.url.empty()) {
817         LOGE("router.Push uri is empty");
818         return;
819     }
820     UpdateSrcPage();
821     if (GetStackSize() >= MAX_ROUTER_STACK_SIZE) {
822         if (target.callback != nullptr) {
823             target.callback(ERROR_CODE_PAGE_STACK_FULL);
824         }
825         return;
826     }
827     if (target.routerMode == RouterMode::SINGLE) {
828         auto pageInfo = FindPageInStack(target.url);
829         if (pageInfo.second) {
830             // find page in stack, move postion and update params.
831             MovePageToFront(pageInfo.first, pageInfo.second, params, false);
832             return;
833         }
834     }
835 
836     LoadPage(GenerateNextPageId(), target, params);
837 }
StartReplacePageWithCallback(const RouterPageInfo & target,const std::string & params)838 void CJPageRouterNG::StartReplacePageWithCallback(const RouterPageInfo& target, const std::string& params)
839 {
840     ProcessGuard guard(this);
841     if (target.url.empty()) {
842         LOGE("router.Push uri is empty");
843         return;
844     }
845     UpdateSrcPage();
846     std::string url = target.url;
847     PopPage("", false, false);
848 
849     if (target.routerMode == RouterMode::SINGLE) {
850         auto pageInfo = FindPageInStack(url);
851         if (pageInfo.second) {
852             // find page in stack, move postion and update params.
853             MovePageToFront(pageInfo.first, pageInfo.second, params, false, true, true);
854             return;
855         }
856     }
857 
858     LoadPage(GenerateNextPageId(), target, params, false, false, false);
859 }
BackCheckAlertIndex(int32_t index,const std::string & params)860 void CJPageRouterNG::BackCheckAlertIndex(int32_t index, const std::string& params)
861 {
862     ProcessGuard guard(this);
863     if (pageRouterStack_.empty()) {
864         LOGI("page route stack is empty");
865         return;
866     }
867     if (static_cast<int32_t>(pageRouterStack_.size()) < index) {
868         LOGI("index is invalid");
869         return;
870     }
871     auto currentPage = pageRouterStack_.back().Upgrade();
872     CHECK_NULL_VOID(currentPage);
873     auto pagePattern = currentPage->GetPattern<PagePattern>();
874     CHECK_NULL_VOID(pagePattern);
875     if (pagePattern->OnBackPressed()) {
876         return;
877     }
878 
879     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
880     CHECK_NULL_VOID(pageInfo);
881     if (pageInfo->GetAlertCallback()) {
882         ngBackIndex_ = index;
883         backParam_ = params;
884 
885         auto pipelineContext = NG::PipelineContext::GetCurrentContext();
886         auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
887         CHECK_NULL_VOID(overlayManager);
888         overlayManager->ShowDialog(
889             pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
890         return;
891     }
892 
893     StartBackIndex(index, params);
894 }
895 
896 } // namespace OHOS::Ace::Framework
897