• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
18 #include <uv.h>
19 
20 #include "camera_log.h"
21 #include "js_native_api.h"
22 #include "js_native_api_types.h"
23 
24 namespace OHOS {
25 namespace CameraStandard {
ListenerBase(napi_env env)26 ListenerBase::ListenerBase(napi_env env) : env_(env)
27 {
28     MEDIA_DEBUG_LOG("ListenerBase is called.");
29 }
30 
~ListenerBase()31 ListenerBase::~ListenerBase()
32 {
33     MEDIA_DEBUG_LOG("~ListenerBase is called.");
34 }
35 
ExecuteCallbackData(napi_env env,napi_value errCode,napi_value returnData)36 ListenerBase::ExecuteCallbackData::ExecuteCallbackData(napi_env env, napi_value errCode, napi_value returnData)
37     : env_(env), errCode_(errCode), returnData_(returnData) {};
38 
SaveCallbackReference(const std::string eventName,napi_value callback,bool isOnce)39 void ListenerBase::SaveCallbackReference(const std::string eventName, napi_value callback, bool isOnce)
40 {
41     CHECK_ERROR_RETURN_LOG(callback == nullptr,
42         "SaveCallbackReference:%s js callback is nullptr, save nothing", eventName.c_str());
43     napi_valuetype valueType = napi_undefined;
44     napi_typeof(env_, callback, &valueType);
45     CHECK_ERROR_RETURN_LOG(valueType != napi_function,
46         "SaveCallbackReference:%s js callback valueType is not function", eventName.c_str());
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_ERROR_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 
ExecuteCallbackScopeSafe(const std::string eventName,const std::function<ExecuteCallbackData ()> fun) const96 void ListenerBase::ExecuteCallbackScopeSafe(
97     const std::string eventName, const std::function<ExecuteCallbackData()> fun) const
98 {
99     napi_handle_scope scope_ = nullptr;
100     napi_open_handle_scope(env_, &scope_);
101 
102     MEDIA_DEBUG_LOG("ListenerBase::ExecuteCallback %{public}s is called", eventName.c_str());
103     auto& callbackList = GetCallbackList(eventName);
104     std::lock_guard<std::mutex> lock(callbackList.listMutex);
105     for (auto it = callbackList.refList.begin(); it != callbackList.refList.end();) {
106         // Do not move this call out of loop.
107         ExecuteCallbackData callbackData = fun();
108         if (callbackData.env_ == nullptr) {
109             MEDIA_ERR_LOG("ExecuteCallback %{public}s env is null ", eventName.c_str());
110             continue;
111         }
112 
113         napi_value result[ARGS_TWO] = { nullptr, nullptr };
114         napi_value retVal;
115         result[0] = callbackData.errCode_;
116         result[1] = callbackData.returnData_;
117 
118         napi_call_function(callbackData.env_, nullptr, it->GetCallbackFunction(), ARGS_TWO, result, &retVal);
119         if (it->isOnce_) {
120             callbackList.refList.erase(it);
121         } else {
122             it++;
123         }
124     }
125     MEDIA_DEBUG_LOG("ListenerBase::ExecuteCallback, %s callback list size [%{public}zu]", eventName.c_str(),
126         callbackList.refList.size());
127 
128     napi_close_handle_scope(env_, scope_);
129 }
130 
RemoveAllCallbacks(const std::string eventName)131 void ListenerBase::RemoveAllCallbacks(const std::string eventName)
132 {
133     auto& callbackList = GetCallbackList(eventName);
134     std::lock_guard<std::mutex> lock(callbackList.listMutex);
135     callbackList.refList.clear();
136     MEDIA_INFO_LOG("RemoveAllCallbacks: remove all js callbacks success");
137 }
138 
IsEmpty(const std::string eventName) const139 bool ListenerBase::IsEmpty(const std::string eventName) const
140 {
141     auto& callbackList = GetCallbackList(eventName);
142     std::lock_guard<std::mutex> lock(callbackList.listMutex);
143     return callbackList.refList.empty();
144 }
145 } // namespace CameraStandard
146 } // namespace OHOS
147