• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "frameworks/bridge/declarative_frontend/ng/page_router_manager.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <iterator>
21 #include <string>
22 
23 #include "base/i18n/localization.h"
24 #include "base/memory/referenced.h"
25 #include "base/ressched/ressched_report.h"
26 #include "base/utils/utils.h"
27 #include "bridge/common/utils/source_map.h"
28 #include "bridge/common/utils/utils.h"
29 #include "bridge/declarative_frontend/ng/entry_page_info.h"
30 #include "bridge/js_frontend/frontend_delegate.h"
31 #include "core/common/container.h"
32 #include "core/common/thread_checker.h"
33 #include "core/components_ng/base/frame_node.h"
34 #include "core/components_ng/pattern/stage/page_pattern.h"
35 #include "core/components_ng/pattern/stage/stage_manager.h"
36 #include "core/components_v2/inspector/inspector_constants.h"
37 #include "core/pipeline/base/element_register.h"
38 #include "core/pipeline_ng/pipeline_context.h"
39 
40 namespace OHOS::Ace::NG {
41 
42 namespace {
43 
44 constexpr int32_t MAX_ROUTER_STACK_SIZE = 32;
45 
ExitToDesktop()46 void ExitToDesktop()
47 {
48     auto container = Container::Current();
49     CHECK_NULL_VOID(container);
50     auto taskExecutor = container->GetTaskExecutor();
51     CHECK_NULL_VOID(taskExecutor);
52     taskExecutor->PostTask(
53         [] {
54             auto pipeline = PipelineContext::GetCurrentContext();
55             CHECK_NULL_VOID(pipeline);
56             AccessibilityEvent event;
57             event.type = AccessibilityEventType::PAGE_CHANGE;
58             pipeline->SendEventToAccessibility(event);
59             pipeline->Finish(false);
60         },
61         TaskExecutor::TaskType::UI);
62 }
63 
64 } // namespace
65 
LoadOhmUrl(const RouterPageInfo & target)66 void PageRouterManager::LoadOhmUrl(const RouterPageInfo& target)
67 {
68     RouterPageInfo info = target;
69     info.path = info.url + ".js";
70     LOGD("router.Push pagePath = %{private}s", info.url.c_str());
71     RouterOptScope scope(this);
72     LoadPage(GenerateNextPageId(), info);
73 }
74 
RunPage(const std::string & url,const std::string & params)75 void PageRouterManager::RunPage(const std::string& url, const std::string& params)
76 {
77     ACE_SCOPED_TRACE("PageRouterManager::RunPage");
78     CHECK_RUN_ON(JS);
79     RouterPageInfo info { url, params };
80 #if !defined(PREVIEW)
81     if (info.url.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
82         auto container = Container::Current();
83         CHECK_NULL_VOID(container);
84         auto pageUrlChecker = container->GetPageUrlChecker();
85         CHECK_NULL_VOID(pageUrlChecker);
86         auto instanceId = container->GetInstanceId();
87         auto taskExecutor = container->GetTaskExecutor();
88         CHECK_NULL_VOID(taskExecutor);
89         auto callback = [weak = AceType::WeakClaim(this), info, taskExecutor, instanceId]() {
90             ContainerScope scope(instanceId);
91             auto pageRouterManager = weak.Upgrade();
92             CHECK_NULL_VOID(pageRouterManager);
93             taskExecutor->PostTask(
94                 [pageRouterManager, info]() { pageRouterManager->LoadOhmUrl(info); }, TaskExecutor::TaskType::JS);
95         };
96 
97         auto silentInstallErrorCallBack = [taskExecutor, instanceId](int32_t errorCode, const std::string& errorMsg) {
98             ContainerScope scope(instanceId);
99             taskExecutor->PostTask(
100                 [errorCode, errorMsg]() {
101                     LOGE("Run page error = %{public}d, errorMsg = %{public}s", errorCode, errorMsg.c_str());
102                 },
103                 TaskExecutor::TaskType::JS);
104         };
105 
106         pageUrlChecker->LoadPageUrl(url, callback, silentInstallErrorCallBack);
107         return;
108     }
109 #endif
110     if (!info.url.empty()) {
111         info.path = manifestParser_->GetRouter()->GetPagePath(url);
112         if (info.path.empty()) {
113             LOGE("[Engine Log] this uri not support in route push.");
114             return;
115         }
116     } else {
117         info.path = manifestParser_->GetRouter()->GetEntry();
118         info.url = manifestParser_->GetRouter()->GetEntry("");
119     }
120     LOGD("router.Push pagePath = %{private}s", info.url.c_str());
121     RouterOptScope scope(this);
122     LoadPage(GenerateNextPageId(), info);
123 }
124 
RunCard(const std::string & url,const std::string & params,int64_t cardId)125 void PageRouterManager::RunCard(const std::string& url, const std::string& params, int64_t cardId)
126 {
127     CHECK_RUN_ON(JS);
128     RouterPageInfo info { url };
129 #ifndef PREVIEW
130     if (!info.url.empty()) {
131         info.path = manifestParser_->GetRouter()->GetPagePath(url);
132     } else {
133         info.path = manifestParser_->GetRouter()->GetEntry();
134         info.url = manifestParser_->GetRouter()->GetEntry("");
135     }
136 #endif
137     LoadCard(0, info, params, cardId);
138 }
139 
Push(const RouterPageInfo & target)140 void PageRouterManager::Push(const RouterPageInfo& target)
141 {
142     CHECK_RUN_ON(JS);
143     if (inRouterOpt_) {
144         LOGI("in router opt, post push router task");
145         auto context = PipelineContext::GetCurrentContext();
146         CHECK_NULL_VOID(context);
147         context->PostAsyncEvent(
148             [weak = WeakClaim(this), target]() {
149                 auto router = weak.Upgrade();
150                 CHECK_NULL_VOID(router);
151                 router->Push(target);
152             },
153             TaskExecutor::TaskType::JS);
154         return;
155     }
156     RouterOptScope scope(this);
157     StartPush(target);
158 }
159 
PushNamedRoute(const RouterPageInfo & target)160 void PageRouterManager::PushNamedRoute(const RouterPageInfo& target)
161 {
162     CHECK_RUN_ON(JS);
163     if (inRouterOpt_) {
164         LOGI("in router opt, post push named route router task");
165         auto context = PipelineContext::GetCurrentContext();
166         CHECK_NULL_VOID(context);
167         context->PostAsyncEvent(
168             [weak = WeakClaim(this), target]() {
169                 auto router = weak.Upgrade();
170                 CHECK_NULL_VOID(router);
171                 router->PushNamedRoute(target);
172             },
173             TaskExecutor::TaskType::JS);
174         return;
175     }
176     RouterOptScope scope(this);
177     if (GetStackSize() >= MAX_ROUTER_STACK_SIZE) {
178         LOGE("router stack size is larger than max size 32.");
179         if (target.errorCallback != nullptr) {
180             target.errorCallback("The pages are pushed too much.", Framework::ERROR_CODE_PAGE_STACK_FULL);
181         }
182         return;
183     }
184     CleanPageOverlay();
185     if (target.routerMode == RouterMode::SINGLE) {
186         auto pageInfo = FindPageInStack(target.url);
187         if (pageInfo.second) {
188             // find page in stack, move postion and update params.
189             MovePageToFront(pageInfo.first, pageInfo.second, target, false);
190             return;
191         }
192     }
193     RouterPageInfo info = target;
194     info.isNamedRouterMode = true;
195     LoadPage(GenerateNextPageId(), info);
196 }
197 
Replace(const RouterPageInfo & target)198 void PageRouterManager::Replace(const RouterPageInfo& target)
199 {
200     CHECK_RUN_ON(JS);
201     if (inRouterOpt_) {
202         LOGI("in router opt, post replace router task");
203         auto context = PipelineContext::GetCurrentContext();
204         CHECK_NULL_VOID(context);
205         context->PostAsyncEvent(
206             [weak = WeakClaim(this), target]() {
207                 auto router = weak.Upgrade();
208                 CHECK_NULL_VOID(router);
209                 router->Replace(target);
210             },
211             TaskExecutor::TaskType::JS);
212         return;
213     }
214     RouterOptScope scope(this);
215     StartReplace(target);
216 }
217 
ReplaceNamedRoute(const RouterPageInfo & target)218 void PageRouterManager::ReplaceNamedRoute(const RouterPageInfo& target)
219 {
220     CHECK_RUN_ON(JS);
221     if (inRouterOpt_) {
222         LOGI("in router opt, post replace named route router task");
223         auto context = PipelineContext::GetCurrentContext();
224         CHECK_NULL_VOID(context);
225         context->PostAsyncEvent(
226             [weak = WeakClaim(this), target]() {
227                 auto router = weak.Upgrade();
228                 CHECK_NULL_VOID(router);
229                 router->ReplaceNamedRoute(target);
230             },
231             TaskExecutor::TaskType::JS);
232         return;
233     }
234     RouterOptScope scope(this);
235     CleanPageOverlay();
236     PopPage("", false, false);
237     if (target.routerMode == RouterMode::SINGLE) {
238         auto pageInfo = FindPageInStack(target.url);
239         if (pageInfo.second) {
240             // find page in stack, move postion and update params.
241             MovePageToFront(pageInfo.first, pageInfo.second, target, false);
242             return;
243         }
244     }
245     RouterPageInfo info = target;
246     info.isNamedRouterMode = true;
247     LoadPage(GenerateNextPageId(), info, false, false);
248 }
249 
BackWithTarget(const RouterPageInfo & target)250 void PageRouterManager::BackWithTarget(const RouterPageInfo& target)
251 {
252     CHECK_RUN_ON(JS);
253     LOGI("router.Back path = %{private}s", target.url.c_str());
254     if (inRouterOpt_) {
255         LOGI("in router opt, post back router task");
256         auto context = PipelineContext::GetCurrentContext();
257         CHECK_NULL_VOID(context);
258         context->PostAsyncEvent(
259             [weak = WeakClaim(this), target]() {
260                 auto router = weak.Upgrade();
261                 CHECK_NULL_VOID(router);
262                 router->BackWithTarget(target);
263             },
264             TaskExecutor::TaskType::JS);
265         return;
266     }
267     RouterOptScope scope(this);
268     BackCheckAlert(target);
269 }
270 
Clear()271 void PageRouterManager::Clear()
272 {
273     CHECK_RUN_ON(JS);
274     if (inRouterOpt_) {
275         LOGI("in router opt, post clear router task");
276         auto context = PipelineContext::GetCurrentContext();
277         CHECK_NULL_VOID(context);
278         context->PostAsyncEvent(
279             [weak = WeakClaim(this)]() {
280                 auto router = weak.Upgrade();
281                 CHECK_NULL_VOID(router);
282                 router->Clear();
283             },
284             TaskExecutor::TaskType::JS);
285         return;
286     }
287     RouterOptScope scope(this);
288     StartClean();
289 }
290 
EnableAlertBeforeBackPage(const std::string & message,std::function<void (int32_t)> && callback)291 void PageRouterManager::EnableAlertBeforeBackPage(const std::string& message, std::function<void(int32_t)>&& callback)
292 {
293     auto currentPage = pageRouterStack_.back().Upgrade();
294     CHECK_NULL_VOID(currentPage);
295     auto pagePattern = currentPage->GetPattern<PagePattern>();
296     CHECK_NULL_VOID(pagePattern);
297     auto pageInfo = pagePattern->GetPageInfo();
298     CHECK_NULL_VOID(pageInfo);
299 
300     DialogProperties dialogProperties = {
301         .content = message,
302         .autoCancel = false,
303         .buttons = { { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"), .textColor = "" },
304             { .text = Localization::GetInstance()->GetEntryLetters("common.ok"), .textColor = "" } },
305         .onSuccess =
306             [weak = AceType::WeakClaim(this), weakPageInfo = AceType::WeakClaim(AceType::RawPtr(pageInfo))](
307                 int32_t successType, int32_t successIndex) {
308                 LOGI("showDialog successType: %{public}d, successIndex: %{public}d", successType, successIndex);
309                 auto pageInfo = weakPageInfo.Upgrade();
310                 if (pageInfo && pageInfo->GetAlertCallback() && !successType) {
311                     pageInfo->GetAlertCallback()(successIndex);
312                     if (successIndex) {
313                         auto router = weak.Upgrade();
314                         CHECK_NULL_VOID(router);
315                         router->StartBack(router->ngBackTarget_);
316                     }
317                 }
318             },
319     };
320 
321     pageInfo->SetDialogProperties(dialogProperties);
322     pageInfo->SetAlertCallback(std::move(callback));
323 }
324 
DisableAlertBeforeBackPage()325 void PageRouterManager::DisableAlertBeforeBackPage()
326 {
327     auto currentPage = pageRouterStack_.back().Upgrade();
328     CHECK_NULL_VOID(currentPage);
329     auto pagePattern = currentPage->GetPattern<PagePattern>();
330     CHECK_NULL_VOID(pagePattern);
331     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
332     CHECK_NULL_VOID(pageInfo);
333     pageInfo->SetAlertCallback(nullptr);
334 }
335 
StartClean()336 void PageRouterManager::StartClean()
337 {
338     if (pageRouterStack_.size() <= 1) {
339         LOGW("current page stack can not clean, %{public}d", static_cast<int32_t>(pageRouterStack_.size()));
340         return;
341     }
342     std::list<WeakPtr<FrameNode>> temp;
343     std::swap(temp, pageRouterStack_);
344     pageRouterStack_.emplace_back(temp.back());
345     if (!OnCleanPageStack()) {
346         LOGE("fail to clean page");
347         std::swap(temp, pageRouterStack_);
348     }
349 }
350 
Pop()351 bool PageRouterManager::Pop()
352 {
353     CHECK_RUN_ON(JS);
354     LOGI("router pop be called");
355     if (inRouterOpt_) {
356         LOGE("in router opt, post Pop router task failed");
357         return false;
358     }
359     RouterOptScope scope(this);
360     return StartPop();
361 }
362 
StartPop()363 bool PageRouterManager::StartPop()
364 {
365     CHECK_RUN_ON(JS);
366     auto currentPage = pageRouterStack_.empty() ? nullptr : pageRouterStack_.back().Upgrade();
367     CHECK_NULL_RETURN(currentPage, false);
368     auto pagePattern = currentPage->GetPattern<PagePattern>();
369     CHECK_NULL_RETURN(pagePattern, false);
370     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
371     CHECK_NULL_RETURN(pageInfo, false);
372     if (pageInfo->GetAlertCallback()) {
373         BackCheckAlert(RouterPageInfo());
374         return true;
375     }
376 
377     if (pageRouterStack_.size() <= 1) {
378         if (!restorePageStack_.empty()) {
379             StartRestore(RouterPageInfo());
380             return true;
381         }
382         // the last page.
383         return false;
384     }
385 
386     auto topNode = pageRouterStack_.back();
387     pageRouterStack_.pop_back();
388     if (!OnPopPage(true, true)) {
389         LOGE("fail to pop page");
390         pageRouterStack_.emplace_back(topNode);
391         return false;
392     }
393     currentPage = pageRouterStack_.empty() ? nullptr : pageRouterStack_.back().Upgrade();
394     CHECK_NULL_RETURN(currentPage, false);
395     pagePattern = currentPage->GetPattern<PagePattern>();
396     CHECK_NULL_RETURN(pagePattern, false);
397     pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
398     CHECK_NULL_RETURN(pageInfo, false);
399     pageInfo->ReplacePageParams("");
400     return true;
401 }
402 
StartRestore(const RouterPageInfo & target)403 void PageRouterManager::StartRestore(const RouterPageInfo& target)
404 {
405     RouterPageInfo info = target;
406     auto tempStack = restorePageStack_;
407     if (target.url.empty()) {
408         info.url = tempStack.back();
409         tempStack.pop_back();
410     } else {
411         info.url = target.url;
412         while (!tempStack.empty() && tempStack.back() != info.url) {
413             tempStack.pop_back();
414         }
415         if (tempStack.empty()) {
416             LOGW("this url not find in current restore stack");
417             return;
418         }
419         tempStack.pop_back();
420     }
421 
422     restorePageStack_ = tempStack;
423     StartClean();
424     PopPage("", false, false);
425     StartPush(info);
426 }
427 
GetStackSize() const428 int32_t PageRouterManager::GetStackSize() const
429 {
430     CHECK_RUN_ON(JS);
431     return static_cast<int32_t>(pageRouterStack_.size());
432 }
433 
GetState(int32_t & index,std::string & name,std::string & path)434 void PageRouterManager::GetState(int32_t& index, std::string& name, std::string& path)
435 {
436     CHECK_RUN_ON(JS);
437     if (pageRouterStack_.empty()) {
438         LOGE("fail to get page state due to stack is null");
439         return;
440     }
441     index = static_cast<int32_t>(pageRouterStack_.size());
442     auto pageNode = pageRouterStack_.back().Upgrade();
443     CHECK_NULL_VOID(pageNode);
444     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
445     CHECK_NULL_VOID(pagePattern);
446     auto pageInfo = pagePattern->GetPageInfo();
447     CHECK_NULL_VOID(pageInfo);
448     auto url = pageInfo->GetPageUrl();
449     auto pos = url.rfind(".js");
450     if (pos == url.length() - 3) {
451         url = url.substr(0, pos);
452     }
453     pos = url.rfind("/");
454     if (pos != std::string::npos) {
455         name = url.substr(pos + 1);
456         path = url.substr(0, pos + 1);
457     }
458 }
459 
GetParams() const460 std::string PageRouterManager::GetParams() const
461 {
462     CHECK_RUN_ON(JS);
463     if (pageRouterStack_.empty()) {
464         LOGE("fail to get page param due to stack is null");
465         return "";
466     }
467     auto pageNode = pageRouterStack_.back().Upgrade();
468     CHECK_NULL_RETURN(pageNode, "");
469     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
470     CHECK_NULL_RETURN(pagePattern, "");
471     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
472     CHECK_NULL_RETURN(pageInfo, "");
473     return pageInfo->GetPageParams();
474 }
475 
GetCurrentPageUrl()476 std::string PageRouterManager::GetCurrentPageUrl()
477 {
478     CHECK_RUN_ON(JS);
479     if (pageRouterStack_.empty()) {
480         LOGW("current page stack is empty");
481         return "";
482     }
483     auto pageNode = pageRouterStack_.back().Upgrade();
484     CHECK_NULL_RETURN(pageNode, "");
485     auto pagePattern = pageNode->GetPattern<PagePattern>();
486     CHECK_NULL_RETURN(pagePattern, "");
487     auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
488     CHECK_NULL_RETURN(entryPageInfo, "");
489     return entryPageInfo->GetPagePath();
490 }
491 
492 // Get the currently running JS page information in NG structure.
GetCurrentPageSourceMap(const RefPtr<AssetManager> & assetManager)493 RefPtr<Framework::RevSourceMap> PageRouterManager::GetCurrentPageSourceMap(const RefPtr<AssetManager>& assetManager)
494 {
495     CHECK_RUN_ON(JS);
496     if (pageRouterStack_.empty()) {
497         LOGW("current page stack is empty");
498         return nullptr;
499     }
500     auto pageNode = pageRouterStack_.back().Upgrade();
501     CHECK_NULL_RETURN(pageNode, nullptr);
502     auto pagePattern = pageNode->GetPattern<PagePattern>();
503     CHECK_NULL_RETURN(pagePattern, nullptr);
504     auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
505     CHECK_NULL_RETURN(entryPageInfo, nullptr);
506     auto pageMap = entryPageInfo->GetPageMap();
507     if (pageMap) {
508         return pageMap;
509     }
510     // initialize page map.
511     std::string jsSourceMap;
512     // stage mode
513     auto container = Container::Current();
514     CHECK_NULL_RETURN(container, nullptr);
515     if (container->IsUseStageModel()) {
516         auto pagePath = entryPageInfo->GetPagePath();
517         auto moduleName = container->GetModuleName();
518         auto judgePath = moduleName + "/src/main/ets/" + pagePath.substr(0, pagePath.size() - 3) + ".ets";
519         if (Framework::GetAssetContentImpl(assetManager, "sourceMaps.map", jsSourceMap)) {
520             auto jsonPages = JsonUtil::ParseJsonString(jsSourceMap);
521             auto jsonPage = jsonPages->GetValue(judgePath)->ToString();
522             auto stagePageMap = MakeRefPtr<Framework::RevSourceMap>();
523             stagePageMap->Init(jsonPage);
524             entryPageInfo->SetPageMap(stagePageMap);
525             return stagePageMap;
526         }
527     } else {
528         if (Framework::GetAssetContentImpl(assetManager, entryPageInfo->GetPagePath() + ".map", jsSourceMap)) {
529             auto faPageMap = MakeRefPtr<Framework::RevSourceMap>();
530             faPageMap->Init(jsSourceMap);
531             entryPageInfo->SetPageMap(faPageMap);
532             return faPageMap;
533         }
534     }
535     LOGW("js source map load failed!");
536     return nullptr;
537 }
538 
GetStackInfo()539 std::unique_ptr<JsonValue> PageRouterManager::GetStackInfo()
540 {
541     auto jsonRouterStack = JsonUtil::CreateArray(false);
542     auto restoreIter = restorePageStack_.begin();
543     while (restoreIter != restorePageStack_.end()) {
544         auto jsonItem = JsonUtil::Create(false);
545         jsonItem->Put("url", restoreIter->c_str());
546         jsonRouterStack->Put(jsonItem);
547         ++restoreIter;
548     }
549     auto iter = pageRouterStack_.begin();
550     while (iter != pageRouterStack_.end()) {
551         auto pageNode = iter->Upgrade();
552         CHECK_NULL_RETURN(pageNode, jsonRouterStack);
553         auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
554         CHECK_NULL_RETURN(pagePattern, jsonRouterStack);
555         auto pageInfo = pagePattern->GetPageInfo();
556         CHECK_NULL_RETURN(pageInfo, jsonRouterStack);
557         auto url = pageInfo->GetPageUrl();
558         auto jsonItem = JsonUtil::Create(false);
559         jsonItem->Put("url", url.c_str());
560         jsonRouterStack->Put(jsonItem);
561         ++iter;
562     }
563     return jsonRouterStack;
564 }
565 
RestoreRouterStack(std::unique_ptr<JsonValue> stackInfo)566 std::string PageRouterManager::RestoreRouterStack(std::unique_ptr<JsonValue> stackInfo)
567 {
568     if (!stackInfo->IsValid() || !stackInfo->IsArray()) {
569         LOGW("restore contentInfo is invalid");
570         return "";
571     }
572     int32_t stackSize = stackInfo->GetArraySize();
573     if (stackSize < 1) {
574         LOGW("restore stack size is invalid");
575         return "";
576     }
577 
578     auto container = Container::Current();
579     CHECK_NULL_RETURN(container, "");
580     auto pipeline = container->GetPipelineContext();
581     CHECK_NULL_RETURN(pipeline, "");
582     auto context = DynamicCast<NG::PipelineContext>(pipeline);
583     auto stageManager = context ? context->GetStageManager() : nullptr;
584     CHECK_NULL_RETURN(stageManager, "");
585 
586     for (int32_t index = 0; index < stackSize - 1; ++index) {
587         std::string url = stackInfo->GetArrayItem(index)->GetValue("url")->ToString();
588         // remove 2 useless character, as "XXX" to XXX
589         url = url.substr(1, url.size() - 2);
590         restorePageStack_.emplace_back(url);
591     }
592     std::string startUrl = stackInfo->GetArrayItem(stackSize - 1)->GetValue("url")->ToString();
593     // remove 2 useless character, as "XXX" to XXX
594     return startUrl.substr(1, startUrl.size() - 2);
595 }
596 
GenerateNextPageId()597 int32_t PageRouterManager::GenerateNextPageId()
598 {
599     return ++pageId_;
600 }
601 
FindPageInStack(const std::string & url,bool needIgnoreBegin)602 std::pair<int32_t, RefPtr<FrameNode>> PageRouterManager::FindPageInStack(const std::string& url, bool needIgnoreBegin)
603 {
604     auto iter = std::find_if(needIgnoreBegin ? ++pageRouterStack_.rbegin() : pageRouterStack_.rbegin(),
605         pageRouterStack_.rend(), [url](const WeakPtr<FrameNode>& item) {
606             auto pageNode = item.Upgrade();
607             CHECK_NULL_RETURN(pageNode, false);
608             auto pagePattern = pageNode->GetPattern<PagePattern>();
609             CHECK_NULL_RETURN(pagePattern, false);
610             auto entryPageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
611             CHECK_NULL_RETURN(entryPageInfo, false);
612             return entryPageInfo->GetPageUrl() == url;
613         });
614     if (iter == pageRouterStack_.rend()) {
615         return { -1, nullptr };
616     }
617     // Returns to the forward position.
618     return { std::distance(iter, pageRouterStack_.rend()) - 1, iter->Upgrade() };
619 }
620 
PushOhmUrl(const RouterPageInfo & target)621 void PageRouterManager::PushOhmUrl(const RouterPageInfo& target)
622 {
623     RouterOptScope scope(this);
624     if (GetStackSize() >= MAX_ROUTER_STACK_SIZE) {
625         LOGE("router stack size is larger than max size 32.");
626         if (target.errorCallback != nullptr) {
627             target.errorCallback("The pages are pushed too much.", Framework::ERROR_CODE_PAGE_STACK_FULL);
628         }
629         return;
630     }
631     RouterPageInfo info = target;
632     info.path = info.url + ".js";
633     LOGD("router.Push pagePath = %{private}s", info.path.c_str());
634 
635     if (target.routerMode == RouterMode::SINGLE) {
636         auto pageInfo = FindPageInStack(info.url);
637         if (pageInfo.second) {
638             // find page in stack, move postion and update params.
639             MovePageToFront(pageInfo.first, pageInfo.second, info, false);
640             return;
641         }
642     }
643 
644     LoadPage(GenerateNextPageId(), info);
645     auto container = Container::Current();
646     CHECK_NULL_VOID(container);
647     auto pageUrlChecker = container->GetPageUrlChecker();
648     CHECK_NULL_VOID(pageUrlChecker);
649     auto taskExecutor = container->GetTaskExecutor();
650     CHECK_NULL_VOID(taskExecutor);
651     taskExecutor->PostTask([pageUrlChecker, url = target.url]() { pageUrlChecker->CheckPreload(url); },
652         TaskExecutor::TaskType::BACKGROUND);
653 }
654 
StartPush(const RouterPageInfo & target)655 void PageRouterManager::StartPush(const RouterPageInfo& target)
656 {
657     CHECK_RUN_ON(JS);
658     RouterOptScope scope(this);
659     if (target.url.empty()) {
660         LOGE("router.Push uri is empty");
661         return;
662     }
663 #if !defined(PREVIEW)
664     if (target.url.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
665         auto container = Container::Current();
666         CHECK_NULL_VOID(container);
667         auto pageUrlChecker = container->GetPageUrlChecker();
668         CHECK_NULL_VOID(pageUrlChecker);
669         auto instanceId = container->GetInstanceId();
670         auto taskExecutor = container->GetTaskExecutor();
671         CHECK_NULL_VOID(taskExecutor);
672         auto callback = [weak = AceType::WeakClaim(this), target, taskExecutor, instanceId]() {
673             ContainerScope scope(instanceId);
674             auto pageRouterManager = weak.Upgrade();
675             CHECK_NULL_VOID(pageRouterManager);
676             taskExecutor->PostTask(
677                 [pageRouterManager, target]() { pageRouterManager->PushOhmUrl(target); }, TaskExecutor::TaskType::JS);
678         };
679 
680         auto silentInstallErrorCallBack = [errorCallback = target.errorCallback, taskExecutor, instanceId](
681                                               int32_t errorCode, const std::string& errorMsg) {
682             ContainerScope scope(instanceId);
683             taskExecutor->PostTask([errorCallback, errorCode, errorMsg]() { errorCallback(errorMsg, errorCode); },
684                 TaskExecutor::TaskType::JS);
685         };
686 
687         pageUrlChecker->LoadPageUrl(target.url, callback, silentInstallErrorCallBack);
688         return;
689     }
690 #endif
691     if (!manifestParser_) {
692         LOGE("the router manifest parser is null.");
693         return;
694     }
695     if (GetStackSize() >= MAX_ROUTER_STACK_SIZE) {
696         LOGE("router stack size is larger than max size 32.");
697         if (target.errorCallback != nullptr) {
698             target.errorCallback("The pages are pushed too much.", Framework::ERROR_CODE_PAGE_STACK_FULL);
699         }
700         return;
701     }
702     RouterPageInfo info = target;
703     info.path = manifestParser_->GetRouter()->GetPagePath(info.url);
704     LOGD("router.Push pagePath = %{private}s", info.path.c_str());
705     if (info.path.empty()) {
706         LOGE("[Engine Log] this uri not support in route push.");
707         if (info.errorCallback != nullptr) {
708             info.errorCallback("The uri of router is not exist.", Framework::ERROR_CODE_URI_ERROR);
709         }
710         return;
711     }
712 
713     CleanPageOverlay();
714 
715     if (info.routerMode == RouterMode::SINGLE) {
716         auto pageInfo = FindPageInStack(info.url);
717         if (pageInfo.second) {
718             // find page in stack, move postion and update params.
719             MovePageToFront(pageInfo.first, pageInfo.second, info, false);
720             return;
721         }
722     }
723 
724     LoadPage(GenerateNextPageId(), info);
725 }
726 
ReplaceOhmUrl(const RouterPageInfo & target)727 void PageRouterManager::ReplaceOhmUrl(const RouterPageInfo& target)
728 {
729     RouterOptScope scope(this);
730     RouterPageInfo info = target;
731     info.path = info.url + ".js";
732     LOGD("router.Push pagePath = %{private}s", info.path.c_str());
733 
734     PopPage("", false, false);
735 
736     if (info.routerMode == RouterMode::SINGLE) {
737         auto pageInfo = FindPageInStack(info.url);
738         if (pageInfo.second) {
739             // find page in stack, move postion and update params.
740             MovePageToFront(pageInfo.first, pageInfo.second, info, false, true, false);
741             return;
742         }
743     }
744 
745     LoadPage(GenerateNextPageId(), info, false, false);
746     auto container = Container::Current();
747     CHECK_NULL_VOID(container);
748     auto pageUrlChecker = container->GetPageUrlChecker();
749     CHECK_NULL_VOID(pageUrlChecker);
750     auto taskExecutor = container->GetTaskExecutor();
751     CHECK_NULL_VOID(taskExecutor);
752     taskExecutor->PostTask([pageUrlChecker, url = target.url]() { pageUrlChecker->CheckPreload(url); },
753         TaskExecutor::TaskType::BACKGROUND);
754 }
755 
StartReplace(const RouterPageInfo & target)756 void PageRouterManager::StartReplace(const RouterPageInfo& target)
757 {
758     CHECK_RUN_ON(JS);
759     CleanPageOverlay();
760     RouterOptScope scope(this);
761     if (target.url.empty()) {
762         LOGE("router.Push uri is empty");
763         return;
764     }
765 #if !defined(PREVIEW)
766     if (target.url.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
767         auto container = Container::Current();
768         CHECK_NULL_VOID(container);
769         auto pageUrlChecker = container->GetPageUrlChecker();
770         CHECK_NULL_VOID(pageUrlChecker);
771         auto instanceId = container->GetInstanceId();
772         auto taskExecutor = container->GetTaskExecutor();
773         CHECK_NULL_VOID(taskExecutor);
774         auto callback = [weak = AceType::WeakClaim(this), target, taskExecutor, instanceId]() {
775             ContainerScope scope(instanceId);
776             auto pageRouterManager = weak.Upgrade();
777             CHECK_NULL_VOID(pageRouterManager);
778             taskExecutor->PostTask([pageRouterManager, target]() { pageRouterManager->ReplaceOhmUrl(target); },
779                 TaskExecutor::TaskType::JS);
780         };
781 
782         auto silentInstallErrorCallBack = [errorCallback = target.errorCallback, taskExecutor, instanceId](
783                                               int32_t errorCode, const std::string& errorMsg) {
784             ContainerScope scope(instanceId);
785             taskExecutor->PostTask([errorCallback, errorCode, errorMsg]() { errorCallback(errorMsg, errorCode); },
786                 TaskExecutor::TaskType::JS);
787         };
788 
789         pageUrlChecker->LoadPageUrl(target.url, callback, silentInstallErrorCallBack);
790         return;
791     }
792 #endif
793     if (!manifestParser_) {
794         LOGE("the router manifest parser is null.");
795         return;
796     }
797     RouterPageInfo info = target;
798     info.path = manifestParser_->GetRouter()->GetPagePath(info.url);
799     LOGD("router.Push pagePath = %{private}s", info.path.c_str());
800     if (info.path.empty()) {
801         LOGE("[Engine Log] this uri not support in route push.");
802         if (info.errorCallback != nullptr) {
803             info.errorCallback("The uri of router is not exist.", Framework::ERROR_CODE_URI_ERROR_LITE);
804         }
805         return;
806     }
807 
808     PopPage("", false, false);
809 
810     if (info.routerMode == RouterMode::SINGLE) {
811         auto pageInfo = FindPageInStack(info.url);
812         if (pageInfo.second) {
813             // find page in stack, move position and update params.
814             MovePageToFront(pageInfo.first, pageInfo.second, info, false, true, false);
815             return;
816         }
817     }
818 
819     LoadPage(GenerateNextPageId(), info, false, false);
820 }
821 
StartBack(const RouterPageInfo & target)822 void PageRouterManager::StartBack(const RouterPageInfo& target)
823 {
824     CleanPageOverlay();
825     if (target.url.empty()) {
826         size_t pageRouteSize = pageRouterStack_.size();
827         if (pageRouteSize <= 1) {
828             if (!restorePageStack_.empty()) {
829                 StartRestore(RouterPageInfo());
830                 return;
831             }
832             LOGI("router stack is only one, back to desktop");
833             ExitToDesktop();
834             return;
835         }
836         PopPage(target.params, true, true);
837         return;
838     }
839 
840     auto pageInfo = FindPageInStack(target.url, true);
841     if (pageInfo.second) {
842         // find page in stack, pop to specified index.
843         RouterPageInfo info = target;
844 #if !defined(PREVIEW)
845         if (info.url.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
846             info.path = info.url + ".js";
847             LOGD("router.Push pagePath = %{private}s", info.path.c_str());
848             PopPageToIndex(pageInfo.first, info.params, true, true);
849             return;
850         }
851 #endif
852         if (!manifestParser_) {
853             LOGE("the router manifest parser is null.");
854             return;
855         }
856 
857         info.path = manifestParser_->GetRouter()->GetPagePath(info.url);
858         LOGD("router.Push pagePath = %{private}s", info.path.c_str());
859         if (info.path.empty()) {
860             LOGE("[Engine Log] this uri not support in route push.");
861             return;
862         }
863         PopPageToIndex(pageInfo.first, info.params, true, true);
864         return;
865     }
866     LOGW("fail to find specified page to pop");
867     if (!restorePageStack_.empty()) {
868         StartRestore(target);
869     }
870 }
871 
BackCheckAlert(const RouterPageInfo & target)872 void PageRouterManager::BackCheckAlert(const RouterPageInfo& target)
873 {
874     RouterOptScope scope(this);
875     if (pageRouterStack_.empty()) {
876         LOGI("page route stack is empty");
877         return;
878     }
879     auto currentPage = pageRouterStack_.back().Upgrade();
880     CHECK_NULL_VOID(currentPage);
881     auto pagePattern = currentPage->GetPattern<PagePattern>();
882     CHECK_NULL_VOID(pagePattern);
883     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
884     CHECK_NULL_VOID(pageInfo);
885     if (pageInfo->GetAlertCallback()) {
886         ngBackTarget_ = target;
887         auto pipelineContext = PipelineContext::GetCurrentContext();
888         auto overlayManager = pipelineContext ? pipelineContext->GetOverlayManager() : nullptr;
889         CHECK_NULL_VOID(overlayManager);
890         overlayManager->ShowDialog(
891             pageInfo->GetDialogProperties(), nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
892         return;
893     }
894     StartBack(target);
895 }
896 
LoadPage(int32_t pageId,const RouterPageInfo & target,bool needHideLast,bool needTransition)897 void PageRouterManager::LoadPage(int32_t pageId, const RouterPageInfo& target, bool needHideLast, bool needTransition)
898 {
899     ACE_SCOPED_TRACE("PageRouterManager::LoadPage");
900     CHECK_RUN_ON(JS);
901     LOGI("PageRouterManager LoadPage[%{public}d]: %{public}s.", pageId, target.url.c_str());
902     auto entryPageInfo = AceType::MakeRefPtr<EntryPageInfo>(pageId, target.url, target.path, target.params);
903     auto pagePattern = AceType::MakeRefPtr<PagePattern>(entryPageInfo);
904     std::unordered_map<std::string, std::string> reportData { { "pageUrl", target.url } };
905     ResSchedReportScope reportScope("push_page", reportData);
906     auto pageNode =
907         FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pagePattern);
908     pageNode->SetHostPageId(pageId);
909     pageRouterStack_.emplace_back(pageNode);
910     auto result = loadJs_(target.path, target.errorCallback);
911     if (pageNode->GetChildren().empty()) {
912         // try to load named route
913         result = loadNamedRouter_(target.url, target.isNamedRouterMode);
914         if (!result && target.isNamedRouterMode && target.errorCallback) {
915             target.errorCallback("The named route is not exist.", Framework::ERROR_CODE_NAMED_ROUTE_ERROR);
916         }
917     }
918     if (target.errorCallback != nullptr) {
919         target.errorCallback("", Framework::ERROR_CODE_NO_ERROR);
920     }
921     if (!result) {
922         LOGE("fail to load page file");
923         pageRouterStack_.pop_back();
924         return;
925     }
926     if (!OnPageReady(pageNode, needHideLast, needTransition)) {
927         LOGE("fail to mount page");
928         pageRouterStack_.pop_back();
929         return;
930     }
931     AccessibilityEventType type = AccessibilityEventType::CHANGE;
932     pageNode->OnAccessibilityEvent(type);
933     LOGI("PageRouterManager LoadPage[%{public}d]: %{public}s. success", pageId, target.url.c_str());
934 }
935 
LoadCard(int32_t pageId,const RouterPageInfo & target,const std::string & params,int64_t cardId,bool,bool needHideLast)936 void PageRouterManager::LoadCard(int32_t pageId, const RouterPageInfo& target, const std::string& params,
937     int64_t cardId, bool /*isRestore*/, bool needHideLast)
938 {
939     CHECK_RUN_ON(JS);
940     auto entryPageInfo = AceType::MakeRefPtr<EntryPageInfo>(pageId, target.url, target.path, params);
941     auto pagePattern = AceType::MakeRefPtr<PagePattern>(entryPageInfo);
942     auto pageNode =
943         FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pagePattern);
944     pageNode->SetHostPageId(pageId);
945     pageRouterStack_.emplace_back(pageNode);
946 
947     if (!loadCard_) {
948         LOGE("PageRouterManager loadCard_ is nullptr");
949         return;
950     }
951     auto result = loadCard_(target.url, cardId);
952     if (!result) {
953         LOGE("fail to load page file");
954         pageRouterStack_.pop_back();
955         return;
956     }
957 
958     if (!OnPageReady(pageNode, needHideLast, false, isCardRouter_, cardId)) {
959         LOGE("fail to mount page");
960         pageRouterStack_.pop_back();
961         return;
962     }
963 }
964 
MovePageToFront(int32_t index,const RefPtr<FrameNode> & pageNode,const RouterPageInfo & target,bool needHideLast,bool forceShowCurrent,bool needTransition)965 void PageRouterManager::MovePageToFront(int32_t index, const RefPtr<FrameNode>& pageNode, const RouterPageInfo& target,
966     bool needHideLast, bool forceShowCurrent, bool needTransition)
967 {
968     LOGD("MovePageToFront to index: %{public}d", index);
969     if (target.errorCallback != nullptr) {
970         target.errorCallback("", Framework::ERROR_CODE_NO_ERROR);
971     }
972 
973     // update param first.
974     CHECK_NULL_VOID(pageNode);
975     auto pagePattern = pageNode->GetPattern<PagePattern>();
976     CHECK_NULL_VOID(pagePattern);
977     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
978     CHECK_NULL_VOID(pageInfo);
979 
980     if (index == static_cast<int32_t>(pageRouterStack_.size() - 1)) {
981         LOGD("already on the top");
982         pageInfo->ReplacePageParams(target.params);
983         if (forceShowCurrent) {
984             pageNode->GetRenderContext()->ResetPageTransitionEffect();
985             StageManager::FirePageShow(pageNode, PageTransitionType::NONE);
986         }
987         return;
988     }
989     CHECK_NULL_VOID(pageNode);
990     auto container = Container::Current();
991     CHECK_NULL_VOID(container);
992     auto pipeline = container->GetPipelineContext();
993     CHECK_NULL_VOID(pipeline);
994     auto context = DynamicCast<NG::PipelineContext>(pipeline);
995     auto stageManager = context ? context->GetStageManager() : nullptr;
996     CHECK_NULL_VOID(stageManager);
997 
998     // clean pageNode on index position.
999     auto iter = pageRouterStack_.begin();
1000     std::advance(iter, index);
1001     auto last = pageRouterStack_.erase(iter);
1002     // push pageNode to top.
1003     pageRouterStack_.emplace_back(pageNode);
1004     std::string tempParam;
1005     tempParam = pageInfo->ReplacePageParams(target.params);
1006     if (!stageManager->MovePageToFront(pageNode, needHideLast, needTransition)) {
1007         LOGE("fail to move page to front");
1008         // restore position and param.
1009         pageRouterStack_.pop_back();
1010         pageRouterStack_.insert(last, pageNode);
1011         if (!tempParam.empty()) {
1012             pageInfo->ReplacePageParams(tempParam);
1013         }
1014     }
1015 }
1016 
FlushFrontend()1017 void PageRouterManager::FlushFrontend()
1018 {
1019     auto currentPage = pageRouterStack_.back().Upgrade();
1020     CHECK_NULL_VOID(currentPage);
1021     auto customNode = DynamicCast<CustomNode>(currentPage->GetFirstChild());
1022     CHECK_NULL_VOID(customNode);
1023     customNode->FlushReload();
1024 }
1025 
PopPage(const std::string & params,bool needShowNext,bool needTransition)1026 void PageRouterManager::PopPage(const std::string& params, bool needShowNext, bool needTransition)
1027 {
1028     CHECK_RUN_ON(JS);
1029     if (pageRouterStack_.empty()) {
1030         LOGE("page router stack size is illegal");
1031         return;
1032     }
1033     if (needShowNext && (pageRouterStack_.size() == 1)) {
1034         LOGE("page router stack size is only one, can not show next");
1035         return;
1036     }
1037     auto topNode = pageRouterStack_.back();
1038     pageRouterStack_.pop_back();
1039     if (!needShowNext) {
1040         if (!OnPopPage(needShowNext, needTransition)) {
1041             LOGE("fail to pop page");
1042             pageRouterStack_.emplace_back(topNode);
1043         }
1044         return;
1045     }
1046 
1047     // update param first.
1048     auto nextNode = pageRouterStack_.back().Upgrade();
1049     CHECK_NULL_VOID(nextNode);
1050     auto pagePattern = nextNode->GetPattern<PagePattern>();
1051     CHECK_NULL_VOID(pagePattern);
1052     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
1053     CHECK_NULL_VOID(pageInfo);
1054     auto temp = pageInfo->ReplacePageParams(params);
1055 
1056     if (OnPopPage(needShowNext, needTransition)) {
1057         return;
1058     }
1059     LOGE("fail to pop page");
1060     // restore stack and pageParam.
1061     pageRouterStack_.emplace_back(topNode);
1062     pageInfo->ReplacePageParams(temp);
1063 }
1064 
PopPageToIndex(int32_t index,const std::string & params,bool needShowNext,bool needTransition)1065 void PageRouterManager::PopPageToIndex(int32_t index, const std::string& params, bool needShowNext, bool needTransition)
1066 {
1067     LOGD("PopPageToIndex to index: %{public}d", index);
1068     std::list<WeakPtr<FrameNode>> temp;
1069     std::swap(temp, pageRouterStack_);
1070     auto iter = temp.begin();
1071     for (int32_t current = 0; current <= index; ++current) {
1072         pageRouterStack_.emplace_back(*iter);
1073         ++iter;
1074     }
1075 
1076     // update param first.
1077     auto nextNode = pageRouterStack_.back().Upgrade();
1078     CHECK_NULL_VOID(nextNode);
1079     auto pagePattern = nextNode->GetPattern<PagePattern>();
1080     CHECK_NULL_VOID(pagePattern);
1081     auto pageInfo = DynamicCast<EntryPageInfo>(pagePattern->GetPageInfo());
1082     CHECK_NULL_VOID(pageInfo);
1083     auto tempParam = pageInfo->ReplacePageParams(params);
1084 
1085     if (OnPopPageToIndex(index, needShowNext, needTransition)) {
1086         return;
1087     }
1088     LOGE("fail to pop page to index");
1089     // restore stack and pageParam.
1090     std::swap(temp, pageRouterStack_);
1091     pageInfo->ReplacePageParams(tempParam);
1092 }
1093 
OnPageReady(const RefPtr<FrameNode> & pageNode,bool needHideLast,bool needTransition,bool isCardRouter,int64_t cardId)1094 bool PageRouterManager::OnPageReady(
1095     const RefPtr<FrameNode>& pageNode, bool needHideLast, bool needTransition, bool isCardRouter, int64_t cardId)
1096 {
1097     auto container = Container::Current();
1098     CHECK_NULL_RETURN(container, false);
1099     RefPtr<PipelineBase> pipeline;
1100     if (isCardRouter) {
1101         auto weak = container->GetCardPipeline(cardId);
1102         pipeline = weak.Upgrade();
1103         CHECK_NULL_RETURN(pipeline, false);
1104     } else {
1105         pipeline = container->GetPipelineContext();
1106         CHECK_NULL_RETURN(pipeline, false);
1107     }
1108 
1109     auto context = DynamicCast<NG::PipelineContext>(pipeline);
1110     auto stageManager = context ? context->GetStageManager() : nullptr;
1111     if (stageManager) {
1112         return stageManager->PushPage(pageNode, needHideLast, needTransition);
1113     }
1114     LOGE("fail to push page due to stage manager is nullptr");
1115     return false;
1116 }
1117 
OnPopPage(bool needShowNext,bool needTransition)1118 bool PageRouterManager::OnPopPage(bool needShowNext, bool needTransition)
1119 {
1120     auto container = Container::Current();
1121     CHECK_NULL_RETURN(container, false);
1122     auto pipeline = container->GetPipelineContext();
1123     CHECK_NULL_RETURN(pipeline, false);
1124     auto context = DynamicCast<NG::PipelineContext>(pipeline);
1125     auto stageManager = context ? context->GetStageManager() : nullptr;
1126     if (stageManager) {
1127         return stageManager->PopPage(needShowNext, needTransition);
1128     }
1129     LOGE("fail to pop page due to stage manager is nullptr");
1130     return false;
1131 }
1132 
OnPopPageToIndex(int32_t index,bool needShowNext,bool needTransition)1133 bool PageRouterManager::OnPopPageToIndex(int32_t index, bool needShowNext, bool needTransition)
1134 {
1135     auto container = Container::Current();
1136     CHECK_NULL_RETURN(container, false);
1137     auto pipeline = container->GetPipelineContext();
1138     CHECK_NULL_RETURN(pipeline, false);
1139     auto context = DynamicCast<NG::PipelineContext>(pipeline);
1140     auto stageManager = context ? context->GetStageManager() : nullptr;
1141     if (stageManager) {
1142         return stageManager->PopPageToIndex(index, needShowNext, needTransition);
1143     }
1144     LOGE("fail to pop page to index due to stage manager is nullptr");
1145     return false;
1146 }
1147 
OnCleanPageStack()1148 bool PageRouterManager::OnCleanPageStack()
1149 {
1150     auto container = Container::Current();
1151     CHECK_NULL_RETURN(container, false);
1152     auto pipeline = container->GetPipelineContext();
1153     CHECK_NULL_RETURN(pipeline, false);
1154     auto context = DynamicCast<NG::PipelineContext>(pipeline);
1155     auto stageManager = context ? context->GetStageManager() : nullptr;
1156     if (stageManager) {
1157         return stageManager->CleanPageStack();
1158     }
1159     LOGE("fail to pop page to index due to stage manager is nullptr");
1160     return false;
1161 }
1162 
CleanPageOverlay()1163 void PageRouterManager::CleanPageOverlay()
1164 {
1165     auto container = Container::Current();
1166     CHECK_NULL_VOID(container);
1167     auto pipeline = container->GetPipelineContext();
1168     CHECK_NULL_VOID(pipeline);
1169     auto context = DynamicCast<NG::PipelineContext>(pipeline);
1170     CHECK_NULL_VOID(context);
1171     auto overlayManager = context->GetOverlayManager();
1172     CHECK_NULL_VOID(overlayManager);
1173     auto taskExecutor = context->GetTaskExecutor();
1174     CHECK_NULL_VOID_NOLOG(taskExecutor);
1175     auto sharedManager = context->GetSharedOverlayManager();
1176     if (sharedManager) {
1177         sharedManager->StopSharedTransition();
1178     }
1179 
1180     if (overlayManager->RemoveOverlay(true, true)) {
1181         LOGI("clean page overlay.");
1182     }
1183 }
1184 } // namespace OHOS::Ace::NG
1185