hid_detection_screen_handler.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/command_line.h"
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/compiler_specific.h"
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/macros.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/histogram.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/pref_service.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string16.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/browser_process.h"
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/pref_names.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/chromeos_switches.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/chromium_strings.h"
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "grit/generated_resources.h"
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace {
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kJsScreenPath[] = "login.HIDDetectionScreen";
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Variants of pairing state.
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePinCode[] = "bluetoothRemotePinCode";
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePasskey[] = "bluetoothRemotePasskey";
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Possible ui-states for device-blocks.
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kSearchingState[] = "searching";
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kUSBConnectedState[] = "connected";
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairedState[] = "paired";
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairingState[] = "pairing";
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Special state for notifications that don't switch ui-state, but add info.
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTUpdateState[] = "update";
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Names of possible arguments used for ui update.
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPincodeArgName[] = "pincode";
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kDeviceNameArgName[] = "name";
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kLabelArgName[] = "keyboard-label";
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Standard length of pincode for pairing BT keyboards.
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kPincodeLength = 6;
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(device::BluetoothDevice::DeviceType device_type) {
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_MOUSE ||
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO ||
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_TABLET;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(const device::InputServiceLinux::InputDeviceInfo& info) {
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return info.is_mouse || info.is_touchpad || info.is_touchscreen ||
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         info.is_tablet;
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsKeyboard(device::BluetoothDevice::DeviceType device_type) {
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_KEYBOARD ||
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace chromeos {
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)HIDDetectionScreenHandler::HIDDetectionScreenHandler(
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CoreOobeActor* core_oobe_actor)
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : BaseScreenHandler(kJsScreenPath),
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      delegate_(NULL),
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      core_oobe_actor_(core_oobe_actor),
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      show_on_init_(false),
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      mouse_is_pairing_(false),
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      pointing_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN),
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_is_pairing_(false),
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      keyboard_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN),
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_(false),
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_ptr_factory_(this) {
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
83a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochHIDDetectionScreenHandler::~HIDDetectionScreenHandler() {
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  adapter_initially_powered_.reset();
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnActorDestroyed(this);
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnStartDiscoverySession(
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT Discovery session started";
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  discovery_session_ = discovery_session.Pass();
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SetPoweredError() {
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(ERROR) << "Failed to power BT adapter";
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void HIDDetectionScreenHandler::SetPoweredOffError() {
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  LOG(ERROR) << "Failed to power off BT adapter";
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::FindDevicesError() {
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Failed to start Bluetooth discovery.";
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Show() {
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready()) {
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = true;
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableDemoMode))
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    core_oobe_actor_->InitDemoModeDetection();
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.AddObserver(this);
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateDevices();
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int num_of_times_dialog_was_shown = local_state->GetInteger(
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      prefs::kTimesHIDDialogShown);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  local_state->SetInteger(prefs::kTimesHIDDialogShown,
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          num_of_times_dialog_was_shown + 1);
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ShowScreen(OobeUI::kScreenHIDDetection, NULL);
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pointing_device_id_.empty())
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SendPointingDeviceNotification();
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!keyboard_device_id_.empty())
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Hide() {
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) {
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  delegate_ = delegate;
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (page_is_ready())
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Initialize();
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void HIDDetectionScreenHandler::CheckIsScreenRequired(
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(bool)>& on_check_done) {
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  input_service_proxy_.GetDevices(
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesListForCheck,
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 on_check_done));
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::DeclareLocalizedValues(
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    LocalizedValuesBuilder* builder) {
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  builder->Add("hidDetectionContinue", IDS_HID_DETECTION_CONTINUE_BUTTON);
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionInvitation", IDS_HID_DETECTION_INVITATION_TEXT);
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionPrerequisites",
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PRECONDITION_TEXT);
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionMouseSearching", IDS_HID_DETECTION_SEARCHING_MOUSE);
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionKeyboardSearching",
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_SEARCHING_KEYBOARD);
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBMouseConnected",
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_MOUSE);
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBKeyboardConnected",
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD);
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTMousePaired",
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE);
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY);
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Initialize() {
173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready() || !delegate_)
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::InitializeAdapter,
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (show_on_init_) {
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Show();
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = false;
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::RegisterMessages() {
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddCallback(
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      "HIDDetectionOnContinue", &HIDDetectionScreenHandler::HandleOnContinue);
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::HandleOnContinue() {
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Continue button pressed.
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ContinueScenarioType scenario_type;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pointing_device_id_.empty() && !keyboard_device_id_.empty())
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = All_DEVICES_DETECTED;
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (pointing_device_id_.empty())
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = KEYBOARD_DEVICE_ONLY_DETECTED;
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = POINTING_DEVICE_ONLY_DETECTED;
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "HIDDetection.OOBEDevicesDetectedOnContinuePressed",
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scenario_type,
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CONTINUE_SCENARIO_TYPE_SIZE);
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Switch off BT adapter if it was off before the screen and no BT device
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // connected.
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (adapter_ && adapter_->IsPresent() && adapter_->IsPowered() &&
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      !(pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH ||
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) &&
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      adapter_initially_powered_ && !(*adapter_initially_powered_)) {
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "Switching off BT adapter after HID OOBE screen as unused.";
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    adapter_->SetPowered(
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        false,
2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Bind(&base::DoNothing),
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::SetPoweredOffError,
2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  core_oobe_actor_->StopDemoModeDetection();
221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnExit();
223a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
224a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::InitializeAdapter(
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_ = adapter;
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(adapter_.get());
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->AddObserver(this);
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::StartBTDiscoverySession() {
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->StartDiscoverySession(
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnStartDiscoverySession,
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()),
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::FindDevicesError,
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPinCode(
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPinCode id = " << device->GetDeviceID()
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPasskey(
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPassKey id = " << device->GetDeviceID()
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPinCode(device::BluetoothDevice* device,
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                               const std::string& pincode) {
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPinCode id = " << device->GetDeviceID()
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePinCode);
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPasskey(
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPassKey id = " << device->GetDeviceID()
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePasskey);
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("passkey", passkey);
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string pincode = base::UintToString(passkey);
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pincode = std::string(kPincodeLength - pincode.length(), '0').append(pincode);
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::KeysEntered(
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 entered) {
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Keys entered";
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTUpdateState);
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("keysEntered", entered);
289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConfirmPasskey(
293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Confirm Passkey";
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AuthorizePairing(
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // There is never any circumstance where this will be called, since the
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // HID detection screen  handler will only be used for outgoing pairing
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // requests, but play it safe.
303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Authorize pairing";
304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->ConfirmPairing();
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AdapterPresentChanged(
308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, bool present) {
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (present && switch_on_adapter_when_ready_) {
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "Switching on BT adapter on HID OOBE screen.";
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    adapter_initially_powered_.reset(new bool(adapter_->IsPowered()));
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->SetPowered(
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        true,
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsPointingDevice(
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() &&
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsPointing(device->GetDeviceType()) &&
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !mouse_is_pairing_) {
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsKeyboardDevice(
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() &&
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsKeyboard(device->GetDeviceType()) &&
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !keyboard_is_pairing_) {
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceAdded(
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT input device added id = " << device->GetDeviceID() <<
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      " name = " << device->GetName();
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceChanged(
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device changed id = " << device->GetDeviceID() << " name = " <<
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceRemoved(
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device removed id = " << device->GetDeviceID() << " name = " <<
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceAdded(
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const InputDeviceInfo& info) {
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Input device added id = " << info.id << " name = " << info.name;
364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(merkulova): deal with all available device types, e.g. joystick.
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!keyboard_device_id_.empty() && !pointing_device_id_.empty())
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() && DeviceIsPointing(info)) {
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_ = info.id;
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_ = info.name;
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = info.type;
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() && info.is_keyboard) {
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_ = info.id;
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_ = info.name;
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = info.type;
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceRemoved(const std::string& id) {
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (id == keyboard_device_id_) {
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_.clear();
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_.clear();
386010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
388010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (id == pointing_device_id_) {
390010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_.clear();
391010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_.clear();
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kTimesHIDDialogShown, 0);
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateDevices() {
404010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.GetDevices(
405010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesList,
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
407010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateBTDevices() {
410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!adapter_ || !adapter_->IsPresent() || !adapter_->IsPowered())
411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If no connected devices found as pointing device and keyboard, we try to
414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // connect some type-suitable active bluetooth device.
415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<device::BluetoothDevice*> bt_devices = adapter_->GetDevices();
416010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<device::BluetoothDevice*>::const_iterator it =
417010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           bt_devices.begin();
418010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != bt_devices.end() &&
419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           (keyboard_device_id_.empty() || pointing_device_id_.empty());
420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
421010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsPointingDevice(*it);
422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsKeyboardDevice(*it);
423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
425010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::ProcessConnectedDevicesList(
427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<InputDeviceInfo>::const_iterator it = devices.begin();
429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != devices.end() &&
430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       (pointing_device_id_.empty() || keyboard_device_id_.empty());
431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (pointing_device_id_.empty() && DeviceIsPointing(*it)) {
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_id_ = it->id;
434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_name_ = it->name;
435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_connect_type_ = it->type;
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (page_is_ready())
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SendPointingDeviceNotification();
438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_device_id_.empty() && it->is_keyboard) {
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_id_ = it->id;
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_name_ = it->name;
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_connect_type_ = it->type;
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (page_is_ready())
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SendKeyboardDeviceNotification(NULL);
445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::TryInitiateBTDevicesUpdate() {
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((pointing_device_id_.empty() || keyboard_device_id_.empty()) &&
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      adapter_) {
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!adapter_->IsPresent()) {
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Switch on BT adapter later when it's available.
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_ = true;
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (!adapter_->IsPowered()) {
4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      VLOG(1) << "Switching on BT adapter on HID OOBE screen.";
4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      adapter_initially_powered_.reset(new bool(false));
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      adapter_->SetPowered(
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          true,
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      UpdateBTDevices();
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void HIDDetectionScreenHandler::OnGetInputDevicesListForCheck(
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(bool)>& on_check_done,
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProcessConnectedDevicesList(devices);
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Screen is not required if both devices are present.
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool all_devices_autodetected = !pointing_device_id_.empty() &&
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  !keyboard_device_id_.empty();
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("HIDDetection.OOBEDialogShown",
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        !all_devices_autodetected);
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  on_check_done.Run(!all_devices_autodetected);
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::OnGetInputDevicesList(
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProcessConnectedDevicesList(devices);
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TryInitiateBTDevicesUpdate();
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConnectBTDevice(
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!device->IsPairable() || device->IsPaired())
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
494010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothDevice::DeviceType device_type = device->GetDeviceType();
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (device_type == device::BluetoothDevice::DEVICE_MOUSE ||
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device_type == device::BluetoothDevice::DEVICE_TABLET) {
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_)
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) {
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_is_pairing_)
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type ==
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) {
507010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_ || keyboard_is_pairing_)
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->Connect(this,
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnected,
514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(), device_type),
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnectError,
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       device->GetAddress(), device_type));
518010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
519010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnected(
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type) {
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsKeyboard(device_type))
525010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
526010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnectError(
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& address,
530010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type,
531010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::ConnectErrorCode error_code) {
532010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(WARNING) << "BTConnectError while connecting " << address
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               << " error code = " << error_code;
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (DeviceIsKeyboard(device_type)) {
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() || keyboard_device_id_.empty())
542010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
543010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
544010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendPointingDeviceNotification() {
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string state;
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty())
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kSearchingState;
550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else if (pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH)
551010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kBTPairedState;
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kUSBConnectedState;
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setPointingDeviceState", state);
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendKeyboardDeviceNotification(
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::DictionaryValue* params) {
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue state_info;
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (params)
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.MergeDictionary(params);
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::string16 device_name;
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!state_info.GetString(kDeviceNameArgName, &device_name)) {
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device_name = l10n_util::GetStringUTF16(
566010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        IDS_HID_DETECTION_DEFAULT_KEYBOARD_NAME);
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty()) {
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!state_info.HasKey("state")) {
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString("state", kSearchingState);
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (state_info.HasKey(kPincodeArgName)) {
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString(
574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          kLabelArgName,
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          l10n_util::GetStringFUTF16(
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              IDS_HID_DETECTION_BLUETOOTH_REMOTE_PIN_CODE_REQUEST,
577010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              device_name));
578010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) {
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kBTPairedState);
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString(
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kLabelArgName,
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        l10n_util::GetStringFUTF16(
584010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD,
585010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::UTF8ToUTF16(keyboard_device_name_)));
586010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kUSBConnectedState);
588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setKeyboardDeviceState", state_info);
590010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
591010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
592a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace chromeos
593