blob: 5317c05edd841a4656ac9d5a62ac1a8727525bec [file] [log] [blame]
// Copyright 2014 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/command_line.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/input_method/input_method_persistence.h"
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/browser/chromeos/login/test/login_screen_tester.h"
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
#include "chrome/common/pref_names.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_utils.h"
namespace chromeos {
namespace {
constexpr char kTestUser1[] = "test-user1@gmail.com";
constexpr char kTestUser1GaiaId[] = "1111111111";
constexpr char kTestUser2[] = "test-user2@gmail.com";
constexpr char kTestUser2GaiaId[] = "2222222222";
constexpr char kTestUser3[] = "test-user3@gmail.com";
constexpr char kTestUser3GaiaId[] = "3333333333";
void Append_en_US_InputMethods(std::vector<std::string>* out) {
out->push_back("xkb:us::eng");
out->push_back("xkb:us:intl:eng");
out->push_back("xkb:us:altgr-intl:eng");
out->push_back("xkb:us:dvorak:eng");
out->push_back("xkb:us:dvp:eng");
out->push_back("xkb:us:colemak:eng");
out->push_back("xkb:us:workman:eng");
out->push_back("xkb:us:workman-intl:eng");
chromeos::input_method::InputMethodManager::Get()->MigrateInputMethods(out);
}
class FocusPODWaiter {
public:
FocusPODWaiter() : focused_(false), runner_(new content::MessageLoopRunner) {
GetOobeUI()->signin_screen_handler()->SetFocusPODCallbackForTesting(
base::Bind(&FocusPODWaiter::OnFocusPOD, base::Unretained(this)));
}
~FocusPODWaiter() {
GetOobeUI()->signin_screen_handler()->SetFocusPODCallbackForTesting(
base::Closure());
}
void OnFocusPOD() {
ASSERT_TRUE(base::MessageLoopCurrentForUI::IsSet());
focused_ = true;
if (runner_.get()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&FocusPODWaiter::ExitMessageLoop,
base::Unretained(this)));
}
}
void ExitMessageLoop() { runner_->Quit(); }
void Wait() {
if (focused_)
return;
runner_->Run();
GetOobeUI()->signin_screen_handler()->SetFocusPODCallbackForTesting(
base::Closure());
runner_ = NULL;
}
private:
OobeUI* GetOobeUI() {
OobeUI* oobe_ui = LoginDisplayHost::default_host()->GetOobeUI();
CHECK(oobe_ui);
return oobe_ui;
}
bool focused_;
scoped_refptr<content::MessageLoopRunner> runner_;
};
} // anonymous namespace
class LoginUIKeyboardTest : public chromeos::LoginManagerTest {
public:
LoginUIKeyboardTest()
: LoginManagerTest(false, true /* should_initialize_webui */) {}
~LoginUIKeyboardTest() override {}
void SetUpOnMainThread() override {
user_input_methods.push_back("xkb:fr::fra");
user_input_methods.push_back("xkb:de::ger");
chromeos::input_method::InputMethodManager::Get()->MigrateInputMethods(
&user_input_methods);
LoginManagerTest::SetUpOnMainThread();
}
// Should be called from PRE_ test so that local_state is saved to disk, and
// reloaded in the main test.
void InitUserLastInputMethod() {
PrefService* local_state = g_browser_process->local_state();
input_method::SetUserLastInputMethodPreferenceForTesting(
kTestUser1, user_input_methods[0], local_state);
input_method::SetUserLastInputMethodPreferenceForTesting(
kTestUser2, user_input_methods[1], local_state);
}
protected:
std::vector<std::string> user_input_methods;
};
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTest, PRE_CheckPODScreenDefault) {
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser1, kTestUser1GaiaId));
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser2, kTestUser2GaiaId));
StartupUtils::MarkOobeCompleted();
}
// Check default IME initialization, when there is no IME configuration in
// local_state.
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTest, CheckPODScreenDefault) {
test::OobeJS().ExpectEQ("$('pod-row').pods.length", 2);
std::vector<std::string> expected_input_methods;
Append_en_US_InputMethods(&expected_input_methods);
EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetActiveInputMethodIds());
}
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTest, PRE_CheckPODScreenWithUsers) {
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser1, kTestUser1GaiaId));
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser2, kTestUser2GaiaId));
InitUserLastInputMethod();
StartupUtils::MarkOobeCompleted();
}
// TODO(crbug.com/602951): Test is flaky.
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTest, DISABLED_CheckPODScreenWithUsers) {
test::OobeJS().ExpectEQ("$('pod-row').pods.length", 2);
EXPECT_EQ(user_input_methods[0], input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetCurrentInputMethod()
.id());
std::vector<std::string> expected_input_methods;
Append_en_US_InputMethods(&expected_input_methods);
// Active IM for the first user (active user POD).
expected_input_methods.push_back(user_input_methods[0]);
EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetActiveInputMethodIds());
FocusPODWaiter waiter;
test::OobeJS().Evaluate("$('pod-row').focusPod($('pod-row').pods[1])");
waiter.Wait();
EXPECT_EQ(user_input_methods[1], input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetCurrentInputMethod()
.id());
}
class LoginUIKeyboardTestWithUsersAndOwner : public chromeos::LoginManagerTest {
public:
LoginUIKeyboardTestWithUsersAndOwner()
: LoginManagerTest(false, true /* should_initialize_webui */) {}
~LoginUIKeyboardTestWithUsersAndOwner() override {}
void SetUpOnMainThread() override {
user_input_methods.push_back("xkb:fr::fra");
user_input_methods.push_back("xkb:de::ger");
user_input_methods.push_back("xkb:pl::pol");
chromeos::input_method::InputMethodManager::Get()->MigrateInputMethods(
&user_input_methods);
scoped_testing_cros_settings_.device_settings()->Set(
kDeviceOwner, base::Value(kTestUser3));
LoginManagerTest::SetUpOnMainThread();
}
// Should be called from PRE_ test so that local_state is saved to disk, and
// reloaded in the main test.
void InitUserLastInputMethod() {
PrefService* local_state = g_browser_process->local_state();
input_method::SetUserLastInputMethodPreferenceForTesting(
kTestUser1, user_input_methods[0], local_state);
input_method::SetUserLastInputMethodPreferenceForTesting(
kTestUser2, user_input_methods[1], local_state);
input_method::SetUserLastInputMethodPreferenceForTesting(
kTestUser3, user_input_methods[2], local_state);
local_state->SetString(language_prefs::kPreferredKeyboardLayout,
user_input_methods[2]);
}
void CheckGaiaKeyboard();
protected:
std::vector<std::string> user_input_methods;
ScopedTestingCrosSettings scoped_testing_cros_settings_;
};
void LoginUIKeyboardTestWithUsersAndOwner::CheckGaiaKeyboard() {
std::vector<std::string> expected_input_methods;
// kPreferredKeyboardLayout is now set to last focused POD.
expected_input_methods.push_back(user_input_methods[0]);
// Locale default input methods (the first one also is hardware IM).
Append_en_US_InputMethods(&expected_input_methods);
EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetActiveInputMethodIds());
}
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTestWithUsersAndOwner,
PRE_CheckPODScreenKeyboard) {
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser1, kTestUser1GaiaId));
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser2, kTestUser2GaiaId));
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser3, kTestUser3GaiaId));
InitUserLastInputMethod();
StartupUtils::MarkOobeCompleted();
}
IN_PROC_BROWSER_TEST_F(LoginUIKeyboardTestWithUsersAndOwner,
CheckPODScreenKeyboard) {
test::OobeJS().ExpectEQ("$('pod-row').pods.length", 3);
std::vector<std::string> expected_input_methods;
// Owner input method.
expected_input_methods.push_back(user_input_methods[2]);
// Locale default input methods (the first one also is hardware IM).
Append_en_US_InputMethods(&expected_input_methods);
// Active IM for the first user (active user POD).
expected_input_methods.push_back(user_input_methods[0]);
EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetActiveInputMethodIds());
// Switch to Gaia.
ASSERT_TRUE(test::LoginScreenTester().ClickAddUserButton());
OobeScreenWaiter(OobeScreen::SCREEN_GAIA_SIGNIN).Wait();
CheckGaiaKeyboard();
// Switch back.
test::OobeJS().Evaluate("$('gaia-signin').cancel()");
OobeScreenWaiter(OobeScreen::SCREEN_ACCOUNT_PICKER).Wait();
EXPECT_EQ(expected_input_methods, input_method::InputMethodManager::Get()
->GetActiveIMEState()
->GetActiveInputMethodIds());
}
} // namespace chromeos