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 "components/pairing/bluetooth_controller_pairing_controller.h" 6 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" 17 18 namespace { 19 const int kReceiveSize = 16384; 20 } 21 22 namespace pairing_chromeos { 23 24 BluetoothControllerPairingController::BluetoothControllerPairingController() 25 : current_stage_(STAGE_NONE), 26 got_initial_status_(false), 27 proto_decoder_(new ProtoDecoder(this)), 28 ptr_factory_(this) { 29 } 30 31 BluetoothControllerPairingController::~BluetoothControllerPairingController() { 32 Reset(); 33 } 34 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); 41 } 42 43 return device; 44 } 45 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)); 52 } 53 54 void BluetoothControllerPairingController::Reset() { 55 got_initial_status_ = false; 56 controller_device_id_.clear(); 57 discovery_session_.reset(); 58 59 if (socket_.get()) { 60 socket_->Close(); 61 socket_ = NULL; 62 } 63 64 if (adapter_.get()) { 65 adapter_->RemoveObserver(this); 66 adapter_ = NULL; 67 } 68 } 69 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()); 79 } 80 } 81 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()); 92 } 93 } 94 95 void BluetoothControllerPairingController::SendBuffer( 96 scoped_refptr<net::IOBuffer> io_buffer, int size) { 97 socket_->Send( 98 io_buffer, size, 99 base::Bind(&BluetoothControllerPairingController::OnSendComplete, 100 ptr_factory_.GetWeakPtr()), 101 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage, 102 ptr_factory_.GetWeakPtr())); 103 } 104 105 void BluetoothControllerPairingController::OnSetPowered() { 106 DCHECK(thread_checker_.CalledOnValidThread()); 107 adapter_->StartDiscoverySession( 108 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession, 109 ptr_factory_.GetWeakPtr()), 110 base::Bind(&BluetoothControllerPairingController::OnError, 111 ptr_factory_.GetWeakPtr())); 112 } 113 114 void BluetoothControllerPairingController::OnGetAdapter( 115 scoped_refptr<device::BluetoothAdapter> adapter) { 116 DCHECK(thread_checker_.CalledOnValidThread()); 117 DCHECK(!adapter_.get()); 118 adapter_ = adapter; 119 adapter_->AddObserver(this); 120 121 if (adapter_->IsPowered()) { 122 OnSetPowered(); 123 } else { 124 adapter_->SetPowered( 125 true, 126 base::Bind(&BluetoothControllerPairingController::OnSetPowered, 127 ptr_factory_.GetWeakPtr()), 128 base::Bind(&BluetoothControllerPairingController::OnError, 129 ptr_factory_.GetWeakPtr())); 130 } 131 } 132 133 void BluetoothControllerPairingController::OnStartDiscoverySession( 134 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { 135 DCHECK(thread_checker_.CalledOnValidThread()); 136 discovery_session_ = discovery_session.Pass(); 137 ChangeStage(STAGE_DEVICES_DISCOVERY); 138 139 device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices(); 140 for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin(); 141 ix != device_list.end(); ++ix) { 142 DeviceFound(*ix); 143 } 144 } 145 146 void BluetoothControllerPairingController::OnConnect() { 147 DCHECK(thread_checker_.CalledOnValidThread()); 148 device::BluetoothDevice* device = GetController(); 149 if (device) { 150 device->ConnectToService( 151 device::BluetoothUUID(kPairingServiceUUID), 152 base::Bind(&BluetoothControllerPairingController::OnConnectToService, 153 ptr_factory_.GetWeakPtr()), 154 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage, 155 ptr_factory_.GetWeakPtr())); 156 } 157 } 158 159 void BluetoothControllerPairingController::OnConnectToService( 160 scoped_refptr<device::BluetoothSocket> socket) { 161 DCHECK(thread_checker_.CalledOnValidThread()); 162 socket_ = socket; 163 164 socket_->Receive( 165 kReceiveSize, 166 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete, 167 ptr_factory_.GetWeakPtr()), 168 base::Bind(&BluetoothControllerPairingController::OnReceiveError, 169 ptr_factory_.GetWeakPtr())); 170 } 171 172 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {} 173 174 void BluetoothControllerPairingController::OnReceiveComplete( 175 int bytes, scoped_refptr<net::IOBuffer> io_buffer) { 176 DCHECK(thread_checker_.CalledOnValidThread()); 177 proto_decoder_->DecodeIOBuffer(bytes, io_buffer); 178 179 socket_->Receive( 180 kReceiveSize, 181 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete, 182 ptr_factory_.GetWeakPtr()), 183 base::Bind(&BluetoothControllerPairingController::OnReceiveError, 184 ptr_factory_.GetWeakPtr())); 185 } 186 187 void BluetoothControllerPairingController::OnError() { 188 LOG(ERROR) << "Pairing initialization failed"; 189 ChangeStage(STAGE_INITIALIZATION_ERROR); 190 Reset(); 191 } 192 193 void BluetoothControllerPairingController::OnErrorWithMessage( 194 const std::string& message) { 195 LOG(ERROR) << message; 196 ChangeStage(STAGE_INITIALIZATION_ERROR); 197 Reset(); 198 } 199 200 void BluetoothControllerPairingController::OnConnectError( 201 device::BluetoothDevice::ConnectErrorCode error_code) { 202 DCHECK(thread_checker_.CalledOnValidThread()); 203 device::BluetoothDevice* device = GetController(); 204 205 if (device && device->IsPaired()) { 206 // The connection attempt is only used to start the pairing between the 207 // devices. If the connection fails, it's not a problem as long as pairing 208 // was successful. 209 OnConnect(); 210 } 211 } 212 213 void BluetoothControllerPairingController::OnReceiveError( 214 device::BluetoothSocket::ErrorReason reason, 215 const std::string& error_message) { 216 LOG(ERROR) << reason << ", " << error_message; 217 Reset(); 218 } 219 220 void BluetoothControllerPairingController::AddObserver( 221 ControllerPairingController::Observer* observer) { 222 observers_.AddObserver(observer); 223 } 224 225 void BluetoothControllerPairingController::RemoveObserver( 226 ControllerPairingController::Observer* observer) { 227 observers_.RemoveObserver(observer); 228 } 229 230 ControllerPairingController::Stage 231 BluetoothControllerPairingController::GetCurrentStage() { 232 return current_stage_; 233 } 234 235 void BluetoothControllerPairingController::StartPairing() { 236 DCHECK(thread_checker_.CalledOnValidThread()); 237 DCHECK(current_stage_ == STAGE_NONE || 238 current_stage_ == STAGE_DEVICE_NOT_FOUND || 239 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR || 240 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR); 241 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { 242 ChangeStage(STAGE_INITIALIZATION_ERROR); 243 return; 244 } 245 246 device::BluetoothAdapterFactory::GetAdapter( 247 base::Bind(&BluetoothControllerPairingController::OnGetAdapter, 248 ptr_factory_.GetWeakPtr())); 249 250 } 251 252 ControllerPairingController::DeviceIdList 253 BluetoothControllerPairingController::GetDiscoveredDevices() { 254 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); 255 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end()); 256 } 257 258 void BluetoothControllerPairingController::ChooseDeviceForPairing( 259 const std::string& device_id) { 260 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); 261 DCHECK(discovered_devices_.count(device_id)); 262 discovery_session_.reset(); 263 controller_device_id_ = device_id; 264 265 device::BluetoothDevice* device = GetController(); 266 267 if (device) { 268 ChangeStage(STAGE_ESTABLISHING_CONNECTION); 269 if (device->IsPaired()) { 270 OnConnect(); 271 } else { 272 device->Connect( 273 this, 274 base::Bind(&BluetoothControllerPairingController::OnConnect, 275 ptr_factory_.GetWeakPtr()), 276 base::Bind(&BluetoothControllerPairingController::OnConnectError, 277 ptr_factory_.GetWeakPtr())); 278 } 279 } 280 } 281 282 void BluetoothControllerPairingController::RepeatDiscovery() { 283 DCHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND || 284 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR || 285 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR); 286 Reset(); 287 StartPairing(); 288 } 289 290 std::string BluetoothControllerPairingController::GetConfirmationCode() { 291 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION); 292 DCHECK(!confirmation_code_.empty()); 293 return confirmation_code_; 294 } 295 296 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect( 297 bool correct) { 298 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION); 299 300 device::BluetoothDevice* device = GetController(); 301 if (!device) 302 return; 303 304 if (correct) { 305 device->ConfirmPairing(); 306 // Once pairing is confirmed, the connection will either be successful, or 307 // fail. Either case is acceptable as long as the devices are paired. 308 } else { 309 device->RejectPairing(); 310 controller_device_id_.clear(); 311 RepeatDiscovery(); 312 } 313 } 314 315 void BluetoothControllerPairingController::SetHostConfiguration( 316 bool accepted_eula, 317 const std::string& lang, 318 const std::string& timezone, 319 bool send_reports, 320 const std::string& keyboard_layout) { 321 322 pairing_api::ConfigureHost host_config; 323 host_config.set_api_version(kPairingAPIVersion); 324 host_config.mutable_parameters()->set_accepted_eula(accepted_eula); 325 host_config.mutable_parameters()->set_lang(lang); 326 host_config.mutable_parameters()->set_timezone(timezone); 327 host_config.mutable_parameters()->set_send_reports(send_reports); 328 host_config.mutable_parameters()->set_keyboard_layout(keyboard_layout); 329 330 int size = 0; 331 scoped_refptr<net::IOBuffer> io_buffer( 332 ProtoDecoder::SendConfigureHost(host_config, &size)); 333 334 SendBuffer(io_buffer, size); 335 } 336 337 void BluetoothControllerPairingController::OnAuthenticationDone( 338 const std::string& domain, 339 const std::string& auth_token) { 340 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS); 341 342 pairing_api::PairDevices pair_devices; 343 pair_devices.set_api_version(kPairingAPIVersion); 344 pair_devices.mutable_parameters()->set_admin_access_token(auth_token); 345 346 int size = 0; 347 scoped_refptr<net::IOBuffer> io_buffer( 348 ProtoDecoder::SendPairDevices(pair_devices, &size)); 349 350 SendBuffer(io_buffer, size); 351 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS); 352 } 353 354 void BluetoothControllerPairingController::StartSession() { 355 DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE); 356 ChangeStage(STAGE_FINISHED); 357 } 358 359 // ProtoDecoder::Observer: 360 void BluetoothControllerPairingController::OnHostStatusMessage( 361 const pairing_api::HostStatus& message) { 362 if (got_initial_status_) { 363 // TODO(zork): Check that the domain matches. (http://crbug.com/405761) 364 // TODO(zork): Handling updating stages (http://crbug.com/405754). 365 pairing_api::CompleteSetup complete_setup; 366 complete_setup.set_api_version(kPairingAPIVersion); 367 // TODO(zork): Get AddAnother from UI (http://crbug.com/405757) 368 complete_setup.mutable_parameters()->set_add_another(false); 369 370 int size = 0; 371 scoped_refptr<net::IOBuffer> io_buffer( 372 ProtoDecoder::SendCompleteSetup(complete_setup, &size)); 373 374 SendBuffer(io_buffer, size); 375 ChangeStage(STAGE_PAIRING_DONE); 376 } else { 377 got_initial_status_ = true; 378 379 // TODO(zork): Check domain. (http://crbug.com/405761) 380 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS); 381 } 382 } 383 384 void BluetoothControllerPairingController::OnConfigureHostMessage( 385 const pairing_api::ConfigureHost& message) { 386 NOTREACHED(); 387 } 388 389 void BluetoothControllerPairingController::OnPairDevicesMessage( 390 const pairing_api::PairDevices& message) { 391 NOTREACHED(); 392 } 393 394 void BluetoothControllerPairingController::OnCompleteSetupMessage( 395 const pairing_api::CompleteSetup& message) { 396 NOTREACHED(); 397 } 398 399 void BluetoothControllerPairingController::OnErrorMessage( 400 const pairing_api::Error& message) { 401 LOG(ERROR) << message.parameters().code() << ", " << 402 message.parameters().description(); 403 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR); 404 } 405 406 void BluetoothControllerPairingController::DeviceAdded( 407 device::BluetoothAdapter* adapter, 408 device::BluetoothDevice* device) { 409 DCHECK_EQ(adapter, adapter_.get()); 410 DeviceFound(device); 411 } 412 413 void BluetoothControllerPairingController::DeviceRemoved( 414 device::BluetoothAdapter* adapter, 415 device::BluetoothDevice* device) { 416 DCHECK_EQ(adapter, adapter_.get()); 417 DeviceLost(device); 418 } 419 420 void BluetoothControllerPairingController::RequestPinCode( 421 device::BluetoothDevice* device) { 422 // Disallow unknown device. 423 device->RejectPairing(); 424 } 425 426 void BluetoothControllerPairingController::RequestPasskey( 427 device::BluetoothDevice* device) { 428 // Disallow unknown device. 429 device->RejectPairing(); 430 } 431 432 void BluetoothControllerPairingController::DisplayPinCode( 433 device::BluetoothDevice* device, 434 const std::string& pincode) { 435 // Disallow unknown device. 436 device->RejectPairing(); 437 } 438 439 void BluetoothControllerPairingController::DisplayPasskey( 440 device::BluetoothDevice* device, 441 uint32 passkey) { 442 // Disallow unknown device. 443 device->RejectPairing(); 444 } 445 446 void BluetoothControllerPairingController::KeysEntered( 447 device::BluetoothDevice* device, 448 uint32 entered) { 449 // Disallow unknown device. 450 device->RejectPairing(); 451 } 452 453 void BluetoothControllerPairingController::ConfirmPasskey( 454 device::BluetoothDevice* device, 455 uint32 passkey) { 456 confirmation_code_ = base::StringPrintf("%06d", passkey); 457 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION); 458 } 459 460 void BluetoothControllerPairingController::AuthorizePairing( 461 device::BluetoothDevice* device) { 462 // Disallow unknown device. 463 device->RejectPairing(); 464 } 465 466 } // namespace pairing_chromeos 467