1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "listener_base.h"
16 
17 #include <uv.h>
18 
19 #include "camera_log.h"
20 #include "js_native_api.h"
21 #include "js_native_api_types.h"
22 
23 namespace OHOS {
24 namespace CameraStandard {
ListenerBase(napi_env env)25 ListenerBase::ListenerBase(napi_env env) : env_(env)
26 {
27     MEDIA_DEBUG_LOG("ListenerBase is called.");
28 }
29 
~ListenerBase()30 ListenerBase::~ListenerBase()
31 {
32     MEDIA_DEBUG_LOG("~ListenerBase is called.");
33 }
34 
SaveCallbackReference(const std::string eventName,napi_value callback,bool isOnce)35 void ListenerBase::SaveCallbackReference(const std::string eventName, napi_value callback, bool isOnce)
36 {
37     if (callback == nullptr) {
38         MEDIA_ERR_LOG("SaveCallbackReference:%s js callback is nullptr, save nothing", eventName.c_str());
39         return;
40     }
41     napi_valuetype valueType = napi_undefined;
42     napi_typeof(env_, callback, &valueType);
43     if (valueType != napi_function) {
44         MEDIA_ERR_LOG("SaveCallbackReference:%s js callback valueType is not function", eventName.c_str());
45         return;
46     }
47     auto& callbackList = GetCallbackList(eventName);
48     std::lock_guard<std::mutex> lock(callbackList.listMutex);
49     for (auto it = callbackList.refList.begin(); it != callbackList.refList.end(); ++it) {
50         bool isSameCallback = CameraNapiUtils::IsSameNapiValue(env_, callback, it->GetCallbackFunction());
51         CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: has same callback, nothing to do");
52     }
53     callbackList.refList.emplace_back(AutoRef(env_, callback, isOnce));
54     MEDIA_DEBUG_LOG("Save callback reference success, %s callback list size [%{public}zu]", eventName.c_str(),
55         callbackList.refList.size());
56 }
57 
RemoveCallbackRef(const std::string eventName,napi_value callback)58 void ListenerBase::RemoveCallbackRef(const std::string eventName, napi_value callback)
59 {
60     if (callback == nullptr) {
61         MEDIA_INFO_LOG("RemoveCallbackReference: js callback is nullptr, remove all callback reference");
62         RemoveAllCallbacks(eventName);
63         return;
64     }
65     auto& callbackList = GetCallbackList(eventName);
66     std::lock_guard<std::mutex> lock(callbackList.listMutex);
67     for (auto it = callbackList.refList.begin(); it != callbackList.refList.end(); ++it) {
68         bool isSameCallback = CameraNapiUtils::IsSameNapiValue(env_, callback, it->GetCallbackFunction());
69         if (isSameCallback) {
70             MEDIA_INFO_LOG("RemoveCallbackReference: find %s callback, delete it", eventName.c_str());
71             callbackList.refList.erase(it);
72             return;
73         }
74     }
75     MEDIA_INFO_LOG("RemoveCallbackReference: %s callback not find", eventName.c_str());
76 }
77 
ExecuteCallback(const std::string eventName,const ExecuteCallbackNapiPara & callbackPara) const78 void ListenerBase::ExecuteCallback(const std::string eventName, const ExecuteCallbackNapiPara& callbackPara) const
79 {
80     MEDIA_DEBUG_LOG("ListenerBase::ExecuteCallback is called");
81     auto& callbackList = GetCallbackList(eventName);
82     std::lock_guard<std::mutex> lock(callbackList.listMutex);
83     for (auto it = callbackList.refList.begin(); it != callbackList.refList.end();) {
84         napi_call_function(env_, callbackPara.recv, it->GetCallbackFunction(), callbackPara.argc, callbackPara.argv,
85             callbackPara.result);
86         if (it->isOnce_) {
87             callbackList.refList.erase(it);
88         } else {
89             it++;
90         }
91     }
92     MEDIA_DEBUG_LOG("ListenerBase::ExecuteCallback, %s callback list size [%{public}zu]", eventName.c_str(),
93         callbackList.refList.size());
94 }
95 
RemoveAllCallbacks(const std::string eventName)96 void ListenerBase::RemoveAllCallbacks(const std::string eventName)
97 {
98     auto& callbackList = GetCallbackList(eventName);
99     std::lock_guard<std::mutex> lock(callbackList.listMutex);
100     callbackList.refList.clear();
101     MEDIA_INFO_LOG("RemoveAllCallbacks: remove all js callbacks success");
102 }
103 
IsEmpty(const std::string eventName) const104 bool ListenerBase::IsEmpty(const std::string eventName) const
105 {
106     auto& callbackList = GetCallbackList(eventName);
107     std::lock_guard<std::mutex> lock(callbackList.listMutex);
108     return callbackList.refList.empty();
109 }
110 } // namespace CameraStandard
111 } // namespace OHOS
112