• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-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  * Description: supply napi interface realization for cast session manager.
15  * Author: zhangjingnan
16  * Create: 2022-7-11
17  */
18 
19 #include <memory>
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 #include "cast_engine_log.h"
23 #include "cast_engine_common.h"
24 #include "cast_session_manager.h"
25 #include "napi_cast_session_manager_listener.h"
26 #include "napi_cast_session.h"
27 #include "napi_castengine_utils.h"
28 #include "napi_cast_session_manager.h"
29 #include "napi_async_work.h"
30 
31 using namespace OHOS::CastEngine::CastEngineClient;
32 using namespace std;
33 
34 namespace OHOS {
35 namespace CastEngine {
36 namespace CastEngineClient {
37 DEFINE_CAST_ENGINE_LABEL("Cast-Napi-SessionManager");
38 
39 std::shared_ptr<NapiCastSessionManagerListener> NapiCastSessionManager::listener_;
40 
41 std::map<std::string, std::pair<NapiCastSessionManager::OnEventHandlerType,
42     NapiCastSessionManager::OffEventHandlerType>>
43     NapiCastSessionManager::eventHandlers_ = {
44     { "serviceDie", { OnServiceDied, OffServiceDie } },
45     { "deviceFound", { OnDeviceFound, OffDeviceFound } },
46     { "sessionCreate", { OnSessionCreated, OffSessionCreated } },
47     { "deviceOffline", { OnDeviceOffline, OffDeviceOffline } }
48 };
49 
Init(napi_env env,napi_value exports)50 napi_value NapiCastSessionManager::Init(napi_env env, napi_value exports)
51 {
52     napi_property_descriptor NapiCastSessionManagerDesc[] = {
53         DECLARE_NAPI_FUNCTION("on", OnEvent),
54         DECLARE_NAPI_FUNCTION("off", OffEvent),
55         DECLARE_NAPI_FUNCTION("startDiscovery", StartDiscovery),
56         DECLARE_NAPI_FUNCTION("stopDiscovery", StopDiscovery),
57         DECLARE_NAPI_FUNCTION("setDiscoverable", SetDiscoverable),
58         DECLARE_NAPI_FUNCTION("createCastSession", CreateCastSession),
59         DECLARE_NAPI_FUNCTION("release", Release)
60     };
61 
62     napi_status status = napi_define_properties(env, exports,
63         sizeof(NapiCastSessionManagerDesc) / sizeof(napi_property_descriptor), NapiCastSessionManagerDesc);
64     if (status != napi_ok) {
65         CLOGE("define manager properties failed");
66         return GetUndefinedValue(env);
67     }
68     return exports;
69 }
70 
StartDiscovery(napi_env env,napi_callback_info info)71 napi_value NapiCastSessionManager::StartDiscovery(napi_env env, napi_callback_info info)
72 {
73     CLOGD("Start to discovery in");
74     struct ConcreteTask : public NapiAsyncTask {
75         int protocolType_;
76     };
77     auto napiAsyntask = std::make_shared<ConcreteTask>();
78     if (napiAsyntask == nullptr) {
79         CLOGE("Create NapiAsyncTask failed");
80         return GetUndefinedValue(env);
81     }
82 
83     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
84         constexpr size_t expectedArgc = 1;
85         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
86             NapiErrors::errcode_[ERR_INVALID_PARAM]);
87         napi_valuetype expectedTypes[expectedArgc] = { napi_object };
88         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
89         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
90             NapiErrors::errcode_[ERR_INVALID_PARAM]);
91         int32_t protocolTypeInt;
92         bool isProtocolTypesValid = GetProtocolTypesFromJS(env, argv[0], protocolTypeInt);
93         CHECK_ARGS_RETURN_VOID(napiAsyntask, isProtocolTypesValid, "invalid arguments",
94             NapiErrors::errcode_[ERR_INVALID_PARAM]);
95         napiAsyntask->protocolType_ = protocolTypeInt;
96     };
97     napiAsyntask->GetJSInfo(env, info, inputParser);
98     auto executor = [napiAsyntask]() {
99         int32_t ret = CastSessionManager::GetInstance().StartDiscovery(napiAsyntask->protocolType_);
100         if (ret != CAST_ENGINE_SUCCESS) {
101             if (ret == ERR_NO_PERMISSION) {
102                 napiAsyntask->errMessage = "StartDiscovery failed : no permission";
103             } else if (ret == ERR_INVALID_PARAM) {
104                 napiAsyntask->errMessage = "StartDiscovery failed : invalid parameters";
105             } else {
106                 napiAsyntask->errMessage = "StartDiscovery failed : native server exception";
107             }
108             napiAsyntask->status = napi_generic_failure;
109             napiAsyntask->errCode = NapiErrors::errcode_[ret];
110         }
111     };
112 
113     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
114     return NapiAsyncWork::Enqueue(env, napiAsyntask, "StartDiscovery", executor, complete);
115 }
116 
StopDiscovery(napi_env env,napi_callback_info info)117 napi_value NapiCastSessionManager::StopDiscovery(napi_env env, napi_callback_info info)
118 {
119     CLOGD("Start to stop discovery in");
120     auto napiAsyntask = std::make_shared<NapiAsyncTask>();
121     if (napiAsyntask == nullptr) {
122         CLOGE("Create NapiAsyncTask failed");
123         return GetUndefinedValue(env);
124     }
125     napiAsyntask->GetJSInfo(env, info);
126 
127     auto executor = [napiAsyntask]() {
128         int32_t ret = CastSessionManager::GetInstance().StopDiscovery();
129         if (ret != CAST_ENGINE_SUCCESS) {
130             if (ret == ERR_NO_PERMISSION) {
131                 napiAsyntask->errMessage = "StopDiscovery failed : no permission";
132             } else {
133                 napiAsyntask->errMessage = "StopDiscovery failed : native server exception";
134             }
135             napiAsyntask->status = napi_generic_failure;
136             napiAsyntask->errCode = NapiErrors::errcode_[ret];
137         }
138     };
139     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
140     return NapiAsyncWork::Enqueue(env, napiAsyntask, "StopDiscovery", executor, complete);
141 }
142 
SetDiscoverable(napi_env env,napi_callback_info info)143 napi_value NapiCastSessionManager::SetDiscoverable(napi_env env, napi_callback_info info)
144 {
145     CLOGD("Start to set discoverable in");
146     struct ConcreteTask : public NapiAsyncTask {
147         bool isEnable_;
148     };
149     auto napiAsyntask = std::make_shared<ConcreteTask>();
150     if (napiAsyntask == nullptr) {
151         CLOGE("Create NapiAsyncTask failed");
152         return GetUndefinedValue(env);
153     }
154 
155     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
156         constexpr size_t expectedArgc = 1;
157         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
158             NapiErrors::errcode_[ERR_INVALID_PARAM]);
159         napi_valuetype expectedTypes[expectedArgc] = { napi_boolean };
160         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
161         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
162             NapiErrors::errcode_[ERR_INVALID_PARAM]);
163         napiAsyntask->isEnable_ = ParseBool(env, argv[0]);
164     };
165     napiAsyntask->GetJSInfo(env, info, inputParser);
166     auto executor = [napiAsyntask]() {
167         int32_t ret = CastSessionManager::GetInstance().SetDiscoverable(napiAsyntask->isEnable_);
168         if (ret != CAST_ENGINE_SUCCESS) {
169             if (ret == ERR_NO_PERMISSION) {
170                 napiAsyntask->errMessage = "SetDiscoverable failed : no permission";
171             } else {
172                 napiAsyntask->errMessage = "SetDiscoverable failed : native server exception";
173             }
174             napiAsyntask->status = napi_generic_failure;
175             napiAsyntask->errCode = NapiErrors::errcode_[ret];
176         }
177     };
178 
179     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
180     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetDiscoverable", executor, complete);
181 }
182 
CreateCastSession(napi_env env,napi_callback_info info)183 napi_value NapiCastSessionManager::CreateCastSession(napi_env env, napi_callback_info info)
184 {
185     CLOGD("Start to create castSession in");
186     struct ConcreteTask : public NapiAsyncTask {
187         CastSessionProperty property_;
188         std::shared_ptr<ICastSession> session_;
189     };
190     auto napiAsyntask = std::make_shared<ConcreteTask>();
191     if (napiAsyntask == nullptr) {
192         CLOGE("Create NapiAsyncTask failed");
193         return GetUndefinedValue(env);
194     }
195 
196     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
197         constexpr size_t expectedArgc = 1;
198         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
199             NapiErrors::errcode_[ERR_INVALID_PARAM]);
200         napi_valuetype expectedTypes[expectedArgc] = { napi_object };
201         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
202         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
203             NapiErrors::errcode_[ERR_INVALID_PARAM]);
204         napiAsyntask->property_ = GetCastSessionPropertyFromJS(env, argv[0]);
205     };
206     napiAsyntask->GetJSInfo(env, info, inputParser);
207     auto executor = [napiAsyntask]() {
208         int32_t ret =
209             CastSessionManager::GetInstance().CreateCastSession(napiAsyntask->property_, napiAsyntask->session_);
210         if (ret != CAST_ENGINE_SUCCESS) {
211             if (ret == ERR_NO_PERMISSION) {
212                 napiAsyntask->errMessage = "CreateCastSession failed : no permission";
213             } else if (ret == ERR_INVALID_PARAM) {
214                 napiAsyntask->errMessage = "CreateCastSession failed : invalid parameters";
215             } else {
216                 napiAsyntask->errMessage = "CreateCastSession failed : native server exception";
217             }
218             napiAsyntask->status = napi_generic_failure;
219             napiAsyntask->errCode = NapiErrors::errcode_[ret];
220         }
221     };
222 
223     auto complete = [napiAsyntask](napi_value &output) {
224         napiAsyntask->status =
225             NapiCastSession::CreateNapiCastSession(napiAsyntask->env, napiAsyntask->session_, output);
226         CHECK_STATUS_RETURN_VOID(napiAsyntask, "convert native object to javascript object failed",
227             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
228     };
229     return NapiAsyncWork::Enqueue(env, napiAsyntask, "CreateCastSession", executor, complete);
230 }
231 
Release(napi_env env,napi_callback_info info)232 napi_value NapiCastSessionManager::Release(napi_env env, napi_callback_info info)
233 {
234     CLOGD("Start to release in");
235     auto napiAsyntask = std::make_shared<NapiAsyncTask>();
236     if (napiAsyntask == nullptr) {
237         CLOGE("Create NapiAsyncTask failed");
238         return GetUndefinedValue(env);
239     }
240     napiAsyntask->GetJSInfo(env, info);
241 
242     auto executor = [napiAsyntask]() {
243         int32_t ret = CastSessionManager::GetInstance().Release();
244         if (ret != CAST_ENGINE_SUCCESS) {
245             if (ret == ERR_NO_PERMISSION) {
246                 napiAsyntask->errMessage = "Release failed : no permission";
247             } else {
248                 napiAsyntask->errMessage = "Release failed : native server exception";
249             }
250             napiAsyntask->status = napi_generic_failure;
251             napiAsyntask->errCode = NapiErrors::errcode_[ret];
252         }
253     };
254     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
255     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Release", executor, complete);
256 }
257 
OnEvent(napi_env env,napi_callback_info info)258 napi_value NapiCastSessionManager::OnEvent(napi_env env, napi_callback_info info)
259 {
260     constexpr size_t expectedArgc = 2;
261     napi_value argv[expectedArgc] = { 0 };
262     napi_valuetype expectedTypes[expectedArgc] = { napi_string, napi_function };
263     if (!GetJSFuncParams(env, info, argv, expectedArgc, expectedTypes)) {
264         return GetUndefinedValue(env);
265     }
266 
267     std::string eventName = ParseString(env, argv[0]);
268     auto it = eventHandlers_.find(eventName);
269     if (it == eventHandlers_.end()) {
270         CLOGE("event name invalid");
271         return GetUndefinedValue(env);
272     }
273 
274     if (RegisterNativeSessionManagerListener() == napi_generic_failure) {
275         return GetUndefinedValue(env);
276     }
277     if (it->second.first(env, argv[1]) != napi_ok) {
278         CLOGE("event name invalid");
279     }
280 
281     return GetUndefinedValue(env);
282 }
283 
OffEvent(napi_env env,napi_callback_info info)284 napi_value NapiCastSessionManager::OffEvent(napi_env env, napi_callback_info info)
285 {
286     constexpr size_t expectedArgc = 2;
287     napi_value argv[expectedArgc] = { 0 };
288     napi_valuetype expectedTypes[expectedArgc] = { napi_string, napi_function};
289     if (!GetJSFuncParams(env, info, argv, expectedArgc, expectedTypes)) {
290         return GetUndefinedValue(env);
291     }
292 
293     std::string eventName = ParseString(env, argv[0]);
294     auto it = eventHandlers_.find(eventName);
295     if (it == eventHandlers_.end()) {
296         CLOGE("event name invalid");
297         return GetUndefinedValue(env);
298     }
299     if (it->second.second(env, argv[1]) != napi_ok) {
300         CLOGE("event name invalid");
301     }
302 
303     return GetUndefinedValue(env);
304 }
305 
OnServiceDied(napi_env env,napi_value callback)306 napi_status NapiCastSessionManager::OnServiceDied(napi_env env, napi_value callback)
307 {
308     if (!listener_) {
309         CLOGE("cast session manager callback is null");
310         return napi_generic_failure;
311     }
312     if (listener_->AddCallback(env, NapiCastSessionManagerListener::EVENT_SERVICE_DIED, callback) != napi_ok) {
313         return napi_generic_failure;
314     }
315     return napi_ok;
316 }
317 
OnDeviceFound(napi_env env,napi_value callback)318 napi_status NapiCastSessionManager::OnDeviceFound(napi_env env, napi_value callback)
319 {
320     if (!listener_) {
321         CLOGE("cast session manager callback is null");
322         return napi_generic_failure;
323     }
324     if (listener_->AddCallback(env, NapiCastSessionManagerListener::EVENT_DEVICE_FOUND, callback) != napi_ok) {
325         return napi_generic_failure;
326     }
327     return napi_ok;
328 }
329 
OnSessionCreated(napi_env env,napi_value callback)330 napi_status NapiCastSessionManager::OnSessionCreated(napi_env env, napi_value callback)
331 {
332     if (!listener_) {
333         CLOGE("cast session manager callback is null");
334         return napi_generic_failure;
335     }
336     if (listener_->AddCallback(env, NapiCastSessionManagerListener::EVENT_SESSION_CREATE, callback) != napi_ok) {
337         return napi_generic_failure;
338     }
339     return napi_ok;
340 }
341 
OnDeviceOffline(napi_env env,napi_value callback)342 napi_status NapiCastSessionManager::OnDeviceOffline(napi_env env, napi_value callback)
343 {
344     if (!listener_) {
345         CLOGE("cast session manager callback is null");
346         return napi_generic_failure;
347     }
348     if (listener_->AddCallback(env, NapiCastSessionManagerListener::EVENT_DEVICE_OFFLINE, callback) != napi_ok) {
349         return napi_generic_failure;
350     }
351     return napi_ok;
352 }
353 
OffServiceDie(napi_env env,napi_value callback)354 napi_status NapiCastSessionManager::OffServiceDie(napi_env env, napi_value callback)
355 {
356     if (!listener_) {
357         CLOGE("cast session manager callback is null");
358         return napi_generic_failure;
359     }
360     if (listener_->RemoveCallback(env, NapiCastSessionManagerListener::EVENT_SERVICE_DIED, callback) != napi_ok) {
361         return napi_generic_failure;
362     }
363     return napi_ok;
364 }
365 
OffDeviceFound(napi_env env,napi_value callback)366 napi_status NapiCastSessionManager::OffDeviceFound(napi_env env, napi_value callback)
367 {
368     if (!listener_) {
369         CLOGE("cast session manager callback is null");
370         return napi_generic_failure;
371     }
372     if (listener_->RemoveCallback(env, NapiCastSessionManagerListener::EVENT_DEVICE_FOUND, callback) != napi_ok) {
373         return napi_generic_failure;
374     }
375     return napi_ok;
376 }
377 
OffSessionCreated(napi_env env,napi_value callback)378 napi_status NapiCastSessionManager::OffSessionCreated(napi_env env, napi_value callback)
379 {
380     if (!listener_) {
381         CLOGE("cast session manager callback is null");
382         return napi_generic_failure;
383     }
384     if (listener_->RemoveCallback(env, NapiCastSessionManagerListener::EVENT_SESSION_CREATE, callback) != napi_ok) {
385         return napi_generic_failure;
386     }
387     return napi_ok;
388 }
389 
OffDeviceOffline(napi_env env,napi_value callback)390 napi_status NapiCastSessionManager::OffDeviceOffline(napi_env env, napi_value callback)
391 {
392     if (!listener_) {
393         CLOGE("cast session manager callback is null");
394         return napi_generic_failure;
395     }
396     if (listener_->RemoveCallback(env, NapiCastSessionManagerListener::EVENT_DEVICE_OFFLINE, callback) != napi_ok) {
397         return napi_generic_failure;
398     }
399     return napi_ok;
400 }
401 
RegisterNativeSessionManagerListener()402 napi_status NapiCastSessionManager::RegisterNativeSessionManagerListener()
403 {
404     if (listener_) {
405         return napi_ok;
406     }
407     listener_ = std::make_shared<NapiCastSessionManagerListener>();
408     if (!listener_) {
409         CLOGE("Failed to malloc session manager listener");
410         return napi_generic_failure;
411     }
412     int32_t ret = CastSessionManager::GetInstance().RegisterListener(listener_);
413     if (ret != CAST_ENGINE_SUCCESS) {
414         CLOGE("native register session manager listener failed");
415         return napi_generic_failure;
416     }
417 
418     return napi_ok;
419 }
420 } // namespace CastEngineClient
421 } // namespace CastEngine
422 } // namespace OHOS