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