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