• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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