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.
5 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "device/bluetooth/bluetooth_device.h"
10 #include "device/bluetooth/bluetooth_device_chromeos.h"
12 using device::BluetoothDevice
;
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
29 // Number of keys that will be entered for a passkey, six digits plus the
31 const uint16 kPasskeyMaxKeysEntered
= 7;
37 BluetoothPairingChromeOS::BluetoothPairingChromeOS(
38 BluetoothDeviceChromeOS
* device
,
39 BluetoothDevice::PairingDelegate
* pairing_delegate
)
41 pairing_delegate_(pairing_delegate
),
42 pairing_delegate_used_(false) {
43 VLOG(1) << "Created BluetoothPairingChromeOS for "
44 << device_
->GetAddress();
47 BluetoothPairingChromeOS::~BluetoothPairingChromeOS() {
48 VLOG(1) << "Destroying BluetoothPairingChromeOS for "
49 << device_
->GetAddress();
51 if (!pairing_delegate_used_
) {
52 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
53 UMA_PAIRING_METHOD_NONE
,
54 UMA_PAIRING_METHOD_COUNT
);
57 if (!pincode_callback_
.is_null()) {
58 pincode_callback_
.Run(
59 BluetoothAgentServiceProvider::Delegate::CANCELLED
, "");
62 if (!passkey_callback_
.is_null()) {
63 passkey_callback_
.Run(
64 BluetoothAgentServiceProvider::Delegate::CANCELLED
, 0);
67 if (!confirmation_callback_
.is_null()) {
68 confirmation_callback_
.Run(
69 BluetoothAgentServiceProvider::Delegate::CANCELLED
);
72 pairing_delegate_
= NULL
;
75 void BluetoothPairingChromeOS::RequestPinCode(
76 const BluetoothAgentServiceProvider::Delegate::PinCodeCallback
& callback
) {
77 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
78 UMA_PAIRING_METHOD_REQUEST_PINCODE
,
79 UMA_PAIRING_METHOD_COUNT
);
82 pincode_callback_
= callback
;
83 pairing_delegate_used_
= true;
84 pairing_delegate_
->RequestPinCode(device_
);
87 bool BluetoothPairingChromeOS::ExpectingPinCode() const {
88 return !pincode_callback_
.is_null();
91 void BluetoothPairingChromeOS::SetPinCode(const std::string
& pincode
) {
92 if (pincode_callback_
.is_null())
95 pincode_callback_
.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS
,
97 pincode_callback_
.Reset();
99 // If this is not an outgoing connection to the device, clean up the pairing
100 // context since the pairing is done. The outgoing connection case is cleaned
101 // up in the callback for the underlying Pair() call.
102 if (!device_
->IsConnecting())
103 device_
->EndPairing();
106 void BluetoothPairingChromeOS::DisplayPinCode(const std::string
& pincode
) {
107 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
108 UMA_PAIRING_METHOD_DISPLAY_PINCODE
,
109 UMA_PAIRING_METHOD_COUNT
);
112 pairing_delegate_used_
= true;
113 pairing_delegate_
->DisplayPinCode(device_
, pincode
);
115 // If this is not an outgoing connection to the device, the pairing context
116 // needs to be cleaned up again as there's no reliable indication of
117 // completion of incoming pairing.
118 if (!device_
->IsConnecting())
119 device_
->EndPairing();
122 void BluetoothPairingChromeOS::RequestPasskey(
123 const BluetoothAgentServiceProvider::Delegate::PasskeyCallback
& callback
) {
124 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
125 UMA_PAIRING_METHOD_REQUEST_PASSKEY
,
126 UMA_PAIRING_METHOD_COUNT
);
129 passkey_callback_
= callback
;
130 pairing_delegate_used_
= true;
131 pairing_delegate_
->RequestPasskey(device_
);
134 bool BluetoothPairingChromeOS::ExpectingPasskey() const {
135 return !passkey_callback_
.is_null();
138 void BluetoothPairingChromeOS::SetPasskey(uint32 passkey
) {
139 if (passkey_callback_
.is_null())
142 passkey_callback_
.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS
,
144 passkey_callback_
.Reset();
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();
153 void BluetoothPairingChromeOS::DisplayPasskey(uint32 passkey
) {
154 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
155 UMA_PAIRING_METHOD_DISPLAY_PASSKEY
,
156 UMA_PAIRING_METHOD_COUNT
);
159 pairing_delegate_used_
= true;
160 pairing_delegate_
->DisplayPasskey(device_
, passkey
);
164 void BluetoothPairingChromeOS::KeysEntered(uint16 entered
) {
165 pairing_delegate_used_
= true;
166 pairing_delegate_
->KeysEntered(device_
, entered
);
168 // If this is not an outgoing connection to the device, the pairing context
169 // needs to be cleaned up again as there's no reliable indication of
170 // completion of incoming pairing.
171 if (entered
>= kPasskeyMaxKeysEntered
&& !device_
->IsConnecting())
172 device_
->EndPairing();
175 void BluetoothPairingChromeOS::RequestConfirmation(
177 const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback
&
179 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
180 UMA_PAIRING_METHOD_CONFIRM_PASSKEY
,
181 UMA_PAIRING_METHOD_COUNT
);
184 confirmation_callback_
= callback
;
185 pairing_delegate_used_
= true;
186 pairing_delegate_
->ConfirmPasskey(device_
, passkey
);
189 void BluetoothPairingChromeOS::RequestAuthorization(
190 const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback
&
192 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
193 UMA_PAIRING_METHOD_NONE
,
194 UMA_PAIRING_METHOD_COUNT
);
197 confirmation_callback_
= callback
;
198 pairing_delegate_used_
= true;
199 pairing_delegate_
->AuthorizePairing(device_
);
202 bool BluetoothPairingChromeOS::ExpectingConfirmation() const {
203 return !confirmation_callback_
.is_null();
206 void BluetoothPairingChromeOS::ConfirmPairing() {
207 if (confirmation_callback_
.is_null())
210 confirmation_callback_
.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS
);
211 confirmation_callback_
.Reset();
213 // If this is not an outgoing connection to the device, clean up the pairing
214 // context since the pairing is done. The outgoing connection case is cleaned
215 // up in the callback for the underlying Pair() call.
216 if (!device_
->IsConnecting())
217 device_
->EndPairing();
220 bool BluetoothPairingChromeOS::RejectPairing() {
221 return RunPairingCallbacks(
222 BluetoothAgentServiceProvider::Delegate::REJECTED
);
225 bool BluetoothPairingChromeOS::CancelPairing() {
226 return RunPairingCallbacks(
227 BluetoothAgentServiceProvider::Delegate::CANCELLED
);
230 BluetoothDevice::PairingDelegate
*
231 BluetoothPairingChromeOS::GetPairingDelegate() const {
232 return pairing_delegate_
;
235 void BluetoothPairingChromeOS::ResetCallbacks() {
236 pincode_callback_
.Reset();
237 passkey_callback_
.Reset();
238 confirmation_callback_
.Reset();
241 bool BluetoothPairingChromeOS::RunPairingCallbacks(
242 BluetoothAgentServiceProvider::Delegate::Status status
) {
243 pairing_delegate_used_
= true;
245 bool callback_run
= false;
246 if (!pincode_callback_
.is_null()) {
247 pincode_callback_
.Run(status
, "");
248 pincode_callback_
.Reset();
252 if (!passkey_callback_
.is_null()) {
253 passkey_callback_
.Run(status
, 0);
254 passkey_callback_
.Reset();
258 if (!confirmation_callback_
.is_null()) {
259 confirmation_callback_
.Run(status
);
260 confirmation_callback_
.Reset();
264 // If this is not an outgoing connection to the device, clean up the pairing
265 // context since the pairing is done. The outgoing connection case is cleaned
266 // up in the callback for the underlying Pair() call.
267 if (!device_
->IsConnecting())
268 device_
->EndPairing();
273 } // namespace chromeos