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> ¶ms, 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