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