• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "hitrace_meter.h"
21 #include "hilog_wrapper.h"
22 #include "js_context_utils.h"
23 #include "js_data_struct_converter.h"
24 #include "js_error_utils.h"
25 #include "js_runtime_utils.h"
26 #include "ability_runtime/js_caller_complex.h"
27 #include "napi_common_ability.h"
28 #include "napi_common_start_options.h"
29 #include "napi_common_util.h"
30 #include "napi_common_want.h"
31 #include "napi_remote_object.h"
32 #include "start_options.h"
33 #include "want.h"
34 #include "event_handler.h"
35 #include "hitrace_meter.h"
36 
37 #ifdef SUPPORT_GRAPHICS
38 #include "pixel_map_napi.h"
39 #endif
40 
41 namespace OHOS {
42 namespace AbilityRuntime {
43 constexpr int32_t INDEX_TWO = 2;
44 constexpr size_t ARGC_ZERO = 0;
45 constexpr size_t ARGC_ONE = 1;
46 constexpr size_t ARGC_TWO = 2;
47 constexpr size_t ARGC_THREE = 3;
48 constexpr int32_t ERROR_CODE_ONE = 1;
49 
50 class StartAbilityByCallParameters {
51 public:
52     int err = 0;
53     sptr<IRemoteObject> remoteCallee = nullptr;
54     std::shared_ptr<CallerCallBack> callerCallBack = nullptr;
55     std::mutex mutexlock;
56     std::condition_variable condition;
57 };
58 
Finalizer(NativeEngine * engine,void * data,void * hint)59 void JsAbilityContext::Finalizer(NativeEngine* engine, void* data, void* hint)
60 {
61     HILOG_INFO("JsAbilityContext::Finalizer is called");
62     std::unique_ptr<JsAbilityContext>(static_cast<JsAbilityContext*>(data));
63 }
64 
StartAbility(NativeEngine * engine,NativeCallbackInfo * info)65 NativeValue* JsAbilityContext::StartAbility(NativeEngine* engine, NativeCallbackInfo* info)
66 {
67     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
68     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
69     return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr;
70 }
71 
StartRecentAbility(NativeEngine * engine,NativeCallbackInfo * info)72 NativeValue* JsAbilityContext::StartRecentAbility(NativeEngine* engine, NativeCallbackInfo* info)
73 {
74     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
75     return (me != nullptr) ? me->OnStartAbility(*engine, *info, true) : nullptr;
76 }
77 
StartAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)78 NativeValue* JsAbilityContext::StartAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
79 {
80     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
81     return (me != nullptr) ? me->OnStartAbilityWithAccount(*engine, *info) : nullptr;
82 }
83 
StartAbilityByCall(NativeEngine * engine,NativeCallbackInfo * info)84 NativeValue* JsAbilityContext::StartAbilityByCall(NativeEngine* engine, NativeCallbackInfo* info)
85 {
86     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
87     return (me != nullptr) ? me->OnStartAbilityByCall(*engine, *info) : nullptr;
88 }
89 
StartAbilityForResult(NativeEngine * engine,NativeCallbackInfo * info)90 NativeValue* JsAbilityContext::StartAbilityForResult(NativeEngine* engine, NativeCallbackInfo* info)
91 {
92     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
93     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
94     return (me != nullptr) ? me->OnStartAbilityForResult(*engine, *info) : nullptr;
95 }
96 
StartAbilityForResultWithAccount(NativeEngine * engine,NativeCallbackInfo * info)97 NativeValue* JsAbilityContext::StartAbilityForResultWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
98 {
99     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
100     return (me != nullptr) ? me->OnStartAbilityForResultWithAccount(*engine, *info) : nullptr;
101 }
102 
StartServiceExtensionAbility(NativeEngine * engine,NativeCallbackInfo * info)103 NativeValue* JsAbilityContext::StartServiceExtensionAbility(NativeEngine* engine, NativeCallbackInfo* info)
104 {
105     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
106     return (me != nullptr) ? me->OnStartExtensionAbility(*engine, *info) : nullptr;
107 }
108 
StartServiceExtensionAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)109 NativeValue* JsAbilityContext::StartServiceExtensionAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
110 {
111     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
112     return (me != nullptr) ? me->OnStartExtensionAbilityWithAccount(*engine, *info) : nullptr;
113 }
114 
StopServiceExtensionAbility(NativeEngine * engine,NativeCallbackInfo * info)115 NativeValue* JsAbilityContext::StopServiceExtensionAbility(NativeEngine* engine, NativeCallbackInfo* info)
116 {
117     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
118     return (me != nullptr) ? me->OnStopExtensionAbility(*engine, *info) : nullptr;
119 }
120 
StopServiceExtensionAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)121 NativeValue* JsAbilityContext::StopServiceExtensionAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
122 {
123     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
124     return (me != nullptr) ? me->OnStopExtensionAbilityWithAccount(*engine, *info) : nullptr;
125 }
126 
ConnectAbility(NativeEngine * engine,NativeCallbackInfo * info)127 NativeValue* JsAbilityContext::ConnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
128 {
129     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
130     return (me != nullptr) ? me->OnConnectAbility(*engine, *info) : nullptr;
131 }
132 
ConnectAbilityWithAccount(NativeEngine * engine,NativeCallbackInfo * info)133 NativeValue* JsAbilityContext::ConnectAbilityWithAccount(NativeEngine* engine, NativeCallbackInfo* info)
134 {
135     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
136     return (me != nullptr) ? me->OnConnectAbilityWithAccount(*engine, *info) : nullptr;
137 }
138 
DisconnectAbility(NativeEngine * engine,NativeCallbackInfo * info)139 NativeValue* JsAbilityContext::DisconnectAbility(NativeEngine* engine, NativeCallbackInfo* info)
140 {
141     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
142     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
143     return (me != nullptr) ? me->OnDisconnectAbility(*engine, *info) : nullptr;
144 }
145 
TerminateSelf(NativeEngine * engine,NativeCallbackInfo * info)146 NativeValue* JsAbilityContext::TerminateSelf(NativeEngine* engine, NativeCallbackInfo* info)
147 {
148     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
149     return (me != nullptr) ? me->OnTerminateSelf(*engine, *info) : nullptr;
150 }
151 
TerminateSelfWithResult(NativeEngine * engine,NativeCallbackInfo * info)152 NativeValue* JsAbilityContext::TerminateSelfWithResult(NativeEngine* engine, NativeCallbackInfo* info)
153 {
154     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
155     return (me != nullptr) ? me->OnTerminateSelfWithResult(*engine, *info) : nullptr;
156 }
157 
RequestPermissionsFromUser(NativeEngine * engine,NativeCallbackInfo * info)158 NativeValue* JsAbilityContext::RequestPermissionsFromUser(NativeEngine* engine, NativeCallbackInfo* info)
159 {
160     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
161     return (me != nullptr) ? me->OnRequestPermissionsFromUser(*engine, *info) : nullptr;
162 }
163 
RestoreWindowStage(NativeEngine * engine,NativeCallbackInfo * info)164 NativeValue* JsAbilityContext::RestoreWindowStage(NativeEngine* engine, NativeCallbackInfo* info)
165 {
166     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
167     return (me != nullptr) ? me->OnRestoreWindowStage(*engine, *info) : nullptr;
168 }
169 
RequestDialogService(NativeEngine * engine,NativeCallbackInfo * info)170 NativeValue* JsAbilityContext::RequestDialogService(NativeEngine* engine, NativeCallbackInfo* info)
171 {
172     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
173     return (me != nullptr) ? me->OnRequestDialogService(*engine, *info) : nullptr;
174 }
175 
IsTerminating(NativeEngine * engine,NativeCallbackInfo * info)176 NativeValue* JsAbilityContext::IsTerminating(NativeEngine* engine, NativeCallbackInfo* info)
177 {
178     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
179     return (me != nullptr) ? me->OnIsTerminating(*engine, *info) : nullptr;
180 }
181 
OnStartAbility(NativeEngine & engine,NativeCallbackInfo & info,bool isStartRecent)182 NativeValue* JsAbilityContext::OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info, bool isStartRecent)
183 {
184     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
185     HILOG_INFO("OnStartAbility is called.");
186 
187     if (info.argc == ARGC_ZERO) {
188         HILOG_ERROR("Not enough params");
189         ThrowTooFewParametersError(engine);
190         return engine.CreateUndefined();
191     }
192 
193     AAFwk::Want want;
194     OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[0]), want);
195     InheritWindowMode(want);
196     decltype(info.argc) unwrapArgc = 1;
197     HILOG_INFO("Start ability, ability name is %{public}s.", want.GetElement().GetAbilityName().c_str());
198     AAFwk::StartOptions startOptions;
199     if (info.argc > ARGC_ONE && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
200         HILOG_INFO("OnStartAbility start options is used.");
201         AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
202             reinterpret_cast<napi_value>(info.argv[1]), startOptions);
203         unwrapArgc++;
204     }
205 
206     if (isStartRecent) {
207         HILOG_INFO("OnStartRecentAbility is called");
208         want.SetParam(Want::PARAM_RESV_START_RECENT, true);
209     }
210 
211     AsyncTask::CompleteCallback complete =
212         [weak = context_, want, startOptions, unwrapArgc](NativeEngine& engine, AsyncTask& task, int32_t status) {
213             auto context = weak.lock();
214             if (!context) {
215                 HILOG_WARN("context is released");
216                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
217                 return;
218             }
219             auto innerErrorCode = (unwrapArgc == 1) ?
220                 context->StartAbility(want, -1) : context->StartAbility(want, startOptions, -1);
221             if (innerErrorCode == 0) {
222                 task.Resolve(engine, engine.CreateUndefined());
223             } else {
224                 task.Reject(engine, CreateJsErrorByNativeErr(engine, innerErrorCode));
225             }
226         };
227 
228     NativeValue* lastParam = (info.argc > unwrapArgc) ? info.argv[unwrapArgc] : nullptr;
229     NativeValue* result = nullptr;
230     AsyncTask::Schedule("JsAbilityContext::OnStartAbility",
231         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
232     return result;
233 }
234 
OnStartAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)235 NativeValue* JsAbilityContext::OnStartAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
236 {
237     HILOG_INFO("OnStartAbilityWithAccount is called");
238     if (info.argc < ARGC_TWO) {
239         ThrowTooFewParametersError(engine);
240         return engine.CreateUndefined();
241     }
242     AAFwk::Want want;
243     OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[0]), want);
244     InheritWindowMode(want);
245     decltype(info.argc) unwrapArgc = 1;
246     HILOG_INFO("abilityName=%{public}s", want.GetElement().GetAbilityName().c_str());
247     int32_t accountId = 0;
248     if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
249         reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
250         HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
251         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
252         return engine.CreateUndefined();
253     }
254     unwrapArgc++;
255     AAFwk::StartOptions startOptions;
256     if (info.argc > ARGC_TWO && info.argv[INDEX_TWO]->TypeOf() == NATIVE_OBJECT) {
257         HILOG_INFO("OnStartAbilityWithAccount start options is used.");
258         AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
259             reinterpret_cast<napi_value>(info.argv[ARGC_TWO]), startOptions);
260         unwrapArgc++;
261     }
262     AsyncTask::CompleteCallback complete =
263         [weak = context_, want, accountId, startOptions, unwrapArgc](
264             NativeEngine& engine, AsyncTask& task, int32_t status) {
265                 auto context = weak.lock();
266                 if (!context) {
267                     HILOG_WARN("context is released");
268                     task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
269                     return;
270                 }
271 
272                 auto innerErrorCode = (unwrapArgc == INDEX_TWO) ?
273                     context->StartAbilityWithAccount(want, accountId, -1) : context->StartAbilityWithAccount(
274                         want, accountId, startOptions, -1);
275                 if (innerErrorCode == 0) {
276                     task.Resolve(engine, engine.CreateUndefined());
277                 } else {
278                     task.Reject(engine, CreateJsErrorByNativeErr(engine, innerErrorCode));
279                 }
280         };
281 
282     NativeValue* lastParam = (info.argc > unwrapArgc) ? info.argv[unwrapArgc] : nullptr;
283     NativeValue* result = nullptr;
284     AsyncTask::Schedule("JsAbilityContext::OnStartAbilityWithAccount",
285         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
286     return result;
287 }
288 
OnStartAbilityByCall(NativeEngine & engine,NativeCallbackInfo & info)289 NativeValue* JsAbilityContext::OnStartAbilityByCall(NativeEngine& engine, NativeCallbackInfo& info)
290 {
291     HILOG_DEBUG("JsAbilityContext::%{public}s, called", __func__);
292     if (info.argc < ARGC_ONE) {
293         ThrowTooFewParametersError(engine);
294         return engine.CreateUndefined();
295     }
296 
297     AAFwk::Want want;
298     if (info.argv[0]->TypeOf() != NATIVE_OBJECT ||
299         !JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
300         HILOG_ERROR("Failed to parse want!");
301         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
302         return engine.CreateUndefined();
303     }
304     InheritWindowMode(want);
305 
306     std::shared_ptr<StartAbilityByCallParameters> calls = std::make_shared<StartAbilityByCallParameters>();
307     NativeValue* lastParam = ((info.argc == ARGC_TWO) ? info.argv[ARGC_ONE] : nullptr);
308     NativeValue* retsult = nullptr;
309 
310     calls->callerCallBack = std::make_shared<CallerCallBack>();
311 
312     auto callBackDone = [calldata = calls] (const sptr<IRemoteObject> &obj) {
313         HILOG_DEBUG("OnStartAbilityByCall callBackDone mutexlock");
314         std::unique_lock<std::mutex> lock(calldata->mutexlock);
315         HILOG_DEBUG("OnStartAbilityByCall callBackDone remoteCallee assignment");
316         calldata->remoteCallee = obj;
317         calldata->condition.notify_all();
318         HILOG_INFO("OnStartAbilityByCall callBackDone is called end");
319     };
320 
321     auto releaseListen = [](const std::string &str) {
322         HILOG_INFO("OnStartAbilityByCall releaseListen is called %{public}s", str.c_str());
323     };
324 
325     auto callExecute = [calldata = calls] () {
326         constexpr int CALLER_TIME_OUT = 10; // 10s
327         std::unique_lock<std::mutex> lock(calldata->mutexlock);
328         if (calldata->remoteCallee != nullptr) {
329             HILOG_INFO("OnStartAbilityByCall callExecute callee isn`t nullptr");
330             return;
331         }
332 
333         if (calldata->condition.wait_for(lock, std::chrono::seconds(CALLER_TIME_OUT)) == std::cv_status::timeout) {
334             HILOG_ERROR("OnStartAbilityByCall callExecute waiting callee timeout");
335             calldata->err = -1;
336         }
337         HILOG_DEBUG("OnStartAbilityByCall callExecute end");
338     };
339 
340     auto callComplete = [weak = context_, calldata = calls] (
341         NativeEngine& engine, AsyncTask& task, int32_t status) {
342         if (calldata->err != 0) {
343             HILOG_ERROR("OnStartAbilityByCall callComplete err is %{public}d", calldata->err);
344             task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
345             return;
346         }
347 
348         auto context = weak.lock();
349         if (context != nullptr && calldata->callerCallBack != nullptr && calldata->remoteCallee != nullptr) {
350             auto releaseCallAbilityFunc = [weak] (
351                 const std::shared_ptr<CallerCallBack> &callback) -> ErrCode {
352                 auto contextForRelease = weak.lock();
353                 if (contextForRelease == nullptr) {
354                     HILOG_ERROR("releaseCallAbilityFunction, context is nullptr");
355                     return -1;
356                 }
357                 return contextForRelease->ReleaseCall(callback);
358             };
359             task.Resolve(engine,
360                 CreateJsCallerComplex(
361                     engine, releaseCallAbilityFunc, calldata->remoteCallee, calldata->callerCallBack));
362         } else {
363             HILOG_ERROR("OnStartAbilityByCall callComplete params error %{public}s is nullptr",
364                 context == nullptr ? "context" :
365                     (calldata->remoteCallee == nullptr ? "remoteCallee" : "callerCallBack"));
366             task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
367         }
368 
369         HILOG_DEBUG("OnStartAbilityByCall callComplete end");
370     };
371 
372     calls->callerCallBack->SetCallBack(callBackDone);
373     calls->callerCallBack->SetOnRelease(releaseListen);
374 
375     auto context = context_.lock();
376     if (context == nullptr) {
377         HILOG_ERROR("OnStartAbilityByCall context is nullptr");
378         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
379         return engine.CreateUndefined();
380     }
381 
382     auto ret = context->StartAbilityByCall(want, calls->callerCallBack);
383     if (ret != 0) {
384         HILOG_ERROR("OnStartAbilityByCall StartAbility is failed");
385         ThrowErrorByNativeErr(engine, ret);
386         return engine.CreateUndefined();
387     }
388 
389     if (calls->remoteCallee == nullptr) {
390         HILOG_INFO("OnStartAbilityByCall async wait execute");
391         AsyncTask::Schedule("JsAbilityContext::OnStartAbilityByCall",
392             engine,
393             CreateAsyncTaskWithLastParam(
394                 engine, lastParam, std::move(callExecute), std::move(callComplete), &retsult));
395     } else {
396         HILOG_INFO("OnStartAbilityByCall promiss return result execute");
397         AsyncTask::Schedule("JsAbilityContext::OnStartAbilityByCall", engine,
398             CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(callComplete), &retsult));
399     }
400 
401     HILOG_DEBUG("JsAbilityContext::%{public}s, called end", __func__);
402     return retsult;
403 }
404 
OnStartAbilityForResult(NativeEngine & engine,NativeCallbackInfo & info)405 NativeValue* JsAbilityContext::OnStartAbilityForResult(NativeEngine& engine, NativeCallbackInfo& info)
406 {
407     HILOG_INFO("OnStartAbilityForResult is called");
408 
409     if (info.argc == ARGC_ZERO) {
410         ThrowTooFewParametersError(engine);
411         return engine.CreateUndefined();
412     }
413 
414     AAFwk::Want want;
415     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
416         HILOG_ERROR("%s Failed to parse want!", __func__);
417         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
418         return engine.CreateUndefined();
419     }
420     InheritWindowMode(want);
421     decltype(info.argc) unwrapArgc = 1;
422     AAFwk::StartOptions startOptions;
423     if (info.argc > ARGC_ONE && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
424         HILOG_INFO("OnStartAbilityForResult start options is used.");
425         AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
426             reinterpret_cast<napi_value>(info.argv[1]), startOptions);
427         unwrapArgc++;
428     }
429 
430     NativeValue* lastParam = info.argc > unwrapArgc ? info.argv[unwrapArgc] : nullptr;
431     NativeValue* result = nullptr;
432     std::unique_ptr<AsyncTask> uasyncTask =
433         CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
434     std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
435     RuntimeTask task = [&engine, asyncTask](int resultCode, const AAFwk::Want& want) {
436         HILOG_INFO("OnStartAbilityForResult async callback is called");
437         NativeValue* abilityResult = JsAbilityContext::WrapAbilityResult(engine, resultCode, want);
438         if (abilityResult == nullptr) {
439             HILOG_WARN("wrap abilityResult failed");
440             asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
441         } else {
442             asyncTask->Resolve(engine, abilityResult);
443         }
444     };
445     auto context = context_.lock();
446     if (context == nullptr) {
447         HILOG_WARN("context is released");
448         asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
449     } else {
450         want.SetParam(Want::PARAM_RESV_FOR_RESULT, true);
451         curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
452         (unwrapArgc == 1) ? context->StartAbilityForResult(want, curRequestCode_, std::move(task)) :
453             context->StartAbilityForResult(want, startOptions, curRequestCode_, std::move(task));
454     }
455     HILOG_INFO("OnStartAbilityForResult is called end");
456     return result;
457 }
458 
OnStartAbilityForResultWithAccount(NativeEngine & engine,NativeCallbackInfo & info)459 NativeValue* JsAbilityContext::OnStartAbilityForResultWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
460 {
461     HILOG_INFO("OnStartAbilityForResultWithAccount is called");
462     if (info.argc < ARGC_TWO) {
463         HILOG_ERROR("Not enough params");
464         ThrowTooFewParametersError(engine);
465         return engine.CreateUndefined();
466     }
467     AAFwk::Want want;
468     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
469         HILOG_ERROR("%s Failed to parse want!", __func__);
470         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
471         return engine.CreateUndefined();
472     }
473     InheritWindowMode(want);
474     decltype(info.argc) unwrapArgc = 1;
475     int32_t accountId = 0;
476     if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
477         reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
478         HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
479         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
480         return engine.CreateUndefined();
481     }
482     unwrapArgc++;
483     AAFwk::StartOptions startOptions;
484     if (info.argc > ARGC_TWO && info.argv[INDEX_TWO]->TypeOf() == NATIVE_OBJECT) {
485         HILOG_INFO("OnStartAbilityForResultWithAccount start options is used.");
486         AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
487             reinterpret_cast<napi_value>(info.argv[INDEX_TWO]), startOptions);
488         unwrapArgc++;
489     }
490     NativeValue* lastParam = info.argc > unwrapArgc ? info.argv[unwrapArgc] : nullptr;
491     NativeValue* result = nullptr;
492     std::unique_ptr<AsyncTask> uasyncTask =
493         CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
494     std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
495     RuntimeTask task = [&engine, asyncTask](int resultCode, const AAFwk::Want& want) {
496         HILOG_INFO("OnStartAbilityForResultWithAccount async callback is called");
497         NativeValue* abilityResult = JsAbilityContext::WrapAbilityResult(engine, resultCode, want);
498         if (abilityResult == nullptr) {
499             HILOG_WARN("wrap abilityResult failed");
500             asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
501         } else {
502             asyncTask->Resolve(engine, abilityResult);
503         }
504         HILOG_INFO("OnStartAbilityForResultWithAccount async callback is called end");
505     };
506     auto context = context_.lock();
507     if (context == nullptr) {
508         HILOG_WARN("context is released");
509         asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
510     } else {
511         curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
512         (unwrapArgc == INDEX_TWO) ? context->StartAbilityForResultWithAccount(
513             want, accountId, curRequestCode_, std::move(task)) : context->StartAbilityForResultWithAccount(
514                 want, accountId, startOptions, curRequestCode_, std::move(task));
515     }
516     HILOG_INFO("OnStartAbilityForResultWithAccount is called end");
517     return result;
518 }
519 
OnStartExtensionAbility(NativeEngine & engine,NativeCallbackInfo & info)520 NativeValue* JsAbilityContext::OnStartExtensionAbility(NativeEngine& engine, NativeCallbackInfo& info)
521 {
522     HILOG_INFO("OnStartExtensionAbility is called.");
523     if (info.argc < ARGC_ONE) {
524         ThrowTooFewParametersError(engine);
525         return engine.CreateUndefined();
526     }
527 
528     AAFwk::Want want;
529     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
530         HILOG_ERROR("Failed to parse want!");
531         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
532         return engine.CreateUndefined();
533     }
534 
535     AsyncTask::CompleteCallback complete =
536         [weak = context_, want](NativeEngine& engine, AsyncTask& task, int32_t status) {
537             auto context = weak.lock();
538             if (!context) {
539                 HILOG_WARN("context is released");
540                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
541                 return;
542             }
543             auto errcode = context->StartServiceExtensionAbility(want);
544             if (errcode == 0) {
545                 task.Resolve(engine, engine.CreateUndefined());
546             } else {
547                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
548             }
549         };
550 
551     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[ARGC_ONE] : nullptr;
552     NativeValue* result = nullptr;
553     AsyncTask::Schedule("JsAbilityContext::OnStartExtensionAbility",
554         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
555     return result;
556 }
557 
OnStartExtensionAbilityWithAccount(NativeEngine & engine,const NativeCallbackInfo & info)558 NativeValue* JsAbilityContext::OnStartExtensionAbilityWithAccount(NativeEngine& engine, const NativeCallbackInfo& info)
559 {
560     HILOG_INFO("OnStartExtensionAbilityWithAccount is called.");
561     if (info.argc < ARGC_TWO) {
562         HILOG_ERROR("param is too few.");
563         ThrowTooFewParametersError(engine);
564         return engine.CreateUndefined();
565     }
566 
567     AAFwk::Want want;
568     int32_t accountId = -1;
569     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want) ||
570         !OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
571                                               reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
572         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
573         return engine.CreateUndefined();
574     }
575 
576     AsyncTask::CompleteCallback complete =
577         [weak = context_, want, accountId](NativeEngine& engine, AsyncTask& task, int32_t status) {
578             auto context = weak.lock();
579             if (!context) {
580                 HILOG_WARN("context is released");
581                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
582                 return;
583             }
584             auto errcode = context->StartServiceExtensionAbility(want, accountId);
585             if (errcode == 0) {
586                 task.Resolve(engine, engine.CreateUndefined());
587             } else {
588                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
589             }
590         };
591 
592     NativeValue* lastParam = (info.argc > ARGC_TWO) ? info.argv[ARGC_TWO] : nullptr;
593     NativeValue* result = nullptr;
594     AsyncTask::Schedule("JsAbilityContext::OnStartExtensionAbilityWithAccount",
595         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
596     return result;
597 }
598 
OnStopExtensionAbility(NativeEngine & engine,const NativeCallbackInfo & info)599 NativeValue* JsAbilityContext::OnStopExtensionAbility(NativeEngine& engine, const NativeCallbackInfo& info)
600 {
601     HILOG_INFO("OnStopExtensionAbility is called.");
602     if (info.argc < ARGC_ONE) {
603         HILOG_ERROR("param is too few for stop extension ability.");
604         ThrowTooFewParametersError(engine);
605         return engine.CreateUndefined();
606     }
607 
608     AAFwk::Want want;
609     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want)) {
610         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
611         return engine.CreateUndefined();
612     }
613 
614     AsyncTask::CompleteCallback complete =
615         [weak = context_, want](NativeEngine& engine, AsyncTask& task, int32_t status) {
616             auto context = weak.lock();
617             if (!context) {
618                 HILOG_WARN("context is released");
619                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
620                 return;
621             }
622             auto errcode = context->StopServiceExtensionAbility(want);
623             if (errcode == 0) {
624                 task.Resolve(engine, engine.CreateUndefined());
625             } else {
626                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
627             }
628         };
629 
630     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[ARGC_ONE] : nullptr;
631     NativeValue* result = nullptr;
632     AsyncTask::Schedule("JsAbilityContext::OnStopExtensionAbility",
633         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
634     return result;
635 }
636 
OnStopExtensionAbilityWithAccount(NativeEngine & engine,const NativeCallbackInfo & info)637 NativeValue* JsAbilityContext::OnStopExtensionAbilityWithAccount(NativeEngine& engine, const NativeCallbackInfo& info)
638 {
639     HILOG_INFO("OnStartExtensionAbilityWithAccount is called.");
640     if (info.argc < ARGC_TWO) {
641         HILOG_ERROR("param is too few for stop extension ability with account.");
642         ThrowTooFewParametersError(engine);
643         return engine.CreateUndefined();
644     }
645 
646     int32_t accountId = -1;
647     AAFwk::Want want;
648     if (!JsAbilityContext::UnWrapWant(engine, info.argv[0], want) ||
649         !OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
650                                               reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
651         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
652         return engine.CreateUndefined();
653     }
654 
655     AsyncTask::CompleteCallback complete =
656         [weak = context_, want, accountId](NativeEngine& engine, AsyncTask& task, int32_t status) {
657             auto context = weak.lock();
658             if (!context) {
659                 HILOG_WARN("context is released");
660                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
661                 return;
662             }
663             auto errcode = context->StopServiceExtensionAbility(want, accountId);
664             if (errcode == 0) {
665                 task.Resolve(engine, engine.CreateUndefined());
666             } else {
667                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
668             }
669         };
670 
671     NativeValue* lastParam = (info.argc > ARGC_TWO) ? info.argv[ARGC_TWO] : nullptr;
672     NativeValue* result = nullptr;
673     AsyncTask::Schedule("JsAbilityContext::OnStopExtensionAbilityWithAccount",
674         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
675     return result;
676 }
677 
OnTerminateSelfWithResult(NativeEngine & engine,NativeCallbackInfo & info)678 NativeValue* JsAbilityContext::OnTerminateSelfWithResult(NativeEngine& engine, NativeCallbackInfo& info)
679 {
680     HILOG_INFO("OnTerminateSelfWithResult is called");
681 
682     if (info.argc == 0) {
683         HILOG_ERROR("Not enough params");
684         ThrowTooFewParametersError(engine);
685         return engine.CreateUndefined();
686     }
687 
688     int resultCode = 0;
689     AAFwk::Want want;
690     if (!JsAbilityContext::UnWrapAbilityResult(engine, info.argv[0], resultCode, want)) {
691         HILOG_ERROR("%s Failed to parse ability result!", __func__);
692         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
693         return engine.CreateUndefined();
694     }
695 
696     auto abilityContext = context_.lock();
697     if (abilityContext != nullptr) {
698         abilityContext->SetTerminating(true);
699     }
700 
701     AsyncTask::CompleteCallback complete =
702         [weak = context_, want, resultCode](NativeEngine& engine, AsyncTask& task, int32_t status) {
703             auto context = weak.lock();
704             if (!context) {
705                 HILOG_WARN("context is released");
706                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
707                 return;
708             }
709 
710             auto errorCode = context->TerminateAbilityWithResult(want, resultCode);
711             if (errorCode == 0) {
712                 task.Resolve(engine, engine.CreateUndefined());
713             } else {
714                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errorCode));
715             }
716         };
717 
718     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[1] : nullptr;
719     NativeValue* result = nullptr;
720     AsyncTask::Schedule("JsAbilityContext::OnTerminateSelfWithResult",
721         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
722     HILOG_INFO("OnTerminateSelfWithResult is called end");
723     return result;
724 }
725 
OnConnectAbility(NativeEngine & engine,NativeCallbackInfo & info)726 NativeValue* JsAbilityContext::OnConnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
727 {
728     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
729     HILOG_INFO("Connect ability called.");
730     // only support two params
731     if (info.argc < ARGC_TWO) {
732         HILOG_ERROR("Connect ability failed, not enough params.");
733         ThrowTooFewParametersError(engine);
734         return engine.CreateUndefined();
735     }
736 
737     // unwrap want
738     AAFwk::Want want;
739     OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
740         reinterpret_cast<napi_value>(info.argv[0]), want);
741     HILOG_INFO("Connect ability called, callee:%{public}s.%{public}s.",
742         want.GetBundle().c_str(),
743         want.GetElement().GetAbilityName().c_str());
744 
745     // unwarp connection
746     sptr<JSAbilityConnection> connection = new JSAbilityConnection(engine);
747     connection->SetJsConnectionObject(info.argv[1]);
748     int64_t connectId = g_serialNumber;
749     ConnectionKey key;
750     key.id = g_serialNumber;
751     key.want = want;
752     connection->SetConnectionId(key.id);
753     abilityConnects_.emplace(key, connection);
754     if (g_serialNumber < INT32_MAX) {
755         g_serialNumber++;
756     } else {
757         g_serialNumber = 0;
758     }
759 
760     AsyncTask::CompleteCallback complete =
761         [weak = context_, want, connection, connectId](NativeEngine& engine, AsyncTask& task, int32_t status) {
762             auto context = weak.lock();
763             if (!context) {
764                 HILOG_ERROR("Connect ability failed, context is released.");
765                 task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
766                 return;
767             }
768             if (!context->ConnectAbility(want, connection)) {
769                 connection->CallJsFailed(ERROR_CODE_ONE);
770             }
771             task.Resolve(engine, engine.CreateUndefined());
772         };
773     NativeValue* result = nullptr;
774     AsyncTask::Schedule("JsAbilityContext::OnConnectAbility",
775         engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
776     return engine.CreateNumber(connectId);
777 }
778 
OnConnectAbilityWithAccount(NativeEngine & engine,NativeCallbackInfo & info)779 NativeValue* JsAbilityContext::OnConnectAbilityWithAccount(NativeEngine& engine, NativeCallbackInfo& info)
780 {
781     HILOG_INFO("OnConnectAbility is called");
782     // only support three params
783     if (info.argc < ARGC_THREE) {
784         HILOG_ERROR("Not enough params");
785         ThrowTooFewParametersError(engine);
786         return engine.CreateUndefined();
787     }
788 
789     // unwrap want
790     AAFwk::Want want;
791     OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
792         reinterpret_cast<napi_value>(info.argv[0]), want);
793     HILOG_INFO("%{public}s bundlename:%{public}s abilityname:%{public}s",
794         __func__,
795         want.GetBundle().c_str(),
796         want.GetElement().GetAbilityName().c_str());
797 
798     int32_t accountId = 0;
799     if (!OHOS::AppExecFwk::UnwrapInt32FromJS2(reinterpret_cast<napi_env>(&engine),
800         reinterpret_cast<napi_value>(info.argv[1]), accountId)) {
801         HILOG_INFO("%{public}s called, the second parameter is invalid.", __func__);
802         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
803         return engine.CreateUndefined();
804     }
805 
806     // unwarp connection
807     sptr<JSAbilityConnection> connection = new JSAbilityConnection(engine);
808     connection->SetJsConnectionObject(info.argv[INDEX_TWO]);
809     int64_t connectId = g_serialNumber;
810     ConnectionKey key;
811     key.id = g_serialNumber;
812     key.want = want;
813     connection->SetConnectionId(key.id);
814     abilityConnects_.emplace(key, connection);
815     if (g_serialNumber < INT32_MAX) {
816         g_serialNumber++;
817     } else {
818         g_serialNumber = 0;
819     }
820     AsyncTask::CompleteCallback complete =
821         [weak = context_, want, accountId, connection, connectId](
822             NativeEngine& engine, AsyncTask& task, int32_t status) {
823                 auto context = weak.lock();
824                 if (!context) {
825                     HILOG_ERROR("context is released");
826                     task.Reject(engine, CreateJsError(engine, 1, "Context is released"));
827                     return;
828                 }
829                 HILOG_INFO("context->ConnectAbilityWithAccount connection:%{public}d", (int32_t)connectId);
830                 if (!context->ConnectAbilityWithAccount(want, accountId, connection)) {
831                     connection->CallJsFailed(ERROR_CODE_ONE);
832                 }
833                 task.Resolve(engine, engine.CreateUndefined());
834         };
835     NativeValue* result = nullptr;
836     AsyncTask::Schedule("JsAbilityContext::OnConnectAbilityWithAccount",
837         engine, CreateAsyncTaskWithLastParam(engine, nullptr, nullptr, std::move(complete), &result));
838     return engine.CreateNumber(connectId);
839 }
840 
OnDisconnectAbility(NativeEngine & engine,NativeCallbackInfo & info)841 NativeValue* JsAbilityContext::OnDisconnectAbility(NativeEngine& engine, NativeCallbackInfo& info)
842 {
843     HILOG_INFO("OnDisconnectAbility is called");
844     // only support one or two params
845     if (info.argc < ARGC_ONE) {
846         HILOG_ERROR("Not enough params");
847         ThrowTooFewParametersError(engine);
848         return engine.CreateUndefined();
849     }
850 
851     // unwrap want
852     AAFwk::Want want;
853     // unwrap connectId
854     int64_t connectId = -1;
855     sptr<JSAbilityConnection> connection = nullptr;
856     napi_get_value_int64(reinterpret_cast<napi_env>(&engine),
857         reinterpret_cast<napi_value>(info.argv[0]), &connectId);
858     HILOG_INFO("Disconnect ability begin, connection:%{public}d.", (int32_t)connectId);
859     auto item = std::find_if(abilityConnects_.begin(),
860         abilityConnects_.end(),
861         [&connectId](const std::map<ConnectionKey, sptr<JSAbilityConnection>>::value_type &obj) {
862             return connectId == obj.first.id;
863         });
864     if (item != abilityConnects_.end()) {
865         // match id
866         want = item->first.want;
867         connection = item->second;
868         HILOG_INFO("%{public}s find conn ability exist", __func__);
869     } else {
870         HILOG_INFO("%{public}s not find conn exist.", __func__);
871     }
872     // begin disconnect
873     AsyncTask::CompleteCallback complete =
874         [weak = context_, want, connection](
875             NativeEngine& engine, AsyncTask& task, int32_t status) {
876             HILOG_INFO("OnDisconnectAbility begin");
877             auto context = weak.lock();
878             if (!context) {
879                 HILOG_WARN("OnDisconnectAbility context is released");
880                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
881                 return;
882             }
883             if (connection == nullptr) {
884                 HILOG_WARN("connection nullptr");
885                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
886                 return;
887             }
888             HILOG_INFO("context->DisconnectAbility");
889             context->DisconnectAbility(want, connection);
890             task.Resolve(engine, engine.CreateUndefined());
891         };
892 
893     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[1] : nullptr;
894     NativeValue* result = nullptr;
895     AsyncTask::Schedule("JsAbilityContext::OnDisconnectAbility",
896         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
897     return result;
898 }
899 
OnTerminateSelf(NativeEngine & engine,NativeCallbackInfo & info)900 NativeValue* JsAbilityContext::OnTerminateSelf(NativeEngine& engine, NativeCallbackInfo& info)
901 {
902     HILOG_INFO("OnTerminateSelf is called");
903     auto abilityContext = context_.lock();
904     if (abilityContext != nullptr) {
905         abilityContext->SetTerminating(true);
906     }
907 
908     AsyncTask::CompleteCallback complete =
909         [weak = context_](NativeEngine& engine, AsyncTask& task, int32_t status) {
910             auto context = weak.lock();
911             if (!context) {
912                 HILOG_WARN("context is released");
913                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
914                 return;
915             }
916 
917             auto errcode = context->TerminateSelf();
918             if (errcode == 0) {
919                 task.Resolve(engine, engine.CreateUndefined());
920             } else {
921                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
922             }
923         };
924 
925     NativeValue* lastParam = (info.argc > ARGC_ZERO) ? info.argv[ARGC_ZERO] : nullptr;
926     NativeValue* result = nullptr;
927     AsyncTask::Schedule("JsAbilityContext::OnTerminateSelf",
928         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
929     return result;
930 }
931 
OnRequestPermissionsFromUser(NativeEngine & engine,NativeCallbackInfo & info)932 NativeValue* JsAbilityContext::OnRequestPermissionsFromUser(NativeEngine& engine, NativeCallbackInfo& info)
933 {
934     HILOG_INFO("OnRequestPermissionsFromUser is called");
935 
936     if (info.argc < ARGC_ONE) {
937         HILOG_ERROR("Not enough params");
938         ThrowTooFewParametersError(engine);
939         return engine.CreateUndefined();
940     }
941 
942     std::vector<std::string> permissionList;
943     if (!OHOS::AppExecFwk::UnwrapArrayStringFromJS(reinterpret_cast<napi_env>(&engine),
944         reinterpret_cast<napi_value>(info.argv[0]), permissionList)) {
945         HILOG_ERROR("%{public}s called, the first parameter is invalid.", __func__);
946         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
947         return engine.CreateUndefined();
948     }
949 
950     if (permissionList.size() == 0) {
951         HILOG_ERROR("%{public}s called, params do not meet specification.", __func__);
952     }
953 
954     NativeValue* lastParam = (info.argc == ARGC_ONE) ? nullptr : info.argv[ARGC_ONE];
955     NativeValue* result = nullptr;
956     auto uasyncTask = CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
957     std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
958     PermissionRequestTask task =
959         [&engine, asyncTask](const std::vector<std::string> &permissions, const std::vector<int> &grantResults) {
960         HILOG_INFO("OnRequestPermissionsFromUser async callback is called");
961         NativeValue* requestResult = JsAbilityContext::WrapPermissionRequestResult(engine, permissions, grantResults);
962         if (requestResult == nullptr) {
963             HILOG_WARN("wrap requestResult failed");
964             asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
965         } else {
966             asyncTask->Resolve(engine, requestResult);
967         }
968         HILOG_INFO("OnRequestPermissionsFromUser async callback is called end");
969     };
970     auto context = context_.lock();
971     if (context == nullptr) {
972         HILOG_WARN("context is released");
973         asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
974     } else {
975         curRequestCode_ = (curRequestCode_ == INT_MAX) ? 0 : (curRequestCode_ + 1);
976         context->RequestPermissionsFromUser(engine, permissionList, curRequestCode_, std::move(task));
977     }
978     HILOG_INFO("OnRequestPermissionsFromUser is called end");
979     return result;
980 }
981 
OnRestoreWindowStage(NativeEngine & engine,NativeCallbackInfo & info)982 NativeValue* JsAbilityContext::OnRestoreWindowStage(NativeEngine& engine, NativeCallbackInfo& info)
983 {
984     HILOG_INFO("OnRestoreWindowStage is called, argc = %{public}d", static_cast<int>(info.argc));
985     if (info.argc < ARGC_ONE) {
986         HILOG_ERROR("OnRestoreWindowStage need one parameters");
987         ThrowTooFewParametersError(engine);
988         return engine.CreateUndefined();
989     }
990     auto context = context_.lock();
991     if (!context) {
992         HILOG_ERROR("OnRestoreWindowStage context is released");
993         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
994         return engine.CreateUndefined();
995     }
996     auto errcode = context->RestoreWindowStage(engine, info.argv[0]);
997     if (errcode != 0) {
998         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INNER);
999         return CreateJsError(engine, errcode, "RestoreWindowStage failed.");
1000     }
1001     return engine.CreateUndefined();
1002 }
1003 
OnRequestDialogService(NativeEngine & engine,NativeCallbackInfo & info)1004 NativeValue* JsAbilityContext::OnRequestDialogService(NativeEngine& engine, NativeCallbackInfo& info)
1005 {
1006     HILOG_INFO("OnRequestDialogService is called");
1007 
1008     if (info.argc < ARGC_ONE) {
1009         HILOG_ERROR("Not enough params");
1010         ThrowTooFewParametersError(engine);
1011         return engine.CreateUndefined();
1012     }
1013 
1014     AAFwk::Want want;
1015     OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(info.argv[0]), want);
1016     HILOG_INFO("requestdialogservice, target:%{public}s.%{public}s.", want.GetBundle().c_str(),
1017         want.GetElement().GetAbilityName().c_str());
1018 
1019     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[ARGC_ONE] : nullptr;
1020     NativeValue* result = nullptr;
1021     auto uasyncTask = CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, nullptr, &result);
1022     std::shared_ptr<AsyncTask> asyncTask = std::move(uasyncTask);
1023     RequestDialogResultTask task =
1024         [&engine, asyncTask](int32_t resultCode) {
1025         HILOG_INFO("OnRequestDialogService async callback is called");
1026         NativeValue* requestResult = JsAbilityContext::WrapRequestDialogResult(engine, resultCode);
1027         if (requestResult == nullptr) {
1028             HILOG_WARN("wrap requestResult failed");
1029             asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INNER));
1030         } else {
1031             asyncTask->Resolve(engine, requestResult);
1032         }
1033         HILOG_INFO("OnRequestDialogService async callback is called end");
1034     };
1035     auto context = context_.lock();
1036     if (context == nullptr) {
1037         HILOG_WARN("context is released, can not requestDialogService");
1038         asyncTask->Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
1039     } else {
1040         auto errCode = context->RequestDialogService(engine, want, std::move(task));
1041         if (errCode != ERR_OK) {
1042             asyncTask->Reject(engine, CreateJsError(engine, GetJsErrorCodeByNativeError(errCode)));
1043         }
1044     }
1045     HILOG_INFO("OnRequestDialogService is called end");
1046     return result;
1047 }
1048 
OnIsTerminating(NativeEngine & engine,NativeCallbackInfo & info)1049 NativeValue* JsAbilityContext::OnIsTerminating(NativeEngine& engine, NativeCallbackInfo& info)
1050 {
1051     HILOG_INFO("OnIsTerminating is called");
1052     auto context = context_.lock();
1053     if (context == nullptr) {
1054         HILOG_ERROR("OnIsTerminating context is nullptr");
1055         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
1056         return engine.CreateUndefined();
1057     }
1058     return engine.CreateBoolean(context->IsTerminating());
1059 }
1060 
UnWrapWant(NativeEngine & engine,NativeValue * argv,AAFwk::Want & want)1061 bool JsAbilityContext::UnWrapWant(NativeEngine& engine, NativeValue* argv, AAFwk::Want& want)
1062 {
1063     if (argv == nullptr) {
1064         HILOG_WARN("%s argv == nullptr!", __func__);
1065         return false;
1066     }
1067     return AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(argv), want);
1068 }
1069 
WrapWant(NativeEngine & engine,const AAFwk::Want & want)1070 NativeValue* JsAbilityContext::WrapWant(NativeEngine& engine, const AAFwk::Want& want)
1071 {
1072     return reinterpret_cast<NativeValue*>(AppExecFwk::WrapWant(reinterpret_cast<napi_env>(&engine), want));
1073 }
1074 
UnWrapAbilityResult(NativeEngine & engine,NativeValue * argv,int & resultCode,AAFwk::Want & want)1075 bool JsAbilityContext::UnWrapAbilityResult(NativeEngine& engine, NativeValue* argv, int& resultCode, AAFwk::Want& want)
1076 {
1077     if (argv == nullptr) {
1078         HILOG_WARN("%s argv == nullptr!", __func__);
1079         return false;
1080     }
1081     if (argv->TypeOf() != NativeValueType::NATIVE_OBJECT) {
1082         HILOG_WARN("%s invalid type of abilityResult!", __func__);
1083         return false;
1084     }
1085     NativeObject* jObj = ConvertNativeValueTo<NativeObject>(argv);
1086     NativeValue* jResultCode = jObj->GetProperty("resultCode");
1087     if (jResultCode == nullptr) {
1088         HILOG_WARN("%s jResultCode == nullptr!", __func__);
1089         return false;
1090     }
1091     if (jResultCode->TypeOf() != NativeValueType::NATIVE_NUMBER) {
1092         HILOG_WARN("%s invalid type of resultCode!", __func__);
1093         return false;
1094     }
1095     resultCode = int64_t(*ConvertNativeValueTo<NativeNumber>(jObj->GetProperty("resultCode")));
1096     NativeValue* jWant = jObj->GetProperty("want");
1097     if (jWant == nullptr) {
1098         HILOG_WARN("%s jWant == nullptr!", __func__);
1099         return false;
1100     }
1101     if (jWant->TypeOf() != NativeValueType::NATIVE_OBJECT) {
1102         HILOG_WARN("%s invalid type of want!", __func__);
1103         return false;
1104     }
1105     return JsAbilityContext::UnWrapWant(engine, jWant, want);
1106 }
1107 
WrapRequestDialogResult(NativeEngine & engine,int32_t resultCode)1108 NativeValue* JsAbilityContext::WrapRequestDialogResult(NativeEngine& engine, int32_t resultCode)
1109 {
1110     NativeValue *objValue = engine.CreateObject();
1111     NativeObject *object = ConvertNativeValueTo<NativeObject>(objValue);
1112     if (object == nullptr) {
1113         HILOG_ERROR("Native object is nullptr.");
1114         return objValue;
1115     }
1116 
1117     object->SetProperty("result", CreateJsValue(engine, resultCode));
1118     return objValue;
1119 }
1120 
WrapAbilityResult(NativeEngine & engine,const int & resultCode,const AAFwk::Want & want)1121 NativeValue* JsAbilityContext::WrapAbilityResult(NativeEngine& engine, const int& resultCode, const AAFwk::Want& want)
1122 {
1123     NativeValue* jAbilityResult = engine.CreateObject();
1124     NativeObject* abilityResult = ConvertNativeValueTo<NativeObject>(jAbilityResult);
1125     abilityResult->SetProperty("resultCode", engine.CreateNumber(resultCode));
1126     abilityResult->SetProperty("want", JsAbilityContext::WrapWant(engine, want));
1127     return jAbilityResult;
1128 }
1129 
WrapPermissionRequestResult(NativeEngine & engine,const std::vector<std::string> & permissions,const std::vector<int> & grantResults)1130 NativeValue* JsAbilityContext::WrapPermissionRequestResult(NativeEngine& engine,
1131     const std::vector<std::string> &permissions, const std::vector<int> &grantResults)
1132 {
1133     NativeValue* jsPermissionRequestResult = engine.CreateObject();
1134     NativeObject* permissionRequestResult = ConvertNativeValueTo<NativeObject>(jsPermissionRequestResult);
1135     permissionRequestResult->SetProperty("permissions", CreateNativeArray(engine, permissions));
1136     permissionRequestResult->SetProperty("authResults", CreateNativeArray(engine, grantResults));
1137     return jsPermissionRequestResult;
1138 }
1139 
InheritWindowMode(AAFwk::Want & want)1140 void JsAbilityContext::InheritWindowMode(AAFwk::Want &want)
1141 {
1142     HILOG_INFO("%{public}s called.", __func__);
1143 #ifdef SUPPORT_GRAPHICS
1144     // only split mode need inherit
1145     auto context = context_.lock();
1146     if (!context) {
1147         HILOG_ERROR("context is nullptr.");
1148         return;
1149     }
1150     auto windowMode = context->GetCurrentWindowMode();
1151     if (windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY ||
1152         windowMode == AAFwk::AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) {
1153         want.SetParam(Want::PARAM_RESV_WINDOW_MODE, windowMode);
1154     }
1155     HILOG_INFO("%{public}s called end. window mode is %{public}d", __func__, windowMode);
1156 #endif
1157 }
1158 
ConfigurationUpdated(NativeEngine * engine,std::shared_ptr<NativeReference> & jsContext,const std::shared_ptr<AppExecFwk::Configuration> & config)1159 void JsAbilityContext::ConfigurationUpdated(NativeEngine* engine, std::shared_ptr<NativeReference> &jsContext,
1160     const std::shared_ptr<AppExecFwk::Configuration> &config)
1161 {
1162     HILOG_INFO("ConfigurationUpdated begin.");
1163     if (jsContext == nullptr || config == nullptr) {
1164         HILOG_INFO("jsContext is nullptr.");
1165         return;
1166     }
1167 
1168     NativeValue* value = jsContext->Get();
1169     NativeObject* object = ConvertNativeValueTo<NativeObject>(value);
1170     if (object == nullptr) {
1171         HILOG_INFO("object is nullptr.");
1172         return;
1173     }
1174 
1175     NativeValue* method = object->GetProperty("onUpdateConfiguration");
1176     if (method == nullptr) {
1177         HILOG_ERROR("Failed to get onUpdateConfiguration from object");
1178         return;
1179     }
1180     HILOG_INFO("JSAbilityConnection::CallFunction onUpdateConfiguration, success");
1181 
1182     HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
1183     NativeValue* argv[] = {CreateJsConfiguration(*engine, *config)};
1184     engine->CallFunction(value, method, argv, ARGC_ONE);
1185 }
1186 
CreateJsAbilityContext(NativeEngine & engine,std::shared_ptr<AbilityContext> context,DetachCallback detach,AttachCallback attach)1187 NativeValue* CreateJsAbilityContext(NativeEngine& engine, std::shared_ptr<AbilityContext> context,
1188                                     DetachCallback detach, AttachCallback attach)
1189 {
1190     NativeValue* objValue = CreateJsBaseContext(engine, context, detach, attach);
1191     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
1192 
1193     std::unique_ptr<JsAbilityContext> jsContext = std::make_unique<JsAbilityContext>(context);
1194     object->SetNativePointer(jsContext.release(), JsAbilityContext::Finalizer, nullptr);
1195 
1196     handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
1197 
1198     auto abilityInfo = context->GetAbilityInfo();
1199     if (abilityInfo != nullptr) {
1200         object->SetProperty("abilityInfo", CreateJsAbilityInfo(engine, *abilityInfo));
1201     }
1202 
1203     auto configuration = context->GetConfiguration();
1204     if (configuration != nullptr) {
1205         object->SetProperty("config", CreateJsConfiguration(engine, *configuration));
1206     }
1207 
1208     const char *moduleName = "JsAbilityContext";
1209     BindNativeFunction(engine, *object, "startAbility", moduleName, JsAbilityContext::StartAbility);
1210     BindNativeFunction(engine, *object, "startAbilityWithAccount", moduleName,
1211         JsAbilityContext::StartAbilityWithAccount);
1212     BindNativeFunction(engine, *object, "startAbilityByCall", moduleName, JsAbilityContext::StartAbilityByCall);
1213     BindNativeFunction(engine, *object, "startAbilityForResult", moduleName, JsAbilityContext::StartAbilityForResult);
1214     BindNativeFunction(engine, *object, "startAbilityForResultWithAccount", moduleName,
1215         JsAbilityContext::StartAbilityForResultWithAccount);
1216     BindNativeFunction(engine, *object, "startServiceExtensionAbility", moduleName,
1217         JsAbilityContext::StartServiceExtensionAbility);
1218     BindNativeFunction(engine, *object, "startServiceExtensionAbilityWithAccount", moduleName,
1219         JsAbilityContext::StartServiceExtensionAbilityWithAccount);
1220     BindNativeFunction(engine, *object, "stopServiceExtensionAbility", moduleName,
1221         JsAbilityContext::StopServiceExtensionAbility);
1222     BindNativeFunction(engine, *object, "stopServiceExtensionAbilityWithAccount", moduleName,
1223         JsAbilityContext::StopServiceExtensionAbilityWithAccount);
1224     BindNativeFunction(engine, *object, "connectAbility", moduleName, JsAbilityContext::ConnectAbility);
1225     BindNativeFunction(engine, *object, "connectServiceExtensionAbility", moduleName, JsAbilityContext::ConnectAbility);
1226     BindNativeFunction(engine, *object, "connectAbilityWithAccount", moduleName,
1227         JsAbilityContext::ConnectAbilityWithAccount);
1228     BindNativeFunction(engine, *object, "connectServiceExtensionAbilityWithAccount", moduleName,
1229         JsAbilityContext::ConnectAbilityWithAccount);
1230     BindNativeFunction(engine, *object, "disconnectAbility", moduleName, JsAbilityContext::DisconnectAbility);
1231     BindNativeFunction(
1232         engine, *object, "disconnectServiceExtensionAbility", moduleName, JsAbilityContext::DisconnectAbility);
1233     BindNativeFunction(engine, *object, "terminateSelf", moduleName, JsAbilityContext::TerminateSelf);
1234     BindNativeFunction(engine, *object, "terminateSelfWithResult", moduleName,
1235         JsAbilityContext::TerminateSelfWithResult);
1236     BindNativeFunction(engine, *object, "requestPermissionsFromUser", moduleName,
1237         JsAbilityContext::RequestPermissionsFromUser);
1238     BindNativeFunction(engine, *object, "restoreWindowStage", moduleName, JsAbilityContext::RestoreWindowStage);
1239     BindNativeFunction(engine, *object, "isTerminating", moduleName, JsAbilityContext::IsTerminating);
1240     BindNativeFunction(engine, *object, "startRecentAbility", moduleName,
1241         JsAbilityContext::StartRecentAbility);
1242     BindNativeFunction(engine, *object, "requestDialogService", moduleName,
1243         JsAbilityContext::RequestDialogService);
1244 
1245 #ifdef SUPPORT_GRAPHICS
1246     BindNativeFunction(engine, *object, "setMissionLabel", moduleName, JsAbilityContext::SetMissionLabel);
1247     BindNativeFunction(engine, *object, "setMissionIcon", moduleName, JsAbilityContext::SetMissionIcon);
1248 #endif
1249     return objValue;
1250 }
1251 
JSAbilityConnection(NativeEngine & engine)1252 JSAbilityConnection::JSAbilityConnection(NativeEngine& engine) : engine_(engine) {}
1253 
~JSAbilityConnection()1254 JSAbilityConnection::~JSAbilityConnection()
1255 {
1256     uv_loop_t *loop = engine_.GetUVLoop();
1257     if (loop == nullptr) {
1258         HILOG_ERROR("~JSAbilityConnection: failed to get uv loop.");
1259         return;
1260     }
1261 
1262     ConnectCallback *cb = new (std::nothrow) ConnectCallback();
1263     if (cb == nullptr) {
1264         HILOG_ERROR("~JSAbilityConnection: failed to create cb.");
1265         return;
1266     }
1267     cb->jsConnectionObject_ = std::move(jsConnectionObject_);
1268 
1269     uv_work_t *work = new (std::nothrow) uv_work_t;
1270     if (work == nullptr) {
1271         HILOG_ERROR("~JSAbilityConnection: failed to create work.");
1272         delete cb;
1273         cb = nullptr;
1274         return;
1275     }
1276     work->data = reinterpret_cast<void *>(cb);
1277     int ret = uv_queue_work(loop, work, [](uv_work_t *work) {},
1278     [](uv_work_t *work, int status) {
1279         if (work == nullptr) {
1280             HILOG_ERROR("~JSAbilityConnection: work is nullptr.");
1281             return;
1282         }
1283         if (work->data == nullptr) {
1284             HILOG_ERROR("~JSAbilityConnection: data is nullptr.");
1285             delete work;
1286             work = nullptr;
1287             return;
1288         }
1289         ConnectCallback *cb = reinterpret_cast<ConnectCallback *>(work->data);
1290         delete cb;
1291         cb = nullptr;
1292         delete work;
1293         work = nullptr;
1294     });
1295     if (ret != 0) {
1296         if (cb != nullptr) {
1297             delete cb;
1298             cb = nullptr;
1299         }
1300         if (work != nullptr) {
1301             delete work;
1302             work = nullptr;
1303         }
1304     }
1305 }
1306 
SetConnectionId(int64_t id)1307 void JSAbilityConnection::SetConnectionId(int64_t id)
1308 {
1309     connectionId_ = id;
1310 }
1311 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)1312 void JSAbilityConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
1313     const sptr<IRemoteObject> &remoteObject, int resultCode)
1314 {
1315     HILOG_INFO("OnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
1316     if (handler_ == nullptr) {
1317         HILOG_INFO("handler_ nullptr");
1318         return;
1319     }
1320 
1321     wptr<JSAbilityConnection> connection = this;
1322     auto task = [connection, element, remoteObject, resultCode] {
1323         sptr<JSAbilityConnection> connectionSptr = connection.promote();
1324         if (!connectionSptr) {
1325             HILOG_INFO("connectionSptr nullptr");
1326             return;
1327         }
1328         connectionSptr->HandleOnAbilityConnectDone(element, remoteObject, resultCode);
1329     };
1330     handler_->PostTask(task, "OnAbilityConnectDone");
1331 }
1332 
HandleOnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)1333 void JSAbilityConnection::HandleOnAbilityConnectDone(const AppExecFwk::ElementName &element,
1334     const sptr<IRemoteObject> &remoteObject, int resultCode)
1335 {
1336     HILOG_INFO("HandleOnAbilityConnectDone begin, resultCode:%{public}d", resultCode);
1337     if (jsConnectionObject_ == nullptr) {
1338         HILOG_ERROR("jsConnectionObject_ nullptr");
1339         return;
1340     }
1341     NativeValue* value = jsConnectionObject_->Get();
1342     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1343     if (obj == nullptr) {
1344         HILOG_ERROR("Failed to get object");
1345         return;
1346     }
1347     NativeValue* methodOnConnect = obj->GetProperty("onConnect");
1348     if (methodOnConnect == nullptr) {
1349         HILOG_ERROR("Failed to get onConnect from object");
1350         return;
1351     }
1352     HILOG_INFO("JSAbilityConnection::CallFunction onConnect, success");
1353 
1354     // wrap RemoteObject
1355     HILOG_INFO("OnAbilityConnectDone begin NAPI_ohos_rpc_CreateJsRemoteObject");
1356     napi_value napiRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
1357         reinterpret_cast<napi_env>(&engine_), remoteObject);
1358     NativeValue* nativeRemoteObject = reinterpret_cast<NativeValue*>(napiRemoteObject);
1359     NativeValue* argv[] = { ConvertElement(element), nativeRemoteObject };
1360     engine_.CallFunction(value, methodOnConnect, argv, ARGC_TWO);
1361     HILOG_INFO("OnAbilityConnectDone end");
1362 }
1363 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)1364 void JSAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
1365 {
1366     HILOG_INFO("OnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
1367     if (handler_ == nullptr) {
1368         HILOG_INFO("handler_ nullptr");
1369         return;
1370     }
1371 
1372     wptr<JSAbilityConnection> connection = this;
1373     auto task = [connection, element, resultCode] {
1374         sptr<JSAbilityConnection> connectionSptr = connection.promote();
1375         if (!connectionSptr) {
1376             HILOG_INFO("connectionSptr nullptr");
1377             return;
1378         }
1379         connectionSptr->HandleOnAbilityDisconnectDone(element, resultCode);
1380     };
1381     handler_->PostTask(task, "OnAbilityDisconnectDone");
1382 }
1383 
HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)1384 void JSAbilityConnection::HandleOnAbilityDisconnectDone(const AppExecFwk::ElementName &element,
1385     int resultCode)
1386 {
1387     HILOG_INFO("HandleOnAbilityDisconnectDone begin, resultCode:%{public}d", resultCode);
1388     if (jsConnectionObject_ == nullptr) {
1389         HILOG_ERROR("jsConnectionObject_ nullptr");
1390         return;
1391     }
1392     NativeValue* value = jsConnectionObject_->Get();
1393     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1394     if (obj == nullptr) {
1395         HILOG_ERROR("Failed to get object");
1396         return;
1397     }
1398 
1399     NativeValue* method = obj->GetProperty("onDisconnect");
1400     if (method == nullptr) {
1401         HILOG_ERROR("Failed to get onDisconnect from object");
1402         return;
1403     }
1404 
1405     // release connect
1406     HILOG_INFO("OnAbilityDisconnectDone abilityConnects_.size:%{public}zu", abilityConnects_.size());
1407     std::string bundleName = element.GetBundleName();
1408     std::string abilityName = element.GetAbilityName();
1409     auto item = std::find_if(abilityConnects_.begin(), abilityConnects_.end(),
1410         [bundleName, abilityName, connectionId = connectionId_] (
1411             const std::map<ConnectionKey, sptr<JSAbilityConnection>>::value_type &obj) {
1412                 return (bundleName == obj.first.want.GetBundle()) &&
1413                     (abilityName == obj.first.want.GetElement().GetAbilityName()) &&
1414                     connectionId == obj.first.id;
1415         });
1416     if (item != abilityConnects_.end()) {
1417         // match bundlename && abilityname
1418         abilityConnects_.erase(item);
1419         HILOG_INFO("OnAbilityDisconnectDone erase abilityConnects_.size:%{public}zu", abilityConnects_.size());
1420     }
1421 
1422     NativeValue* argv[] = { ConvertElement(element) };
1423     HILOG_INFO("OnAbilityDisconnectDone CallFunction success");
1424     engine_.CallFunction(value, method, argv, ARGC_ONE);
1425 }
1426 
CallJsFailed(int32_t errorCode)1427 void JSAbilityConnection::CallJsFailed(int32_t errorCode)
1428 {
1429     HILOG_INFO("CallJsFailed begin");
1430     if (jsConnectionObject_ == nullptr) {
1431         HILOG_ERROR("jsConnectionObject_ nullptr");
1432         return;
1433     }
1434     NativeValue* value = jsConnectionObject_->Get();
1435     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
1436     if (obj == nullptr) {
1437         HILOG_ERROR("Failed to get object");
1438         return;
1439     }
1440 
1441     NativeValue* method = obj->GetProperty("onFailed");
1442     if (method == nullptr) {
1443         HILOG_ERROR("Failed to get onFailed from object");
1444         return;
1445     }
1446 
1447     NativeValue* argv[] = {engine_.CreateNumber(errorCode)};
1448     HILOG_INFO("CallJsFailed CallFunction success");
1449     engine_.CallFunction(value, method, argv, ARGC_ONE);
1450     HILOG_INFO("CallJsFailed end");
1451 }
1452 
ConvertElement(const AppExecFwk::ElementName & element)1453 NativeValue* JSAbilityConnection::ConvertElement(const AppExecFwk::ElementName &element)
1454 {
1455     napi_value napiElementName = OHOS::AppExecFwk::WrapElementName(reinterpret_cast<napi_env>(&engine_), element);
1456     return reinterpret_cast<NativeValue*>(napiElementName);
1457 }
1458 
SetJsConnectionObject(NativeValue * jsConnectionObject)1459 void JSAbilityConnection::SetJsConnectionObject(NativeValue* jsConnectionObject)
1460 {
1461     jsConnectionObject_ = std::unique_ptr<NativeReference>(engine_.CreateReference(jsConnectionObject, 1));
1462 }
1463 
1464 #ifdef SUPPORT_GRAPHICS
SetMissionLabel(NativeEngine * engine,NativeCallbackInfo * info)1465 NativeValue* JsAbilityContext::SetMissionLabel(NativeEngine* engine, NativeCallbackInfo* info)
1466 {
1467     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
1468     return (me != nullptr) ? me->OnSetMissionLabel(*engine, *info) : nullptr;
1469 }
1470 
SetMissionIcon(NativeEngine * engine,NativeCallbackInfo * info)1471 NativeValue* JsAbilityContext::SetMissionIcon(NativeEngine* engine, NativeCallbackInfo* info)
1472 {
1473     JsAbilityContext* me = CheckParamsAndGetThis<JsAbilityContext>(engine, info);
1474     return (me != nullptr) ? me->OnSetMissionIcon(*engine, *info) : nullptr;
1475 }
1476 
OnSetMissionLabel(NativeEngine & engine,NativeCallbackInfo & info)1477 NativeValue* JsAbilityContext::OnSetMissionLabel(NativeEngine& engine, NativeCallbackInfo& info)
1478 {
1479     HILOG_INFO("OnSetMissionLabel is called, argc = %{public}d", static_cast<int>(info.argc));
1480     if (info.argc < ARGC_ONE) {
1481         HILOG_ERROR("OnSetMissionLabel, Not enough params");
1482         ThrowTooFewParametersError(engine);
1483         return engine.CreateUndefined();
1484     }
1485 
1486     std::string label;
1487     if (!ConvertFromJsValue(engine, info.argv[0], label)) {
1488         HILOG_ERROR("OnSetMissionLabel, parse label failed.");
1489         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
1490         return engine.CreateUndefined();
1491     }
1492 
1493     AsyncTask::CompleteCallback complete =
1494         [weak = context_, label](NativeEngine& engine, AsyncTask& task, int32_t status) {
1495             auto context = weak.lock();
1496             if (!context) {
1497                 HILOG_WARN("context is released");
1498                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
1499                 return;
1500             }
1501 
1502             auto errcode = context->SetMissionLabel(label);
1503             if (errcode == 0) {
1504                 task.Resolve(engine, engine.CreateUndefined());
1505             } else {
1506                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
1507             }
1508         };
1509 
1510     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[ARGC_ONE] : nullptr;
1511     NativeValue* result = nullptr;
1512     AsyncTask::Schedule("JsAbilityContext::OnSetMissionLabel",
1513         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
1514     return result;
1515 }
1516 
OnSetMissionIcon(NativeEngine & engine,NativeCallbackInfo & info)1517 NativeValue* JsAbilityContext::OnSetMissionIcon(NativeEngine& engine, NativeCallbackInfo& info)
1518 {
1519     HILOG_INFO("OnSetMissionIcon is called, argc = %{public}d", static_cast<int>(info.argc));
1520     if (info.argc < ARGC_ONE) {
1521         HILOG_ERROR("OnSetMissionIcon, Not enough params");
1522         ThrowTooFewParametersError(engine);
1523         return engine.CreateUndefined();
1524     }
1525 
1526     auto icon = OHOS::Media::PixelMapNapi::GetPixelMap(reinterpret_cast<napi_env>(&engine),
1527         reinterpret_cast<napi_value>(info.argv[0]));
1528     if (!icon) {
1529         HILOG_ERROR("OnSetMissionIcon, parse icon failed.");
1530         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
1531         return engine.CreateUndefined();
1532     }
1533 
1534     AsyncTask::CompleteCallback complete =
1535         [weak = context_, icon](NativeEngine& engine, AsyncTask& task, int32_t status) {
1536             auto context = weak.lock();
1537             if (!context) {
1538                 HILOG_WARN("context is released when set mission icon");
1539                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
1540                 return;
1541             }
1542 
1543             auto errcode = context->SetMissionIcon(icon);
1544             if (errcode == 0) {
1545                 task.Resolve(engine, engine.CreateUndefined());
1546             } else {
1547                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errcode));
1548             }
1549         };
1550 
1551     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[1] : nullptr;
1552     NativeValue* result = nullptr;
1553     AsyncTask::Schedule("JsAbilityContext::OnSetMissionIcon",
1554         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
1555     return result;
1556 }
1557 #endif
1558 }  // namespace AbilityRuntime
1559 }  // namespace OHOS
1560