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"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/chromeos_switches.h"
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_adapter_factory.h"
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace {
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst char kJsScreenPath[] = "login.HIDDetectionScreen";
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Variants of pairing state.
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePinCode[] = "bluetoothRemotePinCode";
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kRemotePasskey[] = "bluetoothRemotePasskey";
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Possible ui-states for device-blocks.
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kSearchingState[] = "searching";
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kUSBConnectedState[] = "connected";
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairedState[] = "paired";
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTPairingState[] = "pairing";
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Special state for notifications that don't switch ui-state, but add info.
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kBTUpdateState[] = "update";
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Names of possible arguments used for ui update.
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kPincodeArgName[] = "pincode";
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kDeviceNameArgName[] = "name";
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const char kLabelArgName[] = "keyboard-label";
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Standard length of pincode for pairing BT keyboards.
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const int kPincodeLength = 6;
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(device::BluetoothDevice::DeviceType device_type) {
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_MOUSE ||
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO ||
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_TABLET;
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsPointing(const device::InputServiceLinux::InputDeviceInfo& info) {
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return info.is_mouse || info.is_touchpad || info.is_touchscreen ||
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         info.is_tablet;
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DeviceIsKeyboard(device::BluetoothDevice::DeviceType device_type) {
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return device_type == device::BluetoothDevice::DEVICE_KEYBOARD ||
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         device_type == device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace chromeos {
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)HIDDetectionScreenHandler::HIDDetectionScreenHandler(
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CoreOobeActor* core_oobe_actor)
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : BaseScreenHandler(kJsScreenPath),
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      delegate_(NULL),
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      core_oobe_actor_(core_oobe_actor),
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      show_on_init_(false),
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      mouse_is_pairing_(false),
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      pointing_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN),
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_is_pairing_(false),
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      keyboard_device_connect_type_(InputDeviceInfo::TYPE_UNKNOWN),
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_(false),
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_ptr_factory_(this) {
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
82a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochHIDDetectionScreenHandler::~HIDDetectionScreenHandler() {
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  adapter_initially_powered_.reset();
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnActorDestroyed(this);
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnStartDiscoverySession(
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT Discovery session started";
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  discovery_session_ = discovery_session.Pass();
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SetPoweredError() {
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(ERROR) << "Failed to power BT adapter";
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void HIDDetectionScreenHandler::SetPoweredOffError() {
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  LOG(ERROR) << "Failed to power off BT adapter";
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::FindDevicesError() {
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Failed to start Bluetooth discovery.";
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Show() {
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready()) {
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = true;
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  core_oobe_actor_->InitDemoModeDetection();
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.AddObserver(this);
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateDevices();
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PrefService* local_state = g_browser_process->local_state();
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int num_of_times_dialog_was_shown = local_state->GetInteger(
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      prefs::kTimesHIDDialogShown);
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  local_state->SetInteger(prefs::kTimesHIDDialogShown,
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          num_of_times_dialog_was_shown + 1);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ShowScreen(OobeUI::kScreenHIDDetection, NULL);
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pointing_device_id_.empty())
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SendPointingDeviceNotification();
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!keyboard_device_id_.empty())
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Hide() {
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (adapter_.get())
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->RemoveObserver(this);
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.RemoveObserver(this);
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) {
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  delegate_ = delegate;
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (page_is_ready())
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Initialize();
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void HIDDetectionScreenHandler::CheckIsScreenRequired(
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(bool)>& on_check_done) {
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  input_service_proxy_.GetDevices(
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesListForCheck,
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 on_check_done));
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::DeclareLocalizedValues(
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    LocalizedValuesBuilder* builder) {
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  builder->Add("hidDetectionContinue", IDS_HID_DETECTION_CONTINUE_BUTTON);
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionInvitation", IDS_HID_DETECTION_INVITATION_TEXT);
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionPrerequisites",
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PRECONDITION_TEXT);
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionMouseSearching", IDS_HID_DETECTION_SEARCHING_MOUSE);
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionKeyboardSearching",
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_SEARCHING_KEYBOARD);
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBMouseConnected",
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_MOUSE);
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionUSBKeyboardConnected",
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD);
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTMousePaired",
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE);
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY);
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::Initialize() {
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!page_is_ready() || !delegate_)
172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothAdapterFactory::GetAdapter(
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::InitializeAdapter,
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (show_on_init_) {
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    Show();
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    show_on_init_ = false;
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::RegisterMessages() {
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AddCallback(
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      "HIDDetectionOnContinue", &HIDDetectionScreenHandler::HandleOnContinue);
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid HIDDetectionScreenHandler::HandleOnContinue() {
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Continue button pressed.
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ContinueScenarioType scenario_type;
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pointing_device_id_.empty() && !keyboard_device_id_.empty())
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = All_DEVICES_DETECTED;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (pointing_device_id_.empty())
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = KEYBOARD_DEVICE_ONLY_DETECTED;
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scenario_type = POINTING_DEVICE_ONLY_DETECTED;
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      "HIDDetection.OOBEDevicesDetectedOnContinuePressed",
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scenario_type,
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CONTINUE_SCENARIO_TYPE_SIZE);
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Switch off BT adapter if it was off before the screen and no BT device
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // connected.
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered() &&
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      !(pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH ||
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) &&
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      adapter_initially_powered_ && !(*adapter_initially_powered_)) {
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "Switching off BT adapter after HID OOBE screen as unused.";
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    adapter_->SetPowered(
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        false,
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Bind(&base::DoNothing),
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::SetPoweredOffError,
2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  core_oobe_actor_->StopDemoModeDetection();
219a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (delegate_)
220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    delegate_->OnExit();
221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::InitializeAdapter(
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<device::BluetoothAdapter> adapter) {
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_ = adapter;
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CHECK(adapter_.get());
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->AddObserver(this);
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateDevices();
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
232010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::StartBTDiscoverySession() {
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  adapter_->StartDiscoverySession(
234010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnStartDiscoverySession,
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()),
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::FindDevicesError,
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPinCode(
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPinCode id = " << device->GetDeviceID()
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::RequestPasskey(
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "RequestPassKey id = " << device->GetDeviceID()
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPinCode(device::BluetoothDevice* device,
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                               const std::string& pincode) {
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPinCode id = " << device->GetDeviceID()
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePinCode);
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DisplayPasskey(
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "DisplayPassKey id = " << device->GetDeviceID()
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          << " name = " << device->GetName();
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTPairingState);
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pairing-state", kRemotePasskey);
273010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("passkey", passkey);
274010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string pincode = base::UintToString(passkey);
275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pincode = std::string(kPincodeLength - pincode.length(), '0').append(pincode);
276010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("pincode", pincode);
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString(kDeviceNameArgName, device->GetName());
278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::KeysEntered(
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 entered) {
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Keys entered";
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue params;
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetString("state", kBTUpdateState);
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  params.SetInteger("keysEntered", entered);
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendKeyboardDeviceNotification(&params);
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConfirmPasskey(
291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device, uint32 passkey) {
292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Confirm Passkey";
293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->CancelPairing();
294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AuthorizePairing(
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // There is never any circumstance where this will be called, since the
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // HID detection screen  handler will only be used for outgoing pairing
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // requests, but play it safe.
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Authorize pairing";
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->ConfirmPairing();
303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::AdapterPresentChanged(
306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, bool present) {
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (present && switch_on_adapter_when_ready_) {
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "Switching on BT adapter on HID OOBE screen.";
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    adapter_initially_powered_.reset(new bool(adapter_->IsPowered()));
310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    adapter_->SetPowered(
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        true,
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsPointingDevice(
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() &&
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsPointing(device->GetDeviceType()) &&
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !mouse_is_pairing_) {
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::TryPairingAsKeyboardDevice(
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() &&
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DeviceIsKeyboard(device->GetDeviceType()) &&
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->IsPairable() && !device->IsPaired() && !keyboard_is_pairing_) {
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ConnectBTDevice(device);
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceAdded(
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT input device added id = " << device->GetDeviceID() <<
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      " name = " << device->GetName();
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceChanged(
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device changed id = " << device->GetDeviceID() << " name = " <<
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsPointingDevice(device);
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  TryPairingAsKeyboardDevice(device);
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::DeviceRemoved(
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothAdapter* adapter, device::BluetoothDevice* device) {
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "BT device removed id = " << device->GetDeviceID() << " name = " <<
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device->GetName();
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceAdded(
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const InputDeviceInfo& info) {
361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  VLOG(1) << "Input device added id = " << info.id << " name = " << info.name;
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(merkulova): deal with all available device types, e.g. joystick.
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!keyboard_device_id_.empty() && !pointing_device_id_.empty())
364010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
365010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() && DeviceIsPointing(info)) {
367010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_ = info.id;
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_ = info.name;
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = info.type;
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
371010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
372010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty() && info.is_keyboard) {
373010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_ = info.id;
374010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_ = info.name;
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = info.type;
376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::OnInputDeviceRemoved(const std::string& id) {
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (id == keyboard_device_id_) {
382010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_id_.clear();
383010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_name_.clear();
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
385010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
386010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (id == pointing_device_id_) {
388010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_id_.clear();
389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_name_.clear();
390010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    pointing_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN;
391010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendPointingDeviceNotification();
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  registry->RegisterIntegerPref(prefs::kTimesHIDDialogShown, 0);
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
401010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateDevices() {
402010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_service_proxy_.GetDevices(
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesList,
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
405010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
406010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
407010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::UpdateBTDevices() {
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!adapter_.get() || !adapter_->IsPresent() || !adapter_->IsPowered())
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // If no connected devices found as pointing device and keyboard, we try to
412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // connect some type-suitable active bluetooth device.
413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<device::BluetoothDevice*> bt_devices = adapter_->GetDevices();
414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<device::BluetoothDevice*>::const_iterator it =
415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           bt_devices.begin();
416010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != bt_devices.end() &&
417010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           (keyboard_device_id_.empty() || pointing_device_id_.empty());
418010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsPointingDevice(*it);
420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    TryPairingAsKeyboardDevice(*it);
421010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::ProcessConnectedDevicesList(
425010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
426010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<InputDeviceInfo>::const_iterator it = devices.begin();
427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       it != devices.end() &&
428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       (pointing_device_id_.empty() || keyboard_device_id_.empty());
429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++it) {
430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (pointing_device_id_.empty() && DeviceIsPointing(*it)) {
431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_id_ = it->id;
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_name_ = it->name;
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pointing_device_connect_type_ = it->type;
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (page_is_ready())
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SendPointingDeviceNotification();
436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_device_id_.empty() && it->is_keyboard) {
438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_id_ = it->id;
439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_name_ = it->name;
440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      keyboard_device_connect_type_ = it->type;
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (page_is_ready())
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SendKeyboardDeviceNotification(NULL);
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::TryInitiateBTDevicesUpdate() {
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((pointing_device_id_.empty() || keyboard_device_id_.empty()) &&
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      adapter_.get()) {
450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!adapter_->IsPresent()) {
451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // Switch on BT adapter later when it's available.
452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      switch_on_adapter_when_ready_ = true;
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (!adapter_->IsPowered()) {
4546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      VLOG(1) << "Switching on BT adapter on HID OOBE screen.";
4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      adapter_initially_powered_.reset(new bool(false));
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      adapter_->SetPowered(
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          true,
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession,
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()),
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          base::Bind(&HIDDetectionScreenHandler::SetPoweredError,
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      UpdateBTDevices();
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void HIDDetectionScreenHandler::OnGetInputDevicesListForCheck(
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(bool)>& on_check_done,
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProcessConnectedDevicesList(devices);
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Screen is not required if both devices are present.
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool all_devices_autodetected = !pointing_device_id_.empty() &&
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  !keyboard_device_id_.empty();
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_BOOLEAN("HIDDetection.OOBEDialogShown",
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        !all_devices_autodetected);
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  on_check_done.Run(!all_devices_autodetected);
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void HIDDetectionScreenHandler::OnGetInputDevicesList(
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<InputDeviceInfo>& devices) {
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProcessConnectedDevicesList(devices);
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TryInitiateBTDevicesUpdate();
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::ConnectBTDevice(
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice* device) {
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!device->IsPairable() || device->IsPaired())
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device::BluetoothDevice::DeviceType device_type = device->GetDeviceType();
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
494010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (device_type == device::BluetoothDevice::DEVICE_MOUSE ||
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device_type == device::BluetoothDevice::DEVICE_TABLET) {
496010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_)
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
498010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) {
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (keyboard_is_pairing_)
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (device_type ==
504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) {
505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (mouse_is_pairing_ || keyboard_is_pairing_)
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
507010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = true;
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = true;
509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  device->Connect(this,
511010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnected,
512010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(), device_type),
513010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::Bind(&HIDDetectionScreenHandler::BTConnectError,
514010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       device->GetAddress(), device_type));
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
518010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnected(
519010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type) {
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsKeyboard(device_type))
523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
525010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
526010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::BTConnectError(
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& address,
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::DeviceType device_type,
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device::BluetoothDevice::ConnectErrorCode error_code) {
530010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  LOG(WARNING) << "BTConnectError while connecting " << address
531010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               << " error code = " << error_code;
532010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (DeviceIsPointing(device_type))
533010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    mouse_is_pairing_ = false;
534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (DeviceIsKeyboard(device_type)) {
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    keyboard_is_pairing_ = false;
536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SendKeyboardDeviceNotification(NULL);
537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
539010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty() || keyboard_device_id_.empty())
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UpdateDevices();
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
542010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
543010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
544010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendPointingDeviceNotification() {
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string state;
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pointing_device_id_.empty())
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kSearchingState;
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else if (pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH)
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kBTPairedState;
550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else
551010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state = kUSBConnectedState;
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setPointingDeviceState", state);
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void HIDDetectionScreenHandler::SendKeyboardDeviceNotification(
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::DictionaryValue* params) {
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::DictionaryValue state_info;
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (params)
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.MergeDictionary(params);
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::string16 device_name;
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!state_info.GetString(kDeviceNameArgName, &device_name)) {
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device_name = l10n_util::GetStringUTF16(
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        IDS_HID_DETECTION_DEFAULT_KEYBOARD_NAME);
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
566010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (keyboard_device_id_.empty()) {
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!state_info.HasKey("state")) {
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString("state", kSearchingState);
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (state_info.HasKey(kPincodeArgName)) {
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      state_info.SetString(
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          kLabelArgName,
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          l10n_util::GetStringFUTF16(
574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              IDS_HID_DETECTION_BLUETOOTH_REMOTE_PIN_CODE_REQUEST,
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)              device_name));
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
577010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) {
578010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kBTPairedState);
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString(
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        kLabelArgName,
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        l10n_util::GetStringFUTF16(
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD,
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            base::UTF8ToUTF16(keyboard_device_name_)));
584010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
585010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    state_info.SetString("state", kUSBConnectedState);
586010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CallJS("setKeyboardDeviceState", state_info);
588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
590a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}  // namespace chromeos
591