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