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