• 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("WallpaperExtensionContext::OnStartAbility",
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("WallpaperExtensionContext::OnStartAbilityWithAccount",
211             engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
212         return result;
213     }
214 
OnTerminateAbility(NativeEngine & engine,const NativeCallbackInfo & info)215     NativeValue* OnTerminateAbility(NativeEngine& engine, const 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("WallpaperExtensionContext::OnTerminateAbility",
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.", __func__);
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("WallpaperExtensionContext::OnConnectAbility",
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.", __func__);
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("WallpaperExtensionContext::OnConnectAbilityWithAccount",
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", static_cast<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 exist", __func__);
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("WallpaperExtensionContext::OnDisconnectAbility",
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     const char *moduleName = "JsWallpaperExtensionContext";
490     BindNativeFunction(engine, *object, "startAbility", moduleName, JsWallpaperExtensionContext::StartAbility);
491     BindNativeFunction(engine, *object, "terminateSelf", moduleName, JsWallpaperExtensionContext::TerminateAbility);
492     BindNativeFunction(engine, *object, "connectAbility", moduleName, JsWallpaperExtensionContext::ConnectAbility);
493     BindNativeFunction(engine, *object,
494         "disconnectAbility", moduleName, JsWallpaperExtensionContext::DisconnectAbility);
495     BindNativeFunction(engine, *object,
496         "startAbilityWithAccount", moduleName, JsWallpaperExtensionContext::StartAbilityWithAccount);
497     BindNativeFunction(engine, *object,
498         "connectAbilityWithAccount", moduleName, JsWallpaperExtensionContext::ConnectAbilityWithAccount);
499 
500     if (context) {
501         HILOG_INFO("Set ExtensionAbilityInfo Property");
502         auto abilityInfo = context->GetAbilityInfo();
503         auto hapModuleInfo = context->GetHapModuleInfo();
504         if (abilityInfo && hapModuleInfo) {
505             auto isExist = [&abilityInfo](const AppExecFwk::ExtensionAbilityInfo &info) {
506                 HILOG_INFO("%{public}s, %{public}s", info.bundleName.c_str(), info.name.c_str());
507                 return info.bundleName == abilityInfo->bundleName && info.name == abilityInfo->name;
508             };
509             auto infoIter = std::find_if(
510                 hapModuleInfo->extensionInfos.begin(), hapModuleInfo->extensionInfos.end(), isExist);
511             if (infoIter == hapModuleInfo->extensionInfos.end()) {
512                 HILOG_INFO("Get target fail.");
513                 return objValue;
514             }
515             object->SetProperty("extensionAbilityInfo", CreateJsExtensionAbilityInfo(engine, *infoIter));
516         }
517     }
518 
519     return objValue;
520 }
521 
JSWallpaperExtensionConnection(NativeEngine & engine)522 JSWallpaperExtensionConnection::JSWallpaperExtensionConnection(NativeEngine& engine) : engine_(engine) {}
523 
524 JSWallpaperExtensionConnection::~JSWallpaperExtensionConnection() = default;
525 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)526 void JSWallpaperExtensionConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
527     const sptr<IRemoteObject> &remoteObject, int resultCode)
528 {
529     HILOG_INFO("OnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
530     if (handler_ == nullptr) {
531         HILOG_INFO("handler_ nullptr");
532         return;
533     }
534     wptr<JSWallpaperExtensionConnection> connection = this;
535     auto task = [connection, element, remoteObject, resultCode]() {
536         sptr<JSWallpaperExtensionConnection> connectionSptr = connection.promote();
537         if (!connectionSptr) {
538             HILOG_INFO("connectionSptr nullptr");
539             return;
540         }
541         connectionSptr->HandleOnAbilityConnectDone(element, remoteObject, resultCode);
542     };
543     handler_->PostTask(task, "OnAbilityConnectDone");
544 }
545 
HandleOnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)546 void JSWallpaperExtensionConnection::HandleOnAbilityConnectDone(const AppExecFwk::ElementName &element,
547     const sptr<IRemoteObject> &remoteObject, int resultCode)
548 {
549     HILOG_INFO("HandleOnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
550     // wrap ElementName
551     napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
552     NativeValue* nativeElementName = reinterpret_cast<NativeValue*>(napiElementName);
553 
554     // wrap RemoteObject
555     HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
556     napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
557         reinterpret_cast<napi_env>(&engine_), remoteObject);
558     NativeValue* nativeRemoteObject = reinterpret_cast<NativeValue*>(napiRemoteObject);
559     NativeValue* argv[] = {nativeElementName, nativeRemoteObject};
560     if (jsConnectionObject_ == nullptr) {
561         HILOG_ERROR("jsConnectionObject_ nullptr");
562         return;
563     }
564     NativeValue* value = jsConnectionObject_->Get();
565     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
566     if (obj == nullptr) {
567         HILOG_ERROR("Failed to get object");
568         return;
569     }
570     NativeValue* methodOnConnect = obj->GetProperty("onConnect");
571     if (methodOnConnect == nullptr) {
572         HILOG_ERROR("Failed to get onConnect from object");
573         return;
574     }
575     HILOG_INFO("JSWallpaperExtensionConnection::CallFunction onConnect, success");
576     engine_.CallFunction(value, methodOnConnect, argv, ARGC_TWO);
577     HILOG_INFO("OnAbilityConnectDone end");
578 }
579 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)580 void JSWallpaperExtensionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
581 {
582     HILOG_INFO("OnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
583     if (handler_ == nullptr) {
584         HILOG_INFO("handler_ nullptr");
585         return;
586     }
587     wptr<JSWallpaperExtensionConnection> connection = this;
588     auto task = [connection, element, resultCode]() {
589         sptr<JSWallpaperExtensionConnection> connectionSptr = connection.promote();
590         if (!connectionSptr) {
591             HILOG_INFO("connectionSptr nullptr");
592             return;
593         }
594         connectionSptr->HandleOnAbilityDisconnectDone(element, resultCode);
595     };
596     handler_->PostTask(task, "OnAbilityDisconnectDone");
597 }
598 
HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)599 void JSWallpaperExtensionConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
600     int resultCode)
601 {
602     HILOG_INFO("HandleOnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
603     napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
604     NativeValue* nativeElementName = reinterpret_cast<NativeValue*>(napiElementName);
605     NativeValue* argv[] = {nativeElementName};
606     if (jsConnectionObject_ == nullptr) {
607         HILOG_ERROR("jsConnectionObject_ nullptr");
608         return;
609     }
610     NativeValue* value = jsConnectionObject_->Get();
611     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
612     if (obj == nullptr) {
613         HILOG_ERROR("Failed to get object");
614         return;
615     }
616 
617     NativeValue* method = obj->GetProperty("onDisconnect");
618     if (method == nullptr) {
619         HILOG_ERROR("Failed to get onDisconnect from object");
620         return;
621     }
622 
623     // release connect
624     HILOG_INFO("OnAbilityDisconnectDone connects_.size:%{public}zu", connects_.size());
625     std::string bundleName = element.GetBundleName();
626     std::string abilityName = element.GetAbilityName();
627     auto item = std::find_if(connects_.begin(),
628         connects_.end(),
629         [bundleName, abilityName](
630             const std::map<ConnecttionKey, sptr<JSWallpaperExtensionConnection>>::value_type &obj) {
631             return (bundleName == obj.first.want.GetBundle()) &&
632                    (abilityName == obj.first.want.GetElement().GetAbilityName());
633         });
634     if (item != connects_.end()) {
635         // match bundlename && abilityname
636         connects_.erase(item);
637         HILOG_INFO("OnAbilityDisconnectDone erase connects_.size:%{public}zu", connects_.size());
638     }
639     HILOG_INFO("OnAbilityDisconnectDone CallFunction success");
640     engine_.CallFunction(value, method, argv, ARGC_ONE);
641 }
642 
SetJsConnectionObject(NativeValue * jsConnectionObject)643 void JSWallpaperExtensionConnection::SetJsConnectionObject(NativeValue* jsConnectionObject)
644 {
645     jsConnectionObject_ = std::unique_ptr<NativeReference>(engine_.CreateReference(jsConnectionObject, 1));
646 }
647 
CallJsFailed(int32_t errorCode)648 void JSWallpaperExtensionConnection::CallJsFailed(int32_t errorCode)
649 {
650     HILOG_INFO("CallJsFailed begin");
651     if (jsConnectionObject_ == nullptr) {
652         HILOG_ERROR("jsConnectionObject_ nullptr");
653         return;
654     }
655     NativeValue* value = jsConnectionObject_->Get();
656     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
657     if (obj == nullptr) {
658         HILOG_ERROR("Failed to get object");
659         return;
660     }
661 
662     NativeValue* method = obj->GetProperty("onFailed");
663     if (method == nullptr) {
664         HILOG_ERROR("Failed to get onFailed from object");
665         return;
666     }
667     NativeValue* argv[] = {engine_.CreateNumber(errorCode)};
668     HILOG_INFO("CallJsFailed CallFunction success");
669     engine_.CallFunction(value, method, argv, ARGC_ONE);
670     HILOG_INFO("CallJsFailed end");
671 }
672 }  // namespace AbilityRuntime
673 }  // namespace OHOS