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