summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
Diffstat (limited to 'device')
-rw-r--r--device/bluetooth/bluetooth_adapter_chromeos.cc9
-rw-r--r--device/bluetooth/bluetooth_adapter_unittest.cc1
-rw-r--r--device/bluetooth/bluetooth_chromeos_unittest.cc158
-rw-r--r--device/bluetooth/bluetooth_device.h9
-rw-r--r--device/bluetooth/bluetooth_pairing_chromeos.cc13
-rw-r--r--device/bluetooth/bluetooth_pairing_chromeos.h8
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();