Commit ca479fec authored by deymo@chromium.org's avatar deymo@chromium.org

Bluetooth: Add support for pairing display notifications

The HID 1.1 spec defines a notification signal sent from the device
every time the user types a new digit of the provided passkey during
the SSP pairing.

This patch extends the BluetoothDevice::PairingDelegate interface to
support a new method DisplayEnteredKeys to update the number of
pressed keys.

BUG=221105
TEST=device_unittest and manual test.

Manual test part:
=================
1. Open the chrome://settings page in the chromebook and click on "Inspect element". A new panel with the HTML is displayed.
2. Go to the "Console" tab in the opened panel and switch the "<top frame>" drop down in the status line at the bottom of the screen to "settings".
3. Run the following command:
options.BrowserOptions.addBluetoothDevice({"name":"MyMouse","address":"00:11:22:33:44:55","pairing":"bluetoothRemotePasskey","entered":4,"passkey":123456})
4. The passkey 123456 should be displayed on the screen with the first 4 keys in a different style.
5. Replacing "entered":4 by "entered":7 should also change the style of the "enter" key.
6. Removing the "entered":4, should show the keys darker than the "entered":0 state.

Review URL: https://chromiumcodereview.appspot.com/13870020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195153 0039d316-1c4b-4281-b951-d872f2087c98
parent ad4576ba
......@@ -274,12 +274,14 @@ cr.define('options', function() {
'bluetooth-keyboard-button' : 'bluetooth-passkey-char';
this.clearElement_(passkeyEl);
var key = String(this.device_.passkey);
var progress = this.device_.entered | 0;
var progress = this.device_.entered;
for (var i = 0; i < key.length; i++) {
var keyEl = document.createElement('span');
keyEl.textContent = key.charAt(i);
keyEl.className = keyClass;
if (i < progress)
if (progress == undefined)
keyEl.classList.add('key-pin');
else if (i < progress)
keyEl.classList.add('key-typed');
passkeyEl.appendChild(keyEl);
}
......@@ -290,6 +292,10 @@ cr.define('options', function() {
keyEl.textContent = label;
keyEl.className = keyClass;
keyEl.id = 'bluetooth-enter-key';
if (progress == undefined)
keyEl.classList.add('key-pin');
else if (progress > key.length)
keyEl.classList.add('key-typed');
passkeyEl.appendChild(keyEl);
}
passkeyEl.hidden = false;
......
......@@ -451,6 +451,13 @@ void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device,
SendDeviceNotification(device, &params);
}
void BluetoothOptionsHandler::KeysEntered(device::BluetoothDevice* device,
uint32 entered) {
DictionaryValue params;
params.SetInteger("entered", entered);
SendDeviceNotification(device, &params);
}
void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device,
uint32 passkey) {
DictionaryValue params;
......
......@@ -95,6 +95,22 @@ class BluetoothOptionsHandler
virtual void DisplayPasskey(
device::BluetoothDevice* device, uint32 passkey) OVERRIDE;
// device::BluetoothDevice::PairingDelegate override.
//
// This method will be called when the Bluetooth daemon gets a notification
// of a key entered on the device |device| while pairing with the device
// using a PIN code or a Passkey.
//
// The UI will show a visual indication that a given key was pressed in the
// same pairing overlay where the PIN code or Passkey is displayed.
//
// A first call with |entered| as 0 will indicate that this notification
// mechanism is supported by the device allowing the UI to display this fact.
// A last call with |entered| as the length of the key plus one will indicate
// that the [enter] key was pressed.
virtual void KeysEntered(device::BluetoothDevice* device,
uint32 entered) OVERRIDE;
// device::BluetoothDevice::PairingDelegate override.
//
// This method will be called when the Bluetooth daemon requires that the
......
......@@ -123,6 +123,22 @@ class BluetoothDevice {
virtual void DisplayPasskey(BluetoothDevice* device,
uint32 passkey) = 0;
// This method will be called when the Bluetooth daemon gets a notification
// of a key entered on the device |device| while pairing with the device
// using a PIN code or a Passkey.
//
// This method will be called only after DisplayPinCode() or
// DisplayPasskey() is called and before the corresponding
// DismissDisplayOrConfirm() is called, but is not warranted to be called
// on every pairing process that requires a PIN code or a Passkey because
// some device may not support this feature.
//
// The |entered| value describes the number of keys entered so far,
// including the last [enter] key. A first call to KeysEntered() with
// |entered| as 0 will be sent when the device supports this feature.
virtual void KeysEntered(BluetoothDevice* device,
uint32 entered) = 0;
// This method will be called when the Bluetooth daemon requires that the
// user confirm that the Passkey |passkey| is displayed on the screen
// of the device |device| so that it may be authenticated. The delegate
......
......@@ -330,12 +330,10 @@ void BluetoothDeviceExperimentalChromeOS::DisplayPasskey(
VLOG(1) << object_path_.value() << ": DisplayPasskey: " << passkey
<< " (" << entered << " entered)";
// TODO(keybuk): disambiguate entered vs display
if (entered > 0)
return;
DCHECK(pairing_delegate_);
pairing_delegate_->DisplayPasskey(this, passkey);
if (entered == 0)
pairing_delegate_->DisplayPasskey(this, passkey);
pairing_delegate_->KeysEntered(this, entered);
}
void BluetoothDeviceExperimentalChromeOS::RequestConfirmation(
......
......@@ -128,8 +128,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
request_passkey_count_(0),
display_pincode_count_(0),
display_passkey_count_(0),
keys_entered_count_(0),
confirm_passkey_count_(0),
dismiss_count_(0) {}
dismiss_count_(0),
last_passkey_(9999999U),
last_entered_(999U) {}
virtual ~TestPairingDelegate() {}
void RequestPinCode(BluetoothDevice* device) OVERRIDE {
......@@ -160,6 +163,14 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
QuitMessageLoop();
}
void KeysEntered(BluetoothDevice* device,
uint32 entered) OVERRIDE {
++call_count_;
++keys_entered_count_;
last_entered_ = entered;
QuitMessageLoop();
}
void ConfirmPasskey(BluetoothDevice* device,
uint32 passkey) OVERRIDE {
++call_count_;
......@@ -179,9 +190,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
int request_passkey_count_;
int display_pincode_count_;
int display_passkey_count_;
int keys_entered_count_;
int confirm_passkey_count_;
int dismiss_count_;
uint32 last_passkey_;
uint32 last_entered_;
std::string last_pincode_;
private:
......@@ -1239,7 +1252,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairAppleKeyboard) {
EXPECT_TRUE(device->IsPaired());
// Pairing dialog should be dismissed
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.dismiss_count_);
// Make sure the trusted property has been set to true.
......@@ -1274,15 +1286,32 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) {
base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1, pairing_delegate.call_count_);
// One call for DisplayPasskey() and one for KeysEntered().
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.display_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
EXPECT_EQ(1, pairing_delegate.keys_entered_count_);
EXPECT_EQ(0U, pairing_delegate.last_entered_);
EXPECT_TRUE(device->IsConnecting());
// TODO(keybuk): verify we get typing notifications
// One call to KeysEntered() for each key, including [enter].
for(int i = 1; i <= 7; ++i) {
message_loop.Run();
EXPECT_EQ(2 + i, pairing_delegate.call_count_);
EXPECT_EQ(1 + i, pairing_delegate.keys_entered_count_);
EXPECT_EQ(static_cast<uint32_t>(i), pairing_delegate.last_entered_);
}
message_loop.Run();
// 8 KeysEntered notifications (0 to 7, inclusive). Two aditional calls for
// DisplayPasskey() and DismissDisplayOrConfirm().
EXPECT_EQ(10, pairing_delegate.call_count_);
EXPECT_EQ(8, pairing_delegate.keys_entered_count_);
EXPECT_EQ(7U, pairing_delegate.last_entered_);
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
......@@ -1296,7 +1325,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) {
EXPECT_TRUE(device->IsPaired());
// Pairing dialog should be dismissed
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.dismiss_count_);
// Make sure the trusted property has been set to true.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment