blob: f0c5b996aaa54f30cedb06c347f8c092d368031d [file] [log] [blame]
// Copyright 2021 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 "chrome/browser/ash/input_method/input_method_settings.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "chrome/common/pref_names.h"
namespace ash {
namespace input_method {
namespace {
namespace mojom = ::ash::ime::mojom;
// The values here should be kept in sync with
// chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
// Although these strings look like UI strings, they are the actual internal
// values stored inside prefs. Therefore, it is important to make sure these
// strings match the settings page exactly.
constexpr char kKoreanPrefsLayoutDubeolsik[] = "2 Set / 두벌식";
constexpr char kKoreanPrefsLayoutDubeolsikOldHangeul[] =
"2 Set (Old Hangul) / 두벌식 (옛글)";
constexpr char kKoreanPrefsLayoutSebeolsik390[] = "3 Set (390) / 세벌식 (390)";
constexpr char kKoreanPrefsLayoutSebeolsikFinal[] =
"3 Set (Final) / 세벌식 (최종)";
constexpr char kKoreanPrefsLayoutSebeolsikNoShift[] =
"3 Set (No Shift) / 세벌식 (순아래)";
constexpr char kKoreanPrefsLayoutSebeolsikOldHangeul[] =
"3 Set (Old Hangul) / 세벌식 (옛글)";
// The values here should be kept in sync with
// chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
constexpr char kPinyinPrefsLayoutUsQwerty[] = "US";
constexpr char kPinyinPrefsLayoutDvorak[] = "Dvorak";
constexpr char kPinyinPrefsLayoutColemak[] = "Colemak";
// The values here should be kept in sync with
// chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
constexpr char kZhuyinPrefsLayoutStandard[] = "Default";
constexpr char kZhuyinPrefsLayoutIbm[] = "IBM";
constexpr char kZhuyinPrefsLayoutEten[] = "Eten";
// The values here should be kept in sync with
// chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
constexpr char kZhuyinPrefsSelectionKeys1234567890[] = "1234567890";
constexpr char kZhuyinPrefsSelectionKeysAsdfghjkl[] = "asdfghjkl;";
constexpr char kZhuyinPrefsSelectionKeysAsdfzxcv89[] = "asdfzxcv89";
constexpr char kZhuyinPrefsSelectionKeysAsdfjkl789[] = "asdfjkl789";
constexpr char kZhuyinPrefsSelectionKeys1234Qweras[] = "1234qweras";
// The values here should be kept in sync with
// chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
constexpr char kZhuyinPrefsPageSize10[] = "10";
constexpr char kZhuyinPrefsPageSize9[] = "9";
constexpr char kZhuyinPrefsPageSize8[] = "8";
std::string ValueOrEmpty(const std::string* str) {
return str ? *str : "";
}
bool IsUsEnglishEngine(const std::string& engine_id) {
return engine_id == "xkb:us::eng";
}
bool IsFstEngine(const std::string& engine_id) {
return base::StartsWith(engine_id, "xkb:", base::CompareCase::SENSITIVE) ||
base::StartsWith(engine_id, "experimental_",
base::CompareCase::SENSITIVE);
}
bool IsKoreanEngine(const std::string& engine_id) {
return base::StartsWith(engine_id, "ko-", base::CompareCase::SENSITIVE);
}
bool IsPinyinEngine(const std::string& engine_id) {
return engine_id == "zh-t-i0-pinyin" || engine_id == "zh-hant-t-i0-pinyin";
}
bool IsZhuyinEngine(const std::string& engine_id) {
return engine_id == "zh-hant-t-i0-und";
}
std::string GetPrefKeyForEngineId(const std::string& engine_id) {
if (engine_id == "zh-t-i0-pinyin") {
return "pinyin";
}
if (engine_id == "zh-hant-t-i0-und") {
return "zhuyin";
}
return engine_id;
}
mojom::LatinSettingsPtr CreateLatinSettings(
const base::Value& input_method_specific_pref,
const PrefService& prefs,
const std::string& engine_id,
const InputFieldContext& context) {
auto settings = mojom::LatinSettings::New();
settings->autocorrect =
base::StartsWith(engine_id, "experimental_",
base::CompareCase::SENSITIVE) ||
input_method_specific_pref
.FindIntKey("physicalKeyboardAutoCorrectionLevel")
.value_or(0) > 0;
settings->predictive_writing =
context.multiword_enabled && context.multiword_allowed &&
!context.lacros_enabled &&
prefs.GetBoolean(prefs::kAssistPredictiveWritingEnabled) &&
IsUsEnglishEngine(engine_id);
return settings;
}
mojom::KoreanLayout KoreanLayoutToMojom(const std::string& layout) {
if (layout == kKoreanPrefsLayoutDubeolsik)
return mojom::KoreanLayout::kDubeolsik;
if (layout == kKoreanPrefsLayoutDubeolsikOldHangeul)
return mojom::KoreanLayout::kDubeolsikOldHangeul;
if (layout == kKoreanPrefsLayoutSebeolsik390)
return mojom::KoreanLayout::kSebeolsik390;
if (layout == kKoreanPrefsLayoutSebeolsikFinal)
return mojom::KoreanLayout::kSebeolsikFinal;
if (layout == kKoreanPrefsLayoutSebeolsikNoShift)
return mojom::KoreanLayout::kSebeolsikNoShift;
if (layout == kKoreanPrefsLayoutSebeolsikOldHangeul)
return mojom::KoreanLayout::kSebeolsikOldHangeul;
return mojom::KoreanLayout::kDubeolsik;
}
mojom::KoreanSettingsPtr CreateKoreanSettings(
const base::Value& input_method_specific_pref) {
auto settings = mojom::KoreanSettings::New();
settings->input_multiple_syllables =
!input_method_specific_pref.FindBoolKey("koreanEnableSyllableInput")
.value_or(true);
const std::string* prefs_layout =
input_method_specific_pref.FindStringKey("koreanKeyboardLayout");
settings->layout = prefs_layout ? KoreanLayoutToMojom(*prefs_layout)
: mojom::KoreanLayout::kDubeolsik;
return settings;
}
mojom::FuzzyPinyinSettingsPtr CreateFuzzyPinyinSettings(
const base::Value& pref) {
auto settings = mojom::FuzzyPinyinSettings::New();
settings->an_ang = pref.FindBoolKey("an:ang").value_or(false);
settings->en_eng = pref.FindBoolKey("en:eng").value_or(false);
settings->ian_iang = pref.FindBoolKey("ian:iang").value_or(false);
settings->k_g = pref.FindBoolKey("k:g").value_or(false);
settings->r_l = pref.FindBoolKey("r:l").value_or(false);
settings->uan_uang = pref.FindBoolKey("uan:uang").value_or(false);
settings->c_ch = pref.FindBoolKey("c:ch").value_or(false);
settings->f_h = pref.FindBoolKey("f:h").value_or(false);
settings->in_ing = pref.FindBoolKey("in:ing").value_or(false);
settings->l_n = pref.FindBoolKey("l:n").value_or(false);
settings->s_sh = pref.FindBoolKey("s:sh").value_or(false);
settings->z_zh = pref.FindBoolKey("z:zh").value_or(false);
return settings;
}
mojom::PinyinLayout PinyinLayoutToMojom(const std::string& layout) {
if (layout == kPinyinPrefsLayoutUsQwerty)
return mojom::PinyinLayout::kUsQwerty;
if (layout == kPinyinPrefsLayoutDvorak)
return mojom::PinyinLayout::kDvorak;
if (layout == kPinyinPrefsLayoutColemak)
return mojom::PinyinLayout::kColemak;
return mojom::PinyinLayout::kUsQwerty;
}
mojom::PinyinSettingsPtr CreatePinyinSettings(
const base::Value& input_method_specific_pref) {
auto settings = mojom::PinyinSettings::New();
settings->fuzzy_pinyin =
CreateFuzzyPinyinSettings(input_method_specific_pref);
const std::string* prefs_layout =
input_method_specific_pref.FindStringKey("xkbLayout");
settings->layout = prefs_layout ? PinyinLayoutToMojom(*prefs_layout)
: mojom::PinyinLayout::kUsQwerty;
settings->use_hyphen_and_equals_to_page_candidates =
input_method_specific_pref.FindBoolKey("pinyinEnableUpperPaging")
.value_or(true);
settings->use_comma_and_period_to_page_candidates =
input_method_specific_pref.FindBoolKey("pinyinEnableLowerPaging")
.value_or(true);
settings->default_to_chinese =
input_method_specific_pref.FindBoolKey("pinyinDefaultChinese")
.value_or(true);
settings->default_to_full_width_characters =
input_method_specific_pref.FindBoolKey("pinyinFullWidthCharacter")
.value_or(false);
settings->default_to_full_width_punctuation =
input_method_specific_pref.FindBoolKey("pinyinChinesePunctuation")
.value_or(true);
return settings;
}
mojom::ZhuyinLayout ZhuyinLayoutToMojom(const std::string& layout) {
if (layout == kZhuyinPrefsLayoutStandard)
return mojom::ZhuyinLayout::kStandard;
if (layout == kZhuyinPrefsLayoutIbm)
return mojom::ZhuyinLayout::kIbm;
if (layout == kZhuyinPrefsLayoutEten)
return mojom::ZhuyinLayout::kEten;
return mojom::ZhuyinLayout::kStandard;
}
mojom::ZhuyinSelectionKeys ZhuyinSelectionKeysToMojom(
const std::string& selection_keys) {
if (selection_keys == kZhuyinPrefsSelectionKeys1234567890)
return mojom::ZhuyinSelectionKeys::k1234567890;
if (selection_keys == kZhuyinPrefsSelectionKeysAsdfghjkl)
return mojom::ZhuyinSelectionKeys::kAsdfghjkl;
if (selection_keys == kZhuyinPrefsSelectionKeysAsdfzxcv89)
return mojom::ZhuyinSelectionKeys::kAsdfzxcv89;
if (selection_keys == kZhuyinPrefsSelectionKeysAsdfjkl789)
return mojom::ZhuyinSelectionKeys::kAsdfjkl789;
if (selection_keys == kZhuyinPrefsSelectionKeys1234Qweras)
return mojom::ZhuyinSelectionKeys::k1234Qweras;
return mojom::ZhuyinSelectionKeys::k1234567890;
}
uint32_t ZhuyinPageSizeToInt(const std::string& page_size) {
if (page_size == kZhuyinPrefsPageSize10)
return 10;
if (page_size == kZhuyinPrefsPageSize9)
return 9;
if (page_size == kZhuyinPrefsPageSize8)
return 8;
return 10;
}
mojom::ZhuyinSettingsPtr CreateZhuyinSettings(
const base::Value& input_method_specific_pref) {
auto settings = mojom::ZhuyinSettings::New();
settings->layout = ZhuyinLayoutToMojom(ValueOrEmpty(
input_method_specific_pref.FindStringKey("zhuyinKeyboardLayout")));
settings->selection_keys = ZhuyinSelectionKeysToMojom(ValueOrEmpty(
input_method_specific_pref.FindStringKey("zhuyinSelectKeys")));
settings->page_size = ZhuyinPageSizeToInt(
ValueOrEmpty(input_method_specific_pref.FindStringKey("zhuyinPageSize")));
return settings;
}
} // namespace
mojom::InputMethodSettingsPtr CreateSettingsFromPrefs(
const PrefService& prefs,
const std::string& engine_id,
const InputFieldContext& context) {
// All input method settings are stored in a single pref whose value is a
// dictionary.
const base::Value& all_input_method_pref =
*prefs.GetDictionary(::prefs::kLanguageInputMethodSpecificSettings);
// For each input method, the dictionary contains an entry, with the key being
// a string that identifies the input method, and the value being a
// subdictionary with the specific settings for that input method.
// The subdictionary structure depends on the type of input method it's for.
// The subdictionary may be null if the user hasn't changed any settings for
// that input method.
const base::Value* input_method_specific_pref_or_null =
all_input_method_pref.FindDictKey(GetPrefKeyForEngineId(engine_id));
// For convenience, pass an empty dictionary if there are no settings for this
// input method yet.
base::DictionaryValue empty_value;
const auto& input_method_specific_pref =
input_method_specific_pref_or_null ? *input_method_specific_pref_or_null
: empty_value;
if (IsFstEngine(engine_id)) {
return mojom::InputMethodSettings::NewLatinSettings(CreateLatinSettings(
input_method_specific_pref, prefs, engine_id, context));
}
if (IsKoreanEngine(engine_id)) {
return mojom::InputMethodSettings::NewKoreanSettings(
CreateKoreanSettings(input_method_specific_pref));
}
if (IsPinyinEngine(engine_id)) {
return mojom::InputMethodSettings::NewPinyinSettings(
CreatePinyinSettings(input_method_specific_pref));
}
if (IsZhuyinEngine(engine_id)) {
return mojom::InputMethodSettings::NewZhuyinSettings(
CreateZhuyinSettings(input_method_specific_pref));
}
return nullptr;
}
} // namespace input_method
} // namespace ash