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