1 /*
2  * Copyright (c) 2022 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/ng/declarative_frontend_ng.h"
17 
18 #include "base/log/dump_log.h"
19 #include "core/common/recorder/node_data_cache.h"
20 #include "core/common/thread_checker.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 #include "frameworks/bridge/declarative_frontend/ng/page_router_manager_factory.h"
23 
24 namespace OHOS::Ace {
25 
~DeclarativeFrontendNG()26 DeclarativeFrontendNG::~DeclarativeFrontendNG() noexcept
27 {
28     LOG_DESTROY();
29 }
30 
Destroy()31 void DeclarativeFrontendNG::Destroy()
32 {
33     // The call doesn't change the page pop status
34     Recorder::NodeDataCache::Get().OnBeforePagePop(true);
35     CHECK_RUN_ON(JS);
36     // To guarantee the jsEngine_ and delegate_ released in js thread
37     delegate_.Reset();
38     jsEngine_->Destroy();
39     jsEngine_.Reset();
40 }
41 
Initialize(FrontendType type,const RefPtr<TaskExecutor> & taskExecutor)42 bool DeclarativeFrontendNG::Initialize(FrontendType type, const RefPtr<TaskExecutor>& taskExecutor)
43 {
44     type_ = type;
45     taskExecutor_ = taskExecutor;
46     ACE_DCHECK(type_ == FrontendType::DECLARATIVE_JS);
47     InitializeDelegate(taskExecutor);
48     bool needPostJsTask = true;
49     auto container = Container::Current();
50     if (container) {
51         const auto& setting = container->GetSettings();
52         needPostJsTask = !(setting.usePlatformAsUIThread && setting.useUIAsJSThread);
53     }
54     auto initJSEngineTask = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_), delegate = delegate_] {
55         auto jsEngine = weakEngine.Upgrade();
56         if (!jsEngine) {
57             return;
58         }
59         jsEngine->Initialize(delegate);
60     };
61     if (needPostJsTask) {
62         taskExecutor->PostTask(initJSEngineTask, TaskExecutor::TaskType::JS, "ArkUIInitJsEngine");
63     } else {
64         initJSEngineTask();
65     }
66     return true;
67 }
68 
AttachPipelineContext(const RefPtr<PipelineBase> & context)69 void DeclarativeFrontendNG::AttachPipelineContext(const RefPtr<PipelineBase>& context)
70 {
71     if (delegate_) {
72         delegate_->AttachPipelineContext(context);
73     }
74 }
75 
AttachSubPipelineContext(const RefPtr<PipelineBase> & context)76 void DeclarativeFrontendNG::AttachSubPipelineContext(const RefPtr<PipelineBase>& context)
77 {
78     if (!delegate_) {
79         return;
80     }
81     delegate_->AttachSubPipelineContext(context);
82 }
83 
SetAssetManager(const RefPtr<AssetManager> & assetManager)84 void DeclarativeFrontendNG::SetAssetManager(const RefPtr<AssetManager>& assetManager)
85 {
86     if (delegate_) {
87         delegate_->SetAssetManager(assetManager);
88     }
89 }
90 
InitializeDelegate(const RefPtr<TaskExecutor> & taskExecutor)91 void DeclarativeFrontendNG::InitializeDelegate(const RefPtr<TaskExecutor>& taskExecutor)
92 {
93     auto pageRouterManager = NG::PageRouterManagerFactory::CreateManager();
94     auto loadPageCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](const std::string& url,
95                                 const std::function<void(const std::string&, int32_t)>& errorCallback) {
96         auto jsEngine = weakEngine.Upgrade();
97         if (!jsEngine) {
98             return false;
99         }
100         return jsEngine->LoadPageSource(url, errorCallback);
101     };
102 
103     auto loadPageByBufferCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
104                                         const std::shared_ptr<std::vector<uint8_t>>& content,
105                                         const std::function<void(const std::string&, int32_t)>& errorCallback,
106                                         const std::string& contentName) {
107         auto jsEngine = weakEngine.Upgrade();
108         if (!jsEngine) {
109             return false;
110         }
111         return jsEngine->LoadPageSource(content, errorCallback, contentName);
112     };
113 
114     auto mediaQueryCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
115                                          const std::string& callbackId, const std::string& args) {
116         auto jsEngine = weakEngine.Upgrade();
117         if (!jsEngine) {
118             return;
119         }
120         jsEngine->MediaQueryCallback(callbackId, args);
121     };
122 
123     auto layoutInspectorCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
124                                        const std::string& componentId) {
125         auto jsEngine = weakEngine.Upgrade();
126         if (!jsEngine) {
127             return;
128         }
129         jsEngine->LayoutInspectorCallback(componentId);
130     };
131 
132     auto drawInspectorCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
133                                      const std::string& componentId) {
134         auto jsEngine = weakEngine.Upgrade();
135         if (!jsEngine) {
136             return;
137         }
138         jsEngine->DrawInspectorCallback(componentId);
139     };
140 
141     auto onStartContinuationCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)]() -> bool {
142         auto jsEngine = weakEngine.Upgrade();
143         if (!jsEngine) {
144             return false;
145         }
146         return jsEngine->OnStartContinuation();
147     };
148 
149     auto onCompleteContinuationCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](int32_t code) {
150         auto jsEngine = weakEngine.Upgrade();
151         if (!jsEngine) {
152             return;
153         }
154         jsEngine->OnCompleteContinuation(code);
155     };
156 
157     auto onSaveDataCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](std::string& savedData) {
158         auto jsEngine = weakEngine.Upgrade();
159         if (!jsEngine) {
160             return;
161         }
162         jsEngine->OnSaveData(savedData);
163     };
164 
165     auto onRemoteTerminatedCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)]() {
166         auto jsEngine = weakEngine.Upgrade();
167         if (!jsEngine) {
168             return;
169         }
170         jsEngine->OnRemoteTerminated();
171     };
172 
173     auto onRestoreDataCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
174                                             const std::string& data) -> bool {
175         auto jsEngine = weakEngine.Upgrade();
176         if (!jsEngine) {
177             return false;
178         }
179         return jsEngine->OnRestoreData(data);
180     };
181 
182     auto destroyApplicationCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
183                                                  const std::string& packageName) {
184         auto jsEngine = weakEngine.Upgrade();
185         if (!jsEngine) {
186             return;
187         }
188         jsEngine->DestroyApplication(packageName);
189     };
190 
191     auto updateApplicationStateCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
192                                                      const std::string& packageName, Frontend::State state) {
193         auto jsEngine = weakEngine.Upgrade();
194         if (!jsEngine) {
195             return;
196         }
197         jsEngine->UpdateApplicationState(packageName, state);
198     };
199 
200     auto onWindowDisplayModeChangedCallBack = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
201                                                          bool isShownInMultiWindow, const std::string& data) {
202         auto jsEngine = weakEngine.Upgrade();
203         if (!jsEngine) {
204             return;
205         }
206         jsEngine->OnWindowDisplayModeChanged(isShownInMultiWindow, data);
207     };
208 
209     auto externalEventCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
210                                             const std::string& componentId, const uint32_t nodeId,
211                                             const bool isDestroy) {
212         auto jsEngine = weakEngine.Upgrade();
213         if (!jsEngine) {
214             return;
215         }
216         jsEngine->FireExternalEvent(componentId, nodeId, isDestroy);
217     };
218 
219     auto timerCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
220                                     const std::string& callbackId, const std::string& delay, bool isInterval) {
221         auto jsEngine = weakEngine.Upgrade();
222         if (!jsEngine) {
223             return;
224         }
225         jsEngine->TimerCallback(callbackId, delay, isInterval);
226     };
227 
228     auto loadNamedRouterCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)](
229                                        const std::string& namedRouter, bool isTriggeredByJs) {
230         auto jsEngine = weakEngine.Upgrade();
231         if (!jsEngine) {
232             return false;
233         }
234         return jsEngine->LoadNamedRouterSource(namedRouter, isTriggeredByJs);
235     };
236 
237     auto updateRootComponentCallback = [weakEngine = WeakPtr<Framework::JsEngine>(jsEngine_)]() {
238         auto jsEngine = weakEngine.Upgrade();
239         if (!jsEngine) {
240             return false;
241         }
242         return jsEngine->UpdateRootComponent();
243     };
244 
245     pageRouterManager->SetLoadJsCallback(std::move(loadPageCallback));
246     pageRouterManager->SetLoadJsByBufferCallback(std::move(loadPageByBufferCallback));
247     pageRouterManager->SetLoadNamedRouterCallback(std::move(loadNamedRouterCallback));
248     pageRouterManager->SetUpdateRootComponentCallback(std::move(updateRootComponentCallback));
249 
250     delegate_ = AceType::MakeRefPtr<Framework::FrontendDelegateDeclarativeNG>(taskExecutor);
251     delegate_->SetMediaQueryCallback(std::move(mediaQueryCallback));
252     delegate_->SetLayoutInspectorCallback(std::move(layoutInspectorCallback));
253     delegate_->SetDrawInspectorCallback(std::move(drawInspectorCallback));
254     delegate_->SetOnStartContinuationCallBack(std::move(onStartContinuationCallBack));
255     delegate_->SetOnCompleteContinuationCallBack(std::move(onCompleteContinuationCallBack));
256     delegate_->SetOnSaveDataCallBack(std::move(onSaveDataCallBack));
257     delegate_->SetOnRemoteTerminatedCallBack(std::move(onRemoteTerminatedCallBack));
258     delegate_->SetOnRestoreDataCallBack(std::move(onRestoreDataCallBack));
259     delegate_->SetDestroyApplicationCallback(std::move(destroyApplicationCallback));
260     delegate_->SetUpdateApplicationStateCallback(std::move(updateApplicationStateCallback));
261     delegate_->SetOnWindowDisplayModeChangedCallback(std::move(onWindowDisplayModeChangedCallBack));
262     delegate_->SetExternalEventCallback(std::move(externalEventCallback));
263     delegate_->SetTimerCallback(std::move(timerCallback));
264 
265     delegate_->SetPageRouterManager(pageRouterManager);
266     if (jsEngine_) {
267         delegate_->SetGroupJsBridge(jsEngine_->GetGroupJsBridge());
268     }
269 }
270 
GetPageRouterManager() const271 RefPtr<NG::PageRouterManager> DeclarativeFrontendNG::GetPageRouterManager() const
272 {
273     CHECK_NULL_RETURN(delegate_, nullptr);
274     return delegate_->GetPageRouterManager();
275 }
276 
UpdateState(Frontend::State state)277 void DeclarativeFrontendNG::UpdateState(Frontend::State state)
278 {
279     if (!delegate_ || state == Frontend::State::ON_CREATE) {
280         return;
281     }
282     bool needPostJsTask = true;
283     auto container = Container::Current();
284     CHECK_NULL_VOID(container);
285     const auto& setting = container->GetSettings();
286     needPostJsTask = !(setting.usePlatformAsUIThread && setting.useUIAsJSThread);
287     if (needPostJsTask) {
288         delegate_->UpdateApplicationState(delegate_->GetAppID(), state);
289         return;
290     }
291     if (jsEngine_) {
292         jsEngine_->UpdateApplicationState(delegate_->GetAppID(), state);
293     }
294 }
295 
OnConfigurationUpdated(const std::string & data)296 void DeclarativeFrontendNG::OnConfigurationUpdated(const std::string& data)
297 {
298     if (delegate_) {
299         delegate_->OnConfigurationUpdated(data);
300     }
301 }
302 
OnActive()303 void DeclarativeFrontendNG::OnActive()
304 {
305     if (delegate_) {
306         foregroundFrontend_ = true;
307         delegate_->InitializeAccessibilityCallback();
308     }
309 }
310 
OnCompleteContinuation(int32_t code)311 void DeclarativeFrontendNG::OnCompleteContinuation(int32_t code)
312 {
313     if (delegate_) {
314         delegate_->OnCompleteContinuation(code);
315     }
316 }
317 
OnSaveData(std::string & data)318 void DeclarativeFrontendNG::OnSaveData(std::string& data)
319 {
320     if (delegate_) {
321         delegate_->OnSaveData(data);
322     }
323 }
324 
OnRemoteTerminated()325 void DeclarativeFrontendNG::OnRemoteTerminated()
326 {
327     if (delegate_) {
328         delegate_->OnRemoteTerminated();
329     }
330 }
331 
NotifyAppStorage(const std::string & key,const std::string & value)332 void DeclarativeFrontendNG::NotifyAppStorage(const std::string& key, const std::string& value)
333 {
334     if (!delegate_) {
335         return;
336     }
337     delegate_->NotifyAppStorage(jsEngine_, key, value);
338 }
339 
GetRouterSize() const340 int32_t DeclarativeFrontendNG::GetRouterSize() const
341 {
342     if (delegate_) {
343         return delegate_->GetStackSize();
344     }
345     return -1;
346 }
347 
OnStartContinuation()348 bool DeclarativeFrontendNG::OnStartContinuation()
349 {
350     if (!delegate_) {
351         return false;
352     }
353     return delegate_->OnStartContinuation();
354 }
355 
OnRestoreData(const std::string & data)356 bool DeclarativeFrontendNG::OnRestoreData(const std::string& data)
357 {
358     if (!delegate_) {
359         return false;
360     }
361     return delegate_->OnRestoreData(data);
362 }
363 
RunPage(const std::string & url,const std::string & params)364 UIContentErrorCode DeclarativeFrontendNG::RunPage(const std::string& url, const std::string& params)
365 {
366     auto container = Container::Current();
367     auto isStageModel = container ? container->IsUseStageModel() : false;
368     if (!isStageModel) {
369         // In NG structure and fa mode, first load app.js
370         auto taskExecutor = container ? container->GetTaskExecutor() : nullptr;
371         CHECK_NULL_RETURN(taskExecutor, UIContentErrorCode::NULL_POINTER);
372         taskExecutor->PostTask(
373             [weak = AceType::WeakClaim(this)]() {
374                 auto frontend = weak.Upgrade();
375                 CHECK_NULL_VOID(frontend);
376                 CHECK_NULL_VOID(frontend->jsEngine_);
377                 frontend->jsEngine_->LoadFaAppSource();
378             },
379             TaskExecutor::TaskType::JS, "ArkUILoadFaAppSource");
380     }
381     // Not use this pageId from backend, manage it in FrontendDelegateDeclarativeNg.
382     if (delegate_) {
383         delegate_->RunPage(url, params, pageProfile_);
384         return UIContentErrorCode::NO_ERRORS;
385     }
386 
387     return UIContentErrorCode::NULL_POINTER;
388 }
389 
RunPage(const std::shared_ptr<std::vector<uint8_t>> & content,const std::string & params)390 UIContentErrorCode DeclarativeFrontendNG::RunPage(
391     const std::shared_ptr<std::vector<uint8_t>>& content, const std::string& params)
392 {
393     auto container = Container::Current();
394     auto isStageModel = container ? container->IsUseStageModel() : false;
395     if (!isStageModel) {
396         LOGE("RunPage by buffer must be run under stage model.");
397         return UIContentErrorCode::NO_STAGE;
398     }
399 
400     if (delegate_) {
401         delegate_->RunPage(content, params, pageProfile_);
402         return UIContentErrorCode::NO_ERRORS;
403     }
404 
405     return UIContentErrorCode::NULL_POINTER;
406 }
407 
RunPageByNamedRouter(const std::string & name,const std::string & params)408 UIContentErrorCode DeclarativeFrontendNG::RunPageByNamedRouter(const std::string& name, const std::string& params)
409 {
410     if (delegate_) {
411         delegate_->RunPage(name, params, pageProfile_, true);
412         return UIContentErrorCode::NO_ERRORS;
413     }
414     return UIContentErrorCode::NULL_POINTER;
415 }
416 
ReplacePage(const std::string & url,const std::string & params)417 void DeclarativeFrontendNG::ReplacePage(const std::string& url, const std::string& params)
418 {
419     if (delegate_) {
420         delegate_->Replace(url, params);
421     }
422 }
423 
PushPage(const std::string & url,const std::string & params)424 void DeclarativeFrontendNG::PushPage(const std::string& url, const std::string& params)
425 {
426     if (delegate_) {
427         delegate_->Push(url, params);
428     }
429 }
430 
431 
GetContextValue()432 napi_value DeclarativeFrontendNG::GetContextValue()
433 {
434     return jsEngine_->GetContextValue();
435 }
436 
GetFrameNodeValueByNodeId(int32_t nodeId)437 napi_value DeclarativeFrontendNG::GetFrameNodeValueByNodeId(int32_t nodeId)
438 {
439     return jsEngine_->GetFrameNodeValueByNodeId(nodeId);
440 }
441 
NavigatePage(uint8_t type,const PageTarget & target,const std::string & params)442 void DeclarativeFrontendNG::NavigatePage(uint8_t type, const PageTarget& target, const std::string& params)
443 {
444     if (delegate_) {
445         delegate_->NavigatePage(type, target, params);
446     }
447 }
448 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)449 void DeclarativeFrontendNG::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
450 {
451     delegate_->OnWindowDisplayModeChanged(isShownInMultiWindow, data);
452 }
453 
GetAccessibilityManager() const454 RefPtr<AccessibilityManager> DeclarativeFrontendNG::GetAccessibilityManager() const
455 {
456     if (!delegate_) {
457         return nullptr;
458     }
459     return delegate_->GetJSAccessibilityManager();
460 }
461 
GetWindowConfig()462 WindowConfig& DeclarativeFrontendNG::GetWindowConfig()
463 {
464     if (!delegate_) {
465         static WindowConfig windowConfig;
466         return windowConfig;
467     }
468     return delegate_->GetWindowConfig();
469 }
470 
OnBackPressed()471 bool DeclarativeFrontendNG::OnBackPressed()
472 {
473     CHECK_NULL_RETURN(delegate_, false);
474     return delegate_->OnPageBackPress();
475 }
476 
OnShow()477 void DeclarativeFrontendNG::OnShow()
478 {
479     foregroundFrontend_ = true;
480     CHECK_NULL_VOID(delegate_);
481     delegate_->OnPageShow();
482 }
483 
OnHide()484 void DeclarativeFrontendNG::OnHide()
485 {
486     foregroundFrontend_ = false;
487     CHECK_NULL_VOID(delegate_);
488     delegate_->OnPageHide();
489 }
490 
CallRouterBack()491 void DeclarativeFrontendNG::CallRouterBack()
492 {
493     if (delegate_) {
494         if (delegate_->GetStackSize() == 1 && isSubWindow_) {
495             LOGW("Can't back because this is the last page of sub window!");
496             return;
497         }
498         delegate_->Back("", "");
499     }
500 }
501 
OnSurfaceChanged(int32_t width,int32_t height)502 void DeclarativeFrontendNG::OnSurfaceChanged(int32_t width, int32_t height)
503 {
504     // TODO: update media query infos
505     if (delegate_) {
506         delegate_->OnSurfaceChanged();
507     }
508 }
509 
OnLayoutCompleted(const std::string & componentId)510 void DeclarativeFrontendNG::OnLayoutCompleted(const std::string& componentId)
511 {
512     if (delegate_) {
513         delegate_->OnLayoutCompleted(componentId);
514     }
515 }
516 
OnDrawCompleted(const std::string & componentId)517 void DeclarativeFrontendNG::OnDrawCompleted(const std::string& componentId)
518 {
519     if (delegate_) {
520         delegate_->OnDrawCompleted(componentId);
521     }
522 }
523 
DumpFrontend() const524 void DeclarativeFrontendNG::DumpFrontend() const
525 {
526     if (!delegate_) {
527         return;
528     }
529     int32_t routerIndex = 0;
530     std::string routerName;
531     std::string routerPath;
532     delegate_->GetState(routerIndex, routerName, routerPath);
533 
534     if (DumpLog::GetInstance().GetDumpFile()) {
535         DumpLog::GetInstance().AddDesc("Components: " + std::to_string(delegate_->GetComponentsCount()));
536         DumpLog::GetInstance().AddDesc("Path: " + routerPath);
537         DumpLog::GetInstance().AddDesc("Length: " + std::to_string(routerIndex));
538         DumpLog::GetInstance().Print(0, routerName, 0);
539     }
540 }
541 
GetPagePath() const542 std::string DeclarativeFrontendNG::GetPagePath() const
543 {
544     if (!delegate_) {
545         return "";
546     }
547     int32_t routerIndex = 0;
548     std::string routerName;
549     std::string routerPath;
550     delegate_->GetState(routerIndex, routerName, routerPath);
551     return routerPath + routerName;
552 }
553 
TriggerGarbageCollection()554 void DeclarativeFrontendNG::TriggerGarbageCollection()
555 {
556     if (jsEngine_) {
557         jsEngine_->RunGarbageCollection();
558     }
559 }
560 
DumpHeapSnapshot(bool isPrivate)561 void DeclarativeFrontendNG::DumpHeapSnapshot(bool isPrivate)
562 {
563     if (jsEngine_) {
564         jsEngine_->DumpHeapSnapshot(isPrivate);
565     }
566 }
567 
NotifyUIIdle()568 void DeclarativeFrontendNG::NotifyUIIdle()
569 {
570     if (jsEngine_) {
571         jsEngine_->NotifyUIIdle();
572     }
573 }
574 
RestoreRouterStack(const std::string & contentInfo,ContentInfoType type)575 std::pair<RouterRecoverRecord, UIContentErrorCode> DeclarativeFrontendNG::RestoreRouterStack(
576     const std::string& contentInfo, ContentInfoType type)
577 {
578     if (delegate_) {
579         return delegate_->RestoreRouterStack(contentInfo, type);
580     }
581     return std::make_pair(RouterRecoverRecord(), UIContentErrorCode::NULL_POINTER);
582 }
583 
GetContentInfo(ContentInfoType type) const584 std::string DeclarativeFrontendNG::GetContentInfo(ContentInfoType type) const
585 {
586     if (delegate_) {
587         return delegate_->GetContentInfo(type);
588     }
589     return "";
590 }
591 
SetColorMode(ColorMode colorMode)592 void DeclarativeFrontendNG::SetColorMode(ColorMode colorMode)
593 {
594     // TODO: update media query infos
595     if (delegate_) {
596         delegate_->SetColorMode(colorMode);
597     }
598 }
599 
RebuildAllPages()600 void DeclarativeFrontendNG::RebuildAllPages()
601 {
602     if (delegate_) {
603         delegate_->RebuildAllPages();
604     }
605 }
606 
FlushReload()607 void DeclarativeFrontendNG::FlushReload()
608 {
609     if (jsEngine_) {
610         jsEngine_->FlushReload();
611     }
612 }
613 
HotReload()614 void DeclarativeFrontendNG::HotReload()
615 {
616     auto manager = GetPageRouterManager();
617     CHECK_NULL_VOID(manager);
618     manager->FlushFrontend();
619 }
620 
GetCurrentPageUrl() const621 std::string DeclarativeFrontendNG::GetCurrentPageUrl() const
622 {
623     auto pageRouterManager = GetPageRouterManager();
624     if (pageRouterManager) {
625         return pageRouterManager->GetCurrentPageUrl();
626     }
627     return "";
628 }
629 } // namespace OHOS::Ace
630