hid_detection_screen_handler.cc revision 010d83a9304c5a91596085d917d248abff47903a
1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// found in the LICENSE file.
4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/bind.h"
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/compiler_specific.h"
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/macros.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string16.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/chromium_strings.h"
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/generated_resources.h"
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace {
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kJsScreenPath[] = "login.HIDDetectionScreen";
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Variants of pairing state.
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePinCode[] = "bluetoothRemotePinCode";
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePasskey[] = "bluetoothRemotePasskey";
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Possible ui-states for device-blocks.
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kSearchingState[] = "searching";
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kUSBConnectedState[] = "connected";
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairedState[] = "paired";
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairingState[] = "pairing";
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Special state for notifications that don't switch ui-state, but add info.
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTUpdateState[] = "update";
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Names of possible arguments used for ui update.
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPincodeArgName[] = "pincode";
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kDeviceNameArgName[] = "name";
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kLabelArgName[] = "keyboard-label";
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Standard length of pincode for pairing BT keyboards.
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kPincodeLength = 6;
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(device::BluetoothDevice::DeviceType device_type) {
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_MOUSE ||
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO ||
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_TABLET;
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(const device::InputServiceLinux::InputDeviceInfo& info) {
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return info.is_mouse || info.is_touchpad || info.is_touchscreen ||
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         info.is_tablet;
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsKeyboard(device::BluetoothDevice::DeviceType device_type) {
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_KEYBOARD ||
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace chromeos {
62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
63a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochHIDDetectionScreenHandler::HIDDetectionScreenHandler()
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : BaseScreenHandler(kJsScreenPath),
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      delegate_(NULL),
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      show_on_init_(false),
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      mouse_is_pairing_(false),
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_is_pairing_(false),
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_(false),
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      skip_screen_if_devices_present_(true),
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_ptr_factory_(this) {
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
74a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochHIDDetectionScreenHandler::~HIDDetectionScreenHandler() {
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnActorDestroyed(this);
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnStartDiscoverySession(
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT Discovery session started";
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  discovery_session_ = discovery_session.Pass();
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SetPoweredError() {
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(ERROR) << "Failed to power BT adapter";
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::FindDevicesError() {
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Failed to start Bluetooth discovery.";
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Show() {
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready()) {
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = true;
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.AddObserver(this);
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  skip_screen_if_devices_present_ = true;
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ShowScreen(OobeUI::kScreenHIDDetection, NULL);
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Hide() {
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) {
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  delegate_ = delegate;
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (page_is_ready())
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Initialize();
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::DeclareLocalizedValues(
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    LocalizedValuesBuilder* builder) {
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  builder->Add("hidDetectionContinue", IDS_HID_DETECTION_CONTINUE_BUTTON);
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionInvitation", IDS_HID_DETECTION_INVITATION_TEXT);
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionPrerequisites",
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PRECONDITION_TEXT);
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionMouseSearching", IDS_HID_DETECTION_SEARCHING_MOUSE);
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionKeyboardSearching",
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_SEARCHING_KEYBOARD);
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBMouseConnected",
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_MOUSE);
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBKeyboardConnected",
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD);
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTMousePaired",
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE);
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY);
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Initialize() {
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready() || !delegate_)
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::InitializeAdapter,
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (show_on_init_) {
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Show();
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = false;
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::RegisterMessages() {
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddCallback(
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      "HIDDetectionOnContinue", &HIDDetectionScreenHandler::HandleOnContinue);
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::HandleOnContinue() {
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnExit();
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::InitializeAdapter(
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_ = adapter;
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(adapter_.get());
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->AddObserver(this);
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::StartBTDiscoverySession() {
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->StartDiscoverySession(
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnStartDiscoverySession,
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()),
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::FindDevicesError,
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPinCode(
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPinCode id = " << device->GetDeviceID()
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPasskey(
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPassKey id = " << device->GetDeviceID()
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPinCode(device::BluetoothDevice* device,
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                               const std::string& pincode) {
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPinCode id = " << device->GetDeviceID()
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePinCode);
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPasskey(
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPassKey id = " << device->GetDeviceID()
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePasskey);
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("passkey", passkey);
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string pincode = base::UintToString(passkey);
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pincode = std::string(kPincodeLength - pincode.length(), '0').append(pincode);
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::KeysEntered(
221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 entered) {
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Keys entered";
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTUpdateState);
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("keysEntered", entered);
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConfirmPasskey(
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Confirm Passkey";
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AuthorizePairing(
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // There is never any circumstance where this will be called, since the
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // HID detection screen  handler will only be used for outgoing pairing
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // requests, but play it safe.
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Authorize pairing";
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->ConfirmPairing();
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AdapterPresentChanged(
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, bool present) {
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (present && switch_on_adapter_when_ready_) {
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->SetPowered(
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        true,
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsPointingDevice(
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() &&
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsPointing(device->GetDeviceType()) &&
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !mouse_is_pairing_) {
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsKeyboardDevice(
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() &&
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsKeyboard(device->GetDeviceType()) &&
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !keyboard_is_pairing_) {
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceAdded(
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT input device added id = " << device->GetDeviceID() <<
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      " name = " << device->GetName();
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceChanged(
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device changed id = " << device->GetDeviceID() << " name = " <<
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceRemoved(
291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device removed id = " << device->GetDeviceID() << " name = " <<
293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceAdded(
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const InputDeviceInfo& info) {
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Input device added id = " << info.id << " name = " << info.name;
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(merkulova): deal with all available device types, e.g. joystick.
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!keyboard_device_id_.empty() && !pointing_device_id_.empty())
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() && DeviceIsPointing(info)) {
304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_ = info.id;
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_ = info.name;
306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = info.type;
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() && info.is_keyboard) {
310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_ = info.id;
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_ = info.name;
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = info.type;
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceRemoved(const std::string& id) {
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (id == keyboard_device_id_) {
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_.clear();
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_.clear();
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (id == pointing_device_id_) {
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_.clear();
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_.clear();
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateDevices() {
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.GetDevices(
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesList,
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Unretained(this)));
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateBTDevices() {
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!adapter_ || !adapter_->IsPresent() || !adapter_->IsPowered())
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If no connected devices found as pointing device and keyboard, we try to
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // connect some type-suitable active bluetooth device.
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<device::BluetoothDevice*> bt_devices = adapter_->GetDevices();
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<device::BluetoothDevice*>::const_iterator it =
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           bt_devices.begin();
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != bt_devices.end() &&
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           (keyboard_device_id_.empty() || pointing_device_id_.empty());
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsPointingDevice(*it);
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsKeyboardDevice(*it);
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnGetInputDevicesList(
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<InputDeviceInfo>::const_iterator it = devices.begin();
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != devices.end() &&
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       (pointing_device_id_.empty() || keyboard_device_id_.empty());
361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (pointing_device_id_.empty() && DeviceIsPointing(*it)) {
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_id_ = it->id;
364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_name_ = it->name;
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_connect_type_ = it->type;
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      SendPointingDeviceNotification();
367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_device_id_.empty() && it->is_keyboard) {
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_id_ = it->id;
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_name_ = it->name;
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_connect_type_ = it->type;
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      SendKeyboardDeviceNotification(NULL);
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Skip screen if both devices are present and skip was requested.
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!pointing_device_id_.empty() &&
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      !keyboard_device_id_.empty() &&
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      skip_screen_if_devices_present_) {
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    HandleOnContinue();
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Skip requested only once on dialog show.
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  skip_screen_if_devices_present_ = false;
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((pointing_device_id_.empty() || keyboard_device_id_.empty()) &&
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      adapter_) {
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!adapter_->IsPresent()) {
386010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Switch on BT adapter later when it's available.
387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_ = true;
388010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (!adapter_->IsPowered()) {
389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      adapter_->SetPowered(
390010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          true,
391010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      UpdateBTDevices();
397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
398010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
399010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
400010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
401010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConnectBTDevice(
402010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!device->IsPairable() || device->IsPaired())
404010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
405010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothDevice::DeviceType device_type = device->GetDeviceType();
406010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
407010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (device_type == device::BluetoothDevice::DEVICE_MOUSE ||
408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device_type == device::BluetoothDevice::DEVICE_TABLET) {
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_)
410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) {
413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_is_pairing_)
414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
416010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type ==
417010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) {
418010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_ || keyboard_is_pairing_)
419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
421010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->Connect(this,
424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnected,
425010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(), device_type),
426010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnectError,
427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       device->GetAddress(), device_type));
429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnected(
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type) {
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsKeyboard(device_type))
436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnectError(
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& address,
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type,
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::ConnectErrorCode error_code) {
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(WARNING) << "BTConnectError while connecting " << address
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               << " error code = " << error_code;
445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsKeyboard(device_type))
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() || keyboard_device_id_.empty())
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendPointingDeviceNotification() {
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string state;
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty())
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kSearchingState;
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else if (pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH)
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kBTPairedState;
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kUSBConnectedState;
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setPointingDeviceState", state);
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendKeyboardDeviceNotification(
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::DictionaryValue* params) {
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue state_info;
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (params)
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.MergeDictionary(params);
471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::string16 device_name;
473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!state_info.GetString(kDeviceNameArgName, &device_name)) {
474010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device_name = l10n_util::GetStringUTF16(
475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        IDS_HID_DETECTION_DEFAULT_KEYBOARD_NAME);
476010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty()) {
479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!state_info.HasKey("state")) {
480010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString("state", kSearchingState);
481010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (state_info.HasKey(kPincodeArgName)) {
482010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString(
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          kLabelArgName,
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          l10n_util::GetStringFUTF16(
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              IDS_HID_DETECTION_BLUETOOTH_REMOTE_PIN_CODE_REQUEST,
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              device_name));
487010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) {
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kBTPairedState);
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString(
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kLabelArgName,
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        l10n_util::GetStringFUTF16(
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD,
494010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::UTF8ToUTF16(keyboard_device_name_)));
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kUSBConnectedState);
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setKeyboardDeviceState", state_info);
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
501a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace chromeos
502