hid_detection_screen_handler.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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 "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/compiler_specific.h" 10#include "base/macros.h" 11#include "base/metrics/histogram.h" 12#include "base/prefs/pref_service.h" 13#include "base/strings/string16.h" 14#include "base/strings/string_number_conversions.h" 15#include "base/strings/utf_string_conversions.h" 16#include "chrome/browser/browser_process.h" 17#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 18#include "chrome/common/pref_names.h" 19#include "chromeos/chromeos_switches.h" 20#include "device/bluetooth/bluetooth_adapter_factory.h" 21#include "grit/generated_resources.h" 22#include "ui/base/l10n/l10n_util.h" 23 24namespace { 25 26const char kJsScreenPath[] = "login.HIDDetectionScreen"; 27 28// Variants of pairing state. 29const char kRemotePinCode[] = "bluetoothRemotePinCode"; 30const char kRemotePasskey[] = "bluetoothRemotePasskey"; 31 32// Possible ui-states for device-blocks. 33const char kSearchingState[] = "searching"; 34const char kUSBConnectedState[] = "connected"; 35const char kBTPairedState[] = "paired"; 36const char kBTPairingState[] = "pairing"; 37// Special state for notifications that don't switch ui-state, but add info. 38const char kBTUpdateState[] = "update"; 39 40// Names of possible arguments used for ui update. 41const char kPincodeArgName[] = "pincode"; 42const char kDeviceNameArgName[] = "name"; 43const char kLabelArgName[] = "keyboard-label"; 44 45// Standard length of pincode for pairing BT keyboards. 46const int kPincodeLength = 6; 47 48bool DeviceIsPointing(device::BluetoothDevice::DeviceType device_type) { 49 return device_type == device::BluetoothDevice::DEVICE_MOUSE || 50 device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO || 51 device_type == device::BluetoothDevice::DEVICE_TABLET; 52} 53 54bool DeviceIsPointing(const device::InputServiceLinux::InputDeviceInfo& info) { 55 return info.is_mouse || info.is_touchpad || info.is_touchscreen || 56 info.is_tablet; 57} 58 59bool DeviceIsKeyboard(device::BluetoothDevice::DeviceType device_type) { 60 return device_type == device::BluetoothDevice::DEVICE_KEYBOARD || 61 device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO; 62} 63 64} // namespace 65 66namespace chromeos { 67 68HIDDetectionScreenHandler::HIDDetectionScreenHandler( 69 CoreOobeActor* core_oobe_actor) 70 : BaseScreenHandler(kJsScreenPath), 71 delegate_(NULL), 72 core_oobe_actor_(core_oobe_actor), 73 show_on_init_(false), 74 mouse_is_pairing_(false), 75 pointing_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN), 76 keyboard_is_pairing_(false), 77 keyboard_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN), 78 switch_on_adapter_when_ready_(false), 79 weak_ptr_factory_(this) { 80} 81 82HIDDetectionScreenHandler::~HIDDetectionScreenHandler() { 83 adapter_initially_powered_.reset(); 84 if (adapter_.get()) 85 adapter_->RemoveObserver(this); 86 input_service_proxy_.RemoveObserver(this); 87 if (delegate_) 88 delegate_->OnActorDestroyed(this); 89} 90 91void HIDDetectionScreenHandler::OnStartDiscoverySession( 92 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { 93 VLOG(1) << "BT Discovery session started"; 94 discovery_session_ = discovery_session.Pass(); 95 UpdateDevices(); 96} 97 98void HIDDetectionScreenHandler::SetPoweredError() { 99 LOG(ERROR) << "Failed to power BT adapter"; 100} 101 102void HIDDetectionScreenHandler::SetPoweredOffError() { 103 LOG(ERROR) << "Failed to power off BT adapter"; 104} 105 106void HIDDetectionScreenHandler::FindDevicesError() { 107 VLOG(1) << "Failed to start Bluetooth discovery."; 108} 109 110void HIDDetectionScreenHandler::Show() { 111 if (!page_is_ready()) { 112 show_on_init_ = true; 113 return; 114 } 115 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableDemoMode)) 116 core_oobe_actor_->InitDemoModeDetection(); 117 input_service_proxy_.AddObserver(this); 118 UpdateDevices(); 119 120 PrefService* local_state = g_browser_process->local_state(); 121 int num_of_times_dialog_was_shown = local_state->GetInteger( 122 prefs::kTimesHIDDialogShown); 123 local_state->SetInteger(prefs::kTimesHIDDialogShown, 124 num_of_times_dialog_was_shown + 1); 125 126 ShowScreen(OobeUI::kScreenHIDDetection, NULL); 127 if (!pointing_device_id_.empty()) 128 SendPointingDeviceNotification(); 129 if (!keyboard_device_id_.empty()) 130 SendKeyboardDeviceNotification(NULL); 131} 132 133void HIDDetectionScreenHandler::Hide() { 134 if (adapter_.get()) 135 adapter_->RemoveObserver(this); 136 input_service_proxy_.RemoveObserver(this); 137} 138 139void HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) { 140 delegate_ = delegate; 141 if (page_is_ready()) 142 Initialize(); 143} 144 145void HIDDetectionScreenHandler::CheckIsScreenRequired( 146 const base::Callback<void(bool)>& on_check_done) { 147 input_service_proxy_.GetDevices( 148 base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesListForCheck, 149 weak_ptr_factory_.GetWeakPtr(), 150 on_check_done)); 151} 152 153void HIDDetectionScreenHandler::DeclareLocalizedValues( 154 LocalizedValuesBuilder* builder) { 155 builder->Add("hidDetectionContinue", IDS_HID_DETECTION_CONTINUE_BUTTON); 156 builder->Add("hidDetectionInvitation", IDS_HID_DETECTION_INVITATION_TEXT); 157 builder->Add("hidDetectionPrerequisites", 158 IDS_HID_DETECTION_PRECONDITION_TEXT); 159 builder->Add("hidDetectionMouseSearching", IDS_HID_DETECTION_SEARCHING_MOUSE); 160 builder->Add("hidDetectionKeyboardSearching", 161 IDS_HID_DETECTION_SEARCHING_KEYBOARD); 162 builder->Add("hidDetectionUSBMouseConnected", 163 IDS_HID_DETECTION_CONNECTED_USB_MOUSE); 164 builder->Add("hidDetectionUSBKeyboardConnected", 165 IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD); 166 builder->Add("hidDetectionBTMousePaired", 167 IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE); 168 builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY); 169} 170 171void HIDDetectionScreenHandler::Initialize() { 172 if (!page_is_ready() || !delegate_) 173 return; 174 175 device::BluetoothAdapterFactory::GetAdapter( 176 base::Bind(&HIDDetectionScreenHandler::InitializeAdapter, 177 weak_ptr_factory_.GetWeakPtr())); 178 179 if (show_on_init_) { 180 Show(); 181 show_on_init_ = false; 182 } 183} 184 185void HIDDetectionScreenHandler::RegisterMessages() { 186 AddCallback( 187 "HIDDetectionOnContinue", &HIDDetectionScreenHandler::HandleOnContinue); 188} 189 190void HIDDetectionScreenHandler::HandleOnContinue() { 191 // Continue button pressed. 192 ContinueScenarioType scenario_type; 193 if (!pointing_device_id_.empty() && !keyboard_device_id_.empty()) 194 scenario_type = All_DEVICES_DETECTED; 195 else if (pointing_device_id_.empty()) 196 scenario_type = KEYBOARD_DEVICE_ONLY_DETECTED; 197 else 198 scenario_type = POINTING_DEVICE_ONLY_DETECTED; 199 200 UMA_HISTOGRAM_ENUMERATION( 201 "HIDDetection.OOBEDevicesDetectedOnContinuePressed", 202 scenario_type, 203 CONTINUE_SCENARIO_TYPE_SIZE); 204 205 // Switch off BT adapter if it was off before the screen and no BT device 206 // connected. 207 if (adapter_ && adapter_->IsPresent() && adapter_->IsPowered() && 208 !(pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH || 209 keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) && 210 adapter_initially_powered_ && !(*adapter_initially_powered_)) { 211 VLOG(1) << "Switching off BT adapter after HID OOBE screen as unused."; 212 adapter_->SetPowered( 213 false, 214 base::Bind(&base::DoNothing), 215 base::Bind(&HIDDetectionScreenHandler::SetPoweredOffError, 216 weak_ptr_factory_.GetWeakPtr())); 217 } 218 219 core_oobe_actor_->StopDemoModeDetection(); 220 if (delegate_) 221 delegate_->OnExit(); 222} 223 224void HIDDetectionScreenHandler::InitializeAdapter( 225 scoped_refptr<device::BluetoothAdapter> adapter) { 226 adapter_ = adapter; 227 CHECK(adapter_.get()); 228 229 adapter_->AddObserver(this); 230 UpdateDevices(); 231} 232 233void HIDDetectionScreenHandler::StartBTDiscoverySession() { 234 adapter_->StartDiscoverySession( 235 base::Bind(&HIDDetectionScreenHandler::OnStartDiscoverySession, 236 weak_ptr_factory_.GetWeakPtr()), 237 base::Bind(&HIDDetectionScreenHandler::FindDevicesError, 238 weak_ptr_factory_.GetWeakPtr())); 239} 240 241void HIDDetectionScreenHandler::RequestPinCode( 242 device::BluetoothDevice* device) { 243 VLOG(1) << "RequestPinCode id = " << device->GetDeviceID() 244 << " name = " << device->GetName(); 245 device->CancelPairing(); 246} 247 248void HIDDetectionScreenHandler::RequestPasskey( 249 device::BluetoothDevice* device) { 250 VLOG(1) << "RequestPassKey id = " << device->GetDeviceID() 251 << " name = " << device->GetName(); 252 device->CancelPairing(); 253} 254 255void HIDDetectionScreenHandler::DisplayPinCode(device::BluetoothDevice* device, 256 const std::string& pincode) { 257 VLOG(1) << "DisplayPinCode id = " << device->GetDeviceID() 258 << " name = " << device->GetName(); 259 base::DictionaryValue params; 260 params.SetString("state", kBTPairingState); 261 params.SetString("pairing-state", kRemotePinCode); 262 params.SetString("pincode", pincode); 263 params.SetString(kDeviceNameArgName, device->GetName()); 264 SendKeyboardDeviceNotification(¶ms); 265} 266 267void HIDDetectionScreenHandler::DisplayPasskey( 268 device::BluetoothDevice* device, uint32 passkey) { 269 VLOG(1) << "DisplayPassKey id = " << device->GetDeviceID() 270 << " name = " << device->GetName(); 271 base::DictionaryValue params; 272 params.SetString("state", kBTPairingState); 273 params.SetString("pairing-state", kRemotePasskey); 274 params.SetInteger("passkey", passkey); 275 std::string pincode = base::UintToString(passkey); 276 pincode = std::string(kPincodeLength - pincode.length(), '0').append(pincode); 277 params.SetString("pincode", pincode); 278 params.SetString(kDeviceNameArgName, device->GetName()); 279 SendKeyboardDeviceNotification(¶ms); 280} 281 282void HIDDetectionScreenHandler::KeysEntered( 283 device::BluetoothDevice* device, uint32 entered) { 284 VLOG(1) << "Keys entered"; 285 base::DictionaryValue params; 286 params.SetString("state", kBTUpdateState); 287 params.SetInteger("keysEntered", entered); 288 SendKeyboardDeviceNotification(¶ms); 289} 290 291void HIDDetectionScreenHandler::ConfirmPasskey( 292 device::BluetoothDevice* device, uint32 passkey) { 293 VLOG(1) << "Confirm Passkey"; 294 device->CancelPairing(); 295} 296 297void HIDDetectionScreenHandler::AuthorizePairing( 298 device::BluetoothDevice* device) { 299 // There is never any circumstance where this will be called, since the 300 // HID detection screen handler will only be used for outgoing pairing 301 // requests, but play it safe. 302 VLOG(1) << "Authorize pairing"; 303 device->ConfirmPairing(); 304} 305 306void HIDDetectionScreenHandler::AdapterPresentChanged( 307 device::BluetoothAdapter* adapter, bool present) { 308 if (present && switch_on_adapter_when_ready_) { 309 VLOG(1) << "Switching on BT adapter on HID OOBE screen."; 310 adapter_initially_powered_.reset(new bool(adapter_->IsPowered())); 311 adapter_->SetPowered( 312 true, 313 base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession, 314 weak_ptr_factory_.GetWeakPtr()), 315 base::Bind(&HIDDetectionScreenHandler::SetPoweredError, 316 weak_ptr_factory_.GetWeakPtr())); 317 } 318} 319 320void HIDDetectionScreenHandler::TryPairingAsPointingDevice( 321 device::BluetoothDevice* device) { 322 if (pointing_device_id_.empty() && 323 DeviceIsPointing(device->GetDeviceType()) && 324 device->IsPairable() && !device->IsPaired() && !mouse_is_pairing_) { 325 ConnectBTDevice(device); 326 } 327} 328 329void HIDDetectionScreenHandler::TryPairingAsKeyboardDevice( 330 device::BluetoothDevice* device) { 331 if (keyboard_device_id_.empty() && 332 DeviceIsKeyboard(device->GetDeviceType()) && 333 device->IsPairable() && !device->IsPaired() && !keyboard_is_pairing_) { 334 ConnectBTDevice(device); 335 } 336} 337 338void HIDDetectionScreenHandler::DeviceAdded( 339 device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { 340 VLOG(1) << "BT input device added id = " << device->GetDeviceID() << 341 " name = " << device->GetName(); 342 TryPairingAsPointingDevice(device); 343 TryPairingAsKeyboardDevice(device); 344} 345 346void HIDDetectionScreenHandler::DeviceChanged( 347 device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { 348 VLOG(1) << "BT device changed id = " << device->GetDeviceID() << " name = " << 349 device->GetName(); 350 TryPairingAsPointingDevice(device); 351 TryPairingAsKeyboardDevice(device); 352} 353 354void HIDDetectionScreenHandler::DeviceRemoved( 355 device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { 356 VLOG(1) << "BT device removed id = " << device->GetDeviceID() << " name = " << 357 device->GetName(); 358} 359 360void HIDDetectionScreenHandler::OnInputDeviceAdded( 361 const InputDeviceInfo& info) { 362 VLOG(1) << "Input device added id = " << info.id << " name = " << info.name; 363 // TODO(merkulova): deal with all available device types, e.g. joystick. 364 if (!keyboard_device_id_.empty() && !pointing_device_id_.empty()) 365 return; 366 367 if (pointing_device_id_.empty() && DeviceIsPointing(info)) { 368 pointing_device_id_ = info.id; 369 pointing_device_name_ = info.name; 370 pointing_device_connect_type_ = info.type; 371 SendPointingDeviceNotification(); 372 } 373 if (keyboard_device_id_.empty() && info.is_keyboard) { 374 keyboard_device_id_ = info.id; 375 keyboard_device_name_ = info.name; 376 keyboard_device_connect_type_ = info.type; 377 SendKeyboardDeviceNotification(NULL); 378 } 379} 380 381void HIDDetectionScreenHandler::OnInputDeviceRemoved(const std::string& id) { 382 if (id == keyboard_device_id_) { 383 keyboard_device_id_.clear(); 384 keyboard_device_name_.clear(); 385 keyboard_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN; 386 SendKeyboardDeviceNotification(NULL); 387 UpdateDevices(); 388 } else if (id == pointing_device_id_) { 389 pointing_device_id_.clear(); 390 pointing_device_name_.clear(); 391 pointing_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN; 392 SendPointingDeviceNotification(); 393 UpdateDevices(); 394 } 395} 396 397// static 398void HIDDetectionScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) { 399 registry->RegisterIntegerPref(prefs::kTimesHIDDialogShown, 0); 400} 401 402void HIDDetectionScreenHandler::UpdateDevices() { 403 input_service_proxy_.GetDevices( 404 base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesList, 405 weak_ptr_factory_.GetWeakPtr())); 406} 407 408void HIDDetectionScreenHandler::UpdateBTDevices() { 409 if (!adapter_ || !adapter_->IsPresent() || !adapter_->IsPowered()) 410 return; 411 412 // If no connected devices found as pointing device and keyboard, we try to 413 // connect some type-suitable active bluetooth device. 414 std::vector<device::BluetoothDevice*> bt_devices = adapter_->GetDevices(); 415 for (std::vector<device::BluetoothDevice*>::const_iterator it = 416 bt_devices.begin(); 417 it != bt_devices.end() && 418 (keyboard_device_id_.empty() || pointing_device_id_.empty()); 419 ++it) { 420 TryPairingAsPointingDevice(*it); 421 TryPairingAsKeyboardDevice(*it); 422 } 423} 424 425void HIDDetectionScreenHandler::ProcessConnectedDevicesList( 426 const std::vector<InputDeviceInfo>& devices) { 427 for (std::vector<InputDeviceInfo>::const_iterator it = devices.begin(); 428 it != devices.end() && 429 (pointing_device_id_.empty() || keyboard_device_id_.empty()); 430 ++it) { 431 if (pointing_device_id_.empty() && DeviceIsPointing(*it)) { 432 pointing_device_id_ = it->id; 433 pointing_device_name_ = it->name; 434 pointing_device_connect_type_ = it->type; 435 if (page_is_ready()) 436 SendPointingDeviceNotification(); 437 } 438 if (keyboard_device_id_.empty() && it->is_keyboard) { 439 keyboard_device_id_ = it->id; 440 keyboard_device_name_ = it->name; 441 keyboard_device_connect_type_ = it->type; 442 if (page_is_ready()) 443 SendKeyboardDeviceNotification(NULL); 444 } 445 } 446} 447 448void HIDDetectionScreenHandler::TryInitiateBTDevicesUpdate() { 449 if ((pointing_device_id_.empty() || keyboard_device_id_.empty()) && 450 adapter_) { 451 if (!adapter_->IsPresent()) { 452 // Switch on BT adapter later when it's available. 453 switch_on_adapter_when_ready_ = true; 454 } else if (!adapter_->IsPowered()) { 455 VLOG(1) << "Switching on BT adapter on HID OOBE screen."; 456 adapter_initially_powered_.reset(new bool(false)); 457 adapter_->SetPowered( 458 true, 459 base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession, 460 weak_ptr_factory_.GetWeakPtr()), 461 base::Bind(&HIDDetectionScreenHandler::SetPoweredError, 462 weak_ptr_factory_.GetWeakPtr())); 463 } else { 464 UpdateBTDevices(); 465 } 466 } 467} 468 469void HIDDetectionScreenHandler::OnGetInputDevicesListForCheck( 470 const base::Callback<void(bool)>& on_check_done, 471 const std::vector<InputDeviceInfo>& devices) { 472 ProcessConnectedDevicesList(devices); 473 474 // Screen is not required if both devices are present. 475 bool all_devices_autodetected = !pointing_device_id_.empty() && 476 !keyboard_device_id_.empty(); 477 UMA_HISTOGRAM_BOOLEAN("HIDDetection.OOBEDialogShown", 478 !all_devices_autodetected); 479 480 on_check_done.Run(!all_devices_autodetected); 481} 482 483void HIDDetectionScreenHandler::OnGetInputDevicesList( 484 const std::vector<InputDeviceInfo>& devices) { 485 ProcessConnectedDevicesList(devices); 486 TryInitiateBTDevicesUpdate(); 487} 488 489void HIDDetectionScreenHandler::ConnectBTDevice( 490 device::BluetoothDevice* device) { 491 if (!device->IsPairable() || device->IsPaired()) 492 return; 493 device::BluetoothDevice::DeviceType device_type = device->GetDeviceType(); 494 495 if (device_type == device::BluetoothDevice::DEVICE_MOUSE || 496 device_type == device::BluetoothDevice::DEVICE_TABLET) { 497 if (mouse_is_pairing_) 498 return; 499 mouse_is_pairing_ = true; 500 } else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) { 501 if (keyboard_is_pairing_) 502 return; 503 keyboard_is_pairing_ = true; 504 } else if (device_type == 505 device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) { 506 if (mouse_is_pairing_ || keyboard_is_pairing_) 507 return; 508 mouse_is_pairing_ = true; 509 keyboard_is_pairing_ = true; 510 } 511 device->Connect(this, 512 base::Bind(&HIDDetectionScreenHandler::BTConnected, 513 weak_ptr_factory_.GetWeakPtr(), device_type), 514 base::Bind(&HIDDetectionScreenHandler::BTConnectError, 515 weak_ptr_factory_.GetWeakPtr(), 516 device->GetAddress(), device_type)); 517} 518 519void HIDDetectionScreenHandler::BTConnected( 520 device::BluetoothDevice::DeviceType device_type) { 521 if (DeviceIsPointing(device_type)) 522 mouse_is_pairing_ = false; 523 if (DeviceIsKeyboard(device_type)) 524 keyboard_is_pairing_ = false; 525} 526 527void HIDDetectionScreenHandler::BTConnectError( 528 const std::string& address, 529 device::BluetoothDevice::DeviceType device_type, 530 device::BluetoothDevice::ConnectErrorCode error_code) { 531 LOG(WARNING) << "BTConnectError while connecting " << address 532 << " error code = " << error_code; 533 if (DeviceIsPointing(device_type)) 534 mouse_is_pairing_ = false; 535 if (DeviceIsKeyboard(device_type)) { 536 keyboard_is_pairing_ = false; 537 SendKeyboardDeviceNotification(NULL); 538 } 539 540 if (pointing_device_id_.empty() || keyboard_device_id_.empty()) 541 UpdateDevices(); 542} 543 544 545void HIDDetectionScreenHandler::SendPointingDeviceNotification() { 546 std::string state; 547 if (pointing_device_id_.empty()) 548 state = kSearchingState; 549 else if (pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) 550 state = kBTPairedState; 551 else 552 state = kUSBConnectedState; 553 CallJS("setPointingDeviceState", state); 554} 555 556void HIDDetectionScreenHandler::SendKeyboardDeviceNotification( 557 base::DictionaryValue* params) { 558 base::DictionaryValue state_info; 559 if (params) 560 state_info.MergeDictionary(params); 561 562 base::string16 device_name; 563 if (!state_info.GetString(kDeviceNameArgName, &device_name)) { 564 device_name = l10n_util::GetStringUTF16( 565 IDS_HID_DETECTION_DEFAULT_KEYBOARD_NAME); 566 } 567 568 if (keyboard_device_id_.empty()) { 569 if (!state_info.HasKey("state")) { 570 state_info.SetString("state", kSearchingState); 571 } else if (state_info.HasKey(kPincodeArgName)) { 572 state_info.SetString( 573 kLabelArgName, 574 l10n_util::GetStringFUTF16( 575 IDS_HID_DETECTION_BLUETOOTH_REMOTE_PIN_CODE_REQUEST, 576 device_name)); 577 } 578 } else if (keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) { 579 state_info.SetString("state", kBTPairedState); 580 state_info.SetString( 581 kLabelArgName, 582 l10n_util::GetStringFUTF16( 583 IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD, 584 base::UTF8ToUTF16(keyboard_device_name_))); 585 } else { 586 state_info.SetString("state", kUSBConnectedState); 587 } 588 CallJS("setKeyboardDeviceState", state_info); 589} 590 591} // namespace chromeos 592