| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/prefs/public/pref_service_base.h" |
| 14 #include "base/string_split.h" | 15 #include "base/string_split.h" |
| 15 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 17 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/chromeos/input_method/input_method_delegate.h" |
| 18 #include "chrome/browser/prefs/pref_service.h" | |
| 19 #include "chrome/common/pref_names.h" | |
| 20 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
| 21 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
| 22 #include "ui/base/l10n/l10n_util_collator.h" | 21 #include "ui/base/l10n/l10n_util_collator.h" |
| 23 #include "unicode/uloc.h" | 22 #include "unicode/uloc.h" |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 // A mapping from an input method id to a string for the language indicator. The | 26 // A mapping from an input method id to a string for the language indicator. The |
| 28 // mapping is necessary since some input methods belong to the same language. | 27 // mapping is necessary since some input methods belong to the same language. |
| 29 // For example, both "xkb:us::eng" and "xkb:us:dvorak:eng" are for US English. | 28 // For example, both "xkb:us::eng" and "xkb:us:dvorak:eng" are for US English. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 { "mozc-chewing", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL }, | 74 { "mozc-chewing", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL }, |
| 76 { "mozc-dv", IDS_LANGUAGES_MEDIUM_LEN_NAME_JAPANESE }, | 75 { "mozc-dv", IDS_LANGUAGES_MEDIUM_LEN_NAME_JAPANESE }, |
| 77 { "mozc-hangul", IDS_LANGUAGES_MEDIUM_LEN_NAME_KOREAN }, | 76 { "mozc-hangul", IDS_LANGUAGES_MEDIUM_LEN_NAME_KOREAN }, |
| 78 { "mozc-jp", IDS_LANGUAGES_MEDIUM_LEN_NAME_JAPANESE }, | 77 { "mozc-jp", IDS_LANGUAGES_MEDIUM_LEN_NAME_JAPANESE }, |
| 79 { "pinyin", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED }, | 78 { "pinyin", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED }, |
| 80 { "pinyin-dv", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED }, | 79 { "pinyin-dv", IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED }, |
| 81 }; | 80 }; |
| 82 const size_t kMappingImeIdToMediumLenNameResourceIdLen = | 81 const size_t kMappingImeIdToMediumLenNameResourceIdLen = |
| 83 ARRAYSIZE_UNSAFE(kMappingImeIdToMediumLenNameResourceId); | 82 ARRAYSIZE_UNSAFE(kMappingImeIdToMediumLenNameResourceId); |
| 84 | 83 |
| 85 string16 GetLanguageName(const std::string& language_code) { | 84 } // namespace |
| 86 const string16 language_name = l10n_util::GetDisplayNameForLocale( | |
| 87 language_code, g_browser_process->GetApplicationLocale(), true); | |
| 88 return language_name; | |
| 89 } | |
| 90 | |
| 91 } | |
| 92 | 85 |
| 93 namespace chromeos { | 86 namespace chromeos { |
| 94 | 87 |
| 95 extern const char* kExtensionImePrefix; | 88 extern const char* kExtensionImePrefix; |
| 96 | 89 |
| 97 namespace input_method { | 90 namespace input_method { |
| 98 | 91 |
| 99 namespace { | 92 namespace { |
| 100 | 93 |
| 101 const struct EnglishToResouceId { | 94 const struct EnglishToResouceId { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 | 253 |
| 261 { "english-m", IDS_STATUSBAR_LAYOUT_USA_MYSTERY }, | 254 { "english-m", IDS_STATUSBAR_LAYOUT_USA_MYSTERY }, |
| 262 }; | 255 }; |
| 263 const size_t kEnglishToResourceIdArraySize = | 256 const size_t kEnglishToResourceIdArraySize = |
| 264 arraysize(kEnglishToResourceIdArray); | 257 arraysize(kEnglishToResourceIdArray); |
| 265 | 258 |
| 266 // The comparator is used for sorting language codes by their | 259 // The comparator is used for sorting language codes by their |
| 267 // corresponding language names, using the ICU collator. | 260 // corresponding language names, using the ICU collator. |
| 268 struct CompareLanguageCodesByLanguageName | 261 struct CompareLanguageCodesByLanguageName |
| 269 : std::binary_function<const std::string&, const std::string&, bool> { | 262 : std::binary_function<const std::string&, const std::string&, bool> { |
| 270 explicit CompareLanguageCodesByLanguageName(icu::Collator* collator) | 263 CompareLanguageCodesByLanguageName(InputMethodUtil* util, |
| 271 : collator_(collator) { | 264 icu::Collator* collator) |
| 265 : util_(util), collator_(collator) { |
| 272 } | 266 } |
| 273 | 267 |
| 274 // Calling GetLanguageDisplayNameFromCode() in the comparator is not | 268 // Calling GetLanguageDisplayNameFromCode() in the comparator is not |
| 275 // efficient, but acceptable as the function is cheap, and the language | 269 // efficient, but acceptable as the function is cheap, and the language |
| 276 // list is short (about 60 at most). | 270 // list is short (about 60 at most). |
| 277 bool operator()(const std::string& s1, const std::string& s2) const { | 271 bool operator()(const std::string& s1, const std::string& s2) const { |
| 278 const string16 key1 = InputMethodUtil::GetLanguageDisplayNameFromCode(s1); | 272 const string16 key1 = util_->GetLanguageDisplayNameFromCode(s1); |
| 279 const string16 key2 = InputMethodUtil::GetLanguageDisplayNameFromCode(s2); | 273 const string16 key2 = util_->GetLanguageDisplayNameFromCode(s2); |
| 280 return l10n_util::StringComparator<string16>(collator_)(key1, key2); | 274 return l10n_util::StringComparator<string16>(collator_)(key1, key2); |
| 281 } | 275 } |
| 282 | 276 |
| 283 private: | 277 private: |
| 278 InputMethodUtil* util_; |
| 284 icu::Collator* collator_; | 279 icu::Collator* collator_; |
| 285 }; | 280 }; |
| 286 | 281 |
| 287 } // namespace | 282 } // namespace |
| 288 | 283 |
| 289 const ExtraLanguage kExtraLanguages[] = { | 284 const ExtraLanguage kExtraLanguages[] = { |
| 290 // Language Code Input Method ID | 285 // Language Code Input Method ID |
| 291 { "en-AU", "xkb:us::eng" }, // For Austrailia, use US keyboard layout. | 286 { "en-AU", "xkb:us::eng" }, // For Austrailia, use US keyboard layout. |
| 292 { "id", "xkb:us::eng" }, // For Indonesian, use US keyboard layout. | 287 { "id", "xkb:us::eng" }, // For Indonesian, use US keyboard layout. |
| 293 // The code "fil" comes from l10_util.cc. | 288 // The code "fil" comes from l10_util.cc. |
| 294 { "fil", "xkb:us::eng" }, // For Filipino, use US keyboard layout. | 289 { "fil", "xkb:us::eng" }, // For Filipino, use US keyboard layout. |
| 295 // For Netherlands, use US international keyboard layout. | 290 // For Netherlands, use US international keyboard layout. |
| 296 { "nl", "xkb:us:intl:eng" }, | 291 { "nl", "xkb:us:intl:eng" }, |
| 297 // The code "es-419" comes from l10_util.cc. | 292 // The code "es-419" comes from l10_util.cc. |
| 298 // For Spanish in Latin America, use Latin American keyboard layout. | 293 // For Spanish in Latin America, use Latin American keyboard layout. |
| 299 { "es-419", "xkb:latam::spa" }, | 294 { "es-419", "xkb:latam::spa" }, |
| 300 // For Malay, use US keyboard layout. crosbug.com/p/8288 | 295 // For Malay, use US keyboard layout. crosbug.com/p/8288 |
| 301 { "ms", "xkb:us::eng" }, | 296 { "ms", "xkb:us::eng" }, |
| 302 | 297 |
| 303 // TODO(yusukes): Add {"sw", "xkb:us::eng"} once Swahili is removed from the | 298 // TODO(yusukes): Add {"sw", "xkb:us::eng"} once Swahili is removed from the |
| 304 // blacklist in src/ui/base/l10n/l10n_util_posix.cc. | 299 // blacklist in src/ui/base/l10n/l10n_util_posix.cc. |
| 305 }; | 300 }; |
| 306 const size_t kExtraLanguagesLength = arraysize(kExtraLanguages); | 301 const size_t kExtraLanguagesLength = arraysize(kExtraLanguages); |
| 307 | 302 |
| 308 InputMethodUtil::InputMethodUtil( | 303 InputMethodUtil::InputMethodUtil( |
| 304 InputMethodDelegate* delegate, |
| 309 scoped_ptr<InputMethodDescriptors> supported_input_methods) | 305 scoped_ptr<InputMethodDescriptors> supported_input_methods) |
| 310 : supported_input_methods_(supported_input_methods.Pass()) { | 306 : supported_input_methods_(supported_input_methods.Pass()), |
| 307 delegate_(delegate) { |
| 311 ReloadInternalMaps(); | 308 ReloadInternalMaps(); |
| 312 | 309 |
| 313 // Initialize a map from English string to Chrome string resource ID as well. | 310 // Initialize a map from English string to Chrome string resource ID as well. |
| 314 for (size_t i = 0; i < kEnglishToResourceIdArraySize; ++i) { | 311 for (size_t i = 0; i < kEnglishToResourceIdArraySize; ++i) { |
| 315 const EnglishToResouceId& map_entry = kEnglishToResourceIdArray[i]; | 312 const EnglishToResouceId& map_entry = kEnglishToResourceIdArray[i]; |
| 316 const bool result = english_to_resource_id_.insert(std::make_pair( | 313 const bool result = english_to_resource_id_.insert(std::make_pair( |
| 317 map_entry.english_string_from_ibus, map_entry.resource_id)).second; | 314 map_entry.english_string_from_ibus, map_entry.resource_id)).second; |
| 318 DCHECK(result) << "Duplicated string is found: " | 315 DCHECK(result) << "Duplicated string is found: " |
| 319 << map_entry.english_string_from_ibus; | 316 << map_entry.english_string_from_ibus; |
| 320 } | 317 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 // Indic languages: they share "Standard Input Method". | 474 // Indic languages: they share "Standard Input Method". |
| 478 const string16 standard_input_method_text = l10n_util::GetStringUTF16( | 475 const string16 standard_input_method_text = l10n_util::GetStringUTF16( |
| 479 IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD); | 476 IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD); |
| 480 const std::string language_code = input_method.language_code(); | 477 const std::string language_code = input_method.language_code(); |
| 481 | 478 |
| 482 string16 text = TranslateString(input_method.id()); | 479 string16 text = TranslateString(input_method.id()); |
| 483 if (text == standard_input_method_text || | 480 if (text == standard_input_method_text || |
| 484 language_code == "de" || | 481 language_code == "de" || |
| 485 language_code == "fr" || | 482 language_code == "fr" || |
| 486 language_code == "nl") { | 483 language_code == "nl") { |
| 487 text = GetLanguageName(language_code) + UTF8ToUTF16(" - ") + text; | 484 const string16 language_name = l10n_util::GetDisplayNameForLocale( |
| 485 language_code, delegate_->GetActiveLocale(), true); |
| 486 |
| 487 text = language_name + UTF8ToUTF16(" - ") + text; |
| 488 } | 488 } |
| 489 | 489 |
| 490 DCHECK(!text.empty()); | 490 DCHECK(!text.empty()); |
| 491 return text; | 491 return text; |
| 492 } | 492 } |
| 493 | 493 |
| 494 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromId( | 494 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromId( |
| 495 const std::string& input_method_id) const { | 495 const std::string& input_method_id) const { |
| 496 InputMethodIdToDescriptorMap::const_iterator iter | 496 InputMethodIdToDescriptorMap::const_iterator iter |
| 497 = id_to_descriptor_.find(input_method_id); | 497 = id_to_descriptor_.find(input_method_id); |
| 498 return (iter == id_to_descriptor_.end()) ? NULL : &(iter->second); | 498 return (iter == id_to_descriptor_.end()) ? NULL : &(iter->second); |
| 499 } | 499 } |
| 500 | 500 |
| 501 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromXkbId( | 501 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromXkbId( |
| 502 const std::string& xkb_id) const { | 502 const std::string& xkb_id) const { |
| 503 InputMethodIdToDescriptorMap::const_iterator iter | 503 InputMethodIdToDescriptorMap::const_iterator iter |
| 504 = xkb_id_to_descriptor_.find(xkb_id); | 504 = xkb_id_to_descriptor_.find(xkb_id); |
| 505 return (iter == xkb_id_to_descriptor_.end()) ? NULL : &(iter->second); | 505 return (iter == xkb_id_to_descriptor_.end()) ? NULL : &(iter->second); |
| 506 } | 506 } |
| 507 | 507 |
| 508 // static | 508 // static |
| 509 string16 InputMethodUtil::GetLanguageDisplayNameFromCode( | 509 string16 InputMethodUtil::GetLanguageDisplayNameFromCode( |
| 510 const std::string& language_code) { | 510 const std::string& language_code) { |
| 511 if (!g_browser_process) { | |
| 512 return string16(); | |
| 513 } | |
| 514 return l10n_util::GetDisplayNameForLocale( | 511 return l10n_util::GetDisplayNameForLocale( |
| 515 language_code, g_browser_process->GetApplicationLocale(), true); | 512 language_code, delegate_->GetActiveLocale(), true); |
| 516 } | 513 } |
| 517 | 514 |
| 518 // static | 515 // static |
| 519 string16 InputMethodUtil::GetLanguageNativeDisplayNameFromCode( | 516 string16 InputMethodUtil::GetLanguageNativeDisplayNameFromCode( |
| 520 const std::string& language_code) { | 517 const std::string& language_code) { |
| 521 return l10n_util::GetDisplayNameForLocale(language_code, language_code, true); | 518 return l10n_util::GetDisplayNameForLocale(language_code, language_code, true); |
| 522 } | 519 } |
| 523 | 520 |
| 524 // static | |
| 525 void InputMethodUtil::SortLanguageCodesByNames( | 521 void InputMethodUtil::SortLanguageCodesByNames( |
| 526 std::vector<std::string>* language_codes) { | 522 std::vector<std::string>* language_codes) { |
| 527 if (!g_browser_process) { | |
| 528 return; | |
| 529 } | |
| 530 // We should build collator outside of the comparator. We cannot have | 523 // We should build collator outside of the comparator. We cannot have |
| 531 // scoped_ptr<> in the comparator for a subtle STL reason. | 524 // scoped_ptr<> in the comparator for a subtle STL reason. |
| 532 UErrorCode error = U_ZERO_ERROR; | 525 UErrorCode error = U_ZERO_ERROR; |
| 533 icu::Locale locale(g_browser_process->GetApplicationLocale().c_str()); | 526 icu::Locale locale(delegate_->GetActiveLocale().c_str()); |
| 534 scoped_ptr<icu::Collator> collator( | 527 scoped_ptr<icu::Collator> collator( |
| 535 icu::Collator::createInstance(locale, error)); | 528 icu::Collator::createInstance(locale, error)); |
| 536 if (U_FAILURE(error)) { | 529 if (U_FAILURE(error)) { |
| 537 collator.reset(); | 530 collator.reset(); |
| 538 } | 531 } |
| 539 std::sort(language_codes->begin(), language_codes->end(), | 532 std::sort(language_codes->begin(), language_codes->end(), |
| 540 CompareLanguageCodesByLanguageName(collator.get())); | 533 CompareLanguageCodesByLanguageName(this, collator.get())); |
| 541 } | 534 } |
| 542 | 535 |
| 543 bool InputMethodUtil::GetInputMethodIdsFromLanguageCode( | 536 bool InputMethodUtil::GetInputMethodIdsFromLanguageCode( |
| 544 const std::string& normalized_language_code, | 537 const std::string& normalized_language_code, |
| 545 InputMethodType type, | 538 InputMethodType type, |
| 546 std::vector<std::string>* out_input_method_ids) const { | 539 std::vector<std::string>* out_input_method_ids) const { |
| 547 return GetInputMethodIdsFromLanguageCodeInternal( | 540 return GetInputMethodIdsFromLanguageCodeInternal( |
| 548 language_code_to_ids_, | 541 language_code_to_ids_, |
| 549 normalized_language_code, type, out_input_method_ids); | 542 normalized_language_code, type, out_input_method_ids); |
| 550 } | 543 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 const std::string language_code = input_method->language_code(); | 633 const std::string language_code = input_method->language_code(); |
| 641 // Add it if it's not already present. | 634 // Add it if it's not already present. |
| 642 if (std::count(out_language_codes->begin(), out_language_codes->end(), | 635 if (std::count(out_language_codes->begin(), out_language_codes->end(), |
| 643 language_code) == 0) { | 636 language_code) == 0) { |
| 644 out_language_codes->push_back(language_code); | 637 out_language_codes->push_back(language_code); |
| 645 } | 638 } |
| 646 } | 639 } |
| 647 } | 640 } |
| 648 | 641 |
| 649 std::string InputMethodUtil::GetHardwareInputMethodId() const { | 642 std::string InputMethodUtil::GetHardwareInputMethodId() const { |
| 650 if (!hardware_input_method_id_for_testing_.empty()) { | 643 const std::string input_method_id = delegate_->GetHardwareKeyboardLayout(); |
| 651 return hardware_input_method_id_for_testing_; | |
| 652 } | |
| 653 | 644 |
| 654 if (!(g_browser_process && g_browser_process->local_state())) { | |
| 655 // This shouldn't happen but just in case. | |
| 656 DVLOG(1) << "Local state is not yet ready"; | |
| 657 return InputMethodDescriptor::GetFallbackInputMethodDescriptor().id(); | |
| 658 } | |
| 659 | |
| 660 PrefService* local_state = g_browser_process->local_state(); | |
| 661 if (!local_state->FindPreference(prefs::kHardwareKeyboardLayout)) { | |
| 662 // This could happen in unittests. We register the preference in | |
| 663 // BrowserMain::InitializeLocalState and that method is not called during | |
| 664 // unittests. | |
| 665 DVLOG(1) << prefs::kHardwareKeyboardLayout << " is not registered"; | |
| 666 return InputMethodDescriptor::GetFallbackInputMethodDescriptor().id(); | |
| 667 } | |
| 668 | |
| 669 const std::string input_method_id = | |
| 670 local_state->GetString(prefs::kHardwareKeyboardLayout); | |
| 671 if (input_method_id.empty()) { | 645 if (input_method_id.empty()) { |
| 672 // This is totally fine if it's empty. The hardware keyboard layout is | 646 // This is totally fine if it's empty. The hardware keyboard layout is |
| 673 // not stored if startup_manifest.json (OEM customization data) is not | 647 // not stored if startup_manifest.json (OEM customization data) is not |
| 674 // present (ex. Cr48 doen't have that file). | 648 // present (ex. Cr48 doen't have that file). |
| 675 return InputMethodDescriptor::GetFallbackInputMethodDescriptor().id(); | 649 return InputMethodDescriptor::GetFallbackInputMethodDescriptor().id(); |
| 676 } | 650 } |
| 677 return input_method_id; | 651 return input_method_id; |
| 678 } | 652 } |
| 679 | 653 |
| 680 void InputMethodUtil::ReloadInternalMaps() { | 654 void InputMethodUtil::ReloadInternalMaps() { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 language_code_to_ids_.insert( | 693 language_code_to_ids_.insert( |
| 720 std::make_pair(language_code, input_method.id())); | 694 std::make_pair(language_code, input_method.id())); |
| 721 } | 695 } |
| 722 } | 696 } |
| 723 } | 697 } |
| 724 | 698 |
| 725 void InputMethodUtil::OnLocaleChanged() { | 699 void InputMethodUtil::OnLocaleChanged() { |
| 726 ReloadInternalMaps(); | 700 ReloadInternalMaps(); |
| 727 } | 701 } |
| 728 | 702 |
| 729 void InputMethodUtil::SetHardwareInputMethodIdForTesting( | |
| 730 const std::string& input_method_id) { | |
| 731 hardware_input_method_id_for_testing_ = input_method_id; | |
| 732 } | |
| 733 | |
| 734 } // namespace input_method | 703 } // namespace input_method |
| 735 } // namespace chromeos | 704 } // namespace chromeos |
| OLD | NEW |