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