blob: 2d7037f59aee510203c090301c39b8ce62a08dd3 [file] [log] [blame]
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/system/sys_info.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/screens/base_screen.h"
#include "chrome/browser/chromeos/login/screens/hid_detection_screen.h"
#include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/browser/chromeos/login/test/oobe_base_test.h"
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/constants/chromeos_switches.h"
#include "content/public/test/browser_test.h"
#include "services/device/public/cpp/hid/fake_input_service_linux.h"
#include "services/device/public/mojom/input_service.mojom.h"
namespace chromeos {
class HIDDetectionScreenTest : public InProcessBrowserTest {
public:
enum class DeviceType { kKeyboard, kMouse };
HIDDetectionScreenTest() {
// HID detection screen only appears for Chromebases, Chromebits, and
// Chromeboxes.
base::SysInfo::SetChromeOSVersionInfoForTest("DEVICETYPE=CHROMEBOX",
base::Time::Now());
fake_input_service_manager_ =
std::make_unique<device::FakeInputServiceLinux>();
HIDDetectionScreen::OverrideInputDeviceManagerBinderForTesting(
base::Bind(&device::FakeInputServiceLinux::Bind,
base::Unretained(fake_input_service_manager_.get())));
}
~HIDDetectionScreenTest() override {
HIDDetectionScreen::OverrideInputDeviceManagerBinderForTesting(
base::NullCallback());
}
// InProcessBrowserTest:
void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpCommandLine(command_line);
command_line->AppendArg(switches::kLoginManager);
}
void SetUpOnMainThread() override {
ShowLoginWizard(HIDDetectionView::kScreenId);
ASSERT_TRUE(WizardController::default_controller());
hid_detection_screen_ = static_cast<HIDDetectionScreen*>(
WizardController::default_controller()->GetScreen(
HIDDetectionView::kScreenId));
ASSERT_TRUE(hid_detection_screen_);
ASSERT_EQ(WizardController::default_controller()->current_screen(),
hid_detection_screen_);
ASSERT_TRUE(hid_detection_screen_->view_);
hid_detection_screen()->SetAdapterInitialPoweredForTesting(false);
}
HIDDetectionScreen* hid_detection_screen() { return hid_detection_screen_; }
HIDDetectionScreenHandler* handler() {
return static_cast<HIDDetectionScreenHandler*>(
hid_detection_screen()->view_);
}
scoped_refptr<device::BluetoothAdapter> adapter() {
return hid_detection_screen_->GetAdapterForTesting();
}
void AddDeviceToService(DeviceType dev_type,
device::mojom::InputDeviceType type) {
const bool is_mouse = dev_type == DeviceType::kMouse;
auto device = device::mojom::InputDeviceInfo::New();
device->id = is_mouse ? "mouse" : "keyboard";
device->subsystem = device::mojom::InputDeviceSubsystem::SUBSYSTEM_INPUT;
device->type = type;
device->is_mouse = is_mouse;
device->is_keyboard = !is_mouse;
fake_input_service_manager_->AddDevice(std::move(device));
base::RunLoop().RunUntilIdle();
}
void RemoveDeviceFromService(DeviceType dev_type) {
const bool is_mouse = dev_type == DeviceType::kMouse;
std::string id = is_mouse ? "mouse" : "keyboard";
fake_input_service_manager_->RemoveDevice(std::move(id));
base::RunLoop().RunUntilIdle();
}
void ContinueToWelcomeScreen() {
// Simulate the user's click on "Continue" button.
test::OobeJS()
.CreateVisibilityWaiter(true, {"hid-detection", "hid-continue-button"})
->Wait();
test::OobeJS().TapOnPath({"hid-detection", "hid-continue-button"});
OobeScreenWaiter(WelcomeView::kScreenId).Wait();
}
private:
HIDDetectionScreen* hid_detection_screen_;
std::unique_ptr<device::FakeInputServiceLinux> fake_input_service_manager_;
DISALLOW_COPY_AND_ASSIGN(HIDDetectionScreenTest);
};
class HIDDetectionScreenChromebookTest : public OobeBaseTest {
public:
HIDDetectionScreenChromebookTest() {
// Set device type to one that should not invoke HIDDetectionScreen logic.
base::SysInfo::SetChromeOSVersionInfoForTest("DEVICETYPE=CHROMEBOOK",
base::Time::Now());
}
};
IN_PROC_BROWSER_TEST_F(HIDDetectionScreenChromebookTest,
HIDDetectionScreenNotAllowed) {
OobeScreenWaiter(WelcomeView::kScreenId).Wait();
ASSERT_TRUE(WizardController::default_controller());
EXPECT_FALSE(WizardController::default_controller()->HasScreen(
HIDDetectionView::kScreenId));
}
IN_PROC_BROWSER_TEST_F(HIDDetectionScreenTest, MouseKeyboardStates) {
// NOTE: State strings match those in hid_detection_screen.cc.
// No devices added yet
EXPECT_EQ("searching", handler()->mouse_state_for_test());
EXPECT_EQ("searching", handler()->keyboard_state_for_test());
EXPECT_FALSE(handler()->continue_button_enabled_for_test());
// Generic connection types. Unlike the pointing device, which may be a tablet
// or touchscreen, the keyboard only reports usb and bluetooth states.
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_SERIO);
EXPECT_TRUE(handler()->continue_button_enabled_for_test());
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_SERIO);
EXPECT_EQ("connected", handler()->mouse_state_for_test());
EXPECT_EQ("usb", handler()->keyboard_state_for_test());
EXPECT_TRUE(handler()->continue_button_enabled_for_test());
// Remove generic devices, add usb devices.
RemoveDeviceFromService(DeviceType::kMouse);
RemoveDeviceFromService(DeviceType::kKeyboard);
EXPECT_FALSE(handler()->continue_button_enabled_for_test());
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_USB);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_USB);
EXPECT_EQ("usb", handler()->mouse_state_for_test());
EXPECT_EQ("usb", handler()->keyboard_state_for_test());
EXPECT_TRUE(handler()->continue_button_enabled_for_test());
// Remove usb devices, add bluetooth devices.
RemoveDeviceFromService(DeviceType::kMouse);
RemoveDeviceFromService(DeviceType::kKeyboard);
EXPECT_FALSE(handler()->continue_button_enabled_for_test());
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_BLUETOOTH);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_BLUETOOTH);
EXPECT_EQ("paired", handler()->mouse_state_for_test());
EXPECT_EQ("paired", handler()->keyboard_state_for_test());
EXPECT_TRUE(handler()->continue_button_enabled_for_test());
}
// Test that if there is any Bluetooth device connected on HID screen, the
// Bluetooth adapter should not be disabled after advancing to the next screen.
IN_PROC_BROWSER_TEST_F(HIDDetectionScreenTest, BluetoothDeviceConnected) {
OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
EXPECT_TRUE(adapter()->IsPowered());
// Add a pair of USB mouse/keyboard so that |pointing_device_type_|
// and |keyboard_type_| are
// device::mojom::InputDeviceType::TYPE_USB.
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_USB);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_USB);
// Add another pair of Bluetooth mouse/keyboard.
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_BLUETOOTH);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_BLUETOOTH);
ContinueToWelcomeScreen();
// The adapter should not be powered off at this moment.
EXPECT_TRUE(adapter()->IsPowered());
}
// Test that if there is no Bluetooth device connected on HID screen, the
// Bluetooth adapter should be disabled after advancing to the next screen.
IN_PROC_BROWSER_TEST_F(HIDDetectionScreenTest, NoBluetoothDeviceConnected) {
OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
EXPECT_TRUE(adapter()->IsPowered());
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_USB);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_USB);
ContinueToWelcomeScreen();
// The adapter should be powered off at this moment.
EXPECT_FALSE(adapter()->IsPowered());
}
// Tests that the connected 'ticks' are shown when the devices are connected.
IN_PROC_BROWSER_TEST_F(HIDDetectionScreenTest, TestTicks) {
OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
test::OobeJS()
.CreateVisibilityWaiter(false, {"hid-detection", "mouse-tick"})
->Wait();
test::OobeJS()
.CreateVisibilityWaiter(false, {"hid-detection", "keyboard-tick"})
->Wait();
AddDeviceToService(DeviceType::kMouse,
device::mojom::InputDeviceType::TYPE_USB);
AddDeviceToService(DeviceType::kKeyboard,
device::mojom::InputDeviceType::TYPE_USB);
test::OobeJS()
.CreateVisibilityWaiter(true, {"hid-detection", "mouse-tick"})
->Wait();
test::OobeJS()
.CreateVisibilityWaiter(true, {"hid-detection", "keyboard-tick"})
->Wait();
ContinueToWelcomeScreen();
}
} // namespace chromeos