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 if (context_) {
313 TAG_LOGD(AAFwkTag::UI_EXT, "set terminating true");
314 context_->SetTerminating(true);
315 }
316 HandleScope handleScope(jsRuntime_);
317 CallObjectMethod("onDestroy");
318 ApplicationConfigurationManager::GetInstance().DeleteIgnoreContext(context_);
319 TAG_LOGI(AAFwkTag::UIABILITY, "GetIgnoreContext size %{public}zu",
320 AbilityRuntime::ApplicationConfigurationManager::GetInstance().GetIgnoreContext().size());
321 #ifdef SUPPORT_GRAPHICS
322 UnregisterDisplayInfoChangedListener();
323 #endif // SUPPORT_GRAPHICS
324 OnStopCallBack();
325 TAG_LOGD(AAFwkTag::UI_EXT, "end");
326 }
327
OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)328 void JsUIExtensionBase::OnStop(AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
329 {
330 if (callbackInfo == nullptr) {
331 isAsyncCallback = false;
332 OnStop();
333 return;
334 }
335 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
336 TAG_LOGD(AAFwkTag::UI_EXT, "begin");
337 if (context_) {
338 TAG_LOGD(AAFwkTag::UI_EXT, "set terminating true");
339 context_->SetTerminating(true);
340 }
341 HandleScope handleScope(jsRuntime_);
342 napi_value result = CallObjectMethod("onDestroy", nullptr, 0, true);
343 if (!CheckPromise(result)) {
344 OnStopCallBack();
345 isAsyncCallback = false;
346 return;
347 }
348
349 auto asyncCallback = [extensionWeakPtr = weak_from_this()]() {
350 auto jsUIExtensionBase = extensionWeakPtr.lock();
351 if (jsUIExtensionBase == nullptr) {
352 TAG_LOGE(AAFwkTag::UI_EXT, "null extension");
353 return;
354 }
355 jsUIExtensionBase->OnStopCallBack();
356 };
357 callbackInfo->Push(asyncCallback);
358 isAsyncCallback = CallPromise(result, callbackInfo);
359 if (!isAsyncCallback) {
360 TAG_LOGE(AAFwkTag::UI_EXT, "call promise failed");
361 OnStopCallBack();
362 }
363 TAG_LOGD(AAFwkTag::UI_EXT, "end");
364 }
365
OnStopCallBack()366 void JsUIExtensionBase::OnStopCallBack()
367 {
368 if (context_ == nullptr) {
369 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
370 return;
371 }
372 auto ret = ConnectionManager::GetInstance().DisconnectCaller(context_->GetToken());
373 if (ret) {
374 ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
375 TAG_LOGD(AAFwkTag::UI_EXT, "service connection not disconnected");
376 }
377
378 auto applicationContext = Context::GetApplicationContext();
379 if (applicationContext != nullptr) {
380 applicationContext->DispatchOnAbilityDestroy(jsObj_);
381 }
382 }
383
CheckPromise(napi_value result)384 bool JsUIExtensionBase::CheckPromise(napi_value result)
385 {
386 if (result == nullptr) {
387 TAG_LOGD(AAFwkTag::UI_EXT, "null result");
388 return false;
389 }
390 HandleScope handleScope(jsRuntime_);
391 napi_env env = jsRuntime_.GetNapiEnv();
392 bool isPromise = false;
393 napi_is_promise(env, result, &isPromise);
394 if (!isPromise) {
395 TAG_LOGD(AAFwkTag::UI_EXT, "result not promise");
396 return false;
397 }
398 return true;
399 }
400
401 namespace {
PromiseCallback(napi_env env,napi_callback_info info)402 napi_value PromiseCallback(napi_env env, napi_callback_info info)
403 {
404 void *data = nullptr;
405 NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data), nullptr);
406 auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
407 if (callbackInfo == nullptr) {
408 TAG_LOGD(AAFwkTag::UI_EXT, "Invalid input");
409 return nullptr;
410 }
411 callbackInfo->Call();
412 AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
413 data = nullptr;
414 return nullptr;
415 }
416 }
417
CallPromise(napi_value result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)418 bool JsUIExtensionBase::CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
419 {
420 HandleScope handleScope(jsRuntime_);
421 napi_env env = jsRuntime_.GetNapiEnv();
422 if (!CheckTypeForNapiValue(env, result, napi_object)) {
423 TAG_LOGE(AAFwkTag::UI_EXT, "convert value failed");
424 return false;
425 }
426 napi_value then = nullptr;
427 napi_get_named_property(env, result, "then", &then);
428 if (then == nullptr) {
429 TAG_LOGE(AAFwkTag::UI_EXT, "null then");
430 return false;
431 }
432 bool isCallable = false;
433 napi_is_callable(env, then, &isCallable);
434 if (!isCallable) {
435 TAG_LOGE(AAFwkTag::UI_EXT, "not callable property then");
436 return false;
437 }
438 napi_value promiseCallback = nullptr;
439 napi_status createStatus = napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback,
440 callbackInfo, &promiseCallback);
441 if (createStatus != napi_ok) {
442 TAG_LOGE(AAFwkTag::UI_EXT, "failed, %{public}d", createStatus);
443 return false;
444 }
445 napi_value argv[1] = { promiseCallback };
446 napi_status callStatus = napi_call_function(env, result, then, 1, argv, nullptr);
447 if (callStatus != napi_ok) {
448 TAG_LOGE(AAFwkTag::UI_EXT, "failed, %{public}d", callStatus);
449 return false;
450 }
451 TAG_LOGD(AAFwkTag::UI_EXT, "exit");
452 return true;
453 }
454
OnCommandWindow(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,AAFwk::WindowCommand winCmd)455 void JsUIExtensionBase::OnCommandWindow(
456 const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo, AAFwk::WindowCommand winCmd)
457 {
458 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
459 TAG_LOGD(AAFwkTag::UI_EXT, "called");
460 if (sessionInfo == nullptr) {
461 TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo");
462 return;
463 }
464 if (InsightIntentExecuteParam::IsInsightIntentExecute(want) && winCmd == AAFwk::WIN_CMD_FOREGROUND) {
465 bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, false);
466 if (finish) {
467 return;
468 }
469 }
470 switch (winCmd) {
471 case AAFwk::WIN_CMD_FOREGROUND:
472 ForegroundWindow(want, sessionInfo);
473 break;
474 case AAFwk::WIN_CMD_BACKGROUND:
475 BackgroundWindow(sessionInfo);
476 break;
477 case AAFwk::WIN_CMD_DESTROY:
478 DestroyWindow(sessionInfo);
479 break;
480 default:
481 TAG_LOGD(AAFwkTag::UI_EXT, "unsupported cmd");
482 break;
483 }
484 OnCommandWindowDone(sessionInfo, winCmd);
485 }
486
ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,InsightIntentExecutorInfo & executorInfo)487 void JsUIExtensionBase::ForegroundWindowInitInsightIntentExecutorInfo(const AAFwk::Want &want,
488 const sptr<AAFwk::SessionInfo> &sessionInfo, InsightIntentExecutorInfo &executorInfo)
489 {
490 if (sessionInfo == nullptr) {
491 TAG_LOGE(AAFwkTag::UI_EXT, "null sessionInfo");
492 return;
493 }
494 if (context_ == nullptr) {
495 TAG_LOGE(AAFwkTag::UI_EXT, "null context_");
496 return;
497 }
498 std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo = context_->GetAbilityInfo();
499 if (abilityInfo != nullptr) {
500 executorInfo.hapPath = abilityInfo->hapPath;
501 executorInfo.windowMode = abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE;
502 }
503 executorInfo.token = context_->GetToken();
504 executorInfo.pageLoader = contentSessions_[sessionInfo->uiExtensionComponentId];
505 executorInfo.executeParam = std::make_shared<InsightIntentExecuteParam>();
506 InsightIntentExecuteParam::GenerateFromWant(want, *executorInfo.executeParam);
507 executorInfo.executeParam->executeMode_ = UI_EXTENSION_ABILITY;
508 executorInfo.srcEntry = want.GetStringParam(INSIGHT_INTENT_SRC_ENTRY);
509 TAG_LOGD(AAFwkTag::UI_EXT, "executorInfo, insightIntentId: %{public}" PRIu64,
510 executorInfo.executeParam->insightIntentId_);
511 return;
512 }
513
ForegroundWindowWithInsightIntent(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,bool needForeground)514 bool JsUIExtensionBase::ForegroundWindowWithInsightIntent(const AAFwk::Want &want,
515 const sptr<AAFwk::SessionInfo> &sessionInfo, bool needForeground)
516 {
517 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
518 TAG_LOGD(AAFwkTag::UI_EXT, "called");
519 if (!HandleSessionCreate(want, sessionInfo)) {
520 TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed");
521 return false;
522 }
523
524 std::unique_ptr<InsightIntentExecutorAsyncCallback> executorCallback = nullptr;
525 executorCallback.reset(InsightIntentExecutorAsyncCallback::Create());
526 if (executorCallback == nullptr) {
527 TAG_LOGE(AAFwkTag::UI_EXT, "null executorCallback");
528 return false;
529 }
530 executorCallback->Push(
531 [weak = weak_from_this(), sessionInfo, needForeground, want](AppExecFwk::InsightIntentExecuteResult result) {
532 TAG_LOGD(AAFwkTag::UI_EXT, "Begin UI extension transaction callback");
533 auto extension = weak.lock();
534 if (extension == nullptr) {
535 TAG_LOGE(AAFwkTag::UI_EXT, "null extension");
536 return;
537 }
538 InsightIntentExecuteParam executeParam;
539 InsightIntentExecuteParam::GenerateFromWant(want, executeParam);
540 if (result.uris.size() > 0) {
541 extension->ExecuteInsightIntentDone(executeParam.insightIntentId_, result);
542 }
543 extension->PostInsightIntentExecuted(sessionInfo, result, needForeground);
544 });
545
546 InsightIntentExecutorInfo executorInfo;
547 ForegroundWindowInitInsightIntentExecutorInfo(want, sessionInfo, executorInfo);
548 int32_t ret = DelayedSingleton<InsightIntentExecutorMgr>::GetInstance()->ExecuteInsightIntent(
549 jsRuntime_, executorInfo, std::move(executorCallback));
550 if (!ret) {
551 TAG_LOGE(AAFwkTag::UI_EXT, "Execute insight intent failed");
552 // callback has removed, release in insight intent executor.
553 }
554 TAG_LOGD(AAFwkTag::UI_EXT, "end");
555 return true;
556 }
557
ExecuteInsightIntentDone(uint64_t intentId,const InsightIntentExecuteResult & result)558 void JsUIExtensionBase::ExecuteInsightIntentDone(uint64_t intentId, const InsightIntentExecuteResult &result)
559 {
560 TAG_LOGD(AAFwkTag::UI_EXT, "intentId %{public}" PRIu64"", intentId);
561 auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token_, intentId, result);
562 if (ret != ERR_OK) {
563 TAG_LOGE(AAFwkTag::UI_EXT, "notify execute done failed");
564 }
565 }
566
PostInsightIntentExecuted(const sptr<AAFwk::SessionInfo> & sessionInfo,const AppExecFwk::InsightIntentExecuteResult & result,bool needForeground)567 void JsUIExtensionBase::PostInsightIntentExecuted(const sptr<AAFwk::SessionInfo> &sessionInfo,
568 const AppExecFwk::InsightIntentExecuteResult &result, bool needForeground)
569 {
570 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
571 TAG_LOGD(AAFwkTag::UI_EXT, "Post insightintent executed");
572 if (needForeground) {
573 // If uiextensionability is started for the first time or need move background to foreground.
574 HandleScope handleScope(jsRuntime_);
575 CallObjectMethod("onForeground");
576 }
577
578 OnInsightIntentExecuteDone(sessionInfo, result);
579
580 if (needForeground) {
581 // If need foreground, that means triggered by onForeground.
582 TAG_LOGI(AAFwkTag::UI_EXT, "call abilityms");
583 AAFwk::PacMap restoreData;
584 AAFwk::AbilityManagerClient::GetInstance()->AbilityTransitionDone(token_, AAFwk::ABILITY_STATE_FOREGROUND_NEW,
585 restoreData);
586 } else {
587 // If uiextensionability has displayed in the foreground.
588 OnCommandWindowDone(sessionInfo, AAFwk::WIN_CMD_FOREGROUND);
589 }
590 }
591
OnCommandWindowDone(const sptr<AAFwk::SessionInfo> & sessionInfo,AAFwk::WindowCommand winCmd)592 void JsUIExtensionBase::OnCommandWindowDone(const sptr<AAFwk::SessionInfo> &sessionInfo, AAFwk::WindowCommand winCmd)
593 {
594 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
595 TAG_LOGD(AAFwkTag::UI_EXT, "called");
596 if (context_ == nullptr) {
597 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
598 return;
599 }
600 AAFwk::AbilityCommand abilityCmd;
601 if (uiWindowMap_.empty()) {
602 abilityCmd = AAFwk::ABILITY_CMD_DESTROY;
603 } else if (foregroundWindows_.empty()) {
604 abilityCmd = AAFwk::ABILITY_CMD_BACKGROUND;
605 } else {
606 abilityCmd = AAFwk::ABILITY_CMD_FOREGROUND;
607 }
608 AAFwk::AbilityManagerClient::GetInstance()->ScheduleCommandAbilityWindowDone(
609 context_->GetToken(), sessionInfo, winCmd, abilityCmd);
610 TAG_LOGD(AAFwkTag::UI_EXT, "end");
611 }
612
OnInsightIntentExecuteDone(const sptr<AAFwk::SessionInfo> & sessionInfo,const AppExecFwk::InsightIntentExecuteResult & result)613 void JsUIExtensionBase::OnInsightIntentExecuteDone(const sptr<AAFwk::SessionInfo> &sessionInfo,
614 const AppExecFwk::InsightIntentExecuteResult &result)
615 {
616 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
617 if (sessionInfo == nullptr) {
618 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
619 return;
620 }
621
622 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
623 auto componentId = sessionInfo->uiExtensionComponentId;
624 auto res = uiWindowMap_.find(componentId);
625 if (res != uiWindowMap_.end() && res->second != nullptr) {
626 WantParams params;
627 params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT_CODE, Integer::Box(result.innerErr));
628 WantParams resultParams;
629 resultParams.SetParam("code", Integer::Box(result.code));
630 if (result.result != nullptr) {
631 sptr<AAFwk::IWantParams> pWantParams = WantParamWrapper::Box(*result.result);
632 if (pWantParams != nullptr) {
633 resultParams.SetParam("result", pWantParams);
634 }
635 }
636 auto size = result.uris.size();
637 sptr<IArray> uriArray = new (std::nothrow) Array(size, g_IID_IString);
638 if (uriArray == nullptr) {
639 TAG_LOGE(AAFwkTag::UI_EXT, "new uriArray failed");
640 return;
641 }
642 for (std::size_t i = 0; i < size; i++) {
643 uriArray->Set(i, String::Box(result.uris[i]));
644 }
645 resultParams.SetParam("uris", uriArray);
646 resultParams.SetParam("flags", Integer::Box(result.flags));
647 sptr<AAFwk::IWantParams> pWantParams = WantParamWrapper::Box(resultParams);
648 if (pWantParams != nullptr) {
649 params.SetParam(INSIGHT_INTENT_EXECUTE_RESULT, pWantParams);
650 }
651
652 Rosen::WMError ret = res->second->TransferExtensionData(params);
653 if (ret == Rosen::WMError::WM_OK) {
654 TAG_LOGD(AAFwkTag::UI_EXT, "TransferExtensionData success");
655 } else {
656 TAG_LOGE(AAFwkTag::UI_EXT, "TransferExtensionData failed, ret=%{public}d", ret);
657 }
658
659 res->second->Show();
660 foregroundWindows_.emplace(componentId);
661 }
662 TAG_LOGD(AAFwkTag::UI_EXT, "end");
663 }
664
OnCommand(const AAFwk::Want & want,bool restart,int32_t startId)665 void JsUIExtensionBase::OnCommand(const AAFwk::Want &want, bool restart, int32_t startId)
666 {
667 TAG_LOGD(AAFwkTag::UI_EXT, "called");
668 HandleScope handleScope(jsRuntime_);
669 napi_env env = jsRuntime_.GetNapiEnv();
670 if (env == nullptr) {
671 TAG_LOGE(AAFwkTag::UI_EXT, "null env");
672 return;
673 }
674 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
675 if (napiWant == nullptr) {
676 TAG_LOGE(AAFwkTag::UI_EXT, "null want");
677 return;
678 }
679 napi_value napiStartId = nullptr;
680 napi_create_int32(env, startId, &napiStartId);
681 if (napiStartId == nullptr) {
682 TAG_LOGE(AAFwkTag::UI_EXT, "null startId");
683 return;
684 }
685 napi_value argv[] = { napiWant, napiStartId };
686 CallObjectMethod("onRequest", argv, ARGC_TWO);
687 }
688
OnForeground(const Want & want,sptr<AAFwk::SessionInfo> sessionInfo)689 void JsUIExtensionBase::OnForeground(const Want &want, sptr<AAFwk::SessionInfo> sessionInfo)
690 {
691 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
692 TAG_LOGD(AAFwkTag::UI_EXT, "called");
693 if (InsightIntentExecuteParam::IsInsightIntentExecute(want)) {
694 bool finish = ForegroundWindowWithInsightIntent(want, sessionInfo, true);
695 if (finish) {
696 return;
697 }
698 }
699
700 ForegroundWindow(want, sessionInfo);
701 HandleScope handleScope(jsRuntime_);
702 CallObjectMethod("onForeground");
703 }
704
OnBackground()705 void JsUIExtensionBase::OnBackground()
706 {
707 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
708 TAG_LOGD(AAFwkTag::UI_EXT, "called");
709 HandleScope handleScope(jsRuntime_);
710 CallObjectMethod("onBackground");
711 }
712
CallJsOnSessionCreate(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo,const sptr<Rosen::Window> & uiWindow,const uint64_t & uiExtensionComponentId)713 bool JsUIExtensionBase::CallJsOnSessionCreate(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo,
714 const sptr<Rosen::Window> &uiWindow, const uint64_t &uiExtensionComponentId)
715 {
716 HandleScope handleScope(jsRuntime_);
717 napi_env env = jsRuntime_.GetNapiEnv();
718 if (env == nullptr) {
719 TAG_LOGE(AAFwkTag::UI_EXT, "null env");
720 return false;
721 }
722 napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
723 if (napiWant == nullptr) {
724 TAG_LOGE(AAFwkTag::UI_EXT, "null want");
725 return false;
726 }
727 napi_value nativeContentSession = JsUIExtensionContentSession::CreateJsUIExtensionContentSession(
728 env, sessionInfo, uiWindow, context_, abilityResultListeners_);
729 if (nativeContentSession == nullptr) {
730 TAG_LOGE(AAFwkTag::UI_EXT, "null contentSession");
731 return false;
732 }
733 napi_ref ref = nullptr;
734 napi_create_reference(env, nativeContentSession, 1, &ref);
735 contentSessions_.emplace(
736 uiExtensionComponentId, std::shared_ptr<NativeReference>(reinterpret_cast<NativeReference*>(ref)));
737 napi_value argv[] = { napiWant, nativeContentSession };
738 CallObjectMethod("onSessionCreate", argv, ARGC_TWO);
739 return true;
740 }
741
CreateWindowOption(const sptr<AAFwk::SessionInfo> & sessionInfo)742 sptr<Rosen::WindowOption> JsUIExtensionBase::CreateWindowOption(const sptr<AAFwk::SessionInfo> &sessionInfo)
743 {
744 auto option = sptr<Rosen::WindowOption>::MakeSptr();
745 if (option == nullptr) {
746 TAG_LOGE(AAFwkTag::UI_EXT, "make option failed");
747 return nullptr;
748 }
749
750 option->SetWindowName(context_->GetBundleName() + context_->GetAbilityInfo()->name);
751 option->SetWindowType(Rosen::WindowType::WINDOW_TYPE_UI_EXTENSION);
752 option->SetWindowSessionType(Rosen::WindowSessionType::EXTENSION_SESSION);
753 option->SetParentId(sessionInfo->hostWindowId);
754 option->SetRealParentId(sessionInfo->realHostWindowId);
755 option->SetParentWindowType(static_cast<Rosen::WindowType>(sessionInfo->parentWindowType));
756 option->SetUIExtensionUsage(static_cast<uint32_t>(sessionInfo->uiExtensionUsage));
757 option->SetDensity(sessionInfo->density);
758 option->SetIsDensityFollowHost(sessionInfo->isDensityFollowHost);
759 if (context_->isNotAllow != -1) {
760 bool isNotAllow = context_->isNotAllow == 1 ? true : false;
761 TAG_LOGD(AAFwkTag::UI_EXT, "isNotAllow: %{public}d", isNotAllow);
762 option->SetConstrainedModal(isNotAllow);
763 }
764 return option;
765 }
766
HandleSessionCreate(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo)767 bool JsUIExtensionBase::HandleSessionCreate(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo)
768 {
769 if (sessionInfo == nullptr || sessionInfo->uiExtensionComponentId == 0) {
770 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
771 return false;
772 }
773 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64 ", element: %{public}s",
774 sessionInfo->uiExtensionComponentId, want.GetElement().GetURI().c_str());
775 if (sessionInfo == nullptr || sessionInfo->uiExtensionComponentId == 0) {
776 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
777 return false;
778 }
779 std::shared_ptr<AAFwk::Want> sharedWant = std::make_shared<AAFwk::Want>(want);
780 auto componentId = sessionInfo->uiExtensionComponentId;
781 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
782 if (context_ == nullptr || context_->GetAbilityInfo() == nullptr) {
783 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
784 return false;
785 }
786 auto option = CreateWindowOption(sessionInfo);
787 if (option == nullptr) {
788 return false;
789 }
790 sptr<Rosen::Window> uiWindow;
791 {
792 HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::Create");
793 option->SetDisplayId(sessionInfo->displayId);
794 uiWindow = Rosen::Window::Create(option, context_, sessionInfo->sessionToken);
795 }
796 if (uiWindow == nullptr) {
797 TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow");
798 return false;
799 }
800 uiWindow->UpdateExtensionConfig(sharedWant);
801 if (!CallJsOnSessionCreate(*sharedWant, sessionInfo, uiWindow, componentId)) {
802 return false;
803 }
804 uiWindowMap_[componentId] = uiWindow;
805 #ifdef SUPPORT_GRAPHICS
806 if (context_->GetWindow() == nullptr) {
807 context_->SetWindow(uiWindow);
808 }
809 #endif // SUPPORT_GRAPHICS
810 } else {
811 auto uiWindow = uiWindowMap_[componentId];
812 if (uiWindow == nullptr) {
813 TAG_LOGE(AAFwkTag::UI_EXT, "null uiWindow");
814 return false;
815 }
816 uiWindow->UpdateExtensionConfig(sharedWant);
817 }
818 return true;
819 }
820
ForegroundWindow(const AAFwk::Want & want,const sptr<AAFwk::SessionInfo> & sessionInfo)821 void JsUIExtensionBase::ForegroundWindow(const AAFwk::Want &want, const sptr<AAFwk::SessionInfo> &sessionInfo)
822 {
823 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
824 if (!HandleSessionCreate(want, sessionInfo)) {
825 TAG_LOGE(AAFwkTag::UI_EXT, "HandleSessionCreate failed");
826 return;
827 }
828 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
829 auto componentId = sessionInfo->uiExtensionComponentId;
830 auto &uiWindow = uiWindowMap_[componentId];
831 if (uiWindow) {
832 HITRACE_METER_NAME(HITRACE_TAG_APP, "Rosen::Window::show");
833 uiWindow->Show();
834 foregroundWindows_.emplace(componentId);
835 }
836 }
837
BackgroundWindow(const sptr<AAFwk::SessionInfo> & sessionInfo)838 void JsUIExtensionBase::BackgroundWindow(const sptr<AAFwk::SessionInfo> &sessionInfo)
839 {
840 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
841 if (sessionInfo == nullptr) {
842 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
843 return;
844 }
845
846 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
847 auto componentId = sessionInfo->uiExtensionComponentId;
848 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
849 TAG_LOGE(AAFwkTag::UI_EXT, "not find uiWindow");
850 return;
851 }
852 auto &uiWindow = uiWindowMap_[componentId];
853 if (uiWindow) {
854 uiWindow->Hide();
855 foregroundWindows_.erase(componentId);
856 }
857 }
858
DestroyWindow(const sptr<AAFwk::SessionInfo> & sessionInfo)859 void JsUIExtensionBase::DestroyWindow(const sptr<AAFwk::SessionInfo> &sessionInfo)
860 {
861 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
862 if (sessionInfo == nullptr) {
863 TAG_LOGE(AAFwkTag::UI_EXT, "Invalid sessionInfo");
864 return;
865 }
866
867 TAG_LOGD(AAFwkTag::UI_EXT, "UIExtension component id: %{public}" PRId64, sessionInfo->uiExtensionComponentId);
868 auto componentId = sessionInfo->uiExtensionComponentId;
869 if (uiWindowMap_.find(componentId) == uiWindowMap_.end()) {
870 TAG_LOGE(AAFwkTag::UI_EXT, "not find uiWindow");
871 return;
872 }
873 if (contentSessions_.find(componentId) != contentSessions_.end() && contentSessions_[componentId] != nullptr) {
874 HandleScope handleScope(jsRuntime_);
875 napi_value argv[] = { contentSessions_[componentId]->GetNapiValue() };
876 CallObjectMethod("onSessionDestroy", argv, ARGC_ONE);
877 }
878 auto &uiWindow = uiWindowMap_[componentId];
879 if (uiWindow) {
880 uiWindow->Destroy();
881 }
882 uiWindowMap_.erase(componentId);
883 foregroundWindows_.erase(componentId);
884 contentSessions_.erase(componentId);
885 if (abilityResultListeners_) {
886 abilityResultListeners_->RemoveListener(componentId);
887 }
888 }
889
CallObjectMethod(const char * name,napi_value const * argv,size_t argc,bool withResult)890 napi_value JsUIExtensionBase::CallObjectMethod(const char *name, napi_value const *argv, size_t argc, bool withResult)
891 {
892 TAG_LOGD(AAFwkTag::UI_EXT, "CallObjectMethod(%{public}s), begin", name);
893 if (!jsObj_) {
894 TAG_LOGE(AAFwkTag::UI_EXT, "Not found .js file");
895 return nullptr;
896 }
897 napi_env env = jsRuntime_.GetNapiEnv();
898 napi_value obj = jsObj_->GetNapiValue();
899 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
900 TAG_LOGE(AAFwkTag::UI_EXT, "get object failed");
901 return nullptr;
902 }
903 HandleEscape handleEscape(jsRuntime_);
904 napi_value method = nullptr;
905 napi_get_named_property(env, obj, name, &method);
906 if (!CheckTypeForNapiValue(env, method, napi_function)) {
907 TAG_LOGE(AAFwkTag::UI_EXT, "get '%{public}s' object failed", name);
908 return nullptr;
909 }
910 if (withResult) {
911 napi_value result = nullptr;
912 napi_call_function(env, obj, method, argc, argv, &result);
913 return handleEscape.Escape(result);
914 }
915 TAG_LOGD(AAFwkTag::UI_EXT, "CallFunction(%{public}s), success", name);
916 napi_value result = nullptr;
917 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
918 napi_call_function(env, obj, method, argc, argv, &result);
919 return result;
920 }
921
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)922 void JsUIExtensionBase::OnConfigurationUpdated(const AppExecFwk::Configuration &configuration)
923 {
924 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
925 TAG_LOGD(AAFwkTag::UI_EXT, "called");
926 if (context_ == nullptr) {
927 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
928 return;
929 }
930
931 auto abilityConfig = context_->GetAbilityConfiguration();
932 auto configUtils = std::make_shared<ConfigurationUtils>();
933
934 if (abilityConfig != nullptr) {
935 auto newConfig = configUtils->UpdateGlobalConfig(configuration, context_->GetConfiguration(),
936 abilityConfig, context_->GetResourceManager());
937 if (newConfig.GetItemSize() == 0) {
938 return;
939 }
940 if (context_->GetWindow()) {
941 TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", newConfig.GetName().c_str());
942 auto diffConfiguration = std::make_shared<AppExecFwk::Configuration>(newConfig);
943 context_->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context_->GetResourceManager());
944 }
945 } else {
946 auto configUtils = std::make_shared<ConfigurationUtils>();
947 configUtils->UpdateGlobalConfig(configuration, context_->GetConfiguration(), context_->GetResourceManager());
948 }
949
950 ConfigurationUpdated();
951 }
952
OnAbilityConfigurationUpdated(const AppExecFwk::Configuration & configuration)953 void JsUIExtensionBase::OnAbilityConfigurationUpdated(const AppExecFwk::Configuration& configuration)
954 {
955 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
956 TAG_LOGD(AAFwkTag::UI_EXT, "called");
957
958 if (context_ == nullptr) {
959 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
960 return;
961 }
962
963 auto configUtils = std::make_shared<ConfigurationUtils>();
964 configUtils->UpdateAbilityConfig(configuration, context_->GetResourceManager());
965
966 if (context_->GetWindow()) {
967 TAG_LOGI(AAFwkTag::UIABILITY, "newConfig: %{public}s", configuration.GetName().c_str());
968 auto diffConfiguration = std::make_shared<AppExecFwk::Configuration>(configuration);
969 context_->GetWindow()->UpdateConfigurationForSpecified(diffConfiguration, context_->GetResourceManager());
970 }
971
972 ConfigurationUpdated();
973 }
974
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)975 void JsUIExtensionBase::Dump(const std::vector<std::string> ¶ms, std::vector<std::string> &info)
976 {
977 TAG_LOGD(AAFwkTag::UI_EXT, "called");
978 HandleScope handleScope(jsRuntime_);
979 napi_env env = jsRuntime_.GetNapiEnv();
980 napi_value argv[] = { CreateNativeArray(env, params) };
981
982 if (!jsObj_) {
983 TAG_LOGE(AAFwkTag::UI_EXT, "Not found .js file");
984 return;
985 }
986 napi_value obj = jsObj_->GetNapiValue();
987 if (!CheckTypeForNapiValue(env, obj, napi_object)) {
988 TAG_LOGE(AAFwkTag::UI_EXT, "get object failed");
989 return;
990 }
991
992 napi_value method = nullptr;
993 napi_get_named_property(env, obj, "onDump", &method);
994 if (!CheckTypeForNapiValue(env, method, napi_function)) {
995 method = nullptr;
996 napi_get_named_property(env, obj, "dump", &method);
997 if (!CheckTypeForNapiValue(env, method, napi_function)) {
998 TAG_LOGE(AAFwkTag::UI_EXT, "get onDump failed");
999 return;
1000 }
1001 }
1002 napi_value dumpInfo = nullptr;
1003 napi_call_function(env, obj, method, ARGC_ONE, argv, &dumpInfo);
1004 if (dumpInfo == nullptr) {
1005 TAG_LOGE(AAFwkTag::UI_EXT, "null dumpInfo");
1006 return;
1007 }
1008 uint32_t len = 0;
1009 napi_get_array_length(env, dumpInfo, &len);
1010 for (uint32_t i = 0; i < len; i++) {
1011 std::string dumpInfoStr;
1012 napi_value element = nullptr;
1013 napi_get_element(env, dumpInfo, i, &element);
1014 if (!ConvertFromJsValue(env, element, dumpInfoStr)) {
1015 TAG_LOGE(AAFwkTag::UI_EXT, "Parse dumpInfoStr error");
1016 return;
1017 }
1018 info.push_back(dumpInfoStr);
1019 }
1020 TAG_LOGD(AAFwkTag::UI_EXT, "Dump info size: %{public}zu", info.size());
1021 }
1022
OnAbilityResult(int32_t requestCode,int32_t resultCode,const Want & resultData)1023 void JsUIExtensionBase::OnAbilityResult(int32_t requestCode, int32_t resultCode, const Want &resultData)
1024 {
1025 TAG_LOGD(AAFwkTag::UI_EXT, "called");
1026 if (context_ == nullptr) {
1027 TAG_LOGW(AAFwkTag::UI_EXT, "null context");
1028 return;
1029 }
1030 context_->OnAbilityResult(requestCode, resultCode, resultData);
1031 if (abilityResultListeners_ == nullptr) {
1032 TAG_LOGW(AAFwkTag::UI_EXT, "null abilityResultListeners");
1033 return;
1034 }
1035 abilityResultListeners_->OnAbilityResult(requestCode, resultCode, resultData);
1036 }
1037
SetAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo> & abilityInfo)1038 void JsUIExtensionBase::SetAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo> &abilityInfo)
1039 {
1040 abilityInfo_ = abilityInfo;
1041 }
1042
SetContext(const std::shared_ptr<UIExtensionContext> & context)1043 void JsUIExtensionBase::SetContext(const std::shared_ptr<UIExtensionContext> &context)
1044 {
1045 context_ = context;
1046 }
1047
ConfigurationUpdated()1048 void JsUIExtensionBase::ConfigurationUpdated()
1049 {
1050 TAG_LOGD(AAFwkTag::UI_EXT, "begin");
1051 HandleScope handleScope(jsRuntime_);
1052 napi_env env = jsRuntime_.GetNapiEnv();
1053
1054 // Notify extension context
1055 if (context_ == nullptr) {
1056 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1057 return;
1058 }
1059
1060 auto abilityConfig = context_->GetAbilityConfiguration();
1061 auto fullConfig = context_->GetConfiguration();
1062 if (fullConfig == nullptr) {
1063 TAG_LOGE(AAFwkTag::UI_EXT, "null configuration");
1064 return;
1065 }
1066
1067 auto realConfig = AppExecFwk::Configuration(*fullConfig);
1068 if (abilityConfig != nullptr) {
1069 std::vector<std::string> changeKeyV;
1070 realConfig.CompareDifferent(changeKeyV, *abilityConfig);
1071 if (!changeKeyV.empty()) {
1072 realConfig.Merge(changeKeyV, *abilityConfig);
1073 }
1074 }
1075 TAG_LOGD(AAFwkTag::UIABILITY, "realConfig: %{public}s", realConfig.GetName().c_str());
1076 auto realConfigPtr = std::make_shared<Configuration>(realConfig);
1077 JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, realConfigPtr);
1078
1079 napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, realConfig);
1080 CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE);
1081 }
1082
1083 #ifdef SUPPORT_GRAPHICS
OnDisplayInfoChange(const sptr<IRemoteObject> & token,Rosen::DisplayId displayId,float density,Rosen::DisplayOrientation orientation)1084 void JsUIExtensionBase::OnDisplayInfoChange(
1085 const sptr<IRemoteObject> &token, Rosen::DisplayId displayId, float density, Rosen::DisplayOrientation orientation)
1086 {
1087 TAG_LOGI(AAFwkTag::UI_EXT, "displayId: %{public}" PRIu64 "", displayId);
1088 if (context_ == nullptr) {
1089 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1090 return;
1091 }
1092
1093 auto contextConfig = context_->GetConfiguration();
1094 if (contextConfig == nullptr) {
1095 TAG_LOGE(AAFwkTag::UI_EXT, "null configuration");
1096 return;
1097 }
1098
1099 TAG_LOGI(AAFwkTag::UI_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
1100 auto configUtils = std::make_shared<ConfigurationUtils>();
1101 auto result = configUtils->UpdateDisplayConfig(
1102 contextConfig, context_->GetResourceManager(), displayId, density, orientation);
1103 TAG_LOGI(AAFwkTag::UI_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
1104 if (result) {
1105 auto jsUiExtension = std::static_pointer_cast<JsUIExtensionBase>(shared_from_this());
1106 auto task = [jsUiExtension]() {
1107 if (jsUiExtension) {
1108 jsUiExtension->ConfigurationUpdated();
1109 }
1110 };
1111 if (handler_ != nullptr) {
1112 handler_->PostTask(task, "JsUIExtensionBase:OnChange");
1113 }
1114 }
1115 }
1116
RegisterDisplayInfoChangedListener()1117 void JsUIExtensionBase::RegisterDisplayInfoChangedListener()
1118 {
1119 // register displayid change callback
1120 auto jsUiExtensionBase = std::static_pointer_cast<JsUIExtensionBase>(shared_from_this());
1121 jsUIExtensionBaseDisplayListener_ = sptr<JsUIExtensionBaseDisplayListener>::MakeSptr(jsUiExtensionBase);
1122 if (jsUIExtensionBaseDisplayListener_ == nullptr) {
1123 TAG_LOGE(AAFwkTag::UI_EXT, "null JsUIExtensionBaseDisplayListener");
1124 return;
1125 }
1126 if (context_ == nullptr || context_->GetToken() == nullptr) {
1127 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1128 return;
1129 }
1130 TAG_LOGI(AAFwkTag::UI_EXT, "RegisterDisplayInfoChangedListener");
1131 Rosen::WindowManager::GetInstance().RegisterDisplayInfoChangedListener(
1132 context_->GetToken(), jsUIExtensionBaseDisplayListener_);
1133 }
1134
UnregisterDisplayInfoChangedListener()1135 void JsUIExtensionBase::UnregisterDisplayInfoChangedListener()
1136 {
1137 if (context_ == nullptr || context_->GetToken() == nullptr) {
1138 TAG_LOGE(AAFwkTag::UI_EXT, "null context");
1139 return;
1140 }
1141 Rosen::WindowManager::GetInstance().UnregisterDisplayInfoChangedListener(
1142 context_->GetToken(), jsUIExtensionBaseDisplayListener_);
1143 }
1144 #endif // SUPPORT_GRAPHICS
1145 } // namespace AbilityRuntime
1146 } // namespace OHOS
1147