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 "ability_runtime/js_ability_context.h"
17
18 #include <cstdint>
19
20 #include "bytrace.h"
21 #include "hilog_wrapper.h"
22 #include "js_context_utils.h"
23 #include "js_data_struct_converter.h"
24 #include "js_runtime_utils.h"
25 #include "ability_runtime/js_caller_complex.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 #include "event_handler.h"
33
34 #ifdef SUPPORT_GRAPHICS
35 #include "pixel_map_napi.h"
36 #endif
37
38 namespace OHOS {
39 namespace AbilityRuntime {
40 constexpr int32_t INDEX_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 int32_t ERROR_CODE_ONE = 1;
46 constexpr int32_t ERR_NOTOK = -1;
47
48 class StartAbilityByCallParameters {
49 public:
50 int err = 0;
51 sptr<IRemoteObject> remoteCallee = nullptr;
52 std::shared_ptr<CallerCallBack> callerCallBack = nullptr;
53 std::mutex mutexlock;
54 std::condition_variable condition;
55 };
56
Finalizer(NativeEngine * engine,void * data,void * hint)57 void JsAbilityContext::Finalizer(NativeEngine* engine, void* data, void* hint)
58 {
59 HILOG_INFO("JsAbilityContext::Finalizer is called");
60 std::unique_ptr<JsAbilityContext>(static_cast<JsAbilityContext*>(data));
61 }
62
StartAbility(NativeEngine * engine,NativeCallbackInfo * info)63 NativeValue* JsAbilityContext::StartAbility(NativeEngine* engine, NativeCallbackInfo* info)
64 {
65 BYTRACE_NAME(BYTRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
66 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
67 return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr;
68 }
69
StartAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)70 NativeValue* JsAbilityContext::StartAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
71 {
72 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
73 return (me != nullptr) ? me->OnStartAbilityWithAccount(*engine, *info) : nullptr;
74 }
75
StartAbilityByCall(NativeEngine * engine,NativeCallbackInfo * info)76 NativeValue* JsAbilityContext::StartAbilityByCall(NativeEngine* engine, NativeCallbackInfo* info)
77 {
78 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
79 return (me != nullptr) ? me->OnStartAbilityByCall(*engine, *info) : nullptr;
80 }
81
StartAbilityForResult(NativeEngine * engine,NativeCallbackInfo * info)82 NativeValue* JsAbilityContext::StartAbilityForResult(NativeEngine* engine, NativeCallbackInfo* info)
83 {
84 BYTRACE_NAME(BYTRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
85 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
86 return (me != nullptr) ? me->OnStartAbilityForResult(*engine, *info) : nullptr;
87 }
88
StartAbilityForResultWithAccount(NativeEngine * engine,NativeCallbackInfo * info)89 NativeValue* JsAbilityContext::StartAbilityForResultWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
90 {
91 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
92 return (me != nullptr) ? me->OnStartAbilityForResultWithAccount(*engine, *info) : nullptr;
93 }
94
ConnectAbility(NativeEngine * engine,NativeCallbackInfo * info)95 NativeValue* JsAbilityContext::ConnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
96 {
97 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
98 return (me != nullptr) ? me->OnConnectAbility(*engine, *info) : nullptr;
99 }
100
ConnectAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)101 NativeValue* JsAbilityContext::ConnectAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
102 {
103 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
104 return (me != nullptr) ? me->OnConnectAbilityWithAccount(*engine, *info) : nullptr;
105 }
106
DisconnectAbility(NativeEngine * engine,NativeCallbackInfo * info)107 NativeValue* JsAbilityContext::DisconnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
108 {
109 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
110 return (me != nullptr) ? me->OnDisconnectAbility(*engine, *info) : nullptr;
111 }
112
TerminateSelf(NativeEngine * engine,NativeCallbackInfo * info)113 NativeValue* JsAbilityContext::TerminateSelf(NativeEngine* engine, NativeCallbackInfo* info)
114 {
115 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
116 return (me != nullptr) ? me->OnTerminateSelf(*engine, *info) : nullptr;
117 }
118
TerminateSelfWithResult(NativeEngine * engine,NativeCallbackInfo * info)119 NativeValue* JsAbilityContext::TerminateSelfWithResult(NativeEngine* engine, NativeCallbackInfo* info)
120 {
121 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
122 return (me != nullptr) ? me->OnTerminateSelfWithResult(*engine, *info) : nullptr;
123 }
124
RequestPermissionsFromUser(NativeEngine * engine,NativeCallbackInfo * info)125 NativeValue* JsAbilityContext::RequestPermissionsFromUser(NativeEngine* engine, NativeCallbackInfo* info)
126 {
127 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
128 return (me != nullptr) ? me->OnRequestPermissionsFromUser(*engine, *info) : nullptr;
129 }
130
RestoreWindowStage(NativeEngine * engine,NativeCallbackInfo * info)131 NativeValue* JsAbilityContext::RestoreWindowStage(NativeEngine* engine, NativeCallbackInfo* info)
132 {
133 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
134 return (me != nullptr) ? me->OnRestoreWindowStage(*engine, *info) : nullptr;
135 }
136
SetMissionLabel(NativeEngine * engine,NativeCallbackInfo * info)137 NativeValue* JsAbilityContext::SetMissionLabel(NativeEngine* engine, NativeCallbackInfo* info)
138 {
139 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
140 return (me != nullptr) ? me->OnSetMissionLabel(*engine, *info) : nullptr;
141 }
142
143 #ifdef SUPPORT_GRAPHICS
SetMissionIcon(NativeEngine * engine,NativeCallbackInfo * info)144 NativeValue* JsAbilityContext::SetMissionIcon(NativeEngine* engine, NativeCallbackInfo* info)
145 {
146 JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
147 return (me != nullptr) ? me->OnSetMissionIcon(*engine, *info) : nullptr;
148 }
149 #endif
150
OnStartAbility(NativeEngine & engine,NativeCallbackInfo & info)151 NativeValue* JsAbilityContext::OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info)
152 {
153 HILOG_INFO("OnStartAbility is called");
154
155 if (info.argc == ARGC_ZERO) {
156 HILOG_ERROR("Not enough params");
157 return engine.CreateUndefined();
158 }
159 AAFwk::Want want;
160 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[0]), want);
161 InheritWindowMode(want);
162 decltype(info.argc) unwrapArgc = 1;
163 HILOG_INFO("abilityName=%{public}s", want.GetElement().GetAbilityName().c_str());
164 AAFwk::StartOptions startOptions;
165 if (info.argc > ARGC_ONE && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
166 HILOG_INFO("OnStartAbility start options is used.");
167 AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
168 reinterpret_cast<napi_value>(info.argv[1]), startOptions);
169 unwrapArgc++;
170 }
171 AsyncTask::CompleteCallback complete =
172 [weak = context_, want, startOptions, unwrapArgc](NativeEngine& engine, AsyncTask& task, int32_t status) {
173 auto context = weak.lock();
174 if (!context) {
175 HILOG_WARN("context is released");
176 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
177 return;
178 }
179 auto errcode = (unwrapArgc == 1) ?
180 context->StartAbility(want, -1) : context->StartAbility(want, startOptions, -1);
181 if (errcode == 0) {
182 task.Resolve(engine, engine.CreateUndefined());
183 } else {
184 task.Reject(engine, CreateJsError(engine, errcode, "Start Ability failed."));
185 }
186 };
187
188 NativeValue* lastParam = (info.argc == unwrapArgc) ? nullptr : info.argv[unwrapArgc];
189 NativeValue* result = nullptr;
190 AsyncTask::Schedule(
191 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
192 return result;
193 }
194
OnStartAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)195 NativeValue* JsAbilityContext::OnStartAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
196 {
197 HILOG_INFO("OnStartAbilityWithAccount is called");
198 if (info.argc == ARGC_ZERO) {
199 HILOG_ERROR("Not enough params");
200 return engine.CreateUndefined();
201 }
202 AAFwk::Want want;
203 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[0]), want);
204 InheritWindowMode(want);
205 decltype(info.argc) unwrapArgc = 1;
206 HILOG_INFO("abilityName=%{public}s", want.GetElement().GetAbilityName().c_str());
207 int32_t accountId = 0;
208 if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
209 reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
210 HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
211 return engine.CreateUndefined();
212 }
213 unwrapArgc++;
214 AAFwk::StartOptions startOptions;
215 if (info.argc > ARGC_TWO && info.argv[INDEX_TWO]->TypeOf() == NATIVE_OBJECT) {
216 HILOG_INFO("OnStartAbilityWithAccount start options is used.");
217 AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
218 reinterpret_cast<napi_value>(info.argv[ARGC_TWO]), startOptions);
219 unwrapArgc++;
220 }
221 AsyncTask::CompleteCallback complete =
222 [weak = context_, want, accountId, startOptions, unwrapArgc](
223 NativeEngine& engine, AsyncTask& task, int32_t status) {
224 auto context = weak.lock();
225 if (!context) {
226 HILOG_WARN("context is released");
227 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
228 return;
229 }
230
231 auto errcode = (unwrapArgc == INDEX_TWO) ?
232 context->StartAbilityWithAccount(want, accountId, -1) : context->StartAbilityWithAccount(
233 want, accountId, startOptions, -1);
234 if (errcode == 0) {
235 task.Resolve(engine, engine.CreateUndefined());
236 } else {
237 task.Reject(engine, CreateJsError(engine, errcode, "Start Ability failed."));
238 }
239 };
240
241 NativeValue* lastParam = (info.argc == unwrapArgc) ? nullptr : info.argv[unwrapArgc];
242 NativeValue* result = nullptr;
243 AsyncTask::Schedule(
244 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
245 return result;
246 }
247
OnStartAbilityByCall(NativeEngine & engine,NativeCallbackInfo & info)248 NativeValue* JsAbilityContext::OnStartAbilityByCall(NativeEngine& engine, NativeCallbackInfo& info)
249 {
250 HILOG_DEBUG("JsAbilityContext::%{public}s, called", __func__);
251 constexpr size_t ARGC_ONE = 1;
252 constexpr size_t ARGC_TWO = 2;
253 if (info.argc < ARGC_ONE || info.argv[0]->TypeOf() != NATIVE_OBJECT) {
254 HILOG_ERROR("int put params count error");
255 return engine.CreateUndefined();
256 }
257
258 AAFwk::Want want;
259 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
260 reinterpret_cast<napi_value>(info.argv[0]), want);
261 InheritWindowMode(want);
262
263 std::shared_ptr<StartAbilityByCallParameters> calls = std::make_shared<StartAbilityByCallParameters>();
264 if (calls == nullptr) {
265 HILOG_ERROR("calls create error");
266 return engine.CreateUndefined();
267 }
268
269 NativeValue* lastParam = ((info.argc == ARGC_TWO) ? info.argv[ARGC_ONE] : nullptr);
270 NativeValue* retsult = nullptr;
271
272 calls->callerCallBack = std::make_shared<CallerCallBack>();
273
274 auto callBackDone = [calldata = calls] (const sptr<IRemoteObject> &obj) {
275 HILOG_DEBUG("OnStartAbilityByCall callBackDone mutexlock");
276 std::unique_lock<std::mutex> lock(calldata->mutexlock);
277 HILOG_DEBUG("OnStartAbilityByCall callBackDone remoteCallee assignment");
278 calldata->remoteCallee = obj;
279 calldata->condition.notify_all();
280 HILOG_INFO("OnStartAbilityByCall callBackDone is called end");
281 };
282
283 auto releaseListen = [](const std::string &str) {
284 HILOG_INFO("OnStartAbilityByCall releaseListen is called %{public}s", str.c_str());
285 };
286
287 auto callExecute = [calldata = calls] () {
288 constexpr int CALLER_TIME_OUT = 10; // 10s
289 std::unique_lock<std::mutex> lock(calldata->mutexlock);
290 if (calldata->remoteCallee != nullptr) {
291 HILOG_INFO("OnStartAbilityByCall callExecute callee isn`t nullptr");
292 return;
293 }
294
295 if (calldata->condition.wait_for(lock, std::chrono::seconds(CALLER_TIME_OUT)) == std::cv_status::timeout) {
296 HILOG_ERROR("OnStartAbilityByCall callExecute waiting callee timeout");
297 calldata->err = -1;
298 }
299 HILOG_DEBUG("OnStartAbilityByCall callExecute end");
300 };
301
302 auto callComplete = [weak = context_, calldata = calls] (
303 NativeEngine& engine, AsyncTask& task, int32_t status) {
304 if (calldata->err != 0) {
305 HILOG_ERROR("OnStartAbilityByCall callComplete err is %{public}d", calldata->err);
306 task.Reject(engine, CreateJsError(engine, calldata->err, "callComplete err."));
307 return;
308 }
309
310 auto context = weak.lock();
311 if (context != nullptr && calldata->callerCallBack != nullptr && calldata->remoteCallee != nullptr) {
312 task.Resolve(engine,
313 CreateJsCallerComplex(engine, context, calldata->remoteCallee, calldata->callerCallBack));
314 } else {
315 HILOG_ERROR("OnStartAbilityByCall callComplete params error %{public}s is nullptr",
316 context == nullptr ? "context" :
317 (calldata->remoteCallee == nullptr ? "remoteCallee" : "callerCallBack"));
318 task.Reject(engine, CreateJsError(engine, -1, "Create Call Failed."));
319 }
320
321 HILOG_DEBUG("OnStartAbilityByCall callComplete end");
322 };
323
324 calls->callerCallBack->SetCallBack(callBackDone);
325 calls->callerCallBack->SetOnRelease(releaseListen);
326
327 auto context = context_.lock();
328 if (context == nullptr) {
329 HILOG_ERROR("OnStartAbilityByCall context is nullptr");
330 return engine.CreateUndefined();
331 }
332
333 if (context->StartAbility(want, calls->callerCallBack) != 0) {
334 HILOG_ERROR("OnStartAbilityByCall StartAbility is failed");
335 return engine.CreateUndefined();
336 }
337
338 if (calls->remoteCallee == nullptr) {
339 HILOG_INFO("OnStartAbilityByCall async wait execute");
340 AsyncTask::Schedule(
341 engine,
342 CreateAsyncTaskWithLastParam(
343 engine, lastParam, std::move(callExecute), std::move(callComplete), &retsult));
344 } else {
345 HILOG_INFO("OnStartAbilityByCall promiss return result execute");
346 AsyncTask::Schedule(
347 engine,
348 CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(callComplete), &retsult));
349 }
350
351 HILOG_DEBUG("JsAbilityContext::%{public}s, called end", __func__);
352 return retsult;
353 }
354
OnStartAbilityForResult(NativeEngine & engine,NativeCallbackInfo & info)355 NativeValue* JsAbilityContext::OnStartAbilityForResult(NativeEngine& engine, NativeCallbackInfo& info)
356 {
357 HILOG_INFO("OnStartAbilityForResult is called");
358
359 if (info.argc == ARGC_ZERO) {
360 HILOG_ERROR("Not enough params");
361 return engine.CreateUndefined();
362 }
363
364 AAFwk::Want want;
365 if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
366 HILOG_ERROR("%s Failed to parse want!", __func__);
367 return engine.CreateUndefined();
368 }
369 InheritWindowMode(want);
370 decltype(info.argc) unwrapArgc = 1;
371 AAFwk::StartOptions startOptions;
372 if (info.argc > ARGC_ONE && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
373 HILOG_INFO("OnStartAbilityForResult start options is used.");
374 AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
375 reinterpret_cast<napi_value>(info.argv[1]), startOptions);
376 unwrapArgc++;
377 }
378
379 NativeValue* lastParam = info.argc == unwrapArgc ? nullptr : info.argv[unwrapArgc];
380 NativeValue* result = nullptr;
381 std::unique_ptr<AsyncTask> uasyncTask =
382 CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
383 std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
384 RuntimeTask task = [&engine, asyncTask](int resultCode, const AAFwk::Want& want) {
385 HILOG_INFO("OnStartAbilityForResult async callback is called");
386 NativeValue* abilityResult = JsAbilityContext::WrapAbilityResult(engine, resultCode, want);
387 if (abilityResult == nullptr) {
388 HILOG_WARN("wrap abilityResult failed");
389 asyncTask->Reject(engine, CreateJsError(engine, 1, "failed to get result data!"));
390 } else {
391 asyncTask->Resolve(engine, abilityResult);
392 }
393 HILOG_INFO("OnStartAbilityForResult async callback is called end");
394 };
395 auto context = context_.lock();
396 if (context == nullptr) {
397 HILOG_WARN("context is released");
398 asyncTask->Reject(engine, CreateJsError(engine, 1, "context is released!"));
399 } else {
400 curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
401 (unwrapArgc == 1) ? context->StartAbilityForResult(want, curRequestCode_, std::move(task)) :
402 context->StartAbilityForResult(want, startOptions, curRequestCode_, std::move(task));
403 }
404 HILOG_INFO("OnStartAbilityForResult is called end");
405 return result;
406 }
407
OnStartAbilityForResultWithAccount(NativeEngine & engine,NativeCallbackInfo & info)408 NativeValue* JsAbilityContext::OnStartAbilityForResultWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
409 {
410 HILOG_INFO("OnStartAbilityForResultWithAccount is called");
411 if (info.argc == ARGC_ZERO) {
412 HILOG_ERROR("Not enough params");
413 return engine.CreateUndefined();
414 }
415 AAFwk::Want want;
416 if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
417 HILOG_ERROR("%s Failed to parse want!", __func__);
418 return engine.CreateUndefined();
419 }
420 InheritWindowMode(want);
421 decltype(info.argc) unwrapArgc = 1;
422 int32_t accountId = 0;
423 if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
424 reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
425 HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
426 return engine.CreateUndefined();
427 }
428 unwrapArgc++;
429 AAFwk::StartOptions startOptions;
430 if (info.argc > ARGC_TWO && info.argv[INDEX_TWO]->TypeOf() == NATIVE_OBJECT) {
431 HILOG_INFO("OnStartAbilityForResultWithAccount start options is used.");
432 AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
433 reinterpret_cast<napi_value>(info.argv[INDEX_TWO]), startOptions);
434 unwrapArgc++;
435 }
436 NativeValue* lastParam = info.argc == unwrapArgc ? nullptr : info.argv[unwrapArgc];
437 NativeValue* result = nullptr;
438 std::unique_ptr<AsyncTask> uasyncTask =
439 CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
440 std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
441 RuntimeTask task = [&engine, asyncTask](int resultCode, const AAFwk::Want& want) {
442 HILOG_INFO("OnStartAbilityForResultWithAccount async callback is called");
443 NativeValue* abilityResult = JsAbilityContext::WrapAbilityResult(engine, resultCode, want);
444 if (abilityResult == nullptr) {
445 HILOG_WARN("wrap abilityResult failed");
446 asyncTask->Reject(engine, CreateJsError(engine, 1, "failed to get result data!"));
447 } else {
448 asyncTask->Resolve(engine, abilityResult);
449 }
450 HILOG_INFO("OnStartAbilityForResultWithAccount async callback is called end");
451 };
452 auto context = context_.lock();
453 if (context == nullptr) {
454 HILOG_WARN("context is released");
455 asyncTask->Reject(engine, CreateJsError(engine, 1, "context is released!"));
456 } else {
457 curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
458 (unwrapArgc == INDEX_TWO) ? context->StartAbilityForResultWithAccount(
459 want, accountId, curRequestCode_, std::move(task)) : context->StartAbilityForResultWithAccount(
460 want, accountId, startOptions, curRequestCode_, std::move(task));
461 }
462 HILOG_INFO("OnStartAbilityForResultWithAccount is called end");
463 return result;
464 }
465
OnTerminateSelfWithResult(NativeEngine & engine,NativeCallbackInfo & info)466 NativeValue* JsAbilityContext::OnTerminateSelfWithResult(NativeEngine& engine, NativeCallbackInfo& info)
467 {
468 HILOG_INFO("OnTerminateSelfWithResult is called");
469
470 if (info.argc == 0) {
471 HILOG_ERROR("Not enough params");
472 return engine.CreateUndefined();
473 }
474
475 int resultCode = 0;
476 AAFwk::Want want;
477 if (!JsAbilityContext::UnWrapAbilityResult(engine, info.argv[0], resultCode, want)) {
478 HILOG_ERROR("%s Failed to parse ability result!", __func__);
479 return engine.CreateUndefined();
480 }
481
482 AsyncTask::CompleteCallback complete =
483 [weak = context_, want, resultCode](NativeEngine& engine, AsyncTask& task, int32_t status) {
484 auto context = weak.lock();
485 if (!context) {
486 HILOG_WARN("context is released");
487 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
488 return;
489 }
490
491 context->TerminateAbilityWithResult(want, resultCode);
492 task.Resolve(engine, engine.CreateUndefined());
493 };
494
495 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
496 NativeValue* result = nullptr;
497 AsyncTask::Schedule(
498 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
499 HILOG_INFO("OnTerminateSelfWithResult is called end");
500 return result;
501 }
502
OnConnectAbility(NativeEngine & engine,NativeCallbackInfo & info)503 NativeValue* JsAbilityContext::OnConnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
504 {
505 HILOG_INFO("OnConnectAbility is called");
506 // only support two params
507 if (info.argc != ARGC_TWO) {
508 HILOG_ERROR("Not enough params");
509 return engine.CreateUndefined();
510 }
511
512 // unwrap want
513 AAFwk::Want want;
514 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
515 reinterpret_cast<napi_value>(info.argv[0]), want);
516 HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
517 __func__,
518 want.GetBundle().c_str(),
519 want.GetElement().GetAbilityName().c_str());
520
521 // unwarp connection
522 sptr<JSAbilityConnection> connection = new JSAbilityConnection(engine);
523 connection->SetJsConnectionObject(info.argv[1]);
524 int64_t connectId = g_serialNumber;
525 ConnectionKey key;
526 key.id = g_serialNumber;
527 key.want = want;
528 abilityConnects_.emplace(key, connection);
529 if (g_serialNumber < INT64_MAX) {
530 g_serialNumber++;
531 } else {
532 g_serialNumber = 0;
533 }
534 HILOG_INFO("%{public}s not find connection, make new one:%{public}p.", __func__, connection.GetRefPtr());
535 AsyncTask::CompleteCallback complete =
536 [weak = context_, want, connection, connectId](NativeEngine& engine, AsyncTask& task, int32_t status) {
537 HILOG_INFO("OnConnectAbility begin");
538 auto context = weak.lock();
539 if (!context) {
540 HILOG_WARN("context is released");
541 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
542 return;
543 }
544 HILOG_INFO("context->ConnectAbility connection:%{public}d", (int32_t)connectId);
545 if (!context->ConnectAbility(want, connection)) {
546 connection->CallJsFailed(ERROR_CODE_ONE);
547 }
548 task.Resolve(engine, engine.CreateUndefined());
549 };
550 NativeValue* result = nullptr;
551 AsyncTask::Schedule(
552 engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
553 return engine.CreateNumber(connectId);
554 }
555
OnConnectAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)556 NativeValue* JsAbilityContext::OnConnectAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
557 {
558 HILOG_INFO("OnConnectAbility is called");
559 // only support three params
560 if (info.argc != ARGC_THREE) {
561 HILOG_ERROR("Not enough params");
562 return engine.CreateUndefined();
563 }
564
565 // unwrap want
566 AAFwk::Want want;
567 OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
568 reinterpret_cast<napi_value>(info.argv[0]), want);
569 HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
570 __func__,
571 want.GetBundle().c_str(),
572 want.GetElement().GetAbilityName().c_str());
573
574 int32_t accountId = 0;
575 if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
576 reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
577 HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
578 return engine.CreateUndefined();
579 }
580
581 // unwarp connection
582 sptr<JSAbilityConnection> connection = new JSAbilityConnection(engine);
583 connection->SetJsConnectionObject(info.argv[INDEX_TWO]);
584 int64_t connectId = g_serialNumber;
585 ConnectionKey key;
586 key.id = g_serialNumber;
587 key.want = want;
588 abilityConnects_.emplace(key, connection);
589 if (g_serialNumber < INT64_MAX) {
590 g_serialNumber++;
591 } else {
592 g_serialNumber = 0;
593 }
594 HILOG_INFO("%{public}s not find connection, make new one:%{public}p.", __func__, connection.GetRefPtr());
595 AsyncTask::CompleteCallback complete =
596 [weak = context_, want, accountId, connection, connectId](
597 NativeEngine& engine, AsyncTask& task, int32_t status) {
598 HILOG_INFO("OnConnectAbilityWithAccount begin");
599 auto context = weak.lock();
600 if (!context) {
601 HILOG_WARN("context is released");
602 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
603 return;
604 }
605 HILOG_INFO("context->ConnectAbilityWithAccount connection:%{public}d", (int32_t)connectId);
606 if (!context->ConnectAbilityWithAccount(want, accountId, connection)) {
607 connection->CallJsFailed(ERROR_CODE_ONE);
608 }
609 task.Resolve(engine, engine.CreateUndefined());
610 };
611 NativeValue* result = nullptr;
612 AsyncTask::Schedule(
613 engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
614 return engine.CreateNumber(connectId);
615 }
616
OnDisconnectAbility(NativeEngine & engine,NativeCallbackInfo & info)617 NativeValue* JsAbilityContext::OnDisconnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
618 {
619 HILOG_INFO("OnDisconnectAbility is called");
620 // only support one or two params
621 if (info.argc != ARGC_ONE && info.argc != ARGC_TWO) {
622 HILOG_ERROR("Not enough params");
623 return engine.CreateUndefined();
624 }
625
626 // unwrap want
627 AAFwk::Want want;
628 // unwrap connectId
629 int64_t connectId = -1;
630 sptr<JSAbilityConnection> connection = nullptr;
631 napi_get_value_int64(reinterpret_cast<napi_env>(&engine),
632 reinterpret_cast<napi_value>(info.argv[0]), &connectId);
633 HILOG_INFO("OnDisconnectAbility connection:%{public}d", (int32_t)connectId);
634 auto item = std::find_if(abilityConnects_.begin(),
635 abilityConnects_.end(),
636 [&connectId](const std::map<ConnectionKey, sptr<JSAbilityConnection>>::value_type &obj) {
637 return connectId == obj.first.id;
638 });
639 if (item != abilityConnects_.end()) {
640 // match id
641 want = item->first.want;
642 connection = item->second;
643 HILOG_INFO("%{public}s find conn ability:%{public}p exist", __func__, item->second.GetRefPtr());
644 } else {
645 HILOG_INFO("%{public}s not find conn exist.", __func__);
646 }
647 // begin disconnect
648 AsyncTask::CompleteCallback complete =
649 [weak = context_, want, connection](
650 NativeEngine& engine, AsyncTask& task, int32_t status) {
651 HILOG_INFO("OnDisconnectAbility begin");
652 auto context = weak.lock();
653 if (!context) {
654 HILOG_WARN("context is released");
655 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
656 return;
657 }
658 if (connection == nullptr) {
659 HILOG_WARN("connection nullptr");
660 task.Reject(engine, CreateJsError(engine, 2, "not found connection"));
661 return;
662 }
663 HILOG_INFO("context->DisconnectAbility");
664 context->DisconnectAbility(want, connection);
665 task.Resolve(engine, engine.CreateUndefined());
666 };
667
668 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
669 NativeValue* result = nullptr;
670 AsyncTask::Schedule(
671 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
672 return result;
673 }
674
OnTerminateSelf(NativeEngine & engine,NativeCallbackInfo & info)675 NativeValue* JsAbilityContext::OnTerminateSelf(NativeEngine& engine, NativeCallbackInfo& info)
676 {
677 HILOG_INFO("OnTerminateSelf is called");
678
679 if (info.argc != ARGC_ZERO && info.argc != ARGC_ONE) {
680 HILOG_ERROR("Not enough params");
681 return engine.CreateUndefined();
682 }
683
684 AsyncTask::CompleteCallback complete =
685 [weak = context_](NativeEngine& engine, AsyncTask& task, int32_t status) {
686 auto context = weak.lock();
687 if (!context) {
688 HILOG_WARN("context is released");
689 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
690 return;
691 }
692
693 auto errcode = context->TerminateSelf();
694 if (errcode == 0) {
695 task.Resolve(engine, engine.CreateUndefined());
696 } else {
697 task.Reject(engine, CreateJsError(engine, errcode, "Terminate Ability failed."));
698 }
699 };
700
701 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
702 NativeValue* result = nullptr;
703 AsyncTask::Schedule(
704 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
705 return result;
706 }
707
OnRequestPermissionsFromUser(NativeEngine & engine,NativeCallbackInfo & info)708 NativeValue* JsAbilityContext::OnRequestPermissionsFromUser(NativeEngine& engine, NativeCallbackInfo& info)
709 {
710 HILOG_INFO("OnRequestPermissionsFromUser is called");
711
712 if (info.argc != ARGC_ONE && info.argc != ARGC_TWO) {
713 HILOG_ERROR("Not enough params");
714 return engine.CreateUndefined();
715 }
716
717 std::vector<std::string> permissionList;
718 if (!OHOS::AppExecFwk::UnwrapArrayStringFromJS(reinterpret_cast<napi_env>(&engine),
719 reinterpret_cast<napi_value>(info.argv[0]), permissionList)) {
720 HILOG_ERROR("%{public}s called, the first parameter is invalid.", __func__);
721 return engine.CreateUndefined();
722 }
723
724 if (permissionList.size() == 0) {
725 HILOG_ERROR("%{public}s called, params do not meet specification.", __func__);
726 }
727
728 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[ARGC_ONE];
729 NativeValue* result = nullptr;
730 auto uasyncTask = CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
731 std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
732 PermissionRequestTask task =
733 [&engine, asyncTask](const std::vector<std::string> &permissions, const std::vector<int> &grantResults) {
734 HILOG_INFO("OnRequestPermissionsFromUser async callback is called");
735 NativeValue* requestResult = JsAbilityContext::WrapPermissionRequestResult(engine, permissions, grantResults);
736 if (requestResult == nullptr) {
737 HILOG_WARN("wrap requestResult failed");
738 asyncTask->Reject(engine, CreateJsError(engine, 1, "failed to get granted result data!"));
739 } else {
740 asyncTask->Resolve(engine, requestResult);
741 }
742 HILOG_INFO("OnRequestPermissionsFromUser async callback is called end");
743 };
744 auto context = context_.lock();
745 if (context == nullptr) {
746 HILOG_WARN("context is released");
747 asyncTask->Reject(engine, CreateJsError(engine, 1, "context is released!"));
748 } else {
749 curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
750 context->RequestPermissionsFromUser(permissionList, curRequestCode_, std::move(task));
751 }
752 HILOG_INFO("OnRequestPermissionsFromUser is called end");
753 return result;
754 }
755
OnRestoreWindowStage(NativeEngine & engine,NativeCallbackInfo & info)756 NativeValue* JsAbilityContext::OnRestoreWindowStage(NativeEngine& engine, NativeCallbackInfo& info)
757 {
758 HILOG_INFO("OnRestoreWindowStage is called, argc = %{public}d", static_cast<int>(info.argc));
759 if (info.argc != ARGC_ONE) {
760 HILOG_ERROR("OnRestoreWindowStage need one parameters");
761 return engine.CreateUndefined();
762 }
763 auto context = context_.lock();
764 if (!context) {
765 HILOG_ERROR("OnRestoreWindowStage context is released");
766 return engine.CreateUndefined();
767 }
768 auto errcode = context->RestoreWindowStage(engine, info.argv[0]);
769 if (errcode != 0) {
770 return CreateJsError(engine, errcode, "RestoreWindowStage failed.");
771 }
772 return engine.CreateUndefined();
773 }
774
OnSetMissionLabel(NativeEngine & engine,NativeCallbackInfo & info)775 NativeValue* JsAbilityContext::OnSetMissionLabel(NativeEngine& engine, NativeCallbackInfo& info)
776 {
777 HILOG_INFO("OnSetMissionLabel is called, argc = %{public}d", static_cast<int>(info.argc));
778
779 if (info.argc < ARGC_ONE) {
780 HILOG_ERROR("OnSetMissionLabel, Not enough params");
781 return engine.CreateUndefined();
782 }
783
784 int32_t errorCode = 0;
785 std::string label;
786 if (!ConvertFromJsValue(engine, info.argv[0], label)) {
787 HILOG_ERROR("OnSetMissionLabel, parse label failed.");
788 errorCode = ERR_NOTOK;
789 }
790
791 AsyncTask::CompleteCallback complete =
792 [weak = context_, label, errorCode](NativeEngine& engine, AsyncTask& task, int32_t status) {
793 if (errorCode != 0) {
794 task.Reject(engine, CreateJsError(engine, errorCode, "Invalidate params."));
795 return;
796 }
797
798 auto context = weak.lock();
799 if (!context) {
800 HILOG_WARN("context is released");
801 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
802 return;
803 }
804
805 auto errcode = context->SetMissionLabel(label);
806 if (errcode == 0) {
807 task.Resolve(engine, engine.CreateUndefined());
808 } else {
809 task.Reject(engine, CreateJsError(engine, errcode, "SetMissionLabel failed."));
810 }
811 };
812
813 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
814 NativeValue* result = nullptr;
815 AsyncTask::Schedule(
816 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
817 return result;
818 }
819
820 #ifdef SUPPORT_GRAPHICS
OnSetMissionIcon(NativeEngine & engine,NativeCallbackInfo & info)821 NativeValue* JsAbilityContext::OnSetMissionIcon(NativeEngine& engine, NativeCallbackInfo& info)
822 {
823 HILOG_INFO("OnSetMissionIcon is called, argc = %{public}d", static_cast<int>(info.argc));
824 if (info.argc < ARGC_ONE) {
825 HILOG_ERROR("OnSetMissionIcon, Not enough params");
826 return engine.CreateUndefined();
827 }
828
829 int32_t errorCode = 0;
830 auto icon = OHOS::Media::PixelMapNapi::GetPixelMap(reinterpret_cast<napi_env>(&engine),
831 reinterpret_cast<napi_value>(info.argv[0]));
832 if (!icon) {
833 HILOG_ERROR("OnSetMissionIcon, parse icon failed.");
834 errorCode = ERR_NOTOK;
835 }
836
837 AsyncTask::CompleteCallback complete =
838 [weak = context_, icon, errorCode](NativeEngine& engine, AsyncTask& task, int32_t status) {
839 if (errorCode != 0) {
840 task.Reject(engine, CreateJsError(engine, errorCode, "Invalidate params."));
841 return;
842 }
843
844 auto context = weak.lock();
845 if (!context) {
846 HILOG_WARN("context is released when set mission icon");
847 task.Reject(engine, CreateJsError(engine, -1, "Context is released"));
848 return;
849 }
850
851 auto errcode = context->SetMissionIcon(icon);
852 if (errcode == 0) {
853 task.Resolve(engine, engine.CreateUndefined());
854 } else {
855 task.Reject(engine, CreateJsError(engine, errcode, "SetMissionIcon failed."));
856 }
857 };
858
859 NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[1];
860 NativeValue* result = nullptr;
861 AsyncTask::Schedule(
862 engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
863 return result;
864 }
865 #endif
866
UnWrapWant(NativeEngine & engine,NativeValue * argv,AAFwk::Want & want)867 bool JsAbilityContext::UnWrapWant(NativeEngine& engine, NativeValue* argv, AAFwk::Want& want)
868 {
869 if (argv == nullptr) {
870 HILOG_WARN("%s argv == nullptr!", __func__);
871 return false;
872 }
873 return AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(argv), want);
874 }
875
WrapWant(NativeEngine & engine,const AAFwk::Want & want)876 NativeValue* JsAbilityContext::WrapWant(NativeEngine& engine, const AAFwk::Want& want)
877 {
878 return reinterpret_cast<NativeValue*>(AppExecFwk::WrapWant(reinterpret_cast<napi_env>(&engine), want));
879 }
880
UnWrapAbilityResult(NativeEngine & engine,NativeValue * argv,int & resultCode,AAFwk::Want & want)881 bool JsAbilityContext::UnWrapAbilityResult(NativeEngine& engine, NativeValue* argv, int& resultCode, AAFwk::Want& want)
882 {
883 if (argv == nullptr) {
884 HILOG_WARN("%s argv == nullptr!", __func__);
885 return false;
886 }
887 if (argv->TypeOf() != NativeValueType::NATIVE_OBJECT) {
888 HILOG_WARN("%s invalid type of abilityResult!", __func__);
889 return false;
890 }
891 NativeObject* jObj = ConvertNativeValueTo<NativeObject>(argv);
892 NativeValue* jResultCode = jObj->GetProperty("resultCode");
893 if (jResultCode == nullptr) {
894 HILOG_WARN("%s jResultCode == nullptr!", __func__);
895 return false;
896 }
897 if (jResultCode->TypeOf() != NativeValueType::NATIVE_NUMBER) {
898 HILOG_WARN("%s invalid type of resultCode!", __func__);
899 return false;
900 }
901 resultCode = int64_t(*ConvertNativeValueTo<NativeNumber>(jObj->GetProperty("resultCode")));
902 NativeValue* jWant = jObj->GetProperty("want");
903 if (jWant == nullptr) {
904 HILOG_WARN("%s jWant == nullptr!", __func__);
905 return false;
906 }
907 if (jWant->TypeOf() != NativeValueType::NATIVE_OBJECT) {
908 HILOG_WARN("%s invalid type of want!", __func__);
909 return false;
910 }
911 return JsAbilityContext::UnWrapWant(engine, jWant, want);
912 }
913
WrapAbilityResult(NativeEngine & engine,const int & resultCode,const AAFwk::Want & want)914 NativeValue* JsAbilityContext::WrapAbilityResult(NativeEngine& engine, const int& resultCode, const AAFwk::Want& want)
915 {
916 NativeValue* jAbilityResult = engine.CreateObject();
917 NativeObject* abilityResult = ConvertNativeValueTo<NativeObject>(jAbilityResult);
918 abilityResult->SetProperty("resultCode", engine.CreateNumber(resultCode));
919 abilityResult->SetProperty("want", JsAbilityContext::WrapWant(engine, want));
920 return jAbilityResult;
921 }
922
WrapPermissionRequestResult(NativeEngine & engine,const std::vector<std::string> & permissions,const std::vector<int> & grantResults)923 NativeValue* JsAbilityContext::WrapPermissionRequestResult(NativeEngine& engine,
924 const std::vector<std::string> &permissions, const std::vector<int> &grantResults)
925 {
926 NativeValue* jsPermissionRequestResult = engine.CreateObject();
927 NativeObject* permissionRequestResult = ConvertNativeValueTo<NativeObject>(jsPermissionRequestResult);
928 permissionRequestResult->SetProperty("permissions", CreateNativeArray(engine, permissions));
929 permissionRequestResult->SetProperty("authResults", CreateNativeArray(engine, grantResults));
930 return jsPermissionRequestResult;
931 }
932
InheritWindowMode(AAFwk::Want & want)933 void JsAbilityContext::InheritWindowMode(AAFwk::Want &want)
934 {
935 HILOG_INFO("%{public}s called.", __func__);
936 #ifdef SUPPORT_GRAPHICS
937 // only split mode need inherit
938 auto context = context_.lock();
939 if (!context) {
940 HILOG_ERROR("context is nullptr.");
941 return;
942 }
943 auto windowMode = context->GetCurrentWindowMode();
944 if (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY ||
945 windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) {
946 want.SetParam(Want::PARAM_RESV_WINDOW_MODE, windowMode);
947 }
948 HILOG_INFO("%{public}s called end. window mode is %{public}d", __func__, windowMode);
949 #endif
950 }
951
ConfigurationUpdated(NativeEngine * engine,std::shared_ptr<NativeReference> & jsContext,const std::shared_ptr<AppExecFwk::Configuration> & config)952 void JsAbilityContext::ConfigurationUpdated(NativeEngine* engine, std::shared_ptr<NativeReference> &jsContext,
953 const std::shared_ptr<AppExecFwk::Configuration> &config)
954 {
955 HILOG_INFO("ConfigurationUpdated begin.");
956 if (jsContext == nullptr || config == nullptr) {
957 HILOG_INFO("jsContext is nullptr.");
958 return;
959 }
960
961 NativeValue* value = jsContext->Get();
962 NativeObject* object = ConvertNativeValueTo<NativeObject>(value);
963 if (object == nullptr) {
964 HILOG_INFO("object is nullptr.");
965 return;
966 }
967
968 NativeValue* method = object->GetProperty("onUpdateConfiguration");
969 if (method == nullptr) {
970 HILOG_ERROR("Failed to get onUpdateConfiguration from object");
971 return;
972 }
973 HILOG_INFO("JSAbilityConnection::CallFunction onUpdateConfiguration, success");
974
975 HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
976 NativeValue* argv[] = {CreateJsConfiguration(*engine, *config)};
977 engine->CallFunction(value, method, argv, ARGC_ONE);
978 }
979
CreateJsAbilityContext(NativeEngine & engine,std::shared_ptr<AbilityContext> context)980 NativeValue* CreateJsAbilityContext(NativeEngine& engine, std::shared_ptr<AbilityContext> context)
981 {
982 NativeValue* objValue = CreateJsBaseContext(engine, context);
983 NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
984
985 std::unique_ptr<JsAbilityContext> jsContext = std::make_unique<JsAbilityContext>(context);
986 object->SetNativePointer(jsContext.release(), JsAbilityContext::Finalizer, nullptr);
987
988 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
989
990 auto abilityInfo = context->GetAbilityInfo();
991 if (abilityInfo != nullptr) {
992 object->SetProperty("abilityInfo", CreateJsAbilityInfo(engine, *abilityInfo));
993 }
994
995 auto configuration = context->GetConfiguration();
996 if (configuration != nullptr) {
997 object->SetProperty("config", CreateJsConfiguration(engine, *configuration));
998 }
999
1000 BindNativeFunction(engine, *object, "startAbility", JsAbilityContext::StartAbility);
1001 BindNativeFunction(engine, *object, "startAbilityWithAccount", JsAbilityContext::StartAbilityWithAccount);
1002 BindNativeFunction(engine, *object, "startAbilityByCall", JsAbilityContext::StartAbilityByCall);
1003 BindNativeFunction(engine, *object, "startAbilityForResult", JsAbilityContext::StartAbilityForResult);
1004 BindNativeFunction(engine, *object, "startAbilityForResultWithAccount",
1005 JsAbilityContext::StartAbilityForResultWithAccount);
1006 BindNativeFunction(engine, *object, "connectAbility", JsAbilityContext::ConnectAbility);
1007 BindNativeFunction(engine, *object, "connectAbilityWithAccount", JsAbilityContext::ConnectAbilityWithAccount);
1008 BindNativeFunction(engine, *object, "disconnectAbility", JsAbilityContext::DisconnectAbility);
1009 BindNativeFunction(engine, *object, "terminateSelf", JsAbilityContext::TerminateSelf);
1010 BindNativeFunction(engine, *object, "terminateSelfWithResult", JsAbilityContext::TerminateSelfWithResult);
1011 BindNativeFunction(engine, *object, "requestPermissionsFromUser", JsAbilityContext::RequestPermissionsFromUser);
1012 BindNativeFunction(engine, *object, "restoreWindowStage", JsAbilityContext::RestoreWindowStage);
1013 BindNativeFunction(engine, *object, "setMissionLabel", JsAbilityContext::SetMissionLabel);
1014
1015 #ifdef SUPPORT_GRAPHICS
1016 BindNativeFunction(engine, *object, "setMissionIcon", JsAbilityContext::SetMissionIcon);
1017 #endif
1018 return objValue;
1019 }
1020
JSAbilityConnection(NativeEngine & engine)1021 JSAbilityConnection::JSAbilityConnection(NativeEngine& engine) : engine_(engine) {}
1022
1023 JSAbilityConnection::~JSAbilityConnection() = default;
1024
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)1025 void JSAbilityConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
1026 const sptr<IRemoteObject> &remoteObject, int resultCode)
1027 {
1028 HILOG_INFO("OnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
1029 if (handler_ == nullptr) {
1030 HILOG_INFO("handler_ nullptr");
1031 return;
1032 }
1033
1034 wptr<JSAbilityConnection> connection = this;
1035 auto task = [connection, element, remoteObject, resultCode] {
1036 sptr<JSAbilityConnection> connectionSptr = connection.promote();
1037 if (!connectionSptr) {
1038 HILOG_INFO("connectionSptr nullptr");
1039 return;
1040 }
1041 connectionSptr->HandleOnAbilityConnectDone(element, remoteObject, resultCode);
1042 };
1043 handler_->PostTask(task, "OnAbilityConnectDone");
1044 }
1045
HandleOnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)1046 void JSAbilityConnection::HandleOnAbilityConnectDone(const AppExecFwk::ElementName &element,
1047 const sptr<IRemoteObject> &remoteObject, int resultCode)
1048 {
1049 HILOG_INFO("HandleOnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
1050 if (jsConnectionObject_ == nullptr) {
1051 HILOG_ERROR("jsConnectionObject_ nullptr");
1052 return;
1053 }
1054 NativeValue* value = jsConnectionObject_->Get();
1055 NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1056 if (obj == nullptr) {
1057 HILOG_ERROR("Failed to get object");
1058 return;
1059 }
1060 NativeValue* methodOnConnect = obj->GetProperty("onConnect");
1061 if (methodOnConnect == nullptr) {
1062 HILOG_ERROR("Failed to get onConnect from object");
1063 return;
1064 }
1065 HILOG_INFO("JSAbilityConnection::CallFunction onConnect, success");
1066
1067 // wrap RemoteObject
1068 HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
1069 napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
1070 reinterpret_cast<napi_env>(&engine_), remoteObject);
1071 NativeValue* nativeRemoteObject = reinterpret_cast<NativeValue*>(napiRemoteObject);
1072 NativeValue* argv[] = { ConvertElement(element), nativeRemoteObject };
1073 engine_.CallFunction(value, methodOnConnect, argv, ARGC_TWO);
1074 HILOG_INFO("OnAbilityConnectDone end");
1075 }
1076
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)1077 void JSAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
1078 {
1079 HILOG_INFO("OnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
1080 if (handler_ == nullptr) {
1081 HILOG_INFO("handler_ nullptr");
1082 return;
1083 }
1084
1085 wptr<JSAbilityConnection> connection = this;
1086 auto task = [connection, element, resultCode] {
1087 sptr<JSAbilityConnection> connectionSptr = connection.promote();
1088 if (!connectionSptr) {
1089 HILOG_INFO("connectionSptr nullptr");
1090 return;
1091 }
1092 connectionSptr->HandleOnAbilityDisconnectDone(element, resultCode);
1093 };
1094 handler_->PostTask(task, "OnAbilityDisconnectDone");
1095 }
1096
HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)1097 void JSAbilityConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
1098 int resultCode)
1099 {
1100 HILOG_INFO("HandleOnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
1101 if (jsConnectionObject_ == nullptr) {
1102 HILOG_ERROR("jsConnectionObject_ nullptr");
1103 return;
1104 }
1105 NativeValue* value = jsConnectionObject_->Get();
1106 NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1107 if (obj == nullptr) {
1108 HILOG_ERROR("Failed to get object");
1109 return;
1110 }
1111
1112 NativeValue* method = obj->GetProperty("onDisconnect");
1113 if (method == nullptr) {
1114 HILOG_ERROR("Failed to get onDisconnect from object");
1115 return;
1116 }
1117
1118 // release connect
1119 HILOG_INFO("OnAbilityDisconnectDone abilityConnects_.size:%{public}zu", abilityConnects_.size());
1120 std::string bundleName = element.GetBundleName();
1121 std::string abilityName = element.GetAbilityName();
1122 auto item = std::find_if(abilityConnects_.begin(), abilityConnects_.end(),
1123 [bundleName, abilityName] (
1124 const std::map<ConnectionKey, sptr<JSAbilityConnection>>::value_type &obj) {
1125 return (bundleName == obj.first.want.GetBundle()) &&
1126 (abilityName == obj.first.want.GetElement().GetAbilityName());
1127 });
1128 if (item != abilityConnects_.end()) {
1129 // match bundlename && abilityname
1130 abilityConnects_.erase(item);
1131 HILOG_INFO("OnAbilityDisconnectDone erase abilityConnects_.size:%{public}zu", abilityConnects_.size());
1132 }
1133
1134 NativeValue* argv[] = { ConvertElement(element) };
1135 HILOG_INFO("OnAbilityDisconnectDone CallFunction success");
1136 engine_.CallFunction(value, method, argv, ARGC_ONE);
1137 }
1138
CallJsFailed(int32_t errorCode)1139 void JSAbilityConnection::CallJsFailed(int32_t errorCode)
1140 {
1141 HILOG_INFO("CallJsFailed begin");
1142 if (jsConnectionObject_ == nullptr) {
1143 HILOG_ERROR("jsConnectionObject_ nullptr");
1144 return;
1145 }
1146 NativeValue* value = jsConnectionObject_->Get();
1147 NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1148 if (obj == nullptr) {
1149 HILOG_ERROR("Failed to get object");
1150 return;
1151 }
1152
1153 NativeValue* method = obj->GetProperty("onFailed");
1154 if (method == nullptr) {
1155 HILOG_ERROR("Failed to get onFailed from object");
1156 return;
1157 }
1158
1159 NativeValue* argv[] = {engine_.CreateNumber(errorCode)};
1160 HILOG_INFO("CallJsFailed CallFunction success");
1161 engine_.CallFunction(value, method, argv, ARGC_ONE);
1162 HILOG_INFO("CallJsFailed end");
1163 }
1164
ConvertElement(const AppExecFwk::ElementName & element)1165 NativeValue* JSAbilityConnection::ConvertElement(const AppExecFwk::ElementName &element)
1166 {
1167 napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
1168 return reinterpret_cast<NativeValue*>(napiElementName);
1169 }
1170
SetJsConnectionObject(NativeValue * jsConnectionObject)1171 void JSAbilityConnection::SetJsConnectionObject(NativeValue* jsConnectionObject)
1172 {
1173 jsConnectionObject_ = std::unique_ptr<NativeReference>(engine_.CreateReference(jsConnectionObject, 1));
1174 }
1175 } // namespace AbilityRuntime
1176 } // namespace OHOS