• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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_handler.h"
19 #include "ability_info.h"
20 #include "configuration_utils.h"
21 #include "hitrace_meter.h"
22 #include "hilog_wrapper.h"
23 #include "js_extension_common.h"
24 #include "js_extension_context.h"
25 #include "js_runtime.h"
26 #include "js_runtime_utils.h"
27 #include "js_service_extension_context.h"
28 #include "napi/native_api.h"
29 #include "napi/native_node_api.h"
30 #include "napi_common_configuration.h"
31 #include "napi_common_want.h"
32 #include "napi_remote_object.h"
33 #ifdef SUPPORT_GRAPHICS
34 #include "iservice_registry.h"
35 #include "system_ability_definition.h"
36 #include "window_scene.h"
37 #endif
38 
39 namespace OHOS {
40 namespace AbilityRuntime {
41 namespace {
42 constexpr size_t ARGC_ONE = 1;
43 constexpr size_t ARGC_TWO = 2;
44 }
45 
46 namespace {
PromiseCallback(NativeEngine * engine,NativeCallbackInfo * info)47 NativeValue *PromiseCallback(NativeEngine *engine, NativeCallbackInfo *info)
48 {
49     if (info == nullptr || info->functionInfo == nullptr || info->functionInfo->data == nullptr) {
50         HILOG_ERROR("PromiseCallback, Invalid input info.");
51         return nullptr;
52     }
53     void *data = info->functionInfo->data;
54     auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<> *>(data);
55     callbackInfo->Call();
56     AppExecFwk::AbilityTransactionCallbackInfo<>::Destroy(callbackInfo);
57     info->functionInfo->data = nullptr;
58     return nullptr;
59 }
60 
OnConnectPromiseCallback(NativeEngine * engine,NativeCallbackInfo * info)61 NativeValue *OnConnectPromiseCallback(NativeEngine *engine, NativeCallbackInfo *info)
62 {
63     if (info == nullptr || info->functionInfo == nullptr || info->functionInfo->data == nullptr) {
64         HILOG_ERROR("PromiseCallback, Invalid input info.");
65         return nullptr;
66     }
67     void *data = info->functionInfo->data;
68     auto *callbackInfo = static_cast<AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *>(data);
69     sptr<IRemoteObject> service = nullptr;
70     if (info->argc > 0) {
71         service = NAPI_ohos_rpc_getNativeRemoteObject(reinterpret_cast<napi_env>(engine),
72             reinterpret_cast<napi_value>(info->argv[0]));
73     }
74     callbackInfo->Call(service);
75     AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>>::Destroy(callbackInfo);
76     info->functionInfo->data = nullptr;
77     return nullptr;
78 }
79 }
80 
81 using namespace OHOS::AppExecFwk;
82 
AttachServiceExtensionContext(NativeEngine * engine,void * value,void *)83 NativeValue *AttachServiceExtensionContext(NativeEngine *engine, void *value, void *)
84 {
85     HILOG_INFO("call");
86     if (value == nullptr) {
87         HILOG_WARN("invalid parameter.");
88         return nullptr;
89     }
90     auto ptr = reinterpret_cast<std::weak_ptr<ServiceExtensionContext> *>(value)->lock();
91     if (ptr == nullptr) {
92         HILOG_WARN("invalid context.");
93         return nullptr;
94     }
95     NativeValue *object = CreateJsServiceExtensionContext(*engine, ptr);
96     auto contextObj = JsRuntime::LoadSystemModuleByEngine(engine,
97         "application.ServiceExtensionContext", &object, 1)->Get();
98     NativeObject *nObject = ConvertNativeValueTo<NativeObject>(contextObj);
99     nObject->ConvertToNativeBindingObject(engine, DetachCallbackFunc, AttachServiceExtensionContext,
100         value, nullptr);
101     auto workContext = new (std::nothrow) std::weak_ptr<ServiceExtensionContext>(ptr);
102     nObject->SetNativePointer(workContext,
103         [](NativeEngine *, void *data, void *) {
104             HILOG_INFO("Finalizer for weak_ptr service extension context is called");
105             delete static_cast<std::weak_ptr<ServiceExtensionContext> *>(data);
106         }, nullptr);
107     return contextObj;
108 }
109 
Create(const std::unique_ptr<Runtime> & runtime)110 JsServiceExtension* JsServiceExtension::Create(const std::unique_ptr<Runtime>& runtime)
111 {
112     return new JsServiceExtension(static_cast<JsRuntime&>(*runtime));
113 }
114 
JsServiceExtension(JsRuntime & jsRuntime)115 JsServiceExtension::JsServiceExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsServiceExtension()116 JsServiceExtension::~JsServiceExtension()
117 {
118     HILOG_DEBUG("Js service extension destructor.");
119     auto context = GetContext();
120     if (context) {
121         context->Unbind();
122     }
123 
124     jsRuntime_.FreeNativeReference(std::move(jsObj_));
125     jsRuntime_.FreeNativeReference(std::move(shellContextRef_));
126 }
127 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)128 void JsServiceExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
129     const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
130     const sptr<IRemoteObject> &token)
131 {
132     ServiceExtension::Init(record, application, handler, token);
133     std::string srcPath = "";
134     GetSrcPath(srcPath);
135     if (srcPath.empty()) {
136         HILOG_ERROR("Failed to get srcPath");
137         return;
138     }
139 
140     std::string moduleName(Extension::abilityInfo_->moduleName);
141     moduleName.append("::").append(abilityInfo_->name);
142     HILOG_DEBUG("JsServiceExtension::Init moduleName:%{public}s,srcPath:%{public}s.",
143         moduleName.c_str(), srcPath.c_str());
144     HandleScope handleScope(jsRuntime_);
145     auto& engine = jsRuntime_.GetNativeEngine();
146 
147     jsObj_ = jsRuntime_.LoadModule(
148         moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == CompileMode::ES_MODULE);
149     if (jsObj_ == nullptr) {
150         HILOG_ERROR("Failed to get jsObj_");
151         return;
152     }
153 
154     HILOG_INFO("JsServiceExtension::Init ConvertNativeValueTo.");
155     NativeObject* obj = ConvertNativeValueTo<NativeObject>(jsObj_->Get());
156     if (obj == nullptr) {
157         HILOG_ERROR("Failed to get JsServiceExtension object");
158         return;
159     }
160 
161     BindContext(engine, obj);
162 
163     SetExtensionCommon(JsExtensionCommon::Create(jsRuntime_, static_cast<NativeReference&>(*jsObj_), shellContextRef_));
164 
165     handler_ = handler;
166     auto context = GetContext();
167     auto appContext = Context::GetApplicationContext();
168     if (context != nullptr && appContext != nullptr) {
169         auto appConfig = appContext->GetConfiguration();
170         if (appConfig != nullptr) {
171             HILOG_DEBUG("Original config dump: %{public}s", appConfig->GetName().c_str());
172             context->SetConfiguration(std::make_shared<Configuration>(*appConfig));
173         }
174     }
175     ListenWMS();
176 }
177 
ListenWMS()178 void JsServiceExtension::ListenWMS()
179 {
180 #ifdef SUPPORT_GRAPHICS
181     HILOG_INFO("RegisterDisplayListener");
182     auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
183     if (abilityManager == nullptr) {
184         HILOG_ERROR("Failed to get SaMgr.");
185         return;
186     }
187     auto jsServiceExtension = std::static_pointer_cast<JsServiceExtension>(shared_from_this());
188     displayListener_ = new JsServiceExtensionDisplayListener(jsServiceExtension);
189     sptr<ISystemAbilityStatusChange> listener = new SystemAbilityStatusChangeListener(displayListener_);
190     auto ret = abilityManager->SubscribeSystemAbility(WINDOW_MANAGER_SERVICE_ID, listener);
191     if (ret != 0) {
192         HILOG_ERROR("subscribe system ability failed, ret = %{public}d.", ret);
193     }
194 #endif
195 }
196 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)197 void JsServiceExtension::SystemAbilityStatusChangeListener::OnAddSystemAbility(int32_t systemAbilityId,
198     const std::string& deviceId)
199 {
200     HILOG_INFO("systemAbilityId: %{public}d add", systemAbilityId);
201     if (systemAbilityId == WINDOW_MANAGER_SERVICE_ID) {
202         Rosen::DisplayManager::GetInstance().RegisterDisplayListener(tmpDisplayListener_);
203     }
204 }
205 
BindContext(NativeEngine & engine,NativeObject * obj)206 void JsServiceExtension::BindContext(NativeEngine& engine, NativeObject* obj)
207 {
208     auto context = GetContext();
209     if (context == nullptr) {
210         HILOG_ERROR("Failed to get context");
211         return;
212     }
213     HILOG_INFO("call");
214     NativeValue* contextObj = CreateJsServiceExtensionContext(engine, context);
215     shellContextRef_ = JsRuntime::LoadSystemModuleByEngine(&engine, "application.ServiceExtensionContext",
216         &contextObj, ARGC_ONE);
217     contextObj = shellContextRef_->Get();
218     NativeObject *nativeObj = ConvertNativeValueTo<NativeObject>(contextObj);
219     if (nativeObj == nullptr) {
220         HILOG_ERROR("Failed to get context native object");
221         return;
222     }
223     auto workContext = new (std::nothrow) std::weak_ptr<ServiceExtensionContext>(context);
224     nativeObj->ConvertToNativeBindingObject(&engine, DetachCallbackFunc, AttachServiceExtensionContext,
225         workContext, nullptr);
226     HILOG_INFO("JsServiceExtension::Init Bind.");
227     context->Bind(jsRuntime_, shellContextRef_.get());
228     HILOG_INFO("JsServiceExtension::SetProperty.");
229     obj->SetProperty("context", contextObj);
230     HILOG_INFO("Set service extension context");
231 
232     nativeObj->SetNativePointer(workContext,
233         [](NativeEngine*, void* data, void*) {
234             HILOG_INFO("Finalizer for weak_ptr service extension context is called");
235             delete static_cast<std::weak_ptr<ServiceExtensionContext>*>(data);
236         }, nullptr);
237 
238     HILOG_INFO("JsServiceExtension::Init end.");
239 }
240 
OnStart(const AAFwk::Want & want)241 void JsServiceExtension::OnStart(const AAFwk::Want &want)
242 {
243     Extension::OnStart(want);
244     HILOG_INFO("call");
245 
246     auto context = GetContext();
247     if (context != nullptr) {
248         int displayId = want.GetIntParam(Want::PARAM_RESV_DISPLAY_ID, Rosen::WindowScene::DEFAULT_DISPLAY_ID);
249         auto configUtils = std::make_shared<ConfigurationUtils>();
250         configUtils->InitDisplayConfig(displayId, context->GetConfiguration(), context->GetResourceManager());
251     }
252 
253     HandleScope handleScope(jsRuntime_);
254     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
255 
256     // display config has changed, need update context.config
257     JsExtensionContext::ConfigurationUpdated(nativeEngine, shellContextRef_, context->GetConfiguration());
258 
259     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
260     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
261     NativeValue* argv[] = {nativeWant};
262     CallObjectMethod("onCreate", argv, ARGC_ONE);
263     HILOG_INFO("ok");
264 }
265 
OnStop()266 void JsServiceExtension::OnStop()
267 {
268     ServiceExtension::OnStop();
269     HILOG_INFO("call");
270     CallObjectMethod("onDestroy");
271     bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
272     if (ret) {
273         ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
274         HILOG_INFO("The service extension connection is not disconnected.");
275     }
276     Rosen::DisplayManager::GetInstance().UnregisterDisplayListener(displayListener_);
277     HILOG_INFO("ok");
278 }
279 
OnConnect(const AAFwk::Want & want)280 sptr<IRemoteObject> JsServiceExtension::OnConnect(const AAFwk::Want &want)
281 {
282     HandleScope handleScope(jsRuntime_);
283     NativeValue *result = CallOnConnect(want);
284     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
285     auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(
286         reinterpret_cast<napi_env>(nativeEngine), reinterpret_cast<napi_value>(result));
287     if (remoteObj == nullptr) {
288         HILOG_ERROR("remoteObj nullptr.");
289     }
290     return remoteObj;
291 }
292 
OnConnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> * callbackInfo,bool & isAsyncCallback)293 sptr<IRemoteObject> JsServiceExtension::OnConnect(const AAFwk::Want &want,
294     AppExecFwk::AbilityTransactionCallbackInfo<sptr<IRemoteObject>> *callbackInfo, bool &isAsyncCallback)
295 {
296     HandleScope handleScope(jsRuntime_);
297     NativeEngine *nativeEngine = &jsRuntime_.GetNativeEngine();
298     NativeValue *result = CallOnConnect(want);
299     bool isPromise = CheckPromise(result);
300     if (!isPromise) {
301         isAsyncCallback = false;
302         sptr<IRemoteObject> remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(reinterpret_cast<napi_env>(nativeEngine),
303             reinterpret_cast<napi_value>(result));
304         if (remoteObj == nullptr) {
305             HILOG_ERROR("remoteObj nullptr.");
306         }
307         return remoteObj;
308     }
309 
310     bool callResult = false;
311     do {
312         auto *retObj = ConvertNativeValueTo<NativeObject>(result);
313         if (retObj == nullptr) {
314             HILOG_ERROR("CallPromise, Failed to convert native value to NativeObject.");
315             break;
316         }
317         NativeValue *then = retObj->GetProperty("then");
318         if (then == nullptr) {
319             HILOG_ERROR("CallPromise, Failed to get property: then.");
320             break;
321         }
322         if (!then->IsCallable()) {
323             HILOG_ERROR("CallPromise, property then is not callable.");
324             break;
325         }
326         auto promiseCallback = nativeEngine->CreateFunction("promiseCallback", strlen("promiseCallback"),
327             OnConnectPromiseCallback, callbackInfo);
328         NativeValue *argv[1] = { promiseCallback };
329         nativeEngine->CallFunction(result, then, argv, 1);
330         callResult = true;
331     } while (false);
332 
333     if (!callResult) {
334         HILOG_ERROR("Failed to call promise.");
335         isAsyncCallback = false;
336     } else {
337         isAsyncCallback = true;
338     }
339     return nullptr;
340 }
341 
OnDisconnect(const AAFwk::Want & want)342 void JsServiceExtension::OnDisconnect(const AAFwk::Want &want)
343 {
344     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
345     Extension::OnDisconnect(want);
346     HILOG_DEBUG("%{public}s begin.", __func__);
347     CallOnDisconnect(want, false);
348     HILOG_DEBUG("%{public}s end.", __func__);
349 }
350 
OnDisconnect(const AAFwk::Want & want,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo,bool & isAsyncCallback)351 void JsServiceExtension::OnDisconnect(const AAFwk::Want &want,
352     AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo, bool &isAsyncCallback)
353 {
354     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
355     Extension::OnDisconnect(want);
356     HILOG_DEBUG("%{public}s begin.", __func__);
357     NativeValue *result = CallOnDisconnect(want, true);
358     bool isPromise = CheckPromise(result);
359     if (!isPromise) {
360         isAsyncCallback = false;
361         return;
362     }
363     bool callResult = CallPromise(result, callbackInfo);
364     if (!callResult) {
365         HILOG_ERROR("Failed to call promise.");
366         isAsyncCallback = false;
367     } else {
368         isAsyncCallback = true;
369     }
370 
371     HILOG_DEBUG("%{public}s end.", __func__);
372 }
373 
OnCommand(const AAFwk::Want & want,bool restart,int startId)374 void JsServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
375 {
376     Extension::OnCommand(want, restart, startId);
377     HILOG_INFO("restart=%{public}s,startId=%{public}d.",
378         restart ? "true" : "false",
379         startId);
380     // wrap want
381     HandleScope handleScope(jsRuntime_);
382     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
383     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
384     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
385     // wrap startId
386     napi_value napiStartId = nullptr;
387     napi_create_int32(reinterpret_cast<napi_env>(nativeEngine), startId, &napiStartId);
388     NativeValue* nativeStartId = reinterpret_cast<NativeValue*>(napiStartId);
389     NativeValue* argv[] = {nativeWant, nativeStartId};
390     CallObjectMethod("onRequest", argv, ARGC_TWO);
391     HILOG_INFO("ok");
392 }
393 
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc)394 NativeValue* JsServiceExtension::CallObjectMethod(const char* name, NativeValue* const* argv, size_t argc)
395 {
396     HILOG_INFO("CallObjectMethod(%{public}s)", name);
397 
398     if (!jsObj_) {
399         HILOG_WARN("Not found ServiceExtension.js");
400         return nullptr;
401     }
402 
403     HandleScope handleScope(jsRuntime_);
404     auto& nativeEngine = jsRuntime_.GetNativeEngine();
405 
406     NativeValue* value = jsObj_->Get();
407     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
408     if (obj == nullptr) {
409         HILOG_ERROR("Failed to get ServiceExtension object");
410         return nullptr;
411     }
412 
413     NativeValue* method = obj->GetProperty(name);
414     if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) {
415         HILOG_ERROR("Failed to get '%{public}s' from ServiceExtension object", name);
416         return nullptr;
417     }
418     HILOG_INFO("CallFunction(%{public}s) ok", name);
419     return nativeEngine.CallFunction(value, method, argv, argc);
420 }
421 
GetSrcPath(std::string & srcPath)422 void JsServiceExtension::GetSrcPath(std::string &srcPath)
423 {
424     if (!Extension::abilityInfo_->isModuleJson) {
425         /* temporary compatibility api8 + config.json */
426         srcPath.append(Extension::abilityInfo_->package);
427         srcPath.append("/assets/js/");
428         if (!Extension::abilityInfo_->srcPath.empty()) {
429             srcPath.append(Extension::abilityInfo_->srcPath);
430         }
431         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
432         return;
433     }
434 
435     if (!Extension::abilityInfo_->srcEntrance.empty()) {
436         srcPath.append(Extension::abilityInfo_->moduleName + "/");
437         srcPath.append(Extension::abilityInfo_->srcEntrance);
438         srcPath.erase(srcPath.rfind('.'));
439         srcPath.append(".abc");
440     }
441 }
442 
CallOnConnect(const AAFwk::Want & want)443 NativeValue *JsServiceExtension::CallOnConnect(const AAFwk::Want &want)
444 {
445     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
446     Extension::OnConnect(want);
447     HILOG_DEBUG("call");
448     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
449     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
450     auto* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
451     NativeValue* argv[] = {nativeWant};
452     if (!jsObj_) {
453         HILOG_WARN("Not found ServiceExtension.js");
454         return nullptr;
455     }
456 
457     NativeValue* value = jsObj_->Get();
458     auto* obj = ConvertNativeValueTo<NativeObject>(value);
459     if (obj == nullptr) {
460         HILOG_ERROR("Failed to get ServiceExtension object");
461         return nullptr;
462     }
463 
464     NativeValue* method = obj->GetProperty("onConnect");
465     if (method == nullptr) {
466         HILOG_ERROR("Failed to get onConnect from ServiceExtension object");
467         return nullptr;
468     }
469     NativeValue* remoteNative = nativeEngine->CallFunction(value, method, argv, ARGC_ONE);
470     if (remoteNative == nullptr) {
471         HILOG_ERROR("remoteNative nullptr.");
472     }
473     HILOG_INFO("ok");
474     return remoteNative;
475 }
476 
CallOnDisconnect(const AAFwk::Want & want,bool withResult)477 NativeValue *JsServiceExtension::CallOnDisconnect(const AAFwk::Want &want, bool withResult)
478 {
479     HandleEscape handleEscape(jsRuntime_);
480     NativeEngine *nativeEngine = &jsRuntime_.GetNativeEngine();
481     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
482     NativeValue *nativeWant = reinterpret_cast<NativeValue *>(napiWant);
483     NativeValue *argv[] = { nativeWant };
484     if (!jsObj_) {
485         HILOG_WARN("Not found ServiceExtension.js");
486         return nullptr;
487     }
488 
489     NativeValue *value = jsObj_->Get();
490     NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
491     if (obj == nullptr) {
492         HILOG_ERROR("Failed to get ServiceExtension object");
493         return nullptr;
494     }
495 
496     NativeValue *method = obj->GetProperty("onDisconnect");
497     if (method == nullptr) {
498         HILOG_ERROR("Failed to get onDisconnect from ServiceExtension object");
499         return nullptr;
500     }
501 
502     if (withResult) {
503         return handleEscape.Escape(nativeEngine->CallFunction(value, method, argv, ARGC_ONE));
504     } else {
505         nativeEngine->CallFunction(value, method, argv, ARGC_ONE);
506         return nullptr;
507     }
508 }
509 
CheckPromise(NativeValue * result)510 bool JsServiceExtension::CheckPromise(NativeValue *result)
511 {
512     if (result == nullptr) {
513         HILOG_DEBUG("CheckPromise, result is null, no need to call promise.");
514         return false;
515     }
516     if (!result->IsPromise()) {
517         HILOG_DEBUG("CheckPromise, result is not promise, no need to call promise.");
518         return false;
519     }
520     return true;
521 }
522 
CallPromise(NativeValue * result,AppExecFwk::AbilityTransactionCallbackInfo<> * callbackInfo)523 bool JsServiceExtension::CallPromise(NativeValue *result, AppExecFwk::AbilityTransactionCallbackInfo<> *callbackInfo)
524 {
525     auto *retObj = ConvertNativeValueTo<NativeObject>(result);
526     if (retObj == nullptr) {
527         HILOG_ERROR("CallPromise, Failed to convert native value to NativeObject.");
528         return false;
529     }
530     NativeValue *then = retObj->GetProperty("then");
531     if (then == nullptr) {
532         HILOG_ERROR("CallPromise, Failed to get property: then.");
533         return false;
534     }
535     if (!then->IsCallable()) {
536         HILOG_ERROR("CallPromise, property then is not callable.");
537         return false;
538     }
539     HandleScope handleScope(jsRuntime_);
540     auto &nativeEngine = jsRuntime_.GetNativeEngine();
541     auto promiseCallback = nativeEngine.CreateFunction("promiseCallback", strlen("promiseCallback"), PromiseCallback,
542         callbackInfo);
543     NativeValue *argv[1] = { promiseCallback };
544     nativeEngine.CallFunction(result, then, argv, 1);
545     return true;
546 }
547 
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)548 void JsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
549 {
550     ServiceExtension::OnConfigurationUpdated(configuration);
551     HILOG_INFO("call");
552     auto context = GetContext();
553     if (context == nullptr) {
554         HILOG_ERROR("Context is invalid.");
555         return;
556     }
557 
558     auto contextConfig = context->GetConfiguration();
559     if (contextConfig != nullptr) {
560         HILOG_DEBUG("Config dump: %{public}s", contextConfig->GetName().c_str());
561         std::vector<std::string> changeKeyV;
562         contextConfig->CompareDifferent(changeKeyV, configuration);
563         if (!changeKeyV.empty()) {
564             contextConfig->Merge(changeKeyV, configuration);
565         }
566         HILOG_DEBUG("Config dump after merge: %{public}s", contextConfig->GetName().c_str());
567     }
568     ConfigurationUpdated();
569 }
570 
ConfigurationUpdated()571 void JsServiceExtension::ConfigurationUpdated()
572 {
573     HILOG_DEBUG("called.");
574     HandleScope handleScope(jsRuntime_);
575     auto& nativeEngine = jsRuntime_.GetNativeEngine();
576 
577     // Notify extension context
578     auto fullConfig = GetContext()->GetConfiguration();
579     if (!fullConfig) {
580         HILOG_ERROR("configuration is nullptr.");
581         return;
582     }
583 
584     napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(
585         reinterpret_cast<napi_env>(&nativeEngine), *fullConfig);
586     NativeValue* jsConfiguration = reinterpret_cast<NativeValue*>(napiConfiguration);
587     CallObjectMethod("onConfigurationUpdated", &jsConfiguration, ARGC_ONE);
588     CallObjectMethod("onConfigurationUpdate", &jsConfiguration, ARGC_ONE);
589     JsExtensionContext::ConfigurationUpdated(&nativeEngine, shellContextRef_, fullConfig);
590 }
591 
Dump(const std::vector<std::string> & params,std::vector<std::string> & info)592 void JsServiceExtension::Dump(const std::vector<std::string> &params, std::vector<std::string> &info)
593 {
594     Extension::Dump(params, info);
595     HILOG_INFO("call");
596     HandleScope handleScope(jsRuntime_);
597     auto& nativeEngine = jsRuntime_.GetNativeEngine();
598     // create js array object of params
599     NativeValue* arrayValue = nativeEngine.CreateArray(params.size());
600     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
601     uint32_t index = 0;
602     for (const auto &param : params) {
603         array->SetElement(index++, CreateJsValue(nativeEngine, param));
604     }
605     NativeValue* argv[] = { arrayValue };
606 
607     if (!jsObj_) {
608         HILOG_WARN("Not found ServiceExtension.js");
609         return;
610     }
611 
612     NativeValue* value = jsObj_->Get();
613     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
614     if (obj == nullptr) {
615         HILOG_ERROR("Failed to get ServiceExtension object");
616         return;
617     }
618 
619     NativeValue* method = obj->GetProperty("onDump");
620     if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) {
621         method = obj->GetProperty("dump");
622         if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) {
623             HILOG_ERROR("Failed to get onConnect from ServiceExtension object");
624             return;
625         }
626     }
627     HILOG_INFO("JsServiceExtension::CallFunction onConnect, success");
628     NativeValue* dumpInfo = nativeEngine.CallFunction(value, method, argv, ARGC_ONE);
629     if (dumpInfo == nullptr) {
630         HILOG_ERROR("dumpInfo nullptr.");
631         return;
632     }
633     NativeArray* dumpInfoNative = ConvertNativeValueTo<NativeArray>(dumpInfo);
634     if (dumpInfoNative == nullptr) {
635         HILOG_ERROR("dumpInfoNative nullptr.");
636         return;
637     }
638     for (uint32_t i = 0; i < dumpInfoNative->GetLength(); i++) {
639         std::string dumpInfoStr;
640         if (!ConvertFromJsValue(nativeEngine, dumpInfoNative->GetElement(i), dumpInfoStr)) {
641             HILOG_ERROR("Parse dumpInfoStr failed");
642             return;
643         }
644         info.push_back(dumpInfoStr);
645     }
646     HILOG_DEBUG("Dump info size: %{public}zu", info.size());
647 }
648 
649 #ifdef SUPPORT_GRAPHICS
OnCreate(Rosen::DisplayId displayId)650 void JsServiceExtension::OnCreate(Rosen::DisplayId displayId)
651 {
652     HILOG_DEBUG("OnCreate.");
653 }
654 
OnDestroy(Rosen::DisplayId displayId)655 void JsServiceExtension::OnDestroy(Rosen::DisplayId displayId)
656 {
657     HILOG_DEBUG("OnDestroy.");
658 }
659 
OnChange(Rosen::DisplayId displayId)660 void JsServiceExtension::OnChange(Rosen::DisplayId displayId)
661 {
662     HILOG_DEBUG("displayId: %{public}" PRIu64"", displayId);
663     auto context = GetContext();
664     if (context == nullptr) {
665         HILOG_ERROR("Context is invalid.");
666         return;
667     }
668 
669     auto contextConfig = context->GetConfiguration();
670     if (contextConfig == nullptr) {
671         HILOG_ERROR("Configuration is invalid.");
672         return;
673     }
674 
675     HILOG_DEBUG("Config dump: %{public}s", contextConfig->GetName().c_str());
676     bool configChanged = false;
677     auto configUtils = std::make_shared<ConfigurationUtils>();
678     configUtils->UpdateDisplayConfig(displayId, contextConfig, context->GetResourceManager(), configChanged);
679     HILOG_DEBUG("Config dump after update: %{public}s", contextConfig->GetName().c_str());
680 
681     if (configChanged) {
682         auto jsServiceExtension = std::static_pointer_cast<JsServiceExtension>(shared_from_this());
683         auto task = [jsServiceExtension]() {
684             if (jsServiceExtension) {
685                 jsServiceExtension->ConfigurationUpdated();
686             }
687         };
688         if (handler_ != nullptr) {
689             handler_->PostTask(task);
690         }
691     }
692 
693     HILOG_DEBUG("finished.");
694 }
695 #endif
696 } // AbilityRuntime
697 } // OHOS
698