Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: chrome/browser/chromeos/input_method/input_method_util.cc

Issue 190033005: [IME] Removes the duplicated IMEs in chrome://settings/languages, and support async component IMEs … (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: try to make test green. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/pref_service.h" 14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "chromeos/ime/component_extension_ime_manager.h" 18 #include "chromeos/ime/component_extension_ime_manager.h"
19 #include "chromeos/ime/extension_ime_util.h" 19 #include "chromeos/ime/extension_ime_util.h"
20 // For SetHardwareKeyboardLayoutForTesting. 20 // For SetHardwareKeyboardLayoutForTesting.
21 #include "chromeos/ime/fake_input_method_delegate.h" 21 #include "chromeos/ime/fake_input_method_delegate.h"
22 #include "chromeos/ime/input_method_delegate.h" 22 #include "chromeos/ime/input_method_delegate.h"
23 #include "chromeos/ime/input_method_whitelist.h"
23 // TODO(nona): move this header from this file. 24 // TODO(nona): move this header from this file.
24 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
25 26
26 namespace { 27 namespace {
27 28
28 // A mapping from an input method id to a string for the language indicator. The 29 // A mapping from an input method id to a string for the language indicator. The
29 // mapping is necessary since some input methods belong to the same language. 30 // mapping is necessary since some input methods belong to the same language.
30 // For example, both "xkb:us::eng" and "xkb:us:dvorak:eng" are for US English. 31 // For example, both "xkb:us::eng" and "xkb:us:dvorak:eng" are for US English.
31 const struct { 32 const struct {
32 const char* input_method_id; 33 const char* input_method_id;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 { "ja", "us", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" }, 120 { "ja", "us", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
120 { "ja", "jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" }, 121 { "ja", "jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
121 { "zh-CN", "us", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" }, 122 { "zh-CN", "us", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
122 { "zh-TW", "us", 123 { "zh-TW", "us",
123 "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und" }, 124 "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und" },
124 { "th", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" }, 125 { "th", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
125 { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" }, 126 { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
126 { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" }, 127 { "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
127 }; 128 };
128 129
130 // The map from xkb layout to the indicator text.
131 // Refer to crbug.com/349829.
132 const char* const kXkbIndicators[][2] = {{"am", "AM"},
133 {"be", "BE"},
134 {"bg", "BG"},
135 {"bg(phonetic)", "BG"},
136 {"br", "BR"},
137 {"by", "BY"},
138 {"ca", "CA"},
139 {"ca(eng)", "CA"},
140 {"ca(multix)", "CA"},
141 {"ch", "CH"},
142 {"ch(fr)", "CH"},
143 {"cz", "CZ"},
144 {"cz(qwerty)", "CS"},
145 {"de", "DE"},
146 {"de(neo)", "NEO"},
147 {"dk", "DK"},
148 {"ee", "EE"},
149 {"es", "ES"},
150 {"es(cat)", "CAS"},
151 {"fi", "FI"},
152 {"fr", "FR"},
153 {"gb(dvorak)", "DV"},
154 {"gb(extd)", "GB"},
155 {"ge", "GE"},
156 {"gr", "GR"},
157 {"hr", "HR"},
158 {"hu", "HU"},
159 {"il", "IL"},
160 {"is", "IS"},
161 {"it", "IT"},
162 {"jp", "JA"},
163 {"latam", "LA"},
164 {"lt", "LT"},
165 {"lv(apostrophe)", "LV"},
166 {"mn", "MN"},
167 {"no", "NO"},
168 {"pl", "PL"},
169 {"pt", "PT"},
170 {"ro", "RO"},
171 {"rs", "RS"},
172 {"ru", "RU"},
173 {"ru(phonetic)", "RU"},
174 {"se", "SE"},
175 {"si", "SI"},
176 {"sk", "SK"},
177 {"tr", "TR"},
178 {"ua", "UA"},
179 {"us", "US"},
180 {"us(altgr-intl)", "EXTD"},
181 {"us(colemak)", "CO"},
182 {"us(dvorak)", "DV"},
183 {"us(intl)", "INTL"}, };
184
129 } // namespace 185 } // namespace
130 186
131 namespace chromeos { 187 namespace chromeos {
132 188
133 extern const char* kExtensionImePrefix; 189 extern const char* kExtensionImePrefix;
134 190
135 namespace input_method { 191 namespace input_method {
136 192
137 namespace { 193 namespace {
138 194
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 const size_t kEnglishToResourceIdArraySize = 340 const size_t kEnglishToResourceIdArraySize =
285 arraysize(kEnglishToResourceIdArray); 341 arraysize(kEnglishToResourceIdArray);
286 342
287 } // namespace 343 } // namespace
288 344
289 InputMethodUtil::InputMethodUtil( 345 InputMethodUtil::InputMethodUtil(
290 InputMethodDelegate* delegate, 346 InputMethodDelegate* delegate,
291 scoped_ptr<InputMethodDescriptors> supported_input_methods) 347 scoped_ptr<InputMethodDescriptors> supported_input_methods)
292 : supported_input_methods_(supported_input_methods.Pass()), 348 : supported_input_methods_(supported_input_methods.Pass()),
293 delegate_(delegate) { 349 delegate_(delegate) {
350 // Makes sure the supported input methods at least have the fallback ime.
351 // So that it won't cause massive test failures.
352 if (supported_input_methods_->empty())
353 supported_input_methods_->push_back(GetFallbackInputMethodDescriptor());
354
294 ReloadInternalMaps(); 355 ReloadInternalMaps();
295 356
296 // Initialize a map from English string to Chrome string resource ID as well. 357 // Initialize a map from English string to Chrome string resource ID as well.
297 for (size_t i = 0; i < kEnglishToResourceIdArraySize; ++i) { 358 for (size_t i = 0; i < kEnglishToResourceIdArraySize; ++i) {
298 const EnglishToResouceId& map_entry = kEnglishToResourceIdArray[i]; 359 const EnglishToResouceId& map_entry = kEnglishToResourceIdArray[i];
299 const bool result = english_to_resource_id_.insert(std::make_pair( 360 const bool result = english_to_resource_id_.insert(std::make_pair(
300 map_entry.english_string_from_ibus, map_entry.resource_id)).second; 361 map_entry.english_string_from_ibus, map_entry.resource_id)).second;
301 DCHECK(result) << "Duplicated string is found: " 362 DCHECK(result) << "Duplicated string is found: "
302 << map_entry.english_string_from_ibus; 363 << map_entry.english_string_from_ibus;
303 } 364 }
365
366 // Initialize the map from xkb layout to indicator text.
367 for (size_t i = 0; i < arraysize(kXkbIndicators); ++i) {
368 xkb_layout_to_indicator_[kXkbIndicators[i][0]] = kXkbIndicators[i][1];
369 }
304 } 370 }
305 371
306 InputMethodUtil::~InputMethodUtil() { 372 InputMethodUtil::~InputMethodUtil() {
307 } 373 }
308 374
309 bool InputMethodUtil::TranslateStringInternal( 375 bool InputMethodUtil::TranslateStringInternal(
310 const std::string& english_string, base::string16 *out_string) const { 376 const std::string& english_string, base::string16 *out_string) const {
311 DCHECK(out_string); 377 DCHECK(out_string);
312 HashType::const_iterator iter = english_to_resource_id_.find(english_string); 378 HashType::const_iterator iter = english_to_resource_id_.find(english_string);
313 if (iter == english_to_resource_id_.end()) { 379 if (iter == english_to_resource_id_.end()) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 // Check special cases first. 457 // Check special cases first.
392 for (size_t i = 0; i < kMappingFromIdToIndicatorTextLen; ++i) { 458 for (size_t i = 0; i < kMappingFromIdToIndicatorTextLen; ++i) {
393 if (kMappingFromIdToIndicatorText[i].input_method_id == 459 if (kMappingFromIdToIndicatorText[i].input_method_id ==
394 input_method.id()) { 460 input_method.id()) {
395 text = base::UTF8ToUTF16(kMappingFromIdToIndicatorText[i].indicator_text); 461 text = base::UTF8ToUTF16(kMappingFromIdToIndicatorText[i].indicator_text);
396 break; 462 break;
397 } 463 }
398 } 464 }
399 465
400 // Display the keyboard layout name when using a keyboard layout. 466 // Display the keyboard layout name when using a keyboard layout.
401 if (text.empty() && 467 if (text.empty() && IsKeyboardLayout(input_method.id())) {
402 IsKeyboardLayout(input_method.id())) { 468 std::map<std::string, std::string>::const_iterator it =
403 const size_t kMaxKeyboardLayoutNameLen = 2; 469 xkb_layout_to_indicator_.find(GetKeyboardLayoutName(input_method.id()));
404 const base::string16 keyboard_layout = 470 if (it != xkb_layout_to_indicator_.end())
405 base::UTF8ToUTF16(GetKeyboardLayoutName(input_method.id())); 471 text = base::UTF8ToUTF16(it->second);
406 text = StringToUpperASCII(keyboard_layout).substr(
407 0, kMaxKeyboardLayoutNameLen);
408 } 472 }
409 473
410 // TODO(yusukes): Some languages have two or more input methods. For example, 474 // TODO(yusukes): Some languages have two or more input methods. For example,
411 // Thai has 3, Vietnamese has 4. If these input methods could be activated at 475 // Thai has 3, Vietnamese has 4. If these input methods could be activated at
412 // the same time, we should do either of the following: 476 // the same time, we should do either of the following:
413 // (1) Add mappings to |kMappingFromIdToIndicatorText| 477 // (1) Add mappings to |kMappingFromIdToIndicatorText|
414 // (2) Add suffix (1, 2, ...) to |text| when ambiguous. 478 // (2) Add suffix (1, 2, ...) to |text| when ambiguous.
415 479
416 if (text.empty()) { 480 if (text.empty()) {
417 const size_t kMaxLanguageNameLen = 2; 481 const size_t kMaxLanguageNameLen = 2;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 538
475 text = language_name + base::UTF8ToUTF16(" - ") + text; 539 text = language_name + base::UTF8ToUTF16(" - ") + text;
476 } 540 }
477 541
478 DCHECK(!text.empty()); 542 DCHECK(!text.empty());
479 return text; 543 return text;
480 } 544 }
481 545
482 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromId( 546 const InputMethodDescriptor* InputMethodUtil::GetInputMethodDescriptorFromId(
483 const std::string& input_method_id) const { 547 const std::string& input_method_id) const {
484 InputMethodIdToDescriptorMap::const_iterator iter 548 InputMethodIdToDescriptorMap::const_iterator iter =
485 = id_to_descriptor_.find(input_method_id); 549 id_to_descriptor_.find(input_method_id);
486 if (iter == id_to_descriptor_.end()) { 550 if (iter == id_to_descriptor_.end())
487 // If failed to find the descriptor for given id, it may because of the id 551 return NULL;
488 // is a component extension xkb id (_comp_ime_...xkb:...).
489 // So try to convert it to legacy xkb id and find again.
490 // This hack is mainly for OOBE session, which requires a sync call to get
491 // the input method descriptor for extension xkb id.
492 // TODO(shuchen): need to support async wait for component extension
493 // loading in OOBE session. This hack won't be needed when it's been done.
494 iter = id_to_descriptor_.find(
495 extension_ime_util::MaybeGetLegacyXkbId(input_method_id));
496 if (iter == id_to_descriptor_.end())
497 return NULL;
498 }
499 return &(iter->second); 552 return &(iter->second);
500 } 553 }
501 554
502 bool InputMethodUtil::GetInputMethodIdsFromLanguageCode( 555 bool InputMethodUtil::GetInputMethodIdsFromLanguageCode(
503 const std::string& normalized_language_code, 556 const std::string& normalized_language_code,
504 InputMethodType type, 557 InputMethodType type,
505 std::vector<std::string>* out_input_method_ids) const { 558 std::vector<std::string>* out_input_method_ids) const {
506 return GetInputMethodIdsFromLanguageCodeInternal( 559 return GetInputMethodIdsFromLanguageCodeInternal(
507 language_code_to_ids_, 560 language_code_to_ids_,
508 normalized_language_code, type, out_input_method_ids); 561 normalized_language_code, type, out_input_method_ids);
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 754
702 bool InputMethodUtil::IsLoginKeyboard(const std::string& input_method_id) 755 bool InputMethodUtil::IsLoginKeyboard(const std::string& input_method_id)
703 const { 756 const {
704 const InputMethodDescriptor* ime = 757 const InputMethodDescriptor* ime =
705 GetInputMethodDescriptorFromId(input_method_id); 758 GetInputMethodDescriptorFromId(input_method_id);
706 return ime ? ime->is_login_keyboard() : false; 759 return ime ? ime->is_login_keyboard() : false;
707 } 760 }
708 761
709 void InputMethodUtil::SetComponentExtensions( 762 void InputMethodUtil::SetComponentExtensions(
710 const InputMethodDescriptors& imes) { 763 const InputMethodDescriptors& imes) {
711 component_extension_ime_id_to_descriptor_.clear();
712 for (size_t i = 0; i < imes.size(); ++i) { 764 for (size_t i = 0; i < imes.size(); ++i) {
713 const InputMethodDescriptor& input_method = imes.at(i); 765 const InputMethodDescriptor& input_method = imes[i];
714 DCHECK(!input_method.language_codes().empty()); 766 DCHECK(!input_method.language_codes().empty());
715 const std::string language_code = input_method.language_codes().at(0); 767 const std::vector<std::string>& language_codes =
716 id_to_language_code_.insert( 768 input_method.language_codes();
717 std::make_pair(input_method.id(), language_code)); 769 id_to_language_code_[input_method.id()] = language_codes[0];
718 id_to_descriptor_.insert( 770 id_to_descriptor_[input_method.id()] = input_method;
719 std::make_pair(input_method.id(), input_method)); 771
772 typedef LanguageCodeToIdsMap::const_iterator It;
773 for (size_t j = 0; j < language_codes.size(); ++j) {
774 std::pair<It, It> range =
775 language_code_to_ids_.equal_range(language_codes[j]);
776 It it = range.first;
777 for (; it != range.second; ++it) {
778 if (it->second == input_method.id())
779 break;
780 }
781 if (it == range.second)
782 language_code_to_ids_.insert(
783 std::make_pair(language_codes[j], input_method.id()));
784 }
720 } 785 }
721 } 786 }
722 787
788 void InputMethodUtil::InitXkbInputMethodsForTesting() {
789 if (!extension_ime_util::UseWrappedExtensionKeyboardLayouts())
790 return;
791 scoped_ptr<InputMethodDescriptors> original_imes =
792 InputMethodWhitelist().GetSupportedInputMethods();
793 InputMethodDescriptors whitelist_imes;
794 for (size_t i = 0; i < original_imes->size(); ++i) {
795 const InputMethodDescriptor& ime = (*original_imes)[i];
796 whitelist_imes.push_back(InputMethodDescriptor(
797 extension_ime_util::GetInputMethodIDByKeyboardLayout(ime.id()),
798 "",
799 ime.indicator(),
800 ime.keyboard_layouts(),
801 ime.language_codes(),
802 ime.is_login_keyboard(),
803 ime.options_page_url(),
804 ime.input_view_url()));
805 }
806 SetComponentExtensions(whitelist_imes);
807 }
808
723 InputMethodDescriptor InputMethodUtil::GetFallbackInputMethodDescriptor() { 809 InputMethodDescriptor InputMethodUtil::GetFallbackInputMethodDescriptor() {
724 std::vector<std::string> layouts; 810 std::vector<std::string> layouts;
725 layouts.push_back("us"); 811 layouts.push_back("us");
726 std::vector<std::string> languages; 812 std::vector<std::string> languages;
727 languages.push_back("en-US"); 813 languages.push_back("en-US");
728 return InputMethodDescriptor( 814 return InputMethodDescriptor(
729 extension_ime_util::GetInputMethodIDByKeyboardLayout("xkb:us::eng"), 815 extension_ime_util::GetInputMethodIDByKeyboardLayout("xkb:us::eng"),
730 "", 816 "",
731 "US", 817 "US",
732 layouts, 818 layouts,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 if (IsKeyboardLayout(input_method.id())) { 851 if (IsKeyboardLayout(input_method.id())) {
766 xkb_id_to_descriptor_.insert( 852 xkb_id_to_descriptor_.insert(
767 std::make_pair(input_method.GetPreferredKeyboardLayout(), 853 std::make_pair(input_method.GetPreferredKeyboardLayout(),
768 input_method)); 854 input_method));
769 } 855 }
770 } 856 }
771 } 857 }
772 858
773 } // namespace input_method 859 } // namespace input_method
774 } // namespace chromeos 860 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698