Home | History | Annotate | Download | only in pairing
      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