Chromium Code Reviews| 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 enabled component extension IMEs. | |
| 59 std::unordered_set<std::string> GetEnabledComponentIMEs( | |
| 60 scoped_refptr<InputMethodManager::State> ime_state) { | |
| 61 const std::vector<std::string>& component_imes( | |
| 62 ime_state->GetActiveInputMethodIds()); | |
|
Shu Chen
2016/04/20 06:38:33
GetActiveInputMethodIds() can include 3rd-party ex
michaelpg
2016/04/20 08:09:08
Oops. I didn't notice because GetSortedComponentIM
| |
| 63 return std::unordered_set<std::string>(component_imes.begin(), | |
| 64 component_imes.end()); | |
| 65 } | |
| 66 | |
| 67 // Returns the set of IDs of enabled third-party extension IMEs. | |
| 68 std::unordered_set<std::string> GetEnabledExtensionIMEs( | |
| 69 InputMethodManager* manager, | |
| 70 scoped_refptr<InputMethodManager::State> ime_state, | |
| 71 PrefService* prefs) { | |
| 72 std::vector<std::string> enabled_extension_imes = | |
| 73 base::SplitString(prefs->GetString(prefs::kLanguageEnabledExtensionImes), | |
| 74 ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 75 return std::unordered_set<std::string>(enabled_extension_imes.begin(), | |
| 76 enabled_extension_imes.end()); | |
| 77 } | |
| 78 | |
| 79 // Sorts the input methods by the order of their associated languages. For | |
| 80 // example, if the enabled language order is: | |
| 81 // - French | |
| 82 // - English | |
| 83 // then the French keyboard should come before the English keyboard. | |
| 84 std::vector<std::string> GetSortedComponentIMEs( | |
| 85 InputMethodManager* manager, | |
| 86 scoped_refptr<InputMethodManager::State> ime_state, | |
| 87 const std::unordered_set<std::string>& component_ime_set, | |
| 88 PrefService* prefs) { | |
| 89 std::vector<std::string> enabled_languages = | |
| 90 base::SplitString(prefs->GetString(prefs::kLanguagePreferredLanguages), | |
| 91 ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 92 | |
| 93 // Duplicate set for membership testing. | |
| 94 std::unordered_set<std::string> available_component_imes(component_ime_set); | |
| 95 std::vector<std::string> component_ime_list; | |
| 96 | |
| 97 for (const auto& language_code : enabled_languages) { | |
| 98 // Get all input methods for this language. | |
| 99 std::vector<std::string> input_method_ids; | |
| 100 manager->GetInputMethodUtil()->GetInputMethodIdsFromLanguageCode( | |
| 101 language_code, chromeos::input_method::kAllInputMethods, | |
| 102 &input_method_ids); | |
| 103 // Append the enabled ones to the new list. Also remove them from the set | |
| 104 // so they aren't duplicated for other languages. | |
| 105 for (const auto& input_method_id : input_method_ids) { | |
| 106 if (available_component_imes.count(input_method_id)) { | |
| 107 component_ime_list.push_back(input_method_id); | |
| 108 available_component_imes.erase(input_method_id); | |
| 109 } | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 return component_ime_list; | |
| 114 } | |
| 115 | |
| 116 // Sorts the third-party IMEs by the order of their associated languages. | |
| 117 std::vector<std::string> GetSortedExtensionIMEs( | |
| 118 scoped_refptr<InputMethodManager::State> ime_state, | |
| 119 const std::unordered_set<std::string>& extension_ime_set, | |
| 120 PrefService* prefs) { | |
| 121 std::vector<std::string> extension_ime_list; | |
| 122 std::string preferred_languages = | |
| 123 prefs->GetString(prefs::kLanguagePreferredLanguages); | |
| 124 std::vector<std::string> enabled_languages = | |
| 125 base::SplitString(preferred_languages, ",", base::TRIM_WHITESPACE, | |
| 126 base::SPLIT_WANT_NONEMPTY); | |
| 127 | |
| 128 InputMethodDescriptors descriptors; | |
| 129 ime_state->GetInputMethodExtensions(&descriptors); | |
| 130 | |
| 131 // Filter out the IMEs not in |extension_ime_set|. | |
| 132 auto it = descriptors.begin(); | |
| 133 while (it != descriptors.end()) { | |
| 134 if (extension_ime_set.count(it->id()) == 0) | |
| 135 it = descriptors.erase(it); | |
| 136 else | |
| 137 it++; | |
| 138 } | |
| 139 | |
| 140 // For each language, add any candidate IMEs that support it. | |
| 141 for (const auto& language : enabled_languages) { | |
| 142 auto it = descriptors.begin(); | |
| 143 while (it != descriptors.end() && descriptors.size()) { | |
| 144 if (extension_ime_set.count(it->id()) && | |
| 145 std::find(it->language_codes().begin(), it->language_codes().end(), | |
| 146 language) != it->language_codes().end()) { | |
| 147 extension_ime_list.push_back(it->id()); | |
| 148 // Remove the added descriptor from the candidate list. | |
| 149 it = descriptors.erase(it); | |
| 150 } else { | |
| 151 it++; | |
| 152 } | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 return extension_ime_list; | |
| 157 } | |
| 158 | |
| 159 } // anonymous namespace | |
| 50 #endif | 160 #endif |
| 51 | 161 |
| 52 LanguageSettingsPrivateGetLanguageListFunction:: | 162 LanguageSettingsPrivateGetLanguageListFunction:: |
| 53 LanguageSettingsPrivateGetLanguageListFunction() { | 163 LanguageSettingsPrivateGetLanguageListFunction() { |
| 54 } | 164 } |
| 55 | 165 |
| 56 LanguageSettingsPrivateGetLanguageListFunction:: | 166 LanguageSettingsPrivateGetLanguageListFunction:: |
| 57 ~LanguageSettingsPrivateGetLanguageListFunction() { | 167 ~LanguageSettingsPrivateGetLanguageListFunction() { |
| 58 } | 168 } |
| 59 | 169 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 82 for (const auto& code : language_codes) { | 192 for (const auto& code : language_codes) { |
| 83 base::string16 display_name = l10n_util::GetDisplayNameForLocale( | 193 base::string16 display_name = l10n_util::GetDisplayNameForLocale( |
| 84 code, app_locale, false); | 194 code, app_locale, false); |
| 85 base::string16 native_display_name = l10n_util::GetDisplayNameForLocale( | 195 base::string16 native_display_name = l10n_util::GetDisplayNameForLocale( |
| 86 code, code, false); | 196 code, code, false); |
| 87 language_map[display_name] = std::make_pair(code, native_display_name); | 197 language_map[display_name] = std::make_pair(code, native_display_name); |
| 88 } | 198 } |
| 89 | 199 |
| 90 // Get the list of available locales (display languages) and convert to a set. | 200 // Get the list of available locales (display languages) and convert to a set. |
| 91 const std::vector<std::string>& locales = l10n_util::GetAvailableLocales(); | 201 const std::vector<std::string>& locales = l10n_util::GetAvailableLocales(); |
| 92 const base::hash_set<std::string> locale_set( | 202 const std::unordered_set<std::string> locale_set(locales.begin(), |
| 93 locales.begin(), locales.end()); | 203 locales.end()); |
| 94 | 204 |
| 95 // Get the list of spell check languages and convert to a set. | 205 // Get the list of spell check languages and convert to a set. |
| 96 std::vector<std::string> spellcheck_languages; | 206 std::vector<std::string> spellcheck_languages; |
| 97 chrome::spellcheck_common::SpellCheckLanguages(&spellcheck_languages); | 207 chrome::spellcheck_common::SpellCheckLanguages(&spellcheck_languages); |
| 98 const base::hash_set<std::string> spellcheck_language_set( | 208 const std::unordered_set<std::string> spellcheck_language_set( |
| 99 spellcheck_languages.begin(), spellcheck_languages.end()); | 209 spellcheck_languages.begin(), spellcheck_languages.end()); |
| 100 | 210 |
| 101 // Get the list of translatable languages and convert to a set. | 211 // Get the list of translatable languages and convert to a set. |
| 102 std::vector<std::string> translate_languages; | 212 std::vector<std::string> translate_languages; |
| 103 translate::TranslateDownloadManager::GetSupportedLanguages( | 213 translate::TranslateDownloadManager::GetSupportedLanguages( |
| 104 &translate_languages); | 214 &translate_languages); |
| 105 const base::hash_set<std::string> translate_language_set( | 215 const std::unordered_set<std::string> translate_language_set( |
| 106 translate_languages.begin(), translate_languages.end()); | 216 translate_languages.begin(), translate_languages.end()); |
| 107 | 217 |
| 108 // Build the language list from the language map. | 218 // Build the language list from the language map. |
| 109 std::unique_ptr<base::ListValue> language_list(new base::ListValue); | 219 std::unique_ptr<base::ListValue> language_list(new base::ListValue); |
| 110 for (const auto& entry : language_map) { | 220 for (const auto& entry : language_map) { |
| 111 const base::string16& display_name = entry.first; | 221 const base::string16& display_name = entry.first; |
| 112 const LanguagePair& pair = entry.second; | 222 const LanguagePair& pair = entry.second; |
| 113 | 223 |
| 114 language_settings_private::Language language; | 224 language_settings_private::Language language; |
| 115 language.code = pair.first; | 225 language.code = pair.first; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 void PopulateInputMethodListFromDescriptors( | 410 void PopulateInputMethodListFromDescriptors( |
| 301 const InputMethodDescriptors& descriptors, | 411 const InputMethodDescriptors& descriptors, |
| 302 std::vector<language_settings_private::InputMethod>* input_methods) { | 412 std::vector<language_settings_private::InputMethod>* input_methods) { |
| 303 InputMethodManager* manager = InputMethodManager::Get(); | 413 InputMethodManager* manager = InputMethodManager::Get(); |
| 304 InputMethodUtil* util = manager->GetInputMethodUtil(); | 414 InputMethodUtil* util = manager->GetInputMethodUtil(); |
| 305 scoped_refptr<InputMethodManager::State> ime_state = | 415 scoped_refptr<InputMethodManager::State> ime_state = |
| 306 manager->GetActiveIMEState(); | 416 manager->GetActiveIMEState(); |
| 307 if (!ime_state.get()) | 417 if (!ime_state.get()) |
| 308 return; | 418 return; |
| 309 | 419 |
| 310 // Get the list of enabled IDs and convert to a set for membership testing. | 420 const std::unordered_set<std::string> active_ids( |
| 311 const std::vector<std::string>& active_ids_list = | 421 GetEnabledComponentIMEs(ime_state)); |
| 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) { | 422 for (const auto& descriptor : descriptors) { |
| 317 language_settings_private::InputMethod input_method; | 423 language_settings_private::InputMethod input_method; |
| 318 input_method.id = descriptor.id(); | 424 input_method.id = descriptor.id(); |
| 319 input_method.display_name = util->GetLocalizedDisplayName(descriptor); | 425 input_method.display_name = util->GetLocalizedDisplayName(descriptor); |
| 320 input_method.language_codes = descriptor.language_codes(); | 426 input_method.language_codes = descriptor.language_codes(); |
| 321 bool enabled = active_ids.find(input_method.id) != active_ids.end(); | 427 bool enabled = active_ids.count(input_method.id) > 0; |
| 322 if (enabled) | 428 if (enabled) |
| 323 input_method.enabled.reset(new bool(true)); | 429 input_method.enabled.reset(new bool(true)); |
| 324 if (descriptor.options_page_url().is_valid()) | 430 if (descriptor.options_page_url().is_valid()) |
| 325 input_method.has_options_page.reset(new bool(true)); | 431 input_method.has_options_page.reset(new bool(true)); |
| 326 input_methods->push_back(std::move(input_method)); | 432 input_methods->push_back(std::move(input_method)); |
| 327 } | 433 } |
| 328 } | 434 } |
| 329 #endif | 435 #endif |
| 330 | 436 |
| 331 LanguageSettingsPrivateGetInputMethodListsFunction:: | 437 LanguageSettingsPrivateGetInputMethodListsFunction:: |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 359 PopulateInputMethodListFromDescriptors( | 465 PopulateInputMethodListFromDescriptors( |
| 360 ext_ime_descriptors, | 466 ext_ime_descriptors, |
| 361 &input_method_lists.third_party_extension_imes); | 467 &input_method_lists.third_party_extension_imes); |
| 362 } | 468 } |
| 363 | 469 |
| 364 return RespondNow(OneArgument(input_method_lists.ToValue())); | 470 return RespondNow(OneArgument(input_method_lists.ToValue())); |
| 365 #endif | 471 #endif |
| 366 } | 472 } |
| 367 | 473 |
| 368 LanguageSettingsPrivateAddInputMethodFunction:: | 474 LanguageSettingsPrivateAddInputMethodFunction:: |
| 369 LanguageSettingsPrivateAddInputMethodFunction() { | 475 LanguageSettingsPrivateAddInputMethodFunction() |
| 370 } | 476 : chrome_details_(this) {} |
| 371 | 477 |
| 372 LanguageSettingsPrivateAddInputMethodFunction:: | 478 LanguageSettingsPrivateAddInputMethodFunction:: |
| 373 ~LanguageSettingsPrivateAddInputMethodFunction() { | 479 ~LanguageSettingsPrivateAddInputMethodFunction() { |
| 374 } | 480 } |
| 375 | 481 |
| 376 ExtensionFunction::ResponseAction | 482 ExtensionFunction::ResponseAction |
| 377 LanguageSettingsPrivateAddInputMethodFunction::Run() { | 483 LanguageSettingsPrivateAddInputMethodFunction::Run() { |
| 378 return RespondNow(OneArgument(new base::FundamentalValue(true))); | 484 #if !defined(OS_CHROMEOS) |
| 485 EXTENSION_FUNCTION_VALIDATE(false); | |
| 486 #else | |
| 487 std::unique_ptr<language_settings_private::AddInputMethod::Params> params = | |
| 488 language_settings_private::AddInputMethod::Params::Create(*args_); | |
| 489 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
| 490 | |
| 491 InputMethodManager* manager = InputMethodManager::Get(); | |
| 492 scoped_refptr<InputMethodManager::State> ime_state = | |
| 493 manager->GetActiveIMEState(); | |
| 494 if (!ime_state.get()) | |
| 495 return RespondNow(NoArguments()); | |
| 496 | |
| 497 std::string new_input_method_id = params->input_method_id; | |
| 498 bool is_extension_ime = | |
| 499 chromeos::extension_ime_util::IsExtensionIME(new_input_method_id); | |
| 500 | |
| 501 PrefService* prefs = chrome_details_.GetProfile()->GetPrefs(); | |
| 502 | |
| 503 // Get the input methods we are adding to. | |
| 504 std::unordered_set<std::string> input_method_set( | |
| 505 is_extension_ime ? GetEnabledExtensionIMEs(manager, ime_state, prefs) | |
| 506 : GetEnabledComponentIMEs(ime_state)); | |
| 507 | |
| 508 // Add the new input method. | |
| 509 input_method_set.insert(new_input_method_id); | |
| 510 | |
| 511 // Sort the new input method list by preferred languages. | |
| 512 std::vector<std::string> input_method_list; | |
| 513 if (is_extension_ime) { | |
| 514 input_method_list = | |
| 515 GetSortedExtensionIMEs(ime_state, input_method_set, prefs); | |
| 516 } else { | |
| 517 input_method_list = | |
| 518 GetSortedComponentIMEs(manager, ime_state, input_method_set, prefs); | |
| 519 } | |
| 520 | |
| 521 std::string input_methods = base::JoinString(input_method_list, ","); | |
| 522 prefs->SetString(is_extension_ime ? prefs::kLanguageEnabledExtensionImes | |
| 523 : prefs::kLanguagePreloadEngines, | |
| 524 input_methods); | |
| 525 #endif | |
| 526 return RespondNow(NoArguments()); | |
| 379 } | 527 } |
| 380 | 528 |
| 381 LanguageSettingsPrivateRemoveInputMethodFunction:: | 529 LanguageSettingsPrivateRemoveInputMethodFunction:: |
| 382 LanguageSettingsPrivateRemoveInputMethodFunction() { | 530 LanguageSettingsPrivateRemoveInputMethodFunction() |
| 383 } | 531 : chrome_details_(this) {} |
| 384 | 532 |
| 385 LanguageSettingsPrivateRemoveInputMethodFunction:: | 533 LanguageSettingsPrivateRemoveInputMethodFunction:: |
| 386 ~LanguageSettingsPrivateRemoveInputMethodFunction() { | 534 ~LanguageSettingsPrivateRemoveInputMethodFunction() { |
| 387 } | 535 } |
| 388 | 536 |
| 389 ExtensionFunction::ResponseAction | 537 ExtensionFunction::ResponseAction |
| 390 LanguageSettingsPrivateRemoveInputMethodFunction::Run() { | 538 LanguageSettingsPrivateRemoveInputMethodFunction::Run() { |
| 391 return RespondNow(OneArgument(new base::FundamentalValue(true))); | 539 #if !defined(OS_CHROMEOS) |
| 540 EXTENSION_FUNCTION_VALIDATE(false); | |
| 541 #else | |
| 542 std::unique_ptr<language_settings_private::RemoveInputMethod::Params> params = | |
| 543 language_settings_private::RemoveInputMethod::Params::Create(*args_); | |
| 544 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
| 545 | |
| 546 InputMethodManager* manager = InputMethodManager::Get(); | |
| 547 scoped_refptr<InputMethodManager::State> ime_state = | |
| 548 manager->GetActiveIMEState(); | |
| 549 if (!ime_state.get()) | |
| 550 return RespondNow(NoArguments()); | |
| 551 | |
| 552 std::string input_method_id = params->input_method_id; | |
| 553 | |
| 554 // Use the pref for the corresponding input method type. | |
| 555 PrefService* prefs = chrome_details_.GetProfile()->GetPrefs(); | |
| 556 const char* pref_name = | |
| 557 chromeos::extension_ime_util::IsExtensionIME(input_method_id) | |
| 558 ? prefs::kLanguageEnabledExtensionImes | |
| 559 : pref_name = prefs::kLanguagePreloadEngines; | |
| 560 | |
| 561 std::string input_method_ids = prefs->GetString(pref_name); | |
| 562 std::vector<std::string> input_method_list = base::SplitString( | |
| 563 input_method_ids, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 564 | |
| 565 // Find and remove the matching input method id. | |
| 566 const auto& pos = std::find(input_method_list.begin(), | |
| 567 input_method_list.end(), input_method_id); | |
| 568 if (pos != input_method_list.end()) { | |
| 569 input_method_list.erase(pos); | |
| 570 prefs->SetString(pref_name, base::JoinString(input_method_list, ",")); | |
| 571 } | |
| 572 #endif | |
| 573 return RespondNow(NoArguments()); | |
| 392 } | 574 } |
| 393 | 575 |
| 394 } // namespace extensions | 576 } // namespace extensions |
| OLD | NEW |