• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_service_extension.h"
17 
18 #include "ability_business_error.h"
19 #include "ability_handler.h"
20 #include "ability_info.h"
21 #include "ability_manager_client.h"
22 #include "configuration_utils.h"
23 #include "display_util.h"
24 #include "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> &params, 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