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