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 "base/i18n/localization.h"
19 #include "bridge/cj_frontend/runtime/cj_runtime_delegate.h"
20 #include "bridge/cj_frontend/frontend/cj_frontend_abstract.h"
21 #include "bridge/cj_frontend/frontend/cj_page_loader.h"
22 #include "bridge/declarative_frontend/ng/entry_page_info.h"
23 #include "bridge/js_frontend/frontend_delegate.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/pattern/stage/page_pattern.h"
26 #include "core/components_v2/inspector/inspector_constants.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28
29 using namespace OHOS::Ace::NG;
30
31 namespace OHOS::Ace::Framework {
32 constexpr int PAGE_SIZE_TWO = 2;
33
UpdateCjPageLifeCycleFuncs(RefPtr<NG::PagePattern> pagePattern,OHOS::wptr<NativeView> weakView,RefPtr<NG::FrameNode> pageNode)34 void UpdateCjPageLifeCycleFuncs(
35 RefPtr<NG::PagePattern> pagePattern, OHOS::wptr<NativeView> weakView, RefPtr<NG::FrameNode> pageNode)
36 {
37 CHECK_NULL_VOID(pagePattern);
38 pagePattern->SetOnPageShow([weakView]() {
39 auto view = weakView.promote();
40 CHECK_NULL_VOID(view);
41 view->FireOnShow();
42 });
43 pagePattern->SetOnPageHide([weakView]() {
44 auto view = weakView.promote();
45 CHECK_NULL_VOID(view);
46 view->FireOnHide();
47 });
48 pagePattern->SetOnBackPressed([weakView]() {
49 auto view = weakView.promote();
50 CHECK_NULL_RETURN(view, false);
51 return view->FireOnBackPress();
52 });
53 pagePattern->SetPageTransitionFunc([weakView, weakPage = WeakPtr<NG::FrameNode>(pageNode)]() {
54 auto view = weakView.promote();
55 CHECK_NULL_VOID(view);
56 NG::ScopedViewStackProcessor scopedViewStackProcessor;
57 NG::ViewStackProcessor::GetInstance()->SetPageNode(weakPage.Upgrade());
58 view->FireOnTransition();
59 NG::ViewStackProcessor::GetInstance()->SetPageNode(nullptr);
60 });
61 }
62
LoadNativeViewNG(NativeView * view)63 bool LoadNativeViewNG(NativeView* view)
64 {
65 LOGI("LoadNativeView start");
66 auto currentObj = Container::Current();
67 if (!currentObj) {
68 LOGE("loadCJView fail, Container is null");
69 return false;
70 }
71 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(currentObj->GetFrontend());
72 if (!frontend) {
73 LOGE("loadCJView fail, frontend is not CJFrontendAbstract");
74 return false;
75 }
76 auto pageRouterManager = AceType::DynamicCast<CJPageRouterNG>(frontend->GetPageRouterManager());
77 if (!pageRouterManager) {
78 LOGE("loadCJView fail, pageRouter not exist");
79 return false;
80 }
81 auto pageNode = pageRouterManager->GetCurrentPageNode();
82 if (!pageNode) {
83 LOGE("loadCJView fail, page node not exist");
84 return false;
85 }
86 Container::SetCurrentUsePartialUpdate(!view->IsFullUpdate());
87 if (!pageNode->GetChildren().empty()) {
88 LOGI("the page has view already, start cleanup");
89 auto oldChild = AceType::DynamicCast<NG::CustomNode>(pageNode->GetChildren().front());
90 if (oldChild) {
91 oldChild->Reset();
92 }
93 pageNode->Clean();
94 }
95 auto pageRootNode = AceType::DynamicCast<NG::UINode>(view->CreateUI());
96 if (!pageRootNode) {
97 LOGE("loadCJView fail, created rootNode is null");
98 return false;
99 }
100 pageRootNode->MountToParent(pageNode);
101 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
102 CHECK_NULL_RETURN(pagePattern, false);
103 OHOS::wptr<NativeView> weak = view;
104 view->SetRenderDoneCallback([pagePattern] {
105 pagePattern->MarkRenderDone();
106 });
107 UpdateCjPageLifeCycleFuncs(pagePattern, weak, pageNode);
108 pageRouterManager->AddView(view->GetID());
109 LOGI("OHOSAceFrameworkNGLoadCJView end.");
110 return true;
111 }
112
113 namespace {
ExitToDesktop()114 void ExitToDesktop()
115 {
116 auto currentObj = Container::Current();
117 CHECK_NULL_VOID(currentObj);
118 auto taskExecutor = currentObj->GetTaskExecutor();
119 CHECK_NULL_VOID(taskExecutor);
120 taskExecutor->PostTask(
121 [] {
122 auto pipeline = NG::PipelineContext::GetCurrentContext();
123 CHECK_NULL_VOID(pipeline);
124 pipeline->Finish(false);
125 },
126 TaskExecutor::TaskType::UI, "CJExitToDesktop");
127 }
128 } // namespace
129
OnShowCurrent()130 void CJPageRouterNG::OnShowCurrent()
131 {
132 auto pageNode = GetCurrentPageNode();
133 if (!pageNode) {
134 LOGE("CJFrontendNG::OnShow no current page");
135 return;
136 }
137 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
138 if (!pagePattern) {
139 LOGE("CJFrontendNG::OnShow current page has no pattern");
140 return;
141 }
142 pagePattern->OnShow();
143 }
144
OnHideCurrent()145 void CJPageRouterNG::OnHideCurrent()
146 {
147 auto pageNode = GetCurrentPageNode();
148 if (!pageNode) {
149 LOGE("CJFrontendNG::OnHide no current page");
150 return;
151 }
152 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
153 if (!pagePattern) {
154 LOGE("CJFrontendNG::OnHide current page has no pattern");
155 return;
156 }
157 pagePattern->OnHide();
158 }
159
PopWithExitCheck()160 bool CJPageRouterNG::PopWithExitCheck()
161 {
162 auto pageNode = GetCurrentPageNode();
163 CHECK_NULL_RETURN(pageNode, false);
164 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
165 CHECK_NULL_RETURN(pagePattern, false);
166 if (pagePattern->OnBackPressed()) {
167 return true;
168 }
169 return Pop();
170 }
171
AllowPopLastPage()172 bool CJPageRouterNG::AllowPopLastPage()
173 {
174 auto currentPage = pageRouterStack_.back().Upgrade();
175 CHECK_NULL_RETURN(currentPage, true);
176 auto pagePattern = currentPage->GetPattern<PagePattern>();
177 CHECK_NULL_RETURN(pagePattern, true);
178 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
179 CHECK_NULL_RETURN(pageInfo, true);
180 if (pageInfo->GetAlertCallback()) {
181 auto pipelineContext = NG::PipelineContext::GetCurrentContext();
182 auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
183 CHECK_NULL_RETURN(overlayManager, true);
184 overlayManager->ShowDialog(
185 pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
186 return false;
187 }
188
189 return true;
190 }
191
EnableAlertBeforeBackPage(const std::string & message,std::function<void (int32_t)> callback)192 void CJPageRouterNG::EnableAlertBeforeBackPage(const std::string& message, std::function<void(int32_t)> callback)
193 {
194 auto currentPage = pageRouterStack_.back().Upgrade();
195 CHECK_NULL_VOID(currentPage);
196 auto pagePattern = currentPage->GetPattern<PagePattern>();
197 CHECK_NULL_VOID(pagePattern);
198 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
199 CHECK_NULL_VOID(pageInfo);
200 ClearAlertCallback(pageInfo);
201
202 DialogProperties dialogProperties = {
203 .content = message,
204 .autoCancel = false,
205 .buttons = { { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"), .textColor = "" },
206 { .text = Localization::GetInstance()->GetEntryLetters("common.ok"), .textColor = "" } },
207 .onSuccess =
208 [weak = AceType::WeakClaim(this), callback](int32_t successType, int32_t successIndex) {
209 LOGI("showDialog successType: %{public}d, successIndex: %{public}d", successType, successIndex);
210 if (!successType) {
211 callback(successIndex);
212 if (successIndex) {
213 auto router = weak.Upgrade();
214 CHECK_NULL_VOID(router);
215 router->StartBack(router->ngBackUri_, router->backParam_);
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 std::list<WeakPtr<FrameNode>> temp;
255 std::swap(temp, pageRouterStack_);
256 pageRouterStack_.emplace_back(temp.back());
257 if (!OnCleanPageStack()) {
258 LOGE("fail to clean page");
259 std::swap(temp, pageRouterStack_);
260 }
261 }
262
StartPop()263 bool CJPageRouterNG::StartPop()
264 {
265 ProcessGuard guard(this);
266 if (pageRouterStack_.size() <= 1 || viewStack_.size() <= 1) {
267 // the last page.
268 return false;
269 }
270 auto topNode = pageRouterStack_.back();
271 auto topView = viewStack_.back();
272 pageRouterStack_.pop_back();
273 viewStack_.pop_back();
274 if (!OnPopPage(true, true)) {
275 LOGE("fail to pop page.");
276 pageRouterStack_.emplace_back(topNode);
277 viewStack_.emplace_back(topView);
278 return false;
279 }
280 return true;
281 }
282
GetStackSize() const283 int32_t CJPageRouterNG::GetStackSize() const
284 {
285 return static_cast<int32_t>(pageRouterStack_.size());
286 }
287
GetState(int32_t & index,std::string & name,std::string & path)288 void CJPageRouterNG::GetState(int32_t& index, std::string& name, std::string& path)
289 {
290 if (pageRouterStack_.empty()) {
291 LOGE("fail to get page state due to stack is null");
292 return;
293 }
294 index = static_cast<int32_t>(pageRouterStack_.size());
295 auto pageNode = pageRouterStack_.back().Upgrade();
296 CHECK_NULL_VOID(pageNode);
297 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
298 CHECK_NULL_VOID(pagePattern);
299 auto pageInfo = pagePattern->GetPageInfo();
300 CHECK_NULL_VOID(pageInfo);
301 name = pageInfo->GetPageUrl();
302 path = pageInfo->GetPagePath();
303 }
304
GetParams() const305 std::string CJPageRouterNG::GetParams() const
306 {
307 if (pageRouterStack_.empty()) {
308 LOGE("fail to get page param due to stack is null");
309 return "";
310 }
311 auto pageNode = pageRouterStack_.back().Upgrade();
312 CHECK_NULL_RETURN(pageNode, "");
313 auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
314 CHECK_NULL_RETURN(pagePattern, "");
315 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
316 CHECK_NULL_RETURN(pageInfo, "");
317 return pageInfo->GetPageParams();
318 }
319
GetCurrentPageUrl()320 std::string CJPageRouterNG::GetCurrentPageUrl()
321 {
322 if (pageRouterStack_.empty()) {
323 LOGW("current page stack is empty");
324 return "";
325 }
326 auto pageNode = pageRouterStack_.back().Upgrade();
327 CHECK_NULL_RETURN(pageNode, "");
328 auto pagePattern = pageNode->GetPattern<PagePattern>();
329 CHECK_NULL_RETURN(pagePattern, "");
330 auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
331 CHECK_NULL_RETURN(entryPageInfo, "");
332 return entryPageInfo->GetPagePath();
333 }
334
FindPageInStack(const std::string & url)335 std::pair<int32_t, RefPtr<FrameNode>> CJPageRouterNG::FindPageInStack(const std::string& url)
336 {
337 auto iter = std::find_if(pageRouterStack_.rbegin(), pageRouterStack_.rend(), [url](const WeakPtr<FrameNode>& item) {
338 auto pageNode = item.Upgrade();
339 CHECK_NULL_RETURN(pageNode, false);
340 auto pagePattern = pageNode->GetPattern<PagePattern>();
341 CHECK_NULL_RETURN(pagePattern, false);
342 auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
343 CHECK_NULL_RETURN(entryPageInfo, false);
344 return entryPageInfo->GetPageUrl() == url;
345 });
346 if (iter == pageRouterStack_.rend()) {
347 return { -1, nullptr };
348 }
349 // Returns to the forward position.
350 return { std::distance(iter, pageRouterStack_.rend()) - 1, iter->Upgrade() };
351 }
352
StartPush(const RouterPageInfo & target,const std::string & params,RouterMode mode)353 void CJPageRouterNG::StartPush(const RouterPageInfo& target, const std::string& params, RouterMode mode)
354 {
355 ProcessGuard guard(this);
356 if (target.url.empty()) {
357 LOGE("router.Push uri is empty");
358 return;
359 }
360
361 if (mode == RouterMode::SINGLE) {
362 auto pageInfo = FindPageInStack(target.url);
363 if (pageInfo.second) {
364 // find page in stack, move postion and update params.
365 MovePageToFront(pageInfo.first, pageInfo.second, params, false);
366 return;
367 }
368 }
369
370 LoadPage(GenerateNextPageId(), target, params);
371 }
372
StartReplace(const RouterPageInfo & target,const std::string & params,RouterMode mode)373 void CJPageRouterNG::StartReplace(const RouterPageInfo& target, const std::string& params, RouterMode mode)
374 {
375 ProcessGuard guard(this);
376 if (target.url.empty()) {
377 LOGE("router.Push uri is empty");
378 return;
379 }
380 std::string url = target.url;
381
382 PopPage("", false, false);
383
384 if (mode == RouterMode::SINGLE) {
385 auto pageInfo = FindPageInStack(url);
386 if (pageInfo.second) {
387 // find page in stack, move postion and update params.
388 MovePageToFront(pageInfo.first, pageInfo.second, params, false, true, false);
389 return;
390 }
391 }
392
393 RouterPageInfo info { url };
394 LoadPage(GenerateNextPageId(), info, params, false, false, false);
395 }
396
StartBack(const RouterPageInfo & target,const std::string & params)397 void CJPageRouterNG::StartBack(const RouterPageInfo& target, const std::string& params)
398 {
399 if (target.url.empty()) {
400 std::string pagePath;
401 size_t pageRouteSize = pageRouterStack_.size();
402 if (pageRouteSize < PAGE_SIZE_TWO) {
403 LOGI("router stack is only one, back to desktop");
404 ExitToDesktop();
405 return;
406 }
407 PopPage(params, true, true);
408 return;
409 }
410 std::string url = target.url;
411 auto pageInfo = FindPageInStack(url);
412 if (pageInfo.second) {
413 // find page in stack, pop to specified index.
414 PopPageToIndex(pageInfo.first, params, true, true);
415 return;
416 }
417 LOGI("fail to find specified page to pop");
418 }
419
BackCheckAlert(const RouterPageInfo & target,const std::string & params)420 void CJPageRouterNG::BackCheckAlert(const RouterPageInfo& target, const std::string& params)
421 {
422 ProcessGuard guard(this);
423 if (pageRouterStack_.empty()) {
424 LOGI("page route stack is empty");
425 return;
426 }
427 auto currentPage = pageRouterStack_.back().Upgrade();
428 CHECK_NULL_VOID(currentPage);
429 auto pagePattern = currentPage->GetPattern<PagePattern>();
430 CHECK_NULL_VOID(pagePattern);
431 if (pagePattern->OnBackPressed()) {
432 return;
433 }
434
435 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
436 CHECK_NULL_VOID(pageInfo);
437 if (pageInfo->GetAlertCallback()) {
438 ngBackUri_ = target;
439 backParam_ = params;
440
441 auto pipelineContext = NG::PipelineContext::GetCurrentContext();
442 auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
443 CHECK_NULL_VOID(overlayManager);
444 overlayManager->ShowDialog(
445 pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
446 return;
447 }
448
449 StartBack(target, params);
450 }
451
LoadPage(int32_t pageId,const RouterPageInfo & target,const std::string & params,bool isRestore,bool needHideLast,bool needTransition)452 void CJPageRouterNG::LoadPage(int32_t pageId, const RouterPageInfo& target, const std::string& params, bool isRestore,
453 bool needHideLast, bool needTransition)
454 {
455 LOGI("PageRouterManager LoadPage[%{public}d]: %{public}s.", pageId, target.url.c_str());
456
457 auto pipeline = GetCurrentPipeline(false);
458 CHECK_NULL_VOID(pipeline);
459 if (!pipeline->GetStageManager()) {
460 LOGE("StageManager is null, waiting...");
461 auto frontend = frontend_.Upgrade();
462 CHECK_NULL_VOID(frontend);
463 auto taskExecutor = frontend->GetTaskExecutor();
464 CHECK_NULL_VOID(taskExecutor);
465 taskExecutor->PostTask([weak = WeakClaim(this), pageId, target, params, isRestore,
466 needHideLast, needTransition] {
467 auto self = weak.Upgrade();
468 CHECK_NULL_VOID(self);
469 self->LoadPage(pageId, target, params, isRestore, needHideLast, needTransition);
470 }, TaskExecutor::TaskType::UI, "CJLoadPage");
471 return;
472 }
473
474 auto entryPageInfo = AceType::MakeRefPtr<NG::EntryPageInfo>(pageId, target.url, target.path, params);
475 auto pagePattern = AceType::MakeRefPtr<NG::PagePattern>(entryPageInfo);
476 auto pageNode =
477 NG::FrameNode::CreateFrameNode("page", ElementRegister::GetInstance()->MakeUniqueId(), pagePattern);
478 pageNode->SetHostPageId(pageId);
479
480 pageRouterStack_.emplace_back(pageNode);
481
482 if (!CJRuntimeDelegate::GetInstance()->LoadAppEntry(target.url)) {
483 LOGE("Run CJ Page fail: %{public}s", target.url.c_str());
484 pageRouterStack_.pop_back();
485 return;
486 }
487
488 if (!OnPageReady(pageNode, needHideLast, needTransition)) {
489 LOGE("fail to mount page");
490 pageRouterStack_.pop_back();
491 return;
492 }
493 LOGI("CJPageRouter LoadPage[%{public}d]: %{public}s. success", pageId, target.url.c_str());
494 }
495
MovePageToFront(int32_t index,const RefPtr<FrameNode> & pageNode,const std::string & params,bool needHideLast,bool forceShowCurrent,bool needTransition)496 void CJPageRouterNG::MovePageToFront(int32_t index, const RefPtr<FrameNode>& pageNode, const std::string& params,
497 bool needHideLast, bool forceShowCurrent, bool needTransition)
498 {
499 LOGD("MovePageToFront to index: %{public}d", index);
500 // update param first.
501 CHECK_NULL_VOID(pageNode);
502 auto pagePattern = pageNode->GetPattern<PagePattern>();
503 CHECK_NULL_VOID(pagePattern);
504 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
505 CHECK_NULL_VOID(pageInfo);
506
507 if (index == static_cast<int32_t>(pageRouterStack_.size() - 1)) {
508 LOGD("already on the top");
509 if (!params.empty()) {
510 pageInfo->ReplacePageParams(params);
511 }
512 if (forceShowCurrent) {
513 StageManager::FirePageShow(pageNode, PageTransitionType::NONE);
514 }
515 return;
516 }
517 CHECK_NULL_VOID(pageNode);
518 auto currentObj = Container::Current();
519 CHECK_NULL_VOID(currentObj);
520 auto pipeline = currentObj->GetPipelineContext();
521 CHECK_NULL_VOID(pipeline);
522 auto context = DynamicCast<NG::PipelineContext>(pipeline);
523 auto stageManager = context ? context->GetStageManager() : nullptr;
524 CHECK_NULL_VOID(stageManager);
525
526 // clean pageNode on index position.
527 auto iter = pageRouterStack_.begin();
528 std::advance(iter, index);
529 auto last = pageRouterStack_.erase(iter);
530 // push pageNode to top.
531 pageRouterStack_.emplace_back(pageNode);
532 std::string tempParam;
533 if (!params.empty()) {
534 tempParam = pageInfo->ReplacePageParams(params);
535 }
536 if (!stageManager->MovePageToFront(pageNode, needHideLast, needTransition)) {
537 LOGE("fail to move page to front");
538 // restore position and param.
539 pageRouterStack_.pop_back();
540 pageRouterStack_.insert(last, pageNode);
541 if (!tempParam.empty()) {
542 pageInfo->ReplacePageParams(tempParam);
543 }
544 }
545 }
546
PopPage(const std::string & params,bool needShowNext,bool needTransition)547 void CJPageRouterNG::PopPage(const std::string& params, bool needShowNext, bool needTransition)
548 {
549 if (pageRouterStack_.empty() || viewStack_.empty()) {
550 LOGE("page router stack size is illegal.");
551 return;
552 }
553 if (needShowNext && (pageRouterStack_.size() == 1)) {
554 LOGE("page router stack size is only one, can not show next.");
555 return;
556 }
557 auto topNode = pageRouterStack_.back();
558 auto topView = viewStack_.back();
559 pageRouterStack_.pop_back();
560 viewStack_.pop_back();
561 if (params.empty()) {
562 if (!OnPopPage(needShowNext, needTransition)) {
563 LOGE("fail to pop page.");
564 pageRouterStack_.emplace_back(topNode);
565 viewStack_.emplace_back(topView);
566 }
567 return;
568 }
569
570 // update param first.
571 auto nextNode = pageRouterStack_.back().Upgrade();
572 CHECK_NULL_VOID(nextNode);
573 auto pagePattern = nextNode->GetPattern<PagePattern>();
574 CHECK_NULL_VOID(pagePattern);
575 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
576 CHECK_NULL_VOID(pageInfo);
577 auto temp = pageInfo->ReplacePageParams(params);
578
579 if (OnPopPage(needShowNext, needTransition)) {
580 return;
581 }
582 LOGE("fail to pop page");
583 // restore stack and pageParam.
584 pageRouterStack_.emplace_back(topNode);
585 viewStack_.emplace_back(topView);
586 pageInfo->ReplacePageParams(temp);
587 }
588
PopPageToIndex(int32_t index,const std::string & params,bool needShowNext,bool needTransition)589 void CJPageRouterNG::PopPageToIndex(int32_t index, const std::string& params, bool needShowNext, bool needTransition)
590 {
591 LOGD("PopPageToIndex to index: %{public}d", index);
592 std::list<WeakPtr<FrameNode>> temp;
593 std::swap(temp, pageRouterStack_);
594 auto iter = temp.begin();
595 for (int32_t current = 0; current <= index; ++current) {
596 pageRouterStack_.emplace_back(*iter);
597 iter++;
598 }
599 if (params.empty()) {
600 if (!OnPopPageToIndex(index, needShowNext, needTransition)) {
601 LOGE("fail to pop page to index.");
602 std::swap(temp, pageRouterStack_);
603 }
604 return;
605 }
606
607 // update param first.
608 auto nextNode = pageRouterStack_.back().Upgrade();
609 CHECK_NULL_VOID(nextNode);
610 auto pagePattern = nextNode->GetPattern<PagePattern>();
611 CHECK_NULL_VOID(pagePattern);
612 auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
613 CHECK_NULL_VOID(pageInfo);
614 auto tempParam = pageInfo->ReplacePageParams(params);
615
616 if (OnPopPageToIndex(index, needShowNext, needTransition)) {
617 return;
618 }
619 LOGE("fail to pop page to index");
620 // restore stack and pageParam.
621 std::swap(temp, pageRouterStack_);
622 pageInfo->ReplacePageParams(tempParam);
623 }
624
GetCurrentPipeline(bool isCardRouter,uint64_t cardId)625 RefPtr<NG::PipelineContext> CJPageRouterNG::GetCurrentPipeline(bool isCardRouter, uint64_t cardId)
626 {
627 auto currentObj = Container::Current();
628 CHECK_NULL_RETURN(currentObj, nullptr);
629 RefPtr<PipelineBase> pipeline;
630 if (isCardRouter) {
631 auto weak = currentObj->GetCardPipeline(cardId);
632 pipeline = weak.Upgrade();
633 CHECK_NULL_RETURN(pipeline, nullptr);
634 } else {
635 pipeline = currentObj->GetPipelineContext();
636 CHECK_NULL_RETURN(pipeline, nullptr);
637 }
638
639 return DynamicCast<NG::PipelineContext>(pipeline);
640 }
641
OnPageReady(const RefPtr<FrameNode> & pageNode,bool needHideLast,bool needTransition,bool isCardRouter,uint64_t cardId)642 bool CJPageRouterNG::OnPageReady(
643 const RefPtr<FrameNode>& pageNode, bool needHideLast, bool needTransition, bool isCardRouter, uint64_t cardId)
644 {
645 auto context = GetCurrentPipeline(isCardRouter, cardId);
646 if (!context) {
647 LOGE("fail to push page due to pipeline context is not NG");
648 return false;
649 }
650 auto stageManager = context->GetStageManager();
651 if (!stageManager) {
652 LOGE("fail to push page due to stage manager is nullptr");
653 return false;
654 }
655 return stageManager->PushPage(pageNode, needHideLast, needTransition);
656 }
657
OnPopPage(bool needShowNext,bool needTransition)658 bool CJPageRouterNG::OnPopPage(bool needShowNext, bool needTransition)
659 {
660 auto currentObj = Container::Current();
661 CHECK_NULL_RETURN(currentObj, false);
662 auto pipeline = currentObj->GetPipelineContext();
663 CHECK_NULL_RETURN(pipeline, false);
664 auto context = DynamicCast<NG::PipelineContext>(pipeline);
665 auto stageManager = context ? context->GetStageManager() : nullptr;
666 if (stageManager) {
667 return stageManager->PopPage(needShowNext, needTransition);
668 }
669 LOGE("fail to pop page due to stage manager is nullptr");
670 return false;
671 }
672
OnPopPageToIndex(int32_t index,bool needShowNext,bool needTransition)673 bool CJPageRouterNG::OnPopPageToIndex(int32_t index, bool needShowNext, bool needTransition)
674 {
675 auto currentObj = Container::Current();
676 CHECK_NULL_RETURN(currentObj, false);
677 auto pipeline = currentObj->GetPipelineContext();
678 CHECK_NULL_RETURN(pipeline, false);
679 auto context = DynamicCast<NG::PipelineContext>(pipeline);
680 auto stageManager = context ? context->GetStageManager() : nullptr;
681 if (stageManager) {
682 return stageManager->PopPageToIndex(index, needShowNext, needTransition);
683 }
684 LOGE("fail to pop page to index due to stage manager is nullptr");
685 return false;
686 }
687
OnCleanPageStack()688 bool CJPageRouterNG::OnCleanPageStack()
689 {
690 auto currentObj = Container::Current();
691 CHECK_NULL_RETURN(currentObj, false);
692 auto pipeline = currentObj->GetPipelineContext();
693 CHECK_NULL_RETURN(pipeline, false);
694 auto context = DynamicCast<NG::PipelineContext>(pipeline);
695 auto stageManager = context ? context->GetStageManager() : nullptr;
696 if (stageManager) {
697 return stageManager->CleanPageStack();
698 }
699 LOGE("fail to pop page to index due to stage manager is nullptr");
700 return false;
701 }
702
FlushReload()703 void CJPageRouterNG::FlushReload()
704 {
705 for (const auto& viewId : viewStack_) {
706 auto view = FFI::FFIData::GetData<NativeView>(viewId);
707 if (view == nullptr) {
708 continue;
709 }
710 view->MarkNeedUpdate();
711 }
712 }
713 } // namespace OHOS::Ace::Framework
714