1 /*
2 * Copyright (c) 2023-2024 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 "js_ui_extension_base.h"
17
18 #include <type_traits>
19 #include <vector>
20
21 #include "ability_info.h"
22 #include "ability_manager_client.h"
23 #include "array_wrapper.h"
24 #include "configuration_utils.h"
25 #include "connection_manager.h"
26 #include "context.h"
27 #include "hilog_tag_wrapper.h"
28 #include "hilog_wrapper.h"
29 #include "hitrace_meter.h"
30 #include "insight_intent_executor_mgr.h"
31 #include "int_wrapper.h"
32 #include "js_data_struct_converter.h"
33 #include "js_extension_common.h"
34 #include "js_extension_context.h"
35 #include "js_runtime.h"
36 #include "js_runtime_utils.h"
37 #include "js_ui_extension_content_session.h"
38 #include "js_ui_extension_context.h"
39 #include "napi/native_api.h"
40 #include "napi/native_node_api.h"
41 #include "napi_common_configuration.h"
42 #include "napi_common_util.h"
43 #include "napi_common_want.h"
44 #include "napi_remote_object.h"
45 #include "string_wrapper.h"
46 #include "ui_extension_window_command.h"
47 #include "want_params_wrapper.h"
48 #include "application_configuration_manager.h"
49 #include "ohos_application.h"
50
51 namespace OHOS {
52 namespace AbilityRuntime {
53 namespace {
54 constexpr size_t ARGC_ONE = 1;
55 constexpr size_t ARGC_TWO = 2;
56 } // namespace
AttachUIExtensionBaseContext(napi_env env,void * value,void *)57 napi_value AttachUIExtensionBaseContext(napi_env env, void *value, void*)
58 {
59 TAG_LOGD(AAFwkTag::UI_EXT, "called");
60 if (value == nullptr) {
61 TAG_LOGE(AAFwkTag::UI_EXT, "null value");
62 return nullptr;
63 }
64
65 auto ptr = reinterpret_cast<std::weak_ptr<UIExtensionContext>*>(value)->lock();
66 if (ptr == nullptr) {
67 TAG_LOGE(AAFwkTag::UI_EXT, "null ptr");
68 return nullptr;
69 }
70 napi_value object = JsUIExtensionContext::CreateJsUIExtensionContext(env, ptr);
71 if (object == nullptr) {
72 TAG_LOGE(AAFwkTag::UI_EXT, "null object");
73 return nullptr;
74 }
75 auto contextRef = JsRuntime::LoadSystemModuleByEngine(
76 env, "application.UIExtensionContext", &object, 1);
77 if (contextRef == nullptr) {
78 TAG_LOGD(AAFwkTag::UI_EXT, "get LoadSystemModuleByEngine failed");
79 return nullptr;
80 }
81 auto contextObj = contextRef->GetNapiValue();
82 if (contextObj == nullptr) {
83 TAG_LOGE(AAFwkTag::UI_EXT, "null contextObj");
84 return nullptr;
85 }
86 if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
87 TAG_LOGE(AAFwkTag::UI_EXT, "not object");
88 return nullptr;
89 }
90 napi_coerce_to_native_binding_object(
91 env, contextObj, DetachCallbackFunc, AttachUIExtensionBaseContext, value, nullptr);
92 auto workContext = new (std::nothrow) std::weak_ptr<UIExtensionContext>(ptr);
93 napi_status status = napi_wrap(env, contextObj, workContext,
94 [](napi_env, void *data, void*) {
95 TAG_LOGD(AAFwkTag::UI_EXT, "Finalizer for weak_ptr ui extension context is called");
96 if (data == nullptr) {
97 TAG_LOGE(AAFwkTag::UI_EXT, "null data");
98 return;
99 }
100 delete static_cast<std::weak_ptr<UIExtensionContext>*>(data);
101 },
102 nullptr, nullptr);
103 if (status != napi_ok && workContext != nullptr) {
104 TAG_LOGE(AAFwkTag::UI_EXT, "napi_wrap Failed: %{public}d", status);
105 delete workContext;
106 return nullptr;
107 }
108
109 return contextObj;
110 }
111
JsUIExtensionBase(const std::unique_ptr<Runtime> & runtime)112 JsUIExtensionBase::JsUIExtensionBase(const std::unique_ptr<Runtime> &runtime)
113 : jsRuntime_(static_cast<JsRuntime&>(*runtime))
114 {
115 abilityResultListeners_ = std::make_shared<AbilityResultListeners>();
116 }
117
~JsUIExtensionBase()118 JsUIExtensionBase::~JsUIExtensionBase()
119 {
120 TAG_LOGD(AAFwkTag::UI_EXT, "destructor");
121 jsRuntime_.FreeNativeReference(std::move(jsObj_));
122 jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
123 for (auto &item : contentSessions_) {
124 jsRuntime_.FreeNativeReference(std::move(item.second));
125 }
126 contentSessions_.clear();
127 }
128
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)129 std::shared_ptr<ExtensionCommon> JsUIExtensionBase::Init(const std::shared_ptr<AbilityLocalRecord> &record,
130 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
131 const sptr<IRemoteObject> &token)
132 {
133 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
134 TAG_LOGD(AAFwkTag::UI_EXT, "called");
135 if (abilityInfo_ == nullptr) {
136 TAG_LOGE(AAFwkTag::UI_EXT, "null abilityInfo");
137 return nullptr;
138 }
139 if (abilityInfo_->srcEntrance.empty()) {
140 TAG_LOGE(AAFwkTag::UI_EXT, "empty abilityInfo srcEntrance");
141 return nullptr;
142 }
143
144 RegisterAbilityConfigUpdateCallback();
145
146 if (record != nullptr) {
147 token_ = record->GetToken();
148 }
149 std::string srcPath(abilityInfo_->moduleName + "/");
150 srcPath.append(abilityInfo_->srcEntrance);
151 srcPath.erase(srcPath.rfind('.'));
152 srcPath.append(".abc");
153
154 std::string moduleName(abilityInfo_->moduleName);
155 moduleName.append("::").append(abilityInfo_->name);
156 HandleScope handleScope(jsRuntime_);
157
158 jsObj_ = jsRuntime_.LoadModule(
159 moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE, false,
160 abilityInfo_->srcEntrance);
161 if (jsObj_ == nullptr) {
162 TAG_LOGE(AAFwkTag::UI_EXT, "null jsObj_");
163 return nullptr;
164 }
165
166 BindContext();
167 handler_ = handler;
168 RegisterDisplayInfoChangedListener();
169 return JsExtensionCommon::Create(jsRuntime_, static_cast<NativeReference&>(*jsObj_), shellContextRef_);
170 }
171
RegisterAbilityConfigUpdateCallback()172 void JsUIExtensionBase::RegisterAbilityConfigUpdateCallback()
173 {
174 auto uiExtensionAbility = std::static_pointer_cast<JsUIExtensionBase>(shared_from_this());
175 std::weak_ptr<JsUIExtensionBase> abilityWptr = uiExtensionAbility;
176 context_->RegisterAbilityConfigUpdateCallback(
177 [abilityWptr, abilityContext = context_](AppExecFwk::Configuration &config) {
178 std::shared_ptr<JsUIExtensionBase> abilitySptr = abilityWptr.lock();
179 if (abilitySptr == nullptr) {
180 TAG_LOGE(AAFwkTag::UIABILITY, "null abilitySptr");
181 return;
182 }
183 if (abilityContext == nullptr || abilityContext->GetAbilityInfo() == nullptr) {
184 TAG_LOGE(AAFwkTag::UIABILITY, "null abilityContext or null GetAbilityInfo");
185 return;
186 }
187 if (abilityContext->GetAbilityConfiguration() == nullptr) {
188 auto abilityModuleContext = abilityContext->CreateModuleContext(
189 abilityContext->GetAbilityInfo()->moduleName);
190 if (abilityModuleContext == nullptr) {
191 TAG_LOGE(AAFwkTag::UIABILITY, "null abilityModuleContext");
192 return;
193 }
194 auto abilityResourceMgr = abilityModuleContext->GetResourceManager();
195 abilityContext->SetAbilityResourceManager(abilityResourceMgr);
196 AbilityRuntime::ApplicationConfigurationManager::GetInstance().
197 AddIgnoreContext(abilityContext, abilityResourceMgr);
198 TAG_LOGD(AAFwkTag::UIABILITY, "%{public}zu",
199 AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetIgnoreContext().size());
200 }
201 abilityContext->SetAbilityConfiguration(config);
202 if (config.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE).
203 compare(AppExecFwk::ConfigurationInner::COLOR_MODE_AUTO) == 0) {
204 config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE,
205 ApplicationConfigurationManager::GetInstance().GetColorMode());
206
207 if (AbilityRuntime::ApplicationConfigurationManager::GetInstance().
208 GetColorModeSetLevel() > AbilityRuntime::SetLevel::System) {
209 config.AddItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP,
210 AppExecFwk::ConfigurationInner::IS_SET_BY_APP);
211 }
212 abilityContext->GetAbilityConfiguration()->
213 RemoveItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
214 abilityContext->GetAbilityConfiguration()->
215 RemoveItem(AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP);
216 }
217
218 abilitySptr->OnAbilityConfigurationUpdated(config);
219 });
220 }
221
BindContext()222 void JsUIExtensionBase::BindContext()
223 {
224 HandleScope handleScope(jsRuntime_);
225 if (jsObj_ == nullptr) {
226 TAG_LOGE(AAFwkTag::UI_EXT, "null jsObj_");
227 return;
228 }
229 napi_env env = jsRuntime_.GetNapiEnv();
230 napi_value obj = jsObj_->GetNapiValue();
231 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
232 TAG_LOGE(AAFwkTag::UI_EXT, "not object");
233 return;
234 }
235 if (context_ == nullptr) {
236 TAG_LOGE(AAFwkTag::UI_EXT, "null context_");
237 return;
238 }
239 TAG_LOGD(AAFwkTag::UI_EXT, "BindContext CreateJsUIExtensionContext");
240 napi_value contextObj = JsUIExtensionContext::CreateJsUIExtensionContext(env, context_);
241 if (contextObj == nullptr) {
242 TAG_LOGE(AAFwkTag::UI_EXT, "null contextObj");
243 return;
244 }
245 shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(
246 env, "application.UIExtensionContext", &contextObj, ARGC_ONE);
247 if (shellContextRef_ == nullptr) {
248 TAG_LOGD(AAFwkTag::UI_EXT, "get LoadSystemModuleByEngine failed");
249 return;
250 }
251 contextObj = shellContextRef_->GetNapiValue();
252 if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
253 TAG_LOGE(AAFwkTag::UI_EXT, "get object failed");
254 return;
255 }
256 auto workContext = new (std::nothrow) std::weak_ptr<UIExtensionContext>(context_);
257 napi_coerce_to_native_binding_object(
258 env, contextObj, DetachCallbackFunc, AttachUIExtensionBaseContext, workContext, nullptr);
259 context_->Bind(jsRuntime_, shellContextRef_.get());
260 napi_set_named_property(env, obj, "context", contextObj);
261 napi_status status = napi_wrap(env, contextObj, workContext,
262 [](napi_env, void *data, void*) {
263 TAG_LOGD(AAFwkTag::UI_EXT, "Finalizer for weak_ptr ui extension context is called");
264 if (data == nullptr) {
265 TAG_LOGE(AAFwkTag::UI_EXT, "null data");
266 return;
267 }
268 delete static_cast<std::weak_ptr<UIExtensionContext>*>(data);
269 },
270 nullptr, nullptr);
271 if (status != napi_ok && workContext != nullptr) {
272 TAG_LOGE(AAFwkTag::UI_EXT, "napi_wrap Failed: %{public}d", status);
273 delete workContext;
274 return;
275 }
276 }
277
OnStart(const AAFwk::Want & want,AAFwk::LaunchParam & launchParam,sptr<AAFwk::SessionInfo> sessionInfo)278 void JsUIExtensionBase::OnStart(
279 const AAFwk::Want &want, AAFwk::LaunchParam &launchParam, sptr<AAFwk::SessionInfo> sessionInfo)
280 {
281 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
282 TAG_LOGD(AAFwkTag::UI_EXT, "called");
283 #ifdef SUPPORT_GRAPHICS
284 if (context_ != nullptr && sessionInfo != nullptr) {
285 auto configUtils = std::make_shared<ConfigurationUtils>();
286 configUtils->InitDisplayConfig(context_->GetConfiguration(), context_->GetResourceManager(),
287 sessionInfo->displayId, sessionInfo->density, sessionInfo->orientation);
288 }
289 #endif // SUPPORT_GRAPHICS
290
291 HandleScope handleScope(jsRuntime_);
292 napi_env env = jsRuntime_.GetNapiEnv();
293
294 if (context_ != nullptr) {
295 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context_->GetConfiguration());
296 }
297 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
298 if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) {
299 launchParam.launchReason = AAFwk::LaunchReason::LAUNCHREASON_INSIGHT_INTENT;
300 }
301 napi_value argv[] = {
302 CreateJsLaunchParam(env, launchParam),
303 napiWant
304 };
305 CallObjectMethod("onCreate", argv, ARGC_TWO);
306 }
307
OnStop()308 void JsUIExtensionBase::OnStop()
309 {
310 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
311 TAG_LOGD(AAFwkTag::UI_EXT, "called");
312 HandleScope handleScope(jsRuntime_);
313 CallObjectMethod("onDestroy");
314 ApplicationConfigurationManager::GetInstance().DeleteIgnoreContext(context_);
315 TAG_LOGI(AAFwkTag::UIABILITY, "GetIgnoreContext size %{public}zu",
316 AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetIgnoreContext().size());
317 #ifdef SUPPORT_GRAPHICS
318 UnregisterDisplayInfoChangedListener();
319 #endif // SUPPORT_GRAPHICS
320 OnStopCallBack();
321 TAG_LOGD(AAFwkTag::UI_EXT, "end");
322 }
323
OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)324 void JsUIExtensionBase::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
325 {
326 if (callbackInfo == nullptr) {
327 isAsyncCallback = false;
328 OnStop();
329 return;
330 }
331 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
332 TAG_LOGD(AAFwkTag::UI_EXT, "begin");
333 HandleScope handleScope(jsRuntime_);
334 napi_value result = CallObjectMethod("onDestroy", nullptr, 0, true);
335 if (!CheckPromise(result)) {
336 OnStopCallBack();
337 isAsyncCallback = false;
338 return;
339 }
340
341 auto asyncCallback = [extensionWeakPtr = weak_from_this()]() {
342 auto jsUIExtensionBase = extensionWeakPtr.lock();
343 if (jsUIExtensionBase == nullptr) {
344 TAG_LOGE(AAFwkTag::UI_EXT, "null extension");
345 return;
346 }
347 jsUIExtensionBase->OnStopCallBack();
348 };
349 callbackInfo->Push(asyncCallback);
350 isAsyncCallback = CallPromise(result, callbackInfo);
351 if (!isAsyncCallback) {
352 TAG_LOGE(AAFwkTag::UI_EXT, "call promise failed");
353 OnStopCallBack();
354 }
355 TAG_LOGD(AAFwkTag::UI_EXT, "end");
356 }
357
OnStopCallBack()358 void JsUIExtensionBase::OnStopCallBack()
359 {
360 if (context_ == nullptr) {
361 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
362 return;
363 }
364 auto ret = ConnectionManager::GetInstance().DisconnectCaller(context_->GetToken());
365 if (ret) {
366 ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
367 TAG_LOGD(AAFwkTag::UI_EXT, "service connection not disconnected");
368 }
369
370 auto applicationContext = Context::GetApplicationContext();
371 if (applicationContext != nullptr) {
372 applicationContext->DispatchOnAbilityDestroy(jsObj_);
373 }
374 }
375
CheckPromise(napi_value result)376 bool JsUIExtensionBase::CheckPromise(napi_value result)
377 {
378 if (result == nullptr) {
379 TAG_LOGD(AAFwkTag::UI_EXT, "null result");
380 return false;
381 }
382 HandleScope handleScope(jsRuntime_);
383 napi_env env = jsRuntime_.GetNapiEnv();
384 bool isPromise = false;
385 napi_is_promise(env, result, &isPromise);
386 if (!isPromise) {
387 TAG_LOGD(AAFwkTag::UI_EXT, "result not promise");
388 return false;
389 }
390 return true;
391 }
392
393 namespace {
PromiseCallback(napi_env env,napi_callback_info info)394 napi_value PromiseCallback(napi_env env, napi_callback_info info)
395 {
396 void *data = nullptr;
397 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data), nullptr);
398 auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
399 if (callbackInfo == nullptr) {
400 TAG_LOGD(AAFwkTag::UI_EXT, "Invalid input");
401 return nullptr;
402 }
403 callbackInfo->Call();
404 AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
405 data = nullptr;
406 return nullptr;
407 }
408 }
409
CallPromise(napi_value result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)410 bool JsUIExtensionBase::CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
411 {
412 HandleScope handleScope(jsRuntime_);
413 napi_env env = jsRuntime_.GetNapiEnv();
414 if (!CheckTypeForNapiValue(env, result, napi_object)) {
415 TAG_LOGE(AAFwkTag::UI_EXT, "convert value failed");
416 return false;
417 }
418 napi_value then = nullptr;
419 napi_get_named_property(env, result, "then", &then);
420 if (then == nullptr) {
421 TAG_LOGE(AAFwkTag::UI_EXT, "null then");
422 return false;
423 }
424 bool isCallable = false;
425 napi_is_callable(env, then, &isCallable);
426 if (!isCallable) {
427 TAG_LOGE(AAFwkTag::UI_EXT, "not callable property then");
428 return false;
429 }
430 napi_value promiseCallback = nullptr;
431 napi_status createStatus = napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback,
432 callbackInfo, &promiseCallback);
433 if (createStatus != napi_ok) {
434 TAG_LOGE(AAFwkTag::UI_EXT, "failed, %{public}d", createStatus);
435 return false;
436 }
437 napi_value argv[1] = { promiseCallback };
438 napi_status callStatus = napi_call_function(env, result, then, 1, argv, nullptr);
439 if (callStatus != napi_ok) {
440 TAG_LOGE(AAFwkTag::UI_EXT, "failed, %{public}d", callStatus);
441 return false;
442 }
443 TAG_LOGD(AAFwkTag::UI_EXT, "exit");
444 return true;
445 }
446
OnCommandWindow(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,AAFwk::WindowCommand winCmd)447 void JsUIExtensionBase::OnCommandWindow(
448 const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo, AAFwk::WindowCommand winCmd)
449 {
450 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
451 TAG_LOGD(AAFwkTag::UI_EXT, "called");
452 if (sessionInfo == nullptr) {
453 TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo");
454 return;
455 }
456 if (InsightIntentExecuteParam::IsInsightIntentExecute(want) && winCmd == AAFwk::WIN_CMD_FOREGROUND) {
457 bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, false);
458 if (finish) {
459 return;
460 }
461 }
462 switch (winCmd) {
463 case AAFwk::WIN_CMD_FOREGROUND:
464 ForegroundWindow(want, sessionInfo);
465 break;
466 case AAFwk::WIN_CMD_BACKGROUND:
467 BackgroundWindow(sessionInfo);
468 break;
469 case AAFwk::WIN_CMD_DESTROY:
470 DestroyWindow(sessionInfo);
471 break;
472 default:
473 TAG_LOGD(AAFwkTag::UI_EXT, "unsupported cmd");
474 break;
475 }
476 OnCommandWindowDone(sessionInfo, winCmd);
477 }
478
ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,InsightIntentExecutorInfo & executorInfo)479 void JsUIExtensionBase::ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want,
480 const sptr<AAFwk::SessionInfo> &sessionInfo, InsightIntentExecutorInfo &executorInfo)
481 {
482 if (sessionInfo == nullptr) {
483 TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo");
484 return;
485 }
486 if (context_ == nullptr) {
487 TAG_LOGE(AAFwkTag::UI_EXT, "null context_");
488 return;
489 }
490 std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo = context_->GetAbilityInfo();
491 if (abilityInfo != nullptr) {
492 executorInfo.hapPath = abilityInfo->hapPath;
493 executorInfo.windowMode = abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE;
494 }
495 executorInfo.token = context_->GetToken();
496 executorInfo.pageLoader = contentSessions_[sessionInfo->uiExtensionComponentId];
497 executorInfo.executeParam = std::make_shared<InsightIntentExecuteParam>();
498 InsightIntentExecuteParam::GenerateFromWant(want, *executorInfo.executeParam);
499 executorInfo.executeParam->executeMode_ = UI_EXTENSION_ABILITY;
500 executorInfo.srcEntry = want.GetStringParam(INSIGHT_INTENT_SRC_ENTRY);
501 TAG_LOGD(AAFwkTag::UI_EXT, "executorInfo, insightIntentId: %{public}" PRIu64,
502 executorInfo.executeParam->insightIntentId_);
503 return;
504 }
505
ForegroundWindowWithInsightIntent(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,bool needForeground)506 bool JsUIExtensionBase::ForegroundWindowWithInsightIntent(const AAFwk::Want &want,
507 const sptr<AAFwk::SessionInfo> &sessionInfo, bool needForeground)
508 {
509 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
510 TAG_LOGD(AAFwkTag::UI_EXT, "called");
511 if (!HandleSessionCreate(want, sessionInfo)) {
512 TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed");
513 return false;
514 }
515
516 std::unique_ptr<InsightIntentExecutorAsyncCallback> executorCallback = nullptr;
517 executorCallback.reset(InsightIntentExecutorAsyncCallback::Create());
518 if (executorCallback == nullptr) {
519 TAG_LOGE(AAFwkTag::UI_EXT, "null executorCallback");
520 return false;
521 }
522 executorCallback->Push(
523 [weak = weak_from_this(), sessionInfo, needForeground, want](AppExecFwk::InsightIntentExecuteResult result) {
524 TAG_LOGD(AAFwkTag::UI_EXT, "Begin UI extension transaction callback");
525 auto extension = weak.lock();
526 if (extension == nullptr) {
527 TAG_LOGE(AAFwkTag::UI_EXT, "null extension");
528 return;
529 }
530 InsightIntentExecuteParam executeParam;
531 InsightIntentExecuteParam::GenerateFromWant(want, executeParam);
532 if (result.uris.size() > 0) {
533 extension->ExecuteInsightIntentDone(executeParam.insightIntentId_, result);
534 }
535 extension->PostInsightIntentExecuted(sessionInfo, result, needForeground);
536 });
537
538 InsightIntentExecutorInfo executorInfo;
539 ForegroundWindowInitInsightIntentExecutorInfo(want, sessionInfo, executorInfo);
540 int32_t ret = DelayedSingleton<InsightIntentExecutorMgr>::GetInstance()->ExecuteInsightIntent(
541 jsRuntime_, executorInfo, std::move(executorCallback));
542 if (!ret) {
543 TAG_LOGE(AAFwkTag::UI_EXT, "Execute insight intent failed");
544 // callback has removed, release in insight intent executor.
545 }
546 TAG_LOGD(AAFwkTag::UI_EXT, "end");
547 return true;
548 }
549
ExecuteInsightIntentDone(uint64_t intentId,const InsightIntentExecuteResult & result)550 void JsUIExtensionBase::ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result)
551 {
552 TAG_LOGD(AAFwkTag::UI_EXT, "intentId %{public}" PRIu64"", intentId);
553 auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token_, intentId, result);
554 if (ret != ERR_OK) {
555 TAG_LOGE(AAFwkTag::UI_EXT, "notify execute done failed");
556 }
557 }
558
PostInsightIntentExecuted(const sptr<AAFwk::SessionInfo> & sessionInfo,const AppExecFwk::InsightIntentExecuteResult & result,bool needForeground)559 void JsUIExtensionBase::PostInsightIntentExecuted(const sptr<AAFwk::SessionInfo> &sessionInfo,
560 const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground)
561 {
562 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
563 TAG_LOGD(AAFwkTag::UI_EXT, "Post insightintent executed");
564 if (needForeground) {
565 // If uiextensionability is started for the first time or need move background to foreground.
566 HandleScope handleScope(jsRuntime_);
567 CallObjectMethod("onForeground");
568 }
569
570 OnInsightIntentExecuteDone(sessionInfo, result);
571
572 if (needForeground) {
573 // If need foreground, that means triggered by onForeground.
574 TAG_LOGI(AAFwkTag::UI_EXT, "call abilityms");
575 AAFwk::PacMap restoreData;
576 AAFwk::AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, AAFwk::ABILITY_STATE_FOREGROUND_NEW,
577 restoreData);
578 } else {
579 // If uiextensionability has displayed in the foreground.
580 OnCommandWindowDone(sessionInfo, AAFwk::WIN_CMD_FOREGROUND);
581 }
582 }
583
OnCommandWindowDone(const sptr<AAFwk::SessionInfo> & sessionInfo,AAFwk::WindowCommand winCmd)584 void JsUIExtensionBase::OnCommandWindowDone(const sptr<AAFwk::SessionInfo> &sessionInfo, AAFwk::WindowCommand winCmd)
585 {
586 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
587 TAG_LOGD(AAFwkTag::UI_EXT, "called");
588 if (context_ == nullptr) {
589 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
590 return;
591 }
592 AAFwk::AbilityCommand abilityCmd;
593 if (uiWindowMap_.empty()) {
594 abilityCmd = AAFwk::ABILITY_CMD_DESTROY;
595 } else if (foregroundWindows_.empty()) {
596 abilityCmd = AAFwk::ABILITY_CMD_BACKGROUND;
597 } else {
598 abilityCmd = AAFwk::ABILITY_CMD_FOREGROUND;
599 }
600 AAFwk::AbilityManagerClient::GetInstance()->ScheduleCommandAbilityWindowDone(
601 context_->GetToken(), sessionInfo, winCmd, abilityCmd);
602 TAG_LOGD(AAFwkTag::UI_EXT, "end");
603 }
604
OnInsightIntentExecuteDone(const sptr<AAFwk::SessionInfo> & sessionInfo,const AppExecFwk::InsightIntentExecuteResult & result)605 void JsUIExtensionBase::OnInsightIntentExecuteDone(const sptr<AAFwk::SessionInfo> &sessionInfo,
606 const AppExecFwk::InsightIntentExecuteResult &result)
607 {
608 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
609 if (sessionInfo == nullptr) {
610 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
611 return;
612 }
613
614 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
615 auto componentId = sessionInfo->uiExtensionComponentId;
616 auto res = uiWindowMap_.find(componentId);
617 if (res != uiWindowMap_.end() && res->second != nullptr) {
618 WantParams params;
619 params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT_CODE, Integer::Box(result.innerErr));
620 WantParams resultParams;
621 resultParams.SetParam("code", Integer::Box(result.code));
622 if (result.result != nullptr) {
623 sptr<AAFwk::IWantParams> pWantParams = WantParamWrapper::Box(*result.result);
624 if (pWantParams != nullptr) {
625 resultParams.SetParam("result", pWantParams);
626 }
627 }
628 auto size = result.uris.size();
629 sptr<IArray> uriArray = new (std::nothrow) Array(size, g_IID_IString);
630 if (uriArray == nullptr) {
631 TAG_LOGE(AAFwkTag::UI_EXT, "new uriArray failed");
632 return;
633 }
634 for (std::size_t i = 0; i < size; i++) {
635 uriArray->Set(i, String::Box(result.uris[i]));
636 }
637 resultParams.SetParam("uris", uriArray);
638 resultParams.SetParam("flags", Integer::Box(result.flags));
639 sptr<AAFwk::IWantParams> pWantParams = WantParamWrapper::Box(resultParams);
640 if (pWantParams != nullptr) {
641 params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT, pWantParams);
642 }
643
644 Rosen::WMError ret = res->second->TransferExtensionData(params);
645 if (ret == Rosen::WMError::WM_OK) {
646 TAG_LOGD(AAFwkTag::UI_EXT, "TransferExtensionData success");
647 } else {
648 TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData failed, ret=%{public}d", ret);
649 }
650
651 res->second->Show();
652 foregroundWindows_.emplace(componentId);
653 }
654 TAG_LOGD(AAFwkTag::UI_EXT, "end");
655 }
656
OnCommand(const AAFwk::Want & want,bool restart,int32_t startId)657 void JsUIExtensionBase::OnCommand(const AAFwk::Want &want, bool restart, int32_t startId)
658 {
659 TAG_LOGD(AAFwkTag::UI_EXT, "called");
660 HandleScope handleScope(jsRuntime_);
661 napi_env env = jsRuntime_.GetNapiEnv();
662 if (env == nullptr) {
663 TAG_LOGE(AAFwkTag::UI_EXT, "null env");
664 return;
665 }
666 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
667 if (napiWant == nullptr) {
668 TAG_LOGE(AAFwkTag::UI_EXT, "null want");
669 return;
670 }
671 napi_value napiStartId = nullptr;
672 napi_create_int32(env, startId, &napiStartId);
673 if (napiStartId == nullptr) {
674 TAG_LOGE(AAFwkTag::UI_EXT, "null startId");
675 return;
676 }
677 napi_value argv[] = { napiWant, napiStartId };
678 CallObjectMethod("onRequest", argv, ARGC_TWO);
679 }
680
OnForeground(const Want & want,sptr<AAFwk::SessionInfo> sessionInfo)681 void JsUIExtensionBase::OnForeground(const Want &want, sptr<AAFwk::SessionInfo> sessionInfo)
682 {
683 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
684 TAG_LOGD(AAFwkTag::UI_EXT, "called");
685 if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) {
686 bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, true);
687 if (finish) {
688 return;
689 }
690 }
691
692 ForegroundWindow(want, sessionInfo);
693 HandleScope handleScope(jsRuntime_);
694 CallObjectMethod("onForeground");
695 }
696
OnBackground()697 void JsUIExtensionBase::OnBackground()
698 {
699 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
700 TAG_LOGD(AAFwkTag::UI_EXT, "called");
701 HandleScope handleScope(jsRuntime_);
702 CallObjectMethod("onBackground");
703 }
704
CallJsOnSessionCreate(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,const sptr<Rosen::Window> & uiWindow,const uint64_t & uiExtensionComponentId)705 bool JsUIExtensionBase::CallJsOnSessionCreate(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo,
706 const sptr<Rosen::Window> &uiWindow, const uint64_t &uiExtensionComponentId)
707 {
708 HandleScope handleScope(jsRuntime_);
709 napi_env env = jsRuntime_.GetNapiEnv();
710 if (env == nullptr) {
711 TAG_LOGE(AAFwkTag::UI_EXT, "null env");
712 return false;
713 }
714 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
715 if (napiWant == nullptr) {
716 TAG_LOGE(AAFwkTag::UI_EXT, "null want");
717 return false;
718 }
719 napi_value nativeContentSession = JsUIExtensionContentSession::CreateJsUIExtensionContentSession(
720 env, sessionInfo, uiWindow, context_, abilityResultListeners_);
721 if (nativeContentSession == nullptr) {
722 TAG_LOGE(AAFwkTag::UI_EXT, "null contentSession");
723 return false;
724 }
725 napi_ref ref = nullptr;
726 napi_create_reference(env, nativeContentSession, 1, &ref);
727 contentSessions_.emplace(
728 uiExtensionComponentId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
729 napi_value argv[] = { napiWant, nativeContentSession };
730 CallObjectMethod("onSessionCreate", argv, ARGC_TWO);
731 return true;
732 }
733
CreateWindowOption(const sptr<AAFwk::SessionInfo> & sessionInfo)734 sptr<Rosen::WindowOption> JsUIExtensionBase::CreateWindowOption(const sptr<AAFwk::SessionInfo> &sessionInfo)
735 {
736 auto option = sptr<Rosen::WindowOption>::MakeSptr();
737 if (option == nullptr) {
738 TAG_LOGE(AAFwkTag::UI_EXT, "make option failed");
739 return nullptr;
740 }
741
742 option->SetWindowName(context_->GetBundleName() + context_->GetAbilityInfo()->name);
743 option->SetWindowType(Rosen::WindowType::WINDOW_TYPE_UI_EXTENSION);
744 option->SetWindowSessionType(Rosen::WindowSessionType::EXTENSION_SESSION);
745 option->SetParentId(sessionInfo->hostWindowId);
746 option->SetRealParentId(sessionInfo->realHostWindowId);
747 option->SetParentWindowType(static_cast<Rosen::WindowType>(sessionInfo->parentWindowType));
748 option->SetUIExtensionUsage(static_cast<uint32_t>(sessionInfo->uiExtensionUsage));
749 option->SetDensity(sessionInfo->density);
750 option->SetIsDensityFollowHost(sessionInfo->isDensityFollowHost);
751 if (context_->isNotAllow != -1) {
752 bool isNotAllow = context_->isNotAllow == 1 ? true : false;
753 TAG_LOGD(AAFwkTag::UI_EXT, "isNotAllow: %{public}d", isNotAllow);
754 option->SetConstrainedModal(isNotAllow);
755 }
756 return option;
757 }
758
HandleSessionCreate(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo)759 bool JsUIExtensionBase::HandleSessionCreate(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo)
760 {
761 if (sessionInfo == nullptr || sessionInfo->uiExtensionComponentId == 0) {
762 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
763 return false;
764 }
765 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64 ", element: %{public}s",
766 sessionInfo->uiExtensionComponentId, want.GetElement().GetURI().c_str());
767 if (sessionInfo == nullptr || sessionInfo->uiExtensionComponentId == 0) {
768 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
769 return false;
770 }
771 std::shared_ptr<AAFwk::Want> sharedWant = std::make_shared<AAFwk::Want>(want);
772 auto componentId = sessionInfo->uiExtensionComponentId;
773 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
774 if (context_ == nullptr || context_->GetAbilityInfo() == nullptr) {
775 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
776 return false;
777 }
778 auto option = CreateWindowOption(sessionInfo);
779 if (option == nullptr) {
780 return false;
781 }
782 sptr<Rosen::Window> uiWindow;
783 {
784 HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::Create");
785 option->SetDisplayId(sessionInfo->displayId);
786 uiWindow = Rosen::Window::Create(option, context_, sessionInfo->sessionToken);
787 }
788 if (uiWindow == nullptr) {
789 TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow");
790 return false;
791 }
792 uiWindow->UpdateExtensionConfig(sharedWant);
793 if (!CallJsOnSessionCreate(*sharedWant, sessionInfo, uiWindow, componentId)) {
794 return false;
795 }
796 uiWindowMap_[componentId] = uiWindow;
797 #ifdef SUPPORT_GRAPHICS
798 if (context_->GetWindow() == nullptr) {
799 context_->SetWindow(uiWindow);
800 }
801 #endif // SUPPORT_GRAPHICS
802 } else {
803 auto uiWindow = uiWindowMap_[componentId];
804 if (uiWindow == nullptr) {
805 TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow");
806 return false;
807 }
808 uiWindow->UpdateExtensionConfig(sharedWant);
809 }
810 return true;
811 }
812
ForegroundWindow(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo)813 void JsUIExtensionBase::ForegroundWindow(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo)
814 {
815 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
816 if (!HandleSessionCreate(want, sessionInfo)) {
817 TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed");
818 return;
819 }
820 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
821 auto componentId = sessionInfo->uiExtensionComponentId;
822 auto &uiWindow = uiWindowMap_[componentId];
823 if (uiWindow) {
824 HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::show");
825 uiWindow->Show();
826 foregroundWindows_.emplace(componentId);
827 }
828 }
829
BackgroundWindow(const sptr<AAFwk::SessionInfo> & sessionInfo)830 void JsUIExtensionBase::BackgroundWindow(const sptr<AAFwk::SessionInfo> &sessionInfo)
831 {
832 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
833 if (sessionInfo == nullptr) {
834 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
835 return;
836 }
837
838 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
839 auto componentId = sessionInfo->uiExtensionComponentId;
840 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
841 TAG_LOGE(AAFwkTag::UI_EXT, "not find uiWindow");
842 return;
843 }
844 auto &uiWindow = uiWindowMap_[componentId];
845 if (uiWindow) {
846 uiWindow->Hide();
847 foregroundWindows_.erase(componentId);
848 }
849 }
850
DestroyWindow(const sptr<AAFwk::SessionInfo> & sessionInfo)851 void JsUIExtensionBase::DestroyWindow(const sptr<AAFwk::SessionInfo> &sessionInfo)
852 {
853 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
854 if (sessionInfo == nullptr) {
855 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
856 return;
857 }
858
859 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
860 auto componentId = sessionInfo->uiExtensionComponentId;
861 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
862 TAG_LOGE(AAFwkTag::UI_EXT, "not find uiWindow");
863 return;
864 }
865 if (contentSessions_.find(componentId) != contentSessions_.end() && contentSessions_[componentId] != nullptr) {
866 HandleScope handleScope(jsRuntime_);
867 napi_value argv[] = { contentSessions_[componentId]->GetNapiValue() };
868 CallObjectMethod("onSessionDestroy", argv, ARGC_ONE);
869 }
870 auto &uiWindow = uiWindowMap_[componentId];
871 if (uiWindow) {
872 uiWindow->Destroy();
873 }
874 uiWindowMap_.erase(componentId);
875 foregroundWindows_.erase(componentId);
876 contentSessions_.erase(componentId);
877 if (abilityResultListeners_) {
878 abilityResultListeners_->RemoveListener(componentId);
879 }
880 }
881
CallObjectMethod(const char * name,napi_value const * argv,size_t argc,bool withResult)882 napi_value JsUIExtensionBase::CallObjectMethod(const char *name, napi_value const *argv, size_t argc, bool withResult)
883 {
884 TAG_LOGD(AAFwkTag::UI_EXT, "CallObjectMethod(%{public}s), begin", name);
885 if (!jsObj_) {
886 TAG_LOGE(AAFwkTag::UI_EXT, "Not found .js file");
887 return nullptr;
888 }
889 napi_env env = jsRuntime_.GetNapiEnv();
890 napi_value obj = jsObj_->GetNapiValue();
891 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
892 TAG_LOGE(AAFwkTag::UI_EXT, "get object failed");
893 return nullptr;
894 }
895 HandleEscape handleEscape(jsRuntime_);
896 napi_value method = nullptr;
897 napi_get_named_property(env, obj, name, &method);
898 if (!CheckTypeForNapiValue(env, method, napi_function)) {
899 TAG_LOGE(AAFwkTag::UI_EXT, "get '%{public}s' object failed", name);
900 return nullptr;
901 }
902 if (withResult) {
903 napi_value result = nullptr;
904 napi_call_function(env, obj, method, argc, argv, &result);
905 return handleEscape.Escape(result);
906 }
907 TAG_LOGD(AAFwkTag::UI_EXT, "CallFunction(%{public}s), success", name);
908 napi_value result = nullptr;
909 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
910 napi_call_function(env, obj, method, argc, argv, &result);
911 return result;
912 }
913
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)914 void JsUIExtensionBase::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration)
915 {
916 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
917 TAG_LOGD(AAFwkTag::UI_EXT, "called");
918 if (context_ == nullptr) {
919 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
920 return;
921 }
922
923 auto abilityConfig = context_->GetAbilityConfiguration();
924 auto configUtils = std::make_shared<ConfigurationUtils>();
925
926 if (abilityConfig != nullptr) {
927 auto newConfig = configUtils->UpdateGlobalConfig(configuration, context_->GetConfiguration(),
928 abilityConfig, context_->GetResourceManager());
929 if (newConfig.GetItemSize() == 0) {
930 return;
931 }
932 if (context_->GetWindow()) {
933 TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", newConfig.GetName().c_str());
934 auto diffConfiguration = std::make_shared<AppExecFwk::Configuration>(newConfig);
935 context_->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context_->GetResourceManager());
936 }
937 } else {
938 auto configUtils = std::make_shared<ConfigurationUtils>();
939 configUtils->UpdateGlobalConfig(configuration, context_->GetConfiguration(), context_->GetResourceManager());
940 }
941
942 ConfigurationUpdated();
943 }
944
OnAbilityConfigurationUpdated(const AppExecFwk::Configuration & configuration)945 void JsUIExtensionBase::OnAbilityConfigurationUpdated(const AppExecFwk::Configuration& configuration)
946 {
947 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
948 TAG_LOGD(AAFwkTag::UI_EXT, "called");
949
950 if (context_ == nullptr) {
951 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
952 return;
953 }
954
955 auto configUtils = std::make_shared<ConfigurationUtils>();
956 configUtils->UpdateAbilityConfig(configuration, context_->GetResourceManager());
957
958 if (context_->GetWindow()) {
959 TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", configuration.GetName().c_str());
960 auto diffConfiguration = std::make_shared<AppExecFwk::Configuration>(configuration);
961 context_->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context_->GetResourceManager());
962 }
963
964 ConfigurationUpdated();
965 }
966
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)967 void JsUIExtensionBase::Dump(const std::vector<std::string> ¶ms, std::vector<std::string> &info)
968 {
969 TAG_LOGD(AAFwkTag::UI_EXT, "called");
970 HandleScope handleScope(jsRuntime_);
971 napi_env env = jsRuntime_.GetNapiEnv();
972 napi_value argv[] = { CreateNativeArray(env, params) };
973
974 if (!jsObj_) {
975 TAG_LOGE(AAFwkTag::UI_EXT, "Not found .js file");
976 return;
977 }
978 napi_value obj = jsObj_->GetNapiValue();
979 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
980 TAG_LOGE(AAFwkTag::UI_EXT, "get object failed");
981 return;
982 }
983
984 napi_value method = nullptr;
985 napi_get_named_property(env, obj, "onDump", &method);
986 if (!CheckTypeForNapiValue(env, method, napi_function)) {
987 method = nullptr;
988 napi_get_named_property(env, obj, "dump", &method);
989 if (!CheckTypeForNapiValue(env, method, napi_function)) {
990 TAG_LOGE(AAFwkTag::UI_EXT, "get onDump failed");
991 return;
992 }
993 }
994 napi_value dumpInfo = nullptr;
995 napi_call_function(env, obj, method, ARGC_ONE, argv, &dumpInfo);
996 if (dumpInfo == nullptr) {
997 TAG_LOGE(AAFwkTag::UI_EXT, "null dumpInfo");
998 return;
999 }
1000 uint32_t len = 0;
1001 napi_get_array_length(env, dumpInfo, &len);
1002 for (uint32_t i = 0; i < len; i++) {
1003 std::string dumpInfoStr;
1004 napi_value element = nullptr;
1005 napi_get_element(env, dumpInfo, i, &element);
1006 if (!ConvertFromJsValue(env, element, dumpInfoStr)) {
1007 TAG_LOGE(AAFwkTag::UI_EXT, "Parse dumpInfoStr error");
1008 return;
1009 }
1010 info.push_back(dumpInfoStr);
1011 }
1012 TAG_LOGD(AAFwkTag::UI_EXT, "Dump info size: %{public}zu", info.size());
1013 }
1014
OnAbilityResult(int32_t requestCode,int32_t resultCode,const Want & resultData)1015 void JsUIExtensionBase::OnAbilityResult(int32_t requestCode, int32_t resultCode, const Want &resultData)
1016 {
1017 TAG_LOGD(AAFwkTag::UI_EXT, "called");
1018 if (context_ == nullptr) {
1019 TAG_LOGW(AAFwkTag::UI_EXT, "null context");
1020 return;
1021 }
1022 context_->OnAbilityResult(requestCode, resultCode, resultData);
1023 if (abilityResultListeners_ == nullptr) {
1024 TAG_LOGW(AAFwkTag::UI_EXT, "null abilityResultListeners");
1025 return;
1026 }
1027 abilityResultListeners_->OnAbilityResult(requestCode, resultCode, resultData);
1028 }
1029
SetAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo)1030 void JsUIExtensionBase::SetAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo)
1031 {
1032 abilityInfo_ = abilityInfo;
1033 }
1034
SetContext(const std::shared_ptr<UIExtensionContext> & context)1035 void JsUIExtensionBase::SetContext(const std::shared_ptr<UIExtensionContext> &context)
1036 {
1037 context_ = context;
1038 }
1039
ConfigurationUpdated()1040 void JsUIExtensionBase::ConfigurationUpdated()
1041 {
1042 TAG_LOGD(AAFwkTag::UI_EXT, "begin");
1043 HandleScope handleScope(jsRuntime_);
1044 napi_env env = jsRuntime_.GetNapiEnv();
1045
1046 // Notify extension context
1047 if (context_ == nullptr) {
1048 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1049 return;
1050 }
1051
1052 auto abilityConfig = context_->GetAbilityConfiguration();
1053 auto fullConfig = context_->GetConfiguration();
1054 if (fullConfig == nullptr) {
1055 TAG_LOGE(AAFwkTag::UI_EXT, "null configuration");
1056 return;
1057 }
1058
1059 auto realConfig = AppExecFwk::Configuration(*fullConfig);
1060 if (abilityConfig != nullptr) {
1061 std::vector<std::string> changeKeyV;
1062 realConfig.CompareDifferent(changeKeyV, *abilityConfig);
1063 if (!changeKeyV.empty()) {
1064 realConfig.Merge(changeKeyV, *abilityConfig);
1065 }
1066 }
1067 TAG_LOGD(AAFwkTag::UIABILITY, "realConfig: %{public}s", realConfig.GetName().c_str());
1068 auto realConfigPtr = std::make_shared<Configuration>(realConfig);
1069 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, realConfigPtr);
1070
1071 napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, realConfig);
1072 CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE);
1073 }
1074
1075 #ifdef SUPPORT_GRAPHICS
OnDisplayInfoChange(const sptr<IRemoteObject> & token,Rosen::DisplayId displayId,float density,Rosen::DisplayOrientation orientation)1076 void JsUIExtensionBase::OnDisplayInfoChange(
1077 const sptr<IRemoteObject> &token, Rosen::DisplayId displayId, float density, Rosen::DisplayOrientation orientation)
1078 {
1079 TAG_LOGI(AAFwkTag::UI_EXT, "displayId: %{public}" PRIu64 "", displayId);
1080 if (context_ == nullptr) {
1081 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1082 return;
1083 }
1084
1085 auto contextConfig = context_->GetConfiguration();
1086 if (contextConfig == nullptr) {
1087 TAG_LOGE(AAFwkTag::UI_EXT, "null configuration");
1088 return;
1089 }
1090
1091 TAG_LOGI(AAFwkTag::UI_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
1092 auto configUtils = std::make_shared<ConfigurationUtils>();
1093 auto result = configUtils->UpdateDisplayConfig(
1094 contextConfig, context_->GetResourceManager(), displayId, density, orientation);
1095 TAG_LOGI(AAFwkTag::UI_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
1096 if (result) {
1097 auto jsUiExtension = std::static_pointer_cast<JsUIExtensionBase>(shared_from_this());
1098 auto task = [jsUiExtension]() {
1099 if (jsUiExtension) {
1100 jsUiExtension->ConfigurationUpdated();
1101 }
1102 };
1103 if (handler_ != nullptr) {
1104 handler_->PostTask(task, "JsUIExtensionBase:OnChange");
1105 }
1106 }
1107 }
1108
RegisterDisplayInfoChangedListener()1109 void JsUIExtensionBase::RegisterDisplayInfoChangedListener()
1110 {
1111 // register displayid change callback
1112 auto jsUiExtensionBase = std::static_pointer_cast<JsUIExtensionBase>(shared_from_this());
1113 jsUIExtensionBaseDisplayListener_ = sptr<JsUIExtensionBaseDisplayListener>::MakeSptr(jsUiExtensionBase);
1114 if (jsUIExtensionBaseDisplayListener_ == nullptr) {
1115 TAG_LOGE(AAFwkTag::UI_EXT, "null JsUIExtensionBaseDisplayListener");
1116 return;
1117 }
1118 if (context_ == nullptr || context_->GetToken() == nullptr) {
1119 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1120 return;
1121 }
1122 TAG_LOGI(AAFwkTag::UI_EXT, "RegisterDisplayInfoChangedListener");
1123 Rosen::WindowManager::GetInstance().RegisterDisplayInfoChangedListener(
1124 context_->GetToken(), jsUIExtensionBaseDisplayListener_);
1125 }
1126
UnregisterDisplayInfoChangedListener()1127 void JsUIExtensionBase::UnregisterDisplayInfoChangedListener()
1128 {
1129 if (context_ == nullptr || context_->GetToken() == nullptr) {
1130 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1131 return;
1132 }
1133 Rosen::WindowManager::GetInstance().UnregisterDisplayInfoChangedListener(
1134 context_->GetToken(), jsUIExtensionBaseDisplayListener_);
1135 }
1136 #endif // SUPPORT_GRAPHICS
1137 } // namespace AbilityRuntime
1138 } // namespace OHOS
1139