• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_wallpaper_extension_context.h"
17 
18 #include <cstdint>
19 
20 #include "hilog_wrapper.h"
21 #include "js_extension_context.h"
22 #include "js_data_struct_converter.h"
23 #include "js_runtime.h"
24 #include "js_runtime_utils.h"
25 #include "napi/native_api.h"
26 #include "napi_common_want.h"
27 #include "napi_common_util.h"
28 #include "napi_remote_object.h"
29 #include "napi_common_start_options.h"
30 #include "start_options.h"
31 
32 namespace OHOS {
33 namespace AbilityRuntime {
34 namespace {
35 constexpr int32_t INDEX_ZERO = 0;
36 constexpr int32_t INDEX_ONE = 1;
37 constexpr int32_t INDEX_TWO = 2;
38 constexpr int32_t ERROR_CODE_ONE = 1;
39 constexpr int32_t ERROR_CODE_TWO = 2;
40 constexpr size_t ARGC_ZERO = 0;
41 constexpr size_t ARGC_ONE = 1;
42 constexpr size_t ARGC_TWO = 2;
43 constexpr size_t ARGC_THREE = 3;
44 constexpr size_t ARGC_FOUR = 4;
45 
46 class JsWallpaperExtensionContext final {
47 public:
JsWallpaperExtensionContext(const std::shared_ptr<WallpaperExtensionContext> & context)48     explicit JsWallpaperExtensionContext(const std::shared_ptr<WallpaperExtensionContext>& context) : context_(context)
49     {
50     }
51     ~JsWallpaperExtensionContext() = default;
52 
Finalizer(NativeEngine * engine,void * data,void * hint)53     static void Finalizer(NativeEngine* engine, void* data, void* hint)
54     {
55         HILOG_INFO("JsAbilityContext::Finalizer is called");
56         std::unique_ptr<JsWallpaperExtensionContext>(static_cast<JsWallpaperExtensionContext*>(data));
57     }
58 
StartAbility(NativeEngine * engine,NativeCallbackInfo * info)59     static NativeValue* StartAbility(NativeEngine* engine, NativeCallbackInfo* info)
60     {
61         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
62         return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr;
63     }
64 
StartAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)65     static NativeValue* StartAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
66     {
67         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
68         return (me != nullptr) ? me->OnStartAbilityWithAccount(*engine, *info) : nullptr;
69     }
70 
ConnectAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)71     static NativeValue* ConnectAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
72     {
73         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
74         return (me != nullptr) ? me->OnConnectAbilityWithAccount(*engine, *info) : nullptr;
75     }
76 
TerminateAbility(NativeEngine * engine,NativeCallbackInfo * info)77     static NativeValue* TerminateAbility(NativeEngine* engine, NativeCallbackInfo* info)
78     {
79         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
80         return (me != nullptr) ? me->OnTerminateAbility(*engine, *info) : nullptr;
81     }
82 
ConnectAbility(NativeEngine * engine,NativeCallbackInfo * info)83     static NativeValue* ConnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
84     {
85         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
86         return (me != nullptr) ? me->OnConnectAbility(*engine, *info) : nullptr;
87     }
88 
DisconnectAbility(NativeEngine * engine,NativeCallbackInfo * info)89     static NativeValue* DisconnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
90     {
91         JsWallpaperExtensionContext* me = CheckParamsAndGetThis<JsWallpaperExtensionContext>(engine, info);
92         return (me != nullptr) ? me->OnDisconnectAbility(*engine, *info) : nullptr;
93     }
94 private:
95     std::weak_ptr<WallpaperExtensionContext> context_;
96 
OnStartAbility(NativeEngine & engine,NativeCallbackInfo & info)97     NativeValue* OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info)
98     {
99         HILOG_INFO("OnStartAbility is called");
100         // only support one or two or three params
101         if (info.argc != ARGC_ONE && info.argc != ARGC_TWO && info.argc != ARGC_THREE) {
102             HILOG_ERROR("Not enough params");
103             return engine.CreateUndefined();
104         }
105 
106         decltype(info.argc) unwrapArgc = 0;
107         AAFwk::Want want;
108         OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
109             reinterpret_cast<napi_value>(info.argv[INDEX_ZERO]), want);
110         HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
111             __func__,
112             want.GetBundle().c_str(),
113             want.GetElement().GetAbilityName().c_str());
114         unwrapArgc++;
115 
116         AAFwk::StartOptions startOptions;
117         if (info.argc > ARGC_ONE && info.argv[INDEX_ONE]->TypeOf() == NATIVE_OBJECT) {
118             HILOG_INFO("OnStartAbility start options is used.");
119             AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
120                 reinterpret_cast<napi_value>(info.argv[INDEX_ONE]), startOptions);
121             unwrapArgc++;
122         }
123 
124         AsyncTask::CompleteCallback complete =
125             [weak = context_, want, startOptions, unwrapArgc](NativeEngine& engine, AsyncTask& task, int32_t status) {
126                 HILOG_INFO("startAbility begin");
127                 auto context = weak.lock();
128                 if (!context) {
129                     HILOG_WARN("context is released");
130                     task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
131                     return;
132                 }
133 
134                 ErrCode errcode = ERR_OK;
135                 (unwrapArgc == 1) ? errcode = context->StartAbility(want) :
136                     errcode = context->StartAbility(want, startOptions);
137                 if (errcode == 0) {
138                     task.Resolve(engine, engine.CreateUndefined());
139                 } else {
140                     task.Reject(engine, CreateJsError(engine, errcode, "Start Ability failed."));
141                 }
142             };
143 
144         NativeValue* lastParam = (info.argc == unwrapArgc) ? nullptr : info.argv[unwrapArgc];
145         NativeValue* result = nullptr;
146         AsyncTask::Schedule(
147             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
148         return result;
149     }
150 
OnStartAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)151     NativeValue* OnStartAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
152     {
153         HILOG_INFO("OnStartAbilityWithAccount is called");
154         // only support two or three or four params
155         if (info.argc != ARGC_TWO && info.argc != ARGC_THREE && info.argc != ARGC_FOUR) {
156             HILOG_ERROR("Not enough params");
157             return engine.CreateUndefined();
158         }
159 
160         decltype(info.argc) unwrapArgc = 0;
161         AAFwk::Want want;
162         OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
163             reinterpret_cast<napi_value>(info.argv[INDEX_ZERO]), want);
164         HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
165             __func__,
166             want.GetBundle().c_str(),
167             want.GetElement().GetAbilityName().c_str());
168         unwrapArgc++;
169 
170         int32_t accountId = 0;
171         if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
172             reinterpret_cast<napi_value>(info.argv[INDEX_ONE]), accountId)) {
173             HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
174             return engine.CreateUndefined();
175         }
176         HILOG_INFO("%{public}d accountId:", accountId);
177         unwrapArgc++;
178 
179         AAFwk::StartOptions startOptions;
180         if (info.argc > ARGC_TWO && info.argv[INDEX_TWO]->TypeOf() == NATIVE_OBJECT) {
181             HILOG_INFO("OnStartAbilityWithAccount start options is used.");
182             AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
183                 reinterpret_cast<napi_value>(info.argv[INDEX_TWO]), startOptions);
184             unwrapArgc++;
185         }
186 
187         AsyncTask::CompleteCallback complete =
188             [weak = context_, want, accountId, startOptions, unwrapArgc](
189                 NativeEngine& engine, AsyncTask& task, int32_t status) {
190                     HILOG_INFO("startAbility begin");
191                     auto context = weak.lock();
192                     if (!context) {
193                         HILOG_WARN("context is released");
194                         task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
195                         return;
196                     }
197 
198                     ErrCode errcode = ERR_OK;
199                     (unwrapArgc == ARGC_TWO) ? errcode = context->StartAbilityWithAccount(want, accountId) :
200                     errcode = context->StartAbilityWithAccount(want, accountId, startOptions);
201                     if (errcode == 0) {
202                         task.Resolve(engine, engine.CreateUndefined());
203                     } else {
204                         task.Reject(engine, CreateJsError(engine, errcode, "Start Ability failed."));
205                     }
206                 };
207 
208         NativeValue* lastParam = (info.argc == unwrapArgc) ? nullptr : info.argv[unwrapArgc];
209         NativeValue* result = nullptr;
210         AsyncTask::Schedule(
211             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
212         return result;
213     }
214 
OnTerminateAbility(NativeEngine & engine,NativeCallbackInfo & info)215     NativeValue* OnTerminateAbility(NativeEngine& engine, NativeCallbackInfo& info)
216     {
217         HILOG_INFO("OnTerminateAbility is called");
218         // only support one or zero params
219         if (info.argc != ARGC_ZERO && info.argc != ARGC_ONE) {
220             HILOG_ERROR("Not enough params");
221             return engine.CreateUndefined();
222         }
223 
224         AsyncTask::CompleteCallback complete =
225             [weak = context_](NativeEngine& engine, AsyncTask& task, int32_t status) {
226                 HILOG_INFO("TerminateAbility begin");
227                 auto context = weak.lock();
228                 if (!context) {
229                     HILOG_WARN("context is released");
230                     task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
231                     return;
232                 }
233 
234                 auto errcode = context->TerminateAbility();
235                 if (errcode == 0) {
236                     task.Resolve(engine, engine.CreateUndefined());
237                 } else {
238                     task.Reject(engine, CreateJsError(engine, errcode, "Terminate Ability failed."));
239                 }
240             };
241 
242         NativeValue* lastParam = (info.argc == ARGC_ZERO) ? nullptr : info.argv[INDEX_ZERO];
243         NativeValue* result = nullptr;
244         AsyncTask::Schedule(
245             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
246         return result;
247     }
248 
OnConnectAbility(NativeEngine & engine,NativeCallbackInfo & info)249     NativeValue* OnConnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
250     {
251         HILOG_INFO("OnConnectAbility is called");
252         // only support two params
253         if (info.argc != ARGC_TWO) {
254             HILOG_ERROR("Not enough params");
255             return engine.CreateUndefined();
256         }
257 
258         // unwrap want
259         AAFwk::Want want;
260         OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
261             reinterpret_cast<napi_value>(info.argv[INDEX_ZERO]), want);
262         HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
263             __func__,
264             want.GetBundle().c_str(),
265             want.GetElement().GetAbilityName().c_str());
266         // unwarp connection
267         sptr<JSWallpaperExtensionConnection> connection = new JSWallpaperExtensionConnection(engine);
268         connection->SetJsConnectionObject(info.argv[1]);
269         int64_t connectId = serialNumber_;
270         ConnecttionKey key;
271         key.id = serialNumber_;
272         key.want = want;
273         connects_.emplace(key, connection);
274         if (serialNumber_ < INT64_MAX) {
275             serialNumber_++;
276         } else {
277             serialNumber_ = 0;
278         }
279         HILOG_INFO("%{public}s not find connection, make new one:%{public}p.", __func__, connection.GetRefPtr());
280         AsyncTask::CompleteCallback complete =
281             [weak = context_, want, connection, connectId](NativeEngine& engine, AsyncTask& task, int32_t status) {
282                 HILOG_INFO("OnConnectAbility begin");
283                 auto context = weak.lock();
284                 if (!context) {
285                     HILOG_WARN("context is released");
286                     task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
287                     return;
288                 }
289                 HILOG_INFO("context->ConnectAbility connection:%{public}d", (int32_t)connectId);
290                 if (!context->ConnectAbility(want, connection)) {
291                     connection->CallJsFailed(ERROR_CODE_ONE);
292                 }
293                 task.Resolve(engine, engine.CreateUndefined());
294             };
295         NativeValue* result = nullptr;
296         AsyncTask::Schedule(
297             engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
298         return engine.CreateNumber(connectId);
299     }
300 
OnConnectAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)301     NativeValue* OnConnectAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
302     {
303         HILOG_INFO("OnConnectAbilityWithAccount is called");
304         // only support three params
305         if (info.argc != ARGC_THREE) {
306             HILOG_ERROR("Not enough params");
307             return engine.CreateUndefined();
308         }
309 
310         // unwrap want
311         AAFwk::Want want;
312         OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
313             reinterpret_cast<napi_value>(info.argv[INDEX_ZERO]), want);
314         HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
315             __func__,
316             want.GetBundle().c_str(),
317             want.GetElement().GetAbilityName().c_str());
318 
319         int32_t accountId = 0;
320         if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
321             reinterpret_cast<napi_value>(info.argv[INDEX_ONE]), accountId)) {
322             HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
323             return engine.CreateUndefined();
324         }
325 
326         // unwarp connection
327         sptr<JSWallpaperExtensionConnection> connection = new JSWallpaperExtensionConnection(engine);
328         connection->SetJsConnectionObject(info.argv[1]);
329         int64_t connectId = serialNumber_;
330         ConnecttionKey key;
331         key.id = serialNumber_;
332         key.want = want;
333         connects_.emplace(key, connection);
334         if (serialNumber_ < INT64_MAX) {
335             serialNumber_++;
336         } else {
337             serialNumber_ = 0;
338         }
339         HILOG_INFO("%{public}s not find connection, make new one:%{public}p.", __func__, connection.GetRefPtr());
340         AsyncTask::CompleteCallback complete =
341             [weak = context_, want, accountId, connection, connectId](
342                 NativeEngine& engine, AsyncTask& task, int32_t status) {
343                     HILOG_INFO("OnConnectAbilityWithAccount begin");
344                     auto context = weak.lock();
345                     if (!context) {
346                         HILOG_WARN("context is released");
347                         task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
348                         return;
349                     }
350                     HILOG_INFO("context->ConnectAbilityWithAccount connection:%{public}d", (int32_t)connectId);
351                     if (!context->ConnectAbilityWithAccount(want, accountId, connection)) {
352                         connection->CallJsFailed(ERROR_CODE_ONE);
353                     }
354                     task.Resolve(engine, engine.CreateUndefined());
355                 };
356         NativeValue* result = nullptr;
357         AsyncTask::Schedule(
358             engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
359         return engine.CreateNumber(connectId);
360     }
361 
OnDisconnectAbility(NativeEngine & engine,NativeCallbackInfo & info)362     NativeValue* OnDisconnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
363     {
364         HILOG_INFO("OnDisconnectAbility is called");
365         // only support one or two params
366         if (info.argc != ARGC_ONE && info.argc != ARGC_TWO) {
367             HILOG_ERROR("Not enough params");
368             return engine.CreateUndefined();
369         }
370 
371         // unwrap want
372         AAFwk::Want want;
373         // unwrap connectId
374         int64_t connectId = -1;
375         sptr<JSWallpaperExtensionConnection> connection = nullptr;
376         napi_get_value_int64(reinterpret_cast<napi_env>(&engine),
377             reinterpret_cast<napi_value>(info.argv[INDEX_ZERO]), &connectId);
378         HILOG_INFO("OnDisconnectAbility connection:%{public}d", (int32_t)connectId);
379         auto item = std::find_if(connects_.begin(), connects_.end(),
380             [&connectId](
381                 const std::map<ConnecttionKey, sptr<JSWallpaperExtensionConnection>>::value_type &obj) {
382                     return connectId == obj.first.id;
383             });
384         if (item != connects_.end()) {
385             // match id
386             want = item->first.want;
387             connection = item->second;
388             HILOG_INFO("%{public}s find conn ability:%{public}p exist", __func__, item->second.GetRefPtr());
389         } else {
390             HILOG_INFO("%{public}s not find conn exist.", __func__);
391         }
392         // begin disconnect
393         AsyncTask::CompleteCallback complete =
394             [weak = context_, want, connection](
395                 NativeEngine& engine, AsyncTask& task, int32_t status) {
396                 HILOG_INFO("OnDisconnectAbility begin");
397                 auto context = weak.lock();
398                 if (!context) {
399                     HILOG_WARN("context is released");
400                     task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
401                     return;
402                 }
403                 if (connection == nullptr) {
404                     HILOG_WARN("connection nullptr");
405                     task.Reject(engine, CreateJsError(engine, ERROR_CODE_TWO, "not found connection"));
406                     return;
407                 }
408                 HILOG_INFO("context->DisconnectAbility");
409                 auto errcode = context->DisconnectAbility(want, connection);
410                 errcode == 0 ? task.Resolve(engine, engine.CreateUndefined()) :
411                     task.Reject(engine, CreateJsError(engine, errcode, "Disconnect Ability failed."));
412             };
413 
414         NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[INDEX_ONE];
415         NativeValue* result = nullptr;
416         AsyncTask::Schedule(
417             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
418         return result;
419     }
420 };
421 } // namespace
422 
CreateJsMetadata(NativeEngine & engine,const AppExecFwk::Metadata & Info)423 NativeValue* CreateJsMetadata(NativeEngine& engine, const AppExecFwk::Metadata &Info)
424 {
425     HILOG_INFO("CreateJsMetadata");
426     NativeValue* objValue = engine.CreateObject();
427     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
428 
429     object->SetProperty("name", CreateJsValue(engine, Info.name));
430     object->SetProperty("value", CreateJsValue(engine, Info.value));
431     object->SetProperty("resource", CreateJsValue(engine, Info.resource));
432     return objValue;
433 }
434 
CreateJsMetadataArray(NativeEngine & engine,const std::vector<AppExecFwk::Metadata> & info)435 NativeValue* CreateJsMetadataArray(NativeEngine& engine, const std::vector<AppExecFwk::Metadata> &info)
436 {
437     HILOG_INFO("CreateJsMetadataArray");
438     NativeValue* arrayValue = engine.CreateArray(info.size());
439     NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
440     uint32_t index = 0;
441     for (const auto& item : info) {
442         array->SetElement(index++, CreateJsMetadata(engine, item));
443     }
444     return arrayValue;
445 }
446 
CreateJsExtensionAbilityInfo(NativeEngine & engine,const AppExecFwk::ExtensionAbilityInfo & info)447 NativeValue* CreateJsExtensionAbilityInfo(NativeEngine& engine, const AppExecFwk::ExtensionAbilityInfo& info)
448 {
449     HILOG_INFO("CreateJsExtensionAbilityInfo");
450     NativeValue* objValue = engine.CreateObject();
451     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
452     object->SetProperty("bundleName", CreateJsValue(engine, info.bundleName));
453     object->SetProperty("moduleName", CreateJsValue(engine, info.moduleName));
454     object->SetProperty("name", CreateJsValue(engine, info.name));
455     object->SetProperty("labelId", CreateJsValue(engine, info.labelId));
456     object->SetProperty("descriptionId", CreateJsValue(engine, info.descriptionId));
457     object->SetProperty("iconId", CreateJsValue(engine, info.iconId));
458     object->SetProperty("isVisible", CreateJsValue(engine, info.visible));
459     object->SetProperty("extensionAbilityType", CreateJsValue(engine, info.type));
460     NativeValue *permissionArrayValue = engine.CreateArray(info.permissions.size());
461     NativeArray *permissionArray = ConvertNativeValueTo<NativeArray>(permissionArrayValue);
462     if (permissionArray != nullptr) {
463         int index = 0;
464         for (auto permission : info.permissions) {
465             permissionArray->SetElement(index++, CreateJsValue(engine, permission));
466         }
467     }
468     object->SetProperty("permissions", permissionArrayValue);
469     object->SetProperty("applicationInfo", CreateJsApplicationInfo(engine, info.applicationInfo));
470     object->SetProperty("metadata", CreateJsMetadataArray(engine, info.metadata));
471     object->SetProperty("enabled", CreateJsValue(engine, info.enabled));
472     object->SetProperty("readPermission", CreateJsValue(engine, info.readPermission));
473     object->SetProperty("writePermission", CreateJsValue(engine, info.writePermission));
474     return objValue;
475 }
476 
CreateJsWallpaperExtensionContext(NativeEngine & engine,std::shared_ptr<WallpaperExtensionContext> context)477 NativeValue* CreateJsWallpaperExtensionContext(NativeEngine& engine, std::shared_ptr<WallpaperExtensionContext> context)
478 {
479     HILOG_INFO("CreateJsWallpaperExtensionContext begin");
480     NativeValue* objValue = CreateJsExtensionContext(engine, context);
481     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
482 
483     std::unique_ptr<JsWallpaperExtensionContext> jsContext = std::make_unique<JsWallpaperExtensionContext>(context);
484     object->SetNativePointer(jsContext.release(), JsWallpaperExtensionContext::Finalizer, nullptr);
485 
486     // make handler
487     handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
488 
489     BindNativeFunction(engine, *object, "startAbility", JsWallpaperExtensionContext::StartAbility);
490     BindNativeFunction(engine, *object, "terminateSelf", JsWallpaperExtensionContext::TerminateAbility);
491     BindNativeFunction(engine, *object, "connectAbility", JsWallpaperExtensionContext::ConnectAbility);
492     BindNativeFunction(engine, *object, "disconnectAbility", JsWallpaperExtensionContext::DisconnectAbility);
493     BindNativeFunction(
494         engine, *object, "startAbilityWithAccount", JsWallpaperExtensionContext::StartAbilityWithAccount);
495     BindNativeFunction(
496         engine, *object, "connectAbilityWithAccount", JsWallpaperExtensionContext::ConnectAbilityWithAccount);
497 
498     if (context) {
499         HILOG_INFO("Set ExtensionAbilityInfo Property");
500         auto abilityInfo = context->GetAbilityInfo();
501         auto hapModuleInfo = context->GetHapModuleInfo();
502         if (abilityInfo && hapModuleInfo) {
503             auto isExist = [&abilityInfo](const AppExecFwk::ExtensionAbilityInfo &info) {
504                 HILOG_INFO("%{public}s, %{public}s", info.bundleName.c_str(), info.name.c_str());
505                 return info.bundleName == abilityInfo->bundleName && info.name == abilityInfo->name;
506             };
507             auto infoIter = std::find_if(
508                 hapModuleInfo->extensionInfos.begin(), hapModuleInfo->extensionInfos.end(), isExist);
509             if (infoIter == hapModuleInfo->extensionInfos.end()) {
510                 HILOG_INFO("Get target fail.");
511                 return objValue;
512             }
513             object->SetProperty("extensionAbilityInfo", CreateJsExtensionAbilityInfo(engine, *infoIter));
514         }
515     }
516 
517     return objValue;
518 }
519 
JSWallpaperExtensionConnection(NativeEngine & engine)520 JSWallpaperExtensionConnection::JSWallpaperExtensionConnection(NativeEngine& engine) : engine_(engine) {}
521 
522 JSWallpaperExtensionConnection::~JSWallpaperExtensionConnection() = default;
523 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)524 void JSWallpaperExtensionConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
525     const sptr<IRemoteObject> &remoteObject, int resultCode)
526 {
527     HILOG_INFO("OnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
528     if (handler_ == nullptr) {
529         HILOG_INFO("handler_ nullptr");
530         return;
531     }
532     wptr<JSWallpaperExtensionConnection> connection = this;
533     auto task = [connection, element, remoteObject, resultCode]() {
534         sptr<JSWallpaperExtensionConnection> connectionSptr = connection.promote();
535         if (!connectionSptr) {
536             HILOG_INFO("connectionSptr nullptr");
537             return;
538         }
539         connectionSptr->HandleOnAbilityConnectDone(element, remoteObject, resultCode);
540     };
541     handler_->PostTask(task, "OnAbilityConnectDone");
542 }
543 
HandleOnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)544 void JSWallpaperExtensionConnection::HandleOnAbilityConnectDone(const AppExecFwk::ElementName &element,
545     const sptr<IRemoteObject> &remoteObject, int resultCode)
546 {
547     HILOG_INFO("HandleOnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
548     // wrap ElementName
549     napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
550     NativeValue* nativeElementName = reinterpret_cast<NativeValue*>(napiElementName);
551 
552     // wrap RemoteObject
553     HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
554     napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
555         reinterpret_cast<napi_env>(&engine_), remoteObject);
556     NativeValue* nativeRemoteObject = reinterpret_cast<NativeValue*>(napiRemoteObject);
557     NativeValue* argv[] = {nativeElementName, nativeRemoteObject};
558     if (jsConnectionObject_ == nullptr) {
559         HILOG_ERROR("jsConnectionObject_ nullptr");
560         return;
561     }
562     NativeValue* value = jsConnectionObject_->Get();
563     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
564     if (obj == nullptr) {
565         HILOG_ERROR("Failed to get object");
566         return;
567     }
568     NativeValue* methodOnConnect = obj->GetProperty("onConnect");
569     if (methodOnConnect == nullptr) {
570         HILOG_ERROR("Failed to get onConnect from object");
571         return;
572     }
573     HILOG_INFO("JSWallpaperExtensionConnection::CallFunction onConnect, success");
574     engine_.CallFunction(value, methodOnConnect, argv, ARGC_TWO);
575     HILOG_INFO("OnAbilityConnectDone end");
576 }
577 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)578 void JSWallpaperExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
579 {
580     HILOG_INFO("OnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
581     if (handler_ == nullptr) {
582         HILOG_INFO("handler_ nullptr");
583         return;
584     }
585     wptr<JSWallpaperExtensionConnection> connection = this;
586     auto task = [connection, element, resultCode]() {
587         sptr<JSWallpaperExtensionConnection> connectionSptr = connection.promote();
588         if (!connectionSptr) {
589             HILOG_INFO("connectionSptr nullptr");
590             return;
591         }
592         connectionSptr->HandleOnAbilityDisconnectDone(element, resultCode);
593     };
594     handler_->PostTask(task, "OnAbilityDisconnectDone");
595 }
596 
HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)597 void JSWallpaperExtensionConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
598     int resultCode)
599 {
600     HILOG_INFO("HandleOnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
601     napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
602     NativeValue* nativeElementName = reinterpret_cast<NativeValue*>(napiElementName);
603     NativeValue* argv[] = {nativeElementName};
604     if (jsConnectionObject_ == nullptr) {
605         HILOG_ERROR("jsConnectionObject_ nullptr");
606         return;
607     }
608     NativeValue* value = jsConnectionObject_->Get();
609     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
610     if (obj == nullptr) {
611         HILOG_ERROR("Failed to get object");
612         return;
613     }
614 
615     NativeValue* method = obj->GetProperty("onDisconnect");
616     if (method == nullptr) {
617         HILOG_ERROR("Failed to get onDisconnect from object");
618         return;
619     }
620 
621     // release connect
622     HILOG_INFO("OnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size());
623     std::string bundleName = element.GetBundleName();
624     std::string abilityName = element.GetAbilityName();
625     auto item = std::find_if(connects_.begin(),
626         connects_.end(),
627         [bundleName, abilityName](
628             const std::map<ConnecttionKey, sptr<JSWallpaperExtensionConnection>>::value_type &obj) {
629             return (bundleName == obj.first.want.GetBundle()) &&
630                    (abilityName == obj.first.want.GetElement().GetAbilityName());
631         });
632     if (item != connects_.end()) {
633         // match bundlename && abilityname
634         connects_.erase(item);
635         HILOG_INFO("OnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size());
636     }
637     HILOG_INFO("OnAbilityDisconnectDone CallFunction success");
638     engine_.CallFunction(value, method, argv, ARGC_ONE);
639 }
640 
SetJsConnectionObject(NativeValue * jsConnectionObject)641 void JSWallpaperExtensionConnection::SetJsConnectionObject(NativeValue* jsConnectionObject)
642 {
643     jsConnectionObject_ = std::unique_ptr<NativeReference>(engine_.CreateReference(jsConnectionObject, 1));
644 }
645 
CallJsFailed(int32_t errorCode)646 void JSWallpaperExtensionConnection::CallJsFailed(int32_t errorCode)
647 {
648     HILOG_INFO("CallJsFailed begin");
649     if (jsConnectionObject_ == nullptr) {
650         HILOG_ERROR("jsConnectionObject_ nullptr");
651         return;
652     }
653     NativeValue* value = jsConnectionObject_->Get();
654     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
655     if (obj == nullptr) {
656         HILOG_ERROR("Failed to get object");
657         return;
658     }
659 
660     NativeValue* method = obj->GetProperty("onFailed");
661     if (method == nullptr) {
662         HILOG_ERROR("Failed to get onFailed from object");
663         return;
664     }
665     NativeValue* argv[] = {engine_.CreateNumber(errorCode)};
666     HILOG_INFO("CallJsFailed CallFunction success");
667     engine_.CallFunction(value, method, argv, ARGC_ONE);
668     HILOG_INFO("CallJsFailed end");
669 }
670 }  // namespace AbilityRuntime
671 }  // namespace OHOS