Chromium Code Reviews| 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 "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 char* kFakeEnrollmentDomain = "http://fake.com"; | |
| 20 const int kReceiveSize = 16384; | |
| 21 } | |
| 22 | |
| 23 namespace pairing_chromeos { | |
| 24 | |
| 25 BluetoothControllerPairingController::BluetoothControllerPairingController() | |
| 26 : ptr_factory_(this), | |
| 27 current_stage_(STAGE_NONE), | |
| 28 got_initial_status_(false), | |
| 29 device_(NULL), | |
| 30 proto_decoder_(new ProtoDecoder(this)) { | |
| 31 } | |
|
achuithb
2014/08/20 21:52:32
Is this expected to be created and used on the UI
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 32 | |
| 33 BluetoothControllerPairingController::~BluetoothControllerPairingController() { | |
| 34 Reset(); | |
| 35 } | |
| 36 | |
| 37 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) { | |
| 38 if (current_stage_ == new_stage) | |
| 39 return; | |
| 40 current_stage_ = new_stage; | |
| 41 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_, | |
| 42 PairingStageChanged(new_stage)); | |
| 43 } | |
| 44 | |
| 45 void BluetoothControllerPairingController::Reset() { | |
| 46 got_initial_status_ = false; | |
| 47 device_ = NULL; | |
| 48 discovery_session_.reset(); | |
| 49 | |
| 50 if (socket_) { | |
| 51 socket_->Close(); | |
| 52 socket_ = NULL; | |
| 53 } | |
| 54 | |
| 55 if (adapter_) { | |
| 56 adapter_->RemoveObserver(this); | |
| 57 adapter_ = NULL; | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 void BluetoothControllerPairingController::DeviceFound( | |
| 62 device::BluetoothDevice* device) { | |
| 63 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); | |
| 64 if (StartsWith(device->GetName(), base::ASCIIToUTF16(kDeviceNamePrefix), | |
| 65 false)) { | |
| 66 discovered_devices_.insert(device->GetAddress()); | |
| 67 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_, | |
| 68 DiscoveredDevicesListChanged()); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 void BluetoothControllerPairingController::DeviceLost( | |
| 73 device::BluetoothDevice* device) { | |
| 74 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); | |
| 75 std::set<std::string>::iterator ix = | |
| 76 discovered_devices_.find(device->GetAddress()); | |
| 77 if (ix != discovered_devices_.end()) { | |
| 78 discovered_devices_.erase(ix); | |
| 79 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_, | |
| 80 DiscoveredDevicesListChanged()); | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 void BluetoothControllerPairingController::OnSetPowered() { | |
| 85 adapter_->StartDiscoverySession( | |
| 86 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession, | |
| 87 ptr_factory_.GetWeakPtr()), | |
| 88 base::Bind(&BluetoothControllerPairingController::OnError, | |
| 89 ptr_factory_.GetWeakPtr())); | |
| 90 } | |
| 91 | |
| 92 void BluetoothControllerPairingController::OnGetAdapter( | |
| 93 scoped_refptr<device::BluetoothAdapter> adapter) { | |
| 94 CHECK(!adapter_); | |
| 95 adapter_ = adapter; | |
| 96 adapter_->AddObserver(this); | |
| 97 | |
| 98 if (adapter_->IsPowered()) { | |
| 99 OnSetPowered(); | |
| 100 } else { | |
| 101 adapter_->SetPowered( | |
| 102 true, | |
| 103 base::Bind(&BluetoothControllerPairingController::OnSetPowered, | |
| 104 ptr_factory_.GetWeakPtr()), | |
| 105 base::Bind(&BluetoothControllerPairingController::OnError, | |
| 106 ptr_factory_.GetWeakPtr())); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void BluetoothControllerPairingController::OnStartDiscoverySession( | |
| 111 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | |
| 112 discovery_session_ = discovery_session.Pass(); | |
| 113 ChangeStage(STAGE_DEVICES_DISCOVERY); | |
| 114 | |
| 115 device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices(); | |
| 116 for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin(); | |
| 117 ix != device_list.end(); ++ix) { | |
| 118 DeviceFound(*ix); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 void BluetoothControllerPairingController::OnConnect() { | |
| 123 device_->ConnectToService( | |
| 124 device::BluetoothUUID(kPairingServiceUUID), | |
| 125 base::Bind(&BluetoothControllerPairingController::OnConnectToService, | |
| 126 ptr_factory_.GetWeakPtr()), | |
| 127 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage, | |
| 128 ptr_factory_.GetWeakPtr())); | |
| 129 } | |
| 130 | |
| 131 void BluetoothControllerPairingController::OnConnectToService( | |
| 132 scoped_refptr<device::BluetoothSocket> socket) { | |
| 133 socket_ = socket; | |
| 134 | |
| 135 socket_->Receive( | |
| 136 kReceiveSize, | |
| 137 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete, | |
| 138 ptr_factory_.GetWeakPtr()), | |
| 139 base::Bind(&BluetoothControllerPairingController::OnReceiveError, | |
| 140 ptr_factory_.GetWeakPtr())); | |
| 141 } | |
| 142 | |
| 143 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {} | |
| 144 | |
| 145 void BluetoothControllerPairingController::OnReceiveComplete( | |
| 146 int bytes, scoped_refptr<net::IOBuffer> io_buffer) { | |
| 147 proto_decoder_->DecodeIOBuffer(bytes, io_buffer); | |
| 148 | |
| 149 socket_->Receive( | |
| 150 kReceiveSize, | |
| 151 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete, | |
| 152 ptr_factory_.GetWeakPtr()), | |
| 153 base::Bind(&BluetoothControllerPairingController::OnReceiveError, | |
| 154 ptr_factory_.GetWeakPtr())); | |
| 155 } | |
| 156 | |
| 157 void BluetoothControllerPairingController::OnError() { | |
| 158 ChangeStage(STAGE_DEVICE_NOT_FOUND); | |
|
achuithb
2014/08/20 21:52:32
Shouldn't we be logging something here? Why STAGE_
Zachary Kuznia
2014/08/21 00:42:07
Added TODO and explanation.
| |
| 159 } | |
| 160 | |
| 161 void BluetoothControllerPairingController::OnErrorWithMessage( | |
| 162 const std::string& message) { | |
| 163 LOG(ERROR) << message; | |
| 164 Reset(); | |
|
achuithb
2014/08/20 21:52:31
Is this the best thing to do? What happens if we r
Zachary Kuznia
2014/08/21 00:42:06
Added TODO and explanation.
| |
| 165 } | |
| 166 | |
| 167 void BluetoothControllerPairingController::OnConnectError( | |
| 168 device::BluetoothDevice::ConnectErrorCode error_code) { | |
| 169 if (device_->IsPaired()) { | |
|
achuithb
2014/08/20 21:52:32
Could you add some comments here - why is connect
Zachary Kuznia
2014/08/21 00:42:06
Added comment.
| |
| 170 // Connection error is fine, as long as pairing was successful. | |
| 171 OnConnect(); | |
| 172 } else { | |
| 173 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR); | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 void BluetoothControllerPairingController::OnReceiveError( | |
| 178 device::BluetoothSocket::ErrorReason reason, | |
| 179 const std::string& error_message) { | |
| 180 LOG(ERROR) << reason << ", " << error_message; | |
| 181 Reset(); | |
| 182 } | |
| 183 | |
| 184 // ControllerPairingController: | |
|
achuithb
2014/08/20 21:52:32
Remove this comment
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 185 void BluetoothControllerPairingController::AddObserver( | |
| 186 ControllerPairingController::Observer* observer) { | |
| 187 observers_.AddObserver(observer); | |
| 188 } | |
| 189 | |
| 190 void BluetoothControllerPairingController::RemoveObserver( | |
| 191 ControllerPairingController::Observer* observer) { | |
| 192 observers_.RemoveObserver(observer); | |
| 193 } | |
| 194 | |
| 195 ControllerPairingController::Stage | |
| 196 BluetoothControllerPairingController::GetCurrentStage() { | |
|
achuithb
2014/08/20 21:52:31
This should be current_stage() and defined in the
Zachary Kuznia
2014/08/21 00:42:06
This is virtual, as discussed.
| |
| 197 return current_stage_; | |
| 198 } | |
| 199 | |
| 200 void BluetoothControllerPairingController::StartPairing() { | |
| 201 DCHECK(current_stage_ == STAGE_NONE || | |
| 202 current_stage_ == STAGE_DEVICE_NOT_FOUND || | |
| 203 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR || | |
| 204 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR); | |
| 205 bool bluetooth_available = | |
|
achuithb
2014/08/20 21:52:32
This variable seems unnecessary - why not inline i
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 206 device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable(); | |
| 207 // TODO(zork): Add a stage for no bluetooth. | |
|
achuithb
2014/08/20 21:52:32
Let's add bug-ids for all TODOs.
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 208 if (!bluetooth_available) | |
| 209 ChangeStage(STAGE_DEVICE_NOT_FOUND); | |
| 210 | |
| 211 device::BluetoothAdapterFactory::GetAdapter( | |
| 212 base::Bind(&BluetoothControllerPairingController::OnGetAdapter, | |
| 213 ptr_factory_.GetWeakPtr())); | |
| 214 | |
| 215 } | |
| 216 | |
| 217 ControllerPairingController::DeviceIdList | |
| 218 BluetoothControllerPairingController::GetDiscoveredDevices() { | |
| 219 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); | |
| 220 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end()); | |
| 221 } | |
| 222 | |
| 223 void BluetoothControllerPairingController::ChooseDeviceForPairing( | |
| 224 const std::string& device_id) { | |
| 225 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY); | |
| 226 CHECK(discovered_devices_.count(device_id)); | |
|
achuithb
2014/08/20 21:52:31
Why CHECK?
Zachary Kuznia
2014/08/21 00:42:06
DCHECK now.
| |
| 227 // TODO: Consider using stop instead of reset(). | |
|
achuithb
2014/08/20 21:52:33
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 228 discovery_session_.reset(); | |
| 229 device_ = adapter_->GetDevice(device_id); | |
| 230 if (device_) { | |
| 231 ChangeStage(STAGE_ESTABLISHING_CONNECTION); | |
| 232 if (device_->IsPaired()) { | |
| 233 OnConnect(); | |
| 234 } else { | |
| 235 device_->Connect( | |
| 236 this, | |
| 237 base::Bind(&BluetoothControllerPairingController::OnConnect, | |
| 238 ptr_factory_.GetWeakPtr()), | |
| 239 base::Bind(&BluetoothControllerPairingController::OnConnectError, | |
| 240 ptr_factory_.GetWeakPtr())); | |
| 241 } | |
| 242 } else { | |
| 243 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 void BluetoothControllerPairingController::RepeatDiscovery() { | |
| 248 CHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND || | |
|
achuithb
2014/08/20 21:52:33
Why CHECK and not DCHECK?
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 249 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR || | |
| 250 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR); | |
| 251 Reset(); | |
| 252 StartPairing(); | |
| 253 } | |
| 254 | |
| 255 std::string BluetoothControllerPairingController::GetConfirmationCode() { | |
|
achuithb
2014/08/20 21:52:32
Return const std::string&
Zachary Kuznia
2014/08/21 00:42:07
This is virtual, as discussed.
| |
| 256 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
| 257 DCHECK(!confirmation_code_.empty()); | |
| 258 return confirmation_code_; | |
| 259 } | |
| 260 | |
| 261 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect( | |
| 262 bool correct) { | |
| 263 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
| 264 if (correct) { | |
| 265 device_->ConfirmPairing(); | |
| 266 // Once pairing is confirmed, the connection will either be successful, or | |
| 267 // fail. Either case is acceptable as long as the devices are paired. | |
| 268 } else { | |
| 269 device_->RejectPairing(); | |
| 270 device_ = NULL; | |
| 271 RepeatDiscovery(); | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 void BluetoothControllerPairingController::OnAuthenticationDone( | |
| 276 const chromeos::UserContext& user_context, | |
| 277 content::BrowserContext* browser_context) { | |
| 278 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS); | |
| 279 | |
| 280 // TODO: Get configuration from UI and send to Host | |
| 281 | |
| 282 // TODO: Get proper credentials. | |
|
achuithb
2014/08/20 21:52:33
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 283 // For now, send a fake domain. | |
| 284 pairing_api::PairDevices pair_devices; | |
| 285 pair_devices.set_api_version(kPairingAPIVersion); | |
| 286 pair_devices.mutable_parameters()->set_admin_access_token( | |
| 287 kFakeEnrollmentDomain); | |
| 288 | |
| 289 int size = 0; | |
| 290 scoped_refptr<net::IOBuffer> io_buffer( | |
| 291 ProtoDecoder::SendPairDevices(pair_devices, &size)); | |
| 292 | |
| 293 socket_->Send( | |
| 294 io_buffer, size, | |
| 295 base::Bind(&BluetoothControllerPairingController::OnSendComplete, | |
| 296 ptr_factory_.GetWeakPtr()), | |
| 297 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage, | |
| 298 ptr_factory_.GetWeakPtr())); | |
| 299 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS); | |
| 300 } | |
| 301 | |
| 302 void BluetoothControllerPairingController::StartSession() { | |
| 303 DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE); | |
| 304 ChangeStage(STAGE_FINISHED); | |
| 305 } | |
| 306 | |
| 307 // ProtoDecoder::Observer: | |
|
achuithb
2014/08/20 21:52:32
Remove this comment
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 308 void BluetoothControllerPairingController::OnHostStatusMessage( | |
| 309 const pairing_api::HostStatus& message) { | |
| 310 if (got_initial_status_) { | |
| 311 if (message.parameters().has_domain()) { | |
| 312 if (message.parameters().domain() == kFakeEnrollmentDomain) { | |
|
achuithb
2014/08/20 21:52:31
Where is this domain supposed to come from?
Zachary Kuznia
2014/08/21 00:42:06
Added a comment to explain.
| |
| 313 pairing_api::CompleteSetup complete_setup; | |
| 314 complete_setup.set_api_version(kPairingAPIVersion); | |
| 315 // TODO: Get AddAnother from UI | |
|
achuithb
2014/08/20 21:52:32
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 316 complete_setup.mutable_parameters()->set_add_another(false); | |
| 317 | |
| 318 int size = 0; | |
| 319 scoped_refptr<net::IOBuffer> io_buffer( | |
| 320 ProtoDecoder::SendCompleteSetup(complete_setup, &size)); | |
| 321 | |
| 322 socket_->Send( | |
| 323 io_buffer, size, | |
| 324 base::Bind(&BluetoothControllerPairingController::OnSendComplete, | |
| 325 ptr_factory_.GetWeakPtr()), | |
| 326 base::Bind( | |
| 327 &BluetoothControllerPairingController::OnErrorWithMessage, | |
|
achuithb
2014/08/20 21:52:31
Should we be retrying?
Zachary Kuznia
2014/08/21 00:42:06
No; if send fails, we'll have to restart the whole
| |
| 328 ptr_factory_.GetWeakPtr())); | |
| 329 ChangeStage(STAGE_PAIRING_DONE); | |
| 330 } else { | |
| 331 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR); | |
| 332 } | |
| 333 } else { | |
| 334 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR); | |
| 335 } | |
| 336 } else { | |
| 337 got_initial_status_ = true; | |
| 338 | |
| 339 // TODO: Check domain. | |
| 340 | |
| 341 // TODO: Handling updating stages. | |
|
achuithb
2014/08/20 21:52:32
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 342 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void BluetoothControllerPairingController::OnConfigureHostMessage( | |
| 347 const pairing_api::ConfigureHost& message) { | |
| 348 NOTREACHED(); | |
| 349 } | |
| 350 | |
| 351 void BluetoothControllerPairingController::OnPairDevicesMessage( | |
| 352 const pairing_api::PairDevices& message) { | |
| 353 NOTREACHED(); | |
| 354 } | |
| 355 | |
| 356 void BluetoothControllerPairingController::OnCompleteSetupMessage( | |
| 357 const pairing_api::CompleteSetup& message) { | |
| 358 NOTREACHED(); | |
| 359 } | |
| 360 | |
| 361 void BluetoothControllerPairingController::OnErrorMessage( | |
| 362 const pairing_api::Error& message) { | |
| 363 LOG(ERROR) << message.parameters().code() << ", " << | |
| 364 message.parameters().description(); | |
| 365 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR); | |
| 366 } | |
| 367 | |
| 368 // device::BluetoothAdapter::Observer: | |
|
achuithb
2014/08/20 21:52:32
REmove this comment
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 369 void BluetoothControllerPairingController::DeviceAdded( | |
| 370 device::BluetoothAdapter* adapter, | |
| 371 device::BluetoothDevice* device) { | |
| 372 DCHECK_EQ(adapter, adapter_.get()); | |
| 373 DeviceFound(device); | |
| 374 } | |
| 375 | |
| 376 void BluetoothControllerPairingController::DeviceRemoved( | |
| 377 device::BluetoothAdapter* adapter, | |
| 378 device::BluetoothDevice* device) { | |
| 379 DCHECK_EQ(adapter, adapter_.get()); | |
| 380 DeviceLost(device); | |
| 381 } | |
| 382 | |
| 383 // device::BluetoothDevice::PairingDelegate: | |
|
achuithb
2014/08/20 21:52:32
REmove this comment
Zachary Kuznia
2014/08/21 00:42:06
Done.
| |
| 384 void BluetoothControllerPairingController::RequestPinCode( | |
| 385 device::BluetoothDevice* device) { | |
| 386 // Disallow unknown device. | |
| 387 device->RejectPairing(); | |
| 388 } | |
| 389 | |
| 390 void BluetoothControllerPairingController::RequestPasskey( | |
| 391 device::BluetoothDevice* device) { | |
| 392 // Disallow unknown device. | |
| 393 device->RejectPairing(); | |
| 394 } | |
| 395 | |
| 396 void BluetoothControllerPairingController::DisplayPinCode( | |
| 397 device::BluetoothDevice* device, | |
| 398 const std::string& pincode) { | |
| 399 // Disallow unknown device. | |
| 400 device->RejectPairing(); | |
| 401 } | |
| 402 | |
| 403 void BluetoothControllerPairingController::DisplayPasskey( | |
| 404 device::BluetoothDevice* device, | |
| 405 uint32 passkey) { | |
| 406 // Disallow unknown device. | |
| 407 device->RejectPairing(); | |
| 408 } | |
| 409 | |
| 410 void BluetoothControllerPairingController::KeysEntered( | |
| 411 device::BluetoothDevice* device, | |
| 412 uint32 entered) { | |
| 413 // Disallow unknown device. | |
| 414 device->RejectPairing(); | |
| 415 } | |
| 416 | |
| 417 void BluetoothControllerPairingController::ConfirmPasskey( | |
| 418 device::BluetoothDevice* device, | |
| 419 uint32 passkey) { | |
| 420 DCHECK_EQ(device, device_); | |
| 421 confirmation_code_ = base::StringPrintf("%06d", passkey); | |
| 422 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
| 423 } | |
| 424 | |
| 425 void BluetoothControllerPairingController::AuthorizePairing( | |
| 426 device::BluetoothDevice* device) { | |
| 427 // Disallow unknown device. | |
| 428 device->RejectPairing(); | |
| 429 } | |
| 430 | |
| 431 } // namespace pairing_chromeos | |
| OLD | NEW |