Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / components / pairing / bluetooth_controller_pairing_controller.cc
blobbb01dd712d74e6de3fe5bc6b7ee982806b82fa5c
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 "components/pairing/bluetooth_controller_pairing_controller.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/pairing/bluetooth_pairing_constants.h"
13 #include "components/pairing/pairing_api.pb.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
15 #include "device/bluetooth/bluetooth_discovery_session.h"
16 #include "net/base/io_buffer.h"
18 namespace {
19 const int kReceiveSize = 16384;
22 namespace pairing_chromeos {
24 BluetoothControllerPairingController::BluetoothControllerPairingController()
25 : current_stage_(STAGE_NONE),
26 got_initial_status_(false),
27 proto_decoder_(new ProtoDecoder(this)),
28 ptr_factory_(this) {
31 BluetoothControllerPairingController::~BluetoothControllerPairingController() {
32 Reset();
35 device::BluetoothDevice* BluetoothControllerPairingController::GetController() {
36 DCHECK(!controller_device_id_.empty());
37 device::BluetoothDevice* device = adapter_->GetDevice(controller_device_id_);
38 if (!device) {
39 LOG(ERROR) << "Lost connection to controller.";
40 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
43 return device;
46 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) {
47 if (current_stage_ == new_stage)
48 return;
49 current_stage_ = new_stage;
50 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
51 PairingStageChanged(new_stage));
54 void BluetoothControllerPairingController::Reset() {
55 got_initial_status_ = false;
56 controller_device_id_.clear();
57 discovery_session_.reset();
59 if (socket_) {
60 socket_->Close();
61 socket_ = NULL;
64 if (adapter_) {
65 adapter_->RemoveObserver(this);
66 adapter_ = NULL;
70 void BluetoothControllerPairingController::DeviceFound(
71 device::BluetoothDevice* device) {
72 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
73 DCHECK(thread_checker_.CalledOnValidThread());
74 if (StartsWith(device->GetName(), base::ASCIIToUTF16(kDeviceNamePrefix),
75 false)) {
76 discovered_devices_.insert(device->GetAddress());
77 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
78 DiscoveredDevicesListChanged());
82 void BluetoothControllerPairingController::DeviceLost(
83 device::BluetoothDevice* device) {
84 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
85 DCHECK(thread_checker_.CalledOnValidThread());
86 std::set<std::string>::iterator ix =
87 discovered_devices_.find(device->GetAddress());
88 if (ix != discovered_devices_.end()) {
89 discovered_devices_.erase(ix);
90 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
91 DiscoveredDevicesListChanged());
95 void BluetoothControllerPairingController::OnSetPowered() {
96 DCHECK(thread_checker_.CalledOnValidThread());
97 adapter_->StartDiscoverySession(
98 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession,
99 ptr_factory_.GetWeakPtr()),
100 base::Bind(&BluetoothControllerPairingController::OnError,
101 ptr_factory_.GetWeakPtr()));
104 void BluetoothControllerPairingController::OnGetAdapter(
105 scoped_refptr<device::BluetoothAdapter> adapter) {
106 DCHECK(thread_checker_.CalledOnValidThread());
107 DCHECK(!adapter_);
108 adapter_ = adapter;
109 adapter_->AddObserver(this);
111 if (adapter_->IsPowered()) {
112 OnSetPowered();
113 } else {
114 adapter_->SetPowered(
115 true,
116 base::Bind(&BluetoothControllerPairingController::OnSetPowered,
117 ptr_factory_.GetWeakPtr()),
118 base::Bind(&BluetoothControllerPairingController::OnError,
119 ptr_factory_.GetWeakPtr()));
123 void BluetoothControllerPairingController::OnStartDiscoverySession(
124 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
125 DCHECK(thread_checker_.CalledOnValidThread());
126 discovery_session_ = discovery_session.Pass();
127 ChangeStage(STAGE_DEVICES_DISCOVERY);
129 device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices();
130 for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin();
131 ix != device_list.end(); ++ix) {
132 DeviceFound(*ix);
136 void BluetoothControllerPairingController::OnConnect() {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 device::BluetoothDevice* device = GetController();
139 if (device) {
140 device->ConnectToService(
141 device::BluetoothUUID(kPairingServiceUUID),
142 base::Bind(&BluetoothControllerPairingController::OnConnectToService,
143 ptr_factory_.GetWeakPtr()),
144 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
145 ptr_factory_.GetWeakPtr()));
149 void BluetoothControllerPairingController::OnConnectToService(
150 scoped_refptr<device::BluetoothSocket> socket) {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 socket_ = socket;
154 socket_->Receive(
155 kReceiveSize,
156 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
157 ptr_factory_.GetWeakPtr()),
158 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
159 ptr_factory_.GetWeakPtr()));
162 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {}
164 void BluetoothControllerPairingController::OnReceiveComplete(
165 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
166 DCHECK(thread_checker_.CalledOnValidThread());
167 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
169 socket_->Receive(
170 kReceiveSize,
171 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
172 ptr_factory_.GetWeakPtr()),
173 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
174 ptr_factory_.GetWeakPtr()));
177 void BluetoothControllerPairingController::OnError() {
178 // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
179 LOG(ERROR) << "Pairing initialization failed";
180 Reset();
183 void BluetoothControllerPairingController::OnErrorWithMessage(
184 const std::string& message) {
185 // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
186 LOG(ERROR) << message;
187 Reset();
190 void BluetoothControllerPairingController::OnConnectError(
191 device::BluetoothDevice::ConnectErrorCode error_code) {
192 DCHECK(thread_checker_.CalledOnValidThread());
193 device::BluetoothDevice* device = GetController();
195 if (device && device->IsPaired()) {
196 // The connection attempt is only used to start the pairing between the
197 // devices. If the connection fails, it's not a problem as long as pairing
198 // was successful.
199 OnConnect();
203 void BluetoothControllerPairingController::OnReceiveError(
204 device::BluetoothSocket::ErrorReason reason,
205 const std::string& error_message) {
206 LOG(ERROR) << reason << ", " << error_message;
207 Reset();
210 void BluetoothControllerPairingController::AddObserver(
211 ControllerPairingController::Observer* observer) {
212 observers_.AddObserver(observer);
215 void BluetoothControllerPairingController::RemoveObserver(
216 ControllerPairingController::Observer* observer) {
217 observers_.RemoveObserver(observer);
220 ControllerPairingController::Stage
221 BluetoothControllerPairingController::GetCurrentStage() {
222 return current_stage_;
225 void BluetoothControllerPairingController::StartPairing() {
226 DCHECK(thread_checker_.CalledOnValidThread());
227 DCHECK(current_stage_ == STAGE_NONE ||
228 current_stage_ == STAGE_DEVICE_NOT_FOUND ||
229 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
230 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
231 // TODO(zork): Add a stage for no bluetooth. (http://crbug.com/405744)
232 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
233 ChangeStage(STAGE_DEVICE_NOT_FOUND);
234 return;
237 device::BluetoothAdapterFactory::GetAdapter(
238 base::Bind(&BluetoothControllerPairingController::OnGetAdapter,
239 ptr_factory_.GetWeakPtr()));
243 ControllerPairingController::DeviceIdList
244 BluetoothControllerPairingController::GetDiscoveredDevices() {
245 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
246 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
249 void BluetoothControllerPairingController::ChooseDeviceForPairing(
250 const std::string& device_id) {
251 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
252 DCHECK(discovered_devices_.count(device_id));
253 discovery_session_.reset();
254 controller_device_id_ = device_id;
256 device::BluetoothDevice* device = GetController();
258 if (device) {
259 ChangeStage(STAGE_ESTABLISHING_CONNECTION);
260 if (device->IsPaired()) {
261 OnConnect();
262 } else {
263 device->Connect(
264 this,
265 base::Bind(&BluetoothControllerPairingController::OnConnect,
266 ptr_factory_.GetWeakPtr()),
267 base::Bind(&BluetoothControllerPairingController::OnConnectError,
268 ptr_factory_.GetWeakPtr()));
273 void BluetoothControllerPairingController::RepeatDiscovery() {
274 DCHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
275 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
276 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
277 Reset();
278 StartPairing();
281 std::string BluetoothControllerPairingController::GetConfirmationCode() {
282 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
283 DCHECK(!confirmation_code_.empty());
284 return confirmation_code_;
287 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect(
288 bool correct) {
289 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
291 device::BluetoothDevice* device = GetController();
292 if (!device)
293 return;
295 if (correct) {
296 device->ConfirmPairing();
297 // Once pairing is confirmed, the connection will either be successful, or
298 // fail. Either case is acceptable as long as the devices are paired.
299 } else {
300 device->RejectPairing();
301 controller_device_id_.clear();
302 RepeatDiscovery();
306 void BluetoothControllerPairingController::SetHostConfiguration(
307 bool accepted_eula,
308 const std::string& lang,
309 const std::string& timezone,
310 bool send_reports,
311 const std::string& keyboard_layout) {
312 // TODO(zork): Get configuration from UI and send to Host.
313 // (http://crbug.com/405744)
316 void BluetoothControllerPairingController::OnAuthenticationDone(
317 const std::string& domain,
318 const std::string& auth_token) {
319 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS);
321 pairing_api::PairDevices pair_devices;
322 pair_devices.set_api_version(kPairingAPIVersion);
323 pair_devices.mutable_parameters()->set_admin_access_token(auth_token);
325 int size = 0;
326 scoped_refptr<net::IOBuffer> io_buffer(
327 ProtoDecoder::SendPairDevices(pair_devices, &size));
329 socket_->Send(
330 io_buffer, size,
331 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
332 ptr_factory_.GetWeakPtr()),
333 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
334 ptr_factory_.GetWeakPtr()));
335 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
338 void BluetoothControllerPairingController::StartSession() {
339 DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE);
340 ChangeStage(STAGE_FINISHED);
343 // ProtoDecoder::Observer:
344 void BluetoothControllerPairingController::OnHostStatusMessage(
345 const pairing_api::HostStatus& message) {
346 if (got_initial_status_) {
347 // TODO(zork): Check that the domain matches. (http://crbug.com/405761)
348 // TODO(zork): Handling updating stages (http://crbug.com/405754).
349 pairing_api::CompleteSetup complete_setup;
350 complete_setup.set_api_version(kPairingAPIVersion);
351 // TODO(zork): Get AddAnother from UI (http://crbug.com/405757)
352 complete_setup.mutable_parameters()->set_add_another(false);
354 int size = 0;
355 scoped_refptr<net::IOBuffer> io_buffer(
356 ProtoDecoder::SendCompleteSetup(complete_setup, &size));
358 socket_->Send(
359 io_buffer, size,
360 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
361 ptr_factory_.GetWeakPtr()),
362 base::Bind(
363 &BluetoothControllerPairingController::OnErrorWithMessage,
364 ptr_factory_.GetWeakPtr()));
365 ChangeStage(STAGE_PAIRING_DONE);
366 } else {
367 got_initial_status_ = true;
369 // TODO(zork): Check domain. (http://crbug.com/405761)
370 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
374 void BluetoothControllerPairingController::OnConfigureHostMessage(
375 const pairing_api::ConfigureHost& message) {
376 NOTREACHED();
379 void BluetoothControllerPairingController::OnPairDevicesMessage(
380 const pairing_api::PairDevices& message) {
381 NOTREACHED();
384 void BluetoothControllerPairingController::OnCompleteSetupMessage(
385 const pairing_api::CompleteSetup& message) {
386 NOTREACHED();
389 void BluetoothControllerPairingController::OnErrorMessage(
390 const pairing_api::Error& message) {
391 LOG(ERROR) << message.parameters().code() << ", " <<
392 message.parameters().description();
393 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
396 void BluetoothControllerPairingController::DeviceAdded(
397 device::BluetoothAdapter* adapter,
398 device::BluetoothDevice* device) {
399 DCHECK_EQ(adapter, adapter_.get());
400 DeviceFound(device);
403 void BluetoothControllerPairingController::DeviceRemoved(
404 device::BluetoothAdapter* adapter,
405 device::BluetoothDevice* device) {
406 DCHECK_EQ(adapter, adapter_.get());
407 DeviceLost(device);
410 void BluetoothControllerPairingController::RequestPinCode(
411 device::BluetoothDevice* device) {
412 // Disallow unknown device.
413 device->RejectPairing();
416 void BluetoothControllerPairingController::RequestPasskey(
417 device::BluetoothDevice* device) {
418 // Disallow unknown device.
419 device->RejectPairing();
422 void BluetoothControllerPairingController::DisplayPinCode(
423 device::BluetoothDevice* device,
424 const std::string& pincode) {
425 // Disallow unknown device.
426 device->RejectPairing();
429 void BluetoothControllerPairingController::DisplayPasskey(
430 device::BluetoothDevice* device,
431 uint32 passkey) {
432 // Disallow unknown device.
433 device->RejectPairing();
436 void BluetoothControllerPairingController::KeysEntered(
437 device::BluetoothDevice* device,
438 uint32 entered) {
439 // Disallow unknown device.
440 device->RejectPairing();
443 void BluetoothControllerPairingController::ConfirmPasskey(
444 device::BluetoothDevice* device,
445 uint32 passkey) {
446 confirmation_code_ = base::StringPrintf("%06d", passkey);
447 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
450 void BluetoothControllerPairingController::AuthorizePairing(
451 device::BluetoothDevice* device) {
452 // Disallow unknown device.
453 device->RejectPairing();
456 } // namespace pairing_chromeos