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