| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/extensions/api/language_settings_private/language_setti
ngs_private_api.h" | 5 #include "chrome/browser/extensions/api/language_settings_private/language_setti
ngs_private_api.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 7 #include <map> | 8 #include <map> |
| 8 #include <memory> | 9 #include <memory> |
| 9 #include <string> | 10 #include <string> |
| 11 #include <unordered_set> |
| 10 #include <utility> | 12 #include <utility> |
| 11 #include <vector> | 13 #include <vector> |
| 12 | 14 |
| 13 #include "base/containers/hash_tables.h" | |
| 14 #include "base/i18n/rtl.h" | 15 #include "base/i18n/rtl.h" |
| 15 #include "base/memory/linked_ptr.h" | 16 #include "base/memory/linked_ptr.h" |
| 16 #include "base/strings/string16.h" | 17 #include "base/strings/string16.h" |
| 18 #include "base/strings/string_split.h" |
| 19 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/values.h" | 21 #include "base/values.h" |
| 19 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 20 #include "chrome/browser/browser_process.h" | 23 #include "chrome/browser/browser_process.h" |
| 21 #include "chrome/browser/extensions/api/language_settings_private/language_setti
ngs_private_delegate.h" | 24 #include "chrome/browser/extensions/api/language_settings_private/language_setti
ngs_private_delegate.h" |
| 22 #include "chrome/browser/extensions/api/language_settings_private/language_setti
ngs_private_delegate_factory.h" | 25 #include "chrome/browser/extensions/api/language_settings_private/language_setti
ngs_private_delegate_factory.h" |
| 23 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
| 24 #include "chrome/browser/spellchecker/spellcheck_factory.h" | 27 #include "chrome/browser/spellchecker/spellcheck_factory.h" |
| 25 #include "chrome/browser/spellchecker/spellcheck_service.h" | 28 #include "chrome/browser/spellchecker/spellcheck_service.h" |
| 26 #include "chrome/browser/translate/chrome_translate_client.h" | 29 #include "chrome/browser/translate/chrome_translate_client.h" |
| 27 #include "chrome/browser/translate/translate_service.h" | 30 #include "chrome/browser/translate/translate_service.h" |
| 28 #include "chrome/common/extensions/api/language_settings_private.h" | 31 #include "chrome/common/extensions/api/language_settings_private.h" |
| 32 #include "chrome/common/pref_names.h" |
| 29 #include "chrome/common/spellcheck_common.h" | 33 #include "chrome/common/spellcheck_common.h" |
| 30 #include "components/translate/core/browser/translate_download_manager.h" | 34 #include "components/translate/core/browser/translate_download_manager.h" |
| 31 #include "third_party/icu/source/i18n/unicode/coll.h" | 35 #include "third_party/icu/source/i18n/unicode/coll.h" |
| 32 #include "ui/base/l10n/l10n_util.h" | 36 #include "ui/base/l10n/l10n_util.h" |
| 33 #include "ui/base/l10n/l10n_util_collator.h" | 37 #include "ui/base/l10n/l10n_util_collator.h" |
| 34 | 38 |
| 35 #if defined(OS_CHROMEOS) | 39 #if defined(OS_CHROMEOS) |
| 36 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 40 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 37 #include "ui/base/ime/chromeos/component_extension_ime_manager.h" | 41 #include "ui/base/ime/chromeos/component_extension_ime_manager.h" |
| 38 #include "ui/base/ime/chromeos/extension_ime_util.h" | 42 #include "ui/base/ime/chromeos/extension_ime_util.h" |
| 39 #include "ui/base/ime/chromeos/input_method_manager.h" | 43 #include "ui/base/ime/chromeos/input_method_manager.h" |
| 40 #endif | 44 #endif |
| 41 | 45 |
| 42 namespace extensions { | 46 namespace extensions { |
| 43 | 47 |
| 44 namespace language_settings_private = api::language_settings_private; | 48 namespace language_settings_private = api::language_settings_private; |
| 45 | 49 |
| 46 #if defined(OS_CHROMEOS) | 50 #if defined(OS_CHROMEOS) |
| 51 using chromeos::input_method::InputMethodDescriptor; |
| 47 using chromeos::input_method::InputMethodDescriptors; | 52 using chromeos::input_method::InputMethodDescriptors; |
| 48 using chromeos::input_method::InputMethodManager; | 53 using chromeos::input_method::InputMethodManager; |
| 49 using chromeos::input_method::InputMethodUtil; | 54 using chromeos::input_method::InputMethodUtil; |
| 55 |
| 56 namespace { |
| 57 |
| 58 // Returns the set of IDs of all enabled IMEs. |
| 59 std::unordered_set<std::string> GetEnabledIMEs( |
| 60 scoped_refptr<InputMethodManager::State> ime_state) { |
| 61 const std::vector<std::string>& ime_ids(ime_state->GetActiveInputMethodIds()); |
| 62 return std::unordered_set<std::string>(ime_ids.begin(), ime_ids.end()); |
| 63 } |
| 64 |
| 65 // Returns the set of IDs of enabled IMEs for the given pref. |
| 66 std::unordered_set<std::string> GetIMEsFromPref(PrefService* prefs, |
| 67 const char* pref_name) { |
| 68 std::vector<std::string> enabled_imes = |
| 69 base::SplitString(prefs->GetString(pref_name), ",", base::TRIM_WHITESPACE, |
| 70 base::SPLIT_WANT_NONEMPTY); |
| 71 return std::unordered_set<std::string>(enabled_imes.begin(), |
| 72 enabled_imes.end()); |
| 73 } |
| 74 |
| 75 // Sorts the input methods by the order of their associated languages. For |
| 76 // example, if the enabled language order is: |
| 77 // - French |
| 78 // - English |
| 79 // then the French keyboard should come before the English keyboard. |
| 80 std::vector<std::string> GetSortedComponentIMEs( |
| 81 InputMethodManager* manager, |
| 82 scoped_refptr<InputMethodManager::State> ime_state, |
| 83 const std::unordered_set<std::string>& component_ime_set, |
| 84 PrefService* prefs) { |
| 85 std::vector<std::string> enabled_languages = |
| 86 base::SplitString(prefs->GetString(prefs::kLanguagePreferredLanguages), |
| 87 ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 88 |
| 89 // Duplicate set for membership testing. |
| 90 std::unordered_set<std::string> available_component_imes(component_ime_set); |
| 91 std::vector<std::string> component_ime_list; |
| 92 |
| 93 for (const auto& language_code : enabled_languages) { |
| 94 // Get all input methods for this language. |
| 95 std::vector<std::string> input_method_ids; |
| 96 manager->GetInputMethodUtil()->GetInputMethodIdsFromLanguageCode( |
| 97 language_code, chromeos::input_method::kAllInputMethods, |
| 98 &input_method_ids); |
| 99 // Append the enabled ones to the new list. Also remove them from the set |
| 100 // so they aren't duplicated for other languages. |
| 101 for (const auto& input_method_id : input_method_ids) { |
| 102 if (available_component_imes.count(input_method_id)) { |
| 103 component_ime_list.push_back(input_method_id); |
| 104 available_component_imes.erase(input_method_id); |
| 105 } |
| 106 } |
| 107 } |
| 108 |
| 109 return component_ime_list; |
| 110 } |
| 111 |
| 112 // Sorts the third-party IMEs by the order of their associated languages. |
| 113 std::vector<std::string> GetSortedExtensionIMEs( |
| 114 scoped_refptr<InputMethodManager::State> ime_state, |
| 115 const std::unordered_set<std::string>& extension_ime_set, |
| 116 PrefService* prefs) { |
| 117 std::vector<std::string> extension_ime_list; |
| 118 std::string preferred_languages = |
| 119 prefs->GetString(prefs::kLanguagePreferredLanguages); |
| 120 std::vector<std::string> enabled_languages = |
| 121 base::SplitString(preferred_languages, ",", base::TRIM_WHITESPACE, |
| 122 base::SPLIT_WANT_NONEMPTY); |
| 123 |
| 124 InputMethodDescriptors descriptors; |
| 125 ime_state->GetInputMethodExtensions(&descriptors); |
| 126 |
| 127 // Filter out the IMEs not in |extension_ime_set|. |
| 128 auto it = descriptors.begin(); |
| 129 while (it != descriptors.end()) { |
| 130 if (extension_ime_set.count(it->id()) == 0) |
| 131 it = descriptors.erase(it); |
| 132 else |
| 133 it++; |
| 134 } |
| 135 |
| 136 // For each language, add any candidate IMEs that support it. |
| 137 for (const auto& language : enabled_languages) { |
| 138 auto it = descriptors.begin(); |
| 139 while (it != descriptors.end() && descriptors.size()) { |
| 140 if (extension_ime_set.count(it->id()) && |
| 141 std::find(it->language_codes().begin(), it->language_codes().end(), |
| 142 language) != it->language_codes().end()) { |
| 143 extension_ime_list.push_back(it->id()); |
| 144 // Remove the added descriptor from the candidate list. |
| 145 it = descriptors.erase(it); |
| 146 } else { |
| 147 it++; |
| 148 } |
| 149 } |
| 150 } |
| 151 |
| 152 return extension_ime_list; |
| 153 } |
| 154 |
| 155 } // anonymous namespace |
| 50 #endif | 156 #endif |
| 51 | 157 |
| 52 LanguageSettingsPrivateGetLanguageListFunction:: | 158 LanguageSettingsPrivateGetLanguageListFunction:: |
| 53 LanguageSettingsPrivateGetLanguageListFunction() { | 159 LanguageSettingsPrivateGetLanguageListFunction() { |
| 54 } | 160 } |
| 55 | 161 |
| 56 LanguageSettingsPrivateGetLanguageListFunction:: | 162 LanguageSettingsPrivateGetLanguageListFunction:: |
| 57 ~LanguageSettingsPrivateGetLanguageListFunction() { | 163 ~LanguageSettingsPrivateGetLanguageListFunction() { |
| 58 } | 164 } |
| 59 | 165 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 82 for (const auto& code : language_codes) { | 188 for (const auto& code : language_codes) { |
| 83 base::string16 display_name = l10n_util::GetDisplayNameForLocale( | 189 base::string16 display_name = l10n_util::GetDisplayNameForLocale( |
| 84 code, app_locale, false); | 190 code, app_locale, false); |
| 85 base::string16 native_display_name = l10n_util::GetDisplayNameForLocale( | 191 base::string16 native_display_name = l10n_util::GetDisplayNameForLocale( |
| 86 code, code, false); | 192 code, code, false); |
| 87 language_map[display_name] = std::make_pair(code, native_display_name); | 193 language_map[display_name] = std::make_pair(code, native_display_name); |
| 88 } | 194 } |
| 89 | 195 |
| 90 // Get the list of available locales (display languages) and convert to a set. | 196 // Get the list of available locales (display languages) and convert to a set. |
| 91 const std::vector<std::string>& locales = l10n_util::GetAvailableLocales(); | 197 const std::vector<std::string>& locales = l10n_util::GetAvailableLocales(); |
| 92 const base::hash_set<std::string> locale_set( | 198 const std::unordered_set<std::string> locale_set(locales.begin(), |
| 93 locales.begin(), locales.end()); | 199 locales.end()); |
| 94 | 200 |
| 95 // Get the list of spell check languages and convert to a set. | 201 // Get the list of spell check languages and convert to a set. |
| 96 std::vector<std::string> spellcheck_languages; | 202 std::vector<std::string> spellcheck_languages; |
| 97 chrome::spellcheck_common::SpellCheckLanguages(&spellcheck_languages); | 203 chrome::spellcheck_common::SpellCheckLanguages(&spellcheck_languages); |
| 98 const base::hash_set<std::string> spellcheck_language_set( | 204 const std::unordered_set<std::string> spellcheck_language_set( |
| 99 spellcheck_languages.begin(), spellcheck_languages.end()); | 205 spellcheck_languages.begin(), spellcheck_languages.end()); |
| 100 | 206 |
| 101 // Get the list of translatable languages and convert to a set. | 207 // Get the list of translatable languages and convert to a set. |
| 102 std::vector<std::string> translate_languages; | 208 std::vector<std::string> translate_languages; |
| 103 translate::TranslateDownloadManager::GetSupportedLanguages( | 209 translate::TranslateDownloadManager::GetSupportedLanguages( |
| 104 &translate_languages); | 210 &translate_languages); |
| 105 const base::hash_set<std::string> translate_language_set( | 211 const std::unordered_set<std::string> translate_language_set( |
| 106 translate_languages.begin(), translate_languages.end()); | 212 translate_languages.begin(), translate_languages.end()); |
| 107 | 213 |
| 108 // Build the language list from the language map. | 214 // Build the language list from the language map. |
| 109 std::unique_ptr<base::ListValue> language_list(new base::ListValue); | 215 std::unique_ptr<base::ListValue> language_list(new base::ListValue); |
| 110 for (const auto& entry : language_map) { | 216 for (const auto& entry : language_map) { |
| 111 const base::string16& display_name = entry.first; | 217 const base::string16& display_name = entry.first; |
| 112 const LanguagePair& pair = entry.second; | 218 const LanguagePair& pair = entry.second; |
| 113 | 219 |
| 114 language_settings_private::Language language; | 220 language_settings_private::Language language; |
| 115 language.code = pair.first; | 221 language.code = pair.first; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 void PopulateInputMethodListFromDescriptors( | 406 void PopulateInputMethodListFromDescriptors( |
| 301 const InputMethodDescriptors& descriptors, | 407 const InputMethodDescriptors& descriptors, |
| 302 std::vector<language_settings_private::InputMethod>* input_methods) { | 408 std::vector<language_settings_private::InputMethod>* input_methods) { |
| 303 InputMethodManager* manager = InputMethodManager::Get(); | 409 InputMethodManager* manager = InputMethodManager::Get(); |
| 304 InputMethodUtil* util = manager->GetInputMethodUtil(); | 410 InputMethodUtil* util = manager->GetInputMethodUtil(); |
| 305 scoped_refptr<InputMethodManager::State> ime_state = | 411 scoped_refptr<InputMethodManager::State> ime_state = |
| 306 manager->GetActiveIMEState(); | 412 manager->GetActiveIMEState(); |
| 307 if (!ime_state.get()) | 413 if (!ime_state.get()) |
| 308 return; | 414 return; |
| 309 | 415 |
| 310 // Get the list of enabled IDs and convert to a set for membership testing. | 416 const std::unordered_set<std::string> active_ids(GetEnabledIMEs(ime_state)); |
| 311 const std::vector<std::string>& active_ids_list = | |
| 312 ime_state->GetActiveInputMethodIds(); | |
| 313 const std::set<std::string> active_ids( | |
| 314 active_ids_list.begin(), active_ids_list.end()); | |
| 315 | |
| 316 for (const auto& descriptor : descriptors) { | 417 for (const auto& descriptor : descriptors) { |
| 317 language_settings_private::InputMethod input_method; | 418 language_settings_private::InputMethod input_method; |
| 318 input_method.id = descriptor.id(); | 419 input_method.id = descriptor.id(); |
| 319 input_method.display_name = util->GetLocalizedDisplayName(descriptor); | 420 input_method.display_name = util->GetLocalizedDisplayName(descriptor); |
| 320 input_method.language_codes = descriptor.language_codes(); | 421 input_method.language_codes = descriptor.language_codes(); |
| 321 bool enabled = active_ids.find(input_method.id) != active_ids.end(); | 422 bool enabled = active_ids.count(input_method.id) > 0; |
| 322 if (enabled) | 423 if (enabled) |
| 323 input_method.enabled.reset(new bool(true)); | 424 input_method.enabled.reset(new bool(true)); |
| 324 if (descriptor.options_page_url().is_valid()) | 425 if (descriptor.options_page_url().is_valid()) |
| 325 input_method.has_options_page.reset(new bool(true)); | 426 input_method.has_options_page.reset(new bool(true)); |
| 326 input_methods->push_back(std::move(input_method)); | 427 input_methods->push_back(std::move(input_method)); |
| 327 } | 428 } |
| 328 } | 429 } |
| 329 #endif | 430 #endif |
| 330 | 431 |
| 331 LanguageSettingsPrivateGetInputMethodListsFunction:: | 432 LanguageSettingsPrivateGetInputMethodListsFunction:: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 359 PopulateInputMethodListFromDescriptors( | 460 PopulateInputMethodListFromDescriptors( |
| 360 ext_ime_descriptors, | 461 ext_ime_descriptors, |
| 361 &input_method_lists.third_party_extension_imes); | 462 &input_method_lists.third_party_extension_imes); |
| 362 } | 463 } |
| 363 | 464 |
| 364 return RespondNow(OneArgument(input_method_lists.ToValue())); | 465 return RespondNow(OneArgument(input_method_lists.ToValue())); |
| 365 #endif | 466 #endif |
| 366 } | 467 } |
| 367 | 468 |
| 368 LanguageSettingsPrivateAddInputMethodFunction:: | 469 LanguageSettingsPrivateAddInputMethodFunction:: |
| 369 LanguageSettingsPrivateAddInputMethodFunction() { | 470 LanguageSettingsPrivateAddInputMethodFunction() |
| 370 } | 471 : chrome_details_(this) {} |
| 371 | 472 |
| 372 LanguageSettingsPrivateAddInputMethodFunction:: | 473 LanguageSettingsPrivateAddInputMethodFunction:: |
| 373 ~LanguageSettingsPrivateAddInputMethodFunction() { | 474 ~LanguageSettingsPrivateAddInputMethodFunction() { |
| 374 } | 475 } |
| 375 | 476 |
| 376 ExtensionFunction::ResponseAction | 477 ExtensionFunction::ResponseAction |
| 377 LanguageSettingsPrivateAddInputMethodFunction::Run() { | 478 LanguageSettingsPrivateAddInputMethodFunction::Run() { |
| 378 return RespondNow(OneArgument(new base::FundamentalValue(true))); | 479 #if !defined(OS_CHROMEOS) |
| 480 EXTENSION_FUNCTION_VALIDATE(false); |
| 481 #else |
| 482 std::unique_ptr<language_settings_private::AddInputMethod::Params> params = |
| 483 language_settings_private::AddInputMethod::Params::Create(*args_); |
| 484 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 485 |
| 486 InputMethodManager* manager = InputMethodManager::Get(); |
| 487 scoped_refptr<InputMethodManager::State> ime_state = |
| 488 manager->GetActiveIMEState(); |
| 489 if (!ime_state.get()) |
| 490 return RespondNow(NoArguments()); |
| 491 |
| 492 std::string new_input_method_id = params->input_method_id; |
| 493 bool is_extension_ime = |
| 494 chromeos::extension_ime_util::IsExtensionIME(new_input_method_id); |
| 495 |
| 496 PrefService* prefs = chrome_details_.GetProfile()->GetPrefs(); |
| 497 const char* pref_name = is_extension_ime |
| 498 ? prefs::kLanguageEnabledExtensionImes |
| 499 : prefs::kLanguagePreloadEngines; |
| 500 |
| 501 // Get the input methods we are adding to. |
| 502 std::unordered_set<std::string> input_method_set( |
| 503 GetIMEsFromPref(prefs, pref_name)); |
| 504 |
| 505 // Add the new input method. |
| 506 input_method_set.insert(new_input_method_id); |
| 507 |
| 508 // Sort the new input method list by preferred languages. |
| 509 std::vector<std::string> input_method_list; |
| 510 if (is_extension_ime) { |
| 511 input_method_list = |
| 512 GetSortedExtensionIMEs(ime_state, input_method_set, prefs); |
| 513 } else { |
| 514 input_method_list = |
| 515 GetSortedComponentIMEs(manager, ime_state, input_method_set, prefs); |
| 516 } |
| 517 |
| 518 std::string input_methods = base::JoinString(input_method_list, ","); |
| 519 prefs->SetString(pref_name, input_methods); |
| 520 #endif |
| 521 return RespondNow(NoArguments()); |
| 379 } | 522 } |
| 380 | 523 |
| 381 LanguageSettingsPrivateRemoveInputMethodFunction:: | 524 LanguageSettingsPrivateRemoveInputMethodFunction:: |
| 382 LanguageSettingsPrivateRemoveInputMethodFunction() { | 525 LanguageSettingsPrivateRemoveInputMethodFunction() |
| 383 } | 526 : chrome_details_(this) {} |
| 384 | 527 |
| 385 LanguageSettingsPrivateRemoveInputMethodFunction:: | 528 LanguageSettingsPrivateRemoveInputMethodFunction:: |
| 386 ~LanguageSettingsPrivateRemoveInputMethodFunction() { | 529 ~LanguageSettingsPrivateRemoveInputMethodFunction() { |
| 387 } | 530 } |
| 388 | 531 |
| 389 ExtensionFunction::ResponseAction | 532 ExtensionFunction::ResponseAction |
| 390 LanguageSettingsPrivateRemoveInputMethodFunction::Run() { | 533 LanguageSettingsPrivateRemoveInputMethodFunction::Run() { |
| 391 return RespondNow(OneArgument(new base::FundamentalValue(true))); | 534 #if !defined(OS_CHROMEOS) |
| 535 EXTENSION_FUNCTION_VALIDATE(false); |
| 536 #else |
| 537 std::unique_ptr<language_settings_private::RemoveInputMethod::Params> params = |
| 538 language_settings_private::RemoveInputMethod::Params::Create(*args_); |
| 539 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 540 |
| 541 InputMethodManager* manager = InputMethodManager::Get(); |
| 542 scoped_refptr<InputMethodManager::State> ime_state = |
| 543 manager->GetActiveIMEState(); |
| 544 if (!ime_state.get()) |
| 545 return RespondNow(NoArguments()); |
| 546 |
| 547 std::string input_method_id = params->input_method_id; |
| 548 |
| 549 // Use the pref for the corresponding input method type. |
| 550 PrefService* prefs = chrome_details_.GetProfile()->GetPrefs(); |
| 551 const char* pref_name = |
| 552 chromeos::extension_ime_util::IsExtensionIME(input_method_id) |
| 553 ? prefs::kLanguageEnabledExtensionImes |
| 554 : prefs::kLanguagePreloadEngines; |
| 555 |
| 556 std::string input_method_ids = prefs->GetString(pref_name); |
| 557 std::vector<std::string> input_method_list = base::SplitString( |
| 558 input_method_ids, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 559 |
| 560 // Find and remove the matching input method id. |
| 561 const auto& pos = std::find(input_method_list.begin(), |
| 562 input_method_list.end(), input_method_id); |
| 563 if (pos != input_method_list.end()) { |
| 564 input_method_list.erase(pos); |
| 565 prefs->SetString(pref_name, base::JoinString(input_method_list, ",")); |
| 566 } |
| 567 #endif |
| 568 return RespondNow(NoArguments()); |
| 392 } | 569 } |
| 393 | 570 |
| 394 } // namespace extensions | 571 } // namespace extensions |
| OLD | NEW |