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