• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params, 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