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_host_pairing_controller.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/strings/stringprintf.h" | |
| 10 #include "components/pairing/bluetooth_pairing_constants.h" | |
| 11 #include "components/pairing/pairing_api.pb.h" | |
| 12 #include "components/pairing/proto_decoder.h" | |
| 13 #include "device/bluetooth/bluetooth_adapter_factory.h" | |
| 14 #include "net/base/io_buffer.h" | |
| 15 | |
| 16 namespace { | |
| 17 const int kReceiveSize = 16384; | |
| 18 } | |
| 19 | |
| 20 namespace pairing_chromeos { | |
| 21 | |
| 22 BluetoothHostPairingController::BluetoothHostPairingController() | |
| 23 : ptr_factory_(this), | |
| 24 current_stage_(STAGE_NONE), | |
| 25 device_(NULL), | |
| 26 proto_decoder_(new ProtoDecoder(this)) { | |
| 27 } | |
| 28 | |
| 29 BluetoothHostPairingController::~BluetoothHostPairingController() {} | |
| 30 | |
| 31 void BluetoothHostPairingController::ChangeStage(Stage new_stage) { | |
| 32 if (current_stage_ == new_stage) | |
| 33 return; | |
| 34 current_stage_ = new_stage; | |
| 35 FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage)); | |
| 36 } | |
| 37 | |
| 38 void BluetoothHostPairingController::SendHostStatus() { | |
| 39 pairing_api::HostStatus host_status; | |
| 40 | |
| 41 host_status.set_api_version(kPairingAPIVersion); | |
| 42 if (!enrollment_domain_.empty()) | |
| 43 host_status.mutable_parameters()->set_domain(enrollment_domain_); | |
| 44 | |
| 45 // TODO: Get these values from the UI. | |
|
achuithb
2014/08/20 21:52:33
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 46 host_status.mutable_parameters()->set_connectivity( | |
| 47 pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTED); | |
| 48 host_status.mutable_parameters()->set_update_status( | |
| 49 pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED); | |
| 50 | |
| 51 // TODO: Get a list of other paired controllers. | |
|
achuithb
2014/08/20 21:52:34
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 52 | |
| 53 int size = 0; | |
| 54 scoped_refptr<net::IOBuffer> io_buffer( | |
| 55 ProtoDecoder::SendHostStatus(host_status, &size)); | |
| 56 | |
| 57 controller_socket_->Send( | |
| 58 io_buffer, size, | |
| 59 base::Bind(&BluetoothHostPairingController::OnSendComplete, | |
| 60 ptr_factory_.GetWeakPtr()), | |
| 61 base::Bind(&BluetoothHostPairingController::OnSendError, | |
| 62 ptr_factory_.GetWeakPtr())); | |
| 63 } | |
| 64 | |
| 65 void BluetoothHostPairingController::AbortWithError( | |
| 66 int code, | |
| 67 const std::string& message) { | |
| 68 if (controller_socket_) { | |
| 69 pairing_api::Error error; | |
| 70 | |
| 71 error.set_api_version(kPairingAPIVersion); | |
| 72 error.mutable_parameters()->set_code(PAIRING_ERROR_PAIRING_OR_ENROLLMENT); | |
| 73 error.mutable_parameters()->set_description(message); | |
| 74 | |
| 75 int size = 0; | |
| 76 scoped_refptr<net::IOBuffer> io_buffer( | |
| 77 ProtoDecoder::SendError(error, &size)); | |
| 78 | |
| 79 controller_socket_->Send( | |
| 80 io_buffer, size, | |
| 81 base::Bind(&BluetoothHostPairingController::OnSendComplete, | |
| 82 ptr_factory_.GetWeakPtr()), | |
| 83 base::Bind(&BluetoothHostPairingController::OnSendError, | |
| 84 ptr_factory_.GetWeakPtr())); | |
| 85 } | |
| 86 Reset(); | |
| 87 } | |
| 88 | |
| 89 void BluetoothHostPairingController::Reset() { | |
| 90 if (controller_socket_) { | |
| 91 controller_socket_->Close(); | |
| 92 controller_socket_ = NULL; | |
| 93 } | |
| 94 | |
| 95 if (service_socket_) { | |
| 96 service_socket_->Close(); | |
| 97 service_socket_ = NULL; | |
| 98 } | |
| 99 ChangeStage(STAGE_NONE); | |
| 100 } | |
| 101 | |
| 102 void BluetoothHostPairingController::OnGetAdapter( | |
| 103 scoped_refptr<device::BluetoothAdapter> adapter) { | |
| 104 CHECK(!adapter_); | |
|
achuithb
2014/08/20 21:52:34
Why CHECK?
Zachary Kuznia
2014/08/21 00:42:08
Done.
| |
| 105 adapter_ = adapter; | |
| 106 | |
| 107 // TODO(zork): Make the device name prettier. | |
|
achuithb
2014/08/20 21:52:33
bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 108 device_name_ = base::StringPrintf("%s%s", kDeviceNamePrefix, | |
| 109 adapter_->GetAddress().c_str()); | |
| 110 adapter_->SetName( | |
| 111 device_name_, | |
| 112 base::Bind(&BluetoothHostPairingController::OnSetName, | |
| 113 ptr_factory_.GetWeakPtr()), | |
| 114 base::Bind(&BluetoothHostPairingController::OnSetError, | |
| 115 ptr_factory_.GetWeakPtr())); | |
| 116 } | |
| 117 | |
| 118 void BluetoothHostPairingController::OnSetName() { | |
| 119 if (adapter_->IsPowered()) { | |
| 120 OnSetPowered(); | |
| 121 } else { | |
| 122 adapter_->SetPowered( | |
| 123 true, | |
| 124 base::Bind(&BluetoothHostPairingController::OnSetPowered, | |
| 125 ptr_factory_.GetWeakPtr()), | |
| 126 base::Bind(&BluetoothHostPairingController::OnSetError, | |
| 127 ptr_factory_.GetWeakPtr())); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 void BluetoothHostPairingController::OnSetPowered() { | |
| 132 adapter_->AddPairingDelegate( | |
| 133 this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH); | |
| 134 | |
| 135 device::BluetoothAdapter::ServiceOptions options; | |
| 136 options.name.reset(new std::string(kPairingServiceName)); | |
| 137 | |
| 138 adapter_->CreateRfcommService( | |
| 139 device::BluetoothUUID(kPairingServiceUUID), options, | |
| 140 base::Bind(&BluetoothHostPairingController::OnCreateService, | |
| 141 ptr_factory_.GetWeakPtr()), | |
| 142 base::Bind(&BluetoothHostPairingController::OnCreateServiceError, | |
| 143 ptr_factory_.GetWeakPtr())); | |
| 144 } | |
| 145 | |
| 146 void BluetoothHostPairingController::OnCreateService( | |
| 147 scoped_refptr<device::BluetoothSocket> socket) { | |
| 148 service_socket_ = socket; | |
| 149 | |
| 150 service_socket_->Accept( | |
| 151 base::Bind(&BluetoothHostPairingController::OnAccept, | |
| 152 ptr_factory_.GetWeakPtr()), | |
| 153 base::Bind(&BluetoothHostPairingController::OnAcceptError, | |
| 154 ptr_factory_.GetWeakPtr())); | |
| 155 | |
| 156 adapter_->SetDiscoverable( | |
| 157 true, | |
| 158 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable, | |
| 159 ptr_factory_.GetWeakPtr(), true), | |
| 160 base::Bind(&BluetoothHostPairingController::OnSetError, | |
| 161 ptr_factory_.GetWeakPtr())); | |
| 162 } | |
| 163 | |
| 164 void BluetoothHostPairingController::OnAccept( | |
| 165 const device::BluetoothDevice* device, | |
| 166 scoped_refptr<device::BluetoothSocket> socket) { | |
| 167 adapter_->SetDiscoverable( | |
| 168 false, | |
| 169 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable, | |
| 170 ptr_factory_.GetWeakPtr(), false), | |
| 171 base::Bind(&BluetoothHostPairingController::OnSetError, | |
| 172 ptr_factory_.GetWeakPtr())); | |
| 173 | |
| 174 controller_socket_ = socket; | |
| 175 service_socket_ = NULL; | |
| 176 | |
| 177 // TODO: Update Host. | |
|
achuithb
2014/08/20 21:52:34
TODO(zork) + bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 178 SendHostStatus(); | |
| 179 | |
| 180 controller_socket_->Receive( | |
| 181 kReceiveSize, | |
| 182 base::Bind(&BluetoothHostPairingController::OnReceiveComplete, | |
| 183 ptr_factory_.GetWeakPtr()), | |
| 184 base::Bind(&BluetoothHostPairingController::OnReceiveError, | |
| 185 ptr_factory_.GetWeakPtr())); | |
| 186 | |
| 187 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS); | |
| 188 } | |
| 189 | |
| 190 void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) { | |
| 191 if (change_stage) { | |
| 192 DCHECK_EQ(current_stage_, STAGE_NONE); | |
| 193 ChangeStage(STAGE_WAITING_FOR_CONTROLLER); | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 void BluetoothHostPairingController::OnSendComplete(int bytes_sent) {} | |
| 198 | |
| 199 void BluetoothHostPairingController::OnReceiveComplete( | |
| 200 int bytes, scoped_refptr<net::IOBuffer> io_buffer) { | |
| 201 proto_decoder_->DecodeIOBuffer(bytes, io_buffer); | |
| 202 | |
| 203 controller_socket_->Receive( | |
| 204 kReceiveSize, | |
| 205 base::Bind(&BluetoothHostPairingController::OnReceiveComplete, | |
| 206 ptr_factory_.GetWeakPtr()), | |
| 207 base::Bind(&BluetoothHostPairingController::OnReceiveError, | |
| 208 ptr_factory_.GetWeakPtr())); | |
| 209 } | |
| 210 | |
| 211 void BluetoothHostPairingController::OnCreateServiceError( | |
| 212 const std::string& message) { | |
| 213 LOG(ERROR) << message; | |
| 214 // TODO(zork): Add a stage for bluetooth error. | |
|
achuithb
2014/08/20 21:52:34
bug-id
Zachary Kuznia
2014/08/21 00:42:08
Done.
| |
| 215 ChangeStage(STAGE_NONE); | |
| 216 } | |
| 217 | |
| 218 void BluetoothHostPairingController::OnSetError() { | |
| 219 adapter_->RemovePairingDelegate(this); | |
| 220 // TODO(zork): Add a stage for bluetooth error. | |
|
achuithb
2014/08/20 21:52:33
bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 221 ChangeStage(STAGE_NONE); | |
| 222 } | |
| 223 | |
| 224 void BluetoothHostPairingController::OnAcceptError( | |
| 225 const std::string& error_message) { | |
| 226 LOG(ERROR) << error_message; | |
| 227 Reset(); | |
| 228 } | |
| 229 | |
| 230 void BluetoothHostPairingController::OnSendError( | |
| 231 const std::string& error_message) { | |
| 232 LOG(ERROR) << error_message; | |
| 233 } | |
| 234 | |
| 235 void BluetoothHostPairingController::OnReceiveError( | |
| 236 device::BluetoothSocket::ErrorReason reason, | |
| 237 const std::string& error_message) { | |
| 238 LOG(ERROR) << reason << ", " << error_message; | |
| 239 Reset(); | |
| 240 } | |
| 241 | |
| 242 void BluetoothHostPairingController::OnHostStatusMessage( | |
| 243 const pairing_api::HostStatus& message) { | |
| 244 NOTREACHED(); | |
| 245 } | |
| 246 | |
| 247 void BluetoothHostPairingController::OnConfigureHostMessage( | |
| 248 const pairing_api::ConfigureHost& message) { | |
| 249 // TODO(zork): Add event to API to handle this case. | |
|
achuithb
2014/08/20 21:52:33
bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 250 } | |
| 251 | |
| 252 void BluetoothHostPairingController::OnPairDevicesMessage( | |
| 253 const pairing_api::PairDevices& message) { | |
| 254 if (current_stage_ != STAGE_WAITING_FOR_CREDENTIALS) { | |
| 255 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol); | |
| 256 return; | |
| 257 } | |
| 258 | |
| 259 if (enrollment_domain_.empty()) { | |
| 260 ChangeStage(STAGE_ENROLLING); | |
| 261 // TODO: Enroll device, send error on error | |
|
achuithb
2014/08/20 21:52:33
TODO(zork/achuith) + bug-id
Zachary Kuznia
2014/08/21 00:42:08
Done.
| |
| 262 // For now, test domain is sent in the access token. | |
| 263 enrollment_domain_ = message.parameters().admin_access_token(); | |
| 264 ChangeStage(STAGE_PAIRING_DONE); | |
| 265 SendHostStatus(); | |
| 266 } else { | |
| 267 // TODO: Check that domain matches. If not, send error and abort. | |
|
achuithb
2014/08/20 21:52:33
TODO(zork/achuith) + bug-id
Did we decide to do t
Zachary Kuznia
2014/08/21 00:42:08
Done.
| |
| 268 NOTREACHED(); | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 void BluetoothHostPairingController::OnCompleteSetupMessage( | |
| 273 const pairing_api::CompleteSetup& message) { | |
| 274 if (current_stage_ != STAGE_PAIRING_DONE) { | |
| 275 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol); | |
| 276 return; | |
| 277 } | |
| 278 | |
| 279 // TODO(zork): Handle adding another controller. | |
|
achuithb
2014/08/20 21:52:34
bug-id
Zachary Kuznia
2014/08/21 00:42:08
Done.
| |
| 280 ChangeStage(STAGE_FINISHED); | |
| 281 } | |
| 282 | |
| 283 void BluetoothHostPairingController::OnErrorMessage( | |
| 284 const pairing_api::Error& message) { | |
| 285 NOTREACHED(); | |
| 286 } | |
| 287 | |
| 288 // HostPairingFlow: | |
|
achuithb
2014/08/20 21:52:33
REmove comment
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 289 void BluetoothHostPairingController::AddObserver(Observer* observer) { | |
| 290 observers_.AddObserver(observer); | |
| 291 } | |
| 292 | |
| 293 void BluetoothHostPairingController::RemoveObserver(Observer* observer) { | |
| 294 observers_.RemoveObserver(observer); | |
| 295 } | |
| 296 | |
| 297 HostPairingController::Stage BluetoothHostPairingController::GetCurrentStage() { | |
|
achuithb
2014/08/20 21:52:34
This should be current_stage() and defined in the
Zachary Kuznia
2014/08/21 00:42:07
Acknowledged.
| |
| 298 return current_stage_; | |
| 299 } | |
| 300 | |
| 301 void BluetoothHostPairingController::StartPairing() { | |
| 302 CHECK(current_stage_ == STAGE_NONE); | |
|
achuithb
2014/08/20 21:52:34
Why CHECK?
Zachary Kuznia
2014/08/21 00:42:08
Acknowledged.
| |
| 303 bool bluetooth_available = | |
| 304 device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable(); | |
| 305 // TODO(zork): Add a stage for no bluetooth. | |
|
achuithb
2014/08/20 21:52:33
bug-id
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 306 if (!bluetooth_available) | |
| 307 return; | |
| 308 | |
| 309 device::BluetoothAdapterFactory::GetAdapter( | |
| 310 base::Bind(&BluetoothHostPairingController::OnGetAdapter, | |
| 311 ptr_factory_.GetWeakPtr())); | |
| 312 } | |
| 313 | |
| 314 std::string BluetoothHostPairingController::GetDeviceName() { | |
|
achuithb
2014/08/20 21:52:33
const std::string& device_name() const
Zachary Kuznia
2014/08/21 00:42:07
Acknowledged.
| |
| 315 return device_name_; | |
| 316 } | |
| 317 | |
| 318 std::string BluetoothHostPairingController::GetConfirmationCode() { | |
|
achuithb
2014/08/20 21:52:34
const std::string& GetConfirmationCode() const
Zachary Kuznia
2014/08/21 00:42:08
Acknowledged.
| |
| 319 CHECK(current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
|
achuithb
2014/08/20 21:52:34
Why CHECK?
Zachary Kuznia
2014/08/21 00:42:07
Done.
| |
| 320 return confirmation_code_; | |
| 321 } | |
| 322 | |
| 323 std::string BluetoothHostPairingController::GetEnrollmentDomain() { | |
|
achuithb
2014/08/20 21:52:34
const std::string& enrollment_domain() const
Zachary Kuznia
2014/08/21 00:42:07
This is a virtual function, as we discussed.
| |
| 324 return enrollment_domain_; | |
| 325 } | |
| 326 | |
| 327 // device::BluetoothDevice::PairingDelegate: | |
| 328 void BluetoothHostPairingController::RequestPinCode( | |
| 329 device::BluetoothDevice* device) { | |
| 330 // Disallow unknown device. | |
| 331 device->RejectPairing(); | |
| 332 } | |
| 333 | |
| 334 void BluetoothHostPairingController::RequestPasskey( | |
| 335 device::BluetoothDevice* device) { | |
| 336 // Disallow unknown device. | |
| 337 device->RejectPairing(); | |
| 338 } | |
| 339 | |
| 340 void BluetoothHostPairingController::DisplayPinCode( | |
| 341 device::BluetoothDevice* device, | |
| 342 const std::string& pincode) { | |
| 343 // Disallow unknown device. | |
| 344 device->RejectPairing(); | |
| 345 } | |
| 346 | |
| 347 void BluetoothHostPairingController::DisplayPasskey( | |
| 348 device::BluetoothDevice* device, | |
| 349 uint32 passkey) { | |
| 350 // Disallow unknown device. | |
| 351 device->RejectPairing(); | |
| 352 } | |
| 353 | |
| 354 void BluetoothHostPairingController::KeysEntered( | |
| 355 device::BluetoothDevice* device, | |
| 356 uint32 entered) { | |
| 357 // Disallow unknown device. | |
| 358 device->RejectPairing(); | |
| 359 } | |
| 360 | |
| 361 void BluetoothHostPairingController::ConfirmPasskey( | |
| 362 device::BluetoothDevice* device, | |
| 363 uint32 passkey) { | |
| 364 confirmation_code_ = base::StringPrintf("%06d", passkey); | |
| 365 device->ConfirmPairing(); | |
| 366 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION); | |
| 367 } | |
| 368 | |
| 369 void BluetoothHostPairingController::AuthorizePairing( | |
| 370 device::BluetoothDevice* device) { | |
| 371 // Disallow unknown device. | |
| 372 device->RejectPairing(); | |
| 373 } | |
| 374 | |
| 375 } // namespace pairing_chromeos | |
| OLD | NEW |