1 /*
2 * Copyright (c) 2022-2023 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_continuation_manager.h"
17
18 #include <memory>
19
20 #include "base/continuationmgr_log.h"
21 #include "distributed_ability_manager_client.h"
22 #include "distributed_sched_utils.h"
23 #include "js_runtime_utils.h"
24 #include "napi_common_util.h"
25 #include "napi_error_code.h"
26
27 namespace OHOS {
28 namespace DistributedSchedule {
29 using namespace OHOS::AbilityRuntime;
30 using namespace OHOS::AppExecFwk;
31 namespace {
32 const std::string TAG = "JsContinuationManager";
33 const std::string CODE_KEY_NAME = "code";
34 constexpr int32_t ERR_NOT_OK = -1;
35 constexpr int32_t ERROR_CODE_ONE = 1;
36 constexpr int32_t ARG_COUNT_ONE = 1;
37 constexpr int32_t ARG_COUNT_TWO = 2;
38 constexpr int32_t ARG_COUNT_THREE = 3;
39 constexpr uint32_t MAX_JSPROCOUNT = 1000000;
40 constexpr int32_t ARG_COUNT_FOUR = 4;
41 }
42
Finalizer(napi_env env,void * data,void * hint)43 void JsContinuationManager::Finalizer(napi_env env, void* data, void* hint)
44 {
45 HILOGI("JsContinuationManager::Finalizer is called");
46 JsContinuationManager* jsContinuationManager = static_cast<JsContinuationManager*>(data);
47 if (jsContinuationManager != nullptr) {
48 delete jsContinuationManager;
49 jsContinuationManager = nullptr;
50 }
51 }
52
Register(napi_env env,napi_callback_info info)53 napi_value JsContinuationManager::Register(napi_env env, napi_callback_info info)
54 {
55 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
56 return (me != nullptr) ? me->OnRegister(env, info) : nullptr;
57 }
58
Unregister(napi_env env,napi_callback_info info)59 napi_value JsContinuationManager::Unregister(napi_env env, napi_callback_info info)
60 {
61 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
62 return (me != nullptr) ? me->OnUnregister(env, info) : nullptr;
63 }
64
RegisterDeviceSelectionCallback(napi_env env,napi_callback_info info)65 napi_value JsContinuationManager::RegisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
66 {
67 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
68 return (me != nullptr) ? me->OnRegisterDeviceSelectionCallback(env, info) : nullptr;
69 }
70
UnregisterDeviceSelectionCallback(napi_env env,napi_callback_info info)71 napi_value JsContinuationManager::UnregisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
72 {
73 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
74 return (me != nullptr) ? me->OnUnregisterDeviceSelectionCallback(env, info) : nullptr;
75 }
76
UpdateConnectStatus(napi_env env,napi_callback_info info)77 napi_value JsContinuationManager::UpdateConnectStatus(napi_env env, napi_callback_info info)
78 {
79 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
80 return (me != nullptr) ? me->OnUpdateConnectStatus(env, info) : nullptr;
81 }
82
StartDeviceManager(napi_env env,napi_callback_info info)83 napi_value JsContinuationManager::StartDeviceManager(napi_env env, napi_callback_info info)
84 {
85 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
86 return (me != nullptr) ? me->OnStartDeviceManager(env, info) : nullptr;
87 }
88
InitDeviceConnectStateObject(napi_env env,napi_callback_info info)89 napi_value JsContinuationManager::InitDeviceConnectStateObject(napi_env env, napi_callback_info info)
90 {
91 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
92 return (me != nullptr) ? me->OnInitDeviceConnectStateObject(env, info) : nullptr;
93 }
94
InitContinuationModeObject(napi_env env,napi_callback_info info)95 napi_value JsContinuationManager::InitContinuationModeObject(napi_env env, napi_callback_info info)
96 {
97 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
98 return (me != nullptr) ? me->OnInitContinuationModeObject(env, info) : nullptr;
99 }
100
RegisterContinuation(napi_env env,napi_callback_info info)101 napi_value JsContinuationManager::RegisterContinuation(napi_env env, napi_callback_info info)
102 {
103 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
104 return (me != nullptr) ? me->OnRegisterContinuation(env, info) : nullptr;
105 }
106
UnregisterContinuation(napi_env env,napi_callback_info info)107 napi_value JsContinuationManager::UnregisterContinuation(napi_env env, napi_callback_info info)
108 {
109 JsContinuationManager* me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
110 return (me != nullptr) ? me->OnUnregisterContinuation(env, info) : nullptr;
111 }
112
UpdateContinuationState(napi_env env,napi_callback_info info)113 napi_value JsContinuationManager::UpdateContinuationState(napi_env env, napi_callback_info info)
114 {
115 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
116 return (me != nullptr) ? me->OnUpdateContinuationState(env, info) : nullptr;
117 }
118
StartContinuationDeviceManager(napi_env env,napi_callback_info info)119 napi_value JsContinuationManager::StartContinuationDeviceManager(napi_env env, napi_callback_info info)
120 {
121 JsContinuationManager *me = CheckParamsAndGetThis<JsContinuationManager>(env, info);
122 return (me != nullptr) ? me->OnStartContinuationDeviceManager(env, info) : nullptr;
123 }
124
OnRegister(napi_env env,napi_callback_info info)125 napi_value JsContinuationManager::OnRegister(napi_env env, napi_callback_info info)
126 {
127 HILOGD("called.");
128 int32_t errCode = 0;
129 size_t unwrapArgc = 0;
130 size_t argc = ARG_COUNT_TWO;
131 napi_value argv[ARG_COUNT_TWO] = { 0 };
132 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
133 std::shared_ptr<ContinuationExtraParams> continuationExtraParams = std::make_shared<ContinuationExtraParams>();
134 napi_valuetype valuetype = napi_valuetype::napi_undefined;
135 if (argc > 0) {
136 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
137 }
138 if (valuetype == napi_valuetype::napi_object) {
139 HILOGI("register options is used.");
140 if (!UnWrapContinuationExtraParams(env, argv[0], continuationExtraParams)) {
141 HILOGE("Parse continuationExtraParams failed");
142 errCode = ERR_NOT_OK;
143 }
144 unwrapArgc++;
145 }
146 NapiAsyncTask::CompleteCallback complete =
147 [continuationExtraParams, unwrapArgc, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
148 napi_handle_scope scope = nullptr;
149 napi_open_handle_scope(env, &scope);
150 if (scope == nullptr) {
151 return;
152 }
153
154 if (errCode != 0) {
155 task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
156 napi_close_handle_scope(env, scope);
157 return;
158 }
159 int32_t token = -1;
160 int32_t ret = (unwrapArgc == 0) ? DistributedAbilityManagerClient::GetInstance().Register(nullptr, token) :
161 DistributedAbilityManagerClient::GetInstance().Register(continuationExtraParams, token);
162 if (ret == ERR_OK) {
163 task.Resolve(env, CreateJsValue(env, token));
164 } else {
165 task.Reject(env, CreateJsError(env, ret, "Register failed."));
166 }
167
168 napi_close_handle_scope(env, scope);
169 };
170
171 napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
172 napi_value result = nullptr;
173 NapiAsyncTask::Schedule("JsContinuationManager::OnRegister",
174 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
175 return result;
176 }
177
GetErrorInforForRegisterContination(napi_env env,napi_callback_info info,size_t & unwrapArgc,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)178 std::string JsContinuationManager::GetErrorInforForRegisterContination(napi_env env, napi_callback_info info,
179 size_t &unwrapArgc, std::shared_ptr<ContinuationExtraParams> &continuationExtraParams)
180 {
181 size_t argc = ARG_COUNT_TWO;
182 napi_value argv[ARG_COUNT_TWO] = { 0 };
183 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
184 if (argc > ARG_COUNT_TWO) {
185 return "Parameter error. The type of \"number of parameters\" must be less than 3";
186 }
187 napi_valuetype valuetype = napi_valuetype::napi_undefined;
188 if (argc > 0) {
189 NAPI_CALL(env, napi_typeof(env, argv[0], &valuetype));
190 }
191 if (valuetype == napi_valuetype::napi_object) {
192 HILOGI("register options is used.");
193 continuationExtraParams = std::make_shared<ContinuationExtraParams>();
194 if (!UnWrapContinuationExtraParams(env, argv[0], continuationExtraParams)) {
195 return "Parameter error. The type of \"options\" must be ContinuationExtraParams";
196 }
197 unwrapArgc++;
198 }
199 return std::string();
200 }
201
OnRegisterContinuation(napi_env env,napi_callback_info info)202 napi_value JsContinuationManager::OnRegisterContinuation(napi_env env, napi_callback_info info)
203 {
204 HILOGD("called.");
205 size_t unwrapArgc = 0;
206 std::shared_ptr<ContinuationExtraParams> continuationExtraParams;
207 std::string errInfo = GetErrorInforForRegisterContination(env, info, unwrapArgc, continuationExtraParams);
208 if (!errInfo.empty()) {
209 HILOGE("%{public}s", errInfo.c_str());
210 napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
211 return CreateJsUndefined(env);
212 }
213 size_t argc = ARG_COUNT_TWO;
214 napi_value argv[ARG_COUNT_TWO] = { 0 };
215 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
216 napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
217 napi_value result = nullptr;
218 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
219 auto asyncTask = [this, continuationExtraParams, unwrapArgc, env, task = napiAsyncTask.get()]() {
220 if (task == nullptr) {
221 return;
222 }
223 napi_handle_scope scope = nullptr;
224 napi_open_handle_scope(env, &scope);
225 if (scope == nullptr) {
226 delete task;
227 return;
228 }
229 int32_t token = -1;
230 int32_t errCode = (unwrapArgc == 0) ? DistributedAbilityManagerClient::GetInstance().Register(nullptr, token) :
231 DistributedAbilityManagerClient::GetInstance().Register(continuationExtraParams, token);
232 if (errCode == ERR_OK) {
233 task->Resolve(env, CreateJsValue(env, token));
234 } else {
235 errCode = ErrorCodeReturn(errCode);
236 task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
237 }
238
239 napi_close_handle_scope(env, scope);
240 delete task;
241 };
242 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
243 napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
244 } else {
245 napiAsyncTask.release();
246 }
247 return result;
248 }
249
OnUnregister(napi_env env,napi_callback_info info)250 napi_value JsContinuationManager::OnUnregister(napi_env env, napi_callback_info info)
251 {
252 HILOGD("called.");
253 int32_t errCode = 0;
254 size_t argc = ARG_COUNT_TWO;
255 napi_value argv[ARG_COUNT_TWO] = { 0 };
256 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
257 if (argc == 0) {
258 HILOGE("Params not match");
259 errCode = ERR_NOT_OK;
260 }
261 int32_t token = -1;
262 if (!errCode && !ConvertFromJsValue(env, argv[0], token)) {
263 HILOGE("Parse token failed");
264 errCode = ERR_NOT_OK;
265 }
266
267 NapiAsyncTask::CompleteCallback complete =
268 [token, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
269 napi_handle_scope scope = nullptr;
270 napi_open_handle_scope(env, &scope);
271 if (scope == nullptr) {
272 return;
273 }
274
275 if (errCode != 0) {
276 task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
277 napi_close_handle_scope(env, scope);
278 return;
279 }
280 int32_t ret = DistributedAbilityManagerClient::GetInstance().Unregister(token);
281 if (ret == ERR_OK) {
282 task.Resolve(env, CreateJsUndefined(env));
283 } else {
284 task.Reject(env, CreateJsError(env, ret, "Unregister failed."));
285 }
286
287 napi_close_handle_scope(env, scope);
288 };
289
290 napi_value lastParam = (argc <= ARG_COUNT_ONE) ? nullptr : argv[ARG_COUNT_ONE];
291 napi_value result = nullptr;
292 NapiAsyncTask::Schedule("JsContinuationManager::OnUnregister",
293 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
294 return result;
295 }
296
OnUnregisterContinuation(napi_env env,napi_callback_info info)297 napi_value JsContinuationManager::OnUnregisterContinuation(napi_env env, napi_callback_info info)
298 {
299 HILOGD("called.");
300 int32_t token = -1;
301 size_t argc = ARG_COUNT_TWO;
302 napi_value argv[ARG_COUNT_TWO] = { 0 };
303 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
304 std::string errInfo = [this, &env, &argc, argv, &token]() -> std::string {
305 if (argc == 0 || argc > ARG_COUNT_TWO) {
306 return "Parameter error. The type of \"number of parameters\" must be greater than 0 and less than 3";
307 }
308 if (!ConvertFromJsValue(env, argv[0], token)) {
309 return "Parameter error. The type of \"token\" must be number";
310 }
311 return std::string();
312 } ();
313 if (!errInfo.empty()) {
314 HILOGE("%{public}s", errInfo.c_str());
315 napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
316 return CreateJsUndefined(env);
317 }
318
319 napi_value lastParam = (argc == ARG_COUNT_ONE) ? nullptr : argv[ARG_COUNT_ONE];
320 napi_value result = nullptr;
321 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
322 auto asyncTask = [this, token, env, task = napiAsyncTask.get()]() {
323 if (task == nullptr) {
324 return;
325 }
326 napi_handle_scope scope = nullptr;
327 napi_open_handle_scope(env, &scope);
328 if (scope == nullptr) {
329 delete task;
330 return;
331 }
332 int32_t errCode = DistributedAbilityManagerClient::GetInstance().Unregister(token);
333 if (errCode == ERR_OK) {
334 task->Resolve(env, CreateJsNull(env));
335 } else {
336 errCode = ErrorCodeReturn(errCode);
337 task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
338 }
339
340 napi_close_handle_scope(env, scope);
341 delete task;
342 };
343 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
344 napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
345 } else {
346 napiAsyncTask.release();
347 }
348 return result;
349 }
350
OnRegisterDeviceSelectionCallbackParameterCheck(napi_env env,napi_callback_info info,std::string & cbType,int32_t & token,napi_value * jsListenerObj)351 std::string JsContinuationManager::OnRegisterDeviceSelectionCallbackParameterCheck(napi_env env,
352 napi_callback_info info, std::string &cbType, int32_t &token, napi_value *jsListenerObj)
353 {
354 size_t argc = ARG_COUNT_THREE;
355 napi_value argv[ARG_COUNT_THREE] = { 0 };
356 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
357 if (argc != ARG_COUNT_THREE) {
358 return "Parameter error. The type of \"number of parameters\" must be 3";
359 }
360 if (!ConvertFromJsValue(env, argv[0], cbType)) {
361 return "Parameter error. The type of \"type\" must be string";
362 }
363 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
364 return "Parameter error. The type of \"type\" must be " +
365 std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
366 }
367 if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], token)) {
368 return "Parameter error. The type of \"token\" must be number";
369 }
370 *jsListenerObj = argv[ARG_COUNT_TWO];
371 if (!IsCallbackValid(env, *jsListenerObj)) {
372 return "Parameter error. The type of \"callback\" must be Callback<Array<ContinuationResult>>";
373 }
374 return std::string();
375 }
376
OnRegisterDeviceSelectionCallback(napi_env env,napi_callback_info info)377 napi_value JsContinuationManager::OnRegisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
378 {
379 HILOGD("called.");
380 std::string cbType;
381 int32_t token = -1;
382 int32_t errCode = PARAMETER_CHECK_FAILED;
383 napi_value jsListenerObj = nullptr;
384 std::string errInfo = OnRegisterDeviceSelectionCallbackParameterCheck(env, info, cbType, token, &jsListenerObj);
385 if (errInfo.empty()) {
386 errInfo = [this, &env, &info, &cbType, &token, &jsListenerObj, &errCode]() -> std::string {
387 std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
388 if (IsCallbackRegistered(token, cbType)) {
389 errCode = REPEATED_REGISTRATION;
390 return ErrorMessageReturn(errCode);
391 }
392 napi_ref tempRef = nullptr;
393 napi_create_reference(env, jsListenerObj, 1, &tempRef);
394 std::unique_ptr<NativeReference> callbackRef;
395 callbackRef.reset(reinterpret_cast<NativeReference*>(tempRef));
396 sptr<JsDeviceSelectionListener> deviceSelectionListener(new JsDeviceSelectionListener(env));
397 if (deviceSelectionListener == nullptr) {
398 HILOGE("deviceSelectionListener is nullptr!");
399 errCode = SYSTEM_WORK_ABNORMALLY;
400 return ErrorMessageReturn(errCode);
401 }
402 errCode = DistributedAbilityManagerClient::GetInstance().RegisterDeviceSelectionCallback(
403 token, cbType, deviceSelectionListener);
404 if (errCode == ERR_OK) {
405 deviceSelectionListener->AddCallback(cbType, jsListenerObj);
406 CallbackPair callbackPair = std::make_pair(std::move(callbackRef), deviceSelectionListener);
407 jsCbMap_[token][cbType] = std::move(callbackPair); // move assignment
408 HILOGI("RegisterDeviceSelectionListener success");
409 } else {
410 deviceSelectionListener = nullptr;
411 errCode = ErrorCodeReturn(errCode);
412 return ErrorMessageReturn(errCode);
413 }
414 return std::string();
415 }();
416 }
417 if (!errInfo.empty()) {
418 HILOGE("%{public}s", errInfo.c_str());
419 napi_throw(env,
420 GenerateBusinessError(env, errCode, errInfo));
421 }
422 return CreateJsUndefined(env);
423 }
424
OnUnregisterDeviceSelectionCallback(napi_env env,napi_callback_info info)425 napi_value JsContinuationManager::OnUnregisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
426 {
427 HILOGD("called.");
428 std::string cbType;
429 int32_t token = -1;
430 int32_t errCode = PARAMETER_CHECK_FAILED;
431 std::string errInfo = [this, &env, &info, &cbType, &token, &errCode]() -> std::string {
432 size_t argc = ARG_COUNT_TWO;
433 napi_value argv[ARG_COUNT_TWO] = { 0 };
434 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
435 if (argc != ARG_COUNT_TWO) {
436 return "Parameter error. The type of \"number of parameters\" must be 2";
437 }
438 if (!ConvertFromJsValue(env, argv[0], cbType)) {
439 return "Parameter error. The type of \"type\" must be string";
440 }
441 if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
442 return "Parameter error. The type of \"type\" must be " +
443 std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
444 }
445 if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], token)) {
446 return "Parameter error. The type of \"token\" must be number";
447 }
448 {
449 std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
450 if (!IsCallbackRegistered(token, cbType)) {
451 errCode = CALLBACK_TOKEN_UNREGISTERED;
452 return ErrorMessageReturn(errCode);
453 }
454 errCode = DistributedAbilityManagerClient::GetInstance().UnregisterDeviceSelectionCallback(token, cbType);
455 if (errCode == ERR_OK) {
456 CallbackPair& callbackPair = jsCbMap_[token][cbType];
457 callbackPair.second->RemoveCallback(cbType);
458 jsCbMap_[token].erase(cbType);
459 if (jsCbMap_[token].empty()) {
460 jsCbMap_.erase(token);
461 }
462 HILOGI("UnregisterDeviceSelectionCallback success");
463 } else {
464 errCode = ErrorCodeReturn(errCode);
465 return ErrorMessageReturn(errCode);
466 }
467 }
468 return std::string();
469 } ();
470 if (!errInfo.empty()) {
471 HILOGE("%{public}s", errInfo.c_str());
472 napi_throw(env, GenerateBusinessError(env, errCode, errInfo));
473 }
474 return CreateJsUndefined(env);
475 }
476
GetInfoForUpdateConnectStatus(napi_env env,napi_value * argv,int32_t & token,std::string & deviceId,DeviceConnectStatus & deviceConnectStatus)477 int32_t JsContinuationManager::GetInfoForUpdateConnectStatus(napi_env env,
478 napi_value *argv, int32_t &token, std::string &deviceId, DeviceConnectStatus &deviceConnectStatus)
479 {
480 int32_t errCode = 0;
481 if (!errCode && !ConvertFromJsValue(env, argv[0], token)) {
482 HILOGE("Parse token failed");
483 errCode = ERR_NOT_OK;
484 }
485 if (!errCode && !ConvertFromJsValue(env, argv[ARG_COUNT_ONE], deviceId)) {
486 HILOGE("Parse deviceId failed");
487 errCode = ERR_NOT_OK;
488 }
489 if (!errCode && !ConvertFromJsValue(env, argv[ARG_COUNT_TWO], deviceConnectStatus)) {
490 HILOGE("Parse device connect status failed");
491 errCode = ERR_NOT_OK;
492 }
493 return errCode;
494 }
495
OnUpdateConnectStatus(napi_env env,napi_callback_info info)496 napi_value JsContinuationManager::OnUpdateConnectStatus(napi_env env, napi_callback_info info)
497 {
498 HILOGD("called.");
499 int32_t errCode = 0;
500 size_t argc = ARG_COUNT_FOUR;
501 napi_value argv[ARG_COUNT_FOUR] = { 0 };
502 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
503 if (argc < ARG_COUNT_THREE) {
504 HILOGE("Params not match");
505 errCode = ERR_NOT_OK;
506 }
507 int32_t token = -1;
508 std::string deviceId;
509 DeviceConnectStatus deviceConnectStatus = DeviceConnectStatus::IDLE;
510 errCode = GetInfoForUpdateConnectStatus(env, argv, token, deviceId, deviceConnectStatus);
511 NapiAsyncTask::CompleteCallback complete =
512 [token, deviceId, deviceConnectStatus, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
513 napi_handle_scope scope = nullptr;
514 napi_open_handle_scope(env, &scope);
515 if (scope == nullptr) {
516 return;
517 }
518
519 if (errCode != 0) {
520 task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
521 napi_close_handle_scope(env, scope);
522 return;
523 }
524 int32_t ret = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
525 token, deviceId, deviceConnectStatus);
526 if (ret == ERR_OK) {
527 task.Resolve(env, CreateJsUndefined(env));
528 } else {
529 task.Reject(env, CreateJsError(env, ret, "UpdateConnectStatus failed."));
530 }
531 napi_close_handle_scope(env, scope);
532 };
533
534 napi_value lastParam = (argc <= ARG_COUNT_THREE) ? nullptr : argv[ARG_COUNT_THREE];
535 napi_value result = nullptr;
536 NapiAsyncTask::Schedule("JsContinuationManager::OnUpdateConnectStatus",
537 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
538 return result;
539 }
540
GetErrorInfo(napi_env env,napi_callback_info info,int32_t & token,std::string & deviceId,DeviceConnectStatus & deviceConnectStatus)541 std::string JsContinuationManager::GetErrorInfo(napi_env env, napi_callback_info info, int32_t &token,
542 std::string &deviceId, DeviceConnectStatus &deviceConnectStatus)
543 {
544 size_t argc = ARG_COUNT_FOUR;
545 napi_value argv[ARG_COUNT_FOUR] = { nullptr };
546 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr));
547 if (argc != ARG_COUNT_THREE && argc != ARG_COUNT_FOUR) {
548 return "Parameter error. The type of \"number of parameters\" must be 3 or 4";
549 }
550 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
551 if (!ConvertFromJsValue(env, argv[0], token)) {
552 return "Parameter error. The type of \"token\" must be number";
553 }
554 if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], deviceId) || deviceId.empty()) {
555 return "Parameter error. The type of \"deviceId\" must be string and not empty";
556 }
557 deviceConnectStatus = DeviceConnectStatus::IDLE;
558 if (!ConvertFromJsValue(env, argv[ARG_COUNT_TWO], deviceConnectStatus)) {
559 return "Parameter error. The type of \"status\" must be DeviceConnectState";
560 }
561 if (static_cast<int32_t>(deviceConnectStatus) < static_cast<int32_t>(DeviceConnectStatus::IDLE) ||
562 static_cast<int32_t>(deviceConnectStatus) > static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)) {
563 HILOGE("deviceConnectStatus is invalid");
564 return "Parameter error. The type of \"status\" must be DeviceConnectState";
565 }
566 return std::string();
567 }
568
OnUpdateContinuationState(napi_env env,napi_callback_info info)569 napi_value JsContinuationManager::OnUpdateContinuationState(napi_env env, napi_callback_info info)
570 {
571 HILOGD("called.");
572 int32_t token = -1;
573 std::string deviceId;
574 DeviceConnectStatus deviceConnectStatus;
575 std::string errInfo = GetErrorInfo(env, info, token, deviceId, deviceConnectStatus);
576 if (!errInfo.empty()) {
577 HILOGE("%{public}s", errInfo.c_str());
578 napi_throw(env,
579 GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
580 return CreateJsUndefined(env);
581 }
582 size_t argc = ARG_COUNT_FOUR;
583 napi_value argv[ARG_COUNT_FOUR] = { 0 };
584 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
585 napi_value lastParam = (argc == ARG_COUNT_THREE) ? nullptr : argv[ARG_COUNT_THREE];
586 napi_value result = nullptr;
587 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
588 auto asyncTask = [this, token, deviceId, deviceConnectStatus, env, task = napiAsyncTask.get()]() {
589 if (task == nullptr) {
590 return;
591 }
592 napi_handle_scope scope = nullptr;
593 napi_open_handle_scope(env, &scope);
594 if (scope == nullptr) {
595 delete task;
596 return;
597 }
598 int32_t errCode = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
599 token, deviceId, deviceConnectStatus);
600 if (errCode == ERR_OK) {
601 task->Resolve(env, CreateJsNull(env));
602 } else {
603 errCode = ErrorCodeReturn(errCode);
604 task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
605 }
606
607 napi_close_handle_scope(env, scope);
608 delete task;
609 };
610 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
611 napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
612 } else {
613 napiAsyncTask.release();
614 }
615 return result;
616 }
617
CheckParamAndGetToken(napi_env env,size_t argc,napi_value * argv,int32_t & token)618 int32_t JsContinuationManager::CheckParamAndGetToken(napi_env env, size_t argc, napi_value *argv, int32_t &token)
619 {
620 int32_t errCode = 0;
621 if (argc < ARG_COUNT_ONE) {
622 HILOGE("Params not match");
623 errCode = ERR_NOT_OK;
624 }
625 if (!errCode && !ConvertFromJsValue(env, argv[0], token)) {
626 HILOGE("Parse token failed");
627 errCode = ERR_NOT_OK;
628 }
629 return errCode;
630 }
631
OnStartDeviceManager(napi_env env,napi_callback_info info)632 napi_value JsContinuationManager::OnStartDeviceManager(napi_env env, napi_callback_info info)
633 {
634 HILOGD("called.");
635 int32_t token = -1;
636 size_t argc = ARG_COUNT_THREE;
637 napi_value argv[ARG_COUNT_THREE] = { 0 };
638 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
639 int32_t errCode = CheckParamAndGetToken(env, argc, argv, token);
640 size_t unwrapArgc = ARG_COUNT_ONE;
641 std::shared_ptr<ContinuationExtraParams> continuationExtraParams = std::make_shared<ContinuationExtraParams>();
642 napi_valuetype valuetype = napi_valuetype::napi_undefined;
643 if (argc > ARG_COUNT_ONE) {
644 NAPI_CALL(env, napi_typeof(env, argv[ARG_COUNT_ONE], &valuetype));
645 }
646 if (valuetype == napi_valuetype::napi_object) {
647 HILOGI("startDeviceManager options is used.");
648 if (!UnWrapContinuationExtraParams(env, argv[ARG_COUNT_ONE], continuationExtraParams)) {
649 HILOGE("Parse continuationExtraParams failed");
650 errCode = ERR_NOT_OK;
651 }
652 unwrapArgc++;
653 }
654 NapiAsyncTask::CompleteCallback complete =
655 [token, continuationExtraParams, unwrapArgc, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
656 napi_handle_scope scope = nullptr;
657 napi_open_handle_scope(env, &scope);
658 if (scope == nullptr) {
659 return;
660 }
661
662 if (errCode != 0) {
663 task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
664 napi_close_handle_scope(env, scope);
665 return;
666 }
667 int32_t ret = (unwrapArgc == ARG_COUNT_ONE) ?
668 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token) :
669 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
670 if (ret == ERR_OK) {
671 task.Resolve(env, CreateJsUndefined(env));
672 } else {
673 task.Reject(env, CreateJsError(env, ret, "StartDeviceManager failed."));
674 }
675
676 napi_close_handle_scope(env, scope);
677 };
678
679 napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
680 napi_value result = nullptr;
681 NapiAsyncTask::Schedule("JsContinuationManager::OnStartDeviceManager",
682 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
683 return result;
684 }
685
GetErrorForStartContinuation(napi_env env,napi_callback_info info,int32_t & token,int32_t & unwrapArgc,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)686 std::string JsContinuationManager::GetErrorForStartContinuation(napi_env env, napi_callback_info info,
687 int32_t &token, int32_t &unwrapArgc, std::shared_ptr<ContinuationExtraParams> &continuationExtraParams)
688 {
689 size_t argc = ARG_COUNT_THREE;
690 napi_value argv[ARG_COUNT_THREE] = { 0 };
691 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
692 if (argc < ARG_COUNT_ONE || argc > ARG_COUNT_THREE) {
693 return "Parameter error. The type of \"number of parameters\" must be greater than 1 and less than 3";
694 }
695 if (!ConvertFromJsValue(env, argv[0], token)) {
696 return "Parameter error. The type of \"token\" must be number";
697 }
698 continuationExtraParams = std::make_shared<ContinuationExtraParams>();
699 napi_valuetype valuetype = napi_valuetype::napi_undefined;
700 if (argc > ARG_COUNT_ONE) {
701 NAPI_CALL(env, napi_typeof(env, argv[ARG_COUNT_ONE], &valuetype));
702 }
703 if (valuetype == napi_valuetype::napi_object) {
704 HILOGI("StartContinuationDeviceManager options is used.");
705 if (!UnWrapContinuationExtraParams(env, argv[ARG_COUNT_ONE], continuationExtraParams)) {
706 return "Parameter error. The type of \"options\" must be ContinuationExtraParams";
707 }
708 unwrapArgc++;
709 }
710 return std::string();
711 }
712
OnStartContinuationDeviceManager(napi_env env,napi_callback_info info)713 napi_value JsContinuationManager::OnStartContinuationDeviceManager(napi_env env, napi_callback_info info)
714 {
715 HILOGD("called.");
716 int32_t token = -1;
717 int32_t argc = ARG_COUNT_ONE;
718 std::shared_ptr<ContinuationExtraParams> continuationExtraParams;
719 std::string errInfo = GetErrorForStartContinuation(env, info, token, argc, continuationExtraParams);
720 if (!errInfo.empty()) {
721 HILOGE("%{public}s", errInfo.c_str());
722 napi_throw(env,
723 GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
724 return CreateJsUndefined(env);
725 }
726 size_t unwrapArgc = argc;
727 size_t napiArgc = ARG_COUNT_THREE;
728 napi_value argv[ARG_COUNT_THREE] = { 0 };
729 NAPI_CALL(env, napi_get_cb_info(env, info, &napiArgc, argv, nullptr, nullptr));
730 napi_value lastParam = (napiArgc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
731 napi_value result = nullptr;
732 std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
733 auto asyncTask = [this, token, continuationExtraParams, unwrapArgc, env, task = napiAsyncTask.get()]() {
734 if (task == nullptr) {
735 return;
736 }
737 napi_handle_scope scope = nullptr;
738 napi_open_handle_scope(env, &scope);
739 if (scope == nullptr) {
740 delete task;
741 return;
742 }
743 int32_t errCode = (unwrapArgc == ARG_COUNT_ONE) ?
744 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token) :
745 DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
746 if (errCode == ERR_OK) {
747 task->Resolve(env, CreateJsNull(env));
748 } else {
749 errCode = ErrorCodeReturn(errCode);
750 task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
751 }
752 napi_close_handle_scope(env, scope);
753 delete task;
754 };
755 if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
756 napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
757 } else {
758 napiAsyncTask.release();
759 }
760 return result;
761 }
762
OnInitDeviceConnectStateObject(napi_env env,napi_callback_info info)763 napi_value JsContinuationManager::OnInitDeviceConnectStateObject(napi_env env, napi_callback_info info)
764 {
765 napi_value object;
766 NAPI_CALL(env, napi_create_object(env, &object));
767
768 NAPI_CALL(env, SetEnumItem(env, object, "IDLE",
769 static_cast<int32_t>(DeviceConnectStatus::IDLE)));
770 NAPI_CALL(env, SetEnumItem(env, object, "CONNECTING",
771 static_cast<int32_t>(DeviceConnectStatus::CONNECTING)));
772 NAPI_CALL(env, SetEnumItem(env, object, "CONNECTED",
773 static_cast<int32_t>(DeviceConnectStatus::CONNECTED)));
774 NAPI_CALL(env, SetEnumItem(env, object, "DISCONNECTING",
775 static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)));
776
777 return object;
778 }
779
OnInitContinuationModeObject(napi_env env,napi_callback_info info)780 napi_value JsContinuationManager::OnInitContinuationModeObject(napi_env env, napi_callback_info info)
781 {
782 napi_value object;
783 NAPI_CALL(env, napi_create_object(env, &object));
784
785 NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_SINGLE",
786 static_cast<int32_t>(ContinuationMode::COLLABORATION_SINGLE)));
787 NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_MULTIPLE",
788 static_cast<int32_t>(ContinuationMode::COLLABORATION_MUTIPLE)));
789
790 return object;
791 }
792
SetEnumItem(const napi_env & env,napi_value object,const char * name,int32_t value)793 napi_status JsContinuationManager::SetEnumItem(const napi_env &env, napi_value object, const char* name, int32_t value)
794 {
795 napi_status status;
796 napi_value itemName;
797 napi_value itemValue;
798
799 NAPI_CALL_BASE(env, status = napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName), status);
800 NAPI_CALL_BASE(env, status = napi_create_int32(env, value, &itemValue), status);
801 NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemName, itemValue), status);
802 NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemValue, itemName), status);
803
804 return napi_ok;
805 }
806
IsCallbackValid(napi_env env,napi_value listenerObj)807 bool JsContinuationManager::IsCallbackValid(napi_env env, napi_value listenerObj)
808 {
809 if (listenerObj == nullptr) {
810 HILOGE("listenerObj is nullptr");
811 return false;
812 }
813 bool isCallable = false;
814 napi_is_callable(env, listenerObj, &isCallable);
815 return isCallable;
816 }
817
IsCallbackRegistered(int32_t token,const std::string & cbType)818 bool JsContinuationManager::IsCallbackRegistered(int32_t token, const std::string& cbType)
819 {
820 if (jsCbMap_.empty() || jsCbMap_.find(token) == jsCbMap_.end()) {
821 HILOGE("token %{public}s not registered callback!", GetAnonymStr(std::to_string(token)).c_str());
822 return false;
823 }
824 if (jsCbMap_[token].empty() || jsCbMap_[token].find(cbType) == jsCbMap_[token].end()) {
825 HILOGE("cbType %{public}s not registered callback!", cbType.c_str());
826 return false;
827 }
828 HILOGI("callback already registered, token: %{public}s, cbType %{public}s",
829 GetAnonymStr(std::to_string(token)).c_str(), cbType.c_str());
830 return true;
831 }
832
UnWrapContinuationExtraParams(const napi_env & env,const napi_value & options,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)833 bool JsContinuationManager::UnWrapContinuationExtraParams(const napi_env &env, const napi_value& options,
834 std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
835 {
836 HILOGD("called.");
837 if (!IsTypeForNapiValue(env, options, napi_object)) {
838 HILOGE("options is invalid.");
839 return false;
840 }
841 if (!continuationExtraParams) {
842 HILOGE("continuationExtraParams is nullptr.");
843 return false;
844 }
845 std::vector<std::string> deviceTypes;
846 if (UnwrapStringArrayByPropertyName(env, options, "deviceType", deviceTypes)) {
847 continuationExtraParams->SetDeviceType(deviceTypes);
848 }
849 std::string targetBundle("");
850 if (UnwrapStringByPropertyName(env, options, "targetBundle", targetBundle)) {
851 continuationExtraParams->SetTargetBundle(targetBundle);
852 }
853 std::string description("");
854 if (UnwrapStringByPropertyName(env, options, "description", description)) {
855 continuationExtraParams->SetDescription(description);
856 }
857 nlohmann::json filter;
858 if (!UnwrapJsonByPropertyName(env, options, "filter", filter)) {
859 return false;
860 }
861 if (!filter.empty()) {
862 continuationExtraParams->SetFilter(filter.dump());
863 }
864 int32_t continuationMode = 0;
865 if (UnwrapInt32ByPropertyName(env, options, "continuationMode", continuationMode)) {
866 continuationExtraParams->SetContinuationMode(static_cast<ContinuationMode>(continuationMode));
867 }
868 nlohmann::json authInfo;
869 if (UnwrapJsonByPropertyName(env, options, "authInfo", authInfo)) {
870 if (!authInfo.empty()) {
871 continuationExtraParams->SetAuthInfo(authInfo.dump());
872 }
873 }
874 return true;
875 }
876
UnwrapJsonByPropertyName(const napi_env & env,const napi_value & param,const std::string & field,nlohmann::json & jsonObj)877 bool JsContinuationManager::UnwrapJsonByPropertyName(const napi_env &env, const napi_value& param,
878 const std::string& field, nlohmann::json& jsonObj)
879 {
880 HILOGD("called.");
881 if (!IsTypeForNapiValue(env, param, napi_object)) {
882 HILOGE("param is invalid.");
883 return false;
884 }
885 napi_value jsonField = nullptr;
886 napi_get_named_property(env, param, field.c_str(), &jsonField);
887 napi_valuetype jsonFieldType = napi_undefined;
888 napi_typeof(env, jsonField, &jsonFieldType);
889 if (jsonFieldType != napi_object && jsonFieldType != napi_undefined) {
890 HILOGE("field: %{public}s is invalid json.", field.c_str());
891 return false;
892 }
893 napi_value jsProNameList = nullptr;
894 uint32_t jsProCount = 0;
895 napi_get_property_names(env, jsonField, &jsProNameList);
896 napi_get_array_length(env, jsProNameList, &jsProCount);
897 if (!PraseJson(env, jsonField, jsProNameList, jsProCount, jsonObj)) {
898 HILOGE("PraseJson failed.");
899 return false;
900 }
901 return true;
902 }
903
PraseJson(const napi_env & env,const napi_value & jsonField,const napi_value & jsProNameList,uint32_t jsProCount,nlohmann::json & jsonObj)904 bool JsContinuationManager::PraseJson(const napi_env &env, const napi_value& jsonField,
905 const napi_value& jsProNameList, uint32_t jsProCount, nlohmann::json& jsonObj)
906 {
907 napi_value jsProName = nullptr;
908 napi_value jsProValue = nullptr;
909 napi_valuetype jsValueType = napi_undefined;
910 if (jsProCount > MAX_JSPROCOUNT) {
911 HILOGE("value of jsProCount is larger than MAX_JSPROCOUNT");
912 return false;
913 }
914 for (uint32_t index = 0; index < jsProCount; index++) {
915 napi_get_element(env, jsProNameList, index, &jsProName);
916 std::string strProName = UnwrapStringFromJS(env, jsProName);
917 napi_get_named_property(env, jsonField, strProName.c_str(), &jsProValue);
918 napi_typeof(env, jsProValue, &jsValueType);
919 switch (jsValueType) {
920 case napi_string: {
921 std::string elementValue = UnwrapStringFromJS(env, jsProValue);
922 HILOGI("Property name=%{public}s, string, value=%{public}s", strProName.c_str(), elementValue.c_str());
923 jsonObj[strProName] = elementValue;
924 break;
925 }
926 case napi_boolean: {
927 bool elementValue = false;
928 napi_get_value_bool(env, jsProValue, &elementValue);
929 HILOGI("Property name=%{public}s, boolean, value=%{public}d.", strProName.c_str(), elementValue);
930 jsonObj[strProName] = elementValue;
931 break;
932 }
933 case napi_number: {
934 int32_t elementValue = 0;
935 if (napi_get_value_int32(env, jsProValue, &elementValue) != napi_ok) {
936 HILOGE("Property name=%{public}s, Property int32_t parse error", strProName.c_str());
937 } else {
938 HILOGI("Property name=%{public}s, number, value=%{public}d.", strProName.c_str(), elementValue);
939 jsonObj[strProName] = elementValue;
940 }
941 break;
942 }
943 default: {
944 HILOGE("Property name=%{public}s, value type not support.", strProName.c_str());
945 break;
946 }
947 }
948 }
949 return true;
950 }
951
ErrorCodeReturn(int32_t code)952 int32_t JsContinuationManager::ErrorCodeReturn(int32_t code)
953 {
954 switch (code) {
955 case DMS_PERMISSION_DENIED:
956 return PERMISSION_DENIED;
957 case ERR_NULL_OBJECT:
958 return SYSTEM_WORK_ABNORMALLY;
959 case ERR_FLATTEN_OBJECT:
960 return SYSTEM_WORK_ABNORMALLY;
961 case CONNECT_ABILITY_FAILED:
962 return SYSTEM_WORK_ABNORMALLY;
963 case INVALID_CONTINUATION_MODE:
964 return PARAMETER_CHECK_FAILED;
965 case UNKNOWN_CALLBACK_TYPE:
966 return PARAMETER_CHECK_FAILED;
967 case INVALID_CONNECT_STATUS:
968 return PARAMETER_CHECK_FAILED;
969 case CALLBACK_HAS_NOT_REGISTERED:
970 return CALLBACK_TOKEN_UNREGISTERED;
971 case TOKEN_HAS_NOT_REGISTERED:
972 return CALLBACK_TOKEN_UNREGISTERED;
973 case REGISTER_EXCEED_MAX_TIMES:
974 return OVER_MAX_REGISTERED_TIMES;
975 case CALLBACK_HAS_REGISTERED:
976 return REPEATED_REGISTRATION;
977 default:
978 return SYSTEM_WORK_ABNORMALLY;
979 };
980 }
981
ErrorMessageReturn(int32_t code)982 std::string JsContinuationManager::ErrorMessageReturn(int32_t code)
983 {
984 switch (code) {
985 case PARAMETER_CHECK_FAILED:
986 return "The parameter check failed.";
987 case SYSTEM_WORK_ABNORMALLY:
988 return "The system ability works abnormally.";
989 case CALLBACK_TOKEN_UNREGISTERED:
990 return "The specified token or callback is not registered.";
991 case OVER_MAX_REGISTERED_TIMES:
992 return "The number of token registration times has reached the upper limit.";
993 case REPEATED_REGISTRATION:
994 return "The specified callback has been registered.";
995 default:
996 return "The system ability works abnormally.";
997 };
998 }
999
GenerateBusinessError(const napi_env & env,int32_t errCode,const std::string & errMsg)1000 napi_value JsContinuationManager::GenerateBusinessError(const napi_env &env, int32_t errCode, const std::string &errMsg)
1001 {
1002 napi_value code = nullptr;
1003 napi_create_int32(env, errCode, &code);
1004 napi_value message = nullptr;
1005 napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
1006 napi_value businessError = nullptr;
1007 napi_create_error(env, nullptr, message, &businessError);
1008 napi_set_named_property(env, businessError, CODE_KEY_NAME.c_str(), code);
1009 return businessError;
1010 }
1011
JsContinuationManagerInit(napi_env env,napi_value exportObj)1012 napi_value JsContinuationManagerInit(napi_env env, napi_value exportObj)
1013 {
1014 HILOGD("called.");
1015 if (env == nullptr || exportObj == nullptr) {
1016 HILOGE("Invalid input parameters");
1017 return nullptr;
1018 }
1019
1020 JsContinuationManager* jsContinuationManager = new JsContinuationManager();
1021 if (napi_wrap(env, exportObj, jsContinuationManager, JsContinuationManager::Finalizer, nullptr, nullptr)
1022 != napi_ok) {
1023 JsContinuationManager::Finalizer(env, jsContinuationManager, nullptr);
1024 jsContinuationManager = nullptr;
1025 return nullptr;
1026 }
1027
1028 const char *moduleName = "JsContinuationManager";
1029 BindNativeFunction(env, exportObj, "register", moduleName, JsContinuationManager::Register);
1030 BindNativeFunction(env, exportObj, "unregister", moduleName, JsContinuationManager::Unregister);
1031 BindNativeFunction(env, exportObj, "on", moduleName, JsContinuationManager::RegisterDeviceSelectionCallback);
1032 BindNativeFunction(env, exportObj, "off", moduleName, JsContinuationManager::UnregisterDeviceSelectionCallback);
1033 BindNativeFunction(env, exportObj, "updateConnectStatus", moduleName, JsContinuationManager::UpdateConnectStatus);
1034 BindNativeFunction(env, exportObj, "startDeviceManager", moduleName, JsContinuationManager::StartDeviceManager);
1035 BindNativeProperty(env, exportObj, "DeviceConnectState", JsContinuationManager::InitDeviceConnectStateObject);
1036 BindNativeProperty(env, exportObj, "ContinuationMode", JsContinuationManager::InitContinuationModeObject);
1037 BindNativeFunction(env, exportObj, "registerContinuation", moduleName,
1038 JsContinuationManager::RegisterContinuation);
1039 BindNativeFunction(env, exportObj, "unregisterContinuation", moduleName,
1040 JsContinuationManager::UnregisterContinuation);
1041 BindNativeFunction(env, exportObj, "updateContinuationState", moduleName,
1042 JsContinuationManager::UpdateContinuationState);
1043 BindNativeFunction(env, exportObj, "startContinuationDeviceManager", moduleName,
1044 JsContinuationManager::StartContinuationDeviceManager);
1045
1046 return CreateJsUndefined(env);
1047 }
1048 } // namespace DistributedSchedule
1049 } // namespace OHOS