• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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     napi_value lastParam = (argc == ARG_COUNT_ONE) ? nullptr : argv[ARG_COUNT_ONE];
319     napi_value result = nullptr;
320     std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
321     auto asyncTask = [this, token, env, task = napiAsyncTask.get()]() {
322         if (task == nullptr) {
323             return;
324         }
325         napi_handle_scope scope = nullptr;
326         napi_open_handle_scope(env, &scope);
327         if (scope == nullptr) {
328             delete task;
329             return;
330         }
331         int32_t errCode = DistributedAbilityManagerClient::GetInstance().Unregister(token);
332         if (errCode == ERR_OK) {
333             task->Resolve(env, CreateJsNull(env));
334         } else {
335             errCode = ErrorCodeReturn(errCode);
336             task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
337         }
338         napi_close_handle_scope(env, scope);
339         delete task;
340     };
341     if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
342         napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
343     } else {
344         napiAsyncTask.release();
345     }
346     return result;
347 }
348 
OnRegisterDeviceSelectionCallbackParameterCheck(napi_env env,napi_callback_info info,std::string & cbType,int32_t & token,napi_value * jsListenerObj)349 std::string JsContinuationManager::OnRegisterDeviceSelectionCallbackParameterCheck(napi_env env,
350     napi_callback_info info, std::string &cbType, int32_t &token, napi_value *jsListenerObj)
351 {
352     size_t argc = ARG_COUNT_THREE;
353     napi_value argv[ARG_COUNT_THREE] = { 0 };
354     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
355     if (argc != ARG_COUNT_THREE) {
356         return "Parameter error. The type of \"number of parameters\" must be 3";
357     }
358     if (!ConvertFromJsValue(env, argv[0], cbType)) {
359         return "Parameter error. The type of \"type\" must be string";
360     }
361     if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
362         return "Parameter error. The type of \"type\" must be " +
363             std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
364     }
365     if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], token)) {
366         return "Parameter error. The type of \"token\" must be number";
367     }
368     *jsListenerObj = argv[ARG_COUNT_TWO];
369     if (!IsCallbackValid(env, *jsListenerObj)) {
370         return "Parameter error. The type of \"callback\" must be Callback<Array<ContinuationResult>>";
371     }
372     return std::string();
373 }
374 
OnRegisterDeviceSelectionCallback(napi_env env,napi_callback_info info)375 napi_value JsContinuationManager::OnRegisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
376 {
377     HILOGD("called.");
378     std::string cbType;
379     int32_t token = -1;
380     int32_t errCode = PARAMETER_CHECK_FAILED;
381     napi_value jsListenerObj = nullptr;
382     std::string errInfo = OnRegisterDeviceSelectionCallbackParameterCheck(env, info, cbType, token, &jsListenerObj);
383     if (errInfo.empty()) {
384         errInfo = [this, &env, &info, &cbType, &token, &jsListenerObj, &errCode]() -> std::string {
385             std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
386             if (IsCallbackRegistered(token, cbType)) {
387                 errCode = REPEATED_REGISTRATION;
388                 return ErrorMessageReturn(errCode);
389             }
390             napi_ref tempRef = nullptr;
391             napi_create_reference(env, jsListenerObj, 1, &tempRef);
392             std::unique_ptr<NativeReference> callbackRef;
393             callbackRef.reset(reinterpret_cast<NativeReference*>(tempRef));
394             sptr<JsDeviceSelectionListener> deviceSelectionListener(new JsDeviceSelectionListener(env));
395             if (deviceSelectionListener == nullptr) {
396                 HILOGE("deviceSelectionListener is nullptr!");
397                 errCode = SYSTEM_WORK_ABNORMALLY;
398                 return ErrorMessageReturn(errCode);
399             }
400             errCode = DistributedAbilityManagerClient::GetInstance().RegisterDeviceSelectionCallback(
401                 token, cbType, deviceSelectionListener);
402             if (errCode == ERR_OK) {
403                 deviceSelectionListener->AddCallback(cbType, jsListenerObj);
404                 CallbackPair callbackPair = std::make_pair(std::move(callbackRef), deviceSelectionListener);
405                 jsCbMap_[token][cbType] = std::move(callbackPair); // move assignment
406                 HILOGI("RegisterDeviceSelectionListener success");
407             } else {
408                 deviceSelectionListener = nullptr;
409                 errCode = ErrorCodeReturn(errCode);
410                 return ErrorMessageReturn(errCode);
411             }
412             return std::string();
413         }();
414     }
415     if (!errInfo.empty()) {
416         HILOGE("%{public}s", errInfo.c_str());
417         napi_throw(env,
418             GenerateBusinessError(env, errCode, errInfo));
419     }
420     return CreateJsUndefined(env);
421 }
422 
OnUnregisterDeviceSelectionCallback(napi_env env,napi_callback_info info)423 napi_value JsContinuationManager::OnUnregisterDeviceSelectionCallback(napi_env env, napi_callback_info info)
424 {
425     HILOGD("called.");
426     std::string cbType;
427     int32_t token = -1;
428     int32_t errCode = PARAMETER_CHECK_FAILED;
429     std::string errInfo = [this, &env, &info, &cbType, &token, &errCode]() -> std::string {
430         size_t argc = ARG_COUNT_TWO;
431         napi_value argv[ARG_COUNT_TWO] = { 0 };
432         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
433         if (argc != ARG_COUNT_TWO) {
434             return "Parameter error. The type of \"number of parameters\" must be 2";
435         }
436         if (!ConvertFromJsValue(env, argv[0], cbType)) {
437             return "Parameter error. The type of \"type\" must be string";
438         }
439         if (cbType != EVENT_CONNECT && cbType != EVENT_DISCONNECT) {
440             return "Parameter error. The type of \"type\" must be " +
441                 std::string(EVENT_CONNECT) + " or " + std::string(EVENT_DISCONNECT);
442         }
443         if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], token)) {
444             return "Parameter error. The type of \"token\" must be number";
445         }
446         {
447             std::lock_guard<std::mutex> jsCbMapLock(jsCbMapMutex_);
448             if (!IsCallbackRegistered(token, cbType)) {
449                 errCode = CALLBACK_TOKEN_UNREGISTERED;
450                 return ErrorMessageReturn(errCode);
451             }
452             errCode = DistributedAbilityManagerClient::GetInstance().UnregisterDeviceSelectionCallback(token, cbType);
453             if (errCode == ERR_OK) {
454                 CallbackPair& callbackPair = jsCbMap_[token][cbType];
455                 callbackPair.second->RemoveCallback(cbType);
456                 jsCbMap_[token].erase(cbType);
457                 if (jsCbMap_[token].empty()) {
458                     jsCbMap_.erase(token);
459                 }
460                 HILOGI("UnregisterDeviceSelectionCallback success");
461             } else {
462                 errCode = ErrorCodeReturn(errCode);
463                 return ErrorMessageReturn(errCode);
464             }
465         }
466         return std::string();
467     } ();
468     if (!errInfo.empty()) {
469         HILOGE("%{public}s", errInfo.c_str());
470         napi_throw(env, GenerateBusinessError(env, errCode, errInfo));
471     }
472     return CreateJsUndefined(env);
473 }
474 
GetInfoForUpdateConnectStatus(napi_env env,napi_value * argv,int32_t & token,std::string & deviceId,DeviceConnectStatus & deviceConnectStatus)475 int32_t JsContinuationManager::GetInfoForUpdateConnectStatus(napi_env env,
476     napi_value *argv, int32_t &token, std::string &deviceId, DeviceConnectStatus &deviceConnectStatus)
477 {
478     int32_t errCode = 0;
479     if (!errCode && !ConvertFromJsValue(env, argv[0], token)) {
480         HILOGE("Parse token failed");
481         errCode = ERR_NOT_OK;
482     }
483     if (!errCode && !ConvertFromJsValue(env, argv[ARG_COUNT_ONE], deviceId)) {
484         HILOGE("Parse deviceId failed");
485         errCode = ERR_NOT_OK;
486     }
487     if (!errCode && !ConvertFromJsValue(env, argv[ARG_COUNT_TWO], deviceConnectStatus)) {
488         HILOGE("Parse device connect status failed");
489         errCode = ERR_NOT_OK;
490     }
491     return errCode;
492 }
493 
OnUpdateConnectStatus(napi_env env,napi_callback_info info)494 napi_value JsContinuationManager::OnUpdateConnectStatus(napi_env env, napi_callback_info info)
495 {
496     HILOGD("called.");
497     int32_t errCode = 0;
498     size_t argc = ARG_COUNT_FOUR;
499     napi_value argv[ARG_COUNT_FOUR] = { 0 };
500     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
501     if (argc < ARG_COUNT_THREE) {
502         HILOGE("Params not match");
503         errCode = ERR_NOT_OK;
504     }
505     int32_t token = -1;
506     std::string deviceId;
507     DeviceConnectStatus deviceConnectStatus = DeviceConnectStatus::IDLE;
508     errCode = GetInfoForUpdateConnectStatus(env, argv, token, deviceId, deviceConnectStatus);
509     NapiAsyncTask::CompleteCallback complete =
510         [token, deviceId, deviceConnectStatus, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
511         napi_handle_scope scope = nullptr;
512         napi_open_handle_scope(env, &scope);
513         if (scope == nullptr) {
514             return;
515         }
516 
517         if (errCode != 0) {
518             task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
519             napi_close_handle_scope(env, scope);
520             return;
521         }
522         int32_t ret = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
523             token, deviceId, deviceConnectStatus);
524         if (ret == ERR_OK) {
525             task.Resolve(env, CreateJsUndefined(env));
526         } else {
527             task.Reject(env, CreateJsError(env, ret, "UpdateConnectStatus failed."));
528         }
529         napi_close_handle_scope(env, scope);
530     };
531 
532     napi_value lastParam = (argc <= ARG_COUNT_THREE) ? nullptr : argv[ARG_COUNT_THREE];
533     napi_value result = nullptr;
534     NapiAsyncTask::Schedule("JsContinuationManager::OnUpdateConnectStatus",
535         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
536     return result;
537 }
538 
GetErrorInfo(napi_env env,napi_callback_info info,int32_t & token,std::string & deviceId,DeviceConnectStatus & deviceConnectStatus)539 std::string JsContinuationManager::GetErrorInfo(napi_env env, napi_callback_info info, int32_t &token,
540                                                 std::string &deviceId, DeviceConnectStatus &deviceConnectStatus)
541 {
542     size_t argc = ARG_COUNT_FOUR;
543     napi_value argv[ARG_COUNT_FOUR] = { nullptr };
544     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr));
545     if (argc != ARG_COUNT_THREE && argc != ARG_COUNT_FOUR) {
546         return "Parameter error. The type of \"number of parameters\" must be 3 or 4";
547     }
548     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
549     if (!ConvertFromJsValue(env, argv[0], token)) {
550         return "Parameter error. The type of \"token\" must be number";
551     }
552     if (!ConvertFromJsValue(env, argv[ARG_COUNT_ONE], deviceId) || deviceId.empty()) {
553         return "Parameter error. The type of \"deviceId\" must be string and not empty";
554     }
555     deviceConnectStatus = DeviceConnectStatus::IDLE;
556     if (!ConvertFromJsValue(env, argv[ARG_COUNT_TWO], deviceConnectStatus)) {
557         return "Parameter error. The type of \"status\" must be DeviceConnectState";
558     }
559     if (static_cast<int32_t>(deviceConnectStatus) < static_cast<int32_t>(DeviceConnectStatus::IDLE) ||
560         static_cast<int32_t>(deviceConnectStatus) > static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)) {
561         HILOGE("deviceConnectStatus is invalid");
562         return "Parameter error. The type of \"status\" must be DeviceConnectState";
563     }
564     return std::string();
565 }
566 
OnUpdateContinuationState(napi_env env,napi_callback_info info)567 napi_value JsContinuationManager::OnUpdateContinuationState(napi_env env, napi_callback_info info)
568 {
569     HILOGD("called.");
570     int32_t token = -1;
571     std::string deviceId;
572     DeviceConnectStatus deviceConnectStatus;
573     std::string errInfo = GetErrorInfo(env, info, token, deviceId, deviceConnectStatus);
574     if (!errInfo.empty()) {
575         HILOGE("%{public}s", errInfo.c_str());
576         napi_throw(env,
577             GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
578         return CreateJsUndefined(env);
579     }
580     size_t argc = ARG_COUNT_FOUR;
581     napi_value argv[ARG_COUNT_FOUR] = { 0 };
582     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
583     napi_value lastParam = (argc == ARG_COUNT_THREE) ? nullptr : argv[ARG_COUNT_THREE];
584     napi_value result = nullptr;
585     std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
586     auto asyncTask = [this, token, deviceId, deviceConnectStatus, env, task = napiAsyncTask.get()]() {
587         if (task == nullptr) {
588             return;
589         }
590         napi_handle_scope scope = nullptr;
591         napi_open_handle_scope(env, &scope);
592         if (scope == nullptr) {
593             delete task;
594             return;
595         }
596         int32_t errCode = DistributedAbilityManagerClient::GetInstance().UpdateConnectStatus(
597             token, deviceId, deviceConnectStatus);
598         if (errCode == ERR_OK) {
599             task->Resolve(env, CreateJsNull(env));
600         } else {
601             errCode = ErrorCodeReturn(errCode);
602             task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
603         }
604 
605         napi_close_handle_scope(env, scope);
606         delete task;
607     };
608     if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
609         napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
610     } else {
611         napiAsyncTask.release();
612     }
613     return result;
614 }
615 
CheckParamAndGetToken(napi_env env,size_t argc,napi_value * argv,int32_t & token)616 int32_t JsContinuationManager::CheckParamAndGetToken(napi_env env, size_t argc, napi_value *argv, int32_t &token)
617 {
618     int32_t errCode = 0;
619     if (argc < ARG_COUNT_ONE) {
620         HILOGE("Params not match");
621         errCode = ERR_NOT_OK;
622     }
623     if (!errCode && !ConvertFromJsValue(env, argv[0], token)) {
624         HILOGE("Parse token failed");
625         errCode = ERR_NOT_OK;
626     }
627     return errCode;
628 }
629 
OnStartDeviceManager(napi_env env,napi_callback_info info)630 napi_value JsContinuationManager::OnStartDeviceManager(napi_env env, napi_callback_info info)
631 {
632     HILOGD("called.");
633     int32_t token = -1;
634     size_t argc = ARG_COUNT_THREE;
635     napi_value argv[ARG_COUNT_THREE] = { 0 };
636     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
637     int32_t errCode = CheckParamAndGetToken(env, argc, argv, token);
638     size_t unwrapArgc = ARG_COUNT_ONE;
639     std::shared_ptr<ContinuationExtraParams> continuationExtraParams = std::make_shared<ContinuationExtraParams>();
640     napi_valuetype valuetype = napi_valuetype::napi_undefined;
641     if (argc > ARG_COUNT_ONE) {
642         NAPI_CALL(env, napi_typeof(env, argv[ARG_COUNT_ONE], &valuetype));
643     }
644     if (valuetype == napi_valuetype::napi_object) {
645         HILOGI("startDeviceManager options is used.");
646         if (!UnWrapContinuationExtraParams(env, argv[ARG_COUNT_ONE], continuationExtraParams)) {
647             HILOGE("Parse continuationExtraParams failed");
648             errCode = ERR_NOT_OK;
649         }
650         unwrapArgc++;
651     }
652     NapiAsyncTask::CompleteCallback complete =
653         [token, continuationExtraParams, unwrapArgc, errCode](napi_env env, NapiAsyncTask &task, int32_t status) {
654         napi_handle_scope scope = nullptr;
655         napi_open_handle_scope(env, &scope);
656         if (scope == nullptr) {
657             return;
658         }
659 
660         if (errCode != 0) {
661             task.Reject(env, CreateJsError(env, errCode, "Invalidate params."));
662             napi_close_handle_scope(env, scope);
663             return;
664         }
665         int32_t ret = (unwrapArgc == ARG_COUNT_ONE) ?
666             DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, nullptr) :
667             DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
668         if (ret == ERR_OK) {
669             task.Resolve(env, CreateJsUndefined(env));
670         } else {
671             task.Reject(env, CreateJsError(env, ret, "StartDeviceManager failed."));
672         }
673 
674         napi_close_handle_scope(env, scope);
675     };
676 
677     napi_value lastParam = (argc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
678     napi_value result = nullptr;
679     NapiAsyncTask::Schedule("JsContinuationManager::OnStartDeviceManager",
680         env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
681     return result;
682 }
683 
GetErrorForStartContinuation(napi_env env,napi_callback_info info,int32_t & token,int32_t & unwrapArgc,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)684 std::string JsContinuationManager::GetErrorForStartContinuation(napi_env env, napi_callback_info info,
685     int32_t &token, int32_t &unwrapArgc, std::shared_ptr<ContinuationExtraParams> &continuationExtraParams)
686 {
687     size_t argc = ARG_COUNT_THREE;
688     napi_value argv[ARG_COUNT_THREE] = { 0 };
689     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
690     if (argc < ARG_COUNT_ONE || argc > ARG_COUNT_THREE) {
691         return "Parameter error. The type of \"number of parameters\" must be greater than 1 and less than 3";
692     }
693     if (!ConvertFromJsValue(env, argv[0], token)) {
694         return "Parameter error. The type of \"token\" must be number";
695     }
696     continuationExtraParams = std::make_shared<ContinuationExtraParams>();
697     napi_valuetype valuetype = napi_valuetype::napi_undefined;
698     if (argc > ARG_COUNT_ONE) {
699         NAPI_CALL(env, napi_typeof(env, argv[ARG_COUNT_ONE], &valuetype));
700     }
701     if (valuetype == napi_valuetype::napi_object) {
702         HILOGI("StartContinuationDeviceManager options is used.");
703         if (!UnWrapContinuationExtraParams(env, argv[ARG_COUNT_ONE], continuationExtraParams)) {
704             return "Parameter error. The type of \"options\" must be ContinuationExtraParams";
705         }
706         unwrapArgc++;
707     }
708     return std::string();
709 }
710 
OnStartContinuationDeviceManager(napi_env env,napi_callback_info info)711 napi_value JsContinuationManager::OnStartContinuationDeviceManager(napi_env env, napi_callback_info info)
712 {
713     HILOGD("called.");
714     int32_t token = -1;
715     int32_t argc = ARG_COUNT_ONE;
716     std::shared_ptr<ContinuationExtraParams> continuationExtraParams;
717     std::string errInfo = GetErrorForStartContinuation(env, info, token, argc, continuationExtraParams);
718     if (!errInfo.empty()) {
719         HILOGE("%{public}s", errInfo.c_str());
720         napi_throw(env,
721             GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
722         return CreateJsUndefined(env);
723     }
724     size_t unwrapArgc = argc;
725     size_t napiArgc = ARG_COUNT_THREE;
726     napi_value argv[ARG_COUNT_THREE] = { 0 };
727     NAPI_CALL(env, napi_get_cb_info(env, info, &napiArgc, argv, nullptr, nullptr));
728     napi_value lastParam = (napiArgc <= unwrapArgc) ? nullptr : argv[unwrapArgc];
729     napi_value result = nullptr;
730     std::unique_ptr<NapiAsyncTask> napiAsyncTask = CreateEmptyAsyncTask(env, lastParam, &result);
731     auto asyncTask = [this, token, continuationExtraParams, unwrapArgc, env, task = napiAsyncTask.get()]() {
732         if (task == nullptr) {
733             return;
734         }
735         napi_handle_scope scope = nullptr;
736         napi_open_handle_scope(env, &scope);
737         if (scope == nullptr) {
738             delete task;
739             return;
740         }
741         int32_t errCode = (unwrapArgc == ARG_COUNT_ONE) ?
742             DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, nullptr) :
743             DistributedAbilityManagerClient::GetInstance().StartDeviceManager(token, continuationExtraParams);
744         if (errCode == ERR_OK) {
745             task->Resolve(env, CreateJsNull(env));
746         } else {
747             errCode = ErrorCodeReturn(errCode);
748             task->Reject(env, CreateJsError(env, errCode, ErrorMessageReturn(errCode)));
749         }
750         napi_close_handle_scope(env, scope);
751         delete task;
752     };
753     if (napi_status::napi_ok != napi_send_event(env, asyncTask, napi_eprio_high)) {
754         napiAsyncTask->Reject(env, CreateJsError(env, ERROR_CODE_ONE, "send event failed"));
755     } else {
756         napiAsyncTask.release();
757     }
758     return result;
759 }
760 
OnInitDeviceConnectStateObject(napi_env env,napi_callback_info info)761 napi_value JsContinuationManager::OnInitDeviceConnectStateObject(napi_env env, napi_callback_info info)
762 {
763     napi_value object;
764     NAPI_CALL(env, napi_create_object(env, &object));
765 
766     NAPI_CALL(env, SetEnumItem(env, object, "IDLE",
767         static_cast<int32_t>(DeviceConnectStatus::IDLE)));
768     NAPI_CALL(env, SetEnumItem(env, object, "CONNECTING",
769         static_cast<int32_t>(DeviceConnectStatus::CONNECTING)));
770     NAPI_CALL(env, SetEnumItem(env, object, "CONNECTED",
771         static_cast<int32_t>(DeviceConnectStatus::CONNECTED)));
772     NAPI_CALL(env, SetEnumItem(env, object, "DISCONNECTING",
773         static_cast<int32_t>(DeviceConnectStatus::DISCONNECTING)));
774 
775     return object;
776 }
777 
OnInitContinuationModeObject(napi_env env,napi_callback_info info)778 napi_value JsContinuationManager::OnInitContinuationModeObject(napi_env env, napi_callback_info info)
779 {
780     napi_value object;
781     NAPI_CALL(env, napi_create_object(env, &object));
782 
783     NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_SINGLE",
784         static_cast<int32_t>(ContinuationMode::COLLABORATION_SINGLE)));
785     NAPI_CALL(env, SetEnumItem(env, object, "COLLABORATION_MULTIPLE",
786         static_cast<int32_t>(ContinuationMode::COLLABORATION_MUTIPLE)));
787 
788     return object;
789 }
790 
SetEnumItem(const napi_env & env,napi_value object,const char * name,int32_t value)791 napi_status JsContinuationManager::SetEnumItem(const napi_env &env, napi_value object, const char* name, int32_t value)
792 {
793     napi_status status;
794     napi_value itemName;
795     napi_value itemValue;
796 
797     NAPI_CALL_BASE(env, status = napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName), status);
798     NAPI_CALL_BASE(env, status = napi_create_int32(env, value, &itemValue), status);
799     NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemName, itemValue), status);
800     NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemValue, itemName), status);
801 
802     return napi_ok;
803 }
804 
IsCallbackValid(napi_env env,napi_value listenerObj)805 bool JsContinuationManager::IsCallbackValid(napi_env env, napi_value listenerObj)
806 {
807     if (listenerObj == nullptr) {
808         HILOGE("listenerObj is nullptr");
809         return false;
810     }
811     bool isCallable = false;
812     napi_is_callable(env, listenerObj, &isCallable);
813     return isCallable;
814 }
815 
IsCallbackRegistered(int32_t token,const std::string & cbType)816 bool JsContinuationManager::IsCallbackRegistered(int32_t token, const std::string& cbType)
817 {
818     if (jsCbMap_.empty() || jsCbMap_.find(token) == jsCbMap_.end()) {
819         HILOGE("token %{public}s not registered callback!", GetAnonymStr(std::to_string(token)).c_str());
820         return false;
821     }
822     if (jsCbMap_[token].empty() || jsCbMap_[token].find(cbType) == jsCbMap_[token].end()) {
823         HILOGE("cbType %{public}s not registered callback!", cbType.c_str());
824         return false;
825     }
826     HILOGI("callback already registered, token: %{public}s, cbType %{public}s",
827         GetAnonymStr(std::to_string(token)).c_str(), cbType.c_str());
828     return true;
829 }
830 
UnWrapContinuationExtraParams(const napi_env & env,const napi_value & options,std::shared_ptr<ContinuationExtraParams> & continuationExtraParams)831 bool JsContinuationManager::UnWrapContinuationExtraParams(const napi_env &env, const napi_value& options,
832     std::shared_ptr<ContinuationExtraParams>& continuationExtraParams)
833 {
834     HILOGD("called.");
835     if (!IsTypeForNapiValue(env, options, napi_object)) {
836         HILOGE("options is invalid.");
837         return false;
838     }
839     if (!continuationExtraParams) {
840         HILOGE("continuationExtraParams is nullptr.");
841         return false;
842     }
843     std::vector<std::string> deviceTypes;
844     if (UnwrapStringArrayByPropertyName(env, options, "deviceType", deviceTypes)) {
845         continuationExtraParams->SetDeviceType(deviceTypes);
846     }
847     std::string targetBundle("");
848     if (UnwrapStringByPropertyName(env, options, "targetBundle", targetBundle)) {
849         continuationExtraParams->SetTargetBundle(targetBundle);
850     }
851     std::string description("");
852     if (UnwrapStringByPropertyName(env, options, "description", description)) {
853         continuationExtraParams->SetDescription(description);
854     }
855     nlohmann::json filter;
856     if (!UnwrapJsonByPropertyName(env, options, "filter", filter)) {
857         return false;
858     }
859     if (!filter.empty()) {
860         continuationExtraParams->SetFilter(filter.dump());
861     }
862     int32_t continuationMode = 0;
863     if (UnwrapInt32ByPropertyName(env, options, "continuationMode", continuationMode)) {
864         continuationExtraParams->SetContinuationMode(static_cast<ContinuationMode>(continuationMode));
865     }
866     nlohmann::json authInfo;
867     if (UnwrapJsonByPropertyName(env, options, "authInfo", authInfo)) {
868         if (!authInfo.empty()) {
869             continuationExtraParams->SetAuthInfo(authInfo.dump());
870         }
871     }
872     return true;
873 }
874 
UnwrapJsonByPropertyName(const napi_env & env,const napi_value & param,const std::string & field,nlohmann::json & jsonObj)875 bool JsContinuationManager::UnwrapJsonByPropertyName(const napi_env &env, const napi_value& param,
876     const std::string& field, nlohmann::json& jsonObj)
877 {
878     HILOGD("called.");
879     if (!IsTypeForNapiValue(env, param, napi_object)) {
880         HILOGE("param is invalid.");
881         return false;
882     }
883     napi_value jsonField = nullptr;
884     napi_get_named_property(env, param, field.c_str(), &jsonField);
885     napi_valuetype jsonFieldType = napi_undefined;
886     napi_typeof(env, jsonField, &jsonFieldType);
887     if (jsonFieldType != napi_object && jsonFieldType != napi_undefined) {
888         HILOGE("field: %{public}s is invalid json.", field.c_str());
889         return false;
890     }
891     napi_value jsProNameList = nullptr;
892     uint32_t jsProCount = 0;
893     napi_get_property_names(env, jsonField, &jsProNameList);
894     napi_get_array_length(env, jsProNameList, &jsProCount);
895     if (!PraseJson(env, jsonField, jsProNameList, jsProCount, jsonObj)) {
896         HILOGE("PraseJson failed.");
897         return false;
898     }
899     return true;
900 }
901 
PraseJson(const napi_env & env,const napi_value & jsonField,const napi_value & jsProNameList,uint32_t jsProCount,nlohmann::json & jsonObj)902 bool JsContinuationManager::PraseJson(const napi_env &env, const napi_value& jsonField,
903     const napi_value& jsProNameList, uint32_t jsProCount, nlohmann::json& jsonObj)
904 {
905     napi_value jsProName = nullptr;
906     napi_value jsProValue = nullptr;
907     napi_valuetype jsValueType = napi_undefined;
908     if (jsProCount > MAX_JSPROCOUNT) {
909         HILOGE("value of jsProCount is larger than MAX_JSPROCOUNT");
910         return false;
911     }
912     for (uint32_t index = 0; index < jsProCount; index++) {
913         napi_get_element(env, jsProNameList, index, &jsProName);
914         std::string strProName = UnwrapStringFromJS(env, jsProName);
915         napi_get_named_property(env, jsonField, strProName.c_str(), &jsProValue);
916         napi_typeof(env, jsProValue, &jsValueType);
917         switch (jsValueType) {
918             case napi_string: {
919                 std::string elementValue = UnwrapStringFromJS(env, jsProValue);
920                 HILOGI("Property name=%{public}s, string, value=%{public}s", strProName.c_str(), elementValue.c_str());
921                 jsonObj[strProName] = elementValue;
922                 break;
923             }
924             case napi_boolean: {
925                 bool elementValue = false;
926                 napi_get_value_bool(env, jsProValue, &elementValue);
927                 HILOGI("Property name=%{public}s, boolean, value=%{public}d.", strProName.c_str(), elementValue);
928                 jsonObj[strProName] = elementValue;
929                 break;
930             }
931             case napi_number: {
932                 int32_t elementValue = 0;
933                 if (napi_get_value_int32(env, jsProValue, &elementValue) != napi_ok) {
934                     HILOGE("Property name=%{public}s, Property int32_t parse error", strProName.c_str());
935                 } else {
936                     HILOGI("Property name=%{public}s, number, value=%{public}d.", strProName.c_str(), elementValue);
937                     jsonObj[strProName] = elementValue;
938                 }
939                 break;
940             }
941             default: {
942                 HILOGE("Property name=%{public}s, value type not support.", strProName.c_str());
943                 break;
944             }
945         }
946     }
947     return true;
948 }
949 
ErrorCodeReturn(int32_t code)950 int32_t JsContinuationManager::ErrorCodeReturn(int32_t code)
951 {
952     switch (code) {
953         case DMS_PERMISSION_DENIED:
954             return PERMISSION_DENIED;
955         case ERR_NULL_OBJECT:
956             return SYSTEM_WORK_ABNORMALLY;
957         case ERR_FLATTEN_OBJECT:
958             return SYSTEM_WORK_ABNORMALLY;
959         case CONNECT_ABILITY_FAILED:
960             return SYSTEM_WORK_ABNORMALLY;
961         case INVALID_CONTINUATION_MODE:
962             return PARAMETER_CHECK_FAILED;
963         case UNKNOWN_CALLBACK_TYPE:
964             return PARAMETER_CHECK_FAILED;
965         case INVALID_CONNECT_STATUS:
966             return PARAMETER_CHECK_FAILED;
967         case CALLBACK_HAS_NOT_REGISTERED:
968             return CALLBACK_TOKEN_UNREGISTERED;
969         case TOKEN_HAS_NOT_REGISTERED:
970             return CALLBACK_TOKEN_UNREGISTERED;
971         case REGISTER_EXCEED_MAX_TIMES:
972             return OVER_MAX_REGISTERED_TIMES;
973         case CALLBACK_HAS_REGISTERED:
974             return REPEATED_REGISTRATION;
975         default:
976             return SYSTEM_WORK_ABNORMALLY;
977     };
978 }
979 
ErrorMessageReturn(int32_t code)980 std::string JsContinuationManager::ErrorMessageReturn(int32_t code)
981 {
982     switch (code) {
983         case PARAMETER_CHECK_FAILED:
984             return "The parameter check failed.";
985         case SYSTEM_WORK_ABNORMALLY:
986             return "The system ability works abnormally.";
987         case CALLBACK_TOKEN_UNREGISTERED:
988             return "The specified token or callback is not registered.";
989         case OVER_MAX_REGISTERED_TIMES:
990             return "The number of token registration times has reached the upper limit.";
991         case REPEATED_REGISTRATION:
992             return "The specified callback has been registered.";
993         default:
994             return "The system ability works abnormally.";
995     };
996 }
997 
GenerateBusinessError(const napi_env & env,int32_t errCode,const std::string & errMsg)998 napi_value JsContinuationManager::GenerateBusinessError(const napi_env &env, int32_t errCode, const std::string &errMsg)
999 {
1000     napi_value code = nullptr;
1001     napi_create_int32(env, errCode, &code);
1002     napi_value message = nullptr;
1003     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
1004     napi_value businessError = nullptr;
1005     napi_create_error(env, nullptr, message, &businessError);
1006     napi_set_named_property(env, businessError, CODE_KEY_NAME.c_str(), code);
1007     return businessError;
1008 }
1009 
JsContinuationManagerInit(napi_env env,napi_value exportObj)1010 napi_value JsContinuationManagerInit(napi_env env, napi_value exportObj)
1011 {
1012     HILOGD("called.");
1013     if (env == nullptr || exportObj == nullptr) {
1014         HILOGE("Invalid input parameters");
1015         return nullptr;
1016     }
1017 
1018     JsContinuationManager* jsContinuationManager = new JsContinuationManager();
1019     if (napi_wrap(env, exportObj, jsContinuationManager, JsContinuationManager::Finalizer, nullptr, nullptr)
1020         != napi_ok) {
1021         JsContinuationManager::Finalizer(env, jsContinuationManager, nullptr);
1022         jsContinuationManager = nullptr;
1023         return nullptr;
1024     }
1025 
1026     const char *moduleName = "JsContinuationManager";
1027     BindNativeFunction(env, exportObj, "register", moduleName, JsContinuationManager::Register);
1028     BindNativeFunction(env, exportObj, "unregister", moduleName, JsContinuationManager::Unregister);
1029     BindNativeFunction(env, exportObj, "on", moduleName, JsContinuationManager::RegisterDeviceSelectionCallback);
1030     BindNativeFunction(env, exportObj, "off", moduleName, JsContinuationManager::UnregisterDeviceSelectionCallback);
1031     BindNativeFunction(env, exportObj, "updateConnectStatus", moduleName, JsContinuationManager::UpdateConnectStatus);
1032     BindNativeFunction(env, exportObj, "startDeviceManager", moduleName, JsContinuationManager::StartDeviceManager);
1033     BindNativeProperty(env, exportObj, "DeviceConnectState", JsContinuationManager::InitDeviceConnectStateObject);
1034     BindNativeProperty(env, exportObj, "ContinuationMode", JsContinuationManager::InitContinuationModeObject);
1035     BindNativeFunction(env, exportObj, "registerContinuation", moduleName,
1036         JsContinuationManager::RegisterContinuation);
1037     BindNativeFunction(env, exportObj, "unregisterContinuation", moduleName,
1038         JsContinuationManager::UnregisterContinuation);
1039     BindNativeFunction(env, exportObj, "updateContinuationState", moduleName,
1040         JsContinuationManager::UpdateContinuationState);
1041     BindNativeFunction(env, exportObj, "startContinuationDeviceManager", moduleName,
1042         JsContinuationManager::StartContinuationDeviceManager);
1043 
1044     return CreateJsUndefined(env);
1045 }
1046 }  // namespace DistributedSchedule
1047 }  // namespace OHOS