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(&params);
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(&params);
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(&params);
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