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 ¶m)
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> ¶m, 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