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