• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_service_extension.h"
17 
18 #include "ability_business_error.h"
19 #include "ability_handler.h"
20 #include "ability_info.h"
21 #include "ability_manager_client.h"
22 #include "configuration_utils.h"
23 #include "display_util.h"
24 #include "hitrace_meter.h"
25 #include "hilog_tag_wrapper.h"
26 #include "insight_intent_execute_param.h"
27 #include "insight_intent_execute_result.h"
28 #include "insight_intent_executor_info.h"
29 #include "insight_intent_executor_mgr.h"
30 #include "js_extension_common.h"
31 #include "js_extension_context.h"
32 #include "js_runtime.h"
33 #include "js_runtime_utils.h"
34 #include "js_service_extension_context.h"
35 #include "napi/native_api.h"
36 #include "napi/native_node_api.h"
37 #include "napi_common_configuration.h"
38 #include "napi_common_want.h"
39 #include "napi_remote_object.h"
40 #ifdef SUPPORT_GRAPHICS
41 #include "iservice_registry.h"
42 #include "system_ability_definition.h"
43 #include "window_scene.h"
44 #endif
45 
46 namespace OHOS {
47 namespace AbilityRuntime {
48 namespace {
49 constexpr size_t ARGC_ONE = 1;
50 constexpr size_t ARGC_TWO = 2;
51 }
52 
53 namespace {
GetNativeRemoteObject(napi_env env,napi_value obj)54 sptr<IRemoteObject> GetNativeRemoteObject(napi_env env, napi_value obj)
55 {
56     if (env == nullptr || obj == nullptr) {
57         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null obj");
58         return nullptr;
59     }
60     napi_valuetype type;
61     napi_typeof(env, obj, &type);
62     if (type == napi_undefined || type == napi_null) {
63         TAG_LOGE(AAFwkTag::SERVICE_EXT, "obj type invalid");
64         return nullptr;
65     }
66     if (type != napi_object) {
67         TAG_LOGE(AAFwkTag::SERVICE_EXT, "obj not object");
68         return nullptr;
69     }
70     return NAPI_ohos_rpc_getNativeRemoteObject(env, obj);
71 }
72 
PromiseCallback(napi_env env,napi_callback_info info)73 napi_value PromiseCallback(napi_env env, napi_callback_info info)
74 {
75     void *data = nullptr;
76     NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data), nullptr);
77     auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
78     callbackInfo->Call();
79     AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
80     data = nullptr;
81     return nullptr;
82 }
83 
OnConnectPromiseCallback(napi_env env,napi_callback_info info)84 napi_value OnConnectPromiseCallback(napi_env env, napi_callback_info info)
85 {
86     TAG_LOGD(AAFwkTag::SERVICE_EXT, "enter");
87     void *data = nullptr;
88     size_t argc = ARGC_MAX_COUNT;
89     napi_value argv[ARGC_MAX_COUNT] = {nullptr};
90     NAPI_CALL_NO_THROW(napi_get_cb_info(env, info, &argc, argv, nullptr, &data), nullptr);
91     auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *>(data);
92     sptr<IRemoteObject> service = nullptr;
93     if (argc > 0) {
94         service = GetNativeRemoteObject(env, argv[0]);
95     }
96     callbackInfo->Call(service);
97     AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>>::Destroy(callbackInfo);
98     data = nullptr;
99     TAG_LOGD(AAFwkTag::SERVICE_EXT, "end");
100     return nullptr;
101 }
102 }
103 
104 using namespace OHOS::AppExecFwk;
105 
AttachServiceExtensionContext(napi_env env,void * value,void *)106 napi_value AttachServiceExtensionContext(napi_env env, void *value, void *)
107 {
108     if (value == nullptr) {
109         TAG_LOGW(AAFwkTag::SERVICE_EXT, "null value");
110         return nullptr;
111     }
112     auto ptr = reinterpret_cast<std::weak_ptr<ServiceExtensionContext> *>(value)->lock();
113     if (ptr == nullptr) {
114         TAG_LOGW(AAFwkTag::SERVICE_EXT, "null ptr");
115         return nullptr;
116     }
117     napi_value object = CreateJsServiceExtensionContext(env, ptr);
118     auto sysModule = JsRuntime::LoadSystemModuleByEngine(env,
119         "application.ServiceExtensionContext", &object, 1);
120     if (sysModule == nullptr) {
121         TAG_LOGW(AAFwkTag::SERVICE_EXT, "null sysModule");
122         return nullptr;
123     }
124     auto contextObj = sysModule->GetNapiValue();
125     napi_coerce_to_native_binding_object(
126         env, contextObj, DetachCallbackFunc, AttachServiceExtensionContext, value, nullptr);
127     auto workContext = new (std::nothrow) std::weak_ptr<ServiceExtensionContext>(ptr);
128     auto res = napi_wrap(env, contextObj, workContext,
129         [](napi_env, void *data, void *) {
130             TAG_LOGD(AAFwkTag::SERVICE_EXT, "Finalizer for weak_ptr service extension context is called");
131             delete static_cast<std::weak_ptr<ServiceExtensionContext> *>(data);
132         },
133         nullptr, nullptr);
134     if (res != napi_ok && workContext != nullptr) {
135         TAG_LOGE(AAFwkTag::SERVICE_EXT, "napi_wrap failed:%{public}d", res);
136         delete workContext;
137         return nullptr;
138     }
139     return contextObj;
140 }
141 
Create(const std::unique_ptr<Runtime> & runtime)142 JsServiceExtension* JsServiceExtension::Create(const std::unique_ptr<Runtime>& runtime)
143 {
144     return new JsServiceExtension(static_cast<JsRuntime&>(*runtime));
145 }
146 
JsServiceExtension(JsRuntime & jsRuntime)147 JsServiceExtension::JsServiceExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsServiceExtension()148 JsServiceExtension::~JsServiceExtension()
149 {
150     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
151     auto context = GetContext();
152     if (context) {
153         context->Unbind();
154     }
155 
156     jsRuntime_.FreeNativeReference(std::move(jsObj_));
157     jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
158 }
159 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)160 void JsServiceExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
161     const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
162     const sptr<IRemoteObject> &token)
163 {
164     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
165     ServiceExtension::Init(record, application, handler, token);
166     std::string srcPath = "";
167     GetSrcPath(srcPath);
168     if (srcPath.empty()) {
169         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get srcPath failed");
170         return;
171     }
172 
173     std::string moduleName(Extension::abilityInfo_->moduleName);
174     moduleName.append("::").append(abilityInfo_->name);
175     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called, moduleName:%{public}s,srcPath:%{public}s",
176         moduleName.c_str(), srcPath.c_str());
177     HandleScope handleScope(jsRuntime_);
178     auto env = jsRuntime_.GetNapiEnv();
179 
180     jsObj_ = jsRuntime_.LoadModule(
181         moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE,
182         false, abilityInfo_->srcEntrance);
183     if (jsObj_ == nullptr) {
184         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null jsObj_");
185         return;
186     }
187 
188     TAG_LOGD(AAFwkTag::SERVICE_EXT, "ConvertNativeValueTo");
189     napi_value obj = jsObj_->GetNapiValue();
190     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
191         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get JsServiceExtension obj failed");
192         return;
193     }
194 
195     BindContext(env, obj);
196 
197     SetExtensionCommon(JsExtensionCommon::Create(jsRuntime_, static_cast<NativeReference&>(*jsObj_), shellContextRef_));
198 
199     handler_ = handler;
200     auto context = GetContext();
201     auto appContext = Context::GetApplicationContext();
202     if (context != nullptr && appContext != nullptr) {
203         auto appConfig = appContext->GetConfiguration();
204         if (appConfig != nullptr) {
205             TAG_LOGD(AAFwkTag::SERVICE_EXT, "Original config dump: %{public}s", appConfig->GetName().c_str());
206             context->SetConfiguration(std::make_shared<Configuration>(*appConfig));
207         }
208     }
209     ListenWMS();
210 }
211 
ListenWMS()212 void JsServiceExtension::ListenWMS()
213 {
214 #ifdef SUPPORT_GRAPHICS
215     TAG_LOGD(AAFwkTag::SERVICE_EXT, "RegisterDisplayListener");
216     auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
217     if (abilityManager == nullptr) {
218         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null SaMgr");
219         return;
220     }
221 
222     auto jsServiceExtension = std::static_pointer_cast<JsServiceExtension>(shared_from_this());
223     displayListener_ = sptr<JsServiceExtensionDisplayListener>::MakeSptr(jsServiceExtension);
224     if (displayListener_ == nullptr) {
225         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null displayListener");
226         return;
227     }
228 
229     auto context = GetContext();
230     if (context == nullptr || context->GetToken() == nullptr) {
231         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
232         return;
233     }
234 
235     saStatusChangeListener_ =
236         sptr<SystemAbilityStatusChangeListener>::MakeSptr(displayListener_, context->GetToken());
237     if (saStatusChangeListener_ == nullptr) {
238         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null saStatusChangeListener");
239         return;
240     }
241 
242     auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, saStatusChangeListener_);
243     if (ret != 0) {
244         TAG_LOGE(AAFwkTag::SERVICE_EXT, "subscribe system ability error:%{public}d.", ret);
245     }
246 #endif
247 }
248 #ifdef SUPPORT_GRAPHICS
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)249 void JsServiceExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId,
250     const std::string& deviceId)
251 {
252     TAG_LOGD(AAFwkTag::SERVICE_EXT, "systemAbilityId: %{public}d add", systemAbilityId);
253     if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) {
254         TAG_LOGI(AAFwkTag::SERVICE_EXT, "RegisterDisplayInfoChangedListener");
255         Rosen::WindowManager::GetInstance().RegisterDisplayInfoChangedListener(token_, tmpDisplayListener_);
256     }
257 }
258 #endif //SUPPORT_GRAPHICS
BindContext(napi_env env,napi_value obj)259 void JsServiceExtension::BindContext(napi_env env, napi_value obj)
260 {
261     auto context = GetContext();
262     if (context == nullptr) {
263         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
264         return;
265     }
266     TAG_LOGD(AAFwkTag::SERVICE_EXT, "call");
267     napi_value contextObj = CreateJsServiceExtensionContext(env, context);
268     shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(env, "application.ServiceExtensionContext",
269         &contextObj, ARGC_ONE);
270     if (shellContextRef_ == nullptr) {
271         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null shellContextRef");
272         return;
273     }
274     contextObj = shellContextRef_->GetNapiValue();
275     if (!CheckTypeForNapiValue(env, contextObj, napi_object)) {
276         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get context native obj failed");
277         return;
278     }
279     auto workContext = new (std::nothrow) std::weak_ptr<ServiceExtensionContext>(context);
280     napi_coerce_to_native_binding_object(
281         env, contextObj, DetachCallbackFunc, AttachServiceExtensionContext, workContext, nullptr);
282     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Bind");
283     context->Bind(jsRuntime_, shellContextRef_.get());
284     napi_set_named_property(env, obj, "context", contextObj);
285 
286     auto res = napi_wrap(env, contextObj, workContext,
287         [](napi_env, void* data, void*) {
288             delete static_cast<std::weak_ptr<ServiceExtensionContext>*>(data);
289         },
290         nullptr, nullptr);
291     if (res != napi_ok && workContext != nullptr) {
292         TAG_LOGE(AAFwkTag::SERVICE_EXT, "napi_wrap failed:%{public}d", res);
293         delete workContext;
294         return;
295     }
296     TAG_LOGD(AAFwkTag::SERVICE_EXT, "end");
297 }
298 
OnStart(const AAFwk::Want & want)299 void JsServiceExtension::OnStart(const AAFwk::Want &want)
300 {
301     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
302     Extension::OnStart(want);
303     TAG_LOGI(AAFwkTag::SERVICE_EXT, "call");
304 
305     auto context = GetContext();
306     if (context != nullptr) {
307 #ifdef SUPPORT_GRAPHICS
308         int32_t displayId = AAFwk::DisplayUtil::GetDefaultDisplayId();
309         displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, displayId);
310         TAG_LOGD(AAFwkTag::SERVICE_EXT, "displayId %{public}d", displayId);
311         auto configUtils = std::make_shared<ConfigurationUtils>();
312         configUtils->InitDisplayConfig(displayId, context->GetConfiguration(), context->GetResourceManager());
313 #endif //SUPPORT_GRAPHICS
314     }
315 
316     HandleScope handleScope(jsRuntime_);
317     napi_env env = jsRuntime_.GetNapiEnv();
318 
319     // display config has changed, need update context.config
320     if (context != nullptr) {
321         JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, context->GetConfiguration());
322     }
323 
324     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
325     napi_value argv[] = {napiWant};
326     CallObjectMethod("onCreate", argv, ARGC_ONE);
327     TAG_LOGD(AAFwkTag::SERVICE_EXT, "ok");
328 }
329 
OnStop()330 void JsServiceExtension::OnStop()
331 {
332     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
333     ServiceExtension::OnStop();
334     TAG_LOGD(AAFwkTag::SERVICE_EXT, "call");
335     CallObjectMethod("onDestroy");
336     bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
337     if (ret) {
338         ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
339         TAG_LOGD(AAFwkTag::SERVICE_EXT, "service extension connection not disconnected");
340     }
341     TAG_LOGI(AAFwkTag::SERVICE_EXT, "UnregisterDisplayInfoChangedListener");
342     auto context = GetContext();
343     if (context == nullptr || context->GetToken() == nullptr) {
344         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
345         return;
346     }
347 #ifdef SUPPORT_GRAPHICS
348     Rosen::WindowManager::GetInstance()
349         .UnregisterDisplayInfoChangedListener(context->GetToken(), displayListener_);
350     if (saStatusChangeListener_) {
351         auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
352         if (saMgr) {
353             saMgr->UnSubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, saStatusChangeListener_);
354         } else {
355             TAG_LOGW(AAFwkTag::SERVICE_EXT, "OnStop SaMgr null");
356         }
357     }
358 #endif //SUPPORT_GRAPHICS
359     TAG_LOGD(AAFwkTag::SERVICE_EXT, "ok");
360 }
361 
OnConnect(const AAFwk::Want & want)362 sptr<IRemoteObject> JsServiceExtension::OnConnect(const AAFwk::Want &want)
363 {
364     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
365     HandleScope handleScope(jsRuntime_);
366     napi_value result = CallOnConnect(want);
367     napi_env env = jsRuntime_.GetNapiEnv();
368     auto remoteObj = GetNativeRemoteObject(env, result);
369     if (remoteObj == nullptr) {
370         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null remoteObj");
371     }
372     return remoteObj;
373 }
374 
OnConnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> * callbackInfo,bool & isAsyncCallback)375 sptr<IRemoteObject> JsServiceExtension::OnConnect(const AAFwk::Want &want,
376     AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *callbackInfo, bool &isAsyncCallback)
377 {
378     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
379     HandleScope handleScope(jsRuntime_);
380     napi_env env = jsRuntime_.GetNapiEnv();
381     napi_value result = CallOnConnect(want);
382     bool isPromise = CheckPromise(result);
383     if (!isPromise) {
384         isAsyncCallback = false;
385         sptr<IRemoteObject> remoteObj = GetNativeRemoteObject(env, result);
386         if (remoteObj == nullptr) {
387             TAG_LOGE(AAFwkTag::SERVICE_EXT, "null remoteObj");
388         }
389         return remoteObj;
390     }
391 
392     bool callResult = false;
393     do {
394         if (!CheckTypeForNapiValue(env, result, napi_object)) {
395             TAG_LOGE(AAFwkTag::SERVICE_EXT, "convert value error");
396             break;
397         }
398         napi_value then = nullptr;
399         napi_get_named_property(env, result, "then", &then);
400         if (then == nullptr) {
401             TAG_LOGE(AAFwkTag::SERVICE_EXT, "null then");
402             break;
403         }
404         bool isCallable = false;
405         napi_is_callable(env, then, &isCallable);
406         if (!isCallable) {
407             TAG_LOGE(AAFwkTag::SERVICE_EXT, "not callable property then");
408             break;
409         }
410         napi_value promiseCallback = nullptr;
411         napi_create_function(env, "promiseCallback", strlen("promiseCallback"),
412             OnConnectPromiseCallback, callbackInfo, &promiseCallback);
413         napi_value argv[1] = { promiseCallback };
414         napi_call_function(env, result, then, 1, argv, nullptr);
415         callResult = true;
416     } while (false);
417 
418     if (!callResult) {
419         TAG_LOGE(AAFwkTag::SERVICE_EXT, "call promise error");
420         isAsyncCallback = false;
421     } else {
422         isAsyncCallback = true;
423     }
424     return nullptr;
425 }
426 
OnDisconnect(const AAFwk::Want & want)427 void JsServiceExtension::OnDisconnect(const AAFwk::Want &want)
428 {
429     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
430     HandleScope handleScope(jsRuntime_);
431     Extension::OnDisconnect(want);
432     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
433     CallOnDisconnect(want, false);
434     TAG_LOGD(AAFwkTag::SERVICE_EXT, "end");
435 }
436 
OnDisconnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)437 void JsServiceExtension::OnDisconnect(const AAFwk::Want &want,
438     AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
439 {
440     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
441     HandleScope handleScope(jsRuntime_);
442     Extension::OnDisconnect(want);
443     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
444     napi_value result = CallOnDisconnect(want, true);
445     bool isPromise = CheckPromise(result);
446     if (!isPromise) {
447         isAsyncCallback = false;
448         return;
449     }
450     bool callResult = CallPromise(result, callbackInfo);
451     if (!callResult) {
452         TAG_LOGE(AAFwkTag::SERVICE_EXT, "call promise error");
453         isAsyncCallback = false;
454     } else {
455         isAsyncCallback = true;
456     }
457 
458     TAG_LOGD(AAFwkTag::SERVICE_EXT, "end");
459 }
460 
OnCommand(const AAFwk::Want & want,bool restart,int startId)461 void JsServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
462 {
463     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
464     Extension::OnCommand(want, restart, startId);
465     TAG_LOGD(AAFwkTag::SERVICE_EXT, "restart=%{public}s,startId=%{public}d",
466         restart ? "true" : "false",
467         startId);
468     // wrap want
469     HandleScope handleScope(jsRuntime_);
470     napi_env env = jsRuntime_.GetNapiEnv();
471     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
472     // wrap startId
473     napi_value napiStartId = nullptr;
474     napi_create_int32(env, startId, &napiStartId);
475     napi_value argv[] = {napiWant, napiStartId};
476     CallObjectMethod("onRequest", argv, ARGC_TWO);
477     TAG_LOGD(AAFwkTag::SERVICE_EXT, "ok");
478 }
479 
HandleInsightIntent(const AAFwk::Want & want)480 bool JsServiceExtension::HandleInsightIntent(const AAFwk::Want &want)
481 {
482     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
483     auto callback = std::make_unique<InsightIntentExecutorAsyncCallback>();
484     callback.reset(InsightIntentExecutorAsyncCallback::Create());
485     if (callback == nullptr) {
486         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null callback");
487         return false;
488     }
489     auto executeParam = std::make_shared<AppExecFwk::InsightIntentExecuteParam>();
490     bool ret = AppExecFwk::InsightIntentExecuteParam::GenerateFromWant(want, *executeParam);
491     if (!ret) {
492         TAG_LOGE(AAFwkTag::SERVICE_EXT, "Generate execute param failed");
493         InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback),
494             static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM));
495         return false;
496     }
497     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Insight bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s"
498         "insightIntentName: %{public}s, executeMode: %{public}d, intentId: %{public}" PRIu64 "",
499         executeParam->bundleName_.c_str(), executeParam->moduleName_.c_str(), executeParam->abilityName_.c_str(),
500         executeParam->insightIntentName_.c_str(), executeParam->executeMode_, executeParam->insightIntentId_);
501     auto asyncCallback = [weak = weak_from_this(), intentId = executeParam->insightIntentId_]
502         (AppExecFwk::InsightIntentExecuteResult result) {
503         TAG_LOGD(AAFwkTag::SERVICE_EXT, "intentId %{public}" PRIu64"", intentId);
504         auto extension = weak.lock();
505         if (extension == nullptr) {
506             TAG_LOGE(AAFwkTag::SERVICE_EXT, "null extension");
507             return;
508         }
509         auto ret = extension->OnInsightIntentExecuteDone(intentId, result);
510         if (!ret) {
511             TAG_LOGE(AAFwkTag::SERVICE_EXT, "OnInsightIntentExecuteDone failed");
512         }
513     };
514     callback->Push(asyncCallback);
515     InsightIntentExecutorInfo executorInfo;
516     ret = GetInsightIntentExecutorInfo(want, executeParam, executorInfo);
517     if (!ret) {
518         TAG_LOGE(AAFwkTag::SERVICE_EXT, "Get Intent executor failed");
519         InsightIntentExecutorMgr::TriggerCallbackInner(std::move(callback),
520             static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INVALID_PARAM));
521         return false;
522     }
523     ret = DelayedSingleton<InsightIntentExecutorMgr>::GetInstance()->ExecuteInsightIntent(
524         jsRuntime_, executorInfo, std::move(callback));
525     if (!ret) {
526         TAG_LOGE(AAFwkTag::SERVICE_EXT, "Execute insight intent failed");
527         return false;
528     }
529     return true;
530 }
531 
GetInsightIntentExecutorInfo(const Want & want,const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & executeParam,InsightIntentExecutorInfo & executorInfo)532 bool JsServiceExtension::GetInsightIntentExecutorInfo(const Want &want,
533     const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> &executeParam,
534     InsightIntentExecutorInfo &executorInfo)
535 {
536     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
537     auto context = GetContext();
538     if (executeParam == nullptr || context == nullptr || abilityInfo_ == nullptr) {
539         TAG_LOGE(AAFwkTag::SERVICE_EXT, "Param invalid");
540         return false;
541     }
542 
543     const WantParams &wantParams = want.GetParams();
544     executorInfo.srcEntry = wantParams.GetStringParam(AppExecFwk::INSIGHT_INTENT_SRC_ENTRY);
545     executorInfo.hapPath = abilityInfo_->hapPath;
546     executorInfo.esmodule = abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE;
547     executorInfo.token = context->GetToken();
548     executorInfo.executeParam = executeParam;
549     return true;
550 }
551 
OnInsightIntentExecuteDone(uint64_t intentId,const AppExecFwk::InsightIntentExecuteResult & result)552 bool JsServiceExtension::OnInsightIntentExecuteDone(uint64_t intentId,
553     const AppExecFwk::InsightIntentExecuteResult &result)
554 {
555     TAG_LOGI(AAFwkTag::SERVICE_EXT, "Notify execute done, intentId %{public}" PRIu64"", intentId);
556     auto context = GetContext();
557     if (context == nullptr) {
558         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
559         return false;
560     }
561     auto token = context->GetToken();
562     if (token == nullptr) {
563         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null token");
564         return false;
565     }
566     auto ret = AAFwk::AbilityManagerClient::GetInstance()->ExecuteInsightIntentDone(token, intentId, result);
567     if (ret != ERR_OK) {
568         TAG_LOGE(AAFwkTag::SERVICE_EXT, "Notify execute done failed");
569         return false;
570     }
571     return true;
572 }
573 
CallObjectMethod(const char * name,napi_value const * argv,size_t argc)574 napi_value JsServiceExtension::CallObjectMethod(const char* name, napi_value const* argv, size_t argc)
575 {
576     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, std::string("CallObjectMethod:") + name);
577     TAG_LOGD(AAFwkTag::SERVICE_EXT, "name:%{public}s", name);
578 
579     if (!jsObj_) {
580         TAG_LOGW(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension.js");
581         return nullptr;
582     }
583 
584     HandleScope handleScope(jsRuntime_);
585     napi_env env = jsRuntime_.GetNapiEnv();
586 
587     napi_value obj = jsObj_->GetNapiValue();
588     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
589         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get ServiceExtension obj failed");
590         return nullptr;
591     }
592 
593     napi_value method = nullptr;
594     napi_get_named_property(env, obj, name, &method);
595     if (!CheckTypeForNapiValue(env, method, napi_function)) {
596         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get '%{public}s' from ServiceExtension obj failed", name);
597         return nullptr;
598     }
599     TAG_LOGI(AAFwkTag::SERVICE_EXT, "CallFunction(%{public}s) ok", name);
600     napi_value result = nullptr;
601     napi_status status = napi_call_function(env, obj, method, argc, argv, &result);
602     if (status != napi_ok) {
603         TAG_LOGE(AAFwkTag::SERVICE_EXT, "call js func failed: %{public}d", status);
604     }
605     return result;
606 }
607 
GetSrcPath(std::string & srcPath)608 void JsServiceExtension::GetSrcPath(std::string &srcPath)
609 {
610     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
611     if (!Extension::abilityInfo_->isModuleJson) {
612         /* temporary compatibility api8 + config.json */
613         srcPath.append(Extension::abilityInfo_->package);
614         srcPath.append("/assets/js/");
615         if (!Extension::abilityInfo_->srcPath.empty()) {
616             srcPath.append(Extension::abilityInfo_->srcPath);
617         }
618         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
619         return;
620     }
621 
622     if (!Extension::abilityInfo_->srcEntrance.empty()) {
623         srcPath.append(Extension::abilityInfo_->moduleName + "/");
624         srcPath.append(Extension::abilityInfo_->srcEntrance);
625         srcPath.erase(srcPath.rfind('.'));
626         srcPath.append(".abc");
627     }
628 }
629 
CallOnConnect(const AAFwk::Want & want)630 napi_value JsServiceExtension::CallOnConnect(const AAFwk::Want &want)
631 {
632     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
633     Extension::OnConnect(want);
634     TAG_LOGD(AAFwkTag::SERVICE_EXT, "call");
635     napi_env env = jsRuntime_.GetNapiEnv();
636     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
637     napi_value argv[] = {napiWant};
638     if (!jsObj_) {
639         TAG_LOGW(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension.js");
640         return nullptr;
641     }
642 
643     napi_value obj = jsObj_->GetNapiValue();
644     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
645         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get ServiceExtension obj failed");
646         return nullptr;
647     }
648 
649     napi_value method = nullptr;
650     napi_get_named_property(env, obj, "onConnect", &method);
651     if (method == nullptr) {
652         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null method");
653         return nullptr;
654     }
655     napi_value remoteNative = nullptr;
656     TAG_LOGI(AAFwkTag::SERVICE_EXT, "Call onConnect");
657     napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, &remoteNative);
658     if (status != napi_ok) {
659         TAG_LOGE(AAFwkTag::SERVICE_EXT, "call js func failed %{public}d", status);
660     }
661     if (remoteNative == nullptr) {
662         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null remoteNative");
663     }
664     TAG_LOGD(AAFwkTag::SERVICE_EXT, "ok");
665     return remoteNative;
666 }
667 
CallOnDisconnect(const AAFwk::Want & want,bool withResult)668 napi_value JsServiceExtension::CallOnDisconnect(const AAFwk::Want &want, bool withResult)
669 {
670     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
671     HandleEscape handleEscape(jsRuntime_);
672     napi_env env = jsRuntime_.GetNapiEnv();
673     napi_value napiWant = OHOS::AppExecFwk::WrapWant(env, want);
674     napi_value argv[] = { napiWant };
675     if (!jsObj_) {
676         TAG_LOGW(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension.js");
677         return nullptr;
678     }
679 
680     napi_value obj = jsObj_->GetNapiValue();
681     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
682         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get ServiceExtension obj failed");
683         return nullptr;
684     }
685 
686     napi_value method = nullptr;
687     napi_get_named_property(env, obj, "onDisconnect", &method);
688     if (method == nullptr) {
689         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null method");
690         return nullptr;
691     }
692     TAG_LOGI(AAFwkTag::SERVICE_EXT, "Call onDisconnect");
693     if (withResult) {
694         napi_value result = nullptr;
695         napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, &result);
696         if (status != napi_ok) {
697             TAG_LOGE(AAFwkTag::SERVICE_EXT, "call js func failed %{public}d", status);
698         }
699         return handleEscape.Escape(result);
700     } else {
701         napi_status status = napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr);
702         if (status != napi_ok) {
703             TAG_LOGE(AAFwkTag::SERVICE_EXT, "call js func failed %{public}d", status);
704         }
705         return nullptr;
706     }
707 }
708 
CheckPromise(napi_value result)709 bool JsServiceExtension::CheckPromise(napi_value result)
710 {
711     if (result == nullptr) {
712         TAG_LOGD(AAFwkTag::SERVICE_EXT, "null result");
713         return false;
714     }
715     napi_env env = jsRuntime_.GetNapiEnv();
716     bool isPromise = false;
717     napi_is_promise(env, result, &isPromise);
718     if (!isPromise) {
719         TAG_LOGD(AAFwkTag::SERVICE_EXT, "result not promise");
720         return false;
721     }
722     return true;
723 }
724 
CallPromise(napi_value result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)725 bool JsServiceExtension::CallPromise(napi_value result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
726 {
727     napi_env env = jsRuntime_.GetNapiEnv();
728     if (!CheckTypeForNapiValue(env, result, napi_object)) {
729         TAG_LOGE(AAFwkTag::SERVICE_EXT, "convert value error");
730         return false;
731     }
732     napi_value then = nullptr;
733     napi_get_named_property(env, result, "then", &then);
734     if (then == nullptr) {
735         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null then");
736         return false;
737     }
738     bool isCallable = false;
739     napi_is_callable(env, then, &isCallable);
740     if (!isCallable) {
741         TAG_LOGE(AAFwkTag::SERVICE_EXT, "not callable property then");
742         return false;
743     }
744     HandleScope handleScope(jsRuntime_);
745     napi_value promiseCallback = nullptr;
746     napi_create_function(env, "promiseCallback", strlen("promiseCallback"), PromiseCallback,
747         callbackInfo, &promiseCallback);
748     napi_value argv[1] = { promiseCallback };
749     napi_call_function(env, result, then, 1, argv, nullptr);
750     TAG_LOGD(AAFwkTag::SERVICE_EXT, "end");
751     return true;
752 }
753 
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)754 void JsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
755 {
756     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
757     ServiceExtension::OnConfigurationUpdated(configuration);
758     TAG_LOGD(AAFwkTag::SERVICE_EXT, "call");
759     auto context = GetContext();
760     if (context == nullptr) {
761         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
762         return;
763     }
764 
765     auto contextConfig = context->GetConfiguration();
766     if (contextConfig != nullptr) {
767         TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
768         std::vector<std::string> changeKeyV;
769         contextConfig->CompareDifferent(changeKeyV, configuration);
770         if (!changeKeyV.empty()) {
771             contextConfig->Merge(changeKeyV, configuration);
772         }
773         TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after merge: %{public}s", contextConfig->GetName().c_str());
774     }
775     ConfigurationUpdated();
776 }
777 
ConfigurationUpdated()778 void JsServiceExtension::ConfigurationUpdated()
779 {
780     TAG_LOGD(AAFwkTag::SERVICE_EXT, "called");
781     HandleScope handleScope(jsRuntime_);
782     napi_env env = jsRuntime_.GetNapiEnv();
783 
784     // Notify extension context
785     auto fullConfig = GetContext()->GetConfiguration();
786     if (!fullConfig) {
787         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null configuration");
788         return;
789     }
790 
791     napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(env, *fullConfig);
792     CallObjectMethod("onConfigurationUpdated", &napiConfiguration, ARGC_ONE);
793     CallObjectMethod("onConfigurationUpdate", &napiConfiguration, ARGC_ONE);
794     JsExtensionContext::ConfigurationUpdated(env, shellContextRef_, fullConfig);
795 }
796 
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)797 void JsServiceExtension::Dump(const std::vector<std::string> &params, std::vector<std::string> &info)
798 {
799     Extension::Dump(params, info);
800     TAG_LOGD(AAFwkTag::SERVICE_EXT, "call");
801     HandleScope handleScope(jsRuntime_);
802     napi_env env = jsRuntime_.GetNapiEnv();
803     // create js array object of params
804     napi_value argv[] = { CreateNativeArray(env, params) };
805 
806     if (!jsObj_) {
807         TAG_LOGW(AAFwkTag::SERVICE_EXT, "Not found ServiceExtension.js");
808         return;
809     }
810 
811     napi_value obj = jsObj_->GetNapiValue();
812     if (!CheckTypeForNapiValue(env, obj, napi_object)) {
813         TAG_LOGE(AAFwkTag::SERVICE_EXT, "get ServiceExtension obj failed");
814         return;
815     }
816 
817     napi_value method = nullptr;
818     napi_get_named_property(env, obj, "onDump", &method);
819     if (!CheckTypeForNapiValue(env, method, napi_function)) {
820         method = nullptr;
821         napi_get_named_property(env, obj, "dump", &method);
822         if (!CheckTypeForNapiValue(env, method, napi_function)) {
823             TAG_LOGE(AAFwkTag::SERVICE_EXT, "get onConnect from ServiceExtension obj failed");
824             return;
825         }
826     }
827     TAG_LOGD(AAFwkTag::SERVICE_EXT, "success");
828     napi_value dumpInfo = nullptr;
829     napi_call_function(env, obj, method, ARGC_ONE, argv, &dumpInfo);
830     if (dumpInfo == nullptr) {
831         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null dumpInfo");
832         return;
833     }
834     uint32_t len = 0;
835     napi_get_array_length(env, dumpInfo, &len);
836     for (uint32_t i = 0; i < len; i++) {
837         std::string dumpInfoStr;
838         napi_value element = nullptr;
839         napi_get_element(env, dumpInfo, i, &element);
840         if (!ConvertFromJsValue(env, element, dumpInfoStr)) {
841             TAG_LOGE(AAFwkTag::SERVICE_EXT, "Parse dumpInfoStr failed");
842             return;
843         }
844         info.push_back(dumpInfoStr);
845     }
846     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Dump info size: %{public}zu", info.size());
847 }
848 
849 #ifdef SUPPORT_GRAPHICS
OnCreate(Rosen::DisplayId displayId)850 void JsServiceExtension::OnCreate(Rosen::DisplayId displayId)
851 {
852     TAG_LOGD(AAFwkTag::SERVICE_EXT, "enter");
853 }
854 
OnDestroy(Rosen::DisplayId displayId)855 void JsServiceExtension::OnDestroy(Rosen::DisplayId displayId)
856 {
857     TAG_LOGD(AAFwkTag::SERVICE_EXT, "exit");
858 }
859 
OnDisplayInfoChange(const sptr<IRemoteObject> & token,Rosen::DisplayId displayId,float density,Rosen::DisplayOrientation orientation)860 void JsServiceExtension::OnDisplayInfoChange(const sptr<IRemoteObject>& token, Rosen::DisplayId displayId,
861     float density, Rosen::DisplayOrientation orientation)
862 {
863     TAG_LOGI(AAFwkTag::SERVICE_EXT, "displayId: %{public}" PRIu64, displayId);
864     auto context = GetContext();
865     if (context == nullptr) {
866         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
867         return;
868     }
869 
870     auto contextConfig = context->GetConfiguration();
871     if (contextConfig == nullptr) {
872         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null contextConfig");
873         return;
874     }
875 
876     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
877     bool configChanged = false;
878     auto configUtils = std::make_shared<ConfigurationUtils>();
879     configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
880     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
881 
882     if (configChanged) {
883         auto jsServiceExtension = std::static_pointer_cast<JsServiceExtension>(shared_from_this());
884         auto task = [jsServiceExtension]() {
885             if (jsServiceExtension) {
886                 jsServiceExtension->ConfigurationUpdated();
887             }
888         };
889         if (handler_ != nullptr) {
890             handler_->PostTask(task, "JsServiceExtension:OnChange");
891         }
892     }
893 
894     TAG_LOGD(AAFwkTag::SERVICE_EXT, "finished");
895 }
896 
OnChange(Rosen::DisplayId displayId)897 void JsServiceExtension::OnChange(Rosen::DisplayId displayId)
898 {
899     TAG_LOGD(AAFwkTag::SERVICE_EXT, "displayId: %{public}" PRIu64"", displayId);
900     auto context = GetContext();
901     if (context == nullptr) {
902         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null context");
903         return;
904     }
905 
906     auto contextConfig = context->GetConfiguration();
907     if (contextConfig == nullptr) {
908         TAG_LOGE(AAFwkTag::SERVICE_EXT, "null contextConfig");
909         return;
910     }
911 
912     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump: %{public}s", contextConfig->GetName().c_str());
913     bool configChanged = false;
914     auto configUtils = std::make_shared<ConfigurationUtils>();
915     configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
916     TAG_LOGD(AAFwkTag::SERVICE_EXT, "Config dump after update: %{public}s", contextConfig->GetName().c_str());
917 
918     if (configChanged) {
919         auto jsServiceExtension = std::static_pointer_cast<JsServiceExtension>(shared_from_this());
920         auto task = [jsServiceExtension]() {
921             if (jsServiceExtension) {
922                 jsServiceExtension->ConfigurationUpdated();
923             }
924         };
925         if (handler_ != nullptr) {
926             handler_->PostTask(task, "JsServiceExtension:OnChange");
927         }
928     }
929 
930     TAG_LOGD(AAFwkTag::SERVICE_EXT, "finished");
931 }
932 #endif
933 } // AbilityRuntime
934 } // OHOS
935