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 */
15
16 #include "js_pip_controller.h"
17
18 #include "js_pip_utils.h"
19 #include "picture_in_picture_manager.h"
20 #include "window_manager_hilog.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 using namespace AbilityRuntime;
25 namespace {
26 constexpr int32_t NUMBER_ZERO = 0;
27 constexpr int32_t NUMBER_ONE = 1;
28 constexpr int32_t NUMBER_TWO = 2;
29 constexpr int32_t NUMBER_FOUR = 4;
30 const std::string STATE_CHANGE_CB = "stateChange";
31 const std::string CONTROL_PANEL_ACTION_EVENT_CB = "controlPanelActionEvent";
32 const std::string CONTROL_EVENT_CB = "controlEvent";
33 }
34
BindFunctions(napi_env env,napi_value object,const char * moduleName)35 void BindFunctions(napi_env env, napi_value object, const char* moduleName)
36 {
37 BindNativeFunction(env, object, "startPiP", moduleName, JsPipController::StartPictureInPicture);
38 BindNativeFunction(env, object, "stopPiP", moduleName, JsPipController::StopPictureInPicture);
39 BindNativeFunction(env, object, "updateContentSize", moduleName, JsPipController::UpdateContentSize);
40 BindNativeFunction(env, object, "updatePiPControlStatus", moduleName, JsPipController::UpdatePiPControlStatus);
41 BindNativeFunction(env, object, "setAutoStartEnabled", moduleName, JsPipController::SetAutoStartEnabled);
42 BindNativeFunction(env, object, "setPiPControlEnabled", moduleName, JsPipController::SetPiPControlEnabled);
43 BindNativeFunction(env, object, "on", moduleName, JsPipController::RegisterCallback);
44 BindNativeFunction(env, object, "off", moduleName, JsPipController::UnregisterCallback);
45 }
46
CreateJsPipControllerObject(napi_env env,sptr<PictureInPictureController> & pipController)47 napi_value CreateJsPipControllerObject(napi_env env, sptr<PictureInPictureController>& pipController)
48 {
49 napi_value objValue = nullptr;
50 napi_create_object(env, &objValue);
51
52 TLOGI(WmsLogTag::WMS_PIP, "CreateJsPipController");
53 std::unique_ptr<JsPipController> jsPipController = std::make_unique<JsPipController>(pipController);
54 napi_wrap(env, objValue, jsPipController.release(), JsPipController::Finalizer, nullptr, nullptr);
55
56 BindFunctions(env, objValue, "JsPipController");
57 return objValue;
58 }
59
JsPipController(const sptr<PictureInPictureController> & pipController)60 JsPipController::JsPipController(const sptr<PictureInPictureController>& pipController)
61 : pipController_(pipController)
62 {
63 listenerCodeMap_ = {
64 { STATE_CHANGE_CB, ListenerType::STATE_CHANGE_CB },
65 { CONTROL_PANEL_ACTION_EVENT_CB, ListenerType::CONTROL_PANEL_ACTION_EVENT_CB },
66 { CONTROL_EVENT_CB, ListenerType::CONTROL_EVENT_CB },
67 };
68 }
69
~JsPipController()70 JsPipController::~JsPipController()
71 {
72 }
73
Finalizer(napi_env env,void * data,void * hint)74 void JsPipController::Finalizer(napi_env env, void* data, void* hint)
75 {
76 TLOGD(WmsLogTag::WMS_PIP, "Finalizer is called");
77 std::unique_ptr<JsPipController>(static_cast<JsPipController*>(data));
78 }
79
StartPictureInPicture(napi_env env,napi_callback_info info)80 napi_value JsPipController::StartPictureInPicture(napi_env env, napi_callback_info info)
81 {
82 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
83 return (me != nullptr) ? me->OnStartPictureInPicture(env, info) : nullptr;
84 }
85
OnStartPictureInPicture(napi_env env,napi_callback_info info)86 napi_value JsPipController::OnStartPictureInPicture(napi_env env, napi_callback_info info)
87 {
88 TLOGI(WmsLogTag::WMS_PIP, "OnStartPictureInPicture is called");
89 if (PictureInPictureManager::ShouldAbortPipStart()) {
90 TLOGI(WmsLogTag::WMS_PIP, "OnStartPictureInPicture abort");
91 return NapiGetUndefined(env);
92 }
93 size_t argc = NUMBER_FOUR;
94 napi_value argv[NUMBER_FOUR] = {nullptr};
95 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
96 napi_value callback = nullptr;
97 if (argc > 0) {
98 callback = GetType(env, argv[0]) == napi_function ? argv[0] : nullptr; // 1: index of callback
99 }
100 NapiAsyncTask::CompleteCallback complete =
101 [weak = wptr<PictureInPictureController>(this->pipController_)]
102 (napi_env env, NapiAsyncTask& task, int32_t status) {
103 if (weak == nullptr) {
104 task.Reject(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_PIP_STATE_ABNORMALLY),
105 "JsPipController::OnStartPictureInPicture failed."));
106 return;
107 }
108 WMError errCode = weak->StartPictureInPicture(StartPipType::USER_START);
109 if (errCode != WMError::WM_OK) {
110 task.Reject(env, CreateJsError(env, static_cast<int32_t>(WM_JS_TO_ERROR_CODE_MAP.at(errCode)),
111 "JsPipController::OnStartPictureInPicture failed."));
112 return;
113 }
114 task.Resolve(env, NapiGetUndefined(env));
115 };
116 napi_value result = nullptr;
117 NapiAsyncTask::Schedule("JsPipController::OnStartPictureInPicture", env,
118 CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
119 return result;
120 }
121
StopPictureInPicture(napi_env env,napi_callback_info info)122 napi_value JsPipController::StopPictureInPicture(napi_env env, napi_callback_info info)
123 {
124 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
125 return (me != nullptr) ? me->OnStopPictureInPicture(env, info) : nullptr;
126 }
127
OnStopPictureInPicture(napi_env env,napi_callback_info info)128 napi_value JsPipController::OnStopPictureInPicture(napi_env env, napi_callback_info info)
129 {
130 TLOGI(WmsLogTag::WMS_PIP, "OnStopPictureInPicture is called");
131 size_t argc = NUMBER_FOUR;
132 napi_value argv[NUMBER_FOUR] = {nullptr};
133 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
134 napi_value callback = nullptr;
135 if (argc > 0) {
136 callback = GetType(env, argv[0]) == napi_function ? argv[0] : nullptr; // 1: index of callback
137 }
138 NapiAsyncTask::CompleteCallback complete =
139 [weak = wptr<PictureInPictureController>(this->pipController_)]
140 (napi_env env, NapiAsyncTask& task, int32_t status) {
141 if (weak == nullptr) {
142 task.Reject(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY),
143 "JsPipController::OnStopPictureInPicture failed."));
144 return;
145 }
146 WMError errCode = weak->StopPictureInPictureFromClient();
147 if (errCode != WMError::WM_OK) {
148 task.Reject(env, CreateJsError(env, static_cast<int32_t>(WM_JS_TO_ERROR_CODE_MAP.at(errCode)),
149 "JsPipController::OnStopPictureInPicture failed."));
150 return;
151 }
152 task.Resolve(env, NapiGetUndefined(env));
153 };
154 napi_value result = nullptr;
155 NapiAsyncTask::Schedule("JsPipController::OnStopPictureInPicture", env,
156 CreateAsyncTaskWithLastParam(env, callback, nullptr, std::move(complete), &result));
157 return result;
158 }
159
SetAutoStartEnabled(napi_env env,napi_callback_info info)160 napi_value JsPipController::SetAutoStartEnabled(napi_env env, napi_callback_info info)
161 {
162 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
163 return (me != nullptr) ? me->OnSetAutoStartEnabled(env, info) : nullptr;
164 }
165
OnSetAutoStartEnabled(napi_env env,napi_callback_info info)166 napi_value JsPipController::OnSetAutoStartEnabled(napi_env env, napi_callback_info info)
167 {
168 TLOGI(WmsLogTag::WMS_PIP, "OnSetAutoStartEnabled is called");
169 size_t argc = NUMBER_FOUR;
170 napi_value argv[NUMBER_FOUR] = {nullptr};
171 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
172 if (argc != 1) {
173 TLOGE(WmsLogTag::WMS_PIP, "Argc count is invalid: %{public}zu", argc);
174 return NapiThrowInvalidParam(env);
175 }
176 bool enable = false;
177 if (!ConvertFromJsValue(env, argv[0], enable)) {
178 TLOGE(WmsLogTag::WMS_PIP, "[NAPI]Failed to convert parameter to bool");
179 return NapiGetUndefined(env);
180 }
181 if (pipController_ == nullptr) {
182 TLOGE(WmsLogTag::WMS_PIP, "[NAPI]OnSetAutoStartEnabled error, controller is nullptr");
183 return NapiGetUndefined(env);
184 }
185 pipController_->SetAutoStartEnabled(enable);
186 return NapiGetUndefined(env);
187 }
188
UpdateContentSize(napi_env env,napi_callback_info info)189 napi_value JsPipController::UpdateContentSize(napi_env env, napi_callback_info info)
190 {
191 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
192 return (me != nullptr) ? me->OnUpdateContentSize(env, info) : nullptr;
193 }
194
OnUpdateContentSize(napi_env env,napi_callback_info info)195 napi_value JsPipController::OnUpdateContentSize(napi_env env, napi_callback_info info)
196 {
197 TLOGI(WmsLogTag::WMS_PIP, "OnUpdateContentSize is called");
198 size_t argc = NUMBER_FOUR;
199 napi_value argv[NUMBER_FOUR] = {nullptr};
200 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
201 if (argc != NUMBER_TWO) {
202 TLOGE(WmsLogTag::WMS_PIP, "Invalid args count, need 2 args but received: %{public}zu", argc);
203 return NapiThrowInvalidParam(env, "Invalid args count, 2 args is needed.");
204 }
205 int32_t width = 0;
206 std::string errMsg = "";
207 if (!ConvertFromJsValue(env, argv[0], width) || width <= 0) {
208 errMsg = "Failed to convert parameter to int or width <= 0";
209 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
210 return NapiThrowInvalidParam(env, errMsg);
211 }
212 int32_t height = 0;
213 if (!ConvertFromJsValue(env, argv[1], height) || height <= 0) {
214 errMsg = "Failed to convert parameter to int or height <= 0";
215 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
216 return NapiThrowInvalidParam(env, errMsg);
217 }
218 if (pipController_ == nullptr) {
219 errMsg = "OnUpdateContentSize error, controller is nullptr";
220 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
221 return NapiThrowInvalidParam(env, errMsg);
222 }
223 pipController_->UpdateContentSize(width, height);
224 return NapiGetUndefined(env);
225 }
226
UpdatePiPControlStatus(napi_env env,napi_callback_info info)227 napi_value JsPipController::UpdatePiPControlStatus(napi_env env, napi_callback_info info)
228 {
229 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
230 return (me != nullptr) ? me->OnUpdatePiPControlStatus(env, info) : nullptr;
231 }
232
OnUpdatePiPControlStatus(napi_env env,napi_callback_info info)233 napi_value JsPipController::OnUpdatePiPControlStatus(napi_env env, napi_callback_info info)
234 {
235 TLOGI(WmsLogTag::WMS_PIP, "called");
236 size_t argc = NUMBER_FOUR;
237 napi_value argv[NUMBER_FOUR] = {nullptr};
238 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
239 if (argc != NUMBER_TWO) {
240 TLOGE(WmsLogTag::WMS_PIP, "Invalid args count, need 2 args but received: %{public}zu", argc);
241 return NapiThrowInvalidParam(env, "Invalid args count, 2 args is needed.");
242 }
243 auto controlType = PiPControlType::VIDEO_PLAY_PAUSE;
244 std::string errMsg;
245 if (!ConvertFromJsValue(env, argv[0], controlType)) {
246 errMsg = "Failed to convert parameter to int or controlType < 0";
247 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
248 return NapiThrowInvalidParam(env, errMsg);
249 }
250 auto status = PiPControlStatus::PLAY;
251 if (!ConvertFromJsValue(env, argv[1], status)) {
252 errMsg = "Failed to convert parameter to int";
253 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
254 return NapiThrowInvalidParam(env, errMsg);
255 }
256 if (pipController_ == nullptr) {
257 errMsg = "OnUpdatePiPControlStatus error, controller is nullptr";
258 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
259 return NapiThrowInvalidParam(env, errMsg);
260 }
261 pipController_->UpdatePiPControlStatus(controlType, status);
262 return NapiGetUndefined(env);
263 }
264
SetPiPControlEnabled(napi_env env,napi_callback_info info)265 napi_value JsPipController::SetPiPControlEnabled(napi_env env, napi_callback_info info)
266 {
267 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
268 return (me != nullptr) ? me->OnSetPiPControlEnabled(env, info) : nullptr;
269 }
270
OnSetPiPControlEnabled(napi_env env,napi_callback_info info)271 napi_value JsPipController::OnSetPiPControlEnabled(napi_env env, napi_callback_info info)
272 {
273 TLOGI(WmsLogTag::WMS_PIP, "called");
274 size_t argc = NUMBER_FOUR;
275 napi_value argv[NUMBER_FOUR] = {nullptr};
276 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
277 if (argc != NUMBER_TWO) {
278 TLOGE(WmsLogTag::WMS_PIP, "Invalid args count, need 2 args but received: %{public}zu", argc);
279 return NapiThrowInvalidParam(env, "Invalid args count, 2 args is needed.");
280 }
281 auto controlType = PiPControlType::VIDEO_PLAY_PAUSE;
282 std::string errMsg = "";
283 if (!ConvertFromJsValue(env, argv[0], controlType)) {
284 errMsg = "Failed to convert parameter to int";
285 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
286 return NapiThrowInvalidParam(env, errMsg);
287 }
288 bool enabled = true;
289 if (!ConvertFromJsValue(env, argv[1], enabled)) {
290 errMsg = "Failed to convert parameter to bool";
291 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
292 return NapiThrowInvalidParam(env, errMsg);
293 }
294 if (pipController_ == nullptr) {
295 errMsg = "OnSetPiPControlEnabled error, controller is nullptr";
296 TLOGE(WmsLogTag::WMS_PIP, "%{public}s", errMsg.c_str());
297 return NapiThrowInvalidParam(env, errMsg);
298 }
299 pipController_->UpdatePiPControlStatus(controlType, enabled ?
300 PiPControlStatus::ENABLED : PiPControlStatus::DISABLED);
301 return NapiGetUndefined(env);
302 }
303
RegisterCallback(napi_env env,napi_callback_info info)304 napi_value JsPipController::RegisterCallback(napi_env env, napi_callback_info info)
305 {
306 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
307 return (me != nullptr) ? me->OnRegisterCallback(env, info) : nullptr;
308 }
309
OnRegisterCallback(napi_env env,napi_callback_info info)310 napi_value JsPipController::OnRegisterCallback(napi_env env, napi_callback_info info)
311 {
312 TLOGI(WmsLogTag::WMS_PIP, "OnRegisterCallback is called");
313 size_t argc = NUMBER_FOUR;
314 napi_value argv[NUMBER_FOUR] = {nullptr};
315 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
316 if (argc < NUMBER_TWO) {
317 TLOGE(WmsLogTag::WMS_PIP, "JsPipController Params not match: %{public}zu", argc);
318 return NapiThrowInvalidParam(env);
319 }
320 std::string cbType = "";
321 if (!ConvertFromJsValue(env, argv[0], cbType)) {
322 TLOGE(WmsLogTag::WMS_PIP, "Failed to convert parameter to callbackType");
323 return NapiThrowInvalidParam(env);
324 }
325 napi_value value = argv[1];
326 if (value == nullptr || !NapiIsCallable(env, value)) {
327 TLOGE(WmsLogTag::WMS_PIP, "Callback is nullptr or not callable");
328 return NapiThrowInvalidParam(env);
329 }
330 WmErrorCode ret = RegisterListenerWithType(env, cbType, value);
331 if (ret != WmErrorCode::WM_OK) {
332 TLOGE(WmsLogTag::WMS_PIP, "OnRegisterCallback failed");
333 return NapiThrowInvalidParam(env);
334 }
335 return NapiGetUndefined(env);
336 }
337
RegisterListenerWithType(napi_env env,const std::string & type,napi_value value)338 WmErrorCode JsPipController::RegisterListenerWithType(napi_env env, const std::string& type, napi_value value)
339 {
340 if (IfCallbackRegistered(env, type, value)) {
341 TLOGE(WmsLogTag::WMS_PIP, "Callback already registered!");
342 return WmErrorCode::WM_ERROR_INVALID_CALLING;
343 }
344 std::shared_ptr<NativeReference> callbackRef;
345 napi_ref result = nullptr;
346 napi_create_reference(env, value, 1, &result);
347 callbackRef.reset(reinterpret_cast<NativeReference*>(result));
348 auto pipWindowListener = sptr<JsPiPWindowListener>::MakeSptr(env, callbackRef);
349 if (pipWindowListener == nullptr) {
350 TLOGE(WmsLogTag::WMS_PIP, "New JsPiPWindowListener failed");
351 return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
352 }
353 jsCbMap_[type].insert(pipWindowListener);
354
355 switch (listenerCodeMap_[type]) {
356 case ListenerType::STATE_CHANGE_CB:
357 ProcessStateChangeRegister(pipWindowListener);
358 break;
359 case ListenerType::CONTROL_PANEL_ACTION_EVENT_CB:
360 ProcessActionEventRegister(pipWindowListener);
361 break;
362 case ListenerType::CONTROL_EVENT_CB:
363 ProcessControlEventRegister(pipWindowListener);
364 break;
365 default:
366 break;
367 }
368 TLOGI(WmsLogTag::WMS_PIP, "Register type %{public}s success! callback map size: %{public}zu",
369 type.c_str(), jsCbMap_[type].size());
370 return WmErrorCode::WM_OK;
371 }
372
IfCallbackRegistered(napi_env env,const std::string & type,napi_value jsListenerObject)373 bool JsPipController::IfCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject)
374 {
375 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
376 TLOGI(WmsLogTag::WMS_PIP, "methodName %{public}s not registered!", type.c_str());
377 return false;
378 }
379 for (auto& listener : jsCbMap_[type]) {
380 bool isEquals = false;
381 napi_strict_equals(env, jsListenerObject, listener->GetCallbackRef()->GetNapiValue(), &isEquals);
382 if (isEquals) {
383 TLOGE(WmsLogTag::WMS_PIP, "Callback already registered!");
384 return true;
385 }
386 }
387 return false;
388 }
389
ProcessStateChangeRegister(const sptr<JsPiPWindowListener> & listener)390 void JsPipController::ProcessStateChangeRegister(const sptr<JsPiPWindowListener>& listener)
391 {
392 if (pipController_ == nullptr) {
393 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
394 return;
395 }
396 sptr<IPiPLifeCycle> thisListener(listener);
397 pipController_->RegisterPiPLifecycle(thisListener);
398 }
399
ProcessActionEventRegister(const sptr<JsPiPWindowListener> & listener)400 void JsPipController::ProcessActionEventRegister(const sptr<JsPiPWindowListener>& listener)
401 {
402 if (pipController_ == nullptr) {
403 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
404 return;
405 }
406 sptr<IPiPActionObserver> thisListener(listener);
407 pipController_->RegisterPiPActionObserver(listener);
408 }
409
ProcessControlEventRegister(const sptr<JsPiPWindowListener> & listener)410 void JsPipController::ProcessControlEventRegister(const sptr<JsPiPWindowListener>& listener)
411 {
412 if (pipController_ == nullptr) {
413 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
414 return;
415 }
416 sptr<IPiPControlObserver> thisListener(listener);
417 pipController_->RegisterPiPControlObserver(thisListener);
418 }
419
ProcessStateChangeUnRegister(const sptr<JsPiPWindowListener> & listener)420 void JsPipController::ProcessStateChangeUnRegister(const sptr<JsPiPWindowListener>& listener)
421 {
422 if (pipController_ == nullptr) {
423 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
424 return;
425 }
426 sptr<IPiPLifeCycle> thisListener(listener);
427 pipController_->UnregisterPiPLifecycle(thisListener);
428 }
429
ProcessActionEventUnRegister(const sptr<JsPiPWindowListener> & listener)430 void JsPipController::ProcessActionEventUnRegister(const sptr<JsPiPWindowListener>& listener)
431 {
432 if (pipController_ == nullptr) {
433 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
434 return;
435 }
436 sptr<IPiPActionObserver> thisListener(listener);
437 pipController_->UnregisterPiPActionObserver(thisListener);
438 }
439
ProcessControlEventUnRegister(const sptr<JsPiPWindowListener> & listener)440 void JsPipController::ProcessControlEventUnRegister(const sptr<JsPiPWindowListener>& listener)
441 {
442 if (pipController_ == nullptr) {
443 TLOGE(WmsLogTag::WMS_PIP, "controller is nullptr");
444 return;
445 }
446 sptr<IPiPControlObserver> thisListener(listener);
447 pipController_->UnregisterPiPControlObserver(thisListener);
448 }
449
UnregisterCallback(napi_env env,napi_callback_info info)450 napi_value JsPipController::UnregisterCallback(napi_env env, napi_callback_info info)
451 {
452 JsPipController* me = CheckParamsAndGetThis<JsPipController>(env, info);
453 return (me != nullptr) ? me->OnUnregisterCallback(env, info) : nullptr;
454 }
455
OnUnregisterCallback(napi_env env,napi_callback_info info)456 napi_value JsPipController::OnUnregisterCallback(napi_env env, napi_callback_info info)
457 {
458 size_t argc = NUMBER_FOUR;
459 napi_value argv[NUMBER_FOUR] = {nullptr};
460 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
461 if (argc == NUMBER_ZERO || argc > NUMBER_TWO) {
462 TLOGE(WmsLogTag::WMS_PIP, "JsPipController Params not match: %{public}zu", argc);
463 return NapiThrowInvalidParam(env);
464 }
465 std::string cbType = "";
466 if (!ConvertFromJsValue(env, argv[0], cbType)) {
467 TLOGE(WmsLogTag::WMS_PIP, "Failed to convert parameter to string");
468 return NapiThrowInvalidParam(env);
469 }
470 if (argc == NUMBER_ONE) {
471 UnRegisterListenerWithType(env, cbType, nullptr);
472 return NapiGetUndefined(env);
473 }
474 napi_value value = argv[NUMBER_ONE];
475 if (value != nullptr && NapiIsCallable(env, value)) {
476 UnRegisterListenerWithType(env, cbType, value);
477 }
478 return NapiGetUndefined(env);
479 }
480
UnRegisterListenerWithType(napi_env env,const std::string & type,napi_value value)481 WmErrorCode JsPipController::UnRegisterListenerWithType(napi_env env, const std::string& type, napi_value value)
482 {
483 if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
484 TLOGI(WmsLogTag::WMS_PIP, "methodName %{public}s not registered!", type.c_str());
485 return WmErrorCode::WM_ERROR_INVALID_CALLING;
486 }
487
488 if (value == nullptr) {
489 for (auto& listener : jsCbMap_[type]) {
490 WmErrorCode ret = UnRegisterListener(type, listener);
491 if (ret != WmErrorCode::WM_OK) {
492 TLOGE(WmsLogTag::WMS_PIP, "Unregister type %{public}s failed, no value", type.c_str());
493 return ret;
494 }
495 }
496 jsCbMap_.erase(type);
497 } else {
498 bool foundCallbackValue = false;
499 for (auto& listener : jsCbMap_[type]) {
500 bool isEquals = false;
501 napi_strict_equals(env, value, listener->GetCallbackRef()->GetNapiValue(), &isEquals);
502 if (!isEquals) {
503 continue;
504 }
505 foundCallbackValue = true;
506 WmErrorCode ret = UnRegisterListener(type, listener);
507 if (ret != WmErrorCode::WM_OK) {
508 TLOGE(WmsLogTag::WMS_PIP, "Unregister type %{public}s failed", type.c_str());
509 return ret;
510 }
511 jsCbMap_[type].erase(listener);
512 break;
513 }
514 if (!foundCallbackValue) {
515 TLOGE(WmsLogTag::WMS_PIP, "Unregister type %{public}s failed because not found callback!", type.c_str());
516 return WmErrorCode::WM_OK;
517 }
518 if (jsCbMap_[type].empty()) {
519 jsCbMap_.erase(type);
520 }
521 }
522 TLOGI(WmsLogTag::WMS_PIP, "Unregister type %{public}s success!", type.c_str());
523 return WmErrorCode::WM_OK;
524 }
525
UnRegisterListener(const std::string & type,const sptr<JsPiPWindowListener> & pipWindowListener)526 WmErrorCode JsPipController::UnRegisterListener(const std::string& type,
527 const sptr<JsPiPWindowListener>& pipWindowListener)
528 {
529 switch (listenerCodeMap_[type]) {
530 case ListenerType::STATE_CHANGE_CB:
531 ProcessStateChangeUnRegister(pipWindowListener);
532 break;
533 case ListenerType::CONTROL_PANEL_ACTION_EVENT_CB:
534 ProcessActionEventUnRegister(pipWindowListener);
535 break;
536 case ListenerType::CONTROL_EVENT_CB:
537 ProcessControlEventUnRegister(pipWindowListener);
538 break;
539 default:
540 break;
541 }
542 return WmErrorCode::WM_OK;
543 }
544 } // namespace Rosen
545 } // namespace OHOS
546