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