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