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