Index: chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc |
diff --git a/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc |
index a2a26b51c9d388b45c3dc5e02a6d186914254b25..57f694d7c7a502e1857bb41a5c63b9a7e2d674b4 100644 |
--- a/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc |
+++ b/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc |
@@ -4,16 +4,33 @@ |
#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" |
+#include "base/bind.h" |
#include "base/compiler_specific.h" |
#include "base/macros.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/utf_string_conversions.h" |
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" |
+#include "device/bluetooth/bluetooth_adapter_factory.h" |
#include "grit/chromium_strings.h" |
#include "grit/generated_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
namespace { |
const char kJsScreenPath[] = "login.HIDDetectionScreen"; |
+const char kRemotePinCode[] = "bluetoothRemotePinCode"; |
Nikita (slow)
2014/04/28 13:51:57
nit: Comment is missing. What are these constants
merkulova
2014/04/29 10:30:24
Done.
|
+const char kRemotePasskey[] = "bluetoothRemotePasskey"; |
+ |
+const char kSearchingState[] = "searching"; |
+const char kUSBConnectedState[] = "connected"; |
+const char kBTPairedState[] = "paired"; |
+const char kBTPairingState[] = "pairing"; |
+ |
+const char kPincodeArgName[] = "pincode"; |
+const char kDeviceNameArgName[] = "name"; |
+const char kLabelArgName[] = "keyboard-label"; |
+ |
} // namespace |
namespace chromeos { |
@@ -21,15 +38,38 @@ namespace chromeos { |
HIDDetectionScreenHandler::HIDDetectionScreenHandler() |
: BaseScreenHandler(kJsScreenPath), |
delegate_(NULL), |
- show_on_init_(false) { |
+ show_on_init_(false), |
+ mouse_is_pairing_(false), |
+ keyboard_is_pairing_(false), |
+ switch_on_adapter_when_ready_(false), |
+ weak_ptr_factory_(this) { |
Nikita (slow)
2014/04/28 13:51:57
pairing_device_passkey_
pairing_device_entered_
s
merkulova
2014/04/29 10:30:24
Removed as unused.
|
+ pointing_device_id_.clear(); |
Nikita (slow)
2014/04/28 13:51:57
nit: Remove strings 46..47. std::string is initial
merkulova
2014/04/29 10:30:24
Done.
|
+ keyboard_device_id_.clear(); |
} |
HIDDetectionScreenHandler::~HIDDetectionScreenHandler() { |
+ if (adapter_.get()) |
+ adapter_->RemoveObserver(this); |
+ input_service_proxy_.RemoveObserver(this); |
if (delegate_) |
delegate_->OnActorDestroyed(this); |
} |
-void HIDDetectionScreenHandler::PrepareToShow() { |
+void HIDDetectionScreenHandler::PrepareToShow() {} |
Nikita (slow)
2014/04/28 13:51:57
nit: Is this default clang formatting?
No particul
merkulova
2014/04/29 10:30:24
Done.
|
+ |
+void HIDDetectionScreenHandler::OnStartDiscoverySession( |
+ scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
+ VLOG(1) << "BT Discovery session started"; |
+ discovery_session_ = discovery_session.Pass(); |
+ UpdateDevices(false /* skip screen if devices present */); |
+} |
+ |
+void HIDDetectionScreenHandler::SetPoweredError() { |
+ LOG(ERROR) << "Failed to power BT adapter"; |
Nikita (slow)
2014/04/28 13:51:57
I wonder if we need a user facing error here for i
merkulova
2014/04/29 10:30:24
Done.
|
+} |
+ |
+void HIDDetectionScreenHandler::FindDevicesError() { |
+ VLOG(1) << "Failed to start Bluetooth discovery."; |
Nikita (slow)
2014/04/28 13:51:57
nit: Same question here.
merkulova
2014/04/29 10:30:24
Done.
|
} |
void HIDDetectionScreenHandler::Show() { |
@@ -37,10 +77,15 @@ void HIDDetectionScreenHandler::Show() { |
show_on_init_ = true; |
return; |
} |
+ input_service_proxy_.AddObserver(this); |
+ UpdateDevices(true /* skip screen if devices present */); |
ShowScreen(OobeUI::kScreenHIDDetection, NULL); |
} |
void HIDDetectionScreenHandler::Hide() { |
+ if (adapter_.get()) |
+ adapter_->RemoveObserver(this); |
+ input_service_proxy_.RemoveObserver(this); |
} |
void HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) { |
@@ -52,12 +97,29 @@ void HIDDetectionScreenHandler::SetDelegate(Delegate* delegate) { |
void HIDDetectionScreenHandler::DeclareLocalizedValues( |
LocalizedValuesBuilder* builder) { |
builder->Add("hidDetectionContinue", IDS_HID_DETECTION_CONTINUE_BUTTON); |
+ builder->Add("hidDetectionInvitation", IDS_HID_DETECTION_INVITATION_TEXT); |
+ builder->Add("hidDetectionPrerequisites", |
+ IDS_HID_DETECTION_PRECONDITION_TEXT); |
+ builder->Add("hidDetectionMouseSearching", IDS_HID_DETECTION_SEARCHING_MOUSE); |
+ builder->Add("hidDetectionKeyboardSearching", |
+ IDS_HID_DETECTION_SEARCHING_KEYBOARD); |
+ builder->Add("hidDetectionUSBMouseConnected", |
+ IDS_HID_DETECTION_CONNECTED_USB_MOUSE); |
+ builder->Add("hidDetectionUSBKeyboardConnected", |
+ IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD); |
+ builder->Add("hidDetectionBTMousePaired", |
+ IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE); |
+ builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY); |
} |
void HIDDetectionScreenHandler::Initialize() { |
if (!page_is_ready() || !delegate_) |
return; |
+ device::BluetoothAdapterFactory::GetAdapter( |
+ base::Bind(&HIDDetectionScreenHandler::InitializeAdapter, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ |
if (show_on_init_) { |
Show(); |
show_on_init_ = false; |
@@ -74,4 +136,351 @@ void HIDDetectionScreenHandler::HandleOnContinue() { |
delegate_->OnExit(); |
} |
+void HIDDetectionScreenHandler::InitializeAdapter( |
+ scoped_refptr<device::BluetoothAdapter> adapter) { |
+ adapter_ = adapter; |
+ CHECK(adapter_.get()); |
+ |
+ adapter_->AddObserver(this); |
+ UpdateDevices(false); |
+} |
+ |
+void HIDDetectionScreenHandler::StartBTDiscoverySession() { |
+ adapter_->StartDiscoverySession( |
+ base::Bind(&HIDDetectionScreenHandler::OnStartDiscoverySession, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&HIDDetectionScreenHandler::FindDevicesError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ |
+} |
+ |
+void HIDDetectionScreenHandler::RequestPinCode( |
+ device::BluetoothDevice* device) { |
+ VLOG(1) << "RequestPinCode id = " << device->GetDeviceID() |
+ << " name = " << device->GetName(); |
+ device->CancelPairing(); |
+} |
+ |
+void HIDDetectionScreenHandler::RequestPasskey( |
+ device::BluetoothDevice* device) { |
+ VLOG(1) << "RequestPassKey id = " << device->GetDeviceID() |
+ << " name = " << device->GetName(); |
+ device->CancelPairing(); |
+} |
+ |
+void HIDDetectionScreenHandler::DisplayPinCode(device::BluetoothDevice* device, |
+ const std::string& pincode) { |
+ VLOG(1) << "DisplayPinCode id = " << device->GetDeviceID() |
+ << " name = " << device->GetName(); |
+ base::DictionaryValue params; |
+ params.SetString("state", kBTPairingState); |
+ params.SetString("pairing-state", kRemotePinCode); |
+ params.SetString("pincode", pincode); |
+ params.SetString(kDeviceNameArgName, device->GetName()); |
+ SendKeyboardDeviceNotification(¶ms); |
+} |
+ |
+void HIDDetectionScreenHandler::DisplayPasskey( |
+ device::BluetoothDevice* device, uint32 passkey) { |
+ VLOG(1) << "DisplayPassKey id = " << device->GetDeviceID() |
+ << " name = " << device->GetName(); |
+ base::DictionaryValue params; |
+ params.SetString("state", kBTPairingState); |
+ params.SetString("pairing-state", kRemotePasskey); |
+ params.SetInteger("passkey", passkey); |
+ params.SetString("pincode", base::UintToString(passkey)); |
+ params.SetString(kDeviceNameArgName, device->GetName()); |
+ SendKeyboardDeviceNotification(¶ms); |
+} |
+ |
+void HIDDetectionScreenHandler::KeysEntered( |
+ device::BluetoothDevice* device, uint32 entered) { |
+ VLOG(1) << "Keys entered"; |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void HIDDetectionScreenHandler::ConfirmPasskey( |
+ device::BluetoothDevice* device, uint32 passkey) { |
+ VLOG(1) << "Confirm Passkey"; |
+ device->CancelPairing(); |
+} |
+ |
+void HIDDetectionScreenHandler::AuthorizePairing( |
+ device::BluetoothDevice* device) { |
+ // There is never any circumstance where this will be called, since the |
+ // HID detection screen handler will only be used for outgoing pairing |
+ // requests, but play it safe. |
+ VLOG(1) << "Authorize pairing"; |
+ device->ConfirmPairing(); |
+} |
+ |
+void HIDDetectionScreenHandler::AdapterPresentChanged( |
+ device::BluetoothAdapter* adapter, bool present) { |
+ if (present && switch_on_adapter_when_ready_) { |
+ adapter_->SetPowered( |
+ true, |
+ base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&HIDDetectionScreenHandler::SetPoweredError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::PairAsPointingDevice( |
+ device::BluetoothDevice* device) { |
+ if (pointing_device_id_.empty() && |
+ (device->GetDeviceType() == device::BluetoothDevice::DEVICE_MOUSE || |
+ device->GetDeviceType() == |
+ device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) && |
+ device->IsPairable() && !device->IsPaired() && !mouse_is_pairing_) { |
+ ConnectBTDevice(device); |
+ } /*else if (device->GetDeviceId() == pointing_device_id_ && )*/ |
+} |
+ |
+void HIDDetectionScreenHandler::PairAsKeyboardDevice( |
+ device::BluetoothDevice* device) { |
+ if (keyboard_device_id_.empty() && |
+ (device->GetDeviceType() == device::BluetoothDevice::DEVICE_KEYBOARD || |
+ device->GetDeviceType() == |
+ device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) && |
+ device->IsPairable() && !device->IsPaired() && !keyboard_is_pairing_) { |
+ ConnectBTDevice(device); |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::DeviceAdded( |
+ device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { |
+ VLOG(1) << "BT input device added id = " << device->GetDeviceID() << |
+ " name = " << device->GetName(); |
+ PairAsPointingDevice(device); |
+ PairAsKeyboardDevice(device); |
+} |
+ |
+void HIDDetectionScreenHandler::DeviceChanged( |
+ device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { |
+ VLOG(1) << "BT device changed id = " << device->GetDeviceID() << " name = " << |
+ device->GetName(); |
+ PairAsPointingDevice(device); |
+ PairAsKeyboardDevice(device); |
+} |
+ |
+void HIDDetectionScreenHandler::DeviceRemoved( |
+ device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { |
+ VLOG(1) << "BT device removed id = " << device->GetDeviceID() << " name = " << |
+ device->GetName(); |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void HIDDetectionScreenHandler::OnInputDeviceAdded( |
+ const InputDeviceInfo& info) { |
+ VLOG(1) << "Input device added id = " << info.id << " name = " << info.name; |
+ // TODO(merkulova): deal with all available device types. |
Nikita (slow)
2014/04/28 13:51:57
nit: mentions something in comments like joystick.
merkulova
2014/04/29 10:30:24
Done.
|
+ if (!keyboard_device_id_.empty() && !pointing_device_id_.empty()) |
+ return; |
+ |
+ if (pointing_device_id_.empty() && (info.is_mouse || info.is_touchpad)) { |
+ pointing_device_id_ = info.id; |
+ pointing_device_name_ = info.name; |
+ pointing_device_connect_type_ = info.type; |
+ SendPointingDeviceNotification(); |
+ } |
+ if (keyboard_device_id_.empty() && info.is_keyboard) { |
+ keyboard_device_id_ = info.id; |
+ keyboard_device_name_ = info.name; |
+ keyboard_device_connect_type_ = info.type; |
+ SendKeyboardDeviceNotification(NULL); |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::OnInputDeviceRemoved(const std::string& id) { |
+ if (id == keyboard_device_id_) { |
+ keyboard_device_id_.clear(); |
+ keyboard_device_name_.clear(); |
+ keyboard_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN; |
+ SendKeyboardDeviceNotification(NULL); |
+ UpdateDevices(false /* skip screen if devices present */); |
+ } else if (id == pointing_device_id_) { |
+ pointing_device_id_.clear(); |
+ pointing_device_name_.clear(); |
+ pointing_device_connect_type_ = InputDeviceInfo::TYPE_UNKNOWN; |
+ SendPointingDeviceNotification(); |
+ UpdateDevices(false /* skip screen if devices present */); |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::UpdateDevices( |
+ bool skip_screen_if_devices_present) { |
+ input_service_proxy_.GetDevices( |
+ base::Bind(&HIDDetectionScreenHandler::OnGetInputDevicesList, |
+ base::Unretained(this), |
+ skip_screen_if_devices_present)); |
+} |
+ |
+void HIDDetectionScreenHandler::UpdateBTDevices() { |
+ if (!adapter_ || !adapter_->IsPresent() || !adapter_->IsPowered()) |
+ return; |
+ // If no connected devices found as pointing device and keyboard, we try to |
+ // connect some type-suitable active bluetooth device. |
+ std::vector<device::BluetoothDevice*> bt_devices = adapter_->GetDevices(); |
+ for (std::vector<device::BluetoothDevice*>::const_iterator it = |
+ bt_devices.begin(); |
+ it != bt_devices.end() && |
+ (keyboard_device_id_.empty() || pointing_device_id_.empty()); |
+ ++it) { |
+ PairAsPointingDevice(*it); |
+ PairAsKeyboardDevice(*it); |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::OnGetInputDevicesList( |
+ bool skip_screen_if_devices_present, |
+ const std::vector<InputDeviceInfo>& devices) { |
+ for (std::vector<InputDeviceInfo>::const_iterator it = devices.begin(); |
+ it != devices.end() && |
+ (pointing_device_id_.empty() || keyboard_device_id_.empty()); |
+ ++it) { |
+ if (pointing_device_id_.empty() && (it->is_mouse || it->is_touchpad)) { |
+ pointing_device_id_ = it->id; |
+ pointing_device_name_ = it->name; |
+ pointing_device_connect_type_ = it->type; |
+ SendPointingDeviceNotification(); |
+ } |
+ if (keyboard_device_id_.empty() && it->is_keyboard) { |
+ keyboard_device_id_ = it->id; |
+ keyboard_device_name_ = it->name; |
+ keyboard_device_connect_type_ = it->type; |
+ SendKeyboardDeviceNotification(NULL); |
+ } |
+ } |
+ // Skip screen if both devices are present and skip was requested. |
+ if (!pointing_device_id_.empty() && |
+ !keyboard_device_id_.empty() && |
+ skip_screen_if_devices_present) { |
+ HandleOnContinue(); |
+ } |
+ if ((pointing_device_id_.empty() || keyboard_device_id_.empty()) && |
+ adapter_) { |
+ if (!adapter_->IsPresent()) { |
+ // Switch on BT adapter later when it's available. |
+ switch_on_adapter_when_ready_ = true; |
+ } else if (!adapter_->IsPowered()) { |
+ adapter_->SetPowered( |
+ true, |
+ base::Bind(&HIDDetectionScreenHandler::StartBTDiscoverySession, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ base::Bind(&HIDDetectionScreenHandler::SetPoweredError, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } else { |
+ UpdateBTDevices(); |
+ } |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::ConnectBTDevice( |
+ device::BluetoothDevice* device) { |
+ if (!device->IsPairable() || device->IsPaired()) |
+ return; |
+ device::BluetoothDevice::DeviceType device_type = device->GetDeviceType(); |
+ if (device_type == device::BluetoothDevice::DEVICE_MOUSE) { |
+ if (mouse_is_pairing_) |
+ return; |
+ mouse_is_pairing_ = true; |
+ } else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) { |
+ if (keyboard_is_pairing_) |
+ return; |
+ keyboard_is_pairing_ = true; |
+ } else if (device_type == |
+ device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) { |
+ if (mouse_is_pairing_ || keyboard_is_pairing_) |
+ return; |
+ mouse_is_pairing_ = true; |
+ keyboard_is_pairing_ = true; |
+ } |
+ device->Connect(this, |
+ base::Bind(&HIDDetectionScreenHandler::BTConnected, |
+ weak_ptr_factory_.GetWeakPtr(), device_type), |
+ base::Bind(&HIDDetectionScreenHandler::BTConnectError, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ device->GetAddress(), device_type)); |
+} |
+ |
+void HIDDetectionScreenHandler::BTConnected( |
+ device::BluetoothDevice::DeviceType device_type) { |
+ if (device_type == device::BluetoothDevice::DEVICE_MOUSE) |
+ mouse_is_pairing_ = false; |
+ else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) |
+ keyboard_is_pairing_ = false; |
+ else if (device_type == |
+ device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) { |
+ mouse_is_pairing_ = false; |
+ keyboard_is_pairing_ = false; |
+ } |
+} |
+ |
+void HIDDetectionScreenHandler::BTConnectError( |
+ const std::string& address, |
+ device::BluetoothDevice::DeviceType device_type, |
+ device::BluetoothDevice::ConnectErrorCode error_code) { |
+ LOG(WARNING) << "BTConnectError"; |
+ if (device_type == device::BluetoothDevice::DEVICE_MOUSE) |
+ mouse_is_pairing_ = false; |
+ else if (device_type == device::BluetoothDevice::DEVICE_KEYBOARD) |
+ keyboard_is_pairing_ = false; |
+ else if (device_type == |
+ device::BluetoothDevice::DEVICE_KEYBOARD_MOUSE_COMBO) { |
+ mouse_is_pairing_ = false; |
+ keyboard_is_pairing_ = false; |
+ } |
+ if (pointing_device_id_.empty() || keyboard_device_id_.empty()) |
+ UpdateDevices(false /* skip screen if devices present */); |
+} |
+ |
+ |
+void HIDDetectionScreenHandler::SendPointingDeviceNotification() { |
+ std::string state; |
+ if (pointing_device_id_.empty()) |
+ state = kSearchingState; |
+ else if (pointing_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) |
+ state = kBTPairedState; |
+ else |
+ state = kUSBConnectedState; |
+ CallJS("setPointingDeviceState", state); |
+} |
+ |
+void HIDDetectionScreenHandler::SendKeyboardDeviceNotification( |
+ base::DictionaryValue* params) { |
+ base::DictionaryValue state_info; |
+ if (params) |
+ state_info.MergeDictionary(params); |
+ |
+ std::string16 device_name; |
+ if (!state_info.GetString(kDeviceNameArgName, &device_name)) { |
+ device_name = l10n_util::GetStringUTF16( |
+ IDS_HID_DETECTION_DEFAULT_KEYBOARD_NAME); |
+ } |
+ |
+ if (keyboard_device_id_.empty()) { |
+ std::string pairing; |
+ if (!state_info.GetString("pairing-state", &pairing)) { |
+ state_info.SetString("state", kSearchingState); |
+ } else if (state_info.HasKey(kPincodeArgName)) { |
+ state_info.SetString( |
+ kLabelArgName, |
+ l10n_util::GetStringFUTF16( |
+ IDS_HID_DETECTION_BLUETOOTH_REMOTE_PIN_CODE_REQUEST, |
+ device_name)); |
+ } |
+ } else if (keyboard_device_connect_type_ == InputDeviceInfo::TYPE_BLUETOOTH) { |
+ state_info.SetString("state", kBTPairedState); |
+ state_info.SetString( |
+ kLabelArgName, |
+ l10n_util::GetStringFUTF16( |
+ IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD, |
+ base::ASCIIToUTF16(keyboard_device_name_))); |
+ } else { |
+ state_info.SetString("state", kUSBConnectedState); |
+ } |
+ CallJS("setKeyboardDeviceState", state_info); |
+} |
+ |
} // namespace chromeos |