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