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