1 /*
2 * Copyright (c) 2021-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 <cstdlib>
17 #include <regex>
18
19 #include "system_ability_definition.h"
20 #include "if_system_ability_manager.h"
21 #include "ability_delegator_registry.h"
22 #include "ability_runtime/js_ability.h"
23
24 #include "ability_runtime/js_ability_context.h"
25 #include "ability_recovery.h"
26 #include "ability_start_setting.h"
27 #include "connection_manager.h"
28 #include "hilog_wrapper.h"
29 #include "js_data_struct_converter.h"
30 #include "js_runtime.h"
31 #include "js_runtime_utils.h"
32 #include "napi_common_configuration.h"
33 #ifdef SUPPORT_GRAPHICS
34 #include "js_window_stage.h"
35 #endif
36 #include "napi_common_want.h"
37 #include "napi_remote_object.h"
38 #include "string_wrapper.h"
39 #include "context/context.h"
40 #include "context/application_context.h"
41 #include "hitrace_meter.h"
42
43 namespace OHOS {
44 namespace AbilityRuntime {
45 namespace {
PromiseCallback(NativeEngine * engine,NativeCallbackInfo * info)46 NativeValue *PromiseCallback(NativeEngine *engine, NativeCallbackInfo *info)
47 {
48 if (info == nullptr || info->functionInfo == nullptr || info->functionInfo->data == nullptr) {
49 HILOG_ERROR("Invalid input info.");
50 return nullptr;
51 }
52 void *data = info->functionInfo->data;
53 auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
54 callbackInfo->Call();
55 AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
56 info->functionInfo->data = nullptr;
57 return nullptr;
58 }
59 }
60
AttachJsAbilityContext(NativeEngine * engine,void * value,void *)61 NativeValue *AttachJsAbilityContext(NativeEngine *engine, void *value, void *)
62 {
63 HILOG_DEBUG("AttachJsAbilityContext");
64 if (value == nullptr) {
65 HILOG_WARN("invalid parameter.");
66 return nullptr;
67 }
68 auto ptr = reinterpret_cast<std::weak_ptr<AbilityRuntime::AbilityContext>*>(value)->lock();
69 if (ptr == nullptr) {
70 HILOG_WARN("invalid context.");
71 return nullptr;
72 }
73 NativeValue *object = CreateJsAbilityContext(*engine, ptr, nullptr, nullptr);
74 auto systemModule = JsRuntime::LoadSystemModuleByEngine(engine, "application.AbilityContext", &object, 1);
75 if (systemModule == nullptr) {
76 HILOG_WARN("invalid systemModule.");
77 return nullptr;
78 }
79 auto contextObj = systemModule->Get();
80 NativeObject *nObject = ConvertNativeValueTo<NativeObject>(contextObj);
81 nObject->ConvertToNativeBindingObject(engine, DetachCallbackFunc, AttachJsAbilityContext, value, nullptr);
82 auto workContext = new (std::nothrow) std::weak_ptr<AbilityRuntime::AbilityContext>(ptr);
83 nObject->SetNativePointer(workContext,
84 [](NativeEngine *, void * data, void *) {
85 HILOG_DEBUG("Finalizer for weak_ptr ability context is called");
86 delete static_cast<std::weak_ptr<AbilityRuntime::AbilityContext> *>(data);
87 }, nullptr);
88 return contextObj;
89 }
90
Create(const std::unique_ptr<Runtime> & runtime)91 Ability *JsAbility::Create(const std::unique_ptr<Runtime> &runtime)
92 {
93 return new JsAbility(static_cast<JsRuntime &>(*runtime));
94 }
95
JsAbility(JsRuntime & jsRuntime)96 JsAbility::JsAbility(JsRuntime &jsRuntime) : jsRuntime_(jsRuntime)
97 {}
~JsAbility()98 JsAbility::~JsAbility()
99 {
100 HILOG_DEBUG("Js ability destructor.");
101 auto context = GetAbilityContext();
102 if (context) {
103 context->Unbind();
104 }
105
106 jsRuntime_.FreeNativeReference(std::move(jsAbilityObj_));
107 jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
108 #ifdef SUPPORT_GRAPHICS
109 jsRuntime_.FreeNativeReference(std::move(jsWindowStageObj_));
110 #endif
111 }
112
Init(const std::shared_ptr<AbilityInfo> & abilityInfo,const std::shared_ptr<OHOSApplication> application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)113 void JsAbility::Init(const std::shared_ptr<AbilityInfo> &abilityInfo,
114 const std::shared_ptr<OHOSApplication> application, std::shared_ptr<AbilityHandler> &handler,
115 const sptr<IRemoteObject> &token)
116 {
117 Ability::Init(abilityInfo, application, handler, token);
118
119 if (!abilityInfo) {
120 HILOG_ERROR("abilityInfo is nullptr");
121 return;
122 }
123
124 std::string srcPath(abilityInfo->package);
125 if (!abilityInfo->isModuleJson) {
126 /* temporary compatibility api8 + config.json */
127 srcPath.append("/assets/js/");
128 if (!abilityInfo->srcPath.empty()) {
129 srcPath.append(abilityInfo->srcPath);
130 }
131 srcPath.append("/").append(abilityInfo->name).append(".abc");
132 } else {
133 if (abilityInfo->srcEntrance.empty()) {
134 HILOG_ERROR("abilityInfo srcEntrance is empty");
135 return;
136 }
137 srcPath.append("/");
138 srcPath.append(abilityInfo->srcEntrance);
139 srcPath.erase(srcPath.rfind("."));
140 srcPath.append(".abc");
141 HILOG_INFO("JsAbility srcPath is %{public}s", srcPath.c_str());
142 }
143
144 std::string moduleName(abilityInfo->moduleName);
145 moduleName.append("::").append(abilityInfo->name);
146
147 HandleScope handleScope(jsRuntime_);
148 auto &engine = jsRuntime_.GetNativeEngine();
149
150 jsAbilityObj_ = jsRuntime_.LoadModule(
151 moduleName, srcPath, abilityInfo->hapPath, abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE);
152 if (jsAbilityObj_ == nullptr) {
153 HILOG_ERROR("Failed to get AbilityStage object");
154 return;
155 }
156
157 NativeObject *obj = ConvertNativeValueTo<NativeObject>(jsAbilityObj_->Get());
158 if (obj == nullptr) {
159 HILOG_ERROR("Failed to convert AbilityStage object");
160 return;
161 }
162
163 auto context = GetAbilityContext();
164 NativeValue *contextObj = CreateJsAbilityContext(engine, context, nullptr, nullptr);
165 shellContextRef_ = std::shared_ptr<NativeReference>(
166 JsRuntime::LoadSystemModuleByEngine(&engine, "application.AbilityContext", &contextObj, 1).release());
167 contextObj = shellContextRef_->Get();
168 auto nativeObj = ConvertNativeValueTo<NativeObject>(contextObj);
169 if (nativeObj == nullptr) {
170 HILOG_ERROR("Failed to get ability native object");
171 return;
172 }
173 auto workContext = new (std::nothrow) std::weak_ptr<AbilityRuntime::AbilityContext>(context);
174 nativeObj->ConvertToNativeBindingObject(&engine, DetachCallbackFunc, AttachJsAbilityContext,
175 workContext, nullptr);
176 context->Bind(jsRuntime_, shellContextRef_.get());
177 obj->SetProperty("context", contextObj);
178 HILOG_DEBUG("Set ability context");
179
180 nativeObj->SetNativePointer(
181 workContext,
182 [](NativeEngine *, void *data, void *) {
183 HILOG_DEBUG("Finalizer for weak_ptr ability context is called");
184 delete static_cast<std::weak_ptr<AbilityRuntime::AbilityContext> *>(data);
185 },
186 nullptr);
187 }
188
OnStart(const Want & want)189 void JsAbility::OnStart(const Want &want)
190 {
191 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
192 HILOG_DEBUG("OnStart begin, ability is %{public}s.", GetAbilityName().c_str());
193 Ability::OnStart(want);
194
195 if (!jsAbilityObj_) {
196 HILOG_WARN("Not found Ability.js");
197 return;
198 }
199 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
200 if (applicationContext != nullptr) {
201 applicationContext->DispatchOnAbilityCreate(jsAbilityObj_);
202 }
203
204 HandleScope handleScope(jsRuntime_);
205 auto &nativeEngine = jsRuntime_.GetNativeEngine();
206
207 NativeValue *value = jsAbilityObj_->Get();
208 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
209 if (obj == nullptr) {
210 HILOG_ERROR("Failed to get Ability object");
211 return;
212 }
213
214 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(&nativeEngine), want);
215 NativeValue *jsWant = reinterpret_cast<NativeValue *>(napiWant);
216
217 obj->SetProperty("launchWant", jsWant);
218 obj->SetProperty("lastRequestWant", jsWant);
219
220 NativeValue *argv[] = {
221 jsWant,
222 CreateJsLaunchParam(nativeEngine, GetLaunchParam()),
223 };
224 CallObjectMethod("onCreate", argv, ArraySize(argv));
225
226 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
227 if (delegator) {
228 HILOG_DEBUG("Call AbilityDelegator::PostPerformStart");
229 delegator->PostPerformStart(CreateADelegatorAbilityProperty());
230 }
231 HILOG_DEBUG("OnStart end, ability is %{public}s.", GetAbilityName().c_str());
232 }
233
OnStop()234 void JsAbility::OnStop()
235 {
236 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
237 HILOG_DEBUG("OnStop begin.");
238 if (abilityContext_) {
239 HILOG_DEBUG("OnStop, set terminating true.");
240 abilityContext_->SetTerminating(true);
241 }
242 Ability::OnStop();
243 CallObjectMethod("onDestroy");
244 OnStopCallback();
245 HILOG_DEBUG("OnStop end.");
246 }
247
OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)248 void JsAbility::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
249 {
250 if (callbackInfo == nullptr) {
251 isAsyncCallback = false;
252 OnStop();
253 return;
254 }
255
256 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
257 HILOG_DEBUG("OnStop begin.");
258 if (abilityContext_) {
259 HILOG_DEBUG("OnStop, set terminating true.");
260 abilityContext_->SetTerminating(true);
261 }
262
263 Ability::OnStop();
264
265 HandleScope handleScope(jsRuntime_);
266 NativeValue *result = CallObjectMethod("onDestroy", nullptr, 0, true);
267 if (!CheckPromise(result)) {
268 OnStopCallback();
269 isAsyncCallback = false;
270 return;
271 }
272
273 std::weak_ptr<Ability> weakPtr = shared_from_this();
274 auto asyncCallback = [abilityWeakPtr = weakPtr]() {
275 auto ability = abilityWeakPtr.lock();
276 if (ability == nullptr) {
277 HILOG_ERROR("ability is nullptr.");
278 return;
279 }
280 ability->OnStopCallback();
281 };
282 callbackInfo->Push(asyncCallback);
283 isAsyncCallback = CallPromise(result, callbackInfo);
284 if (!isAsyncCallback) {
285 HILOG_ERROR("Failed to call promise.");
286 OnStopCallback();
287 }
288 HILOG_DEBUG("OnStop end.");
289 }
290
OnStopCallback()291 void JsAbility::OnStopCallback()
292 {
293 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
294 if (delegator) {
295 HILOG_DEBUG("Call AbilityDelegator::PostPerformStop");
296 delegator->PostPerformStop(CreateADelegatorAbilityProperty());
297 }
298
299 bool ret = ConnectionManager::GetInstance().DisconnectCaller(AbilityContext::token_);
300 if (ret) {
301 ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
302 HILOG_DEBUG("The service connection is not disconnected.");
303 }
304
305 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
306 if (applicationContext != nullptr) {
307 applicationContext->DispatchOnAbilityDestroy(jsAbilityObj_);
308 }
309 }
310
311 #ifdef SUPPORT_GRAPHICS
312 const std::string PAGE_STACK_PROPERTY_NAME = "pageStack";
313 const std::string SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME = "ohos.extra.param.key.supportContinuePageStack";
314
OnSceneCreated()315 void JsAbility::OnSceneCreated()
316 {
317 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
318 HILOG_DEBUG("OnSceneCreated begin, ability is %{public}s.", GetAbilityName().c_str());
319 Ability::OnSceneCreated();
320 auto jsAppWindowStage = CreateAppWindowStage();
321 if (jsAppWindowStage == nullptr) {
322 HILOG_ERROR("Failed to create jsAppWindowStage object by LoadSystemModule");
323 return;
324 }
325
326 HandleScope handleScope(jsRuntime_);
327 NativeValue *argv[] = {jsAppWindowStage->Get()};
328 CallObjectMethod("onWindowStageCreate", argv, ArraySize(argv));
329
330 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
331 if (delegator) {
332 HILOG_DEBUG("Call AbilityDelegator::PostPerformScenceCreated");
333 delegator->PostPerformScenceCreated(CreateADelegatorAbilityProperty());
334 }
335
336 jsWindowStageObj_ = std::shared_ptr<NativeReference>(jsAppWindowStage.release());
337 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
338 if (applicationContext != nullptr) {
339 applicationContext->DispatchOnWindowStageCreate(jsAbilityObj_, jsWindowStageObj_);
340 }
341
342 HILOG_DEBUG("OnSceneCreated end, ability is %{public}s.", GetAbilityName().c_str());
343 }
344
OnSceneRestored()345 void JsAbility::OnSceneRestored()
346 {
347 Ability::OnSceneRestored();
348 HILOG_DEBUG("OnSceneRestored");
349 auto jsAppWindowStage = CreateAppWindowStage();
350 if (jsAppWindowStage == nullptr) {
351 HILOG_ERROR("Failed to create jsAppWindowStage object by LoadSystemModule");
352 return;
353 }
354 NativeValue *argv[] = {jsAppWindowStage->Get()};
355 CallObjectMethod("onWindowStageRestore", argv, ArraySize(argv));
356
357 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
358 if (delegator) {
359 HILOG_DEBUG("Call AbilityDelegator::PostPerformScenceRestored");
360 delegator->PostPerformScenceRestored(CreateADelegatorAbilityProperty());
361 }
362
363 jsWindowStageObj_ = std::shared_ptr<NativeReference>(jsAppWindowStage.release());
364 }
365
onSceneDestroyed()366 void JsAbility::onSceneDestroyed()
367 {
368 HILOG_DEBUG("onSceneDestroyed begin, ability is %{public}s.", GetAbilityName().c_str());
369 Ability::onSceneDestroyed();
370
371 CallObjectMethod("onWindowStageDestroy");
372
373 if (scene_ != nullptr) {
374 auto window = scene_->GetMainWindow();
375 if (window != nullptr) {
376 HILOG_DEBUG("Call UnregisterDisplayMoveListener");
377 window->UnregisterDisplayMoveListener(abilityDisplayMoveListener_);
378 }
379 }
380
381 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
382 if (delegator) {
383 HILOG_DEBUG("Call AbilityDelegator::PostPerformScenceDestroyed");
384 delegator->PostPerformScenceDestroyed(CreateADelegatorAbilityProperty());
385 }
386
387 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
388 if (applicationContext != nullptr) {
389 applicationContext->DispatchOnWindowStageDestroy(jsAbilityObj_, jsWindowStageObj_);
390 }
391 HILOG_DEBUG("onSceneDestroyed end, ability is %{public}s.", GetAbilityName().c_str());
392 }
393
OnForeground(const Want & want)394 void JsAbility::OnForeground(const Want &want)
395 {
396 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
397 HILOG_DEBUG("OnForeground begin, ability is %{public}s.", GetAbilityName().c_str());
398 if (abilityInfo_) {
399 jsRuntime_.UpdateModuleNameAndAssetPath(abilityInfo_->moduleName);
400 }
401
402 Ability::OnForeground(want);
403
404 HandleScope handleScope(jsRuntime_);
405 auto &nativeEngine = jsRuntime_.GetNativeEngine();
406 if (jsAbilityObj_ == nullptr) {
407 HILOG_ERROR("Failed to get AbilityStage object");
408 return;
409 }
410 NativeValue *value = jsAbilityObj_->Get();
411 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
412 if (obj == nullptr) {
413 HILOG_ERROR("Failed to get Ability object");
414 return;
415 }
416
417 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(&nativeEngine), want);
418 NativeValue *jsWant = reinterpret_cast<NativeValue *>(napiWant);
419
420 obj->SetProperty("lastRequestWant", jsWant);
421
422 CallObjectMethod("onForeground", &jsWant, 1);
423
424 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
425 if (delegator) {
426 HILOG_DEBUG("Call AbilityDelegator::PostPerformForeground");
427 delegator->PostPerformForeground(CreateADelegatorAbilityProperty());
428 }
429
430 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
431 if (applicationContext != nullptr) {
432 applicationContext->DispatchOnAbilityForeground(jsAbilityObj_);
433 }
434 HILOG_DEBUG("OnForeground end, ability is %{public}s.", GetAbilityName().c_str());
435 }
436
OnBackground()437 void JsAbility::OnBackground()
438 {
439 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
440 HILOG_DEBUG("OnBackground begin, ability is %{public}s.", GetAbilityName().c_str());
441 CallObjectMethod("onBackground");
442 Ability::OnBackground();
443
444 auto delegator = AppExecFwk::AbilityDelegatorRegistry::GetAbilityDelegator();
445 if (delegator) {
446 HILOG_DEBUG("Call AbilityDelegator::PostPerformBackground");
447 delegator->PostPerformBackground(CreateADelegatorAbilityProperty());
448 }
449
450 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
451 if (applicationContext != nullptr) {
452 applicationContext->DispatchOnAbilityBackground(jsAbilityObj_);
453 }
454 HILOG_DEBUG("OnBackground end, ability is %{public}s.", GetAbilityName().c_str());
455 }
456
CreateAppWindowStage()457 std::unique_ptr<NativeReference> JsAbility::CreateAppWindowStage()
458 {
459 HandleScope handleScope(jsRuntime_);
460 auto &engine = jsRuntime_.GetNativeEngine();
461 NativeValue *jsWindowStage = Rosen::CreateJsWindowStage(engine, GetScene());
462 if (jsWindowStage == nullptr) {
463 HILOG_ERROR("Failed to create jsWindowSatge object");
464 return nullptr;
465 }
466 return JsRuntime::LoadSystemModuleByEngine(&engine, "application.WindowStage", &jsWindowStage, 1);
467 }
468
GetPageStackFromWant(const Want & want,std::string & pageStack)469 void JsAbility::GetPageStackFromWant(const Want &want, std::string &pageStack)
470 {
471 auto stringObj = AAFwk::IString::Query(want.GetParams().GetParam(PAGE_STACK_PROPERTY_NAME));
472 if (stringObj != nullptr) {
473 pageStack = AAFwk::String::Unbox(stringObj);
474 }
475 }
476
IsRestorePageStack(const Want & want)477 bool JsAbility::IsRestorePageStack(const Want &want)
478 {
479 return want.GetBoolParam(SUPPORT_CONTINUE_PAGE_STACK_PROPERTY_NAME, true);
480 }
481
RestorePageStack(const Want & want)482 void JsAbility::RestorePageStack(const Want &want)
483 {
484 if (IsRestorePageStack(want)) {
485 std::string pageStack;
486 GetPageStackFromWant(want, pageStack);
487 HandleScope handleScope(jsRuntime_);
488 auto &engine = jsRuntime_.GetNativeEngine();
489 if (abilityContext_->GetContentStorage()) {
490 scene_->GetMainWindow()->SetUIContent(pageStack, &engine,
491 abilityContext_->GetContentStorage()->Get(), true);
492 } else {
493 HILOG_ERROR("restore: content storage is nullptr");
494 }
495 }
496 }
497
AbilityContinuationOrRecover(const Want & want)498 void JsAbility::AbilityContinuationOrRecover(const Want &want)
499 {
500 // multi-instance ability continuation
501 HILOG_DEBUG("launch reason = %{public}d", launchParam_.launchReason);
502 if (IsRestoredInContinuation()) {
503 RestorePageStack(want);
504 OnSceneRestored();
505 NotifyContinuationResult(want, true);
506 } else if (ShouldRecoverState(want)) {
507 std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST);
508 HandleScope handleScope(jsRuntime_);
509 auto &engine = jsRuntime_.GetNativeEngine();
510 auto mainWindow = scene_->GetMainWindow();
511 if (mainWindow != nullptr) {
512 mainWindow->SetUIContent(pageStack, &engine, abilityContext_->GetContentStorage()->Get(), true);
513 } else {
514 HILOG_ERROR("AppRecovery:AbilityContinuationOrRecover mainWindow nullptr");
515 }
516 OnSceneRestored();
517 } else {
518 OnSceneCreated();
519 }
520 }
521
DoOnForeground(const Want & want)522 void JsAbility::DoOnForeground(const Want &want)
523 {
524 if (scene_ == nullptr) {
525 if ((abilityContext_ == nullptr) || (sceneListener_ == nullptr)) {
526 HILOG_ERROR("Ability::OnForeground error. abilityContext_ or sceneListener_ is nullptr!");
527 return;
528 }
529 scene_ = std::make_shared<Rosen::WindowScene>();
530 int32_t displayId = Rosen::WindowScene::DEFAULT_DISPLAY_ID;
531 if (setting_ != nullptr) {
532 std::string strDisplayId =
533 setting_->GetProperty(OHOS::AppExecFwk::AbilityStartSetting::WINDOW_DISPLAY_ID_KEY);
534 std::regex formatRegex("[0-9]{0,9}$");
535 std::smatch sm;
536 bool flag = std::regex_match(strDisplayId, sm, formatRegex);
537 if (flag && !strDisplayId.empty()) {
538 int base = 10; // Numerical base (radix) that determines the valid characters and their interpretation.
539 displayId = strtol(strDisplayId.c_str(), nullptr, base);
540 HILOG_DEBUG("%{public}s success. displayId is %{public}d", __func__, displayId);
541 } else {
542 HILOG_WARN("%{public}s failed to formatRegex:[%{public}s]", __func__, strDisplayId.c_str());
543 }
544 }
545 auto option = GetWindowOption(want);
546 Rosen::WMError ret = scene_->Init(displayId, abilityContext_, sceneListener_, option);
547 if (ret != Rosen::WMError::WM_OK) {
548 HILOG_ERROR("%{public}s error. failed to init window scene!", __func__);
549 return;
550 }
551
552 AbilityContinuationOrRecover(want);
553 auto window = scene_->GetMainWindow();
554 if (window) {
555 HILOG_DEBUG("Call RegisterDisplayMoveListener, windowId: %{public}d", window->GetWindowId());
556 abilityDisplayMoveListener_ = new AbilityDisplayMoveListener(weak_from_this());
557 window->RegisterDisplayMoveListener(abilityDisplayMoveListener_);
558 }
559 } else {
560 auto window = scene_->GetMainWindow();
561 if (window != nullptr && want.HasParameter(Want::PARAM_RESV_WINDOW_MODE)) {
562 auto windowMode = want.GetIntParam(Want::PARAM_RESV_WINDOW_MODE,
563 AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_UNDEFINED);
564 window->SetWindowMode(static_cast<Rosen::WindowMode>(windowMode));
565 HILOG_DEBUG("set window mode = %{public}d.", windowMode);
566 }
567 }
568
569 auto window = scene_->GetMainWindow();
570 if (window != nullptr && securityFlag_) {
571 window->SetSystemPrivacyMode(true);
572 }
573
574 HILOG_DEBUG("%{public}s begin scene_->GoForeground, sceneFlag_:%{public}d.", __func__, Ability::sceneFlag_);
575 scene_->GoForeground(Ability::sceneFlag_);
576 HILOG_DEBUG("%{public}s end scene_->GoForeground.", __func__);
577 }
578
RequestFocus(const Want & want)579 void JsAbility::RequestFocus(const Want &want)
580 {
581 HILOG_DEBUG("%{public}s called.", __func__);
582 if (scene_ == nullptr) {
583 return;
584 }
585 auto window = scene_->GetMainWindow();
586 if (window != nullptr && want.HasParameter(Want::PARAM_RESV_WINDOW_MODE)) {
587 auto windowMode = want.GetIntParam(Want::PARAM_RESV_WINDOW_MODE,
588 AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_UNDEFINED);
589 window->SetWindowMode(static_cast<Rosen::WindowMode>(windowMode));
590 HILOG_DEBUG("set window mode = %{public}d.", windowMode);
591 }
592 scene_->GoForeground(Ability::sceneFlag_);
593 }
594
ContinuationRestore(const Want & want)595 void JsAbility::ContinuationRestore(const Want &want)
596 {
597 HILOG_DEBUG("%{public}s called.", __func__);
598 if (!IsRestoredInContinuation() || scene_ == nullptr) {
599 return;
600 }
601 RestorePageStack(want);
602 OnSceneRestored();
603 NotifyContinuationResult(want, true);
604 }
605
GetJsWindowStage()606 std::shared_ptr<NativeReference> JsAbility::GetJsWindowStage()
607 {
608 HILOG_DEBUG("%{public}s called.", __func__);
609 if (jsWindowStageObj_ == nullptr) {
610 HILOG_ERROR("jsWindowSatge is nullptr");
611 }
612 return jsWindowStageObj_;
613 }
614 #endif
615
OnContinue(WantParams & wantParams)616 int32_t JsAbility::OnContinue(WantParams &wantParams)
617 {
618 HandleScope handleScope(jsRuntime_);
619 auto &nativeEngine = jsRuntime_.GetNativeEngine();
620 if (jsAbilityObj_ == nullptr) {
621 HILOG_ERROR("Failed to get AbilityStage object");
622 return AppExecFwk::ContinuationManager::OnContinueResult::Reject;
623 }
624 NativeValue *value = jsAbilityObj_->Get();
625 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
626 if (obj == nullptr) {
627 HILOG_ERROR("Failed to get Ability object");
628 return AppExecFwk::ContinuationManager::OnContinueResult::Reject;
629 }
630
631 NativeValue *methodOnCreate = obj->GetProperty("onContinue");
632 if (methodOnCreate == nullptr) {
633 HILOG_ERROR("Failed to get 'onContinue' from Ability object");
634 return AppExecFwk::ContinuationManager::OnContinueResult::Reject;
635 }
636
637 napi_value napiWantParams = OHOS::AppExecFwk::WrapWantParams(reinterpret_cast<napi_env>(&nativeEngine), wantParams);
638 NativeValue *jsWantParams = reinterpret_cast<NativeValue *>(napiWantParams);
639
640 NativeValue *result = nativeEngine.CallFunction(value, methodOnCreate, &jsWantParams, 1);
641
642 napi_value new_napiWantParams = reinterpret_cast<napi_value>(jsWantParams);
643 OHOS::AppExecFwk::UnwrapWantParams(reinterpret_cast<napi_env>(&nativeEngine), new_napiWantParams, wantParams);
644
645 NativeNumber *numberResult = ConvertNativeValueTo<NativeNumber>(result);
646 if (numberResult == nullptr) {
647 HILOG_ERROR("'onContinue' is not implemented");
648 return AppExecFwk::ContinuationManager::OnContinueResult::Reject;
649 }
650
651 auto applicationContext = AbilityRuntime::Context::GetApplicationContext();
652 if (applicationContext != nullptr) {
653 applicationContext->DispatchOnAbilityContinue(jsAbilityObj_);
654 }
655
656 return *numberResult;
657 }
658
OnSaveState(int32_t reason,WantParams & wantParams)659 int32_t JsAbility::OnSaveState(int32_t reason, WantParams &wantParams)
660 {
661 HandleScope handleScope(jsRuntime_);
662 auto &nativeEngine = jsRuntime_.GetNativeEngine();
663 if (jsAbilityObj_ == nullptr) {
664 HILOG_ERROR("AppRecoveryFailed to get AbilityStage object");
665 return -1;
666 }
667 NativeValue *value = jsAbilityObj_->Get();
668 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
669 if (obj == nullptr) {
670 HILOG_ERROR("AppRecovery Failed to get Ability object");
671 return -1;
672 }
673
674 NativeValue *methodOnSaveState = obj->GetProperty("onSaveState");
675 if (methodOnSaveState == nullptr) {
676 HILOG_ERROR("AppRecovery Failed to get 'onSaveState' from Ability object");
677 return -1;
678 }
679
680 napi_value napiWantParams = OHOS::AppExecFwk::WrapWantParams(reinterpret_cast<napi_env>(&nativeEngine), wantParams);
681 NativeValue* jsReason = CreateJsValue(nativeEngine, reason);
682 NativeValue* jsWantParams = reinterpret_cast<NativeValue *>(napiWantParams);
683 NativeValue* args[] = { jsReason, jsWantParams };
684 NativeValue* result = nativeEngine.CallFunction(value, methodOnSaveState, args, 2); // 2:args size
685 napi_value newNapiWantParams = reinterpret_cast<napi_value>(jsWantParams);
686 OHOS::AppExecFwk::UnwrapWantParams(reinterpret_cast<napi_env>(&nativeEngine), newNapiWantParams, wantParams);
687
688 NativeNumber *numberResult = ConvertNativeValueTo<NativeNumber>(result);
689 if (numberResult == nullptr) {
690 HILOG_ERROR("AppRecovery no result return from onSaveState");
691 return -1;
692 }
693 return *numberResult;
694 }
695
OnConfigurationUpdated(const Configuration & configuration)696 void JsAbility::OnConfigurationUpdated(const Configuration &configuration)
697 {
698 Ability::OnConfigurationUpdated(configuration);
699 HILOG_DEBUG("%{public}s called.", __func__);
700
701 HandleScope handleScope(jsRuntime_);
702 auto& nativeEngine = jsRuntime_.GetNativeEngine();
703 auto fullConfig = GetAbilityContext()->GetConfiguration();
704 if (!fullConfig) {
705 HILOG_ERROR("configuration is nullptr.");
706 return;
707 }
708
709 napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(
710 reinterpret_cast<napi_env>(&nativeEngine), configuration);
711 NativeValue* jsConfiguration = reinterpret_cast<NativeValue*>(napiConfiguration);
712 CallObjectMethod("onConfigurationUpdated", &jsConfiguration, 1);
713 CallObjectMethod("onConfigurationUpdate", &jsConfiguration, 1);
714 JsAbilityContext::ConfigurationUpdated(&nativeEngine, shellContextRef_, fullConfig);
715 }
716
OnMemoryLevel(int level)717 void JsAbility::OnMemoryLevel(int level)
718 {
719 Ability::OnMemoryLevel(level);
720 HILOG_DEBUG("%{public}s called.", __func__);
721
722 HandleScope handleScope(jsRuntime_);
723 auto &nativeEngine = jsRuntime_.GetNativeEngine();
724 if (jsAbilityObj_ == nullptr) {
725 HILOG_ERROR("Failed to get AbilityStage object");
726 return;
727 }
728 NativeValue *value = jsAbilityObj_->Get();
729 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
730 if (obj == nullptr) {
731 HILOG_ERROR("Failed to get Ability object");
732 return;
733 }
734
735 NativeValue *jslevel = CreateJsValue(nativeEngine, level);
736 NativeValue *argv[] = {
737 jslevel,
738 };
739 CallObjectMethod("onMemoryLevel", argv, ArraySize(argv));
740 }
741
UpdateContextConfiguration()742 void JsAbility::UpdateContextConfiguration()
743 {
744 HILOG_DEBUG("%{public}s called.", __func__);
745 HandleScope handleScope(jsRuntime_);
746 auto& nativeEngine = jsRuntime_.GetNativeEngine();
747 JsAbilityContext::ConfigurationUpdated(&nativeEngine, shellContextRef_, GetAbilityContext()->GetConfiguration());
748 }
749
OnNewWant(const Want & want)750 void JsAbility::OnNewWant(const Want &want)
751 {
752 HILOG_DEBUG("%{public}s begin.", __func__);
753 Ability::OnNewWant(want);
754
755 #ifdef SUPPORT_GRAPHICS
756 if (scene_) {
757 scene_->OnNewWant(want);
758 }
759 #endif
760
761 HandleScope handleScope(jsRuntime_);
762 auto &nativeEngine = jsRuntime_.GetNativeEngine();
763 if (jsAbilityObj_ == nullptr) {
764 HILOG_ERROR("Failed to get AbilityStage object");
765 return;
766 }
767 NativeValue *value = jsAbilityObj_->Get();
768 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
769 if (obj == nullptr) {
770 HILOG_ERROR("Failed to get Ability object");
771 return;
772 }
773
774 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(&nativeEngine), want);
775 NativeValue *jsWant = reinterpret_cast<NativeValue *>(napiWant);
776
777 obj->SetProperty("lastRequestWant", jsWant);
778
779 NativeValue *argv[] = {
780 jsWant,
781 CreateJsLaunchParam(nativeEngine, GetLaunchParam()),
782 };
783 CallObjectMethod("onNewWant", argv, ArraySize(argv));
784
785 HILOG_DEBUG("%{public}s end.", __func__);
786 }
787
OnAbilityResult(int requestCode,int resultCode,const Want & resultData)788 void JsAbility::OnAbilityResult(int requestCode, int resultCode, const Want &resultData)
789 {
790 HILOG_DEBUG("%{public}s begin.", __func__);
791 Ability::OnAbilityResult(requestCode, resultCode, resultData);
792 std::shared_ptr<AbilityRuntime::AbilityContext> context = GetAbilityContext();
793 if (context == nullptr) {
794 HILOG_WARN("JsAbility not attached to any runtime context!");
795 return;
796 }
797 context->OnAbilityResult(requestCode, resultCode, resultData);
798 HILOG_DEBUG("%{public}s end.", __func__);
799 }
800
CallRequest()801 sptr<IRemoteObject> JsAbility::CallRequest()
802 {
803 HILOG_DEBUG("JsAbility::CallRequest begin.");
804 if (jsAbilityObj_ == nullptr) {
805 HILOG_WARN("JsAbility::CallRequest Obj is nullptr");
806 return nullptr;
807 }
808
809 if (remoteCallee_ != nullptr) {
810 HILOG_DEBUG("JsAbility::CallRequest get Callee remoteObj.");
811 return remoteCallee_;
812 }
813
814 HandleScope handleScope(jsRuntime_);
815 HILOG_DEBUG("JsAbility::CallRequest set runtime scope.");
816 auto &nativeEngine = jsRuntime_.GetNativeEngine();
817 auto value = jsAbilityObj_->Get();
818 if (value == nullptr) {
819 HILOG_ERROR("JsAbility::CallRequest value is nullptr");
820 return nullptr;
821 }
822
823 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
824 if (obj == nullptr) {
825 HILOG_ERROR("JsAbility::CallRequest obj is nullptr");
826 return nullptr;
827 }
828
829 auto method = obj->GetProperty("onCallRequest");
830 if (method == nullptr || !method->IsCallable()) {
831 HILOG_ERROR("JsAbility::CallRequest method is %{public}s", method == nullptr ? "nullptr" : "not func");
832 return nullptr;
833 }
834
835 auto remoteJsObj = nativeEngine.CallFunction(value, method, nullptr, 0);
836 if (remoteJsObj == nullptr) {
837 HILOG_ERROR("JsAbility::CallRequest JsObj is nullptr");
838 return nullptr;
839 }
840
841 remoteCallee_ = SetNewRuleFlagToCallee(nativeEngine, remoteJsObj);
842 HILOG_DEBUG("JsAbility::CallRequest end.");
843 return remoteCallee_;
844 }
845
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc,bool withResult)846 NativeValue *JsAbility::CallObjectMethod(const char *name, NativeValue *const *argv, size_t argc, bool withResult)
847 {
848 HILOG_DEBUG("JsAbility::CallObjectMethod(%{public}s", name);
849
850 if (!jsAbilityObj_) {
851 HILOG_WARN("Not found Ability.js");
852 return nullptr;
853 }
854
855 HandleEscape handleEscape(jsRuntime_);
856 auto &nativeEngine = jsRuntime_.GetNativeEngine();
857
858 NativeValue *value = jsAbilityObj_->Get();
859 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
860 if (obj == nullptr) {
861 HILOG_ERROR("Failed to get Ability object");
862 return nullptr;
863 }
864
865 NativeValue *methodOnCreate = obj->GetProperty(name);
866 if (methodOnCreate == nullptr) {
867 HILOG_ERROR("Failed to get '%{public}s' from Ability object", name);
868 return nullptr;
869 }
870 if (withResult) {
871 return handleEscape.Escape(nativeEngine.CallFunction(value, methodOnCreate, argv, argc));
872 }
873 nativeEngine.CallFunction(value, methodOnCreate, argv, argc);
874 return nullptr;
875 }
876
CheckPromise(NativeValue * result)877 bool JsAbility::CheckPromise(NativeValue *result)
878 {
879 if (result == nullptr) {
880 HILOG_DEBUG("result is null, no need to call promise.");
881 return false;
882 }
883 if (!result->IsPromise()) {
884 HILOG_DEBUG("result is not promise, no need to call promise.");
885 return false;
886 }
887 return true;
888 }
889
CallPromise(NativeValue * result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)890 bool JsAbility::CallPromise(NativeValue *result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
891 {
892 auto *retObj = ConvertNativeValueTo<NativeObject>(result);
893 if (retObj == nullptr) {
894 HILOG_ERROR("Failed to convert native value to NativeObject.");
895 return false;
896 }
897 NativeValue *then = retObj->GetProperty("then");
898 if (then == nullptr) {
899 HILOG_ERROR("Failed to get property: then.");
900 return false;
901 }
902 if (!then->IsCallable()) {
903 HILOG_ERROR("property then is not callable.");
904 return false;
905 }
906 HandleScope handleScope(jsRuntime_);
907 auto &nativeEngine = jsRuntime_.GetNativeEngine();
908 auto promiseCallback = nativeEngine.CreateFunction("promiseCallback", strlen("promiseCallback"), PromiseCallback,
909 callbackInfo);
910 NativeValue *argv[1] = { promiseCallback };
911 nativeEngine.CallFunction(result, then, argv, 1);
912 return true;
913 }
914
CreateADelegatorAbilityProperty()915 std::shared_ptr<AppExecFwk::ADelegatorAbilityProperty> JsAbility::CreateADelegatorAbilityProperty()
916 {
917 auto property = std::make_shared<AppExecFwk::ADelegatorAbilityProperty>();
918 property->token_ = GetAbilityContext()->GetToken();
919 property->name_ = GetAbilityName();
920 if (GetApplicationInfo() == nullptr || GetApplicationInfo()->bundleName.empty()) {
921 property->fullName_ = GetAbilityName();
922 } else {
923 std::string::size_type pos = GetAbilityName().find(GetApplicationInfo()->bundleName);
924 if (pos == std::string::npos || pos != 0) {
925 property->fullName_ = GetApplicationInfo()->bundleName + "." + GetAbilityName();
926 } else {
927 property->fullName_ = GetAbilityName();
928 }
929 }
930 property->lifecycleState_ = GetState();
931 property->object_ = jsAbilityObj_;
932
933 return property;
934 }
935
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)936 void JsAbility::Dump(const std::vector<std::string> ¶ms, std::vector<std::string> &info)
937 {
938 Ability::Dump(params, info);
939 HILOG_DEBUG("%{public}s called.", __func__);
940 HandleScope handleScope(jsRuntime_);
941 auto& nativeEngine = jsRuntime_.GetNativeEngine();
942 // create js array object of params
943 NativeValue* argv[] = { CreateNativeArray(nativeEngine, params) };
944
945 if (!jsAbilityObj_) {
946 HILOG_WARN("Not found .js");
947 return;
948 }
949
950 NativeValue* value = jsAbilityObj_->Get();
951 NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
952 if (obj == nullptr) {
953 HILOG_ERROR("Failed to get object");
954 return;
955 }
956
957 NativeValue* method = obj->GetProperty("dump");
958 NativeValue* onDumpMethod = obj->GetProperty("onDump");
959
960 NativeValue* dumpInfo = nullptr;
961 if (method != nullptr) {
962 dumpInfo = nativeEngine.CallFunction(value, method, argv, 1);
963 }
964
965 NativeValue* onDumpInfo = nullptr;
966 if (onDumpMethod != nullptr) {
967 onDumpInfo = nativeEngine.CallFunction(value, onDumpMethod, argv, 1);
968 }
969
970 NativeArray* dumpInfoNative = nullptr;
971 if (dumpInfo != nullptr) {
972 dumpInfoNative = ConvertNativeValueTo<NativeArray>(dumpInfo);
973 }
974
975 NativeArray* onDumpInfoNative = nullptr;
976 if (onDumpInfo != nullptr) {
977 onDumpInfoNative = ConvertNativeValueTo<NativeArray>(onDumpInfo);
978 }
979
980 if (dumpInfoNative != nullptr) {
981 for (uint32_t i = 0; i < dumpInfoNative->GetLength(); i++) {
982 std::string dumpInfoStr;
983 if (!ConvertFromJsValue(nativeEngine, dumpInfoNative->GetElement(i), dumpInfoStr)) {
984 HILOG_ERROR("Parse dumpInfoStr failed");
985 return;
986 }
987 info.push_back(dumpInfoStr);
988 }
989 }
990
991 if (onDumpInfoNative != nullptr) {
992 for (uint32_t i = 0; i < onDumpInfoNative->GetLength(); i++) {
993 std::string dumpInfoStr;
994 if (!ConvertFromJsValue(nativeEngine, onDumpInfoNative->GetElement(i), dumpInfoStr)) {
995 HILOG_ERROR("Parse dumpInfoStr from onDumpInfoNative failed");
996 return;
997 }
998 info.push_back(dumpInfoStr);
999 }
1000 }
1001
1002 HILOG_DEBUG("Dump info size: %{public}zu", info.size());
1003 }
1004
GetJsAbility()1005 std::shared_ptr<NativeReference> JsAbility::GetJsAbility()
1006 {
1007 HILOG_DEBUG("%{public}s called.", __func__);
1008 if (jsAbilityObj_ == nullptr) {
1009 HILOG_ERROR("jsAbility object is nullptr");
1010 }
1011 return jsAbilityObj_;
1012 }
1013
SetNewRuleFlagToCallee(NativeEngine & nativeEngine,NativeValue * remoteJsObj)1014 sptr<IRemoteObject> JsAbility::SetNewRuleFlagToCallee(NativeEngine &nativeEngine, NativeValue* remoteJsObj)
1015 {
1016 NativeObject* calleeObj = ConvertNativeValueTo<NativeObject>(remoteJsObj);
1017 if (calleeObj == nullptr) {
1018 HILOG_ERROR("JsAbility::SetNewRuleFlagToCallee calleeObj is nullptr");
1019 return nullptr;
1020 }
1021 auto setFlagMethod = calleeObj->GetProperty("setNewRuleFlag");
1022 if (setFlagMethod == nullptr || !setFlagMethod->IsCallable()) {
1023 HILOG_ERROR("JsAbility::SetNewRuleFlagToCallee setFlagMethod is %{public}s",
1024 setFlagMethod == nullptr ? "nullptr" : "not func");
1025 return nullptr;
1026 }
1027 auto flag = nativeEngine.CreateBoolean(IsUseNewStartUpRule());
1028 NativeValue *argv[1] = { flag };
1029 nativeEngine.CallFunction(remoteJsObj, setFlagMethod, argv, 1);
1030
1031 auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(
1032 reinterpret_cast<napi_env>(&nativeEngine), reinterpret_cast<napi_value>(remoteJsObj));
1033 if (remoteObj == nullptr) {
1034 HILOG_ERROR("JsAbility::CallRequest obj is nullptr");
1035 return nullptr;
1036 }
1037 return remoteObj;
1038 }
1039 } // namespace AbilityRuntime
1040 } // namespace OHOS
1041