• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <string>
17 
18 #include "distributed_mission_manager.h"
19 
20 #include "ability_manager_client.h"
21 #include "hilog_wrapper.h"
22 #include "ipc_skeleton.h"
23 #include "napi_common_data.h"
24 #include "napi_common_util.h"
25 #include "napi_common_want.h"
26 #include "napi_remote_object.h"
27 
28 using namespace OHOS::AppExecFwk;
29 
30 namespace OHOS {
31 namespace AAFwk {
32 using AbilityManagerClient = AAFwk::AbilityManagerClient;
33 const std::string TAG = "NAPIMissionRegistration";
34 constexpr size_t VALUE_BUFFER_SIZE = 128;
35 const std::string CODE_KEY_NAME = "code";
36 static const std::map<int32_t, int32_t> DMS_MISSION_MANAGER_ERROR_CODE_MAP = {
37     { NO_ERROR, NO_ERROR },
38     { DMS_PERMISSION_DENIED, PERMISSION_DENIED },
39     { CHECK_PERMISSION_FAILED, PERMISSION_DENIED },
40     { ERR_NULL_OBJECT, PARAMETER_CHECK_FAILED },
41     { INVALID_PARAMETERS_ERR, PARAMETER_CHECK_FAILED },
42     { ERR_INVALID_VALUE, PARAMETER_CHECK_FAILED },
43     { INNER_ERR, SYSTEM_WORK_ABNORMALLY },
44     { ABILITY_SERVICE_NOT_CONNECTED, SYSTEM_WORK_ABNORMALLY },
45     { INVALID_REMOTE_PARAMETERS_ERR, SYSTEM_WORK_ABNORMALLY },
46     { NO_MISSION_INFO_FOR_MISSION_ID, NO_MISSION_INFO_FOR_MISSION_ID },
47     { CONTINUE_REMOTE_UNINSTALLED_UNSUPPORT_FREEINSTALL, REMOTE_UNINSTALLED_AND_UNSUPPORT_FREEINSTALL_FOR_CONTINUE },
48     { CONTINUE_REMOTE_UNINSTALLED_SUPPORT_FREEINSTALL, CONTINUE_WITHOUT_FREEINSTALL_FLAG },
49     { OPERATION_DEVICE_NOT_INITIATOR_OR_TARGET, OPERATION_DEVICE_NOT_INITIATOR_OR_TARGET },
50     { CONTINUE_ALREADY_IN_PROGRESS, CONTINUE_ALREADY_IN_PROGRESS },
51     { MISSION_FOR_CONTINUING_IS_NOT_ALIVE, MISSION_FOR_CONTINUING_IS_NOT_ALIVE },
52 };
53 
54 static const std::map<int32_t, std::string> DMS_MISSION_MANAGER_ERROR_INFO_MAP = {
55     { NO_ERROR, std::string() },
56     { PERMISSION_DENIED, std::string("permission denied") },
57     { PARAMETER_CHECK_FAILED, std::string("parameter check failed.") },
58     { SYSTEM_WORK_ABNORMALLY, std::string("the system ability work abnormally.") },
59     { NO_MISSION_INFO_FOR_MISSION_ID, std::string("failed to get the missionInfo of the specified missionId.") },
60     { REMOTE_UNINSTALLED_AND_UNSUPPORT_FREEINSTALL_FOR_CONTINUE, std::string("the application is not installed on the \
61 remote end and installation-free is not supported.") },
62     { CONTINUE_WITHOUT_FREEINSTALL_FLAG, std::string("the application is not installed on the remote end but \
63 installation-free is supported, try again with freeInstall flag.") },
64     { OPERATION_DEVICE_NOT_INITIATOR_OR_TARGET, std::string("the operation device must be the device where the \
65 application to be continued is located or the target device to be continued.") },
66     { CONTINUE_ALREADY_IN_PROGRESS, std::string("the local continuation task is already in progress.") },
67     { MISSION_FOR_CONTINUING_IS_NOT_ALIVE, std::string("the mission for continuing is not alive, \
68 try again after restart this mission.") },
69 };
70 
GenerateBusinessError(const napi_env & env,int32_t errCode,const std::string & errMsg)71 napi_value GenerateBusinessError(const napi_env &env, int32_t errCode, const std::string &errMsg)
72 {
73     HILOG_ERROR("%{public}s", errMsg.c_str());
74     napi_value code = nullptr;
75     napi_create_int32(env, errCode, &code);
76     napi_value msg = nullptr;
77     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msg);
78     napi_value businessError = nullptr;
79     napi_create_error(env, nullptr, msg, &businessError);
80     napi_set_named_property(env, businessError, CODE_KEY_NAME.c_str(), code);
81     return businessError;
82 }
83 
ErrorCodeReturn(int32_t code)84 int32_t ErrorCodeReturn(int32_t code)
85 {
86     return DMS_MISSION_MANAGER_ERROR_CODE_MAP.find(code) != DMS_MISSION_MANAGER_ERROR_CODE_MAP.end() ?
87         DMS_MISSION_MANAGER_ERROR_CODE_MAP.at(code) : SYSTEM_WORK_ABNORMALLY;
88 }
89 
GetUndefined(const napi_env & env)90 napi_value GetUndefined(const napi_env &env)
91 {
92     napi_value nullResult = nullptr;
93     napi_get_undefined(env, &nullResult);
94     return nullResult;
95 }
96 
ErrorInfoReturn(int32_t code)97 std::string ErrorInfoReturn(int32_t code)
98 {
99     return DMS_MISSION_MANAGER_ERROR_INFO_MAP.find(code) != DMS_MISSION_MANAGER_ERROR_INFO_MAP.end() ?
100         DMS_MISSION_MANAGER_ERROR_INFO_MAP.at(code) : DMS_MISSION_MANAGER_ERROR_INFO_MAP.at(SYSTEM_WORK_ABNORMALLY);
101 }
102 
SetStartSyncMissionsContext(const napi_env & env,const napi_value & value,SyncRemoteMissionsContext * context,std::string & errInfo)103 bool SetStartSyncMissionsContext(const napi_env &env, const napi_value &value,
104     SyncRemoteMissionsContext* context, std::string &errInfo)
105 {
106     HILOG_INFO("%{public}s call.", __func__);
107     bool isFixConflict = false;
108     napi_has_named_property(env, value, "fixConflict", &isFixConflict);
109     if (!isFixConflict) {
110         errInfo = "Parameter error. The key of \"MissionParameter\" must be fixConflict";
111         return false;
112     }
113     napi_value fixConflictValue = nullptr;
114     napi_get_named_property(env, value, "fixConflict", &fixConflictValue);
115     if (fixConflictValue == nullptr) {
116         errInfo = "Parameter error. The value of \"fixConflict\" must not be undefined";
117         return false;
118     }
119     napi_valuetype valueType = napi_undefined;
120     napi_typeof(env, fixConflictValue, &valueType);
121     if (valueType != napi_boolean) {
122         errInfo = "Parameter error. The type of \"fixConflict\" must be boolean";
123         return false;
124     }
125     napi_get_value_bool(env, fixConflictValue, &context->fixConflict);
126     bool isTag = false;
127     napi_has_named_property(env, value, "tag", &isTag);
128     if (!isTag) {
129         errInfo = "Parameter error. The key of \"MissionParameter\" must be tag";
130         return false;
131     }
132     napi_value tagValue = nullptr;
133     napi_get_named_property(env, value, "tag", &tagValue);
134     if (tagValue == nullptr) {
135         errInfo = "Parameter error. The value of \"tag\" must not be undefined";
136         return false;
137     }
138     napi_typeof(env, tagValue, &valueType);
139     if (valueType != napi_number) {
140         errInfo = "Parameter error. The type of \"tag\" must be number";
141         return false;
142     }
143     napi_get_value_int64(env, tagValue, &context->tag);
144     HILOG_INFO("%{public}s end.", __func__);
145     return true;
146 }
147 
SetSyncRemoteMissionsContext(const napi_env & env,const napi_value & value,bool isStart,SyncRemoteMissionsContext * context,std::string & errInfo)148 bool SetSyncRemoteMissionsContext(const napi_env &env, const napi_value &value,
149     bool isStart, SyncRemoteMissionsContext* context, std::string &errInfo)
150 {
151     HILOG_INFO("%{public}s call.", __func__);
152     napi_valuetype valueType = napi_undefined;
153     napi_typeof(env, value, &valueType);
154     if (valueType != napi_object) {
155         errInfo = "Parameter error. The type of \"parameter\" must be MissionParameter";
156         return false;
157     }
158     napi_value deviceIdValue = nullptr;
159     bool isDeviceId = false;
160     napi_has_named_property(env, value, "deviceId", &isDeviceId);
161     if (!isDeviceId) {
162         errInfo = "Parameter error. The key of \"parameter\" must be deviceId";
163         return false;
164     }
165     napi_get_named_property(env, value, "deviceId", &deviceIdValue);
166     if (deviceIdValue == nullptr) {
167         errInfo = "Parameter error. The value of \"deviceId\" must not be undefined";
168         return false;
169     }
170     napi_typeof(env, deviceIdValue, &valueType);
171     if (valueType != napi_string) {
172         errInfo = "Parameter error. The type of \"deviceId\" must be string";
173         return false;
174     }
175 
176     char deviceId[VALUE_BUFFER_SIZE + 1] = {0};
177     napi_get_value_string_utf8(env, deviceIdValue, deviceId, VALUE_BUFFER_SIZE + 1, &context->valueLen);
178     if (context->valueLen > VALUE_BUFFER_SIZE) {
179         errInfo = "Parameter error. The length of \"deviceId\" must be less than " +
180             std::to_string(VALUE_BUFFER_SIZE);
181         return false;
182     }
183     context->deviceId = deviceId;
184 
185     if (isStart) {
186         if (!SetStartSyncMissionsContext (env, value, context, errInfo)) {
187             HILOG_ERROR("%{public}s, Wrong argument for start sync.", __func__);
188             return false;
189         }
190     }
191     HILOG_INFO("%{public}s end.", __func__);
192     return true;
193 }
194 
ProcessSyncInput(napi_env env,napi_callback_info info,bool isStart,SyncRemoteMissionsContext * syncContext,std::string & errInfo)195 bool ProcessSyncInput(napi_env env, napi_callback_info info, bool isStart,
196     SyncRemoteMissionsContext* syncContext, std::string &errInfo)
197 {
198     HILOG_INFO("%{public}s,called.", __func__);
199     size_t argc = 2;
200     napi_value argv[2] = { 0 };
201     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
202     if (argc != ARGS_ONE && argc != ARGS_TWO) {
203         errInfo = "Parameter error. The type of \"number of parameters\" must be 1 or 2";
204         return false;
205     }
206     syncContext->env = env;
207     if (!SetSyncRemoteMissionsContext(env, argv[0], isStart, syncContext, errInfo)) {
208         HILOG_ERROR("%{public}s, Wrong argument.", __func__);
209         return false;
210     }
211     if (argc == ARGS_TWO) {
212         napi_valuetype valueType = napi_undefined;
213         napi_typeof(env, argv[1], &valueType);
214         if (valueType != napi_function) {
215             errInfo = "Parameter error. The type of \"callback\" must be AsynCallback<void>: void";
216             return false;
217         }
218         napi_create_reference(env, argv[1], 1, &syncContext->callbackRef);
219     }
220     HILOG_INFO("%{public}s, end.", __func__);
221     return true;
222 }
223 
StartSyncRemoteMissionsAsyncWork(napi_env env,const napi_value resourceName,SyncRemoteMissionsContext * syncContext)224 void StartSyncRemoteMissionsAsyncWork(napi_env env, const napi_value resourceName,
225     SyncRemoteMissionsContext* syncContext)
226 {
227     HILOG_INFO("%{public}s, called.", __func__);
228     napi_create_async_work(env, nullptr, resourceName,
229         [](napi_env env, void* data) {
230             SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data;
231             syncContext->result = AbilityManagerClient::GetInstance()->
232                 StartSyncRemoteMissions(syncContext->deviceId,
233                 syncContext->fixConflict, syncContext->tag);
234         },
235         [](napi_env env, napi_status status, void* data) {
236             SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data;
237             // set result
238             napi_value result[2] = { nullptr };
239             napi_get_undefined(env, &result[1]);
240             if (syncContext->result == 0) {
241                 napi_get_undefined(env, &result[0]);
242             } else {
243                 int32_t errCode = ErrorCodeReturn(syncContext->result);
244                 result[0] = GenerateBusinessError(env, errCode, ErrorInfoReturn(errCode));
245             }
246 
247             if (syncContext->callbackRef == nullptr) { // promise
248                 if (syncContext->result == 0) {
249                     napi_resolve_deferred(env, syncContext->deferred, result[1]);
250                 } else {
251                     napi_reject_deferred(env, syncContext->deferred, result[0]);
252                 }
253             } else { // AsyncCallback
254                 napi_value callback = nullptr;
255                 napi_get_reference_value(env, syncContext->callbackRef, &callback);
256                 napi_value callResult;
257                 napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult);
258                 napi_delete_reference(env, syncContext->callbackRef);
259             }
260             napi_delete_async_work(env, syncContext->work);
261             delete syncContext;
262             syncContext = nullptr;
263         },
264         static_cast<void *>(syncContext),
265         &syncContext->work);
266         napi_queue_async_work(env, syncContext->work);
267     HILOG_INFO("%{public}s, end.", __func__);
268 }
269 
NAPI_StartSyncRemoteMissions(napi_env env,napi_callback_info info)270 napi_value NAPI_StartSyncRemoteMissions(napi_env env, napi_callback_info info)
271 {
272     HILOG_INFO("%{public}s, called.", __func__);
273     std::string errInfo = "Parameter error";
274     auto syncContext = new SyncRemoteMissionsContext();
275     if (!ProcessSyncInput(env, info, true, syncContext, errInfo)) {
276         delete syncContext;
277         syncContext = nullptr;
278         napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
279         return GetUndefined(env);
280     }
281     napi_value result = nullptr;
282     if (syncContext->callbackRef == nullptr) {
283         napi_create_promise(env, &syncContext->deferred, &result);
284     } else {
285         napi_get_undefined(env, &result);
286     }
287 
288     napi_value resourceName = nullptr;
289     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
290 
291     StartSyncRemoteMissionsAsyncWork(env, resourceName, syncContext);
292     HILOG_INFO("%{public}s, end.", __func__);
293     return result;
294 }
295 
StopSyncRemoteMissionsAsyncWork(napi_env env,napi_value resourceName,SyncRemoteMissionsContext * syncContext)296 void StopSyncRemoteMissionsAsyncWork(napi_env env, napi_value resourceName,
297     SyncRemoteMissionsContext* syncContext)
298 {
299     HILOG_INFO("%{public}s, called.", __func__);
300     napi_create_async_work(env, nullptr, resourceName,
301         [](napi_env env, void* data) {
302             SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data;
303             syncContext->result = AbilityManagerClient::GetInstance()->
304                 StopSyncRemoteMissions(syncContext->deviceId);
305         },
306         [](napi_env env, napi_status status, void* data) {
307             SyncRemoteMissionsContext* syncContext = (SyncRemoteMissionsContext*)data;
308             // set result
309             napi_value result[2] = { nullptr };
310             napi_get_undefined(env, &result[1]);
311             if (syncContext->result == 0) {
312                 napi_get_undefined(env, &result[0]);
313             } else {
314                 int32_t errCode = ErrorCodeReturn(syncContext->result);
315                 result[0] = GenerateBusinessError(env, errCode, ErrorInfoReturn(errCode));
316             }
317 
318             if (syncContext->callbackRef == nullptr) { // promise
319                 if (syncContext->result == 0) {
320                     napi_resolve_deferred(env, syncContext->deferred, result[1]);
321                 } else {
322                     napi_reject_deferred(env, syncContext->deferred, result[0]);
323                 }
324             } else { // AsyncCallback
325                 napi_value callback = nullptr;
326                 napi_get_reference_value(env, syncContext->callbackRef, &callback);
327                 napi_value callResult;
328                 napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult);
329                 napi_delete_reference(env, syncContext->callbackRef);
330             }
331             napi_delete_async_work(env, syncContext->work);
332             delete syncContext;
333             syncContext = nullptr;
334         },
335         static_cast<void *>(syncContext),
336         &syncContext->work);
337         napi_queue_async_work(env, syncContext->work);
338     HILOG_INFO("%{public}s, end.", __func__);
339 }
340 
NAPI_StopSyncRemoteMissions(napi_env env,napi_callback_info info)341 napi_value NAPI_StopSyncRemoteMissions(napi_env env, napi_callback_info info)
342 {
343     HILOG_INFO("%{public}s, called.", __func__);
344     std::string errInfo = "Parameter error";
345     auto syncContext = new SyncRemoteMissionsContext();
346     if (!ProcessSyncInput(env, info, false, syncContext, errInfo)) {
347         delete syncContext;
348         syncContext = nullptr;
349         napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
350         return GetUndefined(env);
351     }
352     napi_value result = nullptr;
353     if (syncContext->callbackRef == nullptr) {
354         napi_create_promise(env, &syncContext->deferred, &result);
355     } else {
356         napi_get_undefined(env, &result);
357     }
358 
359     napi_value resourceName = nullptr;
360     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
361 
362     StopSyncRemoteMissionsAsyncWork(env, resourceName, syncContext);
363     HILOG_INFO("%{public}s, end.", __func__);
364     return result;
365 }
366 
CreateRegisterMissionCBCBInfo(napi_env env)367 RegisterMissionCB *CreateRegisterMissionCBCBInfo(napi_env env)
368 {
369     HILOG_INFO("%{public}s called.", __func__);
370     auto registerMissionCB = new (std::nothrow) RegisterMissionCB;
371     if (registerMissionCB == nullptr) {
372         HILOG_ERROR("%{public}s registerMissionCB == nullptr", __func__);
373         return nullptr;
374     }
375     registerMissionCB->cbBase.cbInfo.env = env;
376     registerMissionCB->cbBase.asyncWork = nullptr;
377     registerMissionCB->cbBase.deferred = nullptr;
378     registerMissionCB->callbackRef = nullptr;
379     HILOG_INFO("%{public}s end.", __func__);
380     return registerMissionCB;
381 }
382 
RegisterMissionExecuteCB(napi_env env,void * data)383 void RegisterMissionExecuteCB(napi_env env, void *data)
384 {
385     HILOG_INFO("%{public}s called.", __func__);
386     auto registerMissionCB = (RegisterMissionCB*)data;
387 
388     std::lock_guard<std::mutex> autoLock(registrationLock_);
389     sptr<NAPIRemoteMissionListener> registration;
390     auto item = registration_.find(registerMissionCB->deviceId);
391     if (item != registration_.end()) {
392         HILOG_INFO("registration exits.");
393         registration = registration_[registerMissionCB->deviceId];
394     } else {
395         HILOG_INFO("registration not exits.");
396         registration = new (std::nothrow) NAPIRemoteMissionListener();
397     }
398     registerMissionCB->missionRegistration = registration;
399     if (registerMissionCB->missionRegistration == nullptr) {
400         HILOG_ERROR("%{public}s missionRegistration == nullptr.", __func__);
401         registerMissionCB->result = -1;
402         return;
403     }
404     registerMissionCB->missionRegistration->SetEnv(env);
405     registerMissionCB->missionRegistration->
406         SetNotifyMissionsChangedCBRef(registerMissionCB->missionRegistrationCB.callback[0]);
407     registerMissionCB->missionRegistration->
408         SetNotifySnapshotCBRef(registerMissionCB->missionRegistrationCB.callback[1]);
409     registerMissionCB->missionRegistration->
410         SetNotifyNetDisconnectCBRef(registerMissionCB->
411             missionRegistrationCB.callback[2]); // 2 refers the second argument
412     HILOG_INFO("set callback success.");
413 
414     registerMissionCB->result =
415         AbilityManagerClient::GetInstance()->
416         RegisterMissionListener(registerMissionCB->deviceId,
417         registerMissionCB->missionRegistration);
418     if (registerMissionCB->result == NO_ERROR) {
419         HILOG_INFO("add registration.");
420         registration_[registerMissionCB->deviceId] = registration;
421     }
422     HILOG_DEBUG("%{public}s end.deviceId:%{public}d ", __func__, registerMissionCB->result);
423 }
424 
RegisterMissionCallbackCompletedCB(napi_env env,napi_status status,void * data)425 void RegisterMissionCallbackCompletedCB(napi_env env, napi_status status, void *data)
426 {
427     HILOG_INFO("%{public}s called.", __func__);
428     auto registerMissionCB = static_cast<RegisterMissionCB *>(data);
429     // set result
430     napi_value result[2] = { nullptr };
431     napi_get_undefined(env, &result[1]);
432     if (registerMissionCB->result == 0) {
433         napi_get_undefined(env, &result[0]);
434     } else {
435         int32_t errCode = ErrorCodeReturn(registerMissionCB->result);
436         result[0] = GenerateBusinessError(env, errCode, ErrorInfoReturn(errCode));
437     }
438 
439     ReturnValueToApplication(env, &result[0], registerMissionCB);
440     delete registerMissionCB;
441     registerMissionCB = nullptr;
442     HILOG_INFO("%{public}s end.", __func__);
443 }
444 
ReturnValueToApplication(napi_env env,napi_value * result,RegisterMissionCB * registerMissionCB)445 void ReturnValueToApplication(napi_env env, napi_value *result, RegisterMissionCB *registerMissionCB)
446 {
447     if (registerMissionCB->callbackRef == nullptr) { // promise
448         if (registerMissionCB->result == 0) {
449             napi_resolve_deferred(env, registerMissionCB->cbBase.deferred, result[1]);
450         } else {
451             napi_reject_deferred(env, registerMissionCB->cbBase.deferred, result[0]);
452         }
453     } else { // AsyncCallback
454         napi_value callback = nullptr;
455         napi_get_reference_value(env, registerMissionCB->callbackRef, &callback);
456         napi_value callResult;
457         napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult);
458         napi_delete_reference(env, registerMissionCB->callbackRef);
459     }
460     NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, registerMissionCB->cbBase.asyncWork));
461 }
462 
RegisterMissionAsync(napi_env env,RegisterMissionCB * registerMissionCB)463 napi_value RegisterMissionAsync(napi_env env, RegisterMissionCB *registerMissionCB)
464 {
465     HILOG_INFO("%{public}s asyncCallback.", __func__);
466     if (registerMissionCB == nullptr) {
467         HILOG_ERROR("%{public}s, registerMissionCB == nullptr.", __func__);
468         napi_throw(env, GenerateBusinessError(env, SYSTEM_WORK_ABNORMALLY, ErrorInfoReturn(SYSTEM_WORK_ABNORMALLY)));
469         return nullptr;
470     }
471     napi_value result = nullptr;
472     if (registerMissionCB->callbackRef == nullptr) {
473         napi_create_promise(env, &registerMissionCB->cbBase.deferred, &result);
474     } else {
475         napi_get_undefined(env, &result);
476     }
477     napi_value resourceName = nullptr;
478     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
479 
480     napi_create_async_work(env,
481         nullptr,
482         resourceName,
483         RegisterMissionExecuteCB,
484         RegisterMissionCallbackCompletedCB,
485         static_cast<void *>(registerMissionCB),
486         &registerMissionCB->cbBase.asyncWork);
487     napi_queue_async_work(env, registerMissionCB->cbBase.asyncWork);
488     HILOG_INFO("%{public}s asyncCallback end.", __func__);
489     return result;
490 }
491 
SetCallbackReference(napi_env env,const napi_value & value,RegisterMissionCB * registerMissionCB,std::string & errInfo)492 bool SetCallbackReference(napi_env env, const napi_value& value,
493     RegisterMissionCB *registerMissionCB, std::string &errInfo)
494 {
495     HILOG_INFO("%{public}s called.", __func__);
496     bool isFirstCallback = false;
497     napi_has_named_property(env, value, "notifyMissionsChanged", &isFirstCallback);
498     bool isSecondCallback = false;
499     napi_has_named_property(env, value, "notifySnapshot", &isSecondCallback);
500     bool isThirdCallback = false;
501     napi_has_named_property(env, value, "notifyNetDisconnect", &isThirdCallback);
502     if (!isFirstCallback || !isSecondCallback || !isThirdCallback) {
503         errInfo = "Parameter error. The type of \"options\" must be MissionCallback";
504         return false;
505     }
506     napi_value jsMethod = nullptr;
507     napi_get_named_property(env, value, "notifyMissionsChanged", &jsMethod);
508     if (jsMethod == nullptr) {
509         errInfo = "Parameter error. The value of \"notifyMissionsChanged\" must not be undefined";
510         return false;
511     }
512     napi_valuetype valuetype = napi_undefined;
513     napi_typeof(env, jsMethod, &valuetype);
514     if (valuetype != napi_function) {
515         errInfo = "Parameter error. The type of \"notifyMissionsChanged\" must be function";
516         return false;
517     }
518     napi_create_reference(env, jsMethod, 1, &registerMissionCB->missionRegistrationCB.callback[0]);
519 
520     napi_get_named_property(env, value, "notifySnapshot", &jsMethod);
521     if (jsMethod == nullptr) {
522         errInfo = "Parameter error. The value of \"notifySnapshot\" must not be undefined";
523         return false;
524     }
525     napi_typeof(env, jsMethod, &valuetype);
526     if (valuetype != napi_function) {
527         errInfo = "Parameter error. The type of \"notifySnapshot\" must be function";
528         return false;
529     }
530     napi_create_reference(env, jsMethod, 1, &registerMissionCB->missionRegistrationCB.callback[1]);
531 
532     napi_get_named_property(env, value, "notifyNetDisconnect", &jsMethod);
533     if (jsMethod == nullptr) {
534         errInfo = "Parameter error. The value of \"notifyNetDisconnect\" must not be undefined";
535         return false;
536     }
537     napi_typeof(env, jsMethod, &valuetype);
538     if (valuetype != napi_function) {
539         errInfo = "Parameter error. The type of \"notifyNetDisconnect\" must be function";
540         return false;
541     }
542     napi_create_reference(env, jsMethod, 1,
543         &registerMissionCB->missionRegistrationCB.callback[2]); // 2 refers the second argument
544     HILOG_INFO("%{public}s called end.", __func__);
545     return true;
546 }
547 
CreateCallbackReference(napi_env env,const napi_value & value,RegisterMissionCB * registerMissionCB,std::string & errInfo)548 bool CreateCallbackReference(napi_env env, const napi_value& value,
549     RegisterMissionCB *registerMissionCB, std::string &errInfo)
550 {
551     HILOG_INFO("%{public}s called.", __func__);
552     napi_valuetype valuetype = napi_undefined;
553     napi_typeof(env, value, &valuetype);
554     if (valuetype == napi_object) {
555         if (!SetCallbackReference(env, value, registerMissionCB, errInfo)) {
556             HILOG_ERROR("%{public}s, Wrong callback.", __func__);
557             return false;
558         }
559     } else {
560         errInfo = "Parameter error. The type of \"options\" must be MissionCallback";
561         return false;
562     }
563     HILOG_INFO("%{public}s called end.", __func__);
564     return true;
565 }
566 
RegisterMissionWrap(napi_env env,napi_callback_info info,RegisterMissionCB * registerMissionCB,std::string & errInfo)567 napi_value RegisterMissionWrap(napi_env env, napi_callback_info info,
568     RegisterMissionCB *registerMissionCB, std::string &errInfo)
569 {
570     HILOG_INFO("%{public}s called.", __func__);
571     size_t argcAsync = 3;
572     napi_value args[ARGS_MAX_COUNT] = {nullptr};
573     napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr);
574     if (argcAsync != ARGS_TWO && argcAsync != ARGS_THREE) {
575         errInfo = "Parameter error. The type of \"number of parameters\" must be 2 or 3";
576         return nullptr;
577     }
578     napi_value firstNApi = nullptr;
579     napi_valuetype valueType = napi_undefined;
580     bool isDeviceId = false;
581     napi_has_named_property(env, args[0], "deviceId", &isDeviceId);
582     napi_typeof(env, args[0], &valueType);
583     if (!isDeviceId || valueType != napi_object) {
584         errInfo = "Parameter error. The key of \"MissionDeviceInfo\" must be deviceId";
585         return nullptr;
586     }
587     napi_get_named_property(env, args[0], "deviceId", &firstNApi);
588     if (firstNApi == nullptr) {
589         errInfo = "Parameter error. The value of \"deviceId\" must not be undefined";
590         return nullptr;
591     }
592 
593     napi_typeof(env, firstNApi, &valueType);
594     if (valueType != napi_string) {
595         errInfo = "Parameter error. The type of \"deviceId\" must be string";
596         return nullptr;
597     }
598     char deviceId[VALUE_BUFFER_SIZE + 1] = {0};
599     size_t valueLen = 0;
600     napi_get_value_string_utf8(env, firstNApi, deviceId, VALUE_BUFFER_SIZE + 1, &valueLen);
601     if (valueLen > VALUE_BUFFER_SIZE) {
602         errInfo = "Parameter error. The length of \"deviceId\" must be less than " +
603             std::to_string(VALUE_BUFFER_SIZE);
604         return nullptr;
605     }
606     registerMissionCB->deviceId = deviceId;
607 
608     if (argcAsync > 1 && !CreateCallbackReference(env, args[1], registerMissionCB, errInfo)) {
609         return nullptr;
610     }
611 
612     if (argcAsync == ARGS_THREE) {
613         napi_typeof(env, args[ARGS_TWO], &valueType);
614         if (valueType != napi_function) {
615             errInfo = "Parameter error. The type of \"options\" must be MissionCallback";
616             return nullptr;
617         }
618         napi_create_reference(env, args[ARGS_TWO], 1, &registerMissionCB->callbackRef);
619     }
620 
621     napi_value ret = RegisterMissionAsync(env, registerMissionCB);
622     HILOG_INFO("%{public}s called end.", __func__);
623     return ret;
624 }
625 
NAPI_RegisterMissionListener(napi_env env,napi_callback_info info)626 napi_value NAPI_RegisterMissionListener(napi_env env, napi_callback_info info)
627 {
628     HILOG_INFO("%{public}s called.", __func__);
629     std::string errInfo = "Parameter error";
630     RegisterMissionCB *registerMissionCB = CreateRegisterMissionCBCBInfo(env);
631     if (registerMissionCB == nullptr) {
632         HILOG_ERROR("%{public}s registerMissionCB == nullptr", __func__);
633         napi_throw(env, GenerateBusinessError(env, SYSTEM_WORK_ABNORMALLY, ErrorInfoReturn(SYSTEM_WORK_ABNORMALLY)));
634         return GetUndefined(env);
635     }
636 
637     napi_value ret = RegisterMissionWrap(env, info, registerMissionCB, errInfo);
638     if (ret == nullptr) {
639         HILOG_ERROR("%{public}s ret == nullptr", __func__);
640         delete registerMissionCB;
641         registerMissionCB = nullptr;
642         napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
643         return GetUndefined(env);
644     }
645     HILOG_INFO("%{public}s end.", __func__);
646     return ret;
647 }
648 
SetEnv(const napi_env & env)649 void NAPIMissionContinue::SetEnv(const napi_env &env)
650 {
651     env_ = env;
652 }
653 
~NAPIRemoteMissionListener()654 NAPIRemoteMissionListener::~NAPIRemoteMissionListener()
655 {
656     if (env_ == nullptr) {
657         return;
658     }
659     if (notifyMissionsChangedRef_ != nullptr) {
660         napi_delete_reference(env_, notifyMissionsChangedRef_);
661         notifyMissionsChangedRef_ = nullptr;
662     }
663     if (notifySnapshotRef_ != nullptr) {
664         napi_delete_reference(env_, notifySnapshotRef_);
665         notifySnapshotRef_ = nullptr;
666     }
667     if (notifyNetDisconnectRef_ != nullptr) {
668         napi_delete_reference(env_, notifyNetDisconnectRef_);
669         notifyNetDisconnectRef_ = nullptr;
670     }
671 }
672 
SetEnv(const napi_env & env)673 void NAPIRemoteMissionListener::SetEnv(const napi_env &env)
674 {
675     env_ = env;
676 }
677 
SetNotifyMissionsChangedCBRef(const napi_ref & ref)678 void NAPIRemoteMissionListener::SetNotifyMissionsChangedCBRef(const napi_ref &ref)
679 {
680     notifyMissionsChangedRef_ = ref;
681 }
682 
SetNotifySnapshotCBRef(const napi_ref & ref)683 void NAPIRemoteMissionListener::SetNotifySnapshotCBRef(const napi_ref &ref)
684 {
685     notifySnapshotRef_ = ref;
686 }
687 
SetNotifyNetDisconnectCBRef(const napi_ref & ref)688 void NAPIRemoteMissionListener::SetNotifyNetDisconnectCBRef(const napi_ref &ref)
689 {
690     notifyNetDisconnectRef_ = ref;
691 }
692 
UvWorkNotifyMissionChanged(uv_work_t * work,int status)693 void UvWorkNotifyMissionChanged(uv_work_t *work, int status)
694 {
695     HILOG_INFO("UvWorkNotifyMissionChanged, uv_queue_work");
696     if (work == nullptr) {
697         HILOG_ERROR("UvWorkNotifyMissionChanged, work is null");
698         return;
699     }
700     RegisterMissionCB *registerMissionCB = static_cast<RegisterMissionCB *>(work->data);
701     if (registerMissionCB == nullptr) {
702         HILOG_ERROR("UvWorkNotifyMissionChanged, registerMissionCB is null");
703         delete work;
704         return;
705     }
706     napi_value result = nullptr;
707     result =
708         WrapString(registerMissionCB->cbBase.cbInfo.env, registerMissionCB->deviceId.c_str(), "deviceId");
709 
710     napi_value callback = nullptr;
711     napi_value undefined = nullptr;
712     napi_get_undefined(registerMissionCB->cbBase.cbInfo.env, &undefined);
713     napi_value callResult = nullptr;
714     napi_get_reference_value(
715         registerMissionCB->cbBase.cbInfo.env, registerMissionCB->cbBase.cbInfo.callback, &callback);
716 
717     napi_call_function(registerMissionCB->cbBase.cbInfo.env, undefined, callback, 1, &result, &callResult);
718     delete registerMissionCB;
719     registerMissionCB = nullptr;
720     delete work;
721     HILOG_INFO("UvWorkNotifyMissionChanged, uv_queue_work end");
722 }
723 
NotifyMissionsChanged(const std::string & deviceId)724 void NAPIRemoteMissionListener::NotifyMissionsChanged(const std::string& deviceId)
725 {
726     HILOG_INFO("%{public}s, called.", __func__);
727     uv_loop_s *loop = nullptr;
728 
729     napi_get_uv_event_loop(env_, &loop);
730     if (loop == nullptr) {
731         HILOG_ERROR("%{public}s, loop == nullptr.", __func__);
732         return;
733     }
734 
735     uv_work_t *work = new uv_work_t;
736 
737     auto registerMissionCB = new (std::nothrow) RegisterMissionCB;
738     if (registerMissionCB == nullptr) {
739         HILOG_ERROR("%{public}s, registerMissionCB == nullptr.", __func__);
740         delete work;
741         return;
742     }
743     registerMissionCB->cbBase.cbInfo.env = env_;
744     registerMissionCB->cbBase.cbInfo.callback = notifyMissionsChangedRef_;
745     registerMissionCB->deviceId = deviceId;
746     work->data = static_cast<void *>(registerMissionCB);
747 
748     int rev = uv_queue_work(
749         loop, work, [](uv_work_t *work) {}, UvWorkNotifyMissionChanged);
750     if (rev != 0) {
751         delete registerMissionCB;
752         registerMissionCB = nullptr;
753         delete work;
754     }
755     HILOG_INFO("%{public}s, end.", __func__);
756 }
757 
UvWorkNotifySnapshot(uv_work_t * work,int status)758 void UvWorkNotifySnapshot(uv_work_t *work, int status)
759 {
760     HILOG_INFO("UvWorkNotifySnapshot, uv_queue_work");
761     if (work == nullptr) {
762         HILOG_ERROR("UvWorkNotifySnapshot, work is null");
763         return;
764     }
765     RegisterMissionCB *registerMissionCB = static_cast<RegisterMissionCB *>(work->data);
766     if (registerMissionCB == nullptr) {
767         HILOG_ERROR("UvWorkNotifySnapshot, registerMissionCB is null");
768         delete work;
769         return;
770     }
771     napi_value result[2] = {nullptr};
772     result[0] =
773         WrapString(registerMissionCB->cbBase.cbInfo.env, registerMissionCB->deviceId.c_str(), "deviceId");
774     result[1] =
775         WrapInt32(registerMissionCB->cbBase.cbInfo.env, registerMissionCB->missionId, "missionId");
776     CallbackReturn(&result[0], registerMissionCB);
777     delete registerMissionCB;
778     registerMissionCB = nullptr;
779     delete work;
780     HILOG_INFO("UvWorkNotifySnapshot, uv_queue_work end");
781 }
782 
CallbackReturn(napi_value * result,RegisterMissionCB * registerMissionCB)783 void CallbackReturn(napi_value *result, RegisterMissionCB *registerMissionCB)
784 {
785     napi_value callback = nullptr;
786     napi_value undefined = nullptr;
787     napi_get_undefined(registerMissionCB->cbBase.cbInfo.env, &undefined);
788     napi_value callResult = nullptr;
789     napi_get_reference_value(
790         registerMissionCB->cbBase.cbInfo.env, registerMissionCB->cbBase.cbInfo.callback, &callback);
791 
792     napi_call_function(registerMissionCB->cbBase.cbInfo.env, undefined, callback, ARGS_TWO, &result[0], &callResult);
793 }
794 
NotifySnapshot(const std::string & deviceId,int32_t missionId)795 void NAPIRemoteMissionListener::NotifySnapshot(const std::string& deviceId, int32_t missionId)
796 {
797     uv_loop_s *loop = nullptr;
798 
799     napi_get_uv_event_loop(env_, &loop);
800     if (loop == nullptr) {
801         HILOG_ERROR("%{public}s, loop == nullptr.", __func__);
802         return;
803     }
804 
805     uv_work_t *work = new uv_work_t;
806 
807     auto registerMissionCB = new (std::nothrow) RegisterMissionCB;
808     if (registerMissionCB == nullptr) {
809         HILOG_ERROR("%{public}s, registerMissionCB == nullptr.", __func__);
810         delete work;
811         return;
812     }
813     registerMissionCB->cbBase.cbInfo.env = env_;
814     registerMissionCB->cbBase.cbInfo.callback = notifySnapshotRef_;
815     registerMissionCB->deviceId = deviceId;
816     registerMissionCB->missionId = missionId;
817     work->data = static_cast<void *>(registerMissionCB);
818 
819     int rev = uv_queue_work(
820         loop, work, [](uv_work_t *work) {}, UvWorkNotifySnapshot);
821     if (rev != 0) {
822         delete registerMissionCB;
823         registerMissionCB = nullptr;
824         delete work;
825     }
826     HILOG_INFO("%{public}s, end.", __func__);
827 }
828 
UvWorkNotifyNetDisconnect(uv_work_t * work,int status)829 void UvWorkNotifyNetDisconnect(uv_work_t *work, int status)
830 {
831     HILOG_INFO("UvWorkNotifyNetDisconnect, uv_queue_work");
832     if (work == nullptr) {
833         HILOG_ERROR("UvWorkNotifyNetDisconnect, work is null");
834         return;
835     }
836     RegisterMissionCB *registerMissionCB = static_cast<RegisterMissionCB *>(work->data);
837     if (registerMissionCB == nullptr) {
838         HILOG_ERROR("UvWorkNotifyNetDisconnect, registerMissionCB is null");
839         delete work;
840         return;
841     }
842     napi_value result[2] = {nullptr};
843     result[0] =
844         WrapString(registerMissionCB->cbBase.cbInfo.env, registerMissionCB->deviceId.c_str(), "deviceId");
845     HILOG_INFO("UvWorkNotifyNetDisconnect, state = %{public}d", registerMissionCB->state);
846     result[1] =
847         WrapInt32(registerMissionCB->cbBase.cbInfo.env, registerMissionCB->state, "state");
848 
849     CallbackReturn(&result[0], registerMissionCB);
850     delete registerMissionCB;
851     registerMissionCB = nullptr;
852     delete work;
853     HILOG_INFO("UvWorkNotifyNetDisconnect, uv_queue_work end");
854 }
855 
NotifyNetDisconnect(const std::string & deviceId,int32_t state)856 void NAPIRemoteMissionListener::NotifyNetDisconnect(const std::string& deviceId, int32_t state)
857 {
858     HILOG_INFO("%{public}s called. state = %{public}d", __func__, state);
859     uv_loop_s *loop = nullptr;
860 
861     napi_get_uv_event_loop(env_, &loop);
862     if (loop == nullptr) {
863         HILOG_ERROR("%{public}s, loop == nullptr.", __func__);
864         return;
865     }
866 
867     uv_work_t *work = new uv_work_t;
868 
869     auto registerMissionCB = new (std::nothrow) RegisterMissionCB;
870     if (registerMissionCB == nullptr) {
871         HILOG_ERROR("%{public}s, registerMissionCB == nullptr.", __func__);
872         delete work;
873         return;
874     }
875     registerMissionCB->cbBase.cbInfo.env = env_;
876     registerMissionCB->cbBase.cbInfo.callback = notifyNetDisconnectRef_;
877     registerMissionCB->deviceId = deviceId;
878     registerMissionCB->state = state;
879     work->data = static_cast<void *>(registerMissionCB);
880 
881     int rev = uv_queue_work(
882         loop, work, [](uv_work_t *work) {}, UvWorkNotifyNetDisconnect);
883     if (rev != 0) {
884         delete registerMissionCB;
885         registerMissionCB = nullptr;
886         delete work;
887     }
888     HILOG_INFO("%{public}s, end.", __func__);
889 }
890 
UnRegisterMissionExecuteCB(napi_env env,void * data)891 void UnRegisterMissionExecuteCB(napi_env env, void *data)
892 {
893     HILOG_INFO("%{public}s called.", __func__);
894     auto registerMissionCB = (RegisterMissionCB*)data;
895 
896     std::lock_guard<std::mutex> autoLock(registrationLock_);
897     sptr<NAPIRemoteMissionListener> registration;
898     auto item = registration_.find(registerMissionCB->deviceId);
899     if (item != registration_.end()) {
900         HILOG_INFO("registration exits.");
901         registration = registration_[registerMissionCB->deviceId];
902     } else {
903         HILOG_INFO("registration not exits.");
904         registerMissionCB->result = -1;
905         return;
906     }
907     registerMissionCB->missionRegistration = registration;
908 
909     registerMissionCB->result =
910         AbilityManagerClient::GetInstance()->
911         UnRegisterMissionListener(registerMissionCB->deviceId,
912         registerMissionCB->missionRegistration);
913     if (registerMissionCB->result == NO_ERROR) {
914         HILOG_INFO("remove registration.");
915         registration_.erase(registerMissionCB->deviceId);
916     }
917     HILOG_DEBUG("%{public}s end.deviceId:%{public}d ", __func__, registerMissionCB->result);
918 }
919 
UnRegisterMissionPromiseCompletedCB(napi_env env,napi_status status,void * data)920 void UnRegisterMissionPromiseCompletedCB(napi_env env, napi_status status, void *data)
921 {
922     HILOG_INFO("%{public}s called.", __func__);
923     auto registerMissionCB = (RegisterMissionCB*)data;
924     // set result
925     napi_value result[2] = { nullptr };
926     napi_get_undefined(env, &result[1]);
927     if (registerMissionCB->result == 0) {
928         napi_get_undefined(env, &result[0]);
929     } else {
930         int32_t errCode = ErrorCodeReturn(registerMissionCB->result);
931         result[0] = GenerateBusinessError(env, errCode, ErrorInfoReturn(errCode));
932     }
933 
934     ReturnValueToApplication(env, &result[0], registerMissionCB);
935     delete registerMissionCB;
936     registerMissionCB = nullptr;
937     HILOG_INFO("%{public}s end.", __func__);
938 }
939 
UnRegisterMissionPromise(napi_env env,RegisterMissionCB * registerMissionCB)940 napi_value UnRegisterMissionPromise(napi_env env, RegisterMissionCB *registerMissionCB)
941 {
942     HILOG_INFO("%{public}s asyncCallback.", __func__);
943     if (registerMissionCB == nullptr) {
944         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
945         return nullptr;
946     }
947     napi_value promise = nullptr;
948     if (registerMissionCB->callbackRef == nullptr) {
949         napi_create_promise(env, &registerMissionCB->cbBase.deferred, &promise);
950     } else {
951         napi_get_undefined(env, &promise);
952     }
953 
954     napi_value resourceName = nullptr;
955     napi_create_string_latin1(env, __func__, NAPI_AUTO_LENGTH, &resourceName);
956 
957     napi_create_async_work(env,
958         nullptr,
959         resourceName,
960         UnRegisterMissionExecuteCB,
961         UnRegisterMissionPromiseCompletedCB,
962         static_cast<void *>(registerMissionCB),
963         &registerMissionCB->cbBase.asyncWork);
964     napi_queue_async_work(env, registerMissionCB->cbBase.asyncWork);
965     HILOG_INFO("%{public}s asyncCallback end.", __func__);
966     return promise;
967 }
968 
GetUnRegisterMissionDeviceId(napi_env env,const napi_value & value,RegisterMissionCB * registerMissionCB,std::string & errInfo)969 bool GetUnRegisterMissionDeviceId(napi_env env, const napi_value& value,
970     RegisterMissionCB *registerMissionCB, std::string &errInfo)
971 {
972     HILOG_INFO("%{public}s called.", __func__);
973     napi_value firstNApi = nullptr;
974     napi_valuetype valueType = napi_undefined;
975     bool isDeviceId = false;
976     napi_has_named_property(env, value, "deviceId", &isDeviceId);
977     napi_typeof(env, value, &valueType);
978     if (isDeviceId && valueType == napi_object) {
979         napi_get_named_property(env, value, "deviceId", &firstNApi);
980     } else {
981         errInfo = "Parameter error. The key of \"MissionDeviceInfo\" must be deviceId";
982         return false;
983     }
984     if (firstNApi == nullptr) {
985         errInfo = "Parameter error. The value of \"deviceId\" must not be undefined";
986         return false;
987     }
988 
989     size_t valueLen = 0;
990     napi_typeof(env, firstNApi, &valueType);
991     if (valueType != napi_string) {
992         errInfo = "Parameter error. The type of \"deviceId\" must be string";
993         return false;
994     }
995     char deviceId[VALUE_BUFFER_SIZE + 1] = {0};
996     napi_get_value_string_utf8(env, firstNApi, deviceId, VALUE_BUFFER_SIZE + 1, &valueLen);
997     if (valueLen > VALUE_BUFFER_SIZE) {
998         errInfo = "Parameter error. The length of \"deviceId\" must be less than " +
999             std::to_string(VALUE_BUFFER_SIZE);
1000         return false;
1001     }
1002     registerMissionCB->deviceId = deviceId;
1003     HILOG_INFO("%{public}s called end.", __func__);
1004     return true;
1005 }
1006 
UnRegisterMissionWrap(napi_env env,napi_callback_info info,RegisterMissionCB * registerMissionCB,std::string & errInfo)1007 napi_value UnRegisterMissionWrap(napi_env env, napi_callback_info info,
1008     RegisterMissionCB *registerMissionCB, std::string &errInfo)
1009 {
1010     HILOG_INFO("%{public}s called.", __func__);
1011     size_t argc = 2;
1012     napi_value args[ARGS_MAX_COUNT] = {nullptr};
1013     napi_value ret = nullptr;
1014 
1015     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
1016     HILOG_INFO("argc is %{public}zu", argc);
1017     if (argc != ARGS_ONE && argc != ARGS_TWO) {
1018         errInfo = "Parameter error. The type of \"number of parameters\" must be 1 or 2";
1019         return nullptr;
1020     }
1021 
1022     if (!GetUnRegisterMissionDeviceId(env, args[0], registerMissionCB, errInfo)) {
1023         HILOG_ERROR("%{public}s, Wrong argument.", __func__);
1024         return nullptr;
1025     }
1026 
1027     if (argc == ARGS_TWO) {
1028         napi_valuetype valueType = napi_undefined;
1029         napi_typeof(env, args[1], &valueType);
1030         if (valueType != napi_function) {
1031             errInfo = "Parameter error. The type of \"callback\" must be AsynCallback<void>: void";
1032             return nullptr;
1033         }
1034         napi_create_reference(env, args[1], 1, &registerMissionCB->callbackRef);
1035     }
1036     ret = UnRegisterMissionPromise(env, registerMissionCB);
1037     HILOG_INFO("%{public}s called end.", __func__);
1038     return ret;
1039 }
1040 
NAPI_UnRegisterMissionListener(napi_env env,napi_callback_info info)1041 napi_value NAPI_UnRegisterMissionListener(napi_env env, napi_callback_info info)
1042 {
1043     HILOG_INFO("%{public}s called.", __func__);
1044     std::string errInfo = "Parameter error";
1045     RegisterMissionCB *registerMissionCB = CreateRegisterMissionCBCBInfo(env);
1046     if (registerMissionCB == nullptr) {
1047         HILOG_ERROR("%{public}s registerMissionCB == nullptr", __func__);
1048         napi_throw(env, GenerateBusinessError(env, SYSTEM_WORK_ABNORMALLY, ErrorInfoReturn(SYSTEM_WORK_ABNORMALLY)));
1049         return GetUndefined(env);
1050     }
1051 
1052     napi_value ret = UnRegisterMissionWrap(env, info, registerMissionCB, errInfo);
1053     if (ret == nullptr) {
1054         HILOG_ERROR("%{public}s ret == nullptr", __func__);
1055         delete registerMissionCB;
1056         registerMissionCB = nullptr;
1057         napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
1058         return GetUndefined(env);
1059     }
1060     HILOG_INFO("%{public}s end.", __func__);
1061     return ret;
1062 }
1063 
WrapString(napi_env env,const std::string & param,const std::string & paramName)1064 napi_value WrapString(napi_env env, const std::string &param, const std::string &paramName)
1065 {
1066     HILOG_INFO("%{public}s called.", __func__);
1067 
1068     napi_value jsObject = nullptr;
1069     napi_create_object(env, &jsObject);
1070 
1071     napi_value jsValue = nullptr;
1072     HILOG_DEBUG("%{public}s called. %{public}s = %{public}s", __func__, paramName.c_str(), param.c_str());
1073     napi_create_string_utf8(env, param.c_str(), NAPI_AUTO_LENGTH, &jsValue);
1074     napi_set_named_property(env, jsObject, paramName.c_str(), jsValue);
1075 
1076     return jsObject;
1077 }
1078 
WrapInt32(napi_env env,int32_t num,const std::string & paramName)1079 napi_value WrapInt32(napi_env env, int32_t num, const std::string &paramName)
1080 {
1081     HILOG_INFO("%{public}s called.", __func__);
1082 
1083     napi_value jsObject = nullptr;
1084     napi_create_object(env, &jsObject);
1085 
1086     napi_value jsValue = nullptr;
1087     HILOG_DEBUG("%{public}s called. %{public}s = %{public}d", __func__, paramName.c_str(), num);
1088     napi_create_int32(env, num, &jsValue);
1089     napi_set_named_property(env, jsObject, paramName.c_str(), jsValue);
1090 
1091     return jsObject;
1092 }
1093 
CreateContinueAbilityCBCBInfo(napi_env env)1094 ContinueAbilityCB *CreateContinueAbilityCBCBInfo(napi_env env)
1095 {
1096     HILOG_INFO("%{public}s called.", __func__);
1097     auto continueAbilityCB = new (std::nothrow) ContinueAbilityCB;
1098     if (continueAbilityCB == nullptr) {
1099         HILOG_ERROR("%{public}s continueAbilityCB == nullptr", __func__);
1100         return nullptr;
1101     }
1102     continueAbilityCB->cbBase.cbInfo.env = env;
1103     continueAbilityCB->cbBase.asyncWork = nullptr;
1104     continueAbilityCB->cbBase.deferred = nullptr;
1105     continueAbilityCB->callbackRef = nullptr;
1106     HILOG_INFO("%{public}s end.", __func__);
1107     return continueAbilityCB;
1108 }
1109 
ContinueAbilityExecuteCB(napi_env env,void * data)1110 void ContinueAbilityExecuteCB(napi_env env, void *data)
1111 {
1112     HILOG_INFO("%{public}s called.", __func__);
1113     auto continueAbilityCB = static_cast<ContinueAbilityCB *>(data);
1114     HILOG_INFO("create continueAbilityCB success.");
1115     sptr<NAPIMissionContinue> continuation(new (std::nothrow) NAPIMissionContinue());
1116     continueAbilityCB->abilityContinuation = continuation;
1117     if (continueAbilityCB->abilityContinuation == nullptr) {
1118         HILOG_ERROR("%{public}s abilityContinuation == nullptr.", __func__);
1119         return;
1120     }
1121     continueAbilityCB->abilityContinuation->SetContinueAbilityEnv(env);
1122     HILOG_INFO("set env success.");
1123     continueAbilityCB->abilityContinuation->
1124         SetContinueAbilityCBRef(continueAbilityCB->abilityContinuationCB.callback[0]);
1125     HILOG_INFO("set callback success.");
1126     continueAbilityCB->result = -1;
1127     continueAbilityCB->result = AAFwk::AbilityManagerClient::GetInstance()->
1128         ContinueMission(continueAbilityCB->srcDeviceId, continueAbilityCB->dstDeviceId,
1129         continueAbilityCB->missionId, continueAbilityCB->abilityContinuation,
1130         continueAbilityCB->wantParams);
1131     HILOG_INFO("%{public}s end. error:%{public}d ", __func__, continueAbilityCB->result);
1132 }
1133 
ContinueAbilityCallbackCompletedCB(napi_env env,napi_status status,void * data)1134 void ContinueAbilityCallbackCompletedCB(napi_env env, napi_status status, void *data)
1135 {
1136     HILOG_INFO("%{public}s called.", __func__);
1137     auto continueAbilityCB = static_cast<ContinueAbilityCB *>(data);
1138     // set result
1139     napi_value result[2] = { nullptr };
1140     napi_get_undefined(env, &result[1]);
1141     if (continueAbilityCB->result == 0) {
1142         napi_get_undefined(env, &result[0]);
1143     } else {
1144         int32_t errCode = ErrorCodeReturn(continueAbilityCB->result);
1145         result[0] = GenerateBusinessError(env, errCode, ErrorInfoReturn(errCode));
1146     }
1147 
1148     if (continueAbilityCB->callbackRef == nullptr) { // promise
1149         if (continueAbilityCB->result == 0) {
1150             napi_resolve_deferred(env, continueAbilityCB->cbBase.deferred, result[1]);
1151         } else {
1152             napi_reject_deferred(env, continueAbilityCB->cbBase.deferred, result[0]);
1153         }
1154     } else { // AsyncCallback
1155         napi_value callback = nullptr;
1156         napi_get_reference_value(env, continueAbilityCB->callbackRef, &callback);
1157         napi_value callResult;
1158         napi_call_function(env, nullptr, callback, ARGS_TWO, &result[0], &callResult);
1159         napi_delete_reference(env, continueAbilityCB->callbackRef);
1160     }
1161     napi_delete_async_work(env, continueAbilityCB->cbBase.asyncWork);
1162     delete continueAbilityCB;
1163     continueAbilityCB = nullptr;
1164     HILOG_INFO("%{public}s end.", __func__);
1165 }
1166 
ContinueAbilityAsync(napi_env env,ContinueAbilityCB * continueAbilityCB)1167 napi_value ContinueAbilityAsync(napi_env env, ContinueAbilityCB *continueAbilityCB)
1168 {
1169     HILOG_INFO("%{public}s asyncCallback.", __func__);
1170     if (continueAbilityCB == nullptr) {
1171         HILOG_ERROR("%{public}s, param == nullptr.", __func__);
1172         return nullptr;
1173     }
1174 
1175     napi_value result = nullptr;
1176     if (continueAbilityCB->callbackRef == nullptr) {
1177         napi_create_promise(env, &continueAbilityCB->cbBase.deferred, &result);
1178     } else {
1179         napi_get_undefined(env, &result);
1180     }
1181 
1182     napi_value resourceName = nullptr;
1183     napi_create_string_latin1(env, "ContinueAbilityAsyncForLauncher", NAPI_AUTO_LENGTH, &resourceName);
1184 
1185     napi_create_async_work(env,
1186         nullptr,
1187         resourceName,
1188         ContinueAbilityExecuteCB,
1189         ContinueAbilityCallbackCompletedCB,
1190         static_cast<void *>(continueAbilityCB),
1191         &continueAbilityCB->cbBase.asyncWork);
1192     napi_queue_async_work(env, continueAbilityCB->cbBase.asyncWork);
1193     HILOG_INFO("%{public}s asyncCallback end.", __func__);
1194     return result;
1195 }
1196 
CheckContinueKeyExist(napi_env env,const napi_value & value)1197 bool CheckContinueKeyExist(napi_env env, const napi_value &value)
1198 {
1199     bool isSrcDeviceId = false;
1200     napi_has_named_property(env, value, "srcDeviceId", &isSrcDeviceId);
1201     bool isDstDeviceId = false;
1202     napi_has_named_property(env, value, "dstDeviceId", &isDstDeviceId);
1203     bool isMissionId = false;
1204     napi_has_named_property(env, value, "missionId", &isMissionId);
1205     bool isWantParam = false;
1206     napi_has_named_property(env, value, "wantParam", &isWantParam);
1207     if (!isSrcDeviceId && !isDstDeviceId && !isMissionId && !isWantParam) {
1208         HILOG_ERROR("%{public}s, Wrong argument key.", __func__);
1209         return false;
1210     }
1211     return true;
1212 }
1213 
CheckContinueFirstArgs(napi_env env,const napi_value & value,ContinueAbilityCB * continueAbilityCB,std::string & errInfo)1214 bool CheckContinueFirstArgs(napi_env env, const napi_value &value,
1215     ContinueAbilityCB *continueAbilityCB, std::string &errInfo)
1216 {
1217     HILOG_INFO("%{public}s called.", __func__);
1218     if (!CheckContinueKeyExist(env, value)) {
1219         errInfo = "Parameter error. The type of \"parameter\" must be ContinueMission";
1220         return false;
1221     }
1222     napi_value firstNApi = nullptr;
1223     napi_value secondNApi = nullptr;
1224     napi_value thirdNApi = nullptr;
1225     napi_value fourthNApi = nullptr;
1226     napi_valuetype valueType = napi_undefined;
1227     napi_typeof(env, value, &valueType);
1228     if (valueType != napi_object) {
1229         errInfo = "Parameter error. The type of \"parameter\" must be ContinueMission";
1230         return false;
1231     }
1232     napi_get_named_property(env, value, "srcDeviceId", &firstNApi);
1233     napi_get_named_property(env, value, "dstDeviceId", &secondNApi);
1234     napi_get_named_property(env, value, "missionId", &thirdNApi);
1235     napi_get_named_property(env, value, "wantParam", &fourthNApi);
1236     if (firstNApi == nullptr || secondNApi == nullptr || thirdNApi == nullptr || fourthNApi == nullptr) {
1237         errInfo = "Parameter error. The number of \"ContinueMission\" must be 4";
1238         return false;
1239     }
1240     napi_typeof(env, firstNApi, &valueType);
1241     if (valueType != napi_string) {
1242         errInfo = "Parameter error. The type of \"srcDeviceId\" must be string";
1243         return false;
1244     }
1245     continueAbilityCB->srcDeviceId = AppExecFwk::UnwrapStringFromJS(env, firstNApi, "");
1246     napi_typeof(env, secondNApi, &valueType);
1247     if (valueType != napi_string) {
1248         errInfo = "Parameter error. The type of \"dstDeviceId\" must be string";
1249         return false;
1250     }
1251     continueAbilityCB->dstDeviceId = AppExecFwk::UnwrapStringFromJS(env, secondNApi, "");
1252     napi_typeof(env, thirdNApi, &valueType);
1253     if (valueType != napi_number) {
1254         errInfo = "Parameter error. The type of \"missionId\" must be number";
1255         return false;
1256     }
1257     continueAbilityCB->missionId = AppExecFwk::UnwrapInt32FromJS(env, thirdNApi, -1);
1258     napi_typeof(env, fourthNApi, &valueType);
1259     if (valueType != napi_object) {
1260         errInfo = "Parameter error. The type of \"wantParams\" must be object";
1261         return false;
1262     }
1263     if (!AppExecFwk::UnwrapWantParams(env, fourthNApi, continueAbilityCB->wantParams)) {
1264         errInfo = "Parameter error. The type of \"wantParams\" must be array";
1265         return false;
1266     }
1267     HILOG_INFO("%{public}s called end.", __func__);
1268     return true;
1269 }
1270 
CheckContinueCallback(napi_env env,const napi_value & value,ContinueAbilityCB * continueAbilityCB,std::string & errInfo)1271 bool CheckContinueCallback(napi_env env, const napi_value &value,
1272     ContinueAbilityCB *continueAbilityCB, std::string &errInfo)
1273 {
1274     HILOG_INFO("%{public}s called.", __func__);
1275     napi_value jsMethod = nullptr;
1276     napi_valuetype valuetype = napi_undefined;
1277     napi_typeof(env, value, &valuetype);
1278     if (valuetype != napi_object) {
1279         errInfo = "Parameter error. The type of \"options\" must be ContinueCallback";
1280         return false;
1281     }
1282     bool isFirstCallback = false;
1283     napi_has_named_property(env, value, "onContinueDone", &isFirstCallback);
1284     if (!isFirstCallback) {
1285         errInfo = "Parameter error. The key of \"ContinueCallback\" must be onContinueDone";
1286         return false;
1287     }
1288     napi_get_named_property(env, value, "onContinueDone", &jsMethod);
1289     if (jsMethod == nullptr) {
1290         errInfo = "Parameter error. The value of \"onContinueDone\" must not be undefined";
1291         return false;
1292     }
1293     napi_typeof(env, jsMethod, &valuetype);
1294     if (valuetype != napi_function) {
1295         errInfo = "Parameter error. The type of \"onContinueDone\" must be function";
1296         return false;
1297     }
1298     napi_create_reference(env, jsMethod, 1, &continueAbilityCB->abilityContinuationCB.callback[0]);
1299     HILOG_INFO("%{public}s called end.", __func__);
1300     return true;
1301 }
1302 
ContinueAbilityWrap(napi_env env,napi_callback_info info,ContinueAbilityCB * continueAbilityCB,std::string & errInfo)1303 napi_value ContinueAbilityWrap(napi_env env, napi_callback_info info,
1304     ContinueAbilityCB *continueAbilityCB, std::string &errInfo)
1305 {
1306     HILOG_INFO("%{public}s called.", __func__);
1307     size_t argcAsync = 3;
1308     napi_value args[ARGS_MAX_COUNT] = {nullptr};
1309     napi_value ret = nullptr;
1310 
1311     napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr);
1312     HILOG_INFO("argcAsync is %{public}zu", argcAsync);
1313     if (argcAsync != ARGS_TWO && argcAsync != ARGS_THREE) {
1314         errInfo = "Parameter error. The type of \"number of parameters\" must be 2 or 3";
1315         return nullptr;
1316     }
1317 
1318     if (!CheckContinueFirstArgs(env, args[0], continueAbilityCB, errInfo)) {
1319         HILOG_ERROR("%{public}s, check the first argument failed.", __func__);
1320         return nullptr;
1321     }
1322 
1323     if (argcAsync > 1) {
1324         if (!CheckContinueCallback(env, args[1], continueAbilityCB, errInfo)) {
1325             HILOG_ERROR("%{public}s, check callback failed.", __func__);
1326             return nullptr;
1327         }
1328     }
1329 
1330     if (argcAsync == ARGS_THREE) {
1331         napi_valuetype valueType = napi_undefined;
1332         napi_typeof(env, args[ARGS_TWO], &valueType);
1333         if (valueType != napi_function) {
1334             errInfo = "Parameter error. The type of \"callback\" must be AsynCallback<void>: void";
1335             return nullptr;
1336         }
1337         napi_create_reference(env, args[ARGS_TWO], 1, &continueAbilityCB->callbackRef);
1338     }
1339 
1340     ret = ContinueAbilityAsync(env, continueAbilityCB);
1341     HILOG_INFO("%{public}s called end.", __func__);
1342     return ret;
1343 }
1344 
NAPI_ContinueAbility(napi_env env,napi_callback_info info)1345 napi_value NAPI_ContinueAbility(napi_env env, napi_callback_info info)
1346 {
1347     HILOG_INFO("%{public}s called.", __func__);
1348     std::string errInfo = "Parameter error";
1349     ContinueAbilityCB *continueAbilityCB = CreateContinueAbilityCBCBInfo(env);
1350     if (continueAbilityCB == nullptr) {
1351         HILOG_ERROR("%{public}s continueAbilityCB == nullptr", __func__);
1352         napi_throw(env, GenerateBusinessError(env, SYSTEM_WORK_ABNORMALLY, ErrorInfoReturn(SYSTEM_WORK_ABNORMALLY)));
1353         return GetUndefined(env);
1354     }
1355 
1356     napi_value ret = ContinueAbilityWrap(env, info, continueAbilityCB, errInfo);
1357     if (ret == nullptr) {
1358         HILOG_ERROR("%{public}s ret == nullptr", __func__);
1359         delete continueAbilityCB;
1360         continueAbilityCB = nullptr;
1361         napi_throw(env, GenerateBusinessError(env, PARAMETER_CHECK_FAILED, errInfo));
1362         return GetUndefined(env);
1363     }
1364     HILOG_INFO("%{public}s end.", __func__);
1365     return ret;
1366 }
1367 
UvWorkOnContinueDone(uv_work_t * work,int status)1368 void UvWorkOnContinueDone(uv_work_t *work, int status)
1369 {
1370     HILOG_INFO("UvWorkOnContinueDone, uv_queue_work");
1371     if (work == nullptr) {
1372         HILOG_ERROR("UvWorkOnContinueDone, work is null");
1373         return;
1374     }
1375     ContinueAbilityCB *continueAbilityCB = static_cast<ContinueAbilityCB *>(work->data);
1376     if (continueAbilityCB == nullptr) {
1377         HILOG_ERROR("UvWorkOnContinueDone, continueAbilityCB is null");
1378         delete work;
1379         return;
1380     }
1381     napi_value result = nullptr;
1382     HILOG_INFO("UvWorkOnContinueDone, resultCode = %{public}d", continueAbilityCB->resultCode);
1383     result =
1384         WrapInt32(continueAbilityCB->cbBase.cbInfo.env, continueAbilityCB->resultCode, "resultCode");
1385 
1386     napi_value callback = nullptr;
1387     napi_value undefined = nullptr;
1388     napi_get_undefined(continueAbilityCB->cbBase.cbInfo.env, &undefined);
1389     napi_value callResult = nullptr;
1390     napi_get_reference_value(continueAbilityCB->cbBase.cbInfo.env,
1391         continueAbilityCB->cbBase.cbInfo.callback, &callback);
1392 
1393     napi_call_function(continueAbilityCB->cbBase.cbInfo.env, undefined, callback, 1, &result, &callResult);
1394     if (continueAbilityCB->cbBase.cbInfo.callback != nullptr) {
1395         napi_delete_reference(continueAbilityCB->cbBase.cbInfo.env, continueAbilityCB->cbBase.cbInfo.callback);
1396     }
1397     delete continueAbilityCB;
1398     continueAbilityCB = nullptr;
1399     delete work;
1400     HILOG_INFO("UvWorkOnContinueDone, uv_queue_work end");
1401 }
1402 
OnContinueDone(int32_t result)1403 void NAPIMissionContinue::OnContinueDone(int32_t result)
1404 {
1405     HILOG_INFO("%{public}s, called. result = %{public}d", __func__, result);
1406     uv_loop_s *loop = nullptr;
1407 
1408     napi_get_uv_event_loop(env_, &loop);
1409     if (loop == nullptr) {
1410         HILOG_ERROR("%{public}s, loop == nullptr.", __func__);
1411         return;
1412     }
1413 
1414     uv_work_t *work = new uv_work_t;
1415 
1416     auto continueAbilityCB = new (std::nothrow) ContinueAbilityCB;
1417     if (continueAbilityCB == nullptr) {
1418         HILOG_ERROR("%{public}s, continueAbilityCB == nullptr.", __func__);
1419         delete work;
1420         return;
1421     }
1422     continueAbilityCB->cbBase.cbInfo.env = env_;
1423     continueAbilityCB->cbBase.cbInfo.callback = onContinueDoneRef_;
1424     continueAbilityCB->resultCode = result;
1425     work->data = static_cast<void *>(continueAbilityCB);
1426 
1427     int rev = uv_queue_work(
1428         loop, work, [](uv_work_t *work) {}, UvWorkOnContinueDone);
1429     if (rev != 0) {
1430         delete continueAbilityCB;
1431         continueAbilityCB = nullptr;
1432         delete work;
1433     }
1434     HILOG_INFO("%{public}s, end.", __func__);
1435 }
1436 
SetContinueAbilityEnv(const napi_env & env)1437 void NAPIMissionContinue::SetContinueAbilityEnv(const napi_env &env)
1438 {
1439     env_ = env;
1440 }
1441 
SetContinueAbilityCBRef(const napi_ref & ref)1442 void NAPIMissionContinue::SetContinueAbilityCBRef(const napi_ref &ref)
1443 {
1444     onContinueDoneRef_ = ref;
1445 }
1446 
DistributedMissionManagerExport(napi_env env,napi_value exports)1447 napi_value DistributedMissionManagerExport(napi_env env, napi_value exports)
1448 {
1449     HILOG_INFO("%{public}s,called", __func__);
1450     napi_property_descriptor properties[] = {
1451         DECLARE_NAPI_FUNCTION("startSyncRemoteMissions", NAPI_StartSyncRemoteMissions),
1452         DECLARE_NAPI_FUNCTION("stopSyncRemoteMissions", NAPI_StopSyncRemoteMissions),
1453         DECLARE_NAPI_FUNCTION("registerMissionListener", NAPI_RegisterMissionListener),
1454         DECLARE_NAPI_FUNCTION("unRegisterMissionListener", NAPI_UnRegisterMissionListener),
1455         DECLARE_NAPI_FUNCTION("continueMission", NAPI_ContinueAbility),
1456     };
1457     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
1458     return exports;
1459 }
1460 
1461 static napi_module missionModule = {
1462     .nm_version = 1,
1463     .nm_flags = 0,
1464     .nm_filename = nullptr,
1465     .nm_register_func = DistributedMissionManagerExport,
1466     .nm_modname = "distributedMissionManager",
1467     .nm_priv = ((void*)nullptr),
1468     .reserved = {nullptr}
1469 };
1470 
AbilityRegister()1471 extern "C" __attribute__((constructor)) void AbilityRegister()
1472 {
1473     napi_module_register(&missionModule);
1474 }
1475 }
1476 }
1477