OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "device/bluetooth/bluetooth_pairing_bluez.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/metrics/histogram.h" | |
9 #include "device/bluetooth/bluetooth_device.h" | |
10 #include "device/bluetooth/bluetooth_device_bluez.h" | |
11 | |
12 using device::BluetoothDevice; | |
13 | |
14 namespace { | |
15 | |
16 // Histogram enumerations for pairing methods. | |
17 enum UMAPairingMethod { | |
18 UMA_PAIRING_METHOD_NONE, | |
19 UMA_PAIRING_METHOD_REQUEST_PINCODE, | |
20 UMA_PAIRING_METHOD_REQUEST_PASSKEY, | |
21 UMA_PAIRING_METHOD_DISPLAY_PINCODE, | |
22 UMA_PAIRING_METHOD_DISPLAY_PASSKEY, | |
23 UMA_PAIRING_METHOD_CONFIRM_PASSKEY, | |
24 // NOTE: Add new pairing methods immediately above this line. Make sure to | |
25 // update the enum list in tools/histogram/histograms.xml accordingly. | |
26 UMA_PAIRING_METHOD_COUNT | |
27 }; | |
28 | |
29 // Number of keys that will be entered for a passkey, six digits plus the | |
30 // final enter. | |
31 const uint16_t kPasskeyMaxKeysEntered = 7; | |
32 | |
33 } // namespace | |
34 | |
35 namespace bluez { | |
36 | |
37 BluetoothPairingBlueZ::BluetoothPairingBlueZ( | |
38 BluetoothDeviceBlueZ* device, | |
39 BluetoothDevice::PairingDelegate* pairing_delegate) | |
40 : device_(device), | |
41 pairing_delegate_(pairing_delegate), | |
42 pairing_delegate_used_(false) { | |
43 VLOG(1) << "Created BluetoothPairingBlueZ for " << device_->GetAddress(); | |
44 } | |
45 | |
46 BluetoothPairingBlueZ::~BluetoothPairingBlueZ() { | |
47 VLOG(1) << "Destroying BluetoothPairingBlueZ for " << device_->GetAddress(); | |
48 | |
49 if (!pairing_delegate_used_) { | |
50 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
51 UMA_PAIRING_METHOD_NONE, | |
52 UMA_PAIRING_METHOD_COUNT); | |
53 } | |
54 | |
55 if (!pincode_callback_.is_null()) { | |
56 pincode_callback_.Run( | |
57 bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, ""); | |
58 } | |
59 | |
60 if (!passkey_callback_.is_null()) { | |
61 passkey_callback_.Run( | |
62 bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, 0); | |
63 } | |
64 | |
65 if (!confirmation_callback_.is_null()) { | |
66 confirmation_callback_.Run( | |
67 bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED); | |
68 } | |
69 | |
70 pairing_delegate_ = NULL; | |
71 } | |
72 | |
73 void BluetoothPairingBlueZ::RequestPinCode( | |
74 const bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback& | |
75 callback) { | |
76 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
77 UMA_PAIRING_METHOD_REQUEST_PINCODE, | |
78 UMA_PAIRING_METHOD_COUNT); | |
79 | |
80 ResetCallbacks(); | |
81 pincode_callback_ = callback; | |
82 pairing_delegate_used_ = true; | |
83 pairing_delegate_->RequestPinCode(device_); | |
84 } | |
85 | |
86 bool BluetoothPairingBlueZ::ExpectingPinCode() const { | |
87 return !pincode_callback_.is_null(); | |
88 } | |
89 | |
90 void BluetoothPairingBlueZ::SetPinCode(const std::string& pincode) { | |
91 if (pincode_callback_.is_null()) | |
92 return; | |
93 | |
94 pincode_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS, | |
95 pincode); | |
96 pincode_callback_.Reset(); | |
97 | |
98 // If this is not an outgoing connection to the device, clean up the pairing | |
99 // context since the pairing is done. The outgoing connection case is cleaned | |
100 // up in the callback for the underlying Pair() call. | |
101 if (!device_->IsConnecting()) | |
102 device_->EndPairing(); | |
103 } | |
104 | |
105 void BluetoothPairingBlueZ::DisplayPinCode(const std::string& pincode) { | |
106 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
107 UMA_PAIRING_METHOD_DISPLAY_PINCODE, | |
108 UMA_PAIRING_METHOD_COUNT); | |
109 | |
110 ResetCallbacks(); | |
111 pairing_delegate_used_ = true; | |
112 pairing_delegate_->DisplayPinCode(device_, pincode); | |
113 | |
114 // If this is not an outgoing connection to the device, the pairing context | |
115 // needs to be cleaned up again as there's no reliable indication of | |
116 // completion of incoming pairing. | |
117 if (!device_->IsConnecting()) | |
118 device_->EndPairing(); | |
119 } | |
120 | |
121 void BluetoothPairingBlueZ::RequestPasskey( | |
122 const bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback& | |
123 callback) { | |
124 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
125 UMA_PAIRING_METHOD_REQUEST_PASSKEY, | |
126 UMA_PAIRING_METHOD_COUNT); | |
127 | |
128 ResetCallbacks(); | |
129 passkey_callback_ = callback; | |
130 pairing_delegate_used_ = true; | |
131 pairing_delegate_->RequestPasskey(device_); | |
132 } | |
133 | |
134 bool BluetoothPairingBlueZ::ExpectingPasskey() const { | |
135 return !passkey_callback_.is_null(); | |
136 } | |
137 | |
138 void BluetoothPairingBlueZ::SetPasskey(uint32_t passkey) { | |
139 if (passkey_callback_.is_null()) | |
140 return; | |
141 | |
142 passkey_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS, | |
143 passkey); | |
144 passkey_callback_.Reset(); | |
145 | |
146 // If this is not an outgoing connection to the device, clean up the pairing | |
147 // context since the pairing is done. The outgoing connection case is cleaned | |
148 // up in the callback for the underlying Pair() call. | |
149 if (!device_->IsConnecting()) | |
150 device_->EndPairing(); | |
151 } | |
152 | |
153 void BluetoothPairingBlueZ::DisplayPasskey(uint32_t passkey) { | |
154 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
155 UMA_PAIRING_METHOD_DISPLAY_PASSKEY, | |
156 UMA_PAIRING_METHOD_COUNT); | |
157 | |
158 ResetCallbacks(); | |
159 pairing_delegate_used_ = true; | |
160 pairing_delegate_->DisplayPasskey(device_, passkey); | |
161 } | |
162 | |
163 void BluetoothPairingBlueZ::KeysEntered(uint16_t entered) { | |
164 pairing_delegate_used_ = true; | |
165 pairing_delegate_->KeysEntered(device_, entered); | |
166 | |
167 // If this is not an outgoing connection to the device, the pairing context | |
168 // needs to be cleaned up again as there's no reliable indication of | |
169 // completion of incoming pairing. | |
170 if (entered >= kPasskeyMaxKeysEntered && !device_->IsConnecting()) | |
171 device_->EndPairing(); | |
172 } | |
173 | |
174 void BluetoothPairingBlueZ::RequestConfirmation( | |
175 uint32_t passkey, | |
176 const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& | |
177 callback) { | |
178 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", | |
179 UMA_PAIRING_METHOD_CONFIRM_PASSKEY, | |
180 UMA_PAIRING_METHOD_COUNT); | |
181 | |
182 ResetCallbacks(); | |
183 confirmation_callback_ = callback; | |
184 pairing_delegate_used_ = true; | |
185 pairing_delegate_->ConfirmPasskey(device_, passkey); | |
186 } | |
187 | |
188 void BluetoothPairingBlueZ::RequestAuthorization( | |
189 const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& | |
190 callback) { | |
191 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", UMA_PAIRING_METHOD_NONE, | |
192 UMA_PAIRING_METHOD_COUNT); | |
193 | |
194 ResetCallbacks(); | |
195 confirmation_callback_ = callback; | |
196 pairing_delegate_used_ = true; | |
197 pairing_delegate_->AuthorizePairing(device_); | |
198 } | |
199 | |
200 bool BluetoothPairingBlueZ::ExpectingConfirmation() const { | |
201 return !confirmation_callback_.is_null(); | |
202 } | |
203 | |
204 void BluetoothPairingBlueZ::ConfirmPairing() { | |
205 if (confirmation_callback_.is_null()) | |
206 return; | |
207 | |
208 confirmation_callback_.Run( | |
209 bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS); | |
210 confirmation_callback_.Reset(); | |
211 | |
212 // If this is not an outgoing connection to the device, clean up the pairing | |
213 // context since the pairing is done. The outgoing connection case is cleaned | |
214 // up in the callback for the underlying Pair() call. | |
215 if (!device_->IsConnecting()) | |
216 device_->EndPairing(); | |
217 } | |
218 | |
219 bool BluetoothPairingBlueZ::RejectPairing() { | |
220 return RunPairingCallbacks( | |
221 bluez::BluetoothAgentServiceProvider::Delegate::REJECTED); | |
222 } | |
223 | |
224 bool BluetoothPairingBlueZ::CancelPairing() { | |
225 return RunPairingCallbacks( | |
226 bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED); | |
227 } | |
228 | |
229 BluetoothDevice::PairingDelegate* BluetoothPairingBlueZ::GetPairingDelegate() | |
230 const { | |
231 return pairing_delegate_; | |
232 } | |
233 | |
234 void BluetoothPairingBlueZ::ResetCallbacks() { | |
235 pincode_callback_.Reset(); | |
236 passkey_callback_.Reset(); | |
237 confirmation_callback_.Reset(); | |
238 } | |
239 | |
240 bool BluetoothPairingBlueZ::RunPairingCallbacks( | |
241 bluez::BluetoothAgentServiceProvider::Delegate::Status status) { | |
242 pairing_delegate_used_ = true; | |
243 | |
244 bool callback_run = false; | |
245 if (!pincode_callback_.is_null()) { | |
246 pincode_callback_.Run(status, ""); | |
247 pincode_callback_.Reset(); | |
248 callback_run = true; | |
249 } | |
250 | |
251 if (!passkey_callback_.is_null()) { | |
252 passkey_callback_.Run(status, 0); | |
253 passkey_callback_.Reset(); | |
254 callback_run = true; | |
255 } | |
256 | |
257 if (!confirmation_callback_.is_null()) { | |
258 confirmation_callback_.Run(status); | |
259 confirmation_callback_.Reset(); | |
260 callback_run = true; | |
261 } | |
262 | |
263 // If this is not an outgoing connection to the device, clean up the pairing | |
264 // context since the pairing is done. The outgoing connection case is cleaned | |
265 // up in the callback for the underlying Pair() call. | |
266 if (!device_->IsConnecting()) | |
267 device_->EndPairing(); | |
268 | |
269 return callback_run; | |
270 } | |
271 | |
272 } // namespace bluez | |
OLD | NEW |