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