• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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