• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ReplacePage(const std::string & url,const std::string & params)408 void DeclarativeFrontendNG::ReplacePage(const std::string& url, const std::string& params)
409 {
410     if (delegate_) {
411         delegate_->Replace(url, params);
412     }
413 }
414 
PushPage(const std::string & url,const std::string & params)415 void DeclarativeFrontendNG::PushPage(const std::string& url, const std::string& params)
416 {
417     if (delegate_) {
418         delegate_->Push(url, params);
419     }
420 }
421 
422 
GetContextValue()423 napi_value DeclarativeFrontendNG::GetContextValue()
424 {
425     return jsEngine_->GetContextValue();
426 }
427 
GetFrameNodeValueByNodeId(int32_t nodeId)428 napi_value DeclarativeFrontendNG::GetFrameNodeValueByNodeId(int32_t nodeId)
429 {
430     return jsEngine_->GetFrameNodeValueByNodeId(nodeId);
431 }
432 
NavigatePage(uint8_t type,const PageTarget & target,const std::string & params)433 void DeclarativeFrontendNG::NavigatePage(uint8_t type, const PageTarget& target, const std::string& params)
434 {
435     if (delegate_) {
436         delegate_->NavigatePage(type, target, params);
437     }
438 }
439 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)440 void DeclarativeFrontendNG::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
441 {
442     delegate_->OnWindowDisplayModeChanged(isShownInMultiWindow, data);
443 }
444 
GetAccessibilityManager() const445 RefPtr<AccessibilityManager> DeclarativeFrontendNG::GetAccessibilityManager() const
446 {
447     if (!delegate_) {
448         return nullptr;
449     }
450     return delegate_->GetJSAccessibilityManager();
451 }
452 
GetWindowConfig()453 WindowConfig& DeclarativeFrontendNG::GetWindowConfig()
454 {
455     if (!delegate_) {
456         static WindowConfig windowConfig;
457         return windowConfig;
458     }
459     return delegate_->GetWindowConfig();
460 }
461 
OnBackPressed()462 bool DeclarativeFrontendNG::OnBackPressed()
463 {
464     CHECK_NULL_RETURN(delegate_, false);
465     return delegate_->OnPageBackPress();
466 }
467 
OnShow()468 void DeclarativeFrontendNG::OnShow()
469 {
470     foregroundFrontend_ = true;
471     CHECK_NULL_VOID(delegate_);
472     delegate_->OnPageShow();
473 }
474 
OnHide()475 void DeclarativeFrontendNG::OnHide()
476 {
477     foregroundFrontend_ = false;
478     CHECK_NULL_VOID(delegate_);
479     delegate_->OnPageHide();
480 }
481 
CallRouterBack()482 void DeclarativeFrontendNG::CallRouterBack()
483 {
484     if (delegate_) {
485         if (delegate_->GetStackSize() == 1 && isSubWindow_) {
486             LOGW("Can't back because this is the last page of sub window!");
487             return;
488         }
489         delegate_->Back("", "");
490     }
491 }
492 
OnSurfaceChanged(int32_t width,int32_t height)493 void DeclarativeFrontendNG::OnSurfaceChanged(int32_t width, int32_t height)
494 {
495     // TODO: update media query infos
496     if (delegate_) {
497         delegate_->OnSurfaceChanged();
498     }
499 }
500 
OnLayoutCompleted(const std::string & componentId)501 void DeclarativeFrontendNG::OnLayoutCompleted(const std::string& componentId)
502 {
503     if (delegate_) {
504         delegate_->OnLayoutCompleted(componentId);
505     }
506 }
507 
OnDrawCompleted(const std::string & componentId)508 void DeclarativeFrontendNG::OnDrawCompleted(const std::string& componentId)
509 {
510     if (delegate_) {
511         delegate_->OnDrawCompleted(componentId);
512     }
513 }
514 
DumpFrontend() const515 void DeclarativeFrontendNG::DumpFrontend() const
516 {
517     if (!delegate_) {
518         return;
519     }
520     int32_t routerIndex = 0;
521     std::string routerName;
522     std::string routerPath;
523     delegate_->GetState(routerIndex, routerName, routerPath);
524 
525     if (DumpLog::GetInstance().GetDumpFile()) {
526         DumpLog::GetInstance().AddDesc("Components: " + std::to_string(delegate_->GetComponentsCount()));
527         DumpLog::GetInstance().AddDesc("Path: " + routerPath);
528         DumpLog::GetInstance().AddDesc("Length: " + std::to_string(routerIndex));
529         DumpLog::GetInstance().Print(0, routerName, 0);
530     }
531 }
532 
GetPagePath() const533 std::string DeclarativeFrontendNG::GetPagePath() const
534 {
535     if (!delegate_) {
536         return "";
537     }
538     int32_t routerIndex = 0;
539     std::string routerName;
540     std::string routerPath;
541     delegate_->GetState(routerIndex, routerName, routerPath);
542     return routerPath + routerName;
543 }
544 
TriggerGarbageCollection()545 void DeclarativeFrontendNG::TriggerGarbageCollection()
546 {
547     if (jsEngine_) {
548         jsEngine_->RunGarbageCollection();
549     }
550 }
551 
DumpHeapSnapshot(bool isPrivate)552 void DeclarativeFrontendNG::DumpHeapSnapshot(bool isPrivate)
553 {
554     if (jsEngine_) {
555         jsEngine_->DumpHeapSnapshot(isPrivate);
556     }
557 }
558 
NotifyUIIdle()559 void DeclarativeFrontendNG::NotifyUIIdle()
560 {
561     if (jsEngine_) {
562         jsEngine_->NotifyUIIdle();
563     }
564 }
565 
RestoreRouterStack(const std::string & contentInfo)566 std::pair<std::string, UIContentErrorCode> DeclarativeFrontendNG::RestoreRouterStack(const std::string& contentInfo)
567 {
568     if (delegate_) {
569         return delegate_->RestoreRouterStack(contentInfo);
570     }
571     return std::make_pair("", UIContentErrorCode::NULL_POINTER);
572 }
573 
GetContentInfo() const574 std::string DeclarativeFrontendNG::GetContentInfo() const
575 {
576     if (delegate_) {
577         return delegate_->GetContentInfo();
578     }
579     return "";
580 }
581 
SetColorMode(ColorMode colorMode)582 void DeclarativeFrontendNG::SetColorMode(ColorMode colorMode)
583 {
584     // TODO: update media query infos
585     if (delegate_) {
586         delegate_->SetColorMode(colorMode);
587     }
588 }
589 
RebuildAllPages()590 void DeclarativeFrontendNG::RebuildAllPages()
591 {
592     if (delegate_) {
593         delegate_->RebuildAllPages();
594     }
595 }
596 
FlushReload()597 void DeclarativeFrontendNG::FlushReload()
598 {
599     if (jsEngine_) {
600         jsEngine_->FlushReload();
601     }
602 }
603 
HotReload()604 void DeclarativeFrontendNG::HotReload()
605 {
606     auto manager = GetPageRouterManager();
607     CHECK_NULL_VOID(manager);
608     manager->FlushFrontend();
609 }
610 
GetCurrentPageUrl() const611 std::string DeclarativeFrontendNG::GetCurrentPageUrl() const
612 {
613     auto pageRouterManager = GetPageRouterManager();
614     if (pageRouterManager) {
615         return pageRouterManager->GetCurrentPageUrl();
616     }
617     return "";
618 }
619 } // namespace OHOS::Ace
620