[OOBE] - Enable non-login input methods in OOBE
Goal of this CL is to lift login-only input methods restriction in OOBE and enable typing in previously requested languages during pre-onboarding part of OOBE (specifically, Japanese and Arabic). CL implements the following steps: * Add OOBE-specific allowlist of input method ids as a mechanism to enable input methods in OOBE per request. At the beginning we add only Japanese and Arabic IMs there among non-XKB IMs. * Introduce new method `EnableOobeInputMethods` that will replace usages of the `EnableLoginLayouts` in all OOBE contexts. Main difference is usage of the `IsOobeAllowlisted` function to decide whether enable input method or not. * `IsOobeAllowlisted` enables only allowlisted input methods. * Logic of the `EnableLoginLayouts` remains the same to not change current language flows of login screen and kiosk. * Extend `oobe_localization_browsertest` to support new changes. Bug: b:260013276 Change-Id: I33397725fd37f3b417939e8618ac5796343dc5b8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6375683 Reviewed-by: Bao-Duy Tran <tranbaoduy@chromium.org> Commit-Queue: Bohdan Tyshchenko <bohdanty@google.com> Reviewed-by: Danila Kuzmin <dkuzmin@google.com> Cr-Commit-Position: refs/heads/main@{#1442615}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
2470a124f2
commit
e10682f3e9
chrome/browser
ash
input_method
login
ui
ui/base/ime/ash
@ -301,8 +301,61 @@ void InputMethodManagerImpl::StateImpl::EnableLoginLayouts(
|
||||
}
|
||||
}
|
||||
|
||||
manager_->GetMigratedInputMethodIDs(&layouts);
|
||||
enabled_input_method_ids_.swap(layouts);
|
||||
// Empty |initial_layouts| work too.
|
||||
FinalizeInputMethodsEnabling(layouts, initial_layouts);
|
||||
}
|
||||
|
||||
void InputMethodManagerImpl::StateImpl::EnableOobeInputMethods(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_input_methods) {
|
||||
if (IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First, hardware input methods should be shown.
|
||||
std::vector<std::string> candidates =
|
||||
manager_->util_.GetHardwareInputMethodIds();
|
||||
|
||||
// Second, locale based input method should be shown.
|
||||
// Add input methods associated with the language.
|
||||
std::vector<std::string> input_methods_from_locale;
|
||||
manager_->util_.GetInputMethodIdsFromLanguageCode(
|
||||
language_code, kAllInputMethods, &input_methods_from_locale);
|
||||
candidates.insert(candidates.end(), input_methods_from_locale.begin(),
|
||||
input_methods_from_locale.end());
|
||||
|
||||
std::vector<std::string> resulting_input_methods;
|
||||
// First, add the initial input method ID, if it's requested, to
|
||||
// resulting_input_methods, so it appears first on the list of enabled input
|
||||
// methods at the input language status menu.
|
||||
for (const auto& initial_input_method : initial_input_methods) {
|
||||
if (manager_->util_.IsValidInputMethodId(initial_input_method) &&
|
||||
manager_->util_.IsOobeAllowlisted(initial_input_method) &&
|
||||
IsInputMethodAllowed(initial_input_method)) {
|
||||
resulting_input_methods.push_back(initial_input_method);
|
||||
}
|
||||
}
|
||||
|
||||
// Add candidates to resulting_input_methods, while skipping duplicates.
|
||||
for (const auto& candidate : candidates) {
|
||||
// Not efficient, but should be fine, as the two vectors are very
|
||||
// short (2-5 items).
|
||||
if (!base::Contains(resulting_input_methods, candidate) &&
|
||||
manager_->util_.IsOobeAllowlisted(candidate) &&
|
||||
IsInputMethodAllowed(candidate)) {
|
||||
resulting_input_methods.push_back(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Empty |initial_input_methods| work too.
|
||||
FinalizeInputMethodsEnabling(resulting_input_methods, initial_input_methods);
|
||||
}
|
||||
|
||||
void InputMethodManagerImpl::StateImpl::FinalizeInputMethodsEnabling(
|
||||
std::vector<std::string>& input_methods_to_enable,
|
||||
const std::vector<std::string>& initial_input_methods) {
|
||||
manager_->GetMigratedInputMethodIDs(&input_methods_to_enable);
|
||||
enabled_input_method_ids_.swap(input_methods_to_enable);
|
||||
|
||||
if (IsActive()) {
|
||||
// Initialize candidate window controller and widgets such as
|
||||
@ -312,11 +365,10 @@ void InputMethodManagerImpl::StateImpl::EnableLoginLayouts(
|
||||
manager_->MaybeInitializeCandidateWindowController();
|
||||
}
|
||||
|
||||
// you can pass empty |initial_layout|.
|
||||
ChangeInputMethod(initial_layouts.empty()
|
||||
ChangeInputMethod(initial_input_methods.empty()
|
||||
? std::string()
|
||||
: extension_ime_util::GetInputMethodIDByEngineID(
|
||||
initial_layouts[0]),
|
||||
initial_input_methods[0]),
|
||||
false);
|
||||
}
|
||||
}
|
||||
@ -707,34 +759,34 @@ void InputMethodManagerImpl::StateImpl::SetEnabledExtensionImes(
|
||||
void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefaultFromVPD(
|
||||
const std::string& locale,
|
||||
const std::string& oem_layout) {
|
||||
std::string layout;
|
||||
std::string input_method_id;
|
||||
if (!oem_layout.empty()) {
|
||||
// If the OEM layout information is provided, use it.
|
||||
layout = oem_layout;
|
||||
input_method_id = oem_layout;
|
||||
} else {
|
||||
// Otherwise, determine the hardware keyboard from the locale.
|
||||
std::vector<std::string> input_method_ids;
|
||||
if (manager_->util_.GetInputMethodIdsFromLanguageCode(
|
||||
locale, kKeyboardLayoutsOnly, &input_method_ids)) {
|
||||
locale, kAllInputMethods, &input_method_ids)) {
|
||||
// The output list |input_method_ids| is sorted by popularity, hence
|
||||
// input_method_ids[0] now contains the most popular keyboard layout
|
||||
// for the given locale.
|
||||
DCHECK_GE(input_method_ids.size(), 1U);
|
||||
layout = input_method_ids[0];
|
||||
input_method_id = input_method_ids[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (layout.empty()) {
|
||||
if (input_method_id.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> layouts = base::SplitString(
|
||||
layout, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
||||
manager_->GetMigratedInputMethodIDs(&layouts);
|
||||
std::vector<std::string> input_method_ids = base::SplitString(
|
||||
input_method_id, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
||||
manager_->GetMigratedInputMethodIDs(&input_method_ids);
|
||||
|
||||
PrefService* prefs = g_browser_process->local_state();
|
||||
prefs->SetString(prefs::kHardwareKeyboardLayout,
|
||||
base::JoinString(layouts, ","));
|
||||
base::JoinString(input_method_ids, ","));
|
||||
|
||||
// This asks the file thread to save the prefs (i.e. doesn't block).
|
||||
// The latest values of Local State reside in memory so we can safely
|
||||
@ -744,11 +796,13 @@ void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefaultFromVPD(
|
||||
|
||||
manager_->util_.UpdateHardwareLayoutCache();
|
||||
|
||||
EnableLoginLayouts(locale, layouts);
|
||||
// This function is called only during system setup in OOBE.
|
||||
EnableOobeInputMethods(locale, input_method_ids);
|
||||
LoadNecessaryComponentExtensions();
|
||||
}
|
||||
|
||||
void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault() {
|
||||
void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault(
|
||||
bool is_in_oobe_context) {
|
||||
// Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
|
||||
// and US dvorak keyboard layouts.
|
||||
if (g_browser_process && g_browser_process->local_state()) {
|
||||
@ -771,7 +825,11 @@ void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault() {
|
||||
input_method_ids_to_be_enabled.push_back(initial_input_method_id);
|
||||
}
|
||||
}
|
||||
EnableLoginLayouts(locale, input_method_ids_to_be_enabled);
|
||||
if (is_in_oobe_context) {
|
||||
EnableOobeInputMethods(locale, input_method_ids_to_be_enabled);
|
||||
} else {
|
||||
EnableLoginLayouts(locale, input_method_ids_to_be_enabled);
|
||||
}
|
||||
LoadNecessaryComponentExtensions();
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,9 @@ class InputMethodManagerImpl : public InputMethodManager,
|
||||
void EnableLoginLayouts(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_layouts) override;
|
||||
void EnableOobeInputMethods(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_input_methods) override;
|
||||
void DisableNonLockScreenLayouts() override;
|
||||
void GetInputMethodExtensions(InputMethodDescriptors* result) override;
|
||||
InputMethodDescriptors GetEnabledInputMethodsSortedByLocalizedDisplayNames()
|
||||
@ -94,7 +97,7 @@ class InputMethodManagerImpl : public InputMethodManager,
|
||||
const std::string& input_method_id) const override;
|
||||
size_t GetNumEnabledInputMethods() const override;
|
||||
void SetEnabledExtensionImes(base::span<const std::string> ids) override;
|
||||
void SetInputMethodLoginDefault() override;
|
||||
void SetInputMethodLoginDefault(bool is_in_oobe_context) override;
|
||||
void SetInputMethodLoginDefaultFromVPD(const std::string& locale,
|
||||
const std::string& layout) override;
|
||||
void SwitchToNextInputMethod() override;
|
||||
@ -135,6 +138,14 @@ class InputMethodManagerImpl : public InputMethodManager,
|
||||
const InputMethodDescriptor* LookupInputMethod(
|
||||
const std::string& input_method_id);
|
||||
|
||||
// Replaces currently enabled input methnods ids list with the
|
||||
// |input_methods_to_enable|. Initializes candidate window controller and
|
||||
// activates first entry of |initial_input_methods| if caller's state is in
|
||||
// the active state and |initial_input_methods| is not empty.
|
||||
void FinalizeInputMethodsEnabling(
|
||||
std::vector<std::string>& input_methods_to_enable,
|
||||
const std::vector<std::string>& initial_input_methods);
|
||||
|
||||
const raw_ptr<Profile, DanglingUntriaged> profile_;
|
||||
|
||||
const raw_ptr<InputMethodManagerImpl, DanglingUntriaged> manager_;
|
||||
|
@ -1574,7 +1574,8 @@ TEST_F(InputMethodManagerImplTest, SetLoginDefaultWithAllowedInputMethods) {
|
||||
EXPECT_TRUE(manager_->GetActiveIMEState()->SetAllowedInputMethods(allowed));
|
||||
EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(
|
||||
manager_->GetActiveIMEState()->GetAllowedInputMethodIds()));
|
||||
manager_->GetActiveIMEState()->SetInputMethodLoginDefault();
|
||||
manager_->GetActiveIMEState()->SetInputMethodLoginDefault(
|
||||
/*is_in_oobe_context=*/false);
|
||||
EXPECT_THAT(manager_->GetActiveIMEState()->GetEnabledInputMethodIds(),
|
||||
testing::ElementsAre(ImeIdFromEngineId("xkb:us::eng"),
|
||||
ImeIdFromEngineId("xkb:de::ger"),
|
||||
|
@ -70,7 +70,7 @@ void SetUserInputMethod(const AccountId& account_id,
|
||||
DVLOG(0) << "SetUserInputMethod: failed to set user layout. Switching to "
|
||||
"default.";
|
||||
|
||||
ime_state->SetInputMethodLoginDefault();
|
||||
ime_state->SetInputMethodLoginDefault(false /* is_in_oobe_context */);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ void StopEnforcingPolicyInputMethods() {
|
||||
imm_state->SetAllowedInputMethods(std::vector<std::string>());
|
||||
if (ImeControllerClientImpl::Get()) // Can be null in tests.
|
||||
ImeControllerClientImpl::Get()->SetImesManagedByPolicy(false);
|
||||
imm_state->SetInputMethodLoginDefault();
|
||||
imm_state->SetInputMethodLoginDefault(false /* is_in_oobe_context */);
|
||||
}
|
||||
|
||||
void SetKeyboardSettings(const AccountId& account_id) {
|
||||
|
@ -102,13 +102,18 @@ struct LocalizationTestParams {
|
||||
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
|
||||
// ------------------ Non-Latin setup
|
||||
// For a non-Latin keyboard layout like Russian, we expect to see the US
|
||||
// keyboard.
|
||||
{"ru", "xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"},
|
||||
{"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"},
|
||||
// keyboard and XKB-IMs attached to a given locale.
|
||||
{"ru", "xkb:ru::rus", "ru", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
{"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
|
||||
// IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese
|
||||
// keyboard.
|
||||
{"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn", "xkb:jp::jpn,[xkb:us::eng]"},
|
||||
// Only allowlisted IMEs are available during OOBE, if given locale doesn't
|
||||
// have any allowlisted IMs attached we will see only Latin IM enabled.
|
||||
{"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn",
|
||||
"xkb:jp::jpn,[nacl_mozc_us,nacl_mozc_jp,xkb:us::eng]"},
|
||||
{"ar", "xkb:us::eng", "ar", "xkb:us::eng", "xkb:us::eng,[vkd_ar]"},
|
||||
{"ko", "xkb:us::eng", "ko", "xkb:us::eng", "xkb:us::eng"},
|
||||
|
||||
// We don't use the Icelandic locale but the Icelandic keyboard layout
|
||||
// should still be selected when specified as the default.
|
||||
@ -130,7 +135,8 @@ struct LocalizationTestParams {
|
||||
{"es,en-US,nl", "xkb:be::nld", "es,en-US,nl", "xkb:be::nld",
|
||||
"xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"},
|
||||
|
||||
{"ru,de", "xkb:ru::rus", "ru,de", kUSLayout, "xkb:us::eng"},
|
||||
{"ru,de", "xkb:ru::rus", "ru,de", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
|
||||
// ------------------ Regional Locales
|
||||
// Synthetic example to test correct merging of different locales.
|
||||
@ -146,13 +152,18 @@ struct LocalizationTestParams {
|
||||
#else
|
||||
// ------------------ Non-Latin setup
|
||||
// For a non-Latin keyboard layout like Russian, we expect to see the US
|
||||
// keyboard.
|
||||
{"ru", "xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"},
|
||||
{"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout, "xkb:us::eng"},
|
||||
// keyboard and XKB-IMs attached to a given locale.
|
||||
{"ru", "xkb:ru::rus", "ru", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
{"ru", "xkb:us::eng,xkb:ru::rus", "ru", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
|
||||
// IMEs do not load at OOBE, so we just expect to see the (Latin) Japanese
|
||||
// keyboard.
|
||||
{"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn", "xkb:jp::jpn,[xkb:us::eng]"},
|
||||
// Only allowlisted IMEs are available during OOBE, if given locale doesn't
|
||||
// have any allowlisted IMs attached we will see only Latin IM enabled.
|
||||
{"ja", "xkb:jp::jpn", "ja", "xkb:jp::jpn",
|
||||
"xkb:jp::jpn,[nacl_mozc_us,nacl_mozc_jp,xkb:us::eng]"},
|
||||
{"ar", "xkb:us::eng", "ar", "xkb:us::eng", "xkb:us::eng,[vkd_ar]"},
|
||||
{"ko", "xkb:us::eng", "ko", "xkb:us::eng", "xkb:us::eng"},
|
||||
|
||||
// We don't use the Icelandic locale but the Icelandic keyboard layout
|
||||
// should still be selected when specified as the default.
|
||||
@ -174,7 +185,8 @@ struct LocalizationTestParams {
|
||||
{"es,en-US,nl", "xkb:be::nld", "es,en-US,nl", "xkb:be::nld",
|
||||
"xkb:be::nld,[xkb:es::spa,xkb:latam::spa,xkb:us::eng]"},
|
||||
|
||||
{"ru,de", "xkb:ru::rus", "ru,de", kUSLayout, "xkb:us::eng"},
|
||||
{"ru,de", "xkb:ru::rus", "ru,de", kUSLayout,
|
||||
"xkb:us::eng,xkb:ru::rus,[xkb:ru:phonetic:rus]"},
|
||||
|
||||
// ------------------ Regional Locales
|
||||
// Synthetic example to test correct merging of different locales.
|
||||
@ -323,16 +335,24 @@ std::string OobeLocalizationTest::DumpOptions(const char* select_id) {
|
||||
return test::OobeJS().GetString(expression);
|
||||
}
|
||||
|
||||
std::string TranslateXKB2Extension(const std::string& src) {
|
||||
std::string TranslateLocal2Global(const std::string& src) {
|
||||
std::string result(src);
|
||||
// Modifies the expected keyboard select control options for the new
|
||||
// extension based xkb id.
|
||||
size_t pos = 0;
|
||||
std::string repl_old = "xkb:";
|
||||
std::string repl_new = extension_ime_util::GetInputMethodIDByEngineID("xkb:");
|
||||
while ((pos = result.find(repl_old, pos)) != std::string::npos) {
|
||||
result.replace(pos, repl_old.length(), repl_new);
|
||||
pos += repl_new.length();
|
||||
const std::vector<std::string> replacements = {
|
||||
"xkb:",
|
||||
"nacl_mozc_",
|
||||
"vkd_",
|
||||
};
|
||||
|
||||
for (const auto& replacement : replacements) {
|
||||
// Modifies the expected keyboard select control options for the new
|
||||
// extension based id.
|
||||
size_t pos = 0;
|
||||
std::string repl_new =
|
||||
extension_ime_util::GetInputMethodIDByEngineID(replacement);
|
||||
while ((pos = result.find(replacement, pos)) != std::string::npos) {
|
||||
result.replace(pos, replacement.length(), repl_new);
|
||||
pos += repl_new.length();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -346,7 +366,7 @@ void OobeLocalizationTest::RunLocalizationTest() {
|
||||
GetParam()->expected_keyboard_select_control);
|
||||
|
||||
const std::string expected_keyboard_select =
|
||||
TranslateXKB2Extension(expected_keyboard_select_control);
|
||||
TranslateLocal2Global(expected_keyboard_select_control);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(LanguageListWaiter().RunUntilLanguageListReady());
|
||||
|
||||
@ -361,7 +381,7 @@ void OobeLocalizationTest::RunLocalizationTest() {
|
||||
<< DumpOptions(kLanguageSelect);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(VerifyInitialOptions(
|
||||
kKeyboardSelect, TranslateXKB2Extension(expected_keyboard_layout).c_str(),
|
||||
kKeyboardSelect, TranslateLocal2Global(expected_keyboard_layout).c_str(),
|
||||
false))
|
||||
<< "Actual value of " << kKeyboardSelect << ":\n"
|
||||
<< DumpOptions(kKeyboardSelect);
|
||||
|
@ -244,9 +244,8 @@ void WelcomeScreen::SetApplicationLocaleAndInputMethod(
|
||||
base::BindOnce(&WelcomeScreen::OnLanguageChangedCallback,
|
||||
language_weak_ptr_factory_.GetWeakPtr(),
|
||||
base::Owned(new InputEventsBlocker), input_method));
|
||||
locale_util::SwitchLanguage(locale, true /* enableLocaleKeyboardLayouts */,
|
||||
true /* login_layouts_only */,
|
||||
std::move(callback),
|
||||
locale_util::SwitchLanguage(locale, /*enable_locale_keyboard_layouts=*/true,
|
||||
/*login_layouts_only=*/false, std::move(callback),
|
||||
ProfileManager::GetActiveUserProfile());
|
||||
}
|
||||
|
||||
@ -272,9 +271,8 @@ void WelcomeScreen::SetApplicationLocale(const std::string& locale,
|
||||
base::BindOnce(&WelcomeScreen::OnLanguageChangedCallback,
|
||||
language_weak_ptr_factory_.GetWeakPtr(),
|
||||
base::Owned(new InputEventsBlocker), std::string()));
|
||||
locale_util::SwitchLanguage(locale, true /* enableLocaleKeyboardLayouts */,
|
||||
true /* login_layouts_only */,
|
||||
std::move(callback),
|
||||
locale_util::SwitchLanguage(locale, /*enable_locale_keyboard_layouts=*/true,
|
||||
/*login_layouts_only=*/false, std::move(callback),
|
||||
ProfileManager::GetActiveUserProfile());
|
||||
if (is_from_ui) {
|
||||
// Write into the local state to save data about locale changes in case of
|
||||
|
@ -82,7 +82,7 @@ void StartKioskSession(KioskAppId app, bool is_auto_launch = false) {
|
||||
|
||||
CHECK_DEREF(input_method::InputMethodManager::Get())
|
||||
.GetActiveIMEState()
|
||||
->SetInputMethodLoginDefault();
|
||||
->SetInputMethodLoginDefault(/*is_in_oobe_context=*/false);
|
||||
|
||||
// Manages its own lifetime. See ShutdownDisplayHost().
|
||||
auto* display_host = new LoginDisplayHostWebUI();
|
||||
|
@ -124,8 +124,7 @@ void SetGaiaInputMethods(const AccountId& account_id) {
|
||||
lock_screen_utils::EnforceDevicePolicyInputMethods(std::string());
|
||||
std::vector<std::string> input_method_ids;
|
||||
if (gaia_ime_state->GetAllowedInputMethodIds().empty()) {
|
||||
input_method_ids =
|
||||
imm->GetInputMethodUtil()->GetHardwareLoginInputMethodIds();
|
||||
input_method_ids = imm->GetInputMethodUtil()->GetHardwareInputMethodIds();
|
||||
} else {
|
||||
input_method_ids = gaia_ime_state->GetAllowedInputMethodIds();
|
||||
}
|
||||
@ -139,7 +138,7 @@ void SetGaiaInputMethods(const AccountId& account_id) {
|
||||
PushFrontImIfNotExists(owner_input_method_id, &input_method_ids);
|
||||
PushFrontImIfNotExists(system_input_method_id, &input_method_ids);
|
||||
|
||||
gaia_ime_state->EnableLoginLayouts(
|
||||
gaia_ime_state->EnableOobeInputMethods(
|
||||
g_browser_process->GetApplicationLocale(), input_method_ids);
|
||||
|
||||
if (!system_input_method_id.empty()) {
|
||||
|
@ -391,7 +391,8 @@ void OnLanguageSwitchedCallback(
|
||||
// (`switch_locale` is empty) or after a locale switch otherwise.
|
||||
void TriggerShowLoginWizardFinish(
|
||||
std::string switch_locale,
|
||||
std::unique_ptr<ShowLoginWizardSwitchLanguageCallbackData> data) {
|
||||
std::unique_ptr<ShowLoginWizardSwitchLanguageCallbackData> data,
|
||||
bool login_input_methods_only) {
|
||||
if (switch_locale.empty()) {
|
||||
ShowLoginWizardFinish(data->first_screen, data->startup_manifest);
|
||||
} else {
|
||||
@ -400,9 +401,10 @@ void TriggerShowLoginWizardFinish(
|
||||
|
||||
// Load locale keyboards here. Hardware layout would be automatically
|
||||
// enabled.
|
||||
locale_util::SwitchLanguage(
|
||||
switch_locale, true, true /* login_layouts_only */, std::move(callback),
|
||||
ProfileManager::GetActiveUserProfile());
|
||||
locale_util::SwitchLanguage(switch_locale,
|
||||
/*enable_locale_keyboard_layouts=*/true,
|
||||
login_input_methods_only, std::move(callback),
|
||||
ProfileManager::GetActiveUserProfile());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,7 +1207,8 @@ void ShowLoginWizard(OobeScreenId first_screen) {
|
||||
input_method::InputMethodManager::Get();
|
||||
|
||||
if (g_browser_process && g_browser_process->local_state()) {
|
||||
manager->GetActiveIMEState()->SetInputMethodLoginDefault();
|
||||
manager->GetActiveIMEState()->SetInputMethodLoginDefault(
|
||||
/*is_in_oobe_context=*/true);
|
||||
}
|
||||
|
||||
system::InputDeviceSettings::Get()->SetNaturalScroll(
|
||||
@ -1266,7 +1269,8 @@ void ShowLoginWizard(OobeScreenId first_screen) {
|
||||
std::unique_ptr<ShowLoginWizardSwitchLanguageCallbackData> data =
|
||||
std::make_unique<ShowLoginWizardSwitchLanguageCallbackData>(
|
||||
first_screen, nullptr);
|
||||
TriggerShowLoginWizardFinish(switch_locale, std::move(data));
|
||||
TriggerShowLoginWizardFinish(switch_locale, std::move(data),
|
||||
/*login_input_methods_only=*/true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1293,7 +1297,8 @@ void ShowLoginWizard(OobeScreenId first_screen) {
|
||||
startup_manifest));
|
||||
|
||||
if (!current_locale.empty() || locale.empty()) {
|
||||
TriggerShowLoginWizardFinish(std::string(), std::move(data));
|
||||
TriggerShowLoginWizardFinish(std::string(), std::move(data),
|
||||
/*login_input_methods_only=*/false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1304,7 +1309,8 @@ void ShowLoginWizard(OobeScreenId first_screen) {
|
||||
prefs->SetString(language::prefs::kApplicationLocale, locale);
|
||||
StartupUtils::SetInitialLocale(locale);
|
||||
|
||||
TriggerShowLoginWizardFinish(locale, std::move(data));
|
||||
TriggerShowLoginWizardFinish(locale, std::move(data),
|
||||
/*login_input_methods_only=*/false);
|
||||
}
|
||||
|
||||
void SwitchWebUItoMojo() {
|
||||
|
@ -500,7 +500,7 @@ std::string FindMostRelevantLocale(
|
||||
return fallback_locale;
|
||||
}
|
||||
|
||||
base::Value::List GetAndActivateLoginKeyboardLayouts(
|
||||
base::Value::List GetAndActivateOobeInputMethods(
|
||||
const std::string& locale,
|
||||
const std::string& selected,
|
||||
input_method::InputMethodManager* input_method_manager) {
|
||||
@ -508,24 +508,24 @@ base::Value::List GetAndActivateLoginKeyboardLayouts(
|
||||
input_method::InputMethodUtil* util =
|
||||
input_method_manager->GetInputMethodUtil();
|
||||
|
||||
const std::vector<std::string>& hardware_login_input_methods =
|
||||
util->GetHardwareLoginInputMethodIds();
|
||||
const std::vector<std::string>& hardware_input_methods =
|
||||
util->GetHardwareInputMethodIds();
|
||||
|
||||
DCHECK(
|
||||
ProfileHelper::IsSigninProfile(ProfileManager::GetActiveUserProfile()));
|
||||
input_method_manager->GetActiveIMEState()->EnableLoginLayouts(
|
||||
locale, hardware_login_input_methods);
|
||||
input_method_manager->GetActiveIMEState()->EnableOobeInputMethods(
|
||||
locale, hardware_input_methods);
|
||||
|
||||
input_method::InputMethodDescriptors input_methods(
|
||||
input_method_manager->GetActiveIMEState()->GetEnabledInputMethods());
|
||||
std::set<std::string> input_methods_added;
|
||||
|
||||
for (const auto& hardware_login_input_method : hardware_login_input_methods) {
|
||||
for (const auto& hardware_input_method : hardware_input_methods) {
|
||||
const input_method::InputMethodDescriptor* ime =
|
||||
util->GetInputMethodDescriptorFromId(hardware_login_input_method);
|
||||
util->GetInputMethodDescriptorFromId(hardware_input_method);
|
||||
// Do not crash in case of misconfiguration.
|
||||
if (ime) {
|
||||
input_methods_added.insert(hardware_login_input_method);
|
||||
input_methods_added.insert(hardware_input_method);
|
||||
input_methods_list.Append(CreateInputMethodsEntry(*ime, selected, util));
|
||||
} else {
|
||||
NOTREACHED();
|
||||
|
@ -65,16 +65,16 @@ std::string FindMostRelevantLocale(
|
||||
const base::Value::List& available_locales,
|
||||
const std::string& fallback_locale);
|
||||
|
||||
// Return a list of keyboard layouts that can be used for `locale` on the login
|
||||
// Return a list of input methods that can be used for `locale` on the welcome
|
||||
// screen. Each list entry is a dictionary that contains data such as an ID and
|
||||
// a display name. The list will consist of the device's hardware layouts,
|
||||
// followed by a divider and locale-specific keyboard layouts, if any. The list
|
||||
// will also always contain the US keyboard layout. If `selected` matches the ID
|
||||
// followed by a divider and locale-specific input method IDs, if any. The list
|
||||
// will also always contain the US keyboard ID. If `selected` matches the ID
|
||||
// of any entry in the resulting list, that entry will be marked as selected.
|
||||
// In addition to returning the list of keyboard layouts, this function also
|
||||
// activates them, so that they can be selected by the user (e.g. by cycling
|
||||
// through keyboard layouts via keyboard shortcuts).
|
||||
base::Value::List GetAndActivateLoginKeyboardLayouts(
|
||||
// In addition to returning the list of IDs, this function also activates them,
|
||||
// so that they can be selected by the user (e.g. by cycling through input
|
||||
// methods via keyboard shortcuts).
|
||||
base::Value::List GetAndActivateOobeInputMethods(
|
||||
const std::string& locale,
|
||||
const std::string& selected,
|
||||
input_method::InputMethodManager* input_method_manager);
|
||||
|
@ -261,7 +261,7 @@ void WelcomeScreenHandler::GetAdditionalParameters(base::Value::Dict* dict) {
|
||||
}
|
||||
|
||||
dict->Set("languageList", std::move(language_list));
|
||||
dict->Set("inputMethodsList", GetAndActivateLoginKeyboardLayouts(
|
||||
dict->Set("inputMethodsList", GetAndActivateOobeInputMethods(
|
||||
application_locale, selected_input_method,
|
||||
input_method_manager));
|
||||
dict->Set("timezoneList", GetTimezoneList());
|
||||
|
@ -174,6 +174,18 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) InputMethodManager {
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_layouts) = 0;
|
||||
|
||||
// Enables OOBE-eligible (based on the allowlist) input methods that are
|
||||
// attached to the |language_code| and then switches to
|
||||
// |initial_input_methods| if the given list is not empty.
|
||||
// For example, if |language_code| is "en-US", US Qwerty, US International,
|
||||
// US Extended, US Dvorak, and US Colemak input methods would be enabled.
|
||||
// Likewise, for Japan locale, "Alphanumeric with Japanese keyboard"
|
||||
// together with the "fuzzy" Japanese input methods will be enabled as they
|
||||
// are part of the allowlist.
|
||||
virtual void EnableOobeInputMethods(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_input_methods) = 0;
|
||||
|
||||
// Filters current state layouts and leaves only suitable for lock screen.
|
||||
virtual void DisableNonLockScreenLayouts() = 0;
|
||||
|
||||
@ -212,10 +224,11 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) InputMethodManager {
|
||||
virtual void SetEnabledExtensionImes(base::span<const std::string> ids) = 0;
|
||||
|
||||
// Sets current input method to login default (first owners, then hardware).
|
||||
virtual void SetInputMethodLoginDefault() = 0;
|
||||
virtual void SetInputMethodLoginDefault(bool is_in_oobe_context) = 0;
|
||||
|
||||
// Sets current input method to login default with the given locale and
|
||||
// layout info from VPD.
|
||||
// This function is called only during system setup in OOBE.
|
||||
virtual void SetInputMethodLoginDefaultFromVPD(
|
||||
const std::string& locale,
|
||||
const std::string& layout) = 0;
|
||||
|
@ -395,6 +395,98 @@ const struct InputMethodNameMap {
|
||||
{"__MSG_TRANSLITERATION_UR__", IDS_IME_NAME_TRANSLITERATION_UR},
|
||||
};
|
||||
|
||||
// List of input methods that should be enabled in OOBE.
|
||||
// The only fuzzy IMs included in this list are those that have required data
|
||||
// pre-bundled in the system's image. Entries in the list should be updated
|
||||
// if pre-bundled data for any fuzzy IM is removed from the image.
|
||||
const char* const kOobeAllowlistedExtensionLocalIds[] = {
|
||||
// Keyboard layout IMs.
|
||||
"xkb:us::eng", // English (US)
|
||||
"xkb:us:altgr-intl:eng", // English (US) with Extended keyboard
|
||||
"xkb:us:colemak:eng", // English (US) with Colemak keyboard
|
||||
"xkb:us:dvorak:eng", // English (US) with Dvorak keyboard
|
||||
"xkb:us:dvp:eng", // English (US) with Programmer Dvorak keyboard
|
||||
"xkb:us:intl_pc:eng", // English (US) with International PC keyboard
|
||||
"xkb:us:intl:eng", // English (US) with International keyboard
|
||||
"xkb:us:workman-intl:eng", // English (US) with Workman International
|
||||
// keyboard
|
||||
"xkb:us:workman:eng", // English (US) with Workman keyboard
|
||||
"xkb:dk::dan", // Danish
|
||||
"xkb:be::nld", // Dutch (Belgium)
|
||||
"xkb:us:intl_pc:nld", // Dutch (Netherlands) with US International PC
|
||||
// keyboard
|
||||
"xkb:us:intl:nld", // Dutch (Netherlands)
|
||||
"xkb:ca:eng:eng", // English (Canada)
|
||||
"xkb:gb:dvorak:eng", // English (UK) with Dvorak keyboard
|
||||
"xkb:gb:extd:eng", // English (UK)
|
||||
"xkb:fi::fin", // Finnish
|
||||
"xkb:be::fra", // French (Belgium)
|
||||
"xkb:ca::fra", // French (Canada)
|
||||
"xkb:ca:multix:fra", // French (Canada) with Multilingual keyboard
|
||||
"xkb:fr::fra", // French (France)
|
||||
"xkb:fr:bepo:fra", // French (France) with Bépo keyboard
|
||||
"xkb:ch:fr:fra", // French (Switzerland)
|
||||
"xkb:be::ger", // German (Belgium)
|
||||
"xkb:de::ger", // German (Germany)
|
||||
"xkb:de:neo:ger", // German (Germany) with Neo 2 keyboard
|
||||
"xkb:ch::ger", // German (Switzerland)
|
||||
"xkb:it::ita", // Italian
|
||||
"xkb:no::nob", // Norwegian
|
||||
"xkb:pl::pol", // Polish
|
||||
"xkb:br::por", // Portuguese (Brazil)
|
||||
"xkb:pt::por", // Portuguese (Portugal)
|
||||
"xkb:us:intl_pc:por", // Portuguese with US International PC keyboard
|
||||
"xkb:us:intl:por", // Portuguese with US International keyboard
|
||||
"xkb:latam::spa", // Spanish (Latin America)
|
||||
"xkb:es::spa", // Spanish (Spain)
|
||||
"xkb:se::swe", // Swedish
|
||||
"xkb:tr::tur", // Turkish
|
||||
"xkb:tr:f:tur", // Turkish with F-keyboard
|
||||
"xkb:am:phonetic:arm", // Armenian
|
||||
"xkb:bg::bul", // Bulgarian
|
||||
"xkb:bg:phonetic:bul", // Bulgarian with Phonetic keyboard
|
||||
"xkb:by::bel", // Belarusian
|
||||
"xkb:es:cat:cat", // Catalan
|
||||
"xkb:cz:qwerty:cze", // Czech with QWERTY keyboard
|
||||
"xkb:cz::cze", // Czech
|
||||
"xkb:in::eng", // English (India)
|
||||
"xkb:pk::eng", // English (Pakistan)
|
||||
"xkb:za:gb:eng", // English (South Africa)
|
||||
"xkb:ee::est", // Estonian
|
||||
"xkb:us::fil", // Filipino
|
||||
"xkb:fo::fao", // Faroese
|
||||
"xkb:ge::geo", // Georgian
|
||||
"xkb:gr::gre", // Greek
|
||||
"xkb:hr::scr", // Croatian
|
||||
"xkb:hu::hun", // Hungarian
|
||||
"xkb:hu:qwerty:hun", // Hungarian with QWERTY keyboard
|
||||
"xkb:us::ind", // Indonesian
|
||||
"xkb:ie::ga", // Irish
|
||||
"xkb:il::heb", // Hebrew
|
||||
"xkb:is::ice", // Icelandic
|
||||
"xkb:jp::jpn", // Alphanumeric with Japanese keyboard
|
||||
"xkb:kz::kaz", // Kazakh
|
||||
"xkb:lt::lit", // Lithuanian
|
||||
"xkb:lv:apostrophe:lav", // Latvian
|
||||
"xkb:mk::mkd", // Macedonian
|
||||
"xkb:mn::mon", // Mongolian
|
||||
"xkb:us::msa", // Malay
|
||||
"xkb:mt::mlt", // Maltese
|
||||
"xkb:ro::rum", // Romanian
|
||||
"xkb:ro:std:rum", // Romanian with Standard keyboard
|
||||
"xkb:ru::rus", // Russian
|
||||
"xkb:ru:phonetic:rus", // Russian with Phonetic keyboard
|
||||
"xkb:rs::srp", // Serbian
|
||||
"xkb:si::slv", // Slovenian
|
||||
"xkb:sk::slo", // Slovak
|
||||
"xkb:ua::ukr", // Ukrainian
|
||||
// Deterministic IMEs.
|
||||
"vkd_ar", // Arabic
|
||||
// Fuzzy IMs.
|
||||
"nacl_mozc_us", // Japanese
|
||||
"nacl_mozc_jp", // Japanese with US keyboard
|
||||
};
|
||||
|
||||
// Inserts {key, value} into the multimap if it does not exist.
|
||||
void MultimapDeduplicatedInsert(LanguageCodeToIdsMap& multimap,
|
||||
const std::string& key,
|
||||
@ -434,6 +526,13 @@ InputMethodUtil::InputMethodUtil(InputMethodDelegate* delegate)
|
||||
english_to_resource_id_ = EnglishToIDMap(std::move(map_storage));
|
||||
DCHECK(english_to_resource_id_.size() == kEnglishToResourceIdArraySize)
|
||||
<< "Duplicate string is found";
|
||||
|
||||
for (const char* extension_local_id : kOobeAllowlistedExtensionLocalIds) {
|
||||
std::string fully_qualified_id =
|
||||
extension_ime_util::GetInputMethodIDByEngineID(
|
||||
std::string(extension_local_id));
|
||||
oobe_allowlisted_ids_.insert(fully_qualified_id);
|
||||
}
|
||||
}
|
||||
|
||||
InputMethodUtil::~InputMethodUtil() = default;
|
||||
@ -781,6 +880,12 @@ bool InputMethodUtil::IsLoginKeyboard(
|
||||
return ime ? ime->is_login_keyboard() : false;
|
||||
}
|
||||
|
||||
bool InputMethodUtil::IsOobeAllowlisted(
|
||||
const std::string& input_method_id) const {
|
||||
return oobe_allowlisted_ids_.find(input_method_id) !=
|
||||
oobe_allowlisted_ids_.cend();
|
||||
}
|
||||
|
||||
void InputMethodUtil::AppendInputMethods(const InputMethodDescriptors& imes) {
|
||||
for (const auto& input_method : imes) {
|
||||
DCHECK(!input_method.language_codes().empty());
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@ -132,6 +133,9 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) InputMethodUtil {
|
||||
// Returns true if given input method can be used to input login data.
|
||||
bool IsLoginKeyboard(const std::string& input_method_id) const;
|
||||
|
||||
// Returns true if given input method is allowlisted for OOBE.
|
||||
bool IsOobeAllowlisted(const std::string& input_method_id) const;
|
||||
|
||||
// Returns true if the given input method id is supported.
|
||||
bool IsValidInputMethodId(const std::string& input_method_id) const;
|
||||
|
||||
@ -185,6 +189,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) InputMethodUtil {
|
||||
std::vector<std::string> hardware_layouts_;
|
||||
std::vector<std::string> hardware_login_layouts_;
|
||||
std::vector<std::string> cached_hardware_layouts_;
|
||||
|
||||
std::set<std::string> oobe_allowlisted_ids_;
|
||||
};
|
||||
|
||||
} // namespace input_method
|
||||
|
@ -43,7 +43,11 @@ bool MockInputMethodManager::State::EnableInputMethod(
|
||||
|
||||
void MockInputMethodManager::State::EnableLoginLayouts(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_layout) {}
|
||||
const std::vector<std::string>& initial_layouts) {}
|
||||
|
||||
void MockInputMethodManager::State::EnableOobeInputMethods(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_input_methods) {}
|
||||
|
||||
void MockInputMethodManager::State::DisableNonLockScreenLayouts() {}
|
||||
|
||||
@ -78,7 +82,8 @@ size_t MockInputMethodManager::State::GetNumEnabledInputMethods() const {
|
||||
void MockInputMethodManager::State::SetEnabledExtensionImes(
|
||||
base::span<const std::string> ids) {}
|
||||
|
||||
void MockInputMethodManager::State::SetInputMethodLoginDefault() {}
|
||||
void MockInputMethodManager::State::SetInputMethodLoginDefault(
|
||||
bool is_in_oobe_context) {}
|
||||
|
||||
void MockInputMethodManager::State::SetInputMethodLoginDefaultFromVPD(
|
||||
const std::string& locale,
|
||||
|
@ -44,6 +44,9 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) MockInputMethodManager
|
||||
void EnableLoginLayouts(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_layouts) override;
|
||||
void EnableOobeInputMethods(
|
||||
const std::string& language_code,
|
||||
const std::vector<std::string>& initial_input_methods) override;
|
||||
void DisableNonLockScreenLayouts() override;
|
||||
void GetInputMethodExtensions(InputMethodDescriptors* result) override;
|
||||
InputMethodDescriptors GetEnabledInputMethodsSortedByLocalizedDisplayNames()
|
||||
@ -54,7 +57,7 @@ class COMPONENT_EXPORT(UI_BASE_IME_ASH) MockInputMethodManager
|
||||
const std::string& input_method_id) const override;
|
||||
size_t GetNumEnabledInputMethods() const override;
|
||||
void SetEnabledExtensionImes(base::span<const std::string> ids) override;
|
||||
void SetInputMethodLoginDefault() override;
|
||||
void SetInputMethodLoginDefault(bool is_in_oobe_context) override;
|
||||
void SetInputMethodLoginDefaultFromVPD(const std::string& locale,
|
||||
const std::string& layout) override;
|
||||
void SwitchToNextInputMethod() override;
|
||||
|
Reference in New Issue
Block a user