1 /*
2 * Copyright (c) 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
16 #include "scan_callback.h"
17 #include "napi/native_node_api.h"
18 #include "napi_scan_utils.h"
19 #include "scan_log.h"
20 #include "scanner_info_helper.h"
21
22 namespace OHOS::Scan {
ScanCallback(napi_env env,napi_ref ref)23 ScanCallback::ScanCallback(napi_env env, napi_ref ref) : env_(env), ref_(ref), callbackFunction_(nullptr)
24 {
25 }
26
ScanCallback(std::function<void (std::vector<ScanDeviceInfo> & infos)> callbackFunction)27 ScanCallback::ScanCallback(std::function<void(std::vector<ScanDeviceInfo> &infos)>
28 callbackFunction) : env_(nullptr), ref_(nullptr), callbackFunction_(callbackFunction)
29 {
30 }
31
~ScanCallback()32 ScanCallback::~ScanCallback()
33 {
34 std::lock_guard<std::mutex> autoLock(mutex_);
35 if (env_ == nullptr || ref_ == nullptr) {
36 return;
37 }
38 SCAN_HILOGI("callback has been destroyed");
39 Param *param = new (std::nothrow) Param;
40 if (param == nullptr) {
41 return;
42 }
43 param->env = env_;
44 param->callbackRef = ref_;
45 auto task = [param]() {
46 SCAN_HILOGI("napi_send_event ScanCallback DeleteReference");
47 if (param == nullptr) {
48 return;
49 }
50 napi_handle_scope scope = nullptr;
51 napi_open_handle_scope(param->env, &scope);
52 if (scope == nullptr) {
53 delete param;
54 return;
55 }
56 napi_ref callbackRef = param->callbackRef;
57 NapiScanUtils::DeleteReference(param->env, callbackRef);
58 napi_close_handle_scope(param->env, scope);
59 delete param;
60 };
61 if (napi_send_event(env_, task, napi_eprio_low) != napi_ok) {
62 SCAN_HILOGE("Failed to send event");
63 delete param;
64 }
65 }
66
InitialCallbackParam(napi_env & env_,napi_ref & ref_,std::mutex & mutex_)67 void CallbackParam::InitialCallbackParam(napi_env &env_, napi_ref &ref_, std::mutex &mutex_)
68 {
69 std::lock_guard<std::mutex> lock(mutex_);
70 this->env = env_;
71 this->ref = ref_;
72 this->mutexPtr = &mutex_;
73 }
74
SetCallbackParam(uint32_t & state,const ScanDeviceInfo & deviceInfo)75 void CallbackParam::SetCallbackParam(uint32_t &state, const ScanDeviceInfo &deviceInfo)
76 {
77 this->state = state;
78 this->deviceInfo = deviceInfo;
79 }
80
SetCallbackSyncParam(uint32_t & state,const ScanDeviceInfoSync & deviceInfoSync)81 void CallbackParam::SetCallbackSyncParam(uint32_t &state, const ScanDeviceInfoSync &deviceInfoSync)
82 {
83 this->state = state;
84 this->deviceInfoSync = deviceInfoSync;
85 }
86
ExecuteNapiEventWork(CallbackParam * param,std::function<void (CallbackParam *)> workFunc)87 bool ScanCallback::ExecuteNapiEventWork(CallbackParam* param, std::function<void(CallbackParam*)> workFunc)
88 {
89 auto task = [param, workFunc]() {
90 if (param == nullptr) {
91 SCAN_HILOGE("param is a nullptr");
92 return;
93 }
94 napi_handle_scope scope = nullptr;
95 napi_open_handle_scope(param->env, &scope);
96 if (scope == nullptr) {
97 delete param;
98 return;
99 }
100 std::lock_guard<std::mutex> autoLock(*param->mutexPtr);
101 napi_value callbackFunc = NapiScanUtils::GetReference(param->env, param->ref);
102 if (callbackFunc != nullptr) {
103 workFunc(param);
104 SCAN_HILOGD("run napi call deviceInfo callback fun success");
105 } else {
106 SCAN_HILOGE("get reference failed");
107 }
108 napi_close_handle_scope(param->env, scope);
109 delete param;
110 };
111
112 napi_status ret = napi_send_event(env_, task, napi_eprio_immediate);
113 if (ret != napi_ok) {
114 SCAN_HILOGE("napi_send_event fail");
115 delete param;
116 return false;
117 }
118 return true;
119 }
120
NapiCallFunction(CallbackParam * cbParam,size_t argcCount,napi_value * callbackValues)121 void ScanCallback::NapiCallFunction(CallbackParam* cbParam, size_t argcCount, napi_value* callbackValues)
122 {
123 if (cbParam == nullptr) {
124 SCAN_HILOGE("cbParam is a nullptr");
125 return;
126 }
127 napi_value callbackFunc = NapiScanUtils::GetReference(cbParam->env, cbParam->ref);
128 if (callbackFunc != nullptr) {
129 napi_call_function(cbParam->env, nullptr, callbackFunc,
130 argcCount, callbackValues, nullptr);
131 }
132 }
133
OnCallback(uint32_t state,const ScanDeviceInfo & info)134 bool ScanCallback::OnCallback(uint32_t state, const ScanDeviceInfo &info)
135 {
136 SCAN_HILOGD("Enter OnCallback::ScanDeviceInfo");
137
138 CallbackParam *param = new (std::nothrow) CallbackParam;
139 if (param == nullptr) {
140 SCAN_HILOGE("Failed to create callback parameter");
141 return false;
142 }
143
144 param->InitialCallbackParam(env_, ref_, mutex_);
145 param->SetCallbackParam(state, info);
146
147 auto workFunc = [this](CallbackParam* cbParam) {
148 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
149 callbackValues[0] = ScannerInfoHelper::MakeJsObject(cbParam->env, cbParam->deviceInfo);
150 NapiCallFunction(cbParam, NapiScanUtils::ARGC_ONE, callbackValues);
151 };
152
153 return ExecuteNapiEventWork(param, workFunc);
154 }
155
OnCallbackSync(uint32_t state,const ScanDeviceInfoSync & info)156 bool ScanCallback::OnCallbackSync(uint32_t state, const ScanDeviceInfoSync &info)
157 {
158 SCAN_HILOGD("Enter OnCallback::ScanDeviceInfo");
159
160 CallbackParam *param = new (std::nothrow) CallbackParam;
161 if (param == nullptr) {
162 SCAN_HILOGE("Failed to create callback parameter");
163 return false;
164 }
165
166 param->InitialCallbackParam(env_, ref_, mutex_);
167 param->SetCallbackSyncParam(state, info);
168
169 auto workFunc = [this](CallbackParam* cbParam) {
170 napi_value callbackValues[NapiScanUtils::ARGC_ONE] = { 0 };
171 callbackValues[0] = ScannerInfoSyncHelper::MakeJsObject(cbParam->env, cbParam->deviceInfoSync);
172 NapiCallFunction(cbParam, NapiScanUtils::ARGC_ONE, callbackValues);
173 };
174
175 return ExecuteNapiEventWork(param, workFunc);
176 }
177
OnGetDevicesList(std::vector<ScanDeviceInfo> & infos)178 bool ScanCallback::OnGetDevicesList(std::vector<ScanDeviceInfo> &infos)
179 {
180 SCAN_HILOGI("Enter OnGetDevicesList");
181 if (callbackFunction_ == nullptr) {
182 SCAN_HILOGE("callbackFunction_ is a nullptr");
183 return false;
184 }
185 callbackFunction_(infos);
186 return true;
187 }
188 } // namespace OHOS::Scan
189