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