• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_napi_common_ability.h"
17 
18 #include "ability_manager_client.h"
19 #include "ability_util.h"
20 
21 #include "hilog_tag_wrapper.h"
22 #include "js_runtime_utils.h"
23 #include "napi_common_ability.h"
24 #include "napi_common_ability_wrap_utils.h"
25 #include "napi_common_util.h"
26 #include "napi_context.h"
27 #include "napi_remote_object.h"
28 
29 using namespace OHOS::AbilityRuntime;
30 
31 namespace OHOS {
32 namespace AppExecFwk {
33 static std::map<ConnectionKey, sptr<NAPIAbilityConnection>, key_compare> connects_;
34 static std::mutex g_connectionsLock_;
35 static int64_t serialNumber_ = 0;
36 
JsNapiCommon()37 JsNapiCommon::JsNapiCommon() : ability_(nullptr)
38 {}
39 
~JsNapiCommon()40 JsNapiCommon::~JsNapiCommon()
41 {
42     RemoveAllCallbacksLocked();
43 }
44 
HandleJsConnectAbilityError(napi_env env,std::shared_ptr<ConnectionCallback> & connectionCallback,const Want & want,int32_t errorVal)45 napi_value JsNapiCommon::HandleJsConnectAbilityError(napi_env env,
46     std::shared_ptr<ConnectionCallback> &connectionCallback, const Want &want, int32_t errorVal)
47 {
48     TAG_LOGD(AAFwkTag::JSNAPI, "called");
49     // return error code in onFailed async callback
50     napi_value callback = nullptr;
51     napi_value undefinedVal = nullptr;
52     napi_value resultVal = nullptr;
53     napi_value callResult = nullptr;
54     int errorCode = NO_ERROR;
55     switch (errorVal) {
56         case NAPI_ERR_ACE_ABILITY:
57             errorCode = ABILITY_NOT_FOUND;
58             break;
59         case NAPI_ERR_PARAM_INVALID:
60             errorCode = INVALID_PARAMETER;
61             break;
62         default:
63             break;
64     }
65     NAPI_CALL_BASE(env, napi_create_int32(env, errorCode, &resultVal), CreateJsUndefined(env));
66     NAPI_CALL_BASE(env, napi_get_reference_value(env, connectionCallback->failedCallbackRef, &callback),
67         CreateJsUndefined(env));
68     NAPI_CALL_BASE(env, napi_call_function(env, undefinedVal, callback, ARGS_ONE, &resultVal, &callResult),
69         CreateJsUndefined(env));
70     connectionCallback->Reset();
71     RemoveConnectionLocked(want);
72     return resultVal;
73 }
74 
OnFindAbilityConnection(napi_env env,sptr<NAPIAbilityConnection> & abilityConnection,std::shared_ptr<ConnectionCallback> & connectionCallback,const Want & want,int64_t id)75 napi_value JsNapiCommon::OnFindAbilityConnection(napi_env env, sptr<NAPIAbilityConnection> &abilityConnection,
76     std::shared_ptr<ConnectionCallback> &connectionCallback, const Want &want, int64_t id)
77 {
78     TAG_LOGI(AAFwkTag::JSNAPI, "callbackSize: %{public}zu",
79         abilityConnection->GetCallbackSize());
80     // Add callback to connection
81     abilityConnection->AddConnectionCallback(connectionCallback);
82     // Judge connection-state
83     auto connectionState = abilityConnection->GetConnectionState();
84     TAG_LOGI(AAFwkTag::JSNAPI, "connectionState=%{public}d", connectionState);
85     if (connectionState == CONNECTION_STATE_CONNECTED) {
86         abilityConnection->HandleOnAbilityConnectDone(*connectionCallback, ERR_OK);
87         return CreateJsValue(env, id);
88     } else if (connectionState == CONNECTION_STATE_CONNECTING) {
89         return CreateJsValue(env, id);
90     } else {
91         RemoveConnectionLocked(want);
92         return CreateJsUndefined(env);
93     }
94 }
95 
JsConnectAbility(napi_env env,napi_callback_info info,const AbilityType abilityType)96 napi_value JsNapiCommon::JsConnectAbility(napi_env env, napi_callback_info info, const AbilityType abilityType)
97 {
98     TAG_LOGD(AAFwkTag::JSNAPI, "called");
99     size_t argc = ARGS_MAX_COUNT;
100     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
101     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
102     if (argc != ARGS_TWO) {
103         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
104         return CreateJsUndefined(env);
105     }
106 
107     std::lock_guard<std::mutex> lock(g_connectionsLock_);
108     Want want;
109     if (!UnwrapWant(env, argv[PARAM0], want)) {
110         TAG_LOGE(AAFwkTag::JSNAPI, "unwrapWant failed");
111         return CreateJsUndefined(env);
112     }
113 
114     auto connectionCallback = std::make_shared<ConnectionCallback>(env, argv[PARAM1], this);
115     bool result = false;
116     int32_t errorVal = static_cast<int32_t>(NAPI_ERR_NO_ERROR);
117     int64_t id = 0;
118     sptr<NAPIAbilityConnection> abilityConnection = nullptr;
119     if (CheckAbilityType(abilityType)) {
120         abilityConnection = FindConnectionLocked(want, id);
121         if (abilityConnection) {
122             return OnFindAbilityConnection(env, abilityConnection, connectionCallback, want, id);
123         } else {
124             result = CreateConnectionAndConnectAbilityLocked(connectionCallback, want, id);
125         }
126     } else {
127         errorVal = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
128     }
129 
130     if (errorVal != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || result == false) {
131         if (HandleJsConnectAbilityError(env, connectionCallback, want, errorVal) == CreateJsUndefined(env)) {
132             return CreateJsUndefined(env);
133         };
134     }
135     // free failed callback here, avoid possible multi-threading problems when disconnect success
136     napi_delete_reference(env, connectionCallback->failedCallbackRef);
137     connectionCallback->failedCallbackRef = nullptr;
138     return CreateJsValue(env, id);
139 }
140 
SetJsDisConnectAbilityCallback(std::shared_ptr<int32_t> & errorVal,const AbilityType & abilityType,sptr<NAPIAbilityConnection> & abilityConnection,NapiAsyncTask::ExecuteCallback & execute,NapiAsyncTask::CompleteCallback & complete)141 void JsNapiCommon::SetJsDisConnectAbilityCallback(std::shared_ptr<int32_t> &errorVal, const AbilityType &abilityType,
142     sptr<NAPIAbilityConnection> &abilityConnection, NapiAsyncTask::ExecuteCallback &execute,
143     NapiAsyncTask::CompleteCallback &complete)
144 {
145     execute = [obj = this, value = errorVal, abilityType, abilityConnection] () {
146         if (obj->ability_ == nullptr) {
147             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
148             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
149             return;
150         }
151         if (!obj->CheckAbilityType(abilityType)) {
152             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
153             return;
154         }
155         *value = obj->ability_->DisconnectAbility(abilityConnection);
156     };
157     complete = [obj = this, value = errorVal]
158         (napi_env env, NapiAsyncTask &task, const int32_t status) {
159         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR)) {
160             task.Reject(env, CreateJsError(env, *value, "DisconnectAbility failed."));
161             return;
162         }
163         task.Resolve(env, CreateJsValue(env, *value));
164     };
165 }
166 
JsDisConnectAbility(napi_env env,napi_callback_info info,const AbilityType abilityType)167 napi_value JsNapiCommon::JsDisConnectAbility(napi_env env, napi_callback_info info, const AbilityType abilityType)
168 {
169     size_t argc = ARGS_MAX_COUNT;
170     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
171     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
172     if (argc == ARGS_ZERO || argc > ARGS_TWO) {
173         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
174         return CreateJsUndefined(env);
175     }
176 
177     std::lock_guard<std::mutex> lock(g_connectionsLock_);
178     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
179     int64_t id = 0;
180     sptr<NAPIAbilityConnection> abilityConnection = nullptr;
181     if (!ConvertFromJsValue(env, argv[PARAM0], id)) {
182         TAG_LOGE(AAFwkTag::JSNAPI, "params error");
183         return CreateJsUndefined(env);
184     }
185     auto item = std::find_if(connects_.begin(), connects_.end(),
186         [&id](const std::map<ConnectionKey, sptr<NAPIAbilityConnection>>::value_type &obj) {
187             return id == obj.first.id;
188         });
189     if (item != connects_.end()) {
190         abilityConnection = item->second;
191     } else {
192         TAG_LOGE(AAFwkTag::JSNAPI, "no ability disconnect");
193         return CreateJsUndefined(env);
194     }
195 
196     NapiAsyncTask::ExecuteCallback execute;
197     NapiAsyncTask::CompleteCallback complete;
198     SetJsDisConnectAbilityCallback(errorVal, abilityType, abilityConnection, execute, complete);
199     napi_value lastParam = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
200     napi_value result = nullptr;
201     NapiAsyncTask::Schedule("JsNapiCommon::JsDisConnectAbility",
202         env, CreateAsyncTaskWithLastParam(env, lastParam, std::move(execute), std::move(complete), &result));
203     return result;
204 }
205 
CreateConnectionAndConnectAbilityLocked(std::shared_ptr<ConnectionCallback> callback,const Want & want,int64_t & id)206 bool JsNapiCommon::CreateConnectionAndConnectAbilityLocked(
207     std::shared_ptr<ConnectionCallback> callback, const Want &want, int64_t &id)
208 {
209     TAG_LOGD(AAFwkTag::JSNAPI, "Create new connection");
210     // Create connection
211     sptr<NAPIAbilityConnection> connection(new (std::nothrow) NAPIAbilityConnection());
212     CHECK_POINTER_AND_RETURN_LOG(connection, false, "null connection");
213     ConnectionKey key;
214     id = serialNumber_;
215     key.id = id;
216     key.want = want;
217     connects_.emplace(key, connection);
218     if (serialNumber_ < INT32_MAX) {
219         serialNumber_++;
220     } else {
221         serialNumber_ = 0;
222     }
223     // Set callback
224     connection->AddConnectionCallback(callback);
225 
226     // connectAbility
227     if (ability_ == nullptr) {
228         TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
229         return false;
230     }
231     connection->SetConnectionState(CONNECTION_STATE_CONNECTING);
232     return ability_->ConnectAbility(want, connection);
233 }
234 
FindConnectionLocked(const Want & want,int64_t & id)235 sptr<NAPIAbilityConnection> JsNapiCommon::FindConnectionLocked(const Want &want, int64_t &id)
236 {
237     TAG_LOGD(AAFwkTag::JSNAPI, "uri:%{public}s", want.GetElement().GetURI().c_str());
238     std::string deviceId = want.GetElement().GetDeviceID();
239     std::string bundleName = want.GetBundle();
240     std::string abilityName = want.GetElement().GetAbilityName();
241     auto iter = std::find_if(connects_.begin(),
242         connects_.end(), [&deviceId, &bundleName, &abilityName](const std::map<ConnectionKey,
243         sptr<NAPIAbilityConnection>>::value_type &obj) {
244             return (deviceId == obj.first.want.GetElement().GetDeviceID()) &&
245                    (bundleName == obj.first.want.GetBundle()) &&
246                    (abilityName == obj.first.want.GetElement().GetAbilityName());
247         });
248     if (iter != connects_.end()) {
249         TAG_LOGD(AAFwkTag::JSNAPI, "find connection exist");
250         auto connection = iter->second;
251         if (connection == nullptr) {
252             TAG_LOGE(AAFwkTag::JSNAPI, "null connection");
253             connects_.erase(iter);
254             return nullptr;
255         }
256         id = iter->first.id;
257         return connection;
258     }
259     return nullptr;
260 }
261 
RemoveAllCallbacksLocked()262 void JsNapiCommon::RemoveAllCallbacksLocked()
263 {
264     TAG_LOGD(AAFwkTag::JSNAPI, "called");
265     std::lock_guard<std::mutex> lock(g_connectionsLock_);
266     for (auto it = connects_.begin(); it != connects_.end();) {
267         auto connection = it->second;
268         if (!connection) {
269             TAG_LOGE(AAFwkTag::JSNAPI, "null connection");
270             it = connects_.erase(it);
271             continue;
272         }
273         connection->RemoveAllCallbacks(this);
274         if (connection->GetCallbackSize() == 0) {
275             it = connects_.erase(it);
276         } else {
277             ++it;
278         }
279     }
280 }
281 
RemoveConnectionLocked(const Want & want)282 void JsNapiCommon::RemoveConnectionLocked(const Want &want)
283 {
284     std::string deviceId = want.GetElement().GetDeviceID();
285     std::string bundleName = want.GetBundle();
286     std::string abilityName = want.GetElement().GetAbilityName();
287     auto iter = std::find_if(connects_.begin(),
288         connects_.end(), [&deviceId, &bundleName, &abilityName](const std::map<ConnectionKey,
289         sptr<NAPIAbilityConnection>>::value_type &obj) {
290             return (deviceId == obj.first.want.GetElement().GetDeviceID()) &&
291                    (bundleName == obj.first.want.GetBundle()) &&
292                    (abilityName == obj.first.want.GetElement().GetAbilityName());
293         });
294     connects_.erase(iter);
295 }
296 
JsGetContext(napi_env env,const napi_callback_info info,const AbilityType abilityType)297 napi_value JsNapiCommon::JsGetContext(napi_env env, const napi_callback_info info, const AbilityType abilityType)
298 {
299     if (!CheckAbilityType(abilityType)) {
300         TAG_LOGE(AAFwkTag::JSNAPI, "ability type error");
301         return CreateJsUndefined(env);
302     }
303 
304     return CreateNapiJSContext(env);
305 }
306 
JsGetFilesDir(napi_env env,napi_callback_info info,const AbilityType abilityType)307 napi_value JsNapiCommon::JsGetFilesDir(napi_env env, napi_callback_info info, const AbilityType abilityType)
308 {
309     TAG_LOGD(AAFwkTag::JSNAPI, "called");
310     size_t argc = ARGS_MAX_COUNT;
311     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
312     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
313     if (argc > ARGS_ONE) {
314         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
315         return CreateJsUndefined(env);
316     }
317 
318     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
319     std::shared_ptr<JsFilesDir> filesDir = std::make_shared<JsFilesDir>();
320     auto execute = [obj = this, dir = filesDir, abilityType, value = errorVal] () {
321         if (obj->ability_ == nullptr) {
322             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
323             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
324             return;
325         }
326         if (!obj->CheckAbilityType(abilityType)) {
327             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
328             return;
329         }
330         auto context = obj->ability_->GetAbilityContext();
331         if (context == nullptr) {
332             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
333             TAG_LOGE(AAFwkTag::JSNAPI, "null abilityContext");
334             return;
335         }
336         dir->name = context->GetFilesDir();
337     };
338     auto complete = [obj = this, dir = filesDir, value = errorVal]
339         (napi_env env, NapiAsyncTask &task, int32_t status) {
340         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || dir == nullptr) {
341             auto ecode = dir == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
342             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
343             return;
344         }
345         task.Resolve(env, CreateJsValue(env, dir->name));
346     };
347 
348     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
349     napi_value result = nullptr;
350     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetFilesDir",
351         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
352     return result;
353 }
354 
JsIsUpdatingConfigurations(napi_env env,napi_callback_info info,const AbilityType abilityType)355 napi_value JsNapiCommon::JsIsUpdatingConfigurations(
356     napi_env env, napi_callback_info info, const AbilityType abilityType)
357 {
358     TAG_LOGD(AAFwkTag::JSNAPI, "called");
359     size_t argc = ARGS_MAX_COUNT;
360     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
361     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
362     if (argc > ARGS_ONE) {
363         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
364         return CreateJsUndefined(env);
365     }
366 
367     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
368     std::shared_ptr<JsConfigurations> config = std::make_shared<JsConfigurations>();
369     auto execute = [obj = this, data = config, value = errorVal, abilityType] () {
370         if (obj->ability_ == nullptr) {
371             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
372             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
373             return;
374         }
375         if (!obj->CheckAbilityType(abilityType)) {
376             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
377             return;
378         }
379         if (data == nullptr) {
380             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
381             TAG_LOGE(AAFwkTag::JSNAPI, "null data");
382             return;
383         }
384         data->status = obj->ability_->IsUpdatingConfigurations();
385     };
386     auto complete = [obj = this, info = config, value = errorVal]
387         (napi_env env, NapiAsyncTask &task, int32_t status) {
388         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || info == nullptr) {
389             auto ecode = info == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
390             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
391             return;
392         }
393         task.Resolve(env, CreateJsValue(env, info->status));
394     };
395 
396     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
397     napi_value result = nullptr;
398     NapiAsyncTask::Schedule("JsNapiCommon::JsIsUpdatingConfigurations",
399         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
400 
401     return result;
402 }
403 
JsPrintDrawnCompleted(napi_env env,napi_callback_info info,const AbilityType abilityType)404 napi_value JsNapiCommon::JsPrintDrawnCompleted(
405     napi_env env, napi_callback_info info, const AbilityType abilityType)
406 {
407     TAG_LOGD(AAFwkTag::JSNAPI, "called");
408     size_t argc = ARGS_MAX_COUNT;
409     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
410     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
411     if (argc > ARGS_ONE) {
412         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
413         return CreateJsUndefined(env);
414     }
415 
416     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
417     std::shared_ptr<JsDrawnCompleted> drawComplete = std::make_shared<JsDrawnCompleted>();
418     auto execute = [obj = this, data = drawComplete, value = errorVal, abilityType] () {
419         if (obj->ability_ == nullptr) {
420             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
421             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
422             return;
423         }
424         if (!obj->CheckAbilityType(abilityType)) {
425             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
426             return;
427         }
428         if (data == nullptr) {
429             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
430             TAG_LOGE(AAFwkTag::JSNAPI, "null data");
431             return;
432         }
433         data->status = obj->ability_->PrintDrawnCompleted();
434     };
435     auto complete = [obj = this, draw = drawComplete, value = errorVal]
436         (napi_env env, NapiAsyncTask &task, int32_t status) {
437         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || draw == nullptr) {
438             auto ecode = draw == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
439             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
440             return;
441         }
442         task.Resolve(env, CreateJsNull(env));
443     };
444 
445     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
446     napi_value result = nullptr;
447     NapiAsyncTask::Schedule("JsNapiCommon::JsPrintDrawnCompleted",
448         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
449 
450     return result;
451 }
452 
JsGetCacheDir(napi_env env,napi_callback_info info,const AbilityType abilityType)453 napi_value JsNapiCommon::JsGetCacheDir(napi_env env, napi_callback_info info, const AbilityType abilityType)
454 {
455     TAG_LOGD(AAFwkTag::JSNAPI, "called");
456     size_t argc = ARGS_MAX_COUNT;
457     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
458     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
459     if (argc > ARGS_ONE) {
460         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
461         return CreateJsUndefined(env);
462     }
463 
464     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
465     std::shared_ptr<JsCacheDir> cacheDir = std::make_shared<JsCacheDir>();
466     auto execute = [obj = this, dir = cacheDir, value = errorVal, abilityType] () {
467         if (obj->ability_ == nullptr) {
468             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
469             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
470             return;
471         }
472         if (!obj->CheckAbilityType(abilityType)) {
473             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
474             return;
475         }
476         auto context = obj->ability_->GetAbilityContext();
477         if (context == nullptr) {
478             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
479             TAG_LOGE(AAFwkTag::JSNAPI, "null context");
480             return;
481         }
482         dir->name = context->GetCacheDir();
483     };
484     auto complete = [obj = this, dir = cacheDir, value = errorVal]
485         (napi_env env, NapiAsyncTask &task, int32_t status) {
486         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || dir == nullptr) {
487             TAG_LOGD(AAFwkTag::JSNAPI, "JsCacheDir is null or errorVal is error");
488             auto ecode = dir == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
489             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
490             return;
491         }
492         task.Resolve(env, CreateJsValue(env, dir->name));
493     };
494 
495     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
496     napi_value result = nullptr;
497     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetCacheDir",
498         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
499 
500     return result;
501 }
502 
JsGetCtxAppType(napi_env env,napi_callback_info info,const AbilityType abilityType)503 napi_value JsNapiCommon::JsGetCtxAppType(
504     napi_env env, napi_callback_info info, const AbilityType abilityType)
505 {
506     TAG_LOGD(AAFwkTag::JSNAPI, "called");
507     size_t argc = ARGS_MAX_COUNT;
508     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
509     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
510     if (argc > ARGS_ONE) {
511         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
512         return CreateJsUndefined(env);
513     }
514 
515     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
516     std::shared_ptr<JsCtxAppType> type = std::make_shared<JsCtxAppType>();
517     auto execute = [obj = this, apptype = type, value = errorVal, abilityType] () {
518         if (obj->ability_ == nullptr) {
519             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
520             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
521             return;
522         }
523         if (!obj->CheckAbilityType(abilityType)) {
524             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
525             return;
526         }
527         if (apptype == nullptr) {
528             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
529             return;
530         }
531         apptype->name = obj->ability_->GetAppType();
532     };
533     auto complete = [obj = this, apptype = type, value = errorVal]
534         (napi_env env, NapiAsyncTask &task, int32_t status) {
535         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || apptype == nullptr) {
536             auto ecode = apptype == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
537             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
538             return;
539         }
540         task.Resolve(env, CreateJsValue(env, apptype->name));
541     };
542 
543     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
544     napi_value result = nullptr;
545     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetCtxAppType",
546         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
547 
548     return result;
549 }
550 
JsGetCtxHapModuleInfo(napi_env env,napi_callback_info info,const AbilityType abilityType)551 napi_value JsNapiCommon::JsGetCtxHapModuleInfo(
552     napi_env env, napi_callback_info info, const AbilityType abilityType)
553 {
554     TAG_LOGD(AAFwkTag::JSNAPI, "called");
555     size_t argc = ARGS_MAX_COUNT;
556     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
557     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
558     if (argc > ARGS_ONE) {
559         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
560         return CreateJsUndefined(env);
561     }
562 
563     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
564     std::shared_ptr<JsHapModuleInfo> infoData = std::make_shared<JsHapModuleInfo>();
565     auto execute = [obj = this, hapMod = infoData, value = errorVal, abilityType] () {
566         if (obj->ability_ == nullptr) {
567             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
568             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
569             return;
570         }
571         if (!obj->CheckAbilityType(abilityType)) {
572             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
573             return;
574         }
575         auto getInfo = obj->ability_->GetHapModuleInfo();
576         if (getInfo != nullptr && hapMod != nullptr) {
577             hapMod->hapModInfo = *getInfo;
578         } else {
579             TAG_LOGE(AAFwkTag::JSNAPI, "GetHapModuleInfo return nullptr");
580             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
581         }
582     };
583     auto complete = [obj = this, info = infoData, value = errorVal]
584         (napi_env env, NapiAsyncTask &task, int32_t status) {
585         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || info == nullptr) {
586             TAG_LOGD(AAFwkTag::JSNAPI, "null info or errorVal==0");
587             auto ecode = info == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
588             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
589             return;
590         }
591         task.Resolve(env, obj->CreateHapModuleInfo(env, info));
592     };
593 
594     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
595     napi_value result = nullptr;
596     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetCtxHapModuleInfo",
597         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
598 
599     return result;
600 }
601 
JsGetAppVersionInfo(napi_env env,napi_callback_info info,const AbilityType abilityType)602 napi_value JsNapiCommon::JsGetAppVersionInfo(
603     napi_env env, napi_callback_info info, const AbilityType abilityType)
604 {
605     TAG_LOGD(AAFwkTag::JSNAPI, "called");
606     size_t argc = ARGS_MAX_COUNT;
607     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
608     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
609     if (argc > ARGS_ONE) {
610         TAG_LOGE(AAFwkTag::JSNAPI, "input arguments count error, argc=%{public}zu", argc);
611         return CreateJsUndefined(env);
612     }
613 
614     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
615     std::shared_ptr<JsApplicationInfo> infoData = std::make_shared<JsApplicationInfo>();
616     auto execute = [obj = this, appInfo = infoData, value = errorVal, abilityType] () {
617         if (obj->ability_ == nullptr) {
618             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
619             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
620             return;
621         }
622         if (!obj->CheckAbilityType(abilityType)) {
623             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
624             return;
625         }
626         auto getInfo = obj->ability_->GetApplicationInfo();
627         if (getInfo != nullptr && appInfo != nullptr) {
628             appInfo->appInfo = *getInfo;
629         } else {
630             TAG_LOGE(AAFwkTag::JSNAPI, "GetApplicationInfo return null");
631             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
632         }
633     };
634     auto complete = [obj = this, info = infoData, value = errorVal]
635         (napi_env env, NapiAsyncTask &task, int32_t status) {
636             TAG_LOGD(AAFwkTag::JSNAPI, "JsHapModuleInfo is null or errorVal is 0");
637         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || info == nullptr) {
638             auto ecode = info == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
639             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
640             return;
641         }
642         task.Resolve(env, obj->CreateAppVersionInfo(env, info));
643     };
644 
645     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
646     napi_value result = nullptr;
647     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetAppVersionInfo",
648         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
649 
650     return result;
651 }
652 
JsGetCtxAbilityInfo(napi_env env,napi_callback_info info,const AbilityType abilityType)653 napi_value JsNapiCommon::JsGetCtxAbilityInfo(
654     napi_env env, napi_callback_info info, const AbilityType abilityType)
655 {
656     TAG_LOGD(AAFwkTag::JSNAPI, "called");
657     size_t argc = ARGS_MAX_COUNT;
658     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
659     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
660     if (argc > ARGS_ONE) {
661         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
662         return CreateJsUndefined(env);
663     }
664 
665     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
666     std::shared_ptr<JsAbilityInfoInfo> infoData = std::make_shared<JsAbilityInfoInfo>();
667     auto execute = [obj = this, abilityInfo = infoData, value = errorVal, abilityType] () {
668         if (obj->ability_ == nullptr) {
669             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
670             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
671             return;
672         }
673         if (!obj->CheckAbilityType(abilityType)) {
674             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
675             return;
676         }
677         auto getInfo = obj->ability_->GetAbilityInfo();
678         if (getInfo != nullptr && abilityInfo != nullptr) {
679             abilityInfo->abilityInfo = *getInfo;
680         } else {
681             TAG_LOGE(AAFwkTag::JSNAPI, "GetAbilityInfo return nullptr");
682             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
683         }
684     };
685     auto complete = [obj = this, info = infoData, value = errorVal]
686         (napi_env env, NapiAsyncTask &task, int32_t status) {
687         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || info == nullptr) {
688             TAG_LOGD(AAFwkTag::JSNAPI, "null info or errorVal==0");
689             auto ecode = info == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
690             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
691             return;
692         }
693         task.Resolve(env, obj->CreateAbilityInfo(env, info));
694     };
695 
696     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
697     napi_value result = nullptr;
698     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetCtxAbilityInfo",
699         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
700 
701     return result;
702 }
703 
JsGetOrCreateDistributedDir(napi_env env,napi_callback_info info,const AbilityType abilityType)704 napi_value JsNapiCommon::JsGetOrCreateDistributedDir(
705     napi_env env, napi_callback_info info, const AbilityType abilityType)
706 {
707     TAG_LOGD(AAFwkTag::JSNAPI, "called");
708     size_t argc = ARGS_MAX_COUNT;
709     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
710     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
711     if (argc > ARGS_ONE) {
712         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
713         return CreateJsUndefined(env);
714     }
715 
716     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
717     std::shared_ptr<JsOrCreateDistributedDir> orCreateDistributedDir = std::make_shared<JsOrCreateDistributedDir>();
718     auto execute = [obj = this, dir = orCreateDistributedDir, value = errorVal, abilityType] () {
719         if (obj->ability_ == nullptr) {
720             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
721             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
722             return;
723         }
724         if (!obj->CheckAbilityType(abilityType)) {
725             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
726             return;
727         }
728         auto context = obj->ability_->GetAbilityContext();
729         if (context == nullptr) {
730             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
731             TAG_LOGE(AAFwkTag::JSNAPI, "null context");
732             return;
733         }
734         dir->name = context->GetDistributedFilesDir();
735     };
736     auto complete = [obj = this, dir = orCreateDistributedDir, value = errorVal]
737         (napi_env env, NapiAsyncTask &task, int32_t status) {
738         if (*value != static_cast<int32_t>(NAPI_ERR_NO_ERROR) || dir == nullptr) {
739             TAG_LOGD(AAFwkTag::JSNAPI, "errorVal is error or JsCacheDir is null");
740             auto ecode = dir == nullptr ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
741             task.Reject(env, CreateJsError(env, ecode, obj->ConvertErrorCode(ecode)));
742             return;
743         }
744         task.Resolve(env, CreateJsValue(env, dir->name));
745     };
746 
747     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
748     napi_value result = nullptr;
749     NapiAsyncTask::Schedule("JsNapiCommon::JsGetOrCreateDistributedDir",
750         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
751 
752     return result;
753 }
754 
755 #ifdef SUPPORT_GRAPHICS
JsGetDisplayOrientation(napi_env env,napi_callback_info info,const AbilityType abilityType)756 napi_value JsNapiCommon::JsGetDisplayOrientation(napi_env env, napi_callback_info info, const AbilityType abilityType)
757 {
758     TAG_LOGD(AAFwkTag::JSNAPI, "called");
759     size_t argc = ARGS_MAX_COUNT;
760     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
761     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
762     if (argc > ARGS_ONE) {
763         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
764         return CreateJsUndefined(env);
765     }
766 
767     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
768     auto execute = [obj = this, value = errorVal, abilityType] () {
769         if (obj->ability_ == nullptr) {
770             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
771             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
772             return;
773         }
774         if (!obj->CheckAbilityType(abilityType)) {
775             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
776             return;
777         }
778         *value = obj->ability_->GetDisplayOrientation();
779     };
780     auto complete = [value = errorVal] (napi_env env, NapiAsyncTask &task, int32_t status) {
781         TAG_LOGD(AAFwkTag::JSNAPI, "innerCall value=%{public}d", *value);
782         if (*value == NAPI_ERR_ACE_ABILITY) {
783             task.Reject(env, CreateJsError(env, NAPI_ERR_ACE_ABILITY, "ability is nullptr"));
784         } else if (*value == NAPI_ERR_ABILITY_TYPE_INVALID) {
785             task.Reject(env, CreateJsError(env, NAPI_ERR_ABILITY_TYPE_INVALID, "ability type is invalid."));
786         } else if (*value == NAPI_ERR_NO_WINDOW) {
787             task.Reject(env, CreateJsError(env, NAPI_ERR_NO_WINDOW, "window is nullptr"));
788         } else {
789             task.Resolve(env, CreateJsValue(env, *value));
790         }
791     };
792 
793     auto callback = argc == ARGS_ZERO ? nullptr : argv[PARAM0];
794     napi_value result = nullptr;
795     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetDisplayOrientation",
796         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
797 
798     return result;
799 }
800 #endif
801 
CreateProcessInfo(napi_env env,const std::shared_ptr<JsProcessInfo> & processInfo)802 napi_value JsNapiCommon::CreateProcessInfo(napi_env env, const std::shared_ptr<JsProcessInfo> &processInfo)
803 {
804     TAG_LOGD(AAFwkTag::JSNAPI, "called");
805     CHECK_POINTER_AND_RETURN_LOG(processInfo, CreateJsUndefined(env), "input params error");
806 
807     napi_value objContext = nullptr;
808     napi_create_object(env, &objContext);
809     CHECK_POINTER_AND_RETURN_LOG(objContext, CreateJsUndefined(env), "CreateObject failed");
810 
811     napi_set_named_property(env, objContext, "processName", CreateJsValue(env, processInfo->processName));
812     napi_set_named_property(env, objContext, "pid", CreateJsValue(env, processInfo->pid));
813 
814     return objContext;
815 }
816 
CreateElementName(napi_env env,const std::shared_ptr<JsElementName> & elementName)817 napi_value JsNapiCommon::CreateElementName(napi_env env, const std::shared_ptr<JsElementName> &elementName)
818 {
819     TAG_LOGD(AAFwkTag::JSNAPI, "called");
820     CHECK_POINTER_AND_RETURN_LOG(elementName, CreateJsUndefined(env), "input params error");
821 
822     napi_value objContext = nullptr;
823     napi_create_object(env, &objContext);
824     CHECK_POINTER_AND_RETURN_LOG(objContext, CreateJsUndefined(env), "CreateObject failed");
825 
826     napi_set_named_property(env, objContext, "deviceId", CreateJsValue(env, elementName->deviceId));
827     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, elementName->bundleName));
828     napi_set_named_property(env, objContext, "abilityName", CreateJsValue(env, elementName->abilityName));
829     napi_set_named_property(env, objContext, "uri", CreateJsValue(env, elementName->uri));
830     napi_set_named_property(env, objContext, "shortName", CreateJsValue(env, elementName->shortName));
831 
832     return objContext;
833 }
834 
CreateHapModuleInfo(napi_env env,const std::shared_ptr<JsHapModuleInfo> & hapModInfo)835 napi_value JsNapiCommon::CreateHapModuleInfo(napi_env env, const std::shared_ptr<JsHapModuleInfo> &hapModInfo)
836 {
837     TAG_LOGD(AAFwkTag::JSNAPI, "called");
838     CHECK_POINTER_AND_RETURN_LOG(hapModInfo, CreateJsUndefined(env), "input params error");
839     napi_value objContext = nullptr;
840     napi_create_object(env, &objContext);
841     CHECK_POINTER_AND_RETURN_LOG(objContext, CreateJsUndefined(env), "CreateObject failed");
842 
843     napi_set_named_property(env, objContext, "name", CreateJsValue(env, hapModInfo->hapModInfo.name));
844     napi_set_named_property(env, objContext, "description", CreateJsValue(env, hapModInfo->hapModInfo.description));
845     napi_set_named_property(env, objContext, "icon", CreateJsValue(env, hapModInfo->hapModInfo.iconPath));
846     napi_set_named_property(env, objContext, "label", CreateJsValue(env, hapModInfo->hapModInfo.label));
847     napi_set_named_property(env, objContext, "backgroundImg",
848         CreateJsValue(env, hapModInfo->hapModInfo.backgroundImg));
849     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, hapModInfo->hapModInfo.moduleName));
850     napi_set_named_property(env, objContext, "mainAbilityName",
851         CreateJsValue(env, hapModInfo->hapModInfo.mainAbility));
852     napi_set_named_property(env, objContext, "supportedModes",
853         CreateJsValue(env, hapModInfo->hapModInfo.supportedModes));
854     napi_set_named_property(env, objContext, "descriptionId",
855         CreateJsValue(env, hapModInfo->hapModInfo.descriptionId));
856     napi_set_named_property(env, objContext, "labelId", CreateJsValue(env, hapModInfo->hapModInfo.labelId));
857     napi_set_named_property(env, objContext, "iconId", CreateJsValue(env, hapModInfo->hapModInfo.iconId));
858     napi_set_named_property(env, objContext, "installationFree",
859         CreateJsValue(env, hapModInfo->hapModInfo.installationFree));
860     napi_set_named_property(env, objContext, "reqCapabilities",
861         CreateNativeArray(env, hapModInfo->hapModInfo.reqCapabilities));
862     napi_set_named_property(env, objContext, "deviceTypes",
863         CreateNativeArray(env, hapModInfo->hapModInfo.deviceTypes));
864     napi_set_named_property(env, objContext, "abilityInfo",
865         CreateAbilityInfos(env, hapModInfo->hapModInfo.abilityInfos));
866 
867     return objContext;
868 }
869 
CreateModuleInfo(napi_env env,const ModuleInfo & modInfo)870 napi_value JsNapiCommon::CreateModuleInfo(napi_env env, const ModuleInfo &modInfo)
871 {
872     napi_value objContext = nullptr;
873     napi_create_object(env, &objContext);
874     if (objContext == nullptr) {
875         TAG_LOGE(AAFwkTag::JSNAPI, "CreateObject error");
876         return CreateJsUndefined(env);
877     }
878     if (!CheckTypeForNapiValue(env, objContext, napi_object)) {
879         TAG_LOGE(AAFwkTag::JSNAPI, "ConvertNativeValueTo object error");
880         return CreateJsUndefined(env);
881     }
882 
883     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, modInfo.moduleName));
884     napi_set_named_property(env, objContext, "moduleSourceDir", CreateJsValue(env, modInfo.moduleSourceDir));
885 
886     return objContext;
887 }
888 
CreateModuleInfos(napi_env env,const std::vector<ModuleInfo> & moduleInfos)889 napi_value JsNapiCommon::CreateModuleInfos(napi_env env, const std::vector<ModuleInfo> &moduleInfos)
890 {
891     napi_value arrayValue = nullptr;
892     napi_create_array_with_length(env, moduleInfos.size(), &arrayValue);
893     if (arrayValue == nullptr) {
894         TAG_LOGE(AAFwkTag::JSNAPI, "CreateArray failed");
895         return CreateJsUndefined(env);
896     }
897     for (uint32_t i = 0; i < moduleInfos.size(); i++) {
898         napi_set_element(env, arrayValue, i, CreateModuleInfo(env, moduleInfos.at(i)));
899     }
900 
901     return arrayValue;
902 }
903 
CreateAppInfo(napi_env env,const ApplicationInfo & appInfo)904 napi_value JsNapiCommon::CreateAppInfo(napi_env env, const ApplicationInfo &appInfo)
905 {
906     TAG_LOGD(AAFwkTag::JSNAPI, "called");
907     napi_value objContext = nullptr;
908     napi_create_object(env, &objContext);
909     if (objContext == nullptr) {
910         TAG_LOGE(AAFwkTag::JSNAPI, "CreateObject error");
911         return CreateJsUndefined(env);
912     }
913     if (!CheckTypeForNapiValue(env, objContext, napi_object)) {
914         TAG_LOGE(AAFwkTag::JSNAPI, "objContext not object");
915         return CreateJsUndefined(env);
916     }
917 
918     napi_set_named_property(env, objContext, "name", CreateJsValue(env, appInfo.name));
919     napi_set_named_property(env, objContext, "description", CreateJsValue(env, appInfo.description));
920     napi_set_named_property(env, objContext, "descriptionId", CreateJsValue(env, appInfo.descriptionId));
921     napi_set_named_property(env, objContext, "systemApp", CreateJsValue(env, appInfo.isSystemApp));
922     napi_set_named_property(env, objContext, "enabled", CreateJsValue(env, appInfo.enabled));
923     napi_set_named_property(env, objContext, "label", CreateJsValue(env, appInfo.label));
924     napi_set_named_property(env, objContext, "labelId", CreateJsValue(env, std::to_string(appInfo.labelId)));
925     napi_set_named_property(env, objContext, "icon", CreateJsValue(env, appInfo.iconPath));
926     napi_set_named_property(env, objContext, "iconId", CreateJsValue(env, std::to_string(appInfo.iconId)));
927     napi_set_named_property(env, objContext, "process", CreateJsValue(env, appInfo.process));
928     napi_set_named_property(env, objContext, "entryDir", CreateJsValue(env, appInfo.entryDir));
929     napi_set_named_property(env, objContext, "supportedModes", CreateJsValue(env, appInfo.supportedModes));
930     napi_set_named_property(env, objContext, "moduleSourceDirs", CreateNativeArray(env, appInfo.moduleSourceDirs));
931     napi_set_named_property(env, objContext, "permissions", CreateNativeArray(env, appInfo.permissions));
932     napi_set_named_property(env, objContext, "moduleInfos", CreateModuleInfos(env, appInfo.moduleInfos));
933 
934     return objContext;
935 }
936 
CreateAppInfo(napi_env env,const std::shared_ptr<JsApplicationInfo> & appInfo)937 napi_value JsNapiCommon::CreateAppInfo(napi_env env, const std::shared_ptr<JsApplicationInfo> &appInfo)
938 {
939     if (appInfo == nullptr) {
940         TAG_LOGE(AAFwkTag::JSNAPI, "input param error");
941         return CreateJsUndefined(env);
942     }
943 
944     return CreateAppInfo(env, appInfo->appInfo);
945 }
946 
CreateAbilityInfo(napi_env env,const AbilityInfo & abilityInfo)947 napi_value JsNapiCommon::CreateAbilityInfo(napi_env env, const AbilityInfo &abilityInfo)
948 {
949     TAG_LOGD(AAFwkTag::JSNAPI, "called");
950     napi_value objContext = nullptr;
951     napi_create_object(env, &objContext);
952     if (objContext == nullptr) {
953         TAG_LOGE(AAFwkTag::JSNAPI, "null objContext");
954         return CreateJsUndefined(env);
955     }
956     if (!CheckTypeForNapiValue(env, objContext, napi_object)) {
957         TAG_LOGE(AAFwkTag::JSNAPI, "objContext not object");
958         return CreateJsUndefined(env);
959     }
960 
961     napi_set_named_property(env, objContext, "bundleName", CreateJsValue(env, abilityInfo.bundleName));
962     napi_set_named_property(env, objContext, "name", CreateJsValue(env, abilityInfo.name));
963     napi_set_named_property(env, objContext, "label", CreateJsValue(env, abilityInfo.label));
964     napi_set_named_property(env, objContext, "description", CreateJsValue(env, abilityInfo.description));
965     napi_set_named_property(env, objContext, "icon", CreateJsValue(env, abilityInfo.iconPath));
966     napi_set_named_property(env, objContext, "moduleName", CreateJsValue(env, abilityInfo.moduleName));
967     napi_set_named_property(env, objContext, "process", CreateJsValue(env, abilityInfo.process));
968     napi_set_named_property(env, objContext, "uri", CreateJsValue(env, abilityInfo.uri));
969     napi_set_named_property(env, objContext, "readPermission", CreateJsValue(env, abilityInfo.readPermission));
970     napi_set_named_property(env, objContext, "writePermission", CreateJsValue(env, abilityInfo.writePermission));
971     napi_set_named_property(env, objContext, "targetAbility", CreateJsValue(env, abilityInfo.targetAbility));
972     napi_set_named_property(env, objContext, "type", CreateJsValue(env, static_cast<int32_t>(abilityInfo.type)));
973     napi_set_named_property(env, objContext, "orientation",
974         CreateJsValue(env, static_cast<int32_t>(abilityInfo.orientation)));
975     napi_set_named_property(env, objContext, "launchMode",
976         CreateJsValue(env, static_cast<int32_t>(abilityInfo.launchMode)));
977     napi_set_named_property(env, objContext, "labelId", CreateJsValue(env, abilityInfo.labelId));
978     napi_set_named_property(env, objContext, "descriptionId", CreateJsValue(env, abilityInfo.descriptionId));
979     napi_set_named_property(env, objContext, "iconId", CreateJsValue(env, abilityInfo.iconId));
980     napi_set_named_property(env, objContext, "formEntity", CreateJsValue(env, abilityInfo.formEntity));
981     napi_set_named_property(env, objContext, "minFormHeight", CreateJsValue(env, abilityInfo.minFormHeight));
982     napi_set_named_property(env, objContext, "defaultFormHeight", CreateJsValue(env, abilityInfo.defaultFormHeight));
983     napi_set_named_property(env, objContext, "minFormWidth", CreateJsValue(env, abilityInfo.minFormWidth));
984     napi_set_named_property(env, objContext, "defaultFormWidth", CreateJsValue(env, abilityInfo.defaultFormWidth));
985     napi_set_named_property(env, objContext, "backgroundModes", CreateJsValue(env, abilityInfo.backgroundModes));
986     napi_set_named_property(env, objContext, "subType", CreateJsValue(env, static_cast<int32_t>(abilityInfo.subType)));
987     napi_set_named_property(env, objContext, "isVisible", CreateJsValue(env, abilityInfo.visible));
988     napi_set_named_property(env, objContext, "formEnabled", CreateJsValue(env, abilityInfo.formEnabled));
989     napi_set_named_property(env, objContext, "permissions", CreateNativeArray(env, abilityInfo.permissions));
990     napi_set_named_property(env, objContext, "deviceCapabilities",
991         CreateNativeArray(env, abilityInfo.deviceCapabilities));
992     napi_set_named_property(env, objContext, "deviceTypes", CreateNativeArray(env, abilityInfo.deviceTypes));
993     napi_set_named_property(env, objContext, "applicationInfo", CreateAppInfo(env, abilityInfo.applicationInfo));
994 
995     return objContext;
996 }
997 
CreateAbilityInfo(napi_env env,const std::shared_ptr<JsAbilityInfoInfo> & abilityInfo)998 napi_value JsNapiCommon::CreateAbilityInfo(
999     napi_env env, const std::shared_ptr<JsAbilityInfoInfo> &abilityInfo)
1000 {
1001     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1002     if (abilityInfo == nullptr) {
1003         TAG_LOGE(AAFwkTag::JSNAPI, "null abilityInfo");
1004         return CreateJsUndefined(env);
1005     }
1006 
1007     return CreateAbilityInfo(env, abilityInfo->abilityInfo);
1008 }
1009 
CreateAbilityInfos(napi_env env,const std::vector<AbilityInfo> & abilityInfos)1010 napi_value JsNapiCommon::CreateAbilityInfos(napi_env env, const std::vector<AbilityInfo> &abilityInfos)
1011 {
1012     napi_value arrayValue = nullptr;
1013     napi_create_array_with_length(env, abilityInfos.size(), &arrayValue);
1014     if (arrayValue == nullptr) {
1015         TAG_LOGE(AAFwkTag::JSNAPI, "CreateArray failed");
1016         return CreateJsUndefined(env);
1017     }
1018     for (uint32_t i = 0; i < abilityInfos.size(); i++) {
1019         napi_set_element(env, arrayValue, i, CreateAbilityInfo(env, abilityInfos.at(i)));
1020     }
1021 
1022     return arrayValue;
1023 }
1024 
CheckAbilityType(const AbilityType typeWant)1025 bool JsNapiCommon::CheckAbilityType(const AbilityType typeWant)
1026 {
1027     if (ability_ == nullptr) {
1028         TAG_LOGE(AAFwkTag::JSNAPI, "params error");
1029         return false;
1030     }
1031     const std::shared_ptr<AbilityInfo> info = ability_->GetAbilityInfo();
1032     if (info == nullptr) {
1033         TAG_LOGE(AAFwkTag::JSNAPI, "get ability info error");
1034         return false;
1035     }
1036 
1037     switch (typeWant) {
1038         case AbilityType::PAGE:
1039             if (static_cast<AbilityType>(info->type) == AbilityType::PAGE ||
1040                 static_cast<AbilityType>(info->type) == AbilityType::DATA) {
1041                 return true;
1042             }
1043             return false;
1044         default:
1045             return static_cast<AbilityType>(info->type) != AbilityType::PAGE;
1046     }
1047     return false;
1048 }
1049 
CreateAppVersionInfo(napi_env env,const std::shared_ptr<JsApplicationInfo> & appInfo)1050 napi_value JsNapiCommon::CreateAppVersionInfo(napi_env env, const std::shared_ptr<JsApplicationInfo> &appInfo)
1051 {
1052     TAG_LOGD(AAFwkTag::JSNAPI, "CreateAppVersionInfo called");
1053     CHECK_POINTER_AND_RETURN_LOG(appInfo, CreateJsUndefined(env), "input params error");
1054     napi_value objContext = nullptr;
1055     napi_create_object(env, &objContext);
1056     CHECK_POINTER_AND_RETURN_LOG(objContext, CreateJsUndefined(env), "CreateObject failed");
1057 
1058     napi_set_named_property(env, objContext, "appName", CreateJsValue(env, appInfo->appInfo.name));
1059     napi_set_named_property(env, objContext, "versionName", CreateJsValue(env, appInfo->appInfo.versionName));
1060     napi_set_named_property(env, objContext, "versionCode",
1061         CreateJsValue(env, static_cast<int32_t>(appInfo->appInfo.versionCode)));
1062 
1063     return objContext;
1064 }
1065 
UnwrapVerifyPermissionParams(napi_env env,napi_callback_info info,JsPermissionOptions & options)1066 bool JsNapiCommon::UnwrapVerifyPermissionParams(napi_env env, napi_callback_info info, JsPermissionOptions &options)
1067 {
1068     bool flagCall = true;
1069     size_t argc = ARGS_MAX_COUNT;
1070     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
1071     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1072     if (argc == ARGS_ONE) {
1073         flagCall = false;
1074     } else if (argc == ARGS_TWO && !AppExecFwk::IsTypeForNapiValue(env, argv[PARAM1], napi_function)) {
1075         if (!GetPermissionOptions(env, argv[PARAM1], options)) {
1076             TAG_LOGE(AAFwkTag::JSNAPI, "argc==2 invalid param");
1077         }
1078         flagCall = false;
1079     } else if (argc == ARGS_THREE) {
1080         if (!GetPermissionOptions(env, argv[PARAM1], options)) {
1081             TAG_LOGE(AAFwkTag::JSNAPI, "argc==3 invalid param");
1082         }
1083     }
1084 
1085     return flagCall;
1086 }
1087 
GetStringsValue(napi_env env,napi_value object,std::vector<std::string> & strList)1088 bool JsNapiCommon::GetStringsValue(napi_env env, napi_value object, std::vector<std::string> &strList)
1089 {
1090     bool isArray = false;
1091     napi_is_array(env, object, &isArray);
1092     if (object == nullptr || !isArray) {
1093         TAG_LOGE(AAFwkTag::JSNAPI, "input params error");
1094         return false;
1095     }
1096     uint32_t length = 0;
1097     napi_get_array_length(env, object, &length);
1098     for (uint32_t i = 0; i < length; i++) {
1099         std::string itemStr("");
1100         napi_value elementVal = nullptr;
1101         napi_get_element(env, object, i, &elementVal);
1102         if (!ConvertFromJsValue(env, elementVal, itemStr)) {
1103             TAG_LOGE(AAFwkTag::JSNAPI, "GetElement from to array [%{public}u] error", i);
1104             return false;
1105         }
1106         strList.push_back(itemStr);
1107     }
1108 
1109     return true;
1110 }
1111 
GetPermissionOptions(napi_env env,napi_value object,JsPermissionOptions & options)1112 bool JsNapiCommon::GetPermissionOptions(napi_env env, napi_value object, JsPermissionOptions &options)
1113 {
1114     if (object == nullptr || !CheckTypeForNapiValue(env, object, napi_object)) {
1115         TAG_LOGE(AAFwkTag::JSNAPI, "input params error");
1116         return false;
1117     }
1118     napi_value uidValue = nullptr;
1119     napi_get_named_property(env, object, "uid", &uidValue);
1120     napi_value pidValue = nullptr;
1121     napi_get_named_property(env, object, "pid", &pidValue);
1122     options.uidFlag = ConvertFromJsValue(env, uidValue, options.uid);
1123     options.pidFlag = ConvertFromJsValue(env, pidValue, options.pid);
1124 
1125     return true;
1126 }
1127 
ConvertErrorCode(int32_t errCode)1128 std::string JsNapiCommon::ConvertErrorCode(int32_t errCode)
1129 {
1130     static std::map<int32_t, std::string> errMap = {
1131         { static_cast<int32_t>(NAPI_ERR_ACE_ABILITY), std::string("get ability error") },
1132         { static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID), std::string("ability call error") },
1133         { static_cast<int32_t>(NAPI_ERR_PARAM_INVALID), std::string("input param error") },
1134         { static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID), std::string("ability type error") }
1135     };
1136     auto findECode = errMap.find(errCode);
1137     if (findECode == errMap.end()) {
1138         TAG_LOGE(AAFwkTag::JSNAPI, "convert error code failed");
1139         return std::string("execution failed");
1140     }
1141 
1142     return findECode->second;
1143 }
1144 
JsGetWant(napi_env env,napi_callback_info info,const AbilityType abilityType)1145 napi_value JsNapiCommon::JsGetWant(napi_env env, napi_callback_info info, const AbilityType abilityType)
1146 {
1147     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1148     size_t argc = ARGS_MAX_COUNT;
1149     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
1150     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1151     if (argc > ARGS_ONE) {
1152         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
1153         return CreateJsUndefined(env);
1154     }
1155 
1156     std::shared_ptr<JsWant> pwant = std::make_shared<JsWant>();
1157     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
1158     auto execute = [obj = this, want = pwant, value = errorVal, abilityType] () {
1159         if (obj->ability_ == nullptr) {
1160             *value = static_cast<int32_t>(NAPI_ERR_ACE_ABILITY);
1161             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
1162             return;
1163         }
1164         if (!obj->CheckAbilityType(abilityType)) {
1165             TAG_LOGE(AAFwkTag::JSNAPI, "abilityType error");
1166             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_TYPE_INVALID);
1167             return;
1168         }
1169 
1170         auto wantData = obj->ability_->GetWant();
1171         if (wantData == nullptr || want == nullptr) {
1172             TAG_LOGE(AAFwkTag::JSNAPI, "null wantData or want");
1173             *value = static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID);
1174             return;
1175         }
1176         want->want = *wantData;
1177     };
1178 
1179     auto complete = [obj = this, value = errorVal, pwant]
1180         (napi_env env, NapiAsyncTask &task, int32_t status) {
1181         if (*value == NAPI_ERR_NO_ERROR && pwant != nullptr) {
1182             task.Resolve(env, obj->CreateWant(env, pwant));
1183         } else {
1184             auto error = (pwant == nullptr) ? static_cast<int32_t>(NAPI_ERR_ABILITY_CALL_INVALID) : *value;
1185             task.Reject(env, CreateJsError(env, error, "GetAbilityInfo return nullptr"));
1186         }
1187     };
1188 
1189     auto callback = (argc == ARGS_ZERO) ? nullptr : argv[PARAM0];
1190     napi_value result = nullptr;
1191     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetWant",
1192         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
1193     return result;
1194 }
1195 
CreateWant(napi_env env,const std::shared_ptr<JsWant> & want)1196 napi_value JsNapiCommon::CreateWant(napi_env env, const std::shared_ptr<JsWant> &want)
1197 {
1198     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1199     if (want == nullptr) {
1200         TAG_LOGE(AAFwkTag::JSNAPI, "null want");
1201         return CreateJsUndefined(env);
1202     }
1203 
1204     return CreateJsWant(env, want->want);
1205 }
1206 
JsTerminateAbility(napi_env env,NapiCallbackInfo & info)1207 napi_value JsNapiCommon::JsTerminateAbility(napi_env env, NapiCallbackInfo& info)
1208 {
1209     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1210     if (info.argc > ARGS_ONE) {
1211         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", info.argc);
1212         return CreateJsUndefined(env);
1213     }
1214 
1215     auto complete = [obj = this](napi_env env, NapiAsyncTask &task, int32_t status) {
1216         if (obj->ability_ != nullptr) {
1217             obj->ability_->TerminateAbility();
1218         } else {
1219             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
1220         }
1221         task.Resolve(env, CreateJsNull(env));
1222     };
1223 
1224     auto callback = (info.argc == ARGS_ZERO) ? nullptr : info.argv[PARAM0];
1225     napi_value result = nullptr;
1226     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsTerminateAbility",
1227         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1228     return result;
1229 }
1230 
1231 /**
1232  * @brief Parse the parameters.
1233  *
1234  * @param param Indicates the parameters saved the parse result.
1235  * @param env The environment that the Node-API call is invoked under.
1236  * @param args Indicates the arguments passed into the callback.
1237  *
1238  * @return The return value from NAPI C++ to JS for the module.
1239  */
UnwrapParamForWant(napi_env env,napi_value args,AbilityType,CallAbilityParam & param)1240 bool UnwrapParamForWant(napi_env env, napi_value args, AbilityType, CallAbilityParam &param)
1241 {
1242     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1243     bool ret = false;
1244     napi_valuetype valueType = napi_undefined;
1245     param.setting = nullptr;
1246     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
1247     if (valueType != napi_object) {
1248         TAG_LOGE(AAFwkTag::JSNAPI, "wrong argument type");
1249         return false;
1250     }
1251 
1252     napi_value jsWant = GetPropertyValueByPropertyName(env, args, "want", napi_object);
1253     if (jsWant == nullptr) {
1254         TAG_LOGE(AAFwkTag::JSNAPI, "null jsWant");
1255         return false;
1256     }
1257 
1258     ret = UnwrapWant(env, jsWant, param.want);
1259 
1260     napi_value jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSettings", napi_object);
1261     if (jsSettingObj == nullptr) {
1262         jsSettingObj = GetPropertyValueByPropertyName(env, args, "abilityStartSetting", napi_object);
1263     }
1264     if (jsSettingObj != nullptr) {
1265         param.setting = AbilityStartSetting::GetEmptySetting();
1266         if (!UnwrapAbilityStartSetting(env, jsSettingObj, *(param.setting))) {
1267             TAG_LOGE(AAFwkTag::JSNAPI, "unwrap abilityStartSetting failed");
1268         }
1269         TAG_LOGI(AAFwkTag::JSNAPI, "abilityStartSetting");
1270     }
1271 
1272     TAG_LOGI(AAFwkTag::JSNAPI, "end");
1273     return ret;
1274 }
1275 
SetJsStartAbilityExecuteCallback(std::shared_ptr<int32_t> & errorVal,AbilityType & abilityType,std::shared_ptr<CallAbilityParam> & param,NapiAsyncTask::ExecuteCallback & execute)1276 void JsNapiCommon::SetJsStartAbilityExecuteCallback(std::shared_ptr<int32_t> &errorVal, AbilityType &abilityType,
1277     std::shared_ptr<CallAbilityParam> &param, NapiAsyncTask::ExecuteCallback &execute)
1278 {
1279     execute = [obj = this, value = errorVal, abilityType, paramObj = param, &observer = freeInstallObserver_] () {
1280         if (*value != NAPI_ERR_NO_ERROR) {
1281             TAG_LOGE(AAFwkTag::JSNAPI, "invalid param");
1282             return;
1283         }
1284 
1285         if (obj->ability_ == nullptr) {
1286             *value = NAPI_ERR_ACE_ABILITY;
1287             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
1288             return;
1289         }
1290 
1291         if (!obj->CheckAbilityType(abilityType)) {
1292             *value = NAPI_ERR_ABILITY_TYPE_INVALID;
1293             TAG_LOGE(AAFwkTag::JSNAPI, "abilityType error");
1294             return;
1295         }
1296 #ifdef SUPPORT_SCREEN
1297         // inherit split mode
1298         auto windowMode = obj->ability_->GetCurrentWindowMode();
1299         if (windowMode == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_PRIMARY ||
1300             windowMode == AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_SECONDARY) {
1301             paramObj->want.SetParam(Want::PARAM_RESV_WINDOW_MODE, windowMode);
1302         }
1303         TAG_LOGD(AAFwkTag::JSNAPI, "window mode is %{public}d", windowMode);
1304 
1305         // follow orientation
1306         paramObj->want.SetParam("ohos.aafwk.Orientation", 0);
1307         if (windowMode != AbilityWindowConfiguration::MULTI_WINDOW_DISPLAY_FLOATING) {
1308             auto orientation = obj->ability_->GetDisplayOrientation();
1309             paramObj->want.SetParam("ohos.aafwk.Orientation", orientation);
1310             TAG_LOGD(AAFwkTag::JSNAPI, "display orientation is %{public}d", orientation);
1311         }
1312 #endif
1313         if (paramObj->setting == nullptr) {
1314             TAG_LOGI(AAFwkTag::JSNAPI, "null setting");
1315             *value = obj->ability_->StartAbility(paramObj->want);
1316         } else {
1317             TAG_LOGI(AAFwkTag::JSNAPI, "null setting");
1318             *value = obj->ability_->StartAbility(paramObj->want, *(paramObj->setting));
1319         }
1320         if ((paramObj->want.GetFlags() & Want::FLAG_INSTALL_ON_DEMAND) == Want::FLAG_INSTALL_ON_DEMAND &&
1321             *value != 0 && observer != nullptr) {
1322             std::string bundleName = paramObj->want.GetElement().GetBundleName();
1323             std::string abilityName = paramObj->want.GetElement().GetAbilityName();
1324             std::string startTime = paramObj->want.GetStringParam(Want::PARAM_RESV_START_TIME);
1325             observer->OnInstallFinished(bundleName, abilityName, startTime, *value);
1326         }
1327     };
1328 }
1329 
JsStartAbility(napi_env env,napi_callback_info info,AbilityType abilityType)1330 napi_value JsNapiCommon::JsStartAbility(napi_env env, napi_callback_info info, AbilityType abilityType)
1331 {
1332     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1333     auto errorVal = std::make_shared<int32_t>(static_cast<int32_t>(NAPI_ERR_NO_ERROR));
1334     auto param = std::make_shared<CallAbilityParam>();
1335     size_t argc = ARGS_MAX_COUNT;
1336     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
1337     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1338     if (argc == 0 || argc > ARGS_TWO) {
1339         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
1340         *errorVal = NAPI_ERR_PARAM_INVALID;
1341     } else {
1342         if (!UnwrapParamForWant(env, argv[PARAM0], abilityType, *param)) {
1343             TAG_LOGE(AAFwkTag::JSNAPI, "unwrapParamForWant failed");
1344             *errorVal = NAPI_ERR_PARAM_INVALID;
1345         }
1346     }
1347 
1348     if ((param->want.GetFlags() & Want::FLAG_INSTALL_ON_DEMAND) == Want::FLAG_INSTALL_ON_DEMAND) {
1349         std::string startTime = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
1350             system_clock::now().time_since_epoch()).count());
1351         param->want.SetParam(Want::PARAM_RESV_START_TIME, startTime);
1352     }
1353     NapiAsyncTask::ExecuteCallback execute;
1354     SetJsStartAbilityExecuteCallback(errorVal, abilityType, param, execute);
1355     auto complete = [value = errorVal]
1356         (napi_env env, NapiAsyncTask& task, int32_t status) {
1357         if (*value != NAPI_ERR_NO_ERROR) {
1358             int32_t errCode = GetStartAbilityErrorCode(*value);
1359             task.Reject(env, CreateJsError(env, errCode, "StartAbility Failed"));
1360             return;
1361         }
1362         task.Resolve(env, CreateJsValue(env, *value));
1363     };
1364 
1365     auto callback = (argc == ARGS_ONE) ? nullptr : argv[PARAM1];
1366     napi_value result = nullptr;
1367     if ((param->want.GetFlags() & Want::FLAG_INSTALL_ON_DEMAND) == Want::FLAG_INSTALL_ON_DEMAND) {
1368         AddFreeInstallObserver(env, param->want, callback, &result);
1369         NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsStartAbility", env,
1370             CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), nullptr, nullptr));
1371     } else {
1372         NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsStartAbility", env,
1373             CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
1374     }
1375 
1376     return result;
1377 }
1378 
JsGetExternalCacheDir(napi_env env,napi_callback_info info,AbilityType abilityType)1379 napi_value JsNapiCommon::JsGetExternalCacheDir(napi_env env, napi_callback_info info, AbilityType abilityType)
1380 {
1381     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1382     size_t argc = ARGS_MAX_COUNT;
1383     napi_value argv[ARGS_MAX_COUNT] = {nullptr};
1384     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1385     if (argc > ARGS_ONE) {
1386         TAG_LOGE(AAFwkTag::JSNAPI, "invalid argc:%{public}zu", argc);
1387         return CreateJsUndefined(env);
1388     }
1389 
1390     auto complete = [obj = this, abilityType](napi_env env, NapiAsyncTask &task, int32_t status) {
1391         if (obj->ability_ == nullptr) {
1392             TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
1393             task.RejectWithCustomize(
1394                 env,
1395                 CreateJsError(env, NAPI_ERR_ACE_ABILITY, "JsGetExternalCacheDir Failed"),
1396                 CreateJsNull(env));
1397             return;
1398         }
1399 
1400         if (!obj->CheckAbilityType(abilityType)) {
1401             TAG_LOGE(AAFwkTag::JSNAPI, "abilityType error");
1402             task.Reject(env, CreateJsError(env, NAPI_ERR_ABILITY_TYPE_INVALID, "JsGetExternalCacheDir Failed"));
1403             return;
1404         }
1405 
1406         std::string result = obj->ability_->GetExternalCacheDir();
1407         task.Resolve(env, CreateJsValue(env, result));
1408     };
1409 
1410     auto callback = (argc == ARGS_ZERO) ? nullptr : argv[PARAM0];
1411     napi_value result = nullptr;
1412     NapiAsyncTask::ScheduleHighQos("JsNapiCommon::JsGetExternalCacheDir",
1413         env, CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
1414     return result;
1415 }
1416 
AddFreeInstallObserver(napi_env env,const AAFwk::Want & want,napi_value callback,napi_value * result)1417 void JsNapiCommon::AddFreeInstallObserver(napi_env env, const AAFwk::Want &want, napi_value callback,
1418     napi_value* result)
1419 {
1420     // adapter free install async return install and start result
1421     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1422     if (ability_ == nullptr) {
1423         TAG_LOGE(AAFwkTag::JSNAPI, "null ability");
1424         return;
1425     }
1426     int ret = 0;
1427     if (freeInstallObserver_ == nullptr) {
1428         freeInstallObserver_ = new JsFreeInstallObserver(env);
1429         ret = ability_->AddFreeInstallObserver(freeInstallObserver_);
1430     }
1431 
1432     if (ret != ERR_OK) {
1433         TAG_LOGE(AAFwkTag::JSNAPI, "add observer failed");
1434     } else {
1435         TAG_LOGD(AAFwkTag::JSNAPI, "called");
1436         // build a callback observer with last param
1437         std::string bundleName = want.GetElement().GetBundleName();
1438         std::string abilityName = want.GetElement().GetAbilityName();
1439         std::string startTime = want.GetStringParam(Want::PARAM_RESV_START_TIME);
1440         freeInstallObserver_->AddJsObserverObject(bundleName, abilityName, startTime, callback, result);
1441     }
1442 }
1443 
ClearCallbackWork(uv_work_t * req,int)1444 void ClearCallbackWork(uv_work_t* req, int)
1445 {
1446     std::unique_ptr<uv_work_t> work(req);
1447     if (!req) {
1448         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1449         return;
1450     }
1451     std::unique_ptr<ConnectionCallback> callback(reinterpret_cast<ConnectionCallback*>(req->data));
1452     if (!callback) {
1453         TAG_LOGE(AAFwkTag::JSNAPI, "null data");
1454         return;
1455     }
1456     callback->Reset();
1457 }
1458 
Reset()1459 void ConnectionCallback::Reset()
1460 {
1461     auto engine = reinterpret_cast<NativeEngine*>(env);
1462     if (engine == nullptr) {
1463         removeKey = nullptr;
1464         return;
1465     }
1466     if (pthread_self() == engine->GetTid()) {
1467         TAG_LOGD(AAFwkTag::JSNAPI, "in-js-thread");
1468         if (connectCallbackRef) {
1469             napi_delete_reference(env, connectCallbackRef);
1470             connectCallbackRef = nullptr;
1471         }
1472         if (disconnectCallbackRef) {
1473             napi_delete_reference(env, disconnectCallbackRef);
1474             disconnectCallbackRef = nullptr;
1475         }
1476         if (failedCallbackRef) {
1477             napi_delete_reference(env, failedCallbackRef);
1478             failedCallbackRef = nullptr;
1479         }
1480         env = nullptr;
1481         removeKey = nullptr;
1482         return;
1483     }
1484     TAG_LOGI(AAFwkTag::JSNAPI, "not in-js-thread");
1485     auto loop = engine->GetUVLoop();
1486     if (loop == nullptr) {
1487         TAG_LOGE(AAFwkTag::JSNAPI, "null loop");
1488         env = nullptr;
1489         removeKey = nullptr;
1490         return;
1491     }
1492     uv_work_t *work = new(std::nothrow) uv_work_t;
1493     if (work == nullptr) {
1494         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1495         return;
1496     }
1497     ConnectionCallback *data = new(std::nothrow) ConnectionCallback(std::move(*this));
1498     if (data == nullptr) {
1499         TAG_LOGE(AAFwkTag::JSNAPI, "null data");
1500         delete work;
1501         return;
1502     }
1503     work->data = data;
1504     auto ret = uv_queue_work(loop, work, [](uv_work_t*) {}, ClearCallbackWork);
1505     if (ret != 0) {
1506         TAG_LOGE(AAFwkTag::JSNAPI, "uv_queue_work failed: %{public}d", ret);
1507         data->env = nullptr;
1508         data->removeKey = nullptr;
1509         delete data;
1510         delete work;
1511     }
1512 }
1513 
AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback)1514 void NAPIAbilityConnection::AddConnectionCallback(std::shared_ptr<ConnectionCallback> callback)
1515 {
1516     std::lock_guard<std::mutex> guard(lock_);
1517     callbacks_.emplace_back(callback);
1518 }
1519 
GetConnectionState() const1520 int NAPIAbilityConnection::GetConnectionState() const
1521 {
1522     std::lock_guard<std::mutex> guard(lock_);
1523     return connectionState_;
1524 }
1525 
SetConnectionState(int connectionState)1526 void NAPIAbilityConnection::SetConnectionState(int connectionState)
1527 {
1528     std::lock_guard<std::mutex> guard(lock_);
1529     connectionState_ = connectionState;
1530 }
1531 
GetCallbackSize()1532 size_t NAPIAbilityConnection::GetCallbackSize()
1533 {
1534     std::lock_guard<std::mutex> guard(lock_);
1535     return callbacks_.size();
1536 }
1537 
RemoveAllCallbacks(ConnectRemoveKeyType key)1538 size_t NAPIAbilityConnection::RemoveAllCallbacks(ConnectRemoveKeyType key)
1539 {
1540     size_t result = 0;
1541     std::lock_guard<std::mutex> guard(lock_);
1542     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
1543         auto callback = *it;
1544         if (callback && callback->removeKey == key) {
1545             it = callbacks_.erase(it);
1546             result++;
1547         } else {
1548             ++it;
1549         }
1550     }
1551     TAG_LOGI(AAFwkTag::JSNAPI, "removed size:%{public}zu, left size:%{public}zu", result,
1552              callbacks_.size());
1553     return result;
1554 }
1555 
UvWorkOnAbilityConnectDone(uv_work_t * work,int status)1556 void UvWorkOnAbilityConnectDone(uv_work_t *work, int status)
1557 {
1558     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1559     std::unique_ptr<uv_work_t> managedWork(work);
1560     if (work == nullptr) {
1561         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1562         return;
1563     }
1564     // JS Thread
1565     std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
1566     if (connectAbilityCB == nullptr) {
1567         TAG_LOGE(AAFwkTag::JSNAPI, "null connectAbilityCB");
1568         return;
1569     }
1570     CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
1571     napi_handle_scope scope = nullptr;
1572     napi_open_handle_scope(cbInfo.env, &scope);
1573     if (scope == nullptr) {
1574         TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
1575         return;
1576     }
1577 
1578     napi_value globalValue;
1579     napi_get_global(cbInfo.env, &globalValue);
1580     napi_value func;
1581     napi_get_named_property(cbInfo.env, globalValue, "requireNapi", &func);
1582 
1583     napi_value rpcInfo;
1584     napi_create_string_utf8(cbInfo.env, "rpc", NAPI_AUTO_LENGTH, &rpcInfo);
1585     napi_value funcArgv[1] = { rpcInfo };
1586     napi_value returnValue;
1587     napi_call_function(cbInfo.env, globalValue, func, 1, funcArgv, &returnValue);
1588 
1589     napi_value result[ARGS_TWO] = {nullptr};
1590     result[PARAM0] =
1591         WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
1592     napi_value jsRemoteObject = NAPI_ohos_rpc_CreateJsRemoteObject(
1593         cbInfo.env, connectAbilityCB->abilityConnectionCB.connection);
1594     result[PARAM1] = jsRemoteObject;
1595 
1596     napi_value callback = nullptr;
1597     napi_value undefined = nullptr;
1598     napi_get_undefined(cbInfo.env, &undefined);
1599     napi_value callResult = nullptr;
1600     napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
1601 
1602     napi_call_function(
1603         cbInfo.env, undefined, callback, ARGS_TWO, &result[PARAM0], &callResult);
1604     if (cbInfo.callback != nullptr) {
1605         napi_delete_reference(cbInfo.env, cbInfo.callback);
1606     }
1607     napi_close_handle_scope(cbInfo.env, scope);
1608 }
1609 
HandleOnAbilityConnectDone(ConnectionCallback & callback,int resultCode)1610 void NAPIAbilityConnection::HandleOnAbilityConnectDone(ConnectionCallback &callback, int resultCode)
1611 {
1612     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1613     uv_loop_s *loop = nullptr;
1614     napi_get_uv_event_loop(callback.env, &loop);
1615     if (loop == nullptr) {
1616         TAG_LOGE(AAFwkTag::JSNAPI, "null loop");
1617         return;
1618     }
1619 
1620     uv_work_t *work = new(std::nothrow) uv_work_t;
1621     if (work == nullptr) {
1622         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1623         return;
1624     }
1625 
1626     ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
1627     if (connectAbilityCB == nullptr) {
1628         TAG_LOGE(AAFwkTag::JSNAPI, "null connectAbilityCB");
1629         if (work != nullptr) {
1630             delete work;
1631             work = nullptr;
1632         }
1633         return;
1634     }
1635     connectAbilityCB->cbBase.cbInfo.env = callback.env;
1636     connectAbilityCB->cbBase.cbInfo.callback = callback.connectCallbackRef;
1637     callback.connectCallbackRef = nullptr;
1638     connectAbilityCB->abilityConnectionCB.elementName = element_;
1639     connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
1640     connectAbilityCB->abilityConnectionCB.connection = serviceRemoteObject_;
1641     work->data = static_cast<void *>(connectAbilityCB);
1642 
1643     int rev = uv_queue_work_with_qos(
1644         loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityConnectDone, uv_qos_user_initiated);
1645     if (rev != 0) {
1646         if (connectAbilityCB != nullptr) {
1647             delete connectAbilityCB;
1648             connectAbilityCB = nullptr;
1649         }
1650         if (work != nullptr) {
1651             delete work;
1652             work = nullptr;
1653         }
1654     }
1655 }
1656 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)1657 void NAPIAbilityConnection::OnAbilityConnectDone(
1658     const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int resultCode)
1659 {
1660     TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
1661              __func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
1662     if (remoteObject == nullptr) {
1663         TAG_LOGE(AAFwkTag::JSNAPI, "%{public}s, remoteObject == nullptr.", __func__);
1664         return;
1665     }
1666     std::lock_guard<std::mutex> guard(lock_);
1667     element_ = element;
1668     serviceRemoteObject_ = remoteObject;
1669     for (const auto &callback : callbacks_) {
1670         HandleOnAbilityConnectDone(*callback, resultCode);
1671     }
1672     connectionState_ = CONNECTION_STATE_CONNECTED;
1673 }
1674 
UvWorkOnAbilityDisconnectDone(uv_work_t * work,int status)1675 void UvWorkOnAbilityDisconnectDone(uv_work_t *work, int status)
1676 {
1677     TAG_LOGD(AAFwkTag::JSNAPI, "called");
1678     std::unique_ptr<uv_work_t> managedWork(work);
1679     if (work == nullptr) {
1680         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1681         return;
1682     }
1683     // JS Thread
1684     std::unique_ptr<ConnectAbilityCB> connectAbilityCB(static_cast<ConnectAbilityCB *>(work->data));
1685     if (connectAbilityCB == nullptr) {
1686         TAG_LOGE(AAFwkTag::JSNAPI, "null connectAbilityCB");
1687         return;
1688     }
1689     CallbackInfo &cbInfo = connectAbilityCB->cbBase.cbInfo;
1690     napi_handle_scope scope = nullptr;
1691     napi_open_handle_scope(cbInfo.env, &scope);
1692     if (scope == nullptr) {
1693         TAG_LOGE(AAFwkTag::JSNAPI, "napi_open_handle_scope failed");
1694         return;
1695     }
1696     napi_value result = WrapElementName(cbInfo.env, connectAbilityCB->abilityConnectionCB.elementName);
1697     if (cbInfo.callback != nullptr) {
1698         napi_value callback = nullptr;
1699         napi_value callResult = nullptr;
1700         napi_value undefined = nullptr;
1701         napi_get_undefined(cbInfo.env, &undefined);
1702         napi_get_reference_value(cbInfo.env, cbInfo.callback, &callback);
1703         napi_call_function(cbInfo.env, undefined, callback, ARGS_ONE, &result, &callResult);
1704         napi_delete_reference(cbInfo.env, cbInfo.callback);
1705         cbInfo.callback = nullptr;
1706     }
1707     napi_close_handle_scope(cbInfo.env, scope);
1708 
1709     // release connect
1710     std::lock_guard<std::mutex> lock(g_connectionsLock_);
1711     TAG_LOGI(AAFwkTag::JSNAPI, "connects_.size:%{public}zu", connects_.size());
1712     std::string deviceId = connectAbilityCB->abilityConnectionCB.elementName.GetDeviceID();
1713     std::string bundleName = connectAbilityCB->abilityConnectionCB.elementName.GetBundleName();
1714     std::string abilityName = connectAbilityCB->abilityConnectionCB.elementName.GetAbilityName();
1715     auto item = std::find_if(connects_.begin(), connects_.end(),
1716         [deviceId, bundleName, abilityName](const std::map<ConnectionKey,
1717             sptr<NAPIAbilityConnection>>::value_type &obj) {
1718             return (deviceId == obj.first.want.GetDeviceId()) &&
1719                    (bundleName == obj.first.want.GetBundle()) &&
1720                    (abilityName == obj.first.want.GetElement().GetAbilityName());
1721         });
1722     if (item != connects_.end()) {
1723         // match deviceId & bundlename && abilityname
1724         connects_.erase(item);
1725         TAG_LOGI(AAFwkTag::JSNAPI, "connects_.size:%{public}zu", connects_.size());
1726     }
1727 }
1728 
HandleOnAbilityDisconnectDone(ConnectionCallback & callback,int resultCode)1729 void NAPIAbilityConnection::HandleOnAbilityDisconnectDone(ConnectionCallback &callback, int resultCode)
1730 {
1731     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1732     uv_loop_s *loop = nullptr;
1733     napi_get_uv_event_loop(callback.env, &loop);
1734     if (loop == nullptr) {
1735         TAG_LOGE(AAFwkTag::JSNAPI, "null loop");
1736         return;
1737     }
1738 
1739     uv_work_t *work = new(std::nothrow) uv_work_t;
1740     if (work == nullptr) {
1741         TAG_LOGE(AAFwkTag::JSNAPI, "null work");
1742         return;
1743     }
1744 
1745     ConnectAbilityCB *connectAbilityCB = new (std::nothrow) ConnectAbilityCB;
1746     if (connectAbilityCB == nullptr) {
1747         TAG_LOGE(AAFwkTag::JSNAPI, "null connectAbilityCB");
1748         if (work != nullptr) {
1749             delete work;
1750             work = nullptr;
1751         }
1752         return;
1753     }
1754 
1755     connectAbilityCB->cbBase.cbInfo.env = callback.env;
1756     connectAbilityCB->cbBase.cbInfo.callback = callback.disconnectCallbackRef;
1757     callback.disconnectCallbackRef = nullptr;
1758     connectAbilityCB->abilityConnectionCB.elementName = element_;
1759     connectAbilityCB->abilityConnectionCB.resultCode = resultCode;
1760     work->data = static_cast<void *>(connectAbilityCB);
1761 
1762     int rev = uv_queue_work(
1763         loop, work, [](uv_work_t *work) {}, UvWorkOnAbilityDisconnectDone);
1764     if (rev != 0) {
1765         if (connectAbilityCB != nullptr) {
1766             delete connectAbilityCB;
1767             connectAbilityCB = nullptr;
1768         }
1769         if (work != nullptr) {
1770             delete work;
1771             work = nullptr;
1772         }
1773     }
1774 }
1775 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)1776 void NAPIAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
1777 {
1778     TAG_LOGI(AAFwkTag::JSNAPI, "%{public}s bundleName:%{public}s abilityName:%{public}s, resultCode:%{public}d",
1779              __func__, element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
1780     std::lock_guard<std::mutex> guard(lock_);
1781     element_ = element;
1782     for (const auto &callback : callbacks_) {
1783         HandleOnAbilityDisconnectDone(*callback, resultCode);
1784     }
1785     connectionState_ = CONNECTION_STATE_DISCONNECTED;
1786 }
1787 }  // namespace AppExecFwk
1788 }  // namespace OHOS
1789