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