• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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/frontend_delegate_declarative.h"
17 
18 #include <atomic>
19 #include <regex>
20 #include <string>
21 
22 #include "base/i18n/localization.h"
23 #include "base/log/ace_trace.h"
24 #include "base/log/event_report.h"
25 #include "base/memory/ace_type.h"
26 #include "base/memory/referenced.h"
27 #include "base/resource/ace_res_config.h"
28 #include "base/subwindow/subwindow_manager.h"
29 #include "base/utils/measure_util.h"
30 #include "base/utils/utils.h"
31 #include "bridge/common/manifest/manifest_parser.h"
32 #include "bridge/common/utils/utils.h"
33 #include "bridge/declarative_frontend/ng/page_router_manager.h"
34 #include "bridge/js_frontend/js_ace_page.h"
35 #include "core/common/ace_application_info.h"
36 #include "core/common/container.h"
37 #include "core/common/container_scope.h"
38 #include "core/common/platform_bridge.h"
39 #include "core/common/thread_checker.h"
40 #include "core/components/dialog/dialog_component.h"
41 #include "core/components/toast/toast_component.h"
42 #include "core/components_ng/base/ui_node.h"
43 #include "core/components_ng/base/view_stack_model.h"
44 #include "core/components_ng/pattern/overlay/overlay_manager.h"
45 #include "core/components_ng/pattern/stage/page_pattern.h"
46 #include "core/components_ng/render/adapter/component_snapshot.h"
47 #include "core/pipeline_ng/pipeline_context.h"
48 #include "frameworks/core/common/ace_engine.h"
49 
50 namespace OHOS::Ace::Framework {
51 namespace {
52 
53 constexpr int32_t INVALID_PAGE_ID = -1;
54 constexpr int32_t MAX_ROUTER_STACK = 32;
55 constexpr int32_t TOAST_TIME_MAX = 10000;    // ms
56 constexpr int32_t TOAST_TIME_DEFAULT = 1500; // ms
57 constexpr int32_t MAX_PAGE_ID_SIZE = sizeof(uint64_t) * 8;
58 constexpr int32_t NANO_TO_MILLI = 1000000; // nanosecond to millisecond
59 constexpr int32_t TO_MILLI = 1000;         // second to millisecond
60 constexpr int32_t CALLBACK_ERRORCODE_SUCCESS = 0;
61 constexpr int32_t CALLBACK_ERRORCODE_CANCEL = 1;
62 constexpr int32_t CALLBACK_ERRORCODE_COMPLETE = 2;
63 constexpr int32_t CALLBACK_DATACODE_ZERO = 0;
64 
65 const char MANIFEST_JSON[] = "manifest.json";
66 const char PAGES_JSON[] = "main_pages.json";
67 const char FILE_TYPE_JSON[] = ".json";
68 const char I18N_FOLDER[] = "i18n/";
69 const char RESOURCES_FOLDER[] = "resources/";
70 const char STYLES_FOLDER[] = "styles/";
71 const char I18N_FILE_SUFFIX[] = "/properties/string.json";
72 
73 // helper function to run OverlayManager task
74 // ensures that the task runs in subwindow instead of main Window
MainWindowOverlay(std::function<void (RefPtr<NG::OverlayManager>)> && task)75 void MainWindowOverlay(std::function<void(RefPtr<NG::OverlayManager>)>&& task)
76 {
77     auto currentId = Container::CurrentId();
78     ContainerScope scope(currentId);
79     auto context = NG::PipelineContext::GetCurrentContext();
80     CHECK_NULL_VOID(context);
81     auto overlayManager = context->GetOverlayManager();
82     context->GetTaskExecutor()->PostTask(
83         [task = std::move(task), weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
84             auto overlayManager = weak.Upgrade();
85             task(overlayManager);
86         },
87         TaskExecutor::TaskType::UI);
88 }
89 
90 } // namespace
91 
GenerateNextPageId()92 int32_t FrontendDelegateDeclarative::GenerateNextPageId()
93 {
94     for (int32_t idx = 0; idx < MAX_PAGE_ID_SIZE; ++idx) {
95         uint64_t bitMask = (1ULL << idx);
96         if ((bitMask & pageIdPool_.fetch_or(bitMask, std::memory_order_relaxed)) == 0) {
97             return idx;
98         }
99     }
100     return INVALID_PAGE_ID;
101 }
102 
RecyclePageId(int32_t pageId)103 void FrontendDelegateDeclarative::RecyclePageId(int32_t pageId)
104 {
105     if (pageId < 0 || pageId >= MAX_PAGE_ID_SIZE) {
106         return;
107     }
108     uint64_t bitMask = (1ULL << pageId);
109     pageIdPool_.fetch_and(~bitMask, std::memory_order_relaxed);
110 }
111 
FrontendDelegateDeclarative(const RefPtr<TaskExecutor> & taskExecutor,const LoadJsCallback & loadCallback,const JsMessageDispatcherSetterCallback & transferCallback,const EventCallback & asyncEventCallback,const EventCallback & syncEventCallback,const UpdatePageCallback & updatePageCallback,const ResetStagingPageCallback & resetLoadingPageCallback,const DestroyPageCallback & destroyPageCallback,const DestroyApplicationCallback & destroyApplicationCallback,const UpdateApplicationStateCallback & updateApplicationStateCallback,const TimerCallback & timerCallback,const MediaQueryCallback & mediaQueryCallback,const LayoutInspectorCallback & layoutInpsectorCallback,const DrawInspectorCallback & drawInpsectorCallback,const RequestAnimationCallback & requestAnimationCallback,const JsCallback & jsCallback,const OnWindowDisplayModeChangedCallBack & onWindowDisplayModeChangedCallBack,const OnConfigurationUpdatedCallBack & onConfigurationUpdatedCallBack,const OnSaveAbilityStateCallBack & onSaveAbilityStateCallBack,const OnRestoreAbilityStateCallBack & onRestoreAbilityStateCallBack,const OnNewWantCallBack & onNewWantCallBack,const OnMemoryLevelCallBack & onMemoryLevelCallBack,const OnStartContinuationCallBack & onStartContinuationCallBack,const OnCompleteContinuationCallBack & onCompleteContinuationCallBack,const OnRemoteTerminatedCallBack & onRemoteTerminatedCallBack,const OnSaveDataCallBack & onSaveDataCallBack,const OnRestoreDataCallBack & onRestoreDataCallBack,const ExternalEventCallback & externalEventCallback)112 FrontendDelegateDeclarative::FrontendDelegateDeclarative(const RefPtr<TaskExecutor>& taskExecutor,
113     const LoadJsCallback& loadCallback, const JsMessageDispatcherSetterCallback& transferCallback,
114     const EventCallback& asyncEventCallback, const EventCallback& syncEventCallback,
115     const UpdatePageCallback& updatePageCallback, const ResetStagingPageCallback& resetLoadingPageCallback,
116     const DestroyPageCallback& destroyPageCallback, const DestroyApplicationCallback& destroyApplicationCallback,
117     const UpdateApplicationStateCallback& updateApplicationStateCallback, const TimerCallback& timerCallback,
118     const MediaQueryCallback& mediaQueryCallback, const LayoutInspectorCallback& layoutInpsectorCallback,
119     const DrawInspectorCallback& drawInpsectorCallback, const RequestAnimationCallback& requestAnimationCallback,
120     const JsCallback& jsCallback, const OnWindowDisplayModeChangedCallBack& onWindowDisplayModeChangedCallBack,
121     const OnConfigurationUpdatedCallBack& onConfigurationUpdatedCallBack,
122     const OnSaveAbilityStateCallBack& onSaveAbilityStateCallBack,
123     const OnRestoreAbilityStateCallBack& onRestoreAbilityStateCallBack, const OnNewWantCallBack& onNewWantCallBack,
124     const OnMemoryLevelCallBack& onMemoryLevelCallBack, const OnStartContinuationCallBack& onStartContinuationCallBack,
125     const OnCompleteContinuationCallBack& onCompleteContinuationCallBack,
126     const OnRemoteTerminatedCallBack& onRemoteTerminatedCallBack, const OnSaveDataCallBack& onSaveDataCallBack,
127     const OnRestoreDataCallBack& onRestoreDataCallBack, const ExternalEventCallback& externalEventCallback)
128     : loadJs_(loadCallback), externalEvent_(externalEventCallback), dispatcherCallback_(transferCallback),
129       asyncEvent_(asyncEventCallback), syncEvent_(syncEventCallback), updatePage_(updatePageCallback),
130       resetStagingPage_(resetLoadingPageCallback), destroyPage_(destroyPageCallback),
131       destroyApplication_(destroyApplicationCallback), updateApplicationState_(updateApplicationStateCallback),
132       timer_(timerCallback), mediaQueryCallback_(mediaQueryCallback), layoutInspectorCallback_(layoutInpsectorCallback),
133       drawInspectorCallback_(drawInpsectorCallback), requestAnimationCallback_(requestAnimationCallback),
134       jsCallback_(jsCallback), onWindowDisplayModeChanged_(onWindowDisplayModeChangedCallBack),
135       onConfigurationUpdated_(onConfigurationUpdatedCallBack), onSaveAbilityState_(onSaveAbilityStateCallBack),
136       onRestoreAbilityState_(onRestoreAbilityStateCallBack), onNewWant_(onNewWantCallBack),
137       onMemoryLevel_(onMemoryLevelCallBack), onStartContinuationCallBack_(onStartContinuationCallBack),
138       onCompleteContinuationCallBack_(onCompleteContinuationCallBack),
139       onRemoteTerminatedCallBack_(onRemoteTerminatedCallBack), onSaveDataCallBack_(onSaveDataCallBack),
140       onRestoreDataCallBack_(onRestoreDataCallBack), manifestParser_(AceType::MakeRefPtr<ManifestParser>()),
141       jsAccessibilityManager_(AccessibilityNodeManager::Create()),
142       mediaQueryInfo_(AceType::MakeRefPtr<MediaQueryInfo>()), taskExecutor_(taskExecutor)
143 {}
144 
~FrontendDelegateDeclarative()145 FrontendDelegateDeclarative::~FrontendDelegateDeclarative()
146 {
147     CHECK_RUN_ON(JS);
148     LOG_DESTROY();
149 }
150 
GetMinPlatformVersion()151 int32_t FrontendDelegateDeclarative::GetMinPlatformVersion()
152 {
153     return manifestParser_->GetMinPlatformVersion();
154 }
155 
RunPage(const std::string & url,const std::string & params,const std::string & profile,bool isNamedRouter)156 UIContentErrorCode FrontendDelegateDeclarative::RunPage(
157     const std::string& url, const std::string& params, const std::string& profile, bool isNamedRouter)
158 {
159     ACE_SCOPED_TRACE("FrontendDelegateDeclarative::RunPage");
160 
161     LOGI("FrontendDelegateDeclarative RunPage url=%{public}s", url.c_str());
162     std::string jsonContent;
163     if (GetAssetContent(MANIFEST_JSON, jsonContent)) {
164         manifestParser_->Parse(jsonContent);
165         manifestParser_->Printer();
166     } else if (!profile.empty() && GetAssetContent(profile, jsonContent)) {
167         LOGI("Parse profile %{public}s", profile.c_str());
168         manifestParser_->Parse(jsonContent);
169     } else if (GetAssetContent(PAGES_JSON, jsonContent)) {
170         LOGI("Parse main_pages.json");
171         manifestParser_->Parse(jsonContent);
172     } else {
173         LOGE("RunPage parse manifest.json failed");
174         EventReport::SendPageRouterException(PageRouterExcepType::RUN_PAGE_ERR, url);
175         return UIContentErrorCode::PARSE_MANIFEST_FAILED;
176     }
177 
178     taskExecutor_->PostTask(
179         [weak = AceType::WeakClaim(this)]() {
180             auto delegate = weak.Upgrade();
181             if (delegate) {
182                 delegate->manifestParser_->GetAppInfo()->ParseI18nJsonInfo();
183             }
184         },
185         TaskExecutor::TaskType::JS);
186 
187     if (Container::IsCurrentUseNewPipeline()) {
188         CHECK_NULL_RETURN(pageRouterManager_, UIContentErrorCode::NULL_PAGE_ROUTER);
189         pageRouterManager_->SetManifestParser(manifestParser_);
190         taskExecutor_->PostTask(
191             [weakPtr = WeakPtr<NG::PageRouterManager>(pageRouterManager_), url, params, isNamedRouter]() {
192                 auto pageRouterManager = weakPtr.Upgrade();
193                 CHECK_NULL_VOID(pageRouterManager);
194                 if (isNamedRouter) {
195                     pageRouterManager->RunPageByNamedRouter(url, params);
196                 } else {
197                     pageRouterManager->RunPage(url, params);
198                 }
199             },
200             TaskExecutor::TaskType::JS);
201         return UIContentErrorCode::NO_ERRORS;
202     }
203     if (!url.empty()) {
204         mainPagePath_ = manifestParser_->GetRouter()->GetPagePath(url);
205     } else {
206         mainPagePath_ = manifestParser_->GetRouter()->GetEntry();
207     }
208     AddRouterTask(RouterTask { RouterAction::PUSH, PageTarget(mainPagePath_), params });
209     return LoadPage(GenerateNextPageId(), PageTarget(mainPagePath_), true, params);
210 }
211 
RunPage(const std::shared_ptr<std::vector<uint8_t>> & content,const std::string & params,const std::string & profile)212 void FrontendDelegateDeclarative::RunPage(
213     const std::shared_ptr<std::vector<uint8_t>>& content, const std::string& params, const std::string& profile)
214 {
215     ACE_SCOPED_TRACE("FrontendDelegateDeclarativeNG::RunPage by buffer size:%zu", content->size());
216     taskExecutor_->PostTask(
217         [delegate = Claim(this), weakPtr = WeakPtr<NG::PageRouterManager>(pageRouterManager_), content, params]() {
218             auto pageRouterManager = weakPtr.Upgrade();
219             CHECK_NULL_VOID(pageRouterManager);
220             pageRouterManager->RunPage(content, params);
221             auto pipeline = delegate->GetPipelineContext();
222         },
223         TaskExecutor::TaskType::JS);
224 }
225 
ChangeLocale(const std::string & language,const std::string & countryOrRegion)226 void FrontendDelegateDeclarative::ChangeLocale(const std::string& language, const std::string& countryOrRegion)
227 {
228     taskExecutor_->PostTask(
229         [language, countryOrRegion]() { AceApplicationInfo::GetInstance().ChangeLocale(language, countryOrRegion); },
230         TaskExecutor::TaskType::PLATFORM);
231 }
232 
GetI18nData(std::unique_ptr<JsonValue> & json)233 void FrontendDelegateDeclarative::GetI18nData(std::unique_ptr<JsonValue>& json)
234 {
235     auto data = JsonUtil::CreateArray(true);
236     GetConfigurationCommon(I18N_FOLDER, data);
237     auto i18nData = JsonUtil::Create(true);
238     i18nData->Put("resources", data);
239     json->Put("i18n", i18nData);
240 }
241 
GetResourceConfiguration(std::unique_ptr<JsonValue> & json)242 void FrontendDelegateDeclarative::GetResourceConfiguration(std::unique_ptr<JsonValue>& json)
243 {
244     auto data = JsonUtil::CreateArray(true);
245     GetConfigurationCommon(RESOURCES_FOLDER, data);
246     json->Put("resourcesConfiguration", data);
247 }
248 
GetConfigurationCommon(const std::string & filePath,std::unique_ptr<JsonValue> & data)249 void FrontendDelegateDeclarative::GetConfigurationCommon(const std::string& filePath, std::unique_ptr<JsonValue>& data)
250 {
251     std::vector<std::string> files;
252     if (assetManager_) {
253         assetManager_->GetAssetList(filePath, files);
254     }
255 
256     std::vector<std::string> fileNameList;
257     for (const auto& file : files) {
258         if (EndWith(file, FILE_TYPE_JSON) && !StartWith(file, STYLES_FOLDER)) {
259             fileNameList.emplace_back(file.substr(0, file.size() - (sizeof(FILE_TYPE_JSON) - 1)));
260         }
261     }
262 
263     std::vector<std::string> priorityFileName;
264     if (filePath.compare(I18N_FOLDER) == 0) {
265         auto localeTag = AceApplicationInfo::GetInstance().GetLocaleTag();
266         priorityFileName = AceResConfig::GetLocaleFallback(localeTag, fileNameList);
267     } else {
268         priorityFileName = AceResConfig::GetResourceFallback(fileNameList);
269     }
270 
271     for (const auto& fileName : priorityFileName) {
272         auto fileFullPath = filePath + fileName + std::string(FILE_TYPE_JSON);
273         std::string content;
274         if (GetAssetContent(fileFullPath, content)) {
275             auto fileData = ParseFileData(content);
276             if (fileData == nullptr) {
277                 LOGW("parse %{private}s.json content failed", filePath.c_str());
278             } else {
279                 data->Put(fileData);
280             }
281         }
282     }
283 }
284 
LoadResourceConfiguration(std::map<std::string,std::string> & mediaResourceFileMap,std::unique_ptr<JsonValue> & currentResourceData)285 void FrontendDelegateDeclarative::LoadResourceConfiguration(
286     std::map<std::string, std::string>& mediaResourceFileMap, std::unique_ptr<JsonValue>& currentResourceData)
287 {
288     std::vector<std::string> files;
289     if (assetManager_) {
290         assetManager_->GetAssetList(RESOURCES_FOLDER, files);
291     }
292 
293     std::set<std::string> resourceFolderName;
294     for (const auto& file : files) {
295         if (file.find_first_of("/") != std::string::npos) {
296             resourceFolderName.insert(file.substr(0, file.find_first_of("/")));
297         }
298     }
299 
300     std::vector<std::string> sortedResourceFolderPath =
301         AceResConfig::GetDeclarativeResourceFallback(resourceFolderName);
302     for (const auto& folderName : sortedResourceFolderPath) {
303         auto fileFullPath = std::string(RESOURCES_FOLDER) + folderName + std::string(I18N_FILE_SUFFIX);
304         std::string content;
305         if (GetAssetContent(fileFullPath, content)) {
306             auto fileData = ParseFileData(content);
307             if (fileData == nullptr) {
308                 LOGW("parse %{private}s i18n content failed", fileFullPath.c_str());
309             } else {
310                 currentResourceData->Put(fileData);
311             }
312         }
313     }
314 
315     std::set<std::string> mediaFileName;
316     for (const auto& file : files) {
317         if (file.find_first_of("/") == std::string::npos) {
318             continue;
319         }
320         auto mediaPathName = file.substr(file.find_first_of("/"));
321         std::regex mediaPattern(R"(^\/media\/\w*(\.jpg|\.png|\.gif|\.svg|\.webp|\.bmp)$)");
322         std::smatch result;
323         if (std::regex_match(mediaPathName, result, mediaPattern)) {
324             mediaFileName.insert(mediaPathName.substr(mediaPathName.find_first_of("/")));
325         }
326     }
327 
328     auto currentResTag = AceResConfig::GetCurrentDeviceResTag();
329     auto currentResolutionTag = currentResTag.substr(currentResTag.find_last_of("-") + 1);
330     for (const auto& folderName : sortedResourceFolderPath) {
331         for (const auto& fileName : mediaFileName) {
332             if (mediaResourceFileMap.find(fileName) != mediaResourceFileMap.end()) {
333                 continue;
334             }
335             auto fullFileName = folderName + fileName;
336             if (std::find(files.begin(), files.end(), fullFileName) != files.end()) {
337                 mediaResourceFileMap.emplace(fileName.substr(fileName.find_last_of("/") + 1),
338                     std::string(RESOURCES_FOLDER).append(fullFileName));
339             }
340         }
341         if (mediaResourceFileMap.size() == mediaFileName.size()) {
342             break;
343         }
344     }
345 }
346 
OnJSCallback(const std::string & callbackId,const std::string & data)347 void FrontendDelegateDeclarative::OnJSCallback(const std::string& callbackId, const std::string& data)
348 {
349     taskExecutor_->PostTask(
350         [weak = AceType::WeakClaim(this), callbackId, args = data] {
351             auto delegate = weak.Upgrade();
352             if (delegate) {
353                 delegate->jsCallback_(callbackId, args);
354             }
355         },
356         TaskExecutor::TaskType::JS);
357 }
358 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher) const359 void FrontendDelegateDeclarative::SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher) const
360 {
361     taskExecutor_->PostTask([dispatcherCallback = dispatcherCallback_, dispatcher] { dispatcherCallback(dispatcher); },
362         TaskExecutor::TaskType::JS);
363 }
364 
TransferComponentResponseData(int32_t callbackId,int32_t,std::vector<uint8_t> && data)365 void FrontendDelegateDeclarative::TransferComponentResponseData(
366     int32_t callbackId, int32_t /*code*/, std::vector<uint8_t>&& data)
367 {
368     auto pipelineContext = pipelineContextHolder_.Get();
369     WeakPtr<PipelineBase> contextWeak(pipelineContext);
370     taskExecutor_->PostTask(
371         [callbackId, data = std::move(data), contextWeak]() mutable {
372             auto context = contextWeak.Upgrade();
373             if (!context) {
374                 LOGE("context is null");
375             } else if (!context->GetMessageBridge()) {
376                 LOGE("messageBridge is null");
377             } else {
378                 context->GetMessageBridge()->HandleCallback(callbackId, std::move(data));
379             }
380         },
381         TaskExecutor::TaskType::UI);
382 }
383 
TransferJsResponseData(int32_t callbackId,int32_t code,std::vector<uint8_t> && data) const384 void FrontendDelegateDeclarative::TransferJsResponseData(
385     int32_t callbackId, int32_t code, std::vector<uint8_t>&& data) const
386 {
387     if (groupJsBridge_ && groupJsBridge_->ForwardToWorker(callbackId)) {
388         groupJsBridge_->TriggerModuleJsCallback(callbackId, code, std::move(data));
389         return;
390     }
391 
392     taskExecutor_->PostTask(
393         [callbackId, code, data = std::move(data), groupJsBridge = groupJsBridge_]() mutable {
394             if (groupJsBridge) {
395                 groupJsBridge->TriggerModuleJsCallback(callbackId, code, std::move(data));
396             }
397         },
398         TaskExecutor::TaskType::JS);
399 }
400 
401 #if defined(PREVIEW)
TransferJsResponseDataPreview(int32_t callbackId,int32_t code,ResponseData responseData) const402 void FrontendDelegateDeclarative::TransferJsResponseDataPreview(
403     int32_t callbackId, int32_t code, ResponseData responseData) const
404 {
405     LOGI("FrontendDelegateDeclarative TransferJsResponseDataPreview");
406     taskExecutor_->PostTask(
407         [callbackId, code, responseData, groupJsBridge = groupJsBridge_]() mutable {
408             if (groupJsBridge) {
409                 groupJsBridge->TriggerModuleJsCallbackPreview(callbackId, code, responseData);
410             }
411         },
412         TaskExecutor::TaskType::JS);
413 }
414 #endif
415 
TransferJsPluginGetError(int32_t callbackId,int32_t errorCode,std::string && errorMessage) const416 void FrontendDelegateDeclarative::TransferJsPluginGetError(
417     int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
418 {
419     taskExecutor_->PostTask(
420         [callbackId, errorCode, errorMessage = std::move(errorMessage), groupJsBridge = groupJsBridge_]() mutable {
421             if (groupJsBridge) {
422                 groupJsBridge->TriggerModulePluginGetErrorCallback(callbackId, errorCode, std::move(errorMessage));
423             }
424         },
425         TaskExecutor::TaskType::JS);
426 }
427 
TransferJsEventData(int32_t callbackId,int32_t code,std::vector<uint8_t> && data) const428 void FrontendDelegateDeclarative::TransferJsEventData(
429     int32_t callbackId, int32_t code, std::vector<uint8_t>&& data) const
430 {
431     taskExecutor_->PostTask(
432         [callbackId, code, data = std::move(data), groupJsBridge = groupJsBridge_]() mutable {
433             if (groupJsBridge) {
434                 groupJsBridge->TriggerEventJsCallback(callbackId, code, std::move(data));
435             }
436         },
437         TaskExecutor::TaskType::JS);
438 }
439 
LoadPluginJsCode(std::string && jsCode) const440 void FrontendDelegateDeclarative::LoadPluginJsCode(std::string&& jsCode) const
441 {
442     taskExecutor_->PostTask(
443         [jsCode = std::move(jsCode), groupJsBridge = groupJsBridge_]() mutable {
444             if (groupJsBridge) {
445                 groupJsBridge->LoadPluginJsCode(std::move(jsCode));
446             }
447         },
448         TaskExecutor::TaskType::JS);
449 }
450 
LoadPluginJsByteCode(std::vector<uint8_t> && jsCode,std::vector<int32_t> && jsCodeLen) const451 void FrontendDelegateDeclarative::LoadPluginJsByteCode(
452     std::vector<uint8_t>&& jsCode, std::vector<int32_t>&& jsCodeLen) const
453 {
454     if (groupJsBridge_ == nullptr) {
455         LOGE("groupJsBridge_ is nullptr");
456         return;
457     }
458     taskExecutor_->PostTask(
459         [jsCode = std::move(jsCode), jsCodeLen = std::move(jsCodeLen), groupJsBridge = groupJsBridge_]() mutable {
460             groupJsBridge->LoadPluginJsByteCode(std::move(jsCode), std::move(jsCodeLen));
461         },
462         TaskExecutor::TaskType::JS);
463 }
464 
OnPageBackPress()465 bool FrontendDelegateDeclarative::OnPageBackPress()
466 {
467     if (Container::IsCurrentUseNewPipeline()) {
468         CHECK_NULL_RETURN(pageRouterManager_, false);
469         auto pageNode = pageRouterManager_->GetCurrentPageNode();
470         CHECK_NULL_RETURN(pageNode, false);
471         auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
472         CHECK_NULL_RETURN(pagePattern, false);
473         if (pagePattern->OnBackPressed()) {
474             return true;
475         }
476         return pageRouterManager_->Pop();
477     }
478 
479     auto result = false;
480     taskExecutor_->PostSyncTask(
481         [weak = AceType::WeakClaim(this), &result] {
482             auto delegate = weak.Upgrade();
483             if (!delegate) {
484                 return;
485             }
486             auto pageId = delegate->GetRunningPageId();
487             auto page = delegate->GetPage(pageId);
488             if (page) {
489                 result = page->FireDeclarativeOnBackPressCallback();
490             }
491         },
492         TaskExecutor::TaskType::JS);
493     return result;
494 }
495 
NotifyAppStorage(const WeakPtr<Framework::JsEngine> & jsEngineWeak,const std::string & key,const std::string & value)496 void FrontendDelegateDeclarative::NotifyAppStorage(
497     const WeakPtr<Framework::JsEngine>& jsEngineWeak, const std::string& key, const std::string& value)
498 {
499     taskExecutor_->PostTask(
500         [jsEngineWeak, key, value] {
501             auto jsEngine = jsEngineWeak.Upgrade();
502             if (!jsEngine) {
503                 return;
504             }
505             jsEngine->NotifyAppStorage(key, value);
506         },
507         TaskExecutor::TaskType::JS);
508 }
509 
OnBackGround()510 void FrontendDelegateDeclarative::OnBackGround()
511 {
512     OnPageHide();
513 }
514 
OnForeground()515 void FrontendDelegateDeclarative::OnForeground()
516 {
517     // first page show will be called by push page successfully
518     if (Container::IsCurrentUseNewPipeline() || !isFirstNotifyShow_) {
519         OnPageShow();
520     }
521     isFirstNotifyShow_ = false;
522 }
523 
OnConfigurationUpdated(const std::string & data)524 void FrontendDelegateDeclarative::OnConfigurationUpdated(const std::string& data)
525 {
526     taskExecutor_->PostSyncTask(
527         [onConfigurationUpdated = onConfigurationUpdated_, data] { onConfigurationUpdated(data); },
528         TaskExecutor::TaskType::JS);
529     OnMediaQueryUpdate();
530 }
531 
OnStartContinuation()532 bool FrontendDelegateDeclarative::OnStartContinuation()
533 {
534     bool ret = false;
535     taskExecutor_->PostSyncTask(
536         [weak = AceType::WeakClaim(this), &ret] {
537             auto delegate = weak.Upgrade();
538             if (delegate && delegate->onStartContinuationCallBack_) {
539                 ret = delegate->onStartContinuationCallBack_();
540             }
541         },
542         TaskExecutor::TaskType::JS);
543     return ret;
544 }
545 
OnCompleteContinuation(int32_t code)546 void FrontendDelegateDeclarative::OnCompleteContinuation(int32_t code)
547 {
548     taskExecutor_->PostSyncTask(
549         [weak = AceType::WeakClaim(this), code] {
550             auto delegate = weak.Upgrade();
551             if (delegate && delegate->onCompleteContinuationCallBack_) {
552                 delegate->onCompleteContinuationCallBack_(code);
553             }
554         },
555         TaskExecutor::TaskType::JS);
556 }
557 
OnRemoteTerminated()558 void FrontendDelegateDeclarative::OnRemoteTerminated()
559 {
560     taskExecutor_->PostSyncTask(
561         [weak = AceType::WeakClaim(this)] {
562             auto delegate = weak.Upgrade();
563             if (delegate && delegate->onRemoteTerminatedCallBack_) {
564                 delegate->onRemoteTerminatedCallBack_();
565             }
566         },
567         TaskExecutor::TaskType::JS);
568 }
569 
OnSaveData(std::string & data)570 void FrontendDelegateDeclarative::OnSaveData(std::string& data)
571 {
572     std::string savedData;
573     taskExecutor_->PostSyncTask(
574         [weak = AceType::WeakClaim(this), &savedData] {
575             auto delegate = weak.Upgrade();
576             if (delegate && delegate->onSaveDataCallBack_) {
577                 delegate->onSaveDataCallBack_(savedData);
578             }
579         },
580         TaskExecutor::TaskType::JS);
581     std::string pageUri = GetRunningPageUrl();
582     data = std::string("{\"url\":\"").append(pageUri).append("\",\"__remoteData\":").append(savedData).append("}");
583 }
584 
OnRestoreData(const std::string & data)585 bool FrontendDelegateDeclarative::OnRestoreData(const std::string& data)
586 {
587     bool ret = false;
588     taskExecutor_->PostSyncTask(
589         [weak = AceType::WeakClaim(this), &data, &ret] {
590             auto delegate = weak.Upgrade();
591             if (delegate && delegate->onRestoreDataCallBack_) {
592                 ret = delegate->onRestoreDataCallBack_(data);
593             }
594         },
595         TaskExecutor::TaskType::JS);
596     return ret;
597 }
598 
OnMemoryLevel(const int32_t level)599 void FrontendDelegateDeclarative::OnMemoryLevel(const int32_t level)
600 {
601     taskExecutor_->PostTask(
602         [onMemoryLevel = onMemoryLevel_, level]() {
603             if (onMemoryLevel) {
604                 onMemoryLevel(level);
605             }
606         },
607         TaskExecutor::TaskType::JS);
608 }
609 
GetPluginsUsed(std::string & data)610 void FrontendDelegateDeclarative::GetPluginsUsed(std::string& data)
611 {
612     if (!GetAssetContentImpl(assetManager_, "module_collection.txt", data)) {
613         LOGW("read failed, will load all the system plugin");
614         data = "All";
615     }
616 }
617 
OnNewRequest(const std::string & data)618 void FrontendDelegateDeclarative::OnNewRequest(const std::string& data)
619 {
620     FireSyncEvent("_root", std::string("\"onNewRequest\","), data);
621 }
622 
CallPopPage()623 void FrontendDelegateDeclarative::CallPopPage()
624 {
625     LOGI("CallPopPage begin");
626     Back("", "");
627 }
628 
ResetStagingPage()629 void FrontendDelegateDeclarative::ResetStagingPage()
630 {
631     if (resetStagingPage_) {
632         taskExecutor_->PostTask(
633             [resetStagingPage = resetStagingPage_] { resetStagingPage(); }, TaskExecutor::TaskType::JS);
634     } else {
635         LOGE("resetStagingPage_ is null");
636     }
637 }
638 
OnApplicationDestroy(const std::string & packageName)639 void FrontendDelegateDeclarative::OnApplicationDestroy(const std::string& packageName)
640 {
641     taskExecutor_->PostSyncTask(
642         [destroyApplication = destroyApplication_, packageName] { destroyApplication(packageName); },
643         TaskExecutor::TaskType::JS);
644 }
645 
UpdateApplicationState(const std::string & packageName,Frontend::State state)646 void FrontendDelegateDeclarative::UpdateApplicationState(const std::string& packageName, Frontend::State state)
647 {
648     taskExecutor_->PostTask([updateApplicationState = updateApplicationState_, packageName,
649                                 state] { updateApplicationState(packageName, state); },
650         TaskExecutor::TaskType::JS);
651 }
652 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)653 void FrontendDelegateDeclarative::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
654 {
655     taskExecutor_->PostTask([onWindowDisplayModeChanged = onWindowDisplayModeChanged_, isShownInMultiWindow,
656                                 data] { onWindowDisplayModeChanged(isShownInMultiWindow, data); },
657         TaskExecutor::TaskType::JS);
658 }
659 
OnSaveAbilityState(std::string & data)660 void FrontendDelegateDeclarative::OnSaveAbilityState(std::string& data)
661 {
662     taskExecutor_->PostSyncTask(
663         [onSaveAbilityState = onSaveAbilityState_, &data] { onSaveAbilityState(data); }, TaskExecutor::TaskType::JS);
664 }
665 
OnRestoreAbilityState(const std::string & data)666 void FrontendDelegateDeclarative::OnRestoreAbilityState(const std::string& data)
667 {
668     taskExecutor_->PostTask([onRestoreAbilityState = onRestoreAbilityState_, data] { onRestoreAbilityState(data); },
669         TaskExecutor::TaskType::JS);
670 }
671 
OnNewWant(const std::string & data)672 void FrontendDelegateDeclarative::OnNewWant(const std::string& data)
673 {
674     taskExecutor_->PostTask([onNewWant = onNewWant_, data] { onNewWant(data); }, TaskExecutor::TaskType::JS);
675 }
676 
FireAsyncEvent(const std::string & eventId,const std::string & param,const std::string & jsonArgs)677 void FrontendDelegateDeclarative::FireAsyncEvent(
678     const std::string& eventId, const std::string& param, const std::string& jsonArgs)
679 {
680     std::string args = param;
681     args.append(",null").append(",null"); // callback and dom changes
682     if (!jsonArgs.empty()) {
683         args.append(",").append(jsonArgs); // method args
684     }
685     taskExecutor_->PostTask(
686         [weak = AceType::WeakClaim(this), eventId, args = std::move(args)] {
687             auto delegate = weak.Upgrade();
688             if (delegate) {
689                 delegate->asyncEvent_(eventId, args);
690             }
691         },
692         TaskExecutor::TaskType::JS);
693 }
694 
FireSyncEvent(const std::string & eventId,const std::string & param,const std::string & jsonArgs)695 bool FrontendDelegateDeclarative::FireSyncEvent(
696     const std::string& eventId, const std::string& param, const std::string& jsonArgs)
697 {
698     std::string resultStr;
699     FireSyncEvent(eventId, param, jsonArgs, resultStr);
700     return (resultStr == "true");
701 }
702 
FireExternalEvent(const std::string &,const std::string & componentId,const uint32_t nodeId,const bool isDestroy)703 void FrontendDelegateDeclarative::FireExternalEvent(
704     const std::string& /*eventId*/, const std::string& componentId, const uint32_t nodeId, const bool isDestroy)
705 {
706     taskExecutor_->PostSyncTask(
707         [weak = AceType::WeakClaim(this), componentId, nodeId, isDestroy] {
708             auto delegate = weak.Upgrade();
709             if (delegate) {
710                 delegate->externalEvent_(componentId, nodeId, isDestroy);
711             }
712         },
713         TaskExecutor::TaskType::JS);
714 }
715 
FireSyncEvent(const std::string & eventId,const std::string & param,const std::string & jsonArgs,std::string & result)716 void FrontendDelegateDeclarative::FireSyncEvent(
717     const std::string& eventId, const std::string& param, const std::string& jsonArgs, std::string& result)
718 {
719     int32_t callbackId = callbackCnt_++;
720     std::string args = param;
721     args.append("{\"_callbackId\":\"").append(std::to_string(callbackId)).append("\"}").append(",null");
722     if (!jsonArgs.empty()) {
723         args.append(",").append(jsonArgs); // method args
724     }
725     taskExecutor_->PostSyncTask(
726         [weak = AceType::WeakClaim(this), eventId, args = std::move(args)] {
727             auto delegate = weak.Upgrade();
728             if (delegate) {
729                 delegate->syncEvent_(eventId, args);
730             }
731         },
732         TaskExecutor::TaskType::JS);
733 
734     result = jsCallBackResult_[callbackId];
735     jsCallBackResult_.erase(callbackId);
736 }
737 
FireAccessibilityEvent(const AccessibilityEvent & accessibilityEvent)738 void FrontendDelegateDeclarative::FireAccessibilityEvent(const AccessibilityEvent& accessibilityEvent)
739 {
740     jsAccessibilityManager_->SendAccessibilityAsyncEvent(accessibilityEvent);
741 }
742 
InitializeAccessibilityCallback()743 void FrontendDelegateDeclarative::InitializeAccessibilityCallback()
744 {
745     jsAccessibilityManager_->InitializeCallback();
746 }
747 
GetCurrentPageUrl()748 std::string FrontendDelegateDeclarative::GetCurrentPageUrl()
749 {
750     if (!Container::IsCurrentUseNewPipeline()) {
751         return "";
752     }
753     CHECK_NULL_RETURN(pageRouterManager_, "");
754     return pageRouterManager_->GetCurrentPageUrl();
755 }
756 
757 // Get the currently running JS page information in NG structure.
GetCurrentPageSourceMap()758 RefPtr<RevSourceMap> FrontendDelegateDeclarative::GetCurrentPageSourceMap()
759 {
760     if (!Container::IsCurrentUseNewPipeline()) {
761         return nullptr;
762     }
763     CHECK_NULL_RETURN(pageRouterManager_, nullptr);
764     return pageRouterManager_->GetCurrentPageSourceMap(assetManager_);
765 }
766 
767 // Get the currently running JS page information in NG structure.
GetFaAppSourceMap()768 RefPtr<RevSourceMap> FrontendDelegateDeclarative::GetFaAppSourceMap()
769 {
770     if (!Container::IsCurrentUseNewPipeline()) {
771         return nullptr;
772     }
773     if (appSourceMap_) {
774         return appSourceMap_;
775     }
776     std::string appMap;
777     if (GetAssetContent("app.js.map", appMap)) {
778         appSourceMap_ = AceType::MakeRefPtr<RevSourceMap>();
779         appSourceMap_->Init(appMap);
780     } else {
781         LOGW("app map load failed!");
782     }
783     return appSourceMap_;
784 }
785 
GetStageSourceMap(std::unordered_map<std::string,RefPtr<Framework::RevSourceMap>> & sourceMaps)786 void FrontendDelegateDeclarative::GetStageSourceMap(
787     std::unordered_map<std::string, RefPtr<Framework::RevSourceMap>>& sourceMaps)
788 {
789     if (!Container::IsCurrentUseNewPipeline()) {
790         return;
791     }
792 
793     std::string maps;
794     if (GetAssetContent(MERGE_SOURCEMAPS_PATH, maps)) {
795         auto SourceMap = AceType::MakeRefPtr<RevSourceMap>();
796         SourceMap->StageModeSourceMapSplit(maps, sourceMaps);
797     } else {
798         LOGW("app map load failed!");
799     }
800 }
801 
InitializeRouterManager(NG::LoadPageCallback && loadPageCallback,NG::LoadPageByBufferCallback && loadPageByBufferCallback,NG::LoadNamedRouterCallback && loadNamedRouterCallback,NG::UpdateRootComponentCallback && updateRootComponentCallback)802 void FrontendDelegateDeclarative::InitializeRouterManager(NG::LoadPageCallback&& loadPageCallback,
803     NG::LoadPageByBufferCallback&& loadPageByBufferCallback, NG::LoadNamedRouterCallback&& loadNamedRouterCallback,
804     NG::UpdateRootComponentCallback&& updateRootComponentCallback)
805 {
806     pageRouterManager_ = AceType::MakeRefPtr<NG::PageRouterManager>();
807     pageRouterManager_->SetLoadJsCallback(std::move(loadPageCallback));
808     pageRouterManager_->SetLoadJsByBufferCallback(std::move(loadPageByBufferCallback));
809     pageRouterManager_->SetLoadNamedRouterCallback(std::move(loadNamedRouterCallback));
810     pageRouterManager_->SetUpdateRootComponentCallback(std::move(updateRootComponentCallback));
811 }
812 
813 #if defined(PREVIEW)
SetIsComponentPreview(NG::IsComponentPreviewCallback && callback)814 void FrontendDelegateDeclarative::SetIsComponentPreview(NG::IsComponentPreviewCallback&& callback)
815 {
816     pageRouterManager_->SetIsComponentPreview(std::move(callback));
817 }
818 #endif
819 
820 // Start FrontendDelegate overrides.
Push(const std::string & uri,const std::string & params)821 void FrontendDelegateDeclarative::Push(const std::string& uri, const std::string& params)
822 {
823     if (Container::IsCurrentUseNewPipeline()) {
824         CHECK_NULL_VOID(pageRouterManager_);
825         auto currentId = GetEffectiveContainerId();
826         CHECK_EQUAL_VOID(currentId.has_value(), false);
827         ContainerScope scope(currentId.value());
828         pageRouterManager_->Push(NG::RouterPageInfo({ uri, params }));
829         OnMediaQueryUpdate();
830         return;
831     }
832 
833     Push(PageTarget(uri), params);
834 }
835 
PushWithMode(const std::string & uri,const std::string & params,uint32_t routerMode)836 void FrontendDelegateDeclarative::PushWithMode(const std::string& uri, const std::string& params, uint32_t routerMode)
837 {
838     if (Container::IsCurrentUseNewPipeline()) {
839         CHECK_NULL_VOID(pageRouterManager_);
840         auto currentId = GetEffectiveContainerId();
841         CHECK_EQUAL_VOID(currentId.has_value(), false);
842         ContainerScope scope(currentId.value());
843         pageRouterManager_->Push(NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode) }));
844         OnMediaQueryUpdate();
845         return;
846     }
847     Push(PageTarget(uri, static_cast<RouterMode>(routerMode)), params);
848 }
849 
PushWithCallback(const std::string & uri,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback,uint32_t routerMode)850 void FrontendDelegateDeclarative::PushWithCallback(const std::string& uri, const std::string& params,
851     const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode)
852 {
853     if (Container::IsCurrentUseNewPipeline()) {
854         CHECK_NULL_VOID(pageRouterManager_);
855         auto currentId = GetEffectiveContainerId();
856         CHECK_EQUAL_VOID(currentId.has_value(), false);
857         ContainerScope scope(currentId.value());
858         pageRouterManager_->Push(
859             NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode), errorCallback }));
860         OnMediaQueryUpdate();
861         return;
862     }
863     Push(PageTarget(uri, static_cast<RouterMode>(routerMode)), params, errorCallback);
864 }
865 
PushNamedRoute(const std::string & uri,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback,uint32_t routerMode)866 void FrontendDelegateDeclarative::PushNamedRoute(const std::string& uri, const std::string& params,
867     const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode)
868 {
869     CHECK_NULL_VOID(pageRouterManager_);
870     auto currentId = GetEffectiveContainerId();
871     CHECK_EQUAL_VOID(currentId.has_value(), false);
872     ContainerScope scope(currentId.value());
873     pageRouterManager_->PushNamedRoute(
874         NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode), errorCallback }));
875     OnMediaQueryUpdate();
876 }
877 
Replace(const std::string & uri,const std::string & params)878 void FrontendDelegateDeclarative::Replace(const std::string& uri, const std::string& params)
879 {
880     if (Container::IsCurrentUseNewPipeline()) {
881         CHECK_NULL_VOID(pageRouterManager_);
882         auto currentId = GetEffectiveContainerId();
883         CHECK_EQUAL_VOID(currentId.has_value(), false);
884         ContainerScope scope(currentId.value());
885         pageRouterManager_->Replace(NG::RouterPageInfo({ uri, params }));
886         OnMediaQueryUpdate();
887         return;
888     }
889     Replace(PageTarget(uri), params);
890 }
891 
ReplaceWithMode(const std::string & uri,const std::string & params,uint32_t routerMode)892 void FrontendDelegateDeclarative::ReplaceWithMode(
893     const std::string& uri, const std::string& params, uint32_t routerMode)
894 {
895     if (Container::IsCurrentUseNewPipeline()) {
896         CHECK_NULL_VOID(pageRouterManager_);
897         auto currentId = GetEffectiveContainerId();
898         CHECK_EQUAL_VOID(currentId.has_value(), false);
899         ContainerScope scope(currentId.value());
900         pageRouterManager_->Replace(NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode) }));
901         OnMediaQueryUpdate();
902         return;
903     }
904     Replace(PageTarget(uri, static_cast<RouterMode>(routerMode)), params);
905 }
906 
ReplaceWithCallback(const std::string & uri,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback,uint32_t routerMode)907 void FrontendDelegateDeclarative::ReplaceWithCallback(const std::string& uri, const std::string& params,
908     const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode)
909 {
910     if (Container::IsCurrentUseNewPipeline()) {
911         CHECK_NULL_VOID(pageRouterManager_);
912         auto currentId = GetEffectiveContainerId();
913         CHECK_EQUAL_VOID(currentId.has_value(), false);
914         ContainerScope scope(currentId.value());
915         pageRouterManager_->Replace(
916             NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode), errorCallback }));
917         OnMediaQueryUpdate();
918         return;
919     }
920     Replace(PageTarget(uri, static_cast<RouterMode>(routerMode)), params, errorCallback);
921 }
922 
ReplaceNamedRoute(const std::string & uri,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback,uint32_t routerMode)923 void FrontendDelegateDeclarative::ReplaceNamedRoute(const std::string& uri, const std::string& params,
924     const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode)
925 {
926     CHECK_NULL_VOID(pageRouterManager_);
927     auto currentId = GetEffectiveContainerId();
928     CHECK_EQUAL_VOID(currentId.has_value(), false);
929     ContainerScope scope(currentId.value());
930     pageRouterManager_->ReplaceNamedRoute(
931         NG::RouterPageInfo({ uri, params, static_cast<NG::RouterMode>(routerMode), errorCallback }));
932     OnMediaQueryUpdate();
933 }
934 
Back(const std::string & uri,const std::string & params)935 void FrontendDelegateDeclarative::Back(const std::string& uri, const std::string& params)
936 {
937     if (Container::IsCurrentUseNewPipeline()) {
938         CHECK_NULL_VOID(pageRouterManager_);
939         auto currentId = GetEffectiveContainerId();
940         CHECK_EQUAL_VOID(currentId.has_value(), false);
941         ContainerScope scope(currentId.value());
942         pageRouterManager_->BackWithTarget(NG::RouterPageInfo({ uri, params }));
943         OnMediaQueryUpdate();
944         return;
945     }
946     BackWithTarget(PageTarget(uri), params);
947 }
948 
Clear()949 void FrontendDelegateDeclarative::Clear()
950 {
951     if (Container::IsCurrentUseNewPipeline()) {
952         CHECK_NULL_VOID(pageRouterManager_);
953         auto currentId = GetEffectiveContainerId();
954         CHECK_EQUAL_VOID(currentId.has_value(), false);
955         ContainerScope scope(currentId.value());
956         pageRouterManager_->Clear();
957         return;
958     }
959     {
960         std::lock_guard<std::mutex> lock(routerQueueMutex_);
961         if (!routerQueue_.empty()) {
962             AddRouterTask(RouterTask { RouterAction::CLEAR });
963             return;
964         }
965         AddRouterTask(RouterTask { RouterAction::CLEAR });
966     }
967     ClearInvisiblePages();
968 }
969 
GetStackSize() const970 int32_t FrontendDelegateDeclarative::GetStackSize() const
971 {
972     if (Container::IsCurrentUseNewPipeline()) {
973         CHECK_NULL_RETURN(pageRouterManager_, 0);
974         auto currentId = GetEffectiveContainerId();
975         CHECK_EQUAL_RETURN(currentId.has_value(), false, 0);
976         ContainerScope scope(currentId.value());
977         return pageRouterManager_->GetStackSize();
978     }
979     std::lock_guard<std::mutex> lock(mutex_);
980     return static_cast<int32_t>(pageRouteStack_.size());
981 }
982 
GetState(int32_t & index,std::string & name,std::string & path)983 void FrontendDelegateDeclarative::GetState(int32_t& index, std::string& name, std::string& path)
984 {
985     if (Container::IsCurrentUseNewPipeline()) {
986         CHECK_NULL_VOID(pageRouterManager_);
987         auto currentId = GetEffectiveContainerId();
988         CHECK_EQUAL_VOID(currentId.has_value(), false);
989         ContainerScope scope(currentId.value());
990         pageRouterManager_->GetState(index, name, path);
991         return;
992     }
993 
994     std::string url;
995     {
996         std::lock_guard<std::mutex> lock(mutex_);
997         if (pageRouteStack_.empty()) {
998             return;
999         }
1000         index = static_cast<int32_t>(pageRouteStack_.size());
1001         url = pageRouteStack_.back().url;
1002     }
1003     auto pos = url.rfind(".js");
1004     if (pos == url.length() - 3) {
1005         url = url.substr(0, pos);
1006     }
1007     pos = url.rfind("/");
1008     if (pos != std::string::npos) {
1009         name = url.substr(pos + 1);
1010         path = url.substr(0, pos + 1);
1011     }
1012 }
1013 
GetParams()1014 std::string FrontendDelegateDeclarative::GetParams()
1015 {
1016     if (Container::IsCurrentUseNewPipeline()) {
1017         CHECK_NULL_RETURN(pageRouterManager_, "");
1018         auto currentId = GetEffectiveContainerId();
1019         CHECK_EQUAL_RETURN(currentId.has_value(), false, "");
1020         ContainerScope scope(currentId.value());
1021         return pageRouterManager_->GetParams();
1022     }
1023     if (pageParamMap_.find(pageId_) != pageParamMap_.end()) {
1024         return pageParamMap_.find(pageId_)->second;
1025     }
1026     return "";
1027 }
1028 
GetIndexByUrl(const std::string & url)1029 int32_t FrontendDelegateDeclarative::GetIndexByUrl(const std::string& url)
1030 {
1031     if (Container::IsCurrentUseNewPipeline()) {
1032         CHECK_NULL_RETURN(pageRouterManager_, INVALID_PAGE_ID);
1033         auto currentId = GetEffectiveContainerId();
1034         CHECK_EQUAL_RETURN(currentId.has_value(), false, 0);
1035         ContainerScope scope(currentId.value());
1036         return pageRouterManager_->GetIndexByUrl(url);
1037     }
1038     std::lock_guard<std::mutex> lock(mutex_);
1039     for (int32_t i = 0; i < pageRouteStack_.size(); ++ i) {
1040         if (pageRouteStack_[i].url == url) {
1041             return i;
1042         }
1043     }
1044     return INVALID_PAGE_ID;
1045 }
1046 
AddRouterTask(const RouterTask & task)1047 void FrontendDelegateDeclarative::AddRouterTask(const RouterTask& task)
1048 {
1049     if (routerQueue_.size() < MAX_ROUTER_STACK) {
1050         routerQueue_.emplace(task);
1051     }
1052 }
1053 
ProcessRouterTask()1054 void FrontendDelegateDeclarative::ProcessRouterTask()
1055 {
1056     std::lock_guard<std::mutex> lock(routerQueueMutex_);
1057     if (!routerQueue_.empty()) {
1058         routerQueue_.pop();
1059     }
1060     if (routerQueue_.empty()) {
1061         return;
1062     }
1063     RouterTask currentTask = routerQueue_.front();
1064     LOGI("ProcessRouterTask current size = %{public}zu, action = %{public}d, url = %{public}s", routerQueue_.size(),
1065         static_cast<uint32_t>(currentTask.action), currentTask.target.url.c_str());
1066     taskExecutor_->PostTask(
1067         [weak = AceType::WeakClaim(this), currentTask] {
1068             auto delegate = weak.Upgrade();
1069             if (!delegate) {
1070                 return;
1071             }
1072             switch (currentTask.action) {
1073                 case RouterAction::PUSH:
1074                     delegate->StartPush(currentTask.target, currentTask.params, currentTask.errorCallback);
1075                     break;
1076                 case RouterAction::REPLACE:
1077                     delegate->StartReplace(currentTask.target, currentTask.params, currentTask.errorCallback);
1078                     break;
1079                 case RouterAction::BACK:
1080                     delegate->BackCheckAlert(currentTask.target, currentTask.params);
1081                     break;
1082                 case RouterAction::CLEAR:
1083                     delegate->ClearInvisiblePages();
1084                     break;
1085                 default:
1086                     break;
1087             }
1088         },
1089         TaskExecutor::TaskType::JS);
1090 }
1091 
IsNavigationStage(const PageTarget & target)1092 bool FrontendDelegateDeclarative::IsNavigationStage(const PageTarget& target)
1093 {
1094     return target.container.Upgrade();
1095 }
1096 
Push(const PageTarget & target,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback)1097 void FrontendDelegateDeclarative::Push(const PageTarget& target, const std::string& params,
1098     const std::function<void(const std::string&, int32_t)>& errorCallback)
1099 {
1100     if (IsNavigationStage(target)) {
1101         StartPush(target, params, errorCallback);
1102         return;
1103     }
1104     {
1105         std::lock_guard<std::mutex> lock(routerQueueMutex_);
1106         if (!routerQueue_.empty()) {
1107             AddRouterTask(RouterTask { RouterAction::PUSH, target, params, errorCallback });
1108             return;
1109         }
1110         AddRouterTask(RouterTask { RouterAction::PUSH, target, params, errorCallback });
1111     }
1112     StartPush(target, params, errorCallback);
1113 }
1114 
StartPush(const PageTarget & target,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback)1115 void FrontendDelegateDeclarative::StartPush(const PageTarget& target, const std::string& params,
1116     const std::function<void(const std::string&, int32_t)>& errorCallback)
1117 {
1118     if (target.url.empty()) {
1119         LOGE("router.Push uri is empty");
1120         ProcessRouterTask();
1121         return;
1122     }
1123     if (isRouteStackFull_) {
1124         LOGE("the router stack has reached its max size, you can't push any more pages.");
1125         EventReport::SendPageRouterException(PageRouterExcepType::PAGE_STACK_OVERFLOW_ERR, target.url);
1126         if (errorCallback != nullptr) {
1127             errorCallback("The pages are pushed too much.", ERROR_CODE_PAGE_STACK_FULL);
1128         }
1129         ProcessRouterTask();
1130         return;
1131     }
1132 
1133     std::string pagePath = manifestParser_->GetRouter()->GetPagePath(target.url);
1134     if (!pagePath.empty()) {
1135         LoadPage(GenerateNextPageId(), PageTarget(target, pagePath), false, params);
1136         if (errorCallback != nullptr) {
1137             errorCallback("", ERROR_CODE_NO_ERROR);
1138         }
1139     } else {
1140         LOGW("[Engine Log] this uri not support in route push.");
1141         if (errorCallback != nullptr) {
1142             errorCallback("The uri of router is not exist.", ERROR_CODE_URI_ERROR);
1143         }
1144         ProcessRouterTask();
1145     }
1146 }
1147 
Replace(const PageTarget & target,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback)1148 void FrontendDelegateDeclarative::Replace(const PageTarget& target, const std::string& params,
1149     const std::function<void(const std::string&, int32_t)>& errorCallback)
1150 {
1151     if (IsNavigationStage(target)) {
1152         StartReplace(target, params, errorCallback);
1153         return;
1154     }
1155     {
1156         std::lock_guard<std::mutex> lock(routerQueueMutex_);
1157         if (!routerQueue_.empty()) {
1158             AddRouterTask(RouterTask { RouterAction::REPLACE, target, params, errorCallback });
1159             return;
1160         }
1161         AddRouterTask(RouterTask { RouterAction::REPLACE, target, params, errorCallback });
1162     }
1163     StartReplace(target, params, errorCallback);
1164 }
1165 
StartReplace(const PageTarget & target,const std::string & params,const std::function<void (const std::string &,int32_t)> & errorCallback)1166 void FrontendDelegateDeclarative::StartReplace(const PageTarget& target, const std::string& params,
1167     const std::function<void(const std::string&, int32_t)>& errorCallback)
1168 {
1169     if (target.url.empty()) {
1170         LOGE("router.Replace uri is empty");
1171         ProcessRouterTask();
1172         return;
1173     }
1174 
1175     std::string pagePath = manifestParser_->GetRouter()->GetPagePath(target.url);
1176     if (!pagePath.empty()) {
1177         LoadReplacePage(GenerateNextPageId(), PageTarget(target, pagePath), params);
1178         if (errorCallback != nullptr) {
1179             errorCallback("", ERROR_CODE_NO_ERROR);
1180         }
1181     } else {
1182         LOGW("[Engine Log] this uri not support in route replace.");
1183         if (errorCallback != nullptr) {
1184             errorCallback("The uri of router is not exist.", ERROR_CODE_URI_ERROR_LITE);
1185         }
1186         ProcessRouterTask();
1187     }
1188 }
1189 
PostponePageTransition()1190 void FrontendDelegateDeclarative::PostponePageTransition()
1191 {
1192     taskExecutor_->PostTask(
1193         [weak = AceType::WeakClaim(this)] {
1194             auto delegate = weak.Upgrade();
1195             if (!delegate) {
1196                 return;
1197             }
1198             auto pipelineContext = delegate->pipelineContextHolder_.Get();
1199             pipelineContext->PostponePageTransition();
1200         },
1201         TaskExecutor::TaskType::UI);
1202 }
1203 
LaunchPageTransition()1204 void FrontendDelegateDeclarative::LaunchPageTransition()
1205 {
1206     taskExecutor_->PostTask(
1207         [weak = AceType::WeakClaim(this)] {
1208             auto delegate = weak.Upgrade();
1209             if (!delegate) {
1210                 return;
1211             }
1212             auto pipelineContext = delegate->pipelineContextHolder_.Get();
1213             pipelineContext->LaunchPageTransition();
1214         },
1215         TaskExecutor::TaskType::UI);
1216 }
1217 
BackCheckAlert(const PageTarget & target,const std::string & params)1218 void FrontendDelegateDeclarative::BackCheckAlert(const PageTarget& target, const std::string& params)
1219 {
1220     {
1221         std::lock_guard<std::mutex> lock(mutex_);
1222         if (pageRouteStack_.empty()) {
1223             LOGI("page route stack is empty");
1224             ProcessRouterTask();
1225             return;
1226         }
1227         auto& currentPage = pageRouteStack_.back();
1228         if (currentPage.alertCallback) {
1229             backUri_ = target;
1230             backParam_ = params;
1231             auto context = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1232             taskExecutor_->PostTask(
1233                 [context, dialogProperties = pageRouteStack_.back().dialogProperties,
1234                     isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft()]() {
1235                     if (context) {
1236                         context->ShowDialog(dialogProperties, isRightToLeft);
1237                     }
1238                 },
1239                 TaskExecutor::TaskType::UI);
1240             return;
1241         }
1242     }
1243     StartBack(target, params);
1244 }
1245 
BackWithTarget(const PageTarget & target,const std::string & params)1246 void FrontendDelegateDeclarative::BackWithTarget(const PageTarget& target, const std::string& params)
1247 {
1248     if (IsNavigationStage(target)) {
1249         BackCheckAlert(target, params);
1250         return;
1251     }
1252     {
1253         std::lock_guard<std::mutex> lock(routerQueueMutex_);
1254         if (!routerQueue_.empty()) {
1255             AddRouterTask(RouterTask { RouterAction::BACK, target, params });
1256             return;
1257         }
1258         AddRouterTask(RouterTask { RouterAction::BACK, target, params });
1259     }
1260     BackCheckAlert(target, params);
1261 }
1262 
StartBack(const PageTarget & target,const std::string & params)1263 void FrontendDelegateDeclarative::StartBack(const PageTarget& target, const std::string& params)
1264 {
1265     if (target.url.empty()) {
1266         std::string pagePath;
1267         {
1268             std::lock_guard<std::mutex> lock(mutex_);
1269             size_t pageRouteSize = pageRouteStack_.size();
1270             if (pageRouteSize > 1) {
1271                 pageId_ = pageRouteStack_[pageRouteSize - 2].pageId;
1272                 if (!params.empty()) {
1273                     pageParamMap_[pageId_] = params;
1274                 }
1275                 // determine whether the previous page needs to be loaded
1276                 if (pageRouteStack_[pageRouteSize - 2].isRestore) {
1277                     pagePath = pageRouteStack_[pageRouteSize - 2].url;
1278                 }
1279             }
1280         }
1281         if (!pagePath.empty()) {
1282             LoadPage(pageId_, PageTarget(target, pagePath), false, params, true);
1283             return;
1284         }
1285         LOGI("run in normal back");
1286         PopPage();
1287     } else {
1288         std::string pagePath = manifestParser_->GetRouter()->GetPagePath(target.url, ".js");
1289         if (!pagePath.empty()) {
1290             bool isRestore = false;
1291             pageId_ = GetPageIdByUrl(pagePath, isRestore);
1292             if (isRestore) {
1293                 LoadPage(pageId_, PageTarget(target, pagePath), false, params, true);
1294                 return;
1295             }
1296             if (!params.empty()) {
1297                 std::lock_guard<std::mutex> lock(mutex_);
1298                 pageParamMap_[pageId_] = params;
1299             }
1300             PopToPage(pagePath);
1301         } else {
1302             LOGW("[Engine Log] this uri not support in route Back.");
1303             ProcessRouterTask();
1304         }
1305     }
1306 }
1307 
GetComponentsCount()1308 size_t FrontendDelegateDeclarative::GetComponentsCount()
1309 {
1310     if (Container::IsCurrentUseNewPipeline()) {
1311         CHECK_NULL_RETURN(pageRouterManager_, 0);
1312         auto pageNode = pageRouterManager_->GetCurrentPageNode();
1313         CHECK_NULL_RETURN(pageNode, 0);
1314         return pageNode->GetAllDepthChildrenCount();
1315     }
1316     auto pipelineContext = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1317     CHECK_NULL_RETURN(pipelineContext, 0);
1318     const auto& pageElement = pipelineContext->GetLastPage();
1319     if (pageElement) {
1320         return pageElement->GetComponentsCount();
1321     }
1322     return 0;
1323 }
1324 
TriggerPageUpdate(int32_t pageId,bool directExecute)1325 void FrontendDelegateDeclarative::TriggerPageUpdate(int32_t pageId, bool directExecute)
1326 {
1327     auto page = GetPage(pageId);
1328     if (!page) {
1329         return;
1330     }
1331 
1332     auto jsPage = AceType::DynamicCast<Framework::JsAcePage>(page);
1333     ACE_DCHECK(jsPage);
1334 
1335     // Pop all JS command and execute them in UI thread.
1336     auto jsCommands = std::make_shared<std::vector<RefPtr<JsCommand>>>();
1337     jsPage->PopAllCommands(*jsCommands);
1338 
1339     auto pipelineContext = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1340     WeakPtr<Framework::JsAcePage> jsPageWeak(jsPage);
1341     WeakPtr<PipelineContext> contextWeak(pipelineContext);
1342     auto updateTask = [jsPageWeak, contextWeak, jsCommands] {
1343         ACE_SCOPED_TRACE("FlushUpdateCommands");
1344         auto jsPage = jsPageWeak.Upgrade();
1345         auto context = contextWeak.Upgrade();
1346         if (!jsPage || !context) {
1347             LOGE("Page update failed. page or context is null.");
1348             EventReport::SendPageRouterException(PageRouterExcepType::UPDATE_PAGE_ERR);
1349             return;
1350         }
1351         // Flush all JS commands.
1352         for (const auto& command : *jsCommands) {
1353             command->Execute(jsPage);
1354         }
1355         if (jsPage->GetDomDocument()) {
1356             jsPage->GetDomDocument()->HandleComponentPostBinding();
1357         }
1358         auto accessibilityManager = context->GetAccessibilityManager();
1359         if (accessibilityManager) {
1360             accessibilityManager->HandleComponentPostBinding();
1361         }
1362 
1363         jsPage->ClearShowCommand();
1364         std::vector<NodeId> dirtyNodes;
1365         jsPage->PopAllDirtyNodes(dirtyNodes);
1366         for (auto nodeId : dirtyNodes) {
1367             auto patchComponent = jsPage->BuildPagePatch(nodeId);
1368             if (patchComponent) {
1369                 context->ScheduleUpdate(patchComponent);
1370             }
1371         }
1372     };
1373 
1374     taskExecutor_->PostTask(
1375         [updateTask, pipelineContext, directExecute]() {
1376             if (pipelineContext) {
1377                 pipelineContext->AddPageUpdateTask(std::move(updateTask), directExecute);
1378             }
1379         },
1380         TaskExecutor::TaskType::UI);
1381 }
1382 
PostJsTask(std::function<void ()> && task)1383 void FrontendDelegateDeclarative::PostJsTask(std::function<void()>&& task)
1384 {
1385     taskExecutor_->PostTask(task, TaskExecutor::TaskType::JS);
1386 }
1387 
GetAppID() const1388 const std::string& FrontendDelegateDeclarative::GetAppID() const
1389 {
1390     return manifestParser_->GetAppInfo()->GetAppID();
1391 }
1392 
GetAppName() const1393 const std::string& FrontendDelegateDeclarative::GetAppName() const
1394 {
1395     return manifestParser_->GetAppInfo()->GetAppName();
1396 }
1397 
GetVersionName() const1398 const std::string& FrontendDelegateDeclarative::GetVersionName() const
1399 {
1400     return manifestParser_->GetAppInfo()->GetVersionName();
1401 }
1402 
GetVersionCode() const1403 int32_t FrontendDelegateDeclarative::GetVersionCode() const
1404 {
1405     return manifestParser_->GetAppInfo()->GetVersionCode();
1406 }
1407 
MeasureText(const MeasureContext & context)1408 double FrontendDelegateDeclarative::MeasureText(const MeasureContext& context)
1409 {
1410     return MeasureUtil::MeasureText(context);
1411 }
1412 
MeasureTextSize(const MeasureContext & context)1413 Size FrontendDelegateDeclarative::MeasureTextSize(const MeasureContext& context)
1414 {
1415     return MeasureUtil::MeasureTextSize(context);
1416 }
1417 
ShowToast(const std::string & message,int32_t duration,const std::string & bottom,const NG::ToastShowMode & showMode)1418 void FrontendDelegateDeclarative::ShowToast(
1419     const std::string& message, int32_t duration, const std::string& bottom, const NG::ToastShowMode& showMode)
1420 {
1421     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast enter");
1422     int32_t durationTime = std::clamp(duration, TOAST_TIME_DEFAULT, TOAST_TIME_MAX);
1423     bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
1424     if (Container::IsCurrentUseNewPipeline()) {
1425         auto task = [durationTime, message, bottom, isRightToLeft, showMode, containerId = Container::CurrentId()](
1426                         const RefPtr<NG::OverlayManager>& overlayManager) {
1427             CHECK_NULL_VOID(overlayManager);
1428             ContainerScope scope(containerId);
1429             overlayManager->ShowToast(message, durationTime, bottom, isRightToLeft, showMode);
1430         };
1431         MainWindowOverlay(std::move(task));
1432         return;
1433     }
1434     auto pipeline = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1435     taskExecutor_->PostTask(
1436         [durationTime, message, bottom, isRightToLeft, context = pipeline] {
1437             ToastComponent::GetInstance().Show(context, message, durationTime, bottom, isRightToLeft);
1438         },
1439         TaskExecutor::TaskType::UI);
1440 }
1441 
SetToastStopListenerCallback(std::function<void ()> && stopCallback)1442 void FrontendDelegateDeclarative::SetToastStopListenerCallback(std::function<void()>&& stopCallback)
1443 {
1444     TAG_LOGD(AceLogTag::ACE_OVERLAY, "set toast stop listener enter");
1445     ToastComponent::GetInstance().SetToastStopListenerCallback(std::move(stopCallback));
1446 }
1447 
ShowDialogInner(DialogProperties & dialogProperties,std::function<void (int32_t,int32_t)> && callback,const std::set<std::string> & callbacks)1448 void FrontendDelegateDeclarative::ShowDialogInner(DialogProperties& dialogProperties,
1449     std::function<void(int32_t, int32_t)>&& callback, const std::set<std::string>& callbacks)
1450 {
1451     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog inner enter");
1452     auto pipelineContext = pipelineContextHolder_.Get();
1453     if (Container::IsCurrentUseNewPipeline()) {
1454         LOGI("Dialog IsCurrentUseNewPipeline.");
1455         dialogProperties.onSuccess = std::move(callback);
1456         dialogProperties.onCancel = [callback, taskExecutor = taskExecutor_] {
1457             taskExecutor->PostTask([callback]() { callback(CALLBACK_ERRORCODE_CANCEL, CALLBACK_DATACODE_ZERO); },
1458                 TaskExecutor::TaskType::JS);
1459         };
1460         auto task = [dialogProperties](const RefPtr<NG::OverlayManager>& overlayManager) {
1461             CHECK_NULL_VOID(overlayManager);
1462             RefPtr<NG::FrameNode> dialog;
1463             LOGI("Begin to show dialog ");
1464             if (dialogProperties.isShowInSubWindow) {
1465                 dialog = SubwindowManager::GetInstance()->ShowDialogNG(dialogProperties, nullptr);
1466                 CHECK_NULL_VOID(dialog);
1467                 if (dialogProperties.isModal) {
1468                     DialogProperties Maskarg;
1469                     Maskarg.isMask = true;
1470                     Maskarg.autoCancel = dialogProperties.autoCancel;
1471                     auto mask = overlayManager->ShowDialog(Maskarg, nullptr, false);
1472                     CHECK_NULL_VOID(mask);
1473                     overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
1474                 }
1475             } else {
1476                 dialog = overlayManager->ShowDialog(
1477                     dialogProperties, nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
1478                 CHECK_NULL_VOID(dialog);
1479             }
1480         };
1481         MainWindowOverlay(std::move(task));
1482         return;
1483     }
1484     std::unordered_map<std::string, EventMarker> callbackMarkers;
1485     if (callbacks.find(COMMON_SUCCESS) != callbacks.end()) {
1486         auto successEventMarker = BackEndEventManager<void(int32_t)>::GetInstance().GetAvailableMarker();
1487         BackEndEventManager<void(int32_t)>::GetInstance().BindBackendEvent(
1488             successEventMarker, [callback, taskExecutor = taskExecutor_](int32_t successType) {
1489                 taskExecutor->PostTask([callback, successType]() { callback(CALLBACK_ERRORCODE_SUCCESS, successType); },
1490                     TaskExecutor::TaskType::JS);
1491             });
1492         callbackMarkers.emplace(COMMON_SUCCESS, successEventMarker);
1493     }
1494 
1495     if (callbacks.find(COMMON_CANCEL) != callbacks.end()) {
1496         auto cancelEventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1497         BackEndEventManager<void()>::GetInstance().BindBackendEvent(
1498             cancelEventMarker, [callback, taskExecutor = taskExecutor_] {
1499                 taskExecutor->PostTask([callback]() { callback(CALLBACK_ERRORCODE_CANCEL, CALLBACK_DATACODE_ZERO); },
1500                     TaskExecutor::TaskType::JS);
1501             });
1502         callbackMarkers.emplace(COMMON_CANCEL, cancelEventMarker);
1503     }
1504 
1505     if (callbacks.find(COMMON_COMPLETE) != callbacks.end()) {
1506         auto completeEventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1507         BackEndEventManager<void()>::GetInstance().BindBackendEvent(
1508             completeEventMarker, [callback, taskExecutor = taskExecutor_] {
1509                 taskExecutor->PostTask([callback]() { callback(CALLBACK_ERRORCODE_COMPLETE, CALLBACK_DATACODE_ZERO); },
1510                     TaskExecutor::TaskType::JS);
1511             });
1512         callbackMarkers.emplace(COMMON_COMPLETE, completeEventMarker);
1513     }
1514     dialogProperties.callbacks = std::move(callbackMarkers);
1515     auto context = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1516     CHECK_NULL_VOID(context);
1517     context->ShowDialog(dialogProperties, AceApplicationInfo::GetInstance().IsRightToLeft());
1518 }
1519 
ShowDialog(const std::string & title,const std::string & message,const std::vector<ButtonInfo> & buttons,bool autoCancel,std::function<void (int32_t,int32_t)> && callback,const std::set<std::string> & callbacks)1520 void FrontendDelegateDeclarative::ShowDialog(const std::string& title, const std::string& message,
1521     const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& callback,
1522     const std::set<std::string>& callbacks)
1523 {
1524     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1525     DialogProperties dialogProperties = {
1526         .title = title,
1527         .content = message,
1528         .autoCancel = autoCancel,
1529         .buttons = buttons,
1530     };
1531     ShowDialogInner(dialogProperties, std::move(callback), callbacks);
1532 }
1533 
ShowDialog(const std::string & title,const std::string & message,const std::vector<ButtonInfo> & buttons,bool autoCancel,std::function<void (int32_t,int32_t)> && callback,const std::set<std::string> & callbacks,std::function<void (bool)> && onStatusChanged)1534 void FrontendDelegateDeclarative::ShowDialog(const std::string& title, const std::string& message,
1535     const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& callback,
1536     const std::set<std::string>& callbacks, std::function<void(bool)>&& onStatusChanged)
1537 {
1538     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1539     DialogProperties dialogProperties = {
1540         .title = title,
1541         .content = message,
1542         .autoCancel = autoCancel,
1543         .buttons = buttons,
1544         .onStatusChanged = std::move(onStatusChanged),
1545     };
1546     ShowDialogInner(dialogProperties, std::move(callback), callbacks);
1547 }
1548 
ShowDialog(const PromptDialogAttr & dialogAttr,const std::vector<ButtonInfo> & buttons,std::function<void (int32_t,int32_t)> && callback,const std::set<std::string> & callbacks)1549 void FrontendDelegateDeclarative::ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
1550     std::function<void(int32_t, int32_t)>&& callback, const std::set<std::string>& callbacks)
1551 {
1552     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1553     DialogProperties dialogProperties = {
1554         .title = dialogAttr.title,
1555         .content = dialogAttr.message,
1556         .autoCancel = dialogAttr.autoCancel,
1557         .buttons = buttons,
1558         .isShowInSubWindow = dialogAttr.showInSubWindow,
1559         .isModal = dialogAttr.isModal,
1560         .maskRect = dialogAttr.maskRect,
1561     };
1562     if (dialogAttr.alignment.has_value()) {
1563         dialogProperties.alignment = dialogAttr.alignment.value();
1564     }
1565     if (dialogAttr.offset.has_value()) {
1566         dialogProperties.offset = dialogAttr.offset.value();
1567     }
1568     ShowDialogInner(dialogProperties, std::move(callback), callbacks);
1569 }
1570 
ShowDialog(const PromptDialogAttr & dialogAttr,const std::vector<ButtonInfo> & buttons,std::function<void (int32_t,int32_t)> && callback,const std::set<std::string> & callbacks,std::function<void (bool)> && onStatusChanged)1571 void FrontendDelegateDeclarative::ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
1572     std::function<void(int32_t, int32_t)>&& callback, const std::set<std::string>& callbacks,
1573     std::function<void(bool)>&& onStatusChanged)
1574 {
1575     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1576     DialogProperties dialogProperties = {
1577         .title = dialogAttr.title,
1578         .content = dialogAttr.message,
1579         .autoCancel = dialogAttr.autoCancel,
1580         .buttons = buttons,
1581         .isShowInSubWindow = dialogAttr.showInSubWindow,
1582         .isModal = dialogAttr.isModal,
1583         .onStatusChanged = std::move(onStatusChanged),
1584         .maskRect = dialogAttr.maskRect,
1585     };
1586     if (dialogAttr.alignment.has_value()) {
1587         dialogProperties.alignment = dialogAttr.alignment.value();
1588     }
1589     if (dialogAttr.offset.has_value()) {
1590         dialogProperties.offset = dialogAttr.offset.value();
1591     }
1592     ShowDialogInner(dialogProperties, std::move(callback), callbacks);
1593 }
1594 
OpenCustomDialog(const PromptDialogAttr & dialogAttr,std::function<void (int32_t)> && callback)1595 void FrontendDelegateDeclarative::OpenCustomDialog(const PromptDialogAttr &dialogAttr,
1596     std::function<void(int32_t)> &&callback)
1597 {
1598     DialogProperties dialogProperties = {
1599         .isShowInSubWindow = dialogAttr.showInSubWindow,
1600         .isModal = dialogAttr.isModal,
1601         .isSysBlurStyle = false,
1602         .customBuilder = dialogAttr.customBuilder,
1603         .maskRect = dialogAttr.maskRect,
1604     };
1605     if (dialogAttr.alignment.has_value()) {
1606         dialogProperties.alignment = dialogAttr.alignment.value();
1607     }
1608     if (dialogAttr.offset.has_value()) {
1609         dialogProperties.offset = dialogAttr.offset.value();
1610     }
1611     auto pipelineContext = pipelineContextHolder_.Get();
1612     if (Container::IsCurrentUseNewPipeline()) {
1613         LOGI("Dialog IsCurrentUseNewPipeline.");
1614         auto task = [dialogAttr, dialogProperties, callback](const RefPtr<NG::OverlayManager>& overlayManager) mutable {
1615             CHECK_NULL_VOID(overlayManager);
1616             LOGI("Begin to open custom dialog ");
1617             if (dialogProperties.isShowInSubWindow) {
1618                 SubwindowManager::GetInstance()->OpenCustomDialog(dialogAttr, std::move(callback));
1619                 if (dialogProperties.isModal) {
1620                     // temporary not support isShowInSubWindow and isModal
1621                     LOGW("temporary not support isShowInSubWindow and isModal");
1622                 }
1623             } else {
1624                 overlayManager->OpenCustomDialog(dialogProperties, std::move(callback));
1625             }
1626         };
1627         MainWindowOverlay(std::move(task));
1628         return;
1629     } else {
1630         LOGW("not support old pipeline");
1631     }
1632     return;
1633 }
1634 
CloseCustomDialog(const int32_t dialogId)1635 void FrontendDelegateDeclarative::CloseCustomDialog(const int32_t dialogId)
1636 {
1637     auto task = [dialogId](const RefPtr<NG::OverlayManager>& overlayManager) {
1638         CHECK_NULL_VOID(overlayManager);
1639         LOGI("begin to close custom dialog.");
1640         overlayManager->CloseCustomDialog(dialogId);
1641     };
1642     MainWindowOverlay(std::move(task));
1643     return;
1644 }
1645 
ShowActionMenuInner(DialogProperties & dialogProperties,const std::vector<ButtonInfo> & button,std::function<void (int32_t,int32_t)> && callback)1646 void FrontendDelegateDeclarative::ShowActionMenuInner(DialogProperties& dialogProperties,
1647     const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
1648 {
1649     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show action menu inner enter");
1650     ButtonInfo buttonInfo = { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"), .textColor = "" };
1651     dialogProperties.buttons.emplace_back(buttonInfo);
1652     if (Container::IsCurrentUseNewPipeline()) {
1653         dialogProperties.onSuccess = std::move(callback);
1654         dialogProperties.onCancel = [callback, taskExecutor = taskExecutor_] {
1655             taskExecutor->PostTask([callback]() { callback(CALLBACK_ERRORCODE_CANCEL, CALLBACK_DATACODE_ZERO); },
1656                 TaskExecutor::TaskType::JS);
1657         };
1658         auto context = DynamicCast<NG::PipelineContext>(pipelineContextHolder_.Get());
1659         auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1660         taskExecutor_->PostTask(
1661             [dialogProperties, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1662                 auto overlayManager = weak.Upgrade();
1663                 CHECK_NULL_VOID(overlayManager);
1664                 RefPtr<NG::FrameNode> dialog;
1665                 if (dialogProperties.isShowInSubWindow) {
1666                     dialog = SubwindowManager::GetInstance()->ShowDialogNG(dialogProperties, nullptr);
1667                     CHECK_NULL_VOID(dialog);
1668                     if (dialogProperties.isModal) {
1669                         DialogProperties Maskarg;
1670                         Maskarg.isMask = true;
1671                         Maskarg.autoCancel = dialogProperties.autoCancel;
1672                         auto mask = overlayManager->ShowDialog(Maskarg, nullptr, false);
1673                         CHECK_NULL_VOID(mask);
1674                         overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
1675                     }
1676                 } else {
1677                     dialog = overlayManager->ShowDialog(
1678                         dialogProperties, nullptr, AceApplicationInfo::GetInstance().IsRightToLeft());
1679                     CHECK_NULL_VOID(dialog);
1680                 }
1681             },
1682             TaskExecutor::TaskType::UI);
1683         return;
1684     }
1685 
1686     std::unordered_map<std::string, EventMarker> callbackMarkers;
1687     auto successEventMarker = BackEndEventManager<void(int32_t)>::GetInstance().GetAvailableMarker();
1688     BackEndEventManager<void(int32_t)>::GetInstance().BindBackendEvent(
1689         successEventMarker, [callback, number = button.size(), taskExecutor = taskExecutor_](int32_t successType) {
1690             taskExecutor->PostTask(
1691                 [callback, number, successType]() {
1692                     // if callback index is larger than button's number, cancel button is selected
1693                     if (static_cast<size_t>(successType) == number) {
1694                         callback(CALLBACK_ERRORCODE_CANCEL, CALLBACK_DATACODE_ZERO);
1695                     } else {
1696                         callback(CALLBACK_ERRORCODE_SUCCESS, successType);
1697                     }
1698                 },
1699                 TaskExecutor::TaskType::JS);
1700         });
1701     callbackMarkers.emplace(COMMON_SUCCESS, successEventMarker);
1702 
1703     auto cancelEventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1704     BackEndEventManager<void()>::GetInstance().BindBackendEvent(
1705         cancelEventMarker, [callback, taskExecutor = taskExecutor_] {
1706             taskExecutor->PostTask([callback]() { callback(CALLBACK_ERRORCODE_CANCEL, CALLBACK_DATACODE_ZERO); },
1707                 TaskExecutor::TaskType::JS);
1708         });
1709     callbackMarkers.emplace(COMMON_CANCEL, cancelEventMarker);
1710     dialogProperties.callbacks = std::move(callbackMarkers);
1711     auto context = AceType::DynamicCast<PipelineContext>(pipelineContextHolder_.Get());
1712     CHECK_NULL_VOID(context);
1713     context->ShowDialog(dialogProperties, AceApplicationInfo::GetInstance().IsRightToLeft());
1714 }
1715 
ShowActionMenu(const std::string & title,const std::vector<ButtonInfo> & button,std::function<void (int32_t,int32_t)> && callback)1716 void FrontendDelegateDeclarative::ShowActionMenu(
1717     const std::string& title, const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
1718 {
1719     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show action menu enter");
1720     DialogProperties dialogProperties = {
1721         .title = title,
1722         .autoCancel = true,
1723         .isMenu = true,
1724         .buttons = button,
1725     };
1726     ShowActionMenuInner(dialogProperties, button, std::move(callback));
1727 }
1728 
ShowActionMenu(const std::string & title,const std::vector<ButtonInfo> & button,std::function<void (int32_t,int32_t)> && callback,std::function<void (bool)> && onStatusChanged)1729 void FrontendDelegateDeclarative::ShowActionMenu(const std::string& title, const std::vector<ButtonInfo>& button,
1730     std::function<void(int32_t, int32_t)>&& callback, std::function<void(bool)>&& onStatusChanged)
1731 {
1732     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show action menu enter");
1733     DialogProperties dialogProperties = {
1734         .title = title,
1735         .autoCancel = true,
1736         .isMenu = true,
1737         .buttons = button,
1738         .onStatusChanged = std::move(onStatusChanged),
1739     };
1740     ShowActionMenuInner(dialogProperties, button, std::move(callback));
1741 }
1742 
ShowActionMenu(const PromptDialogAttr & dialogAttr,const std::vector<ButtonInfo> & buttons,std::function<void (int32_t,int32_t)> && callback)1743 void FrontendDelegateDeclarative::ShowActionMenu(const PromptDialogAttr& dialogAttr,
1744     const std::vector<ButtonInfo>& buttons, std::function<void(int32_t, int32_t)>&& callback)
1745 {
1746     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show action menu enter");
1747     DialogProperties dialogProperties = {
1748         .title = dialogAttr.title,
1749         .autoCancel = true,
1750         .isMenu = true,
1751         .buttons = buttons,
1752         .isShowInSubWindow = dialogAttr.showInSubWindow,
1753         .isModal = dialogAttr.isModal,
1754     };
1755     ShowActionMenuInner(dialogProperties, buttons, std::move(callback));
1756 }
1757 
EnableAlertBeforeBackPage(const std::string & message,std::function<void (int32_t)> && callback)1758 void FrontendDelegateDeclarative::EnableAlertBeforeBackPage(
1759     const std::string& message, std::function<void(int32_t)>&& callback)
1760 {
1761     if (Container::IsCurrentUseNewPipeline()) {
1762         LOGI("EnableAlertBeforeBackPage IsCurrentUseNewPipeline.");
1763         CHECK_NULL_VOID(pageRouterManager_);
1764         pageRouterManager_->EnableAlertBeforeBackPage(message, std::move(callback));
1765         return;
1766     }
1767 
1768     if (!taskExecutor_) {
1769         LOGE("task executor is null.");
1770         return;
1771     }
1772     std::unordered_map<std::string, EventMarker> callbackMarkers;
1773     auto pipelineContext = pipelineContextHolder_.Get();
1774     auto successEventMarker = BackEndEventManager<void(int32_t)>::GetInstance().GetAvailableMarker();
1775     BackEndEventManager<void(int32_t)>::GetInstance().BindBackendEvent(successEventMarker,
1776         [weak = AceType::WeakClaim(this), callback, taskExecutor = taskExecutor_](int32_t successType) {
1777             taskExecutor->PostTask(
1778                 [weak, callback, successType]() {
1779                     callback(successType);
1780                     auto delegate = weak.Upgrade();
1781                     if (!delegate) {
1782                         return;
1783                     }
1784                     if (!successType) {
1785                         LOGI("dialog choose cancel button, can not back");
1786                         delegate->ProcessRouterTask();
1787                         return;
1788                     }
1789                     delegate->StartBack(delegate->backUri_, delegate->backParam_);
1790                 },
1791                 TaskExecutor::TaskType::JS);
1792         });
1793     callbackMarkers.emplace(COMMON_SUCCESS, successEventMarker);
1794 
1795     std::lock_guard<std::mutex> lock(mutex_);
1796     if (pageRouteStack_.empty()) {
1797         LOGE("page stack is null.");
1798         return;
1799     }
1800 
1801     auto& currentPage = pageRouteStack_.back();
1802     ClearAlertCallback(currentPage);
1803     currentPage.alertCallback = callback;
1804     currentPage.dialogProperties = {
1805         .content = message,
1806         .autoCancel = false,
1807         .buttons = { { .text = Localization::GetInstance()->GetEntryLetters("common.cancel"), .textColor = "" },
1808             { .text = Localization::GetInstance()->GetEntryLetters("common.ok"), .textColor = "" } },
1809         .callbacks = std::move(callbackMarkers),
1810     };
1811 }
1812 
DisableAlertBeforeBackPage()1813 void FrontendDelegateDeclarative::DisableAlertBeforeBackPage()
1814 {
1815     if (Container::IsCurrentUseNewPipeline()) {
1816         LOGI("DisableAlertBeforeBackPage IsCurrentUseNewPipeline.");
1817         CHECK_NULL_VOID(pageRouterManager_);
1818         pageRouterManager_->DisableAlertBeforeBackPage();
1819         return;
1820     }
1821 
1822     std::lock_guard<std::mutex> lock(mutex_);
1823     if (pageRouteStack_.empty()) {
1824         LOGE("page stack is null.");
1825         return;
1826     }
1827     auto& currentPage = pageRouteStack_.back();
1828     ClearAlertCallback(currentPage);
1829     currentPage.alertCallback = nullptr;
1830 }
1831 
GetBoundingRectData(NodeId nodeId)1832 Rect FrontendDelegateDeclarative::GetBoundingRectData(NodeId nodeId)
1833 {
1834     Rect rect;
1835     auto task = [context = pipelineContextHolder_.Get(), nodeId, &rect]() {
1836         context->GetBoundingRectData(nodeId, rect);
1837     };
1838     PostSyncTaskToPage(task);
1839     return rect;
1840 }
1841 
GetInspector(NodeId nodeId)1842 std::string FrontendDelegateDeclarative::GetInspector(NodeId nodeId)
1843 {
1844     std::string attrs;
1845     auto task = [weak = WeakClaim(AceType::RawPtr(jsAccessibilityManager_)), nodeId, &attrs]() {
1846         auto accessibilityNodeManager = weak.Upgrade();
1847         if (accessibilityNodeManager) {
1848             attrs = accessibilityNodeManager->GetInspectorNodeById(nodeId);
1849         }
1850     };
1851     PostSyncTaskToPage(task);
1852     return attrs;
1853 }
1854 
SetCallBackResult(const std::string & callBackId,const std::string & result)1855 void FrontendDelegateDeclarative::SetCallBackResult(const std::string& callBackId, const std::string& result)
1856 {
1857     jsCallBackResult_.try_emplace(StringToInt(callBackId), result);
1858 }
1859 
WaitTimer(const std::string & callbackId,const std::string & delay,bool isInterval,bool isFirst)1860 void FrontendDelegateDeclarative::WaitTimer(
1861     const std::string& callbackId, const std::string& delay, bool isInterval, bool isFirst)
1862 {
1863     if (!isFirst) {
1864         auto timeoutTaskIter = timeoutTaskMap_.find(callbackId);
1865         // If not find the callbackId in map, means this timer already was removed,
1866         // no need create a new cancelableTimer again.
1867         if (timeoutTaskIter == timeoutTaskMap_.end()) {
1868             return;
1869         }
1870     }
1871 
1872     int32_t delayTime = StringToInt(delay);
1873     // CancelableCallback class can only be executed once.
1874     CancelableCallback<void()> cancelableTimer;
1875     cancelableTimer.Reset([callbackId, delay, isInterval, call = timer_] { call(callbackId, delay, isInterval); });
1876     auto result = timeoutTaskMap_.try_emplace(callbackId, cancelableTimer);
1877     if (!result.second) {
1878         result.first->second = cancelableTimer;
1879     }
1880     taskExecutor_->PostDelayedTask(cancelableTimer, TaskExecutor::TaskType::JS, delayTime);
1881 }
1882 
ClearTimer(const std::string & callbackId)1883 void FrontendDelegateDeclarative::ClearTimer(const std::string& callbackId)
1884 {
1885     auto timeoutTaskIter = timeoutTaskMap_.find(callbackId);
1886     if (timeoutTaskIter != timeoutTaskMap_.end()) {
1887         timeoutTaskIter->second.Cancel();
1888         timeoutTaskMap_.erase(timeoutTaskIter);
1889     } else {
1890         LOGW("ClearTimer callbackId not found");
1891     }
1892 }
1893 
PostSyncTaskToPage(std::function<void ()> && task)1894 void FrontendDelegateDeclarative::PostSyncTaskToPage(std::function<void()>&& task)
1895 {
1896     pipelineContextHolder_.Get(); // Wait until Pipeline Context is attached.
1897     taskExecutor_->PostSyncTask(task, TaskExecutor::TaskType::UI);
1898 }
1899 
AddTaskObserver(std::function<void ()> && task)1900 void FrontendDelegateDeclarative::AddTaskObserver(std::function<void()>&& task)
1901 {
1902     taskExecutor_->AddTaskObserver(std::move(task));
1903 }
1904 
RemoveTaskObserver()1905 void FrontendDelegateDeclarative::RemoveTaskObserver()
1906 {
1907     taskExecutor_->RemoveTaskObserver();
1908 }
1909 
GetAssetContent(const std::string & url,std::string & content)1910 bool FrontendDelegateDeclarative::GetAssetContent(const std::string& url, std::string& content)
1911 {
1912     return GetAssetContentImpl(assetManager_, url, content);
1913 }
1914 
GetAssetContent(const std::string & url,std::vector<uint8_t> & content)1915 bool FrontendDelegateDeclarative::GetAssetContent(const std::string& url, std::vector<uint8_t>& content)
1916 {
1917     return GetAssetContentImpl(assetManager_, url, content);
1918 }
1919 
GetAssetPath(const std::string & url)1920 std::string FrontendDelegateDeclarative::GetAssetPath(const std::string& url)
1921 {
1922     return GetAssetPathImpl(assetManager_, url);
1923 }
1924 
LoadPage(int32_t pageId,const PageTarget & target,bool isMainPage,const std::string & params,bool isRestore)1925 UIContentErrorCode FrontendDelegateDeclarative::LoadPage(
1926     int32_t pageId, const PageTarget& target, bool isMainPage, const std::string& params, bool isRestore)
1927 {
1928     LOGI("LoadPage[%{public}d]: %{public}s.", pageId, target.url.c_str());
1929     if (pageId == INVALID_PAGE_ID) {
1930         LOGE("FrontendDelegateDeclarative, invalid page id");
1931         EventReport::SendPageRouterException(PageRouterExcepType::LOAD_PAGE_ERR, target.url);
1932         ProcessRouterTask();
1933         return UIContentErrorCode::INVALID_PAGE_ID;
1934     }
1935     {
1936         std::lock_guard<std::mutex> lock(mutex_);
1937         pageId_ = pageId;
1938         pageParamMap_[pageId] = params;
1939     }
1940     if (isStagingPageExist_) {
1941         LOGE("FrontendDelegateDeclarative, load page failed, waiting for current page loading finish.");
1942         RecyclePageId(pageId);
1943         ProcessRouterTask();
1944         return UIContentErrorCode::STAGING_PAGE_EXIST;
1945     }
1946     isStagingPageExist_ = true;
1947 
1948     singlePageId_ = INVALID_PAGE_ID;
1949     if (target.routerMode == RouterMode::SINGLE) {
1950         singlePageId_ = GetPageIdByUrl(target.url);
1951         LOGI("single page id = %{public}d", singlePageId_);
1952     }
1953 
1954     auto document = AceType::MakeRefPtr<DOMDocument>(pageId);
1955     auto page = AceType::MakeRefPtr<JsAcePage>(pageId, document, target.url, target.container);
1956     page->SetPageParams(params);
1957     page->SetFlushCallback([weak = AceType::WeakClaim(this), isMainPage, isRestore](const RefPtr<JsAcePage>& acePage) {
1958         auto delegate = weak.Upgrade();
1959         if (!delegate) {
1960             return;
1961         }
1962         if (acePage) {
1963             delegate->FlushPageCommand(acePage, acePage->GetUrl(), isMainPage, isRestore);
1964         } else {
1965             LOGE("flush callback called unexpected");
1966             delegate->ProcessRouterTask();
1967         }
1968     });
1969     taskExecutor_->PostTask(
1970         [weak = AceType::WeakClaim(this), page, isMainPage] {
1971             auto delegate = weak.Upgrade();
1972             if (!delegate) {
1973                 return;
1974             }
1975             delegate->loadJs_(page->GetUrl(), page, isMainPage);
1976             page->FlushCommands();
1977             // just make sure the pipelineContext is created.
1978             auto pipeline = delegate->pipelineContextHolder_.Get();
1979             if (delegate->GetMinPlatformVersion() > 0) {
1980                 pipeline->SetMinPlatformVersion(delegate->GetMinPlatformVersion());
1981             }
1982             delegate->taskExecutor_->PostTask(
1983                 [weak, page] {
1984                     auto delegate = weak.Upgrade();
1985                     if (delegate) {
1986                         auto context = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
1987                         if (context) {
1988                             context->FlushFocus();
1989                         }
1990                     }
1991                     if (page->GetDomDocument()) {
1992                         page->GetDomDocument()->HandlePageLoadFinish();
1993                     }
1994                 },
1995                 TaskExecutor::TaskType::UI);
1996         },
1997         TaskExecutor::TaskType::JS);
1998 
1999     return UIContentErrorCode::NO_ERRORS;
2000 }
2001 
OnSurfaceChanged()2002 void FrontendDelegateDeclarative::OnSurfaceChanged()
2003 {
2004     if (mediaQueryInfo_->GetIsInit()) {
2005         mediaQueryInfo_->SetIsInit(false);
2006     }
2007     mediaQueryInfo_->EnsureListenerIdValid();
2008     OnMediaQueryUpdate(true);
2009 }
2010 
OnMediaQueryUpdate(bool isSynchronous)2011 void FrontendDelegateDeclarative::OnMediaQueryUpdate(bool isSynchronous)
2012 {
2013     auto containerId = Container::CurrentId();
2014     if (containerId < 0) {
2015         auto container = Container::GetActive();
2016         if (container) {
2017             containerId = container->GetInstanceId();
2018         }
2019     }
2020     bool isInSubwindow = containerId >= 1000000;
2021     if (isInSubwindow) {
2022         return;
2023     }
2024     if (mediaQueryInfo_->GetIsInit()) {
2025         return;
2026     }
2027 
2028     auto callback = [weak = AceType::WeakClaim(this)] {
2029         auto delegate = weak.Upgrade();
2030         if (!delegate) {
2031             return;
2032         }
2033         const auto& info = delegate->mediaQueryInfo_->GetMediaQueryInfo();
2034         // request css mediaquery
2035         std::string param("\"viewsizechanged\",");
2036         param.append(info);
2037         delegate->asyncEvent_("_root", param);
2038 
2039         // request js media query
2040         const auto& listenerId = delegate->mediaQueryInfo_->GetListenerId();
2041         delegate->mediaQueryCallback_(listenerId, info);
2042         delegate->mediaQueryInfo_->ResetListenerId();
2043     };
2044     auto container = Container::Current();
2045     if (container && container->IsUseStageModel() && isSynchronous) {
2046         callback();
2047         return;
2048     }
2049     taskExecutor_->PostTask(callback, TaskExecutor::TaskType::JS);
2050 }
2051 
OnLayoutCompleted(const std::string & componentId)2052 void FrontendDelegateDeclarative::OnLayoutCompleted(const std::string& componentId)
2053 {
2054     taskExecutor_->PostTask(
2055         [weak = AceType::WeakClaim(this), componentId] {
2056             auto delegate = weak.Upgrade();
2057             if (!delegate) {
2058                 return;
2059             }
2060             delegate->layoutInspectorCallback_(componentId);
2061         },
2062         TaskExecutor::TaskType::JS);
2063 }
2064 
OnDrawCompleted(const std::string & componentId)2065 void FrontendDelegateDeclarative::OnDrawCompleted(const std::string& componentId)
2066 {
2067     taskExecutor_->PostTask(
2068         [weak = AceType::WeakClaim(this), componentId] {
2069             auto delegate = weak.Upgrade();
2070             if (!delegate) {
2071                 return;
2072             }
2073             delegate->drawInspectorCallback_(componentId);
2074         },
2075         TaskExecutor::TaskType::JS);
2076 }
2077 
OnPageReady(const RefPtr<JsAcePage> & page,const std::string & url,bool isMainPage,bool isRestore)2078 void FrontendDelegateDeclarative::OnPageReady(
2079     const RefPtr<JsAcePage>& page, const std::string& url, bool isMainPage, bool isRestore)
2080 {
2081     LOGI("OnPageReady url = %{private}s", url.c_str());
2082     // Pop all JS command and execute them in UI thread.
2083     auto jsCommands = std::make_shared<std::vector<RefPtr<JsCommand>>>();
2084     page->PopAllCommands(*jsCommands);
2085 
2086     auto pipelineContext = pipelineContextHolder_.Get();
2087     page->SetPipelineContext(pipelineContext);
2088     taskExecutor_->PostTask(
2089         [weak = AceType::WeakClaim(this), page, url, jsCommands, isMainPage, isRestore] {
2090             auto delegate = weak.Upgrade();
2091             if (!delegate) {
2092                 return;
2093             }
2094             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2095             CHECK_NULL_VOID(pipelineContext);
2096             // Flush all JS commands.
2097             for (const auto& command : *jsCommands) {
2098                 command->Execute(page);
2099             }
2100             // Just clear all dirty nodes.
2101             page->ClearAllDirtyNodes();
2102             if (page->GetDomDocument()) {
2103                 page->GetDomDocument()->HandleComponentPostBinding();
2104             }
2105             if (pipelineContext->GetAccessibilityManager()) {
2106                 pipelineContext->GetAccessibilityManager()->HandleComponentPostBinding();
2107             }
2108             if (isRestore) {
2109                 delegate->RestorePopPage(page, url);
2110                 return;
2111             }
2112             if (pipelineContext->CanPushPage()) {
2113                 if (!isMainPage) {
2114                     delegate->OnPageHide();
2115                 }
2116                 delegate->OnPrePageChange(page);
2117                 pipelineContext->RemovePageTransitionListener(delegate->pageTransitionListenerId_);
2118                 delegate->pageTransitionListenerId_ = pipelineContext->AddPageTransitionListener(
2119                     [weak, page](
2120                         const TransitionEvent& event, const WeakPtr<PageElement>& in, const WeakPtr<PageElement>& out) {
2121                         auto delegate = weak.Upgrade();
2122                         if (delegate) {
2123                             delegate->PushPageTransitionListener(event, page);
2124                         }
2125                     });
2126                 if (delegate->singlePageId_ != INVALID_PAGE_ID) {
2127                     pipelineContext->SetSinglePageId(delegate->singlePageId_);
2128                 }
2129                 pipelineContext->PushPage(page->BuildPage(url), page->GetStageElement());
2130             } else {
2131                 // This page has been loaded but become useless now, the corresponding js instance
2132                 // must be destroyed to avoid memory leak.
2133                 LOGW("router push run in unexpected process");
2134                 delegate->OnPageDestroy(page->GetPageId());
2135                 delegate->ResetStagingPage();
2136                 delegate->ProcessRouterTask();
2137             }
2138             delegate->isStagingPageExist_ = false;
2139         },
2140         TaskExecutor::TaskType::UI);
2141 }
2142 
PushPageTransitionListener(const TransitionEvent & event,const RefPtr<JsAcePage> & page)2143 void FrontendDelegateDeclarative::PushPageTransitionListener(
2144     const TransitionEvent& event, const RefPtr<JsAcePage>& page)
2145 {
2146     if (event == TransitionEvent::PUSH_END) {
2147         OnPushPageSuccess(page, page->GetUrl());
2148         SetCurrentPage(page->GetPageId());
2149         OnPageShow();
2150         OnMediaQueryUpdate();
2151         ProcessRouterTask();
2152     }
2153 }
2154 
OnPushPageSuccess(const RefPtr<JsAcePage> & page,const std::string & url)2155 void FrontendDelegateDeclarative::OnPushPageSuccess(const RefPtr<JsAcePage>& page, const std::string& url)
2156 {
2157     std::lock_guard<std::mutex> lock(mutex_);
2158     AddPageLocked(page);
2159     pageRouteStack_.emplace_back(PageInfo { page->GetPageId(), page->GetUrl() });
2160     if (singlePageId_ != INVALID_PAGE_ID) {
2161         RecycleSinglePage();
2162     }
2163     if (pageRouteStack_.size() >= MAX_ROUTER_STACK) {
2164         isRouteStackFull_ = true;
2165         EventReport::SendPageRouterException(PageRouterExcepType::PAGE_STACK_OVERFLOW_ERR, page->GetUrl());
2166     }
2167     LOGI("OnPushPageSuccess size=%{private}zu,pageId=%{private}d,url=%{private}s", pageRouteStack_.size(),
2168         pageRouteStack_.back().pageId, pageRouteStack_.back().url.c_str());
2169 }
2170 
RecycleSinglePage()2171 void FrontendDelegateDeclarative::RecycleSinglePage()
2172 {
2173     LOGI("single page recycle");
2174     auto iter = find_if(pageRouteStack_.begin(), pageRouteStack_.end(),
2175         [&](const PageInfo& item) { return item.pageId == singlePageId_; });
2176     if (iter != pageRouteStack_.end()) {
2177         pageMap_.erase(singlePageId_);
2178         pageParamMap_.erase(singlePageId_);
2179         pageRouteStack_.erase(iter);
2180         OnPageDestroy(singlePageId_);
2181     }
2182     singlePageId_ = INVALID_PAGE_ID;
2183 }
2184 
OnPrePageChange(const RefPtr<JsAcePage> & page)2185 void FrontendDelegateDeclarative::OnPrePageChange(const RefPtr<JsAcePage>& page)
2186 {
2187     if (page && page->GetDomDocument() && jsAccessibilityManager_) {
2188         jsAccessibilityManager_->SetRootNodeId(page->GetDomDocument()->GetRootNodeId());
2189     }
2190 }
2191 
FlushPageCommand(const RefPtr<JsAcePage> & page,const std::string & url,bool isMainPage,bool isRestore)2192 void FrontendDelegateDeclarative::FlushPageCommand(
2193     const RefPtr<JsAcePage>& page, const std::string& url, bool isMainPage, bool isRestore)
2194 {
2195     if (!page) {
2196         ProcessRouterTask();
2197         return;
2198     }
2199     if (page->FragmentCount() == 1) {
2200         OnPageReady(page, url, isMainPage, isRestore);
2201     } else {
2202         TriggerPageUpdate(page->GetPageId());
2203     }
2204 }
2205 
AddPageLocked(const RefPtr<JsAcePage> & page)2206 void FrontendDelegateDeclarative::AddPageLocked(const RefPtr<JsAcePage>& page)
2207 {
2208     auto result = pageMap_.try_emplace(page->GetPageId(), page);
2209     if (!result.second) {
2210         LOGW("the page has already in the map");
2211     }
2212 }
2213 
SetCurrentPage(int32_t pageId)2214 void FrontendDelegateDeclarative::SetCurrentPage(int32_t pageId)
2215 {
2216     auto page = GetPage(pageId);
2217     if (page != nullptr) {
2218         jsAccessibilityManager_->SetVersion(AccessibilityVersion::JS_DECLARATIVE_VERSION);
2219         jsAccessibilityManager_->SetRunningPage(page);
2220         taskExecutor_->PostTask([updatePage = updatePage_, page] { updatePage(page); }, TaskExecutor::TaskType::JS);
2221     } else {
2222         LOGE("FrontendDelegateDeclarative SetCurrentPage page is null.");
2223     }
2224 }
2225 
PopToPage(const std::string & url)2226 void FrontendDelegateDeclarative::PopToPage(const std::string& url)
2227 {
2228     taskExecutor_->PostTask(
2229         [weak = AceType::WeakClaim(this), url] {
2230             auto delegate = weak.Upgrade();
2231             if (!delegate) {
2232                 return;
2233             }
2234             auto pageId = delegate->GetPageIdByUrl(url);
2235             if (pageId == INVALID_PAGE_ID) {
2236                 delegate->ProcessRouterTask();
2237                 return;
2238             }
2239             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2240             CHECK_NULL_VOID(pipelineContext);
2241             if (!pipelineContext->CanPopPage()) {
2242                 LOGW("router pop to page run in unexpected process");
2243                 delegate->ResetStagingPage();
2244                 delegate->ProcessRouterTask();
2245                 return;
2246             }
2247             delegate->OnPageHide();
2248             pipelineContext->RemovePageTransitionListener(delegate->pageTransitionListenerId_);
2249             delegate->pageTransitionListenerId_ = pipelineContext->AddPageTransitionListener(
2250                 [weak, url, pageId](
2251                     const TransitionEvent& event, const WeakPtr<PageElement>& in, const WeakPtr<PageElement>& out) {
2252                     auto delegate = weak.Upgrade();
2253                     if (delegate) {
2254                         delegate->PopToPageTransitionListener(event, url, pageId);
2255                     }
2256                 });
2257             pipelineContext->PopToPage(pageId);
2258         },
2259         TaskExecutor::TaskType::UI);
2260 }
2261 
PopToPageTransitionListener(const TransitionEvent & event,const std::string & url,int32_t pageId)2262 void FrontendDelegateDeclarative::PopToPageTransitionListener(
2263     const TransitionEvent& event, const std::string& url, int32_t pageId)
2264 {
2265     if (event == TransitionEvent::POP_END) {
2266         OnPopToPageSuccess(url);
2267         SetCurrentPage(pageId);
2268         OnPageShow();
2269         OnMediaQueryUpdate();
2270         ProcessRouterTask();
2271     }
2272 }
2273 
OnPopToPageSuccess(const std::string & url)2274 void FrontendDelegateDeclarative::OnPopToPageSuccess(const std::string& url)
2275 {
2276     std::lock_guard<std::mutex> lock(mutex_);
2277     while (!pageRouteStack_.empty()) {
2278         if (pageRouteStack_.back().url == url) {
2279             break;
2280         }
2281         OnPageDestroy(pageRouteStack_.back().pageId);
2282         pageMap_.erase(pageRouteStack_.back().pageId);
2283         pageParamMap_.erase(pageRouteStack_.back().pageId);
2284         ClearAlertCallback(pageRouteStack_.back());
2285         pageRouteStack_.pop_back();
2286     }
2287 
2288     if (isRouteStackFull_) {
2289         isRouteStackFull_ = false;
2290     }
2291 }
2292 
OnPopPageSuccess()2293 int32_t FrontendDelegateDeclarative::OnPopPageSuccess()
2294 {
2295     std::lock_guard<std::mutex> lock(mutex_);
2296     pageMap_.erase(pageRouteStack_.back().pageId);
2297     pageParamMap_.erase(pageRouteStack_.back().pageId);
2298     ClearAlertCallback(pageRouteStack_.back());
2299     pageRouteStack_.pop_back();
2300     if (isRouteStackFull_) {
2301         isRouteStackFull_ = false;
2302     }
2303     if (!pageRouteStack_.empty()) {
2304         LOGI("OnPopPageSuccess: pop to page %{private}s", pageRouteStack_.back().url.c_str());
2305         return pageRouteStack_.back().pageId;
2306     }
2307     return INVALID_PAGE_ID;
2308 }
2309 
PopPage()2310 void FrontendDelegateDeclarative::PopPage()
2311 {
2312     taskExecutor_->PostTask(
2313         [weak = AceType::WeakClaim(this)] {
2314             auto delegate = weak.Upgrade();
2315             if (!delegate) {
2316                 return;
2317             }
2318             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2319             CHECK_NULL_VOID(pipelineContext);
2320             if (delegate->GetStackSize() == 1) {
2321                 if (delegate->disallowPopLastPage_) {
2322                     LOGW("Not allow back because this is the last page!");
2323                     delegate->ProcessRouterTask();
2324                     return;
2325                 }
2326                 delegate->OnPageHide();
2327                 delegate->OnPageDestroy(delegate->GetRunningPageId());
2328                 delegate->OnPopPageSuccess();
2329                 pipelineContext->Finish();
2330                 return;
2331             }
2332             if (!pipelineContext->CanPopPage()) {
2333                 delegate->ResetStagingPage();
2334                 LOGW("router pop run in unexpected process");
2335                 delegate->ProcessRouterTask();
2336                 return;
2337             }
2338             delegate->OnPageHide();
2339             pipelineContext->RemovePageTransitionListener(delegate->pageTransitionListenerId_);
2340             delegate->pageTransitionListenerId_ = pipelineContext->AddPageTransitionListener(
2341                 [weak, destroyPageId = delegate->GetRunningPageId()](
2342                     const TransitionEvent& event, const WeakPtr<PageElement>& in, const WeakPtr<PageElement>& out) {
2343                     auto delegate = weak.Upgrade();
2344                     if (delegate) {
2345                         delegate->PopPageTransitionListener(event, destroyPageId);
2346                     }
2347                 });
2348             pipelineContext->PopPage();
2349         },
2350         TaskExecutor::TaskType::UI);
2351 }
2352 
PopPageTransitionListener(const TransitionEvent & event,int32_t destroyPageId)2353 void FrontendDelegateDeclarative::PopPageTransitionListener(const TransitionEvent& event, int32_t destroyPageId)
2354 {
2355     if (event == TransitionEvent::POP_END) {
2356         OnPageDestroy(destroyPageId);
2357         auto pageId = OnPopPageSuccess();
2358         SetCurrentPage(pageId);
2359         OnPageShow();
2360         OnMediaQueryUpdate();
2361         ProcessRouterTask();
2362     }
2363 }
2364 
RestorePopPage(const RefPtr<JsAcePage> & page,const std::string & url)2365 void FrontendDelegateDeclarative::RestorePopPage(const RefPtr<JsAcePage>& page, const std::string& url)
2366 {
2367     taskExecutor_->PostTask(
2368         [weak = AceType::WeakClaim(this), page, url] {
2369             auto delegate = weak.Upgrade();
2370             if (!delegate) {
2371                 return;
2372             }
2373             LOGI("RestorePopPage begin");
2374             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2375             CHECK_NULL_VOID(pipelineContext);
2376             if (delegate->GetStackSize() == 1) {
2377                 if (delegate->disallowPopLastPage_) {
2378                     LOGW("Not allow back because this is the last page!");
2379                     delegate->ProcessRouterTask();
2380                     return;
2381                 }
2382                 delegate->OnPageHide();
2383                 delegate->OnPageDestroy(delegate->GetRunningPageId());
2384                 delegate->OnPopPageSuccess();
2385                 pipelineContext->Finish();
2386                 return;
2387             }
2388             delegate->OnPageHide();
2389             pipelineContext->RemovePageTransitionListener(delegate->pageTransitionListenerId_);
2390             delegate->pageTransitionListenerId_ = pipelineContext->AddPageTransitionListener(
2391                 [weak, url, page](
2392                     const TransitionEvent& event, const WeakPtr<PageElement>& in, const WeakPtr<PageElement>& out) {
2393                     auto delegate = weak.Upgrade();
2394                     if (delegate) {
2395                         delegate->RestorePageTransitionListener(event, url, page);
2396                     }
2397                 });
2398             pipelineContext->RestorePopPage(page->BuildPage(url));
2399             delegate->isStagingPageExist_ = false;
2400         },
2401         TaskExecutor::TaskType::UI);
2402 }
2403 
RestorePageTransitionListener(const TransitionEvent & event,const std::string & url,const RefPtr<JsAcePage> & page)2404 void FrontendDelegateDeclarative::RestorePageTransitionListener(
2405     const TransitionEvent& event, const std::string& url, const RefPtr<JsAcePage>& page)
2406 {
2407     if (event == TransitionEvent::PUSH_END) {
2408         LOGI("RestorePageTransitionListener %{public}s", url.c_str());
2409         OnPopToPageSuccess(url);
2410         {
2411             std::lock_guard<std::mutex> lock(mutex_);
2412             AddPageLocked(page);
2413             pageRouteStack_.back().isRestore = false;
2414         }
2415         SetCurrentPage(GetPageIdByUrl(url));
2416         OnPageShow();
2417         OnMediaQueryUpdate();
2418         ProcessRouterTask();
2419     }
2420 }
2421 
OnClearInvisiblePagesSuccess()2422 int32_t FrontendDelegateDeclarative::OnClearInvisiblePagesSuccess()
2423 {
2424     std::lock_guard<std::mutex> lock(mutex_);
2425     PageInfo pageInfo = std::move(pageRouteStack_.back());
2426     pageRouteStack_.pop_back();
2427     for (const auto& info : pageRouteStack_) {
2428         ClearAlertCallback(info);
2429         OnPageDestroy(info.pageId);
2430         pageMap_.erase(info.pageId);
2431         pageParamMap_.erase(info.pageId);
2432     }
2433     pageRouteStack_.clear();
2434     int32_t resPageId = pageInfo.pageId;
2435     pageRouteStack_.emplace_back(std::move(pageInfo));
2436     if (isRouteStackFull_) {
2437         isRouteStackFull_ = false;
2438     }
2439     return resPageId;
2440 }
2441 
ClearInvisiblePages()2442 void FrontendDelegateDeclarative::ClearInvisiblePages()
2443 {
2444     taskExecutor_->PostTask(
2445         [weak = AceType::WeakClaim(this)] {
2446             auto delegate = weak.Upgrade();
2447             if (!delegate) {
2448                 return;
2449             }
2450             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2451             CHECK_NULL_VOID(pipelineContext);
2452             if (pipelineContext->ClearInvisiblePages([weak]() {
2453                     auto delegate = weak.Upgrade();
2454                     if (!delegate) {
2455                         return;
2456                     }
2457                     delegate->ProcessRouterTask();
2458                 })) {
2459                 auto pageId = delegate->OnClearInvisiblePagesSuccess();
2460                 delegate->SetCurrentPage(pageId);
2461             } else {
2462                 delegate->ProcessRouterTask();
2463             }
2464         },
2465         TaskExecutor::TaskType::UI);
2466 }
2467 
OnReplacePageSuccess(const RefPtr<JsAcePage> & page,const std::string & url)2468 void FrontendDelegateDeclarative::OnReplacePageSuccess(const RefPtr<JsAcePage>& page, const std::string& url)
2469 {
2470     if (!page) {
2471         return;
2472     }
2473     std::lock_guard<std::mutex> lock(mutex_);
2474     AddPageLocked(page);
2475     if (!pageRouteStack_.empty()) {
2476         pageMap_.erase(pageRouteStack_.back().pageId);
2477         pageParamMap_.erase(pageRouteStack_.back().pageId);
2478         ClearAlertCallback(pageRouteStack_.back());
2479         pageRouteStack_.pop_back();
2480     }
2481     pageRouteStack_.emplace_back(PageInfo { page->GetPageId(), url });
2482     if (singlePageId_ != INVALID_PAGE_ID) {
2483         RecycleSinglePage();
2484     }
2485 }
2486 
ReplacePage(const RefPtr<JsAcePage> & page,const std::string & url)2487 void FrontendDelegateDeclarative::ReplacePage(const RefPtr<JsAcePage>& page, const std::string& url)
2488 {
2489     LOGI("ReplacePage url = %{private}s", url.c_str());
2490     // Pop all JS command and execute them in UI thread.
2491     auto jsCommands = std::make_shared<std::vector<RefPtr<JsCommand>>>();
2492     page->PopAllCommands(*jsCommands);
2493 
2494     auto pipelineContext = pipelineContextHolder_.Get();
2495     page->SetPipelineContext(pipelineContext);
2496     taskExecutor_->PostTask(
2497         [weak = AceType::WeakClaim(this), page, url, jsCommands] {
2498             auto delegate = weak.Upgrade();
2499             if (!delegate) {
2500                 return;
2501             }
2502             auto pipelineContext = AceType::DynamicCast<PipelineContext>(delegate->pipelineContextHolder_.Get());
2503             CHECK_NULL_VOID(pipelineContext);
2504             // Flush all JS commands.
2505             for (const auto& command : *jsCommands) {
2506                 command->Execute(page);
2507             }
2508             // Just clear all dirty nodes.
2509             page->ClearAllDirtyNodes();
2510             page->GetDomDocument()->HandleComponentPostBinding();
2511             pipelineContext->GetAccessibilityManager()->HandleComponentPostBinding();
2512             if (pipelineContext->CanReplacePage()) {
2513                 delegate->OnPageHide();
2514                 delegate->OnPageDestroy(delegate->GetRunningPageId());
2515                 delegate->OnPrePageChange(page);
2516                 if (delegate->singlePageId_ != INVALID_PAGE_ID) {
2517                     pipelineContext->SetSinglePageId(delegate->singlePageId_);
2518                 }
2519                 pipelineContext->ReplacePage(page->BuildPage(url), page->GetStageElement(), [weak, page, url]() {
2520                     auto delegate = weak.Upgrade();
2521                     if (!delegate) {
2522                         return;
2523                     }
2524                     delegate->OnReplacePageSuccess(page, url);
2525                     delegate->SetCurrentPage(page->GetPageId());
2526                     delegate->OnPageShow();
2527                     delegate->OnMediaQueryUpdate();
2528                     delegate->ProcessRouterTask();
2529                 });
2530             } else {
2531                 // This page has been loaded but become useless now, the corresponding js instance
2532                 // must be destroyed to avoid memory leak.
2533                 LOGW("replace run in unexpected process");
2534                 delegate->OnPageDestroy(page->GetPageId());
2535                 delegate->ResetStagingPage();
2536                 delegate->ProcessRouterTask();
2537             }
2538             delegate->isStagingPageExist_ = false;
2539         },
2540         TaskExecutor::TaskType::UI);
2541 }
2542 
ReplacePageInSubStage(const RefPtr<JsAcePage> & page,const std::string & url)2543 void FrontendDelegateDeclarative::ReplacePageInSubStage(const RefPtr<JsAcePage>& page, const std::string& url)
2544 {
2545     LOGI("ReplacePageInSubStage url = %{private}s", url.c_str());
2546     auto pipelineContext = pipelineContextHolder_.Get();
2547     page->SetPipelineContext(pipelineContext);
2548     taskExecutor_->PostTask(
2549         [weak = AceType::WeakClaim(this), page, url] {
2550             auto delegate = weak.Upgrade();
2551             if (!delegate) {
2552                 return;
2553             }
2554             auto pipelineContext = AceType::DynamicCast<PipelineContext>(page->GetPipelineContext().Upgrade());
2555             if (!pipelineContext) {
2556                 LOGE("pipelineContext is null");
2557                 return;
2558             }
2559             auto stageElement = page->GetStageElement();
2560             if (!stageElement) {
2561                 LOGE("stageElement is null");
2562                 return;
2563             }
2564 
2565             if (stageElement->GetChildren().empty()) {
2566                 delegate->OnPrePageChange(page);
2567                 pipelineContext->RemovePageTransitionListener(delegate->pageTransitionListenerId_);
2568                 delegate->pageTransitionListenerId_ = pipelineContext->AddPageTransitionListener(
2569                     [weak, page](
2570                         const TransitionEvent& event, const WeakPtr<PageElement>& in, const WeakPtr<PageElement>& out) {
2571                         auto delegate = weak.Upgrade();
2572                         if (delegate) {
2573                             delegate->PushPageTransitionListener(event, page);
2574                         }
2575                     });
2576                 pipelineContext->PushPage(page->BuildPage(url), page->GetStageElement());
2577                 delegate->isStagingPageExist_ = false;
2578                 return;
2579             }
2580 
2581             if (stageElement->CanReplacePage()) {
2582                 delegate->OnPageHide();
2583                 delegate->OnPageDestroy(delegate->GetRunningPageId());
2584                 delegate->OnPrePageChange(page);
2585                 stageElement->Replace(page->BuildPage(url), [weak, page, url]() {
2586                     auto delegate = weak.Upgrade();
2587                     if (!delegate) {
2588                         return;
2589                     }
2590                     delegate->OnReplacePageSuccess(page, url);
2591                     delegate->SetCurrentPage(page->GetPageId());
2592                     delegate->OnPageShow();
2593                     delegate->OnMediaQueryUpdate();
2594                     delegate->ProcessRouterTask();
2595                 });
2596             } else {
2597                 // This page has been loaded but become useless now, the corresponding js instance
2598                 // must be destroyed to avoid memory leak.
2599                 LOGW("replace run in unexpected process");
2600                 delegate->OnPageDestroy(page->GetPageId());
2601                 delegate->ResetStagingPage();
2602                 delegate->ProcessRouterTask();
2603             }
2604             delegate->isStagingPageExist_ = false;
2605         },
2606         TaskExecutor::TaskType::UI);
2607 }
2608 
GetEffectiveContainerId() const2609 std::optional<int32_t> FrontendDelegateDeclarative::GetEffectiveContainerId() const
2610 {
2611     std::optional<int32_t> id;
2612     auto currentId = Container::CurrentId();
2613     auto container = Container::GetContainer(currentId);
2614     CHECK_NULL_RETURN(container, id);
2615     if (container->IsSubContainer()) {
2616         currentId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
2617     }
2618     id.emplace(currentId);
2619     return id;
2620 }
2621 
LoadReplacePage(int32_t pageId,const PageTarget & target,const std::string & params)2622 void FrontendDelegateDeclarative::LoadReplacePage(int32_t pageId, const PageTarget& target, const std::string& params)
2623 {
2624     LOGI("FrontendDelegateDeclarative LoadReplacePage[%{private}d]: %{private}s.", pageId, target.url.c_str());
2625     if (pageId == INVALID_PAGE_ID) {
2626         LOGW("FrontendDelegateDeclarative, invalid page id");
2627         EventReport::SendPageRouterException(PageRouterExcepType::REPLACE_PAGE_ERR, target.url);
2628         ProcessRouterTask();
2629         return;
2630     }
2631     {
2632         std::lock_guard<std::mutex> lock(mutex_);
2633         pageId_ = pageId;
2634         pageParamMap_[pageId] = params;
2635     }
2636     auto document = AceType::MakeRefPtr<DOMDocument>(pageId);
2637     auto page = AceType::MakeRefPtr<JsAcePage>(pageId, document, target.url, target.container);
2638     page->SetSubStage(target.useSubStage);
2639     if (isStagingPageExist_ && !page->GetSubStageFlag()) {
2640         LOGW("FrontendDelegateDeclarative, replace page failed, waiting for current page loading finish.");
2641         EventReport::SendPageRouterException(PageRouterExcepType::REPLACE_PAGE_ERR, target.url);
2642         ProcessRouterTask();
2643         return;
2644     }
2645 
2646     singlePageId_ = INVALID_PAGE_ID;
2647     if (target.routerMode == RouterMode::SINGLE) {
2648         singlePageId_ = GetPageIdByUrl(target.url);
2649         LOGI("single page id = %{public}d", singlePageId_);
2650     }
2651 
2652     isStagingPageExist_ = true;
2653     page->SetPageParams(params);
2654     taskExecutor_->PostTask(
2655         [page, weak = AceType::WeakClaim(this)] {
2656             auto delegate = weak.Upgrade();
2657             if (delegate) {
2658                 delegate->loadJs_(page->GetUrl(), page, false);
2659                 if (page->GetSubStageFlag()) {
2660                     page->FireDeclarativeOnPageAppearCallback();
2661                     delegate->ReplacePageInSubStage(page, page->GetUrl());
2662                 } else {
2663                     delegate->ReplacePage(page, page->GetUrl());
2664                 }
2665             }
2666         },
2667         TaskExecutor::TaskType::JS);
2668 }
2669 
SetColorMode(ColorMode colorMode)2670 void FrontendDelegateDeclarative::SetColorMode(ColorMode colorMode)
2671 {
2672     OnMediaQueryUpdate();
2673 }
2674 
RebuildAllPages()2675 void FrontendDelegateDeclarative::RebuildAllPages()
2676 {
2677     if (Container::IsCurrentUseNewPipeline()) {
2678         CHECK_NULL_VOID(pageRouterManager_);
2679         auto url = pageRouterManager_->GetCurrentPageUrl();
2680         pageRouterManager_->Clear();
2681         pageRouterManager_->RunPage(url, "");
2682         return;
2683     }
2684     std::unordered_map<int32_t, RefPtr<JsAcePage>> pages;
2685     {
2686         std::lock_guard<std::mutex> lock(mutex_);
2687         pages.insert(pageMap_.begin(), pageMap_.end());
2688     }
2689     for (const auto& [pageId, page] : pages) {
2690         page->FireDeclarativeOnPageRefreshCallback();
2691         TriggerPageUpdate(page->GetPageId(), true);
2692     }
2693 }
2694 
OnPageShow()2695 void FrontendDelegateDeclarative::OnPageShow()
2696 {
2697     auto task = [weak = AceType::WeakClaim(this)] {
2698         auto delegate = weak.Upgrade();
2699         CHECK_NULL_VOID(delegate);
2700         if (Container::IsCurrentUseNewPipeline()) {
2701             auto pageRouterManager = delegate->GetPageRouterManager();
2702             CHECK_NULL_VOID(pageRouterManager);
2703             auto pageNode = pageRouterManager->GetCurrentPageNode();
2704             CHECK_NULL_VOID(pageNode);
2705             auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
2706             CHECK_NULL_VOID(pagePattern);
2707             pagePattern->OnShow();
2708             return;
2709         }
2710 
2711         auto pageId = delegate->GetRunningPageId();
2712         auto page = delegate->GetPage(pageId);
2713         if (page) {
2714             page->FireDeclarativeOnPageAppearCallback();
2715         }
2716     };
2717 
2718     if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::JS)) {
2719         task();
2720         FireSyncEvent("_root", std::string("\"viewappear\",null,null"), std::string(""));
2721         return;
2722     } else {
2723         taskExecutor_->PostTask(task, TaskExecutor::TaskType::JS);
2724         FireAsyncEvent("_root", std::string("\"viewappear\",null,null"), std::string(""));
2725     }
2726 }
2727 
OnPageHide()2728 void FrontendDelegateDeclarative::OnPageHide()
2729 {
2730     auto task = [weak = AceType::WeakClaim(this)] {
2731         auto delegate = weak.Upgrade();
2732         CHECK_NULL_VOID(delegate);
2733         if (Container::IsCurrentUseNewPipeline()) {
2734             auto pageRouterManager = delegate->GetPageRouterManager();
2735             CHECK_NULL_VOID(pageRouterManager);
2736             auto pageNode = pageRouterManager->GetCurrentPageNode();
2737             CHECK_NULL_VOID(pageNode);
2738             auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
2739             CHECK_NULL_VOID(pagePattern);
2740             pagePattern->OnHide();
2741             return;
2742         }
2743 
2744         auto pageId = delegate->GetRunningPageId();
2745         auto page = delegate->GetPage(pageId);
2746         if (page) {
2747             page->FireDeclarativeOnPageDisAppearCallback();
2748         }
2749     };
2750 
2751     if (taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::JS)) {
2752         task();
2753         FireSyncEvent("_root", std::string("\"viewdisappear\",null,null"), std::string(""));
2754     } else {
2755         taskExecutor_->PostTask(task, TaskExecutor::TaskType::JS);
2756         FireAsyncEvent("_root", std::string("\"viewdisappear\",null,null"), std::string(""));
2757     }
2758 }
2759 
ClearAlertCallback(PageInfo pageInfo)2760 void FrontendDelegateDeclarative::ClearAlertCallback(PageInfo pageInfo)
2761 {
2762     if (pageInfo.alertCallback) {
2763         // notify to clear js reference
2764         pageInfo.alertCallback(static_cast<int32_t>(AlertState::RECOVERY));
2765         pageInfo.alertCallback = nullptr;
2766     }
2767 }
2768 
OnPageDestroy(int32_t pageId)2769 void FrontendDelegateDeclarative::OnPageDestroy(int32_t pageId)
2770 {
2771     taskExecutor_->PostTask(
2772         [weak = AceType::WeakClaim(this), pageId] {
2773             auto delegate = weak.Upgrade();
2774             if (delegate) {
2775                 delegate->destroyPage_(pageId);
2776                 delegate->RecyclePageId(pageId);
2777             }
2778         },
2779         TaskExecutor::TaskType::JS);
2780 }
2781 
GetRunningPageId() const2782 int32_t FrontendDelegateDeclarative::GetRunningPageId() const
2783 {
2784     std::lock_guard<std::mutex> lock(mutex_);
2785     if (pageRouteStack_.empty()) {
2786         return INVALID_PAGE_ID;
2787     }
2788     return pageRouteStack_.back().pageId;
2789 }
2790 
GetRunningPageUrl() const2791 std::string FrontendDelegateDeclarative::GetRunningPageUrl() const
2792 {
2793     std::lock_guard<std::mutex> lock(mutex_);
2794     if (pageRouteStack_.empty()) {
2795         return std::string();
2796     }
2797     const auto& pageUrl = pageRouteStack_.back().url;
2798     auto pos = pageUrl.rfind(".js");
2799     if (pos == pageUrl.length() - 3) {
2800         return pageUrl.substr(0, pos);
2801     }
2802     return pageUrl;
2803 }
2804 
GetPageIdByUrl(const std::string & url,bool & isRestore)2805 int32_t FrontendDelegateDeclarative::GetPageIdByUrl(const std::string& url, bool& isRestore)
2806 {
2807     std::lock_guard<std::mutex> lock(mutex_);
2808     auto pageIter = std::find_if(std::rbegin(pageRouteStack_), std::rend(pageRouteStack_),
2809         [&url](const PageInfo& pageRoute) { return url == pageRoute.url; });
2810     if (pageIter != std::rend(pageRouteStack_)) {
2811         isRestore = pageIter->isRestore;
2812         return pageIter->pageId;
2813     }
2814     return INVALID_PAGE_ID;
2815 }
2816 
GetPage(int32_t pageId) const2817 RefPtr<JsAcePage> FrontendDelegateDeclarative::GetPage(int32_t pageId) const
2818 {
2819     std::lock_guard<std::mutex> lock(mutex_);
2820     auto itPage = pageMap_.find(pageId);
2821     if (itPage == pageMap_.end()) {
2822         LOGE("the page is not in the map");
2823         return nullptr;
2824     }
2825     return itPage->second;
2826 }
2827 
RegisterFont(const std::string & familyName,const std::string & familySrc,const std::string & bundleName,const std::string & moduleName)2828 void FrontendDelegateDeclarative::RegisterFont(const std::string& familyName, const std::string& familySrc,
2829     const std::string& bundleName, const std::string& moduleName)
2830 {
2831     pipelineContextHolder_.Get()->RegisterFont(familyName, familySrc, bundleName, moduleName);
2832 }
2833 
GetSystemFontList(std::vector<std::string> & fontList)2834 void FrontendDelegateDeclarative::GetSystemFontList(std::vector<std::string>& fontList)
2835 {
2836     pipelineContextHolder_.Get()->GetSystemFontList(fontList);
2837 }
2838 
GetUIFontConfig(FontConfigJsonInfo & fontConfigJsonInfo)2839 void FrontendDelegateDeclarative::GetUIFontConfig(FontConfigJsonInfo& fontConfigJsonInfo)
2840 {
2841     pipelineContextHolder_.Get()->GetUIFontConfig(fontConfigJsonInfo);
2842 }
2843 
GetSystemFont(const std::string & fontName,FontInfo & fontInfo)2844 bool FrontendDelegateDeclarative::GetSystemFont(const std::string& fontName, FontInfo& fontInfo)
2845 {
2846     return pipelineContextHolder_.Get()->GetSystemFont(fontName, fontInfo);
2847 }
2848 
HandleImage(const std::string & src,std::function<void (bool,int32_t,int32_t)> && callback)2849 void FrontendDelegateDeclarative::HandleImage(
2850     const std::string& src, std::function<void(bool, int32_t, int32_t)>&& callback)
2851 {
2852     LOGW("Not implement in declarative frontend.");
2853 }
2854 
PushJsCallbackToRenderNode(NodeId id,double ratio,std::function<void (bool,double)> && callback)2855 void FrontendDelegateDeclarative::PushJsCallbackToRenderNode(
2856     NodeId id, double ratio, std::function<void(bool, double)>&& callback)
2857 {
2858     LOGW("Not implement in declarative frontend.");
2859 }
2860 
RequestAnimationFrame(const std::string & callbackId)2861 void FrontendDelegateDeclarative::RequestAnimationFrame(const std::string& callbackId)
2862 {
2863     CancelableCallback<void()> cancelableTask;
2864     cancelableTask.Reset([callbackId, call = requestAnimationCallback_, weak = AceType::WeakClaim(this)] {
2865         auto delegate = weak.Upgrade();
2866         if (delegate && call) {
2867             call(callbackId, delegate->GetSystemRealTime());
2868         }
2869     });
2870     animationFrameTaskMap_.try_emplace(callbackId, cancelableTask);
2871     animationFrameTaskIds_.emplace(callbackId);
2872 }
2873 
GetSystemRealTime()2874 uint64_t FrontendDelegateDeclarative::GetSystemRealTime()
2875 {
2876     struct timespec ts;
2877     clock_gettime(CLOCK_REALTIME, &ts);
2878     return ts.tv_sec * TO_MILLI + ts.tv_nsec / NANO_TO_MILLI;
2879 }
2880 
CancelAnimationFrame(const std::string & callbackId)2881 void FrontendDelegateDeclarative::CancelAnimationFrame(const std::string& callbackId)
2882 {
2883     auto animationTaskIter = animationFrameTaskMap_.find(callbackId);
2884     if (animationTaskIter != animationFrameTaskMap_.end()) {
2885         animationTaskIter->second.Cancel();
2886         animationFrameTaskMap_.erase(animationTaskIter);
2887     } else {
2888         LOGW("cancelAnimationFrame callbackId not found");
2889     }
2890 }
2891 
FlushAnimationTasks()2892 void FrontendDelegateDeclarative::FlushAnimationTasks()
2893 {
2894     while (!animationFrameTaskIds_.empty()) {
2895         const auto& callbackId = animationFrameTaskIds_.front();
2896         if (!callbackId.empty()) {
2897             auto taskIter = animationFrameTaskMap_.find(callbackId);
2898             if (taskIter != animationFrameTaskMap_.end()) {
2899                 taskExecutor_->PostTask(taskIter->second, TaskExecutor::TaskType::JS);
2900             }
2901         }
2902         animationFrameTaskIds_.pop();
2903     }
2904 }
2905 
GetAnimationJsTask()2906 SingleTaskExecutor FrontendDelegateDeclarative::GetAnimationJsTask()
2907 {
2908     return SingleTaskExecutor::Make(taskExecutor_, TaskExecutor::TaskType::JS);
2909 }
2910 
GetUiTask()2911 SingleTaskExecutor FrontendDelegateDeclarative::GetUiTask()
2912 {
2913     return SingleTaskExecutor::Make(taskExecutor_, TaskExecutor::TaskType::UI);
2914 }
2915 
AttachPipelineContext(const RefPtr<PipelineBase> & context)2916 void FrontendDelegateDeclarative::AttachPipelineContext(const RefPtr<PipelineBase>& context)
2917 {
2918     if (!context) {
2919         return;
2920     }
2921     context->SetOnPageShow([weak = AceType::WeakClaim(this)] {
2922         auto delegate = weak.Upgrade();
2923         if (delegate) {
2924             delegate->OnPageShow();
2925         }
2926     });
2927     context->SetAnimationCallback([weak = AceType::WeakClaim(this)] {
2928         auto delegate = weak.Upgrade();
2929         if (delegate) {
2930             delegate->FlushAnimationTasks();
2931         }
2932     });
2933     pipelineContextHolder_.Attach(context);
2934     jsAccessibilityManager_->SetPipelineContext(context);
2935     jsAccessibilityManager_->InitializeCallback();
2936 }
2937 
AttachSubPipelineContext(const RefPtr<PipelineBase> & context)2938 void FrontendDelegateDeclarative::AttachSubPipelineContext(const RefPtr<PipelineBase>& context)
2939 {
2940     if (!context) {
2941         return;
2942     }
2943     jsAccessibilityManager_->AddSubPipelineContext(context);
2944     jsAccessibilityManager_->RegisterSubWindowInteractionOperation(context->GetWindowId());
2945 }
2946 
GetPipelineContext()2947 RefPtr<PipelineBase> FrontendDelegateDeclarative::GetPipelineContext()
2948 {
2949     return pipelineContextHolder_.Get();
2950 }
2951 
RestoreRouterStack(const std::string & contentInfo)2952 std::pair<std::string, UIContentErrorCode> FrontendDelegateDeclarative::RestoreRouterStack(
2953     const std::string& contentInfo)
2954 {
2955     LOGI("FrontendDelegateDeclarative::RestoreRouterStack: contentInfo = %{public}s", contentInfo.c_str());
2956     auto jsonContentInfo = JsonUtil::ParseJsonString(contentInfo);
2957     if (!jsonContentInfo->IsValid() || !jsonContentInfo->IsObject()) {
2958         LOGW("restore contentInfo is invalid");
2959         return std::make_pair("", UIContentErrorCode::WRONG_PAGE_ROUTER);
2960     }
2961     // restore node info
2962     auto jsonNodeInfo = jsonContentInfo->GetValue("nodeInfo");
2963     auto pipelineContext = pipelineContextHolder_.Get();
2964     CHECK_NULL_RETURN(pipelineContext, std::make_pair("", UIContentErrorCode::WRONG_PAGE_ROUTER));
2965     pipelineContext->RestoreNodeInfo(std::move(jsonNodeInfo));
2966     // restore stack info
2967     auto routerStack = jsonContentInfo->GetValue("stackInfo");
2968     if (Container::IsCurrentUseNewPipeline()) {
2969         CHECK_NULL_RETURN(pageRouterManager_, std::make_pair("", UIContentErrorCode::NULL_PAGE_ROUTER));
2970         return pageRouterManager_->RestoreRouterStack(std::move(routerStack));
2971     } else {
2972         std::lock_guard<std::mutex> lock(mutex_);
2973         if (!routerStack->IsValid() || !routerStack->IsArray()) {
2974             LOGW("restore router stack is invalid");
2975             return std::make_pair("", UIContentErrorCode::WRONG_PAGE_ROUTER);
2976         }
2977         int32_t stackSize = routerStack->GetArraySize();
2978         if (stackSize < 1) {
2979             LOGW("restore stack size is invalid");
2980             return std::make_pair("", UIContentErrorCode::WRONG_PAGE_ROUTER);
2981         }
2982         for (int32_t index = 0; index < stackSize - 1; ++index) {
2983             std::string url = routerStack->GetArrayItem(index)->ToString();
2984             // remove 2 useless character, as "XXX" to XXX
2985             pageRouteStack_.emplace_back(PageInfo { GenerateNextPageId(), url.substr(1, url.size() - 2), true });
2986         }
2987         std::string startUrl = routerStack->GetArrayItem(stackSize - 1)->ToString();
2988         // remove 5 useless character, as "XXX.js" to XXX
2989         return std::make_pair(startUrl.substr(1, startUrl.size() - 5), UIContentErrorCode::NO_ERRORS);
2990     }
2991 }
2992 
GetContentInfo()2993 std::string FrontendDelegateDeclarative::GetContentInfo()
2994 {
2995     auto jsonContentInfo = JsonUtil::Create(true);
2996 
2997     if (!Container::IsCurrentUseNewPipeline()) {
2998         std::lock_guard<std::mutex> lock(mutex_);
2999         auto jsonRouterStack = JsonUtil::CreateArray(true);
3000         for (size_t index = 0; index < pageRouteStack_.size(); ++index) {
3001             jsonRouterStack->Put("", pageRouteStack_[index].url.c_str());
3002         }
3003         jsonContentInfo->Put("stackInfo", jsonRouterStack);
3004     } else {
3005         CHECK_NULL_RETURN(pageRouterManager_, "");
3006         jsonContentInfo->Put("stackInfo", pageRouterManager_->GetStackInfo());
3007     }
3008 
3009     auto pipelineContext = pipelineContextHolder_.Get();
3010     CHECK_NULL_RETURN(pipelineContext, jsonContentInfo->ToString());
3011     jsonContentInfo->Put("nodeInfo", pipelineContext->GetStoredNodeInfo());
3012 
3013     return jsonContentInfo->ToString();
3014 }
3015 
GetSnapshot(const std::string & componentId,NG::ComponentSnapshot::JsCallback && callback)3016 void FrontendDelegateDeclarative::GetSnapshot(
3017     const std::string& componentId, NG::ComponentSnapshot::JsCallback&& callback)
3018 {
3019 #ifdef ENABLE_ROSEN_BACKEND
3020     NG::ComponentSnapshot::Get(componentId, std::move(callback));
3021 #endif
3022 }
3023 
CreateSnapshot(std::function<void ()> && customBuilder,NG::ComponentSnapshot::JsCallback && callback,bool enableInspector)3024 void FrontendDelegateDeclarative::CreateSnapshot(
3025     std::function<void()>&& customBuilder, NG::ComponentSnapshot::JsCallback&& callback, bool enableInspector)
3026 {
3027 #ifdef ENABLE_ROSEN_BACKEND
3028     ViewStackModel::GetInstance()->NewScope();
3029     CHECK_NULL_VOID(customBuilder);
3030     customBuilder();
3031     auto customNode = ViewStackModel::GetInstance()->Finish();
3032 
3033     NG::ComponentSnapshot::Create(customNode, std::move(callback), enableInspector);
3034 #endif
3035 }
3036 } // namespace OHOS::Ace::Framework
3037