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