1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_coordination_context.h"
17 
18 #include "devicestatus_define.h"
19 #include "napi_constants.h"
20 #include "util_napi_error.h"
21 #include "utility.h"
22 
23 #undef LOG_TAG
24 #define LOG_TAG "JsCoordinationContext"
25 
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
29 namespace {
30 const char* COORDINATION_CLASS { "Coordination_class" };
31 const char* COORDINATION { "Coordination" };
32 inline constexpr std::string_view GET_VALUE_BOOL { "napi_get_value_bool" };
33 inline constexpr std::string_view GET_VALUE_INT32 { "napi_get_value_int32" };
34 inline constexpr std::string_view GET_VALUE_STRING_UTF8 { "napi_get_value_string_utf8" };
35 inline constexpr size_t MAX_STRING_LEN { 1024 };
36 } // namespace
37 
JsCoordinationContext()38 JsCoordinationContext::JsCoordinationContext()
39     : mgr_(std::make_shared<JsCoordinationManager>()) {}
40 
~JsCoordinationContext()41 JsCoordinationContext::~JsCoordinationContext()
42 {
43     std::lock_guard<std::mutex> guard(mutex_);
44     auto jsCoordinationMgr = mgr_;
45     mgr_.reset();
46     if (jsCoordinationMgr != nullptr) {
47         jsCoordinationMgr->ResetEnv();
48     }
49 }
50 
Export(napi_env env,napi_value exports)51 napi_value JsCoordinationContext::Export(napi_env env, napi_value exports)
52 {
53     CALL_INFO_TRACE;
54     auto instance = CreateInstance(env);
55     CHKPP(instance);
56     DeclareDeviceCoordinationInterface(env, exports);
57     DeclareDeviceCoordinationData(env, exports);
58     DeclareDeviceCooperateData(env, exports);
59     return exports;
60 }
61 
Prepare(napi_env env,napi_callback_info info)62 napi_value JsCoordinationContext::Prepare(napi_env env, napi_callback_info info)
63 {
64     CALL_INFO_TRACE;
65     return PrepareCompatible(env, info);
66 }
67 
PrepareCooperate(napi_env env,napi_callback_info info)68 napi_value JsCoordinationContext::PrepareCooperate(napi_env env, napi_callback_info info)
69 {
70     CALL_INFO_TRACE;
71     return PrepareCompatible(env, info, true);
72 }
73 
PrepareCompatible(napi_env env,napi_callback_info info,bool isCompatible)74 napi_value JsCoordinationContext::PrepareCompatible(napi_env env, napi_callback_info info, bool isCompatible)
75 {
76     size_t argc = 1;
77     napi_value argv[1] = { nullptr };
78     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
79 
80     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
81     CHKPP(jsDev);
82     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
83     CHKPP(jsCoordinationMgr);
84     if (argc == 0) {
85         return jsCoordinationMgr->Prepare(env, isCompatible);
86     }
87     if (!UtilNapi::TypeOf(env, argv[0], napi_function)) {
88         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
89         return nullptr;
90     }
91     return jsCoordinationMgr->Prepare(env, isCompatible, argv[0]);
92 }
93 
Unprepare(napi_env env,napi_callback_info info)94 napi_value JsCoordinationContext::Unprepare(napi_env env, napi_callback_info info)
95 {
96     CALL_INFO_TRACE;
97     return UnprepareCompatible(env, info);
98 }
99 
UnprepareCooperate(napi_env env,napi_callback_info info)100 napi_value JsCoordinationContext::UnprepareCooperate(napi_env env, napi_callback_info info)
101 {
102     CALL_INFO_TRACE;
103     return UnprepareCompatible(env, info, true);
104 }
105 
UnprepareCompatible(napi_env env,napi_callback_info info,bool isCompatible)106 napi_value JsCoordinationContext::UnprepareCompatible(napi_env env, napi_callback_info info, bool isCompatible)
107 {
108     size_t argc = 1;
109     napi_value argv[1] = { nullptr };
110     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
111 
112     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
113     CHKPP(jsDev);
114     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
115     CHKPP(jsCoordinationMgr);
116     if (argc == 0) {
117         return jsCoordinationMgr->Unprepare(env, isCompatible);
118     }
119     if (!UtilNapi::TypeOf(env, argv[0], napi_function)) {
120         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
121         return nullptr;
122     }
123     return jsCoordinationMgr->Unprepare(env, isCompatible, argv[0]);
124 }
125 
Activate(napi_env env,napi_callback_info info)126 napi_value JsCoordinationContext::Activate(napi_env env, napi_callback_info info)
127 {
128     CALL_INFO_TRACE;
129     return ActivateCompatible(env, info);
130 }
131 
ActivateCooperate(napi_env env,napi_callback_info info)132 napi_value JsCoordinationContext::ActivateCooperate(napi_env env, napi_callback_info info)
133 {
134     CALL_INFO_TRACE;
135     return ActivateCompatible(env, info, true);
136 }
137 
ActivateCompatible(napi_env env,napi_callback_info info,bool isCompatible)138 napi_value JsCoordinationContext::ActivateCompatible(napi_env env, napi_callback_info info, bool isCompatible)
139 {
140     size_t argc = 3;
141     napi_value argv[3] = { nullptr };
142     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
143 
144     if (argc < 2) {
145         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
146         return nullptr;
147     }
148     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
149         THROWERR(env, COMMON_PARAMETER_ERROR, "targetNetworkId", "string");
150         return nullptr;
151     }
152     if (!UtilNapi::TypeOf(env, argv[1], napi_number)) {
153         THROWERR(env, COMMON_PARAMETER_ERROR, "inputDeviceId", "number");
154         return nullptr;
155     }
156     char remoteNetworkId[MAX_STRING_LEN] = { 0 };
157     int32_t startDeviceId = 0;
158     size_t length = 0;
159     CHKRP(napi_get_value_string_utf8(env, argv[0], remoteNetworkId,
160         sizeof(remoteNetworkId), &length), GET_VALUE_STRING_UTF8);
161     CHKRP(napi_get_value_int32(env, argv[1], &startDeviceId), GET_VALUE_INT32);
162 
163     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
164     CHKPP(jsDev);
165     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
166     CHKPP(jsCoordinationMgr);
167     if (argc == 2) {
168         return jsCoordinationMgr->Activate(env, remoteNetworkId, startDeviceId, isCompatible);
169     }
170     if (!UtilNapi::TypeOf(env, argv[2], napi_function)) {
171         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
172         return nullptr;
173     }
174     return jsCoordinationMgr->Activate(env, std::string(remoteNetworkId), startDeviceId, isCompatible, argv[2]);
175 }
176 
Deactivate(napi_env env,napi_callback_info info)177 napi_value JsCoordinationContext::Deactivate(napi_env env, napi_callback_info info)
178 {
179     CALL_INFO_TRACE;
180     return DeactivateCompatible(env, info);
181 }
182 
DeactivateCooperate(napi_env env,napi_callback_info info)183 napi_value JsCoordinationContext::DeactivateCooperate(napi_env env, napi_callback_info info)
184 {
185     CALL_INFO_TRACE;
186     return DeactivateCompatible(env, info, true);
187 }
188 
DeactivateCompatible(napi_env env,napi_callback_info info,bool isCompatible)189 napi_value JsCoordinationContext::DeactivateCompatible(napi_env env, napi_callback_info info, bool isCompatible)
190 {
191     size_t argc = 2;
192     napi_value argv[2] = { nullptr };
193     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
194 
195     if (argc == 0) {
196         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
197         return nullptr;
198     }
199     if (!UtilNapi::TypeOf(env, argv[0], napi_boolean)) {
200         THROWERR(env, COMMON_PARAMETER_ERROR, "isUnchained", "boolean");
201         return nullptr;
202     }
203     bool isUnchained = false;
204     CHKRP(napi_get_value_bool(env, argv[0], &isUnchained), GET_VALUE_BOOL);
205 
206     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
207     CHKPP(jsDev);
208     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
209     CHKPP(jsCoordinationMgr);
210     if (argc == 1) {
211         return jsCoordinationMgr->Deactivate(env, isUnchained, isCompatible);
212     }
213     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
214         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
215         return nullptr;
216     }
217     return jsCoordinationMgr->Deactivate(env, isUnchained, isCompatible, argv[1]);
218 }
219 
GetCrossingSwitchState(napi_env env,napi_callback_info info)220 napi_value JsCoordinationContext::GetCrossingSwitchState(napi_env env, napi_callback_info info)
221 {
222     CALL_INFO_TRACE;
223     return GetCrossingSwitchStateCompatible(env, info);
224 }
225 
GetCooperateSwitchState(napi_env env,napi_callback_info info)226 napi_value JsCoordinationContext::GetCooperateSwitchState(napi_env env, napi_callback_info info)
227 {
228     CALL_INFO_TRACE;
229     return GetCrossingSwitchStateCompatible(env, info, true);
230 }
231 
GetCrossingSwitchStateCompatible(napi_env env,napi_callback_info info,bool isCompatible)232 napi_value JsCoordinationContext::GetCrossingSwitchStateCompatible(napi_env env,
233     napi_callback_info info, bool isCompatible)
234 {
235     size_t argc = 2;
236     napi_value argv[2] = { nullptr };
237     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
238 
239     if (argc == 0) {
240         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Incorrect parameter count");
241         return nullptr;
242     }
243     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
244         THROWERR(env, COMMON_PARAMETER_ERROR, "networkId", "string");
245         return nullptr;
246     }
247     char networkId[MAX_STRING_LEN] = { 0 };
248     size_t length = 0;
249     CHKRP(napi_get_value_string_utf8(env, argv[0], networkId,
250         sizeof(networkId), &length), GET_VALUE_STRING_UTF8);
251     std::string networkIdTemp = networkId;
252 
253     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
254     CHKPP(jsDev);
255     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
256     CHKPP(jsCoordinationMgr);
257     if (argc == 1) {
258         return jsCoordinationMgr->GetCrossingSwitchState(env, networkIdTemp, isCompatible);
259     }
260     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
261         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
262         return nullptr;
263     }
264     return jsCoordinationMgr->GetCrossingSwitchState(env, networkIdTemp, isCompatible, argv[1]);
265 }
266 
On(napi_env env,napi_callback_info info)267 napi_value JsCoordinationContext::On(napi_env env, napi_callback_info info)
268 {
269     CALL_INFO_TRACE;
270     size_t argc = 1;
271     napi_value argv[1] = { nullptr };
272     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
273 
274     if (argc < 1) {
275         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter mismatch error");
276         return nullptr;
277     }
278     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
279         THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
280         return nullptr;
281     }
282 
283     char type[MAX_STRING_LEN] = { 0 };
284     size_t length = 0;
285     CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_VALUE_STRING_UTF8);
286 
287     if ((COOPERATE_NAME.compare(type)) == 0 || (COOPERATE_MESSAGE_NAME.compare(type)) == 0) {
288         return RegisterCooperateListener(env, type, info);
289     }
290     if ((COOPERATE_MOUSE_NAME.compare(type)) == 0) {
291         return RegisterMouseListener(env, info);
292     }
293     FI_HILOGE("Unknow type:%{public}s", std::string(type).c_str());
294     THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be cooperate, cooperateMessage or cooperateMouse");
295     return nullptr;
296 }
297 
Off(napi_env env,napi_callback_info info)298 napi_value JsCoordinationContext::Off(napi_env env, napi_callback_info info)
299 {
300     CALL_INFO_TRACE;
301     napi_value argv[1] = { nullptr };
302     size_t argc = 1;
303     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
304     if (argc < 1) {
305         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
306         return nullptr;
307     }
308     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
309         THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
310         return nullptr;
311     }
312     size_t length = 0;
313     char type[MAX_STRING_LEN] = { 0 };
314     CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_VALUE_STRING_UTF8);
315 
316     if ((COOPERATE_NAME.compare(type)) == 0 || (COOPERATE_MESSAGE_NAME.compare(type)) == 0) {
317         return UnregisterCooperateListener(env, type, info);
318     }
319     if ((COOPERATE_MOUSE_NAME.compare(type)) == 0) {
320         return UnregisterMouseListener(env, info);
321     }
322     FI_HILOGE("Unknow type:%{public}s", std::string(type).c_str());
323     THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be cooperate, cooperateMessage or cooperateMouse");
324     return nullptr;
325 }
326 
RegisterCooperateListener(napi_env env,const std::string & type,napi_callback_info info)327 napi_value JsCoordinationContext::RegisterCooperateListener(
328     napi_env env, const std::string &type, napi_callback_info info)
329 {
330     CALL_INFO_TRACE;
331     size_t argc = 2;
332     napi_value argv[2] = { nullptr };
333     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
334     if (argc < 2) {
335         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
336         return nullptr;
337     }
338     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
339     CHKPP(jsDev);
340     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
341     CHKPP(jsCoordinationMgr);
342     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
343         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
344         return nullptr;
345     }
346     jsCoordinationMgr->RegisterListener(env, type, argv[1]);
347     return nullptr;
348 }
349 
UnregisterCooperateListener(napi_env env,const std::string & type,napi_callback_info info)350 napi_value JsCoordinationContext::UnregisterCooperateListener(
351     napi_env env, const std::string &type, napi_callback_info info)
352 {
353     CALL_INFO_TRACE;
354     size_t argc = 2;
355     napi_value argv[2] = { nullptr };
356     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
357     if (argc < 1) {
358         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
359         return nullptr;
360     }
361     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
362     CHKPP(jsDev);
363     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
364     CHKPP(jsCoordinationMgr);
365     if (argc < 2) {
366         jsCoordinationMgr->UnregisterListener(env, type);
367         return nullptr;
368     }
369     if (UtilNapi::TypeOf(env, argv[1], napi_undefined) || UtilNapi::TypeOf(env, argv[1], napi_null)) {
370         FI_HILOGW("Undefined callback, unregister all listener of type:%{public}s", type.c_str());
371         jsCoordinationMgr->UnregisterListener(env, type);
372         return nullptr;
373     }
374     if (UtilNapi::TypeOf(env, argv[1], napi_function)) {
375         jsCoordinationMgr->UnregisterListener(env, type, argv[1]);
376         return nullptr;
377     }
378     THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
379     FI_HILOGE("UnregisterCooperateListener failed, invalid parameter");
380     return nullptr;
381 }
382 
RegisterMouseListener(napi_env env,napi_callback_info info)383 napi_value JsCoordinationContext::RegisterMouseListener(napi_env env, napi_callback_info info)
384 {
385     CALL_INFO_TRACE;
386     size_t argc = 3;
387     napi_value argv[3] = { nullptr };
388     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
389     if (argc < 3) {
390         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
391         return nullptr;
392     }
393     char type[MAX_STRING_LEN] = { 0 };
394     size_t length = 0;
395     CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_VALUE_STRING_UTF8);
396     if ((COOPERATE_MOUSE_NAME.compare(type)) != 0) {
397         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be cooperateMouse");
398         return nullptr;
399     }
400 
401     char networkId[MAX_STRING_LEN] = { 0 };
402     size_t len = 0;
403     CHKRP(napi_get_value_string_utf8(env, argv[1], networkId, sizeof(networkId), &len), GET_VALUE_STRING_UTF8);
404 
405     if (!UtilNapi::TypeOf(env, argv[2], napi_function)) {
406         THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
407         return nullptr;
408     }
409 
410     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
411     CHKPP(jsDev);
412     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
413     CHKPP(jsCoordinationMgr);
414     jsCoordinationMgr->RegisterListener(env, type, networkId, argv[2]);
415     return nullptr;
416 }
417 
UnregisterMouseListener(napi_env env,napi_callback_info info)418 napi_value JsCoordinationContext::UnregisterMouseListener(napi_env env, napi_callback_info info)
419 {
420     CALL_INFO_TRACE;
421     napi_value argv[3] = { nullptr };
422     size_t argc = 3;
423     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
424     if (argc < 2) {
425         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
426         return nullptr;
427     }
428     char type[MAX_STRING_LEN] = { 0 };
429     size_t length = 0;
430     CHKRP(napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_VALUE_STRING_UTF8);
431     if ((COOPERATE_MOUSE_NAME.compare(type)) != 0) {
432         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be cooperateMouse");
433         return nullptr;
434     }
435 
436     char networkId[MAX_STRING_LEN] = { 0 };
437     size_t len = 0;
438     CHKRP(napi_get_value_string_utf8(env, argv[1], networkId, sizeof(networkId), &len), GET_VALUE_STRING_UTF8);
439 
440     JsCoordinationContext *jsDev = JsCoordinationContext::GetInstance(env);
441     CHKPP(jsDev);
442     std::shared_ptr<JsCoordinationManager> jsCoordinationMgr = jsDev->GetJsCoordinationMgr();
443     CHKPP(jsCoordinationMgr);
444 
445     if (argc == 2) {
446         jsCoordinationMgr->UnregisterListener(env, type, networkId);
447         return nullptr;
448     }
449     if (UtilNapi::TypeOf(env, argv[2], napi_undefined) || UtilNapi::TypeOf(env, argv[2], napi_null)) {
450         FI_HILOGW("Undefined callback, unregister all listener of networkId: %{public}s",
451             Utility::Anonymize(networkId).c_str());
452         jsCoordinationMgr->UnregisterListener(env, type, networkId);
453         return nullptr;
454     }
455     if (UtilNapi::TypeOf(env, argv[2], napi_function)) {
456         jsCoordinationMgr->UnregisterListener(env, type, networkId, argv[2]);
457         return nullptr;
458     }
459     THROWERR(env, COMMON_PARAMETER_ERROR, "callback", "function");
460     FI_HILOGE("UnregisterMouseListener failed, invalid parameter");
461     return nullptr;
462 }
463 
GetJsCoordinationMgr()464 std::shared_ptr<JsCoordinationManager> JsCoordinationContext::GetJsCoordinationMgr()
465 {
466     std::lock_guard<std::mutex> guard(mutex_);
467     return mgr_;
468 }
469 
CreateInstance(napi_env env)470 napi_value JsCoordinationContext::CreateInstance(napi_env env)
471 {
472     CALL_INFO_TRACE;
473     napi_value global = nullptr;
474     CHKRP(napi_get_global(env, &global), GET_GLOBAL);
475 
476     constexpr char className[] = "JsCoordinationContext";
477     napi_value jsClass = nullptr;
478     napi_property_descriptor desc[] = {};
479     napi_status status = napi_define_class(env, className, sizeof(className),
480         JsCoordinationContext::JsConstructor, nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
481     CHKRP(status, DEFINE_CLASS);
482 
483     status = napi_set_named_property(env, global, COORDINATION_CLASS, jsClass);
484     CHKRP(status, SET_NAMED_PROPERTY);
485 
486     napi_value jsInstance = nullptr;
487     CHKRP(napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
488     CHKRP(napi_set_named_property(env, global, COORDINATION, jsInstance),
489         SET_NAMED_PROPERTY);
490 
491     JsCoordinationContext *jsContext = nullptr;
492     CHKRP(napi_unwrap(env, jsInstance, reinterpret_cast<void**>(&jsContext)), UNWRAP);
493     CHKPP(jsContext);
494     CHKRP(napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
495 
496     uint32_t refCount = 0;
497     status = napi_reference_ref(env, jsContext->contextRef_, &refCount);
498     if (status != napi_ok) {
499         FI_HILOGE("Reference to nullptr");
500         napi_delete_reference(env, jsContext->contextRef_);
501         return nullptr;
502     }
503     return jsInstance;
504 }
505 
JsConstructor(napi_env env,napi_callback_info info)506 napi_value JsCoordinationContext::JsConstructor(napi_env env, napi_callback_info info)
507 {
508     CALL_INFO_TRACE;
509     napi_value thisVar = nullptr;
510     void *data = nullptr;
511     CHKRP(napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
512 
513     JsCoordinationContext *jsContext = new (std::nothrow) JsCoordinationContext();
514     CHKPP(jsContext);
515     napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void *data, void *hin) {
516         FI_HILOGI("Jsvm ends");
517         JsCoordinationContext *context = static_cast<JsCoordinationContext*>(data);
518         delete context;
519     }, nullptr, nullptr);
520     if (status != napi_ok) {
521         delete jsContext;
522         FI_HILOGE("%{public}s failed", std::string(WRAP).c_str());
523         auto infoTemp = std::string(__FUNCTION__) + ": " + std::string(WRAP) + " failed";
524         napi_throw_error(env, nullptr, infoTemp.c_str());
525         return nullptr;
526     }
527     return thisVar;
528 }
529 
GetInstance(napi_env env)530 JsCoordinationContext *JsCoordinationContext::GetInstance(napi_env env)
531 {
532     CALL_INFO_TRACE;
533     napi_value napiGlobal = nullptr;
534     CHKRP(napi_get_global(env, &napiGlobal), GET_GLOBAL);
535 
536     bool result = false;
537     CHKRP(napi_has_named_property(env, napiGlobal, COORDINATION, &result), HAS_NAMED_PROPERTY);
538     if (!result) {
539         FI_HILOGE("Coordination was not found");
540         return nullptr;
541     }
542 
543     napi_handle_scope handleScope = nullptr;
544     napi_open_handle_scope(env, &handleScope);
545     CHKPP(handleScope);
546     napi_value object = nullptr;
547     CHKRP_SCOPE(env, napi_get_named_property(env, napiGlobal, COORDINATION, &object),
548         GET_NAMED_PROPERTY, handleScope);
549     if (object == nullptr) {
550         napi_close_handle_scope(env, handleScope);
551         FI_HILOGE("object is nullptr");
552         return nullptr;
553     }
554 
555     JsCoordinationContext *instance = nullptr;
556     CHKRP_SCOPE(env, napi_unwrap(env, object, reinterpret_cast<void**>(&instance)), UNWRAP, handleScope);
557     if (instance == nullptr) {
558         napi_close_handle_scope(env, handleScope);
559         FI_HILOGE("instance is nullptr");
560         return nullptr;
561     }
562     napi_close_handle_scope(env, handleScope);
563     return instance;
564 }
565 
DeclareDeviceCoordinationData(napi_env env,napi_value exports)566 void JsCoordinationContext::DeclareDeviceCoordinationData(napi_env env, napi_value exports)
567 {
568     napi_value prepare = nullptr;
569     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::PREPARE), &prepare),
570         CREATE_INT32);
571     napi_value unprepare = nullptr;
572     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::UNPREPARE), &unprepare),
573         CREATE_INT32);
574     napi_value activate = nullptr;
575     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE), &activate),
576         CREATE_INT32);
577     napi_value activateSuccess = nullptr;
578     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE_SUCCESS), &activateSuccess),
579         CREATE_INT32);
580     napi_value activateFail = nullptr;
581     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE_FAIL), &activateFail),
582         CREATE_INT32);
583     napi_value deactivateSuccess = nullptr;
584     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::DEACTIVATE_SUCCESS), &deactivateSuccess),
585         CREATE_INT32);
586     napi_value deactivateFail = nullptr;
587     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::DEACTIVATE_FAIL), &deactivateFail),
588         CREATE_INT32);
589     napi_value sessionClosed = nullptr;
590     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::SESSION_CLOSED), &sessionClosed),
591         CREATE_INT32);
592 
593     napi_property_descriptor msg[] = {
594         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_PREPARE", prepare),
595         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_UNPREPARE", unprepare),
596         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE", activate),
597         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE_SUCCESS", activateSuccess),
598         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE_FAIL", activateFail),
599         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_DEACTIVATE_SUCCESS", deactivateSuccess),
600         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_DEACTIVATE_FAIL", deactivateFail),
601         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_SESSION_DISCONNECTED", sessionClosed)
602     };
603 
604     napi_value cooperateMsg = nullptr;
605     CHKRV(napi_define_class(env, "CooperateMsg", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
606         sizeof(msg) / sizeof(*msg), msg, &cooperateMsg), DEFINE_CLASS);
607     CHKRV(napi_set_named_property(env, exports, "CooperateMsg", cooperateMsg), SET_NAMED_PROPERTY);
608 }
609 
DeclareDeviceCooperateData(napi_env env,napi_value exports)610 void JsCoordinationContext::DeclareDeviceCooperateData(napi_env env, napi_value exports)
611 {
612     napi_value prepare = nullptr;
613     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::PREPARE), &prepare),
614         CREATE_INT32);
615     napi_value unprepare = nullptr;
616     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::UNPREPARE), &unprepare),
617         CREATE_INT32);
618     napi_value activate = nullptr;
619     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE), &activate),
620         CREATE_INT32);
621     napi_value activateSuccess = nullptr;
622     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE_SUCCESS), &activateSuccess),
623         CREATE_INT32);
624     napi_value activateFail = nullptr;
625     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::ACTIVATE_FAIL), &activateFail),
626         CREATE_INT32);
627     napi_value deactivateSuccess = nullptr;
628     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::DEACTIVATE_SUCCESS), &deactivateSuccess),
629         CREATE_INT32);
630     napi_value deactivateFail = nullptr;
631     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::DEACTIVATE_FAIL), &deactivateFail),
632         CREATE_INT32);
633     napi_value sessionClosed = nullptr;
634     CHKRV(napi_create_int32(env, static_cast<int32_t>(CoordinationMessage::SESSION_CLOSED), &sessionClosed),
635         CREATE_INT32);
636 
637     napi_property_descriptor msg[] = {
638         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_PREPARE", prepare),
639         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_UNPREPARE", unprepare),
640         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE", activate),
641         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE_SUCCESS", activateSuccess),
642         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_ACTIVATE_FAILURE", activateFail),
643         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_DEACTIVATE_SUCCESS", deactivateSuccess),
644         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_DEACTIVATE_FAILURE", deactivateFail),
645         DECLARE_NAPI_STATIC_PROPERTY("COOPERATE_SESSION_DISCONNECTED", sessionClosed)
646     };
647 
648     napi_value cooperateMsg = nullptr;
649     CHKRV(napi_define_class(env, "CooperateState", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
650         sizeof(msg) / sizeof(*msg), msg, &cooperateMsg), DEFINE_CLASS);
651     CHKRV(napi_set_named_property(env, exports, "CooperateState", cooperateMsg), SET_NAMED_PROPERTY);
652 }
653 
DeclareDeviceCoordinationInterface(napi_env env,napi_value exports)654 void JsCoordinationContext::DeclareDeviceCoordinationInterface(napi_env env, napi_value exports)
655 {
656     napi_property_descriptor functions[] = {
657         DECLARE_NAPI_STATIC_FUNCTION("prepare", Prepare),
658         DECLARE_NAPI_STATIC_FUNCTION("prepareCooperate", PrepareCooperate),
659         DECLARE_NAPI_STATIC_FUNCTION("unprepare", Unprepare),
660         DECLARE_NAPI_STATIC_FUNCTION("unprepareCooperate", UnprepareCooperate),
661         DECLARE_NAPI_STATIC_FUNCTION("activate", Activate),
662         DECLARE_NAPI_STATIC_FUNCTION("activateCooperate", ActivateCooperate),
663         DECLARE_NAPI_STATIC_FUNCTION("deactivate", Deactivate),
664         DECLARE_NAPI_STATIC_FUNCTION("deactivateCooperate", DeactivateCooperate),
665         DECLARE_NAPI_STATIC_FUNCTION("getCrossingSwitchState", GetCrossingSwitchState),
666         DECLARE_NAPI_STATIC_FUNCTION("getCooperateSwitchState", GetCooperateSwitchState),
667         DECLARE_NAPI_STATIC_FUNCTION("on", On),
668         DECLARE_NAPI_STATIC_FUNCTION("off", Off)
669     };
670     CHKRV(napi_define_properties(env, exports,
671         sizeof(functions) / sizeof(*functions), functions), DEFINE_PROPERTIES);
672 }
673 
EnumClassConstructor(napi_env env,napi_callback_info info)674 napi_value JsCoordinationContext::EnumClassConstructor(napi_env env, napi_callback_info info)
675 {
676     size_t argc = 0;
677     napi_value args[1] = { nullptr };
678     napi_value result = nullptr;
679     void *data = nullptr;
680     CHKRP(napi_get_cb_info(env, info, &argc, args, &result, &data), GET_CB_INFO);
681     return result;
682 }
683 } // namespace DeviceStatus
684 } // namespace Msdp
685 } // namespace OHOS
686