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() { ...@@ -274,12 +274,14 @@ cr.define('options', function() {
'bluetooth-keyboard-button' : 'bluetooth-passkey-char'; 'bluetooth-keyboard-button' : 'bluetooth-passkey-char';
this.clearElement_(passkeyEl); this.clearElement_(passkeyEl);
var key = String(this.device_.passkey); 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++) { for (var i = 0; i < key.length; i++) {
var keyEl = document.createElement('span'); var keyEl = document.createElement('span');
keyEl.textContent = key.charAt(i); keyEl.textContent = key.charAt(i);
keyEl.className = keyClass; keyEl.className = keyClass;
if (i < progress) if (progress == undefined)
keyEl.classList.add('key-pin');
else if (i < progress)
keyEl.classList.add('key-typed'); keyEl.classList.add('key-typed');
passkeyEl.appendChild(keyEl); passkeyEl.appendChild(keyEl);
} }
...@@ -290,6 +292,10 @@ cr.define('options', function() { ...@@ -290,6 +292,10 @@ cr.define('options', function() {
keyEl.textContent = label; keyEl.textContent = label;
keyEl.className = keyClass; keyEl.className = keyClass;
keyEl.id = 'bluetooth-enter-key'; 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.appendChild(keyEl);
} }
passkeyEl.hidden = false; passkeyEl.hidden = false;
......
...@@ -451,6 +451,13 @@ void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device, ...@@ -451,6 +451,13 @@ void BluetoothOptionsHandler::DisplayPasskey(device::BluetoothDevice* device,
SendDeviceNotification(device, &params); 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, void BluetoothOptionsHandler::ConfirmPasskey(device::BluetoothDevice* device,
uint32 passkey) { uint32 passkey) {
DictionaryValue params; DictionaryValue params;
......
...@@ -95,6 +95,22 @@ class BluetoothOptionsHandler ...@@ -95,6 +95,22 @@ class BluetoothOptionsHandler
virtual void DisplayPasskey( virtual void DisplayPasskey(
device::BluetoothDevice* device, uint32 passkey) OVERRIDE; 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. // device::BluetoothDevice::PairingDelegate override.
// //
// This method will be called when the Bluetooth daemon requires that the // This method will be called when the Bluetooth daemon requires that the
......
...@@ -123,6 +123,22 @@ class BluetoothDevice { ...@@ -123,6 +123,22 @@ class BluetoothDevice {
virtual void DisplayPasskey(BluetoothDevice* device, virtual void DisplayPasskey(BluetoothDevice* device,
uint32 passkey) = 0; 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 // This method will be called when the Bluetooth daemon requires that the
// user confirm that the Passkey |passkey| is displayed on the screen // user confirm that the Passkey |passkey| is displayed on the screen
// of the device |device| so that it may be authenticated. The delegate // of the device |device| so that it may be authenticated. The delegate
......
...@@ -330,12 +330,10 @@ void BluetoothDeviceExperimentalChromeOS::DisplayPasskey( ...@@ -330,12 +330,10 @@ void BluetoothDeviceExperimentalChromeOS::DisplayPasskey(
VLOG(1) << object_path_.value() << ": DisplayPasskey: " << passkey VLOG(1) << object_path_.value() << ": DisplayPasskey: " << passkey
<< " (" << entered << " entered)"; << " (" << entered << " entered)";
// TODO(keybuk): disambiguate entered vs display
if (entered > 0)
return;
DCHECK(pairing_delegate_); DCHECK(pairing_delegate_);
pairing_delegate_->DisplayPasskey(this, passkey); if (entered == 0)
pairing_delegate_->DisplayPasskey(this, passkey);
pairing_delegate_->KeysEntered(this, entered);
} }
void BluetoothDeviceExperimentalChromeOS::RequestConfirmation( void BluetoothDeviceExperimentalChromeOS::RequestConfirmation(
......
...@@ -128,8 +128,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { ...@@ -128,8 +128,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
request_passkey_count_(0), request_passkey_count_(0),
display_pincode_count_(0), display_pincode_count_(0),
display_passkey_count_(0), display_passkey_count_(0),
keys_entered_count_(0),
confirm_passkey_count_(0), confirm_passkey_count_(0),
dismiss_count_(0) {} dismiss_count_(0),
last_passkey_(9999999U),
last_entered_(999U) {}
virtual ~TestPairingDelegate() {} virtual ~TestPairingDelegate() {}
void RequestPinCode(BluetoothDevice* device) OVERRIDE { void RequestPinCode(BluetoothDevice* device) OVERRIDE {
...@@ -160,6 +163,14 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { ...@@ -160,6 +163,14 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
QuitMessageLoop(); QuitMessageLoop();
} }
void KeysEntered(BluetoothDevice* device,
uint32 entered) OVERRIDE {
++call_count_;
++keys_entered_count_;
last_entered_ = entered;
QuitMessageLoop();
}
void ConfirmPasskey(BluetoothDevice* device, void ConfirmPasskey(BluetoothDevice* device,
uint32 passkey) OVERRIDE { uint32 passkey) OVERRIDE {
++call_count_; ++call_count_;
...@@ -179,9 +190,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate { ...@@ -179,9 +190,11 @@ class TestPairingDelegate : public BluetoothDevice::PairingDelegate {
int request_passkey_count_; int request_passkey_count_;
int display_pincode_count_; int display_pincode_count_;
int display_passkey_count_; int display_passkey_count_;
int keys_entered_count_;
int confirm_passkey_count_; int confirm_passkey_count_;
int dismiss_count_; int dismiss_count_;
uint32 last_passkey_; uint32 last_passkey_;
uint32 last_entered_;
std::string last_pincode_; std::string last_pincode_;
private: private:
...@@ -1239,7 +1252,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairAppleKeyboard) { ...@@ -1239,7 +1252,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairAppleKeyboard) {
EXPECT_TRUE(device->IsPaired()); EXPECT_TRUE(device->IsPaired());
// Pairing dialog should be dismissed // Pairing dialog should be dismissed
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.dismiss_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_);
// Make sure the trusted property has been set to true. // Make sure the trusted property has been set to true.
...@@ -1274,15 +1286,32 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) { ...@@ -1274,15 +1286,32 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) {
base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback, base::Bind(&BluetoothExperimentalChromeOSTest::ConnectErrorCallback,
base::Unretained(this))); 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(1, pairing_delegate.display_passkey_count_);
EXPECT_EQ(123456U, pairing_delegate.last_passkey_); 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()); 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(); 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(1, callback_count_);
EXPECT_EQ(0, error_callback_count_); EXPECT_EQ(0, error_callback_count_);
...@@ -1296,7 +1325,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) { ...@@ -1296,7 +1325,6 @@ TEST_F(BluetoothExperimentalChromeOSTest, PairMotorolaKeyboard) {
EXPECT_TRUE(device->IsPaired()); EXPECT_TRUE(device->IsPaired());
// Pairing dialog should be dismissed // Pairing dialog should be dismissed
EXPECT_EQ(2, pairing_delegate.call_count_);
EXPECT_EQ(1, pairing_delegate.dismiss_count_); EXPECT_EQ(1, pairing_delegate.dismiss_count_);
// Make sure the trusted property has been set to true. // 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