diff options
Diffstat (limited to 'device')
-rw-r--r-- | device/bluetooth/bluetooth_adapter_chromeos.cc | 9 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_adapter_unittest.cc | 1 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_chromeos_unittest.cc | 158 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_device.h | 9 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_pairing_chromeos.cc | 13 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_pairing_chromeos.h | 8 |
6 files changed, 196 insertions, 2 deletions
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.cc b/device/bluetooth/bluetooth_adapter_chromeos.cc index 9539ebb..f5a8ad7 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.cc +++ b/device/bluetooth/bluetooth_adapter_chromeos.cc @@ -433,8 +433,13 @@ void BluetoothAdapterChromeOS::RequestAuthorization( DCHECK(agent_.get()); VLOG(1) << device_path.value() << ": RequestAuthorization"; - // TODO(keybuk): implement - callback.Run(CANCELLED); + BluetoothPairingChromeOS* pairing = GetPairing(device_path); + if (!pairing) { + callback.Run(REJECTED); + return; + } + + pairing->RequestAuthorization(callback); } void BluetoothAdapterChromeOS::AuthorizeService( diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index c063bed..f4653c2 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc @@ -114,6 +114,7 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { uint32 entered) OVERRIDE {} virtual void ConfirmPasskey(BluetoothDevice* device, uint32 passkey) OVERRIDE {} + virtual void AuthorizePairing(BluetoothDevice* device) OVERRIDE {} }; diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc index e39a746..0d10dd0 100644 --- a/device/bluetooth/bluetooth_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_chromeos_unittest.cc @@ -142,6 +142,7 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { display_passkey_count_(0), keys_entered_count_(0), confirm_passkey_count_(0), + authorize_pairing_count_(0), last_passkey_(9999999U), last_entered_(999U) {} virtual ~TestPairingDelegate() {} @@ -189,6 +190,12 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { QuitMessageLoop(); } + virtual void AuthorizePairing(BluetoothDevice* device) OVERRIDE { + ++call_count_; + ++authorize_pairing_count_; + QuitMessageLoop(); + } + int call_count_; int request_pincode_count_; int request_passkey_count_; @@ -196,6 +203,7 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { int display_passkey_count_; int keys_entered_count_; int confirm_passkey_count_; + int authorize_pairing_count_; uint32 last_passkey_; uint32 last_entered_; std::string last_pincode_; @@ -2071,6 +2079,58 @@ TEST_F(BluetoothChromeOSTest, PairWeirdDevice) { EXPECT_TRUE(properties->trusted.value()); } +TEST_F(BluetoothChromeOSTest, PairBoseSpeakers) { + base::MessageLoop message_loop; + fake_bluetooth_device_client_->SetSimulationIntervalMs(10); + + GetAdapter(); + DiscoverDevices(); + + // Use the "bose speakers" fake that uses just-works pairing, since this is + // an outgoing pairing, no delegate interaction is required. + BluetoothDevice* device = adapter_->GetDevice( + FakeBluetoothDeviceClient::kBoseSpeakersAddress); + ASSERT_TRUE(device != NULL); + ASSERT_FALSE(device->IsPaired()); + + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + TestPairingDelegate pairing_delegate; + device->Connect( + &pairing_delegate, + base::Bind(&BluetoothChromeOSTest::Callback, + base::Unretained(this)), + base::Bind(&BluetoothChromeOSTest::ConnectErrorCallback, + base::Unretained(this))); + + EXPECT_EQ(0, pairing_delegate.call_count_); + + message_loop.Run(); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + + // Two changes for connecting, one change for connected, one for paired and + // two for trusted (after pairing and connection). + EXPECT_EQ(6, observer.device_changed_count_); + EXPECT_EQ(device, observer.last_device_); + + EXPECT_TRUE(device->IsConnected()); + EXPECT_FALSE(device->IsConnecting()); + + EXPECT_TRUE(device->IsPaired()); + + // Non HID devices are always connectable. + EXPECT_TRUE(device->IsConnectable()); + + // Make sure the trusted property has been set to true. + FakeBluetoothDeviceClient::Properties* properties = + fake_bluetooth_device_client_->GetProperties( + dbus::ObjectPath(FakeBluetoothDeviceClient::kBoseSpeakersPath)); + EXPECT_TRUE(properties->trusted.value()); +} + TEST_F(BluetoothChromeOSTest, PairUnpairableDeviceFails) { base::MessageLoop message_loop; fake_bluetooth_device_client_->SetSimulationIntervalMs(10); @@ -2663,6 +2723,60 @@ TEST_F(BluetoothChromeOSTest, IncomingPairWeirdDevice) { EXPECT_TRUE(device_chromeos->GetPairing() == NULL); } +TEST_F(BluetoothChromeOSTest, IncomingPairBoseSpeakers) { + base::MessageLoop message_loop; + fake_bluetooth_device_client_->SetSimulationIntervalMs(10); + + GetAdapter(); + + TestPairingDelegate pairing_delegate; + adapter_->AddPairingDelegate( + &pairing_delegate, + BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH); + + // The Bose Speakers use just-works pairing so require authorization when + // the request is incoming. + fake_bluetooth_device_client_->CreateDevice( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(FakeBluetoothDeviceClient::kBoseSpeakersPath)); + BluetoothDevice* device = adapter_->GetDevice( + FakeBluetoothDeviceClient::kBoseSpeakersAddress); + ASSERT_TRUE(device != NULL); + ASSERT_FALSE(device->IsPaired()); + + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + fake_bluetooth_device_client_->SimulatePairing( + dbus::ObjectPath(FakeBluetoothDeviceClient::kBoseSpeakersPath), + true, + base::Bind(&BluetoothChromeOSTest::Callback, + base::Unretained(this)), + base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); + + EXPECT_EQ(1, pairing_delegate.call_count_); + EXPECT_EQ(1, pairing_delegate.authorize_pairing_count_); + + // Confirm the pairing. + device->ConfirmPairing(); + message_loop.Run(); + + EXPECT_EQ(1, callback_count_); + EXPECT_EQ(0, error_callback_count_); + + // One for paired. + EXPECT_EQ(1, observer.device_changed_count_); + EXPECT_EQ(device, observer.last_device_); + + EXPECT_TRUE(device->IsPaired()); + + // No pairing context should remain on the device. + BluetoothDeviceChromeOS* device_chromeos = + static_cast<BluetoothDeviceChromeOS*>(device); + EXPECT_TRUE(device_chromeos->GetPairing() == NULL); +} + TEST_F(BluetoothChromeOSTest, IncomingPairSonyHeadphonesWithoutDelegate) { base::MessageLoop message_loop; fake_bluetooth_device_client_->SetSimulationIntervalMs(10); @@ -2795,6 +2909,50 @@ TEST_F(BluetoothChromeOSTest, IncomingPairWeirdDeviceWithoutDelegate) { EXPECT_TRUE(device_chromeos->GetPairing() == NULL); } +TEST_F(BluetoothChromeOSTest, IncomingPairBoseSpeakersWithoutDelegate) { + base::MessageLoop message_loop; + fake_bluetooth_device_client_->SetSimulationIntervalMs(10); + + GetAdapter(); + + // The Bose Speakers uses just-works pairing and thus requires authorization, + // without a pairing delegate, that will be rejected. + fake_bluetooth_device_client_->CreateDevice( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(FakeBluetoothDeviceClient::kBoseSpeakersPath)); + BluetoothDevice* device = adapter_->GetDevice( + FakeBluetoothDeviceClient::kBoseSpeakersAddress); + ASSERT_TRUE(device != NULL); + ASSERT_FALSE(device->IsPaired()); + + TestObserver observer(adapter_); + adapter_->AddObserver(&observer); + + fake_bluetooth_device_client_->SimulatePairing( + dbus::ObjectPath(FakeBluetoothDeviceClient::kBoseSpeakersPath), + true, + base::Bind(&BluetoothChromeOSTest::Callback, + base::Unretained(this)), + base::Bind(&BluetoothChromeOSTest::DBusErrorCallback, + base::Unretained(this))); + + message_loop.Run(); + + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); + EXPECT_EQ(bluetooth_device::kErrorAuthenticationRejected, last_client_error_); + + // No changes should be observer. + EXPECT_EQ(0, observer.device_changed_count_); + + EXPECT_FALSE(device->IsPaired()); + + // No pairing context should remain on the device. + BluetoothDeviceChromeOS* device_chromeos = + static_cast<BluetoothDeviceChromeOS*>(device); + EXPECT_TRUE(device_chromeos->GetPairing() == NULL); +} + TEST_F(BluetoothChromeOSTest, RemovePairingDelegateDuringPairing) { base::MessageLoop message_loop; fake_bluetooth_device_client_->SetSimulationIntervalMs(10); diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h index d0b1765..48df49f 100644 --- a/device/bluetooth/bluetooth_device.h +++ b/device/bluetooth/bluetooth_device.h @@ -150,6 +150,15 @@ class BluetoothDevice { // digits. virtual void ConfirmPasskey(BluetoothDevice* device, uint32 passkey) = 0; + + // This method will be called when the Bluetooth daemon requires that a + // pairing request, usually only incoming, using the just-works model is + // authorized. The delegate should decide whether the user should confirm + // or not, then call ConfirmPairing() on the device to confirm the pairing + // (whether by user action or by default), RejectPairing() on the device to + // reject or CancelPairing() on the device to cancel authorization for + // any other reason. + virtual void AuthorizePairing(BluetoothDevice* device) = 0; }; // Returns true if uuid is in a a valid canonical format diff --git a/device/bluetooth/bluetooth_pairing_chromeos.cc b/device/bluetooth/bluetooth_pairing_chromeos.cc index d3b826d..b81c342 100644 --- a/device/bluetooth/bluetooth_pairing_chromeos.cc +++ b/device/bluetooth/bluetooth_pairing_chromeos.cc @@ -180,6 +180,19 @@ void BluetoothPairingChromeOS::RequestConfirmation( pairing_delegate_used_ = true; } +void BluetoothPairingChromeOS::RequestAuthorization( + const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& + callback) { + UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod", + UMA_PAIRING_METHOD_NONE, + UMA_PAIRING_METHOD_COUNT); + + DCHECK(confirmation_callback_.is_null()); + confirmation_callback_ = callback; + pairing_delegate_->AuthorizePairing(device_); + pairing_delegate_used_ = true; +} + bool BluetoothPairingChromeOS::ExpectingConfirmation() const { return !confirmation_callback_.is_null(); } diff --git a/device/bluetooth/bluetooth_pairing_chromeos.h b/device/bluetooth/bluetooth_pairing_chromeos.h index 6772497..85c45c6 100644 --- a/device/bluetooth/bluetooth_pairing_chromeos.h +++ b/device/bluetooth/bluetooth_pairing_chromeos.h @@ -84,6 +84,14 @@ class BluetoothPairingChromeOS { const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& callback); + // Requests authorization that the current device be allowed to pair with + // this device from the current pairing delegate. The ConfirmPairing(), + // RejectPairing() and CancelPairing() method calls on this object are + // translated into the appropriate response to |callback|. + void RequestAuthorization( + const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback& + callback); + // Confirms to the remote device during pairing that a passkey provided by // the ConfirmPasskey() delegate call is displayed on both devices. void ConfirmPairing(); |