| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/ui/webui/chromeos/login/l10n_util.h" | 5 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/bind.h" |
| 14 #include "base/i18n/rtl.h" | 15 #include "base/i18n/rtl.h" |
| 16 #include "base/location.h" |
| 15 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/memory/ref_counted.h" |
| 19 #include "base/sequenced_task_runner.h" |
| 16 #include "base/strings/string16.h" | 20 #include "base/strings/string16.h" |
| 17 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 23 #include "base/task_runner_util.h" |
| 24 #include "base/threading/sequenced_worker_pool.h" |
| 19 #include "base/values.h" | 25 #include "base/values.h" |
| 20 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
| 21 #include "chrome/browser/chromeos/customization_document.h" | 27 #include "chrome/browser/chromeos/customization_document.h" |
| 22 #include "chrome/browser/chromeos/input_method/input_method_util.h" | 28 #include "chrome/browser/chromeos/input_method/input_method_util.h" |
| 23 #include "chromeos/ime/component_extension_ime_manager.h" | 29 #include "chromeos/ime/component_extension_ime_manager.h" |
| 24 #include "chromeos/ime/input_method_descriptor.h" | 30 #include "chromeos/ime/input_method_descriptor.h" |
| 25 #include "chromeos/ime/input_method_manager.h" | 31 #include "chromeos/ime/input_method_manager.h" |
| 32 #include "content/public/browser/browser_thread.h" |
| 26 #include "grit/generated_resources.h" | 33 #include "grit/generated_resources.h" |
| 27 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 28 | 35 |
| 29 namespace chromeos { | 36 namespace chromeos { |
| 30 | 37 |
| 31 namespace { | 38 namespace { |
| 32 | 39 |
| 33 base::DictionaryValue* CreateInputMethodsEntry( | 40 const char kSequenceToken[] = "chromeos_login_l10n_util"; |
| 41 |
| 42 scoped_ptr<base::DictionaryValue> CreateInputMethodsEntry( |
| 34 const input_method::InputMethodDescriptor& method, | 43 const input_method::InputMethodDescriptor& method, |
| 35 const std::string selected) { | 44 const std::string selected) { |
| 36 input_method::InputMethodUtil* util = | 45 input_method::InputMethodUtil* util = |
| 37 input_method::InputMethodManager::Get()->GetInputMethodUtil(); | 46 input_method::InputMethodManager::Get()->GetInputMethodUtil(); |
| 38 const std::string& ime_id = method.id(); | 47 const std::string& ime_id = method.id(); |
| 39 scoped_ptr<base::DictionaryValue> input_method(new base::DictionaryValue); | 48 scoped_ptr<base::DictionaryValue> input_method(new base::DictionaryValue); |
| 40 input_method->SetString("value", ime_id); | 49 input_method->SetString("value", ime_id); |
| 41 input_method->SetString("title", util->GetInputMethodLongName(method)); | 50 input_method->SetString("title", util->GetInputMethodLongName(method)); |
| 42 input_method->SetBoolean("selected", ime_id == selected); | 51 input_method->SetBoolean("selected", ime_id == selected); |
| 43 return input_method.release(); | 52 return input_method.Pass(); |
| 44 } | 53 } |
| 45 | 54 |
| 46 // Returns true if element was inserted. | 55 // Returns true if element was inserted. |
| 47 bool InsertString(const std::string& str, std::set<std::string>& to) { | 56 bool InsertString(const std::string& str, std::set<std::string>& to) { |
| 48 const std::pair<std::set<std::string>::iterator, bool> result = | 57 const std::pair<std::set<std::string>::iterator, bool> result = |
| 49 to.insert(str); | 58 to.insert(str); |
| 50 return result.second; | 59 return result.second; |
| 51 } | 60 } |
| 52 | 61 |
| 53 void AddOptgroupOtherLayouts(base::ListValue* input_methods_list) { | 62 void AddOptgroupOtherLayouts(base::ListValue* input_methods_list) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 dictionary->SetString("code", pair.first); | 272 dictionary->SetString("code", pair.first); |
| 264 dictionary->SetString("displayName", out_display_names[i]); | 273 dictionary->SetString("displayName", out_display_names[i]); |
| 265 dictionary->SetString("textDirection", directionality); | 274 dictionary->SetString("textDirection", directionality); |
| 266 dictionary->SetString("nativeDisplayName", pair.second); | 275 dictionary->SetString("nativeDisplayName", pair.second); |
| 267 language_list->Append(dictionary); | 276 language_list->Append(dictionary); |
| 268 } | 277 } |
| 269 | 278 |
| 270 return language_list.Pass(); | 279 return language_list.Pass(); |
| 271 } | 280 } |
| 272 | 281 |
| 282 // Invokes |callback| with a list of keyboard layouts that can be used for |
| 283 // |resolved_locale|. |
| 284 void GetKeyboardLayoutsForResolvedLocale( |
| 285 const GetKeyboardLayoutsForLocaleCallback& callback, |
| 286 const std::string& resolved_locale) { |
| 287 input_method::InputMethodUtil* util = |
| 288 input_method::InputMethodManager::Get()->GetInputMethodUtil(); |
| 289 std::vector<std::string> layouts = util->GetHardwareInputMethodIds(); |
| 290 std::vector<std::string> layouts_from_locale; |
| 291 util->GetInputMethodIdsFromLanguageCode( |
| 292 resolved_locale, |
| 293 input_method::kKeyboardLayoutsOnly, |
| 294 &layouts_from_locale); |
| 295 layouts.insert(layouts.end(), layouts_from_locale.begin(), |
| 296 layouts_from_locale.end()); |
| 297 |
| 298 std::string selected; |
| 299 if (!layouts_from_locale.empty()) { |
| 300 selected = |
| 301 util->GetInputMethodDescriptorFromId(layouts_from_locale[0])->id(); |
| 302 } |
| 303 |
| 304 scoped_ptr<base::ListValue> input_methods_list(new base::ListValue); |
| 305 std::set<std::string> input_methods_added; |
| 306 for (std::vector<std::string>::const_iterator it = layouts.begin(); |
| 307 it != layouts.end(); ++it) { |
| 308 const input_method::InputMethodDescriptor* ime = |
| 309 util->GetInputMethodDescriptorFromId(*it); |
| 310 if (!InsertString(ime->id(), input_methods_added)) |
| 311 continue; |
| 312 input_methods_list->Append( |
| 313 CreateInputMethodsEntry(*ime, selected).release()); |
| 314 } |
| 315 |
| 316 callback.Run(input_methods_list.Pass()); |
| 317 } |
| 318 |
| 273 } // namespace | 319 } // namespace |
| 274 | 320 |
| 275 const char kMostRelevantLanguagesDivider[] = "MOST_RELEVANT_LANGUAGES_DIVIDER"; | 321 const char kMostRelevantLanguagesDivider[] = "MOST_RELEVANT_LANGUAGES_DIVIDER"; |
| 276 | 322 |
| 277 scoped_ptr<base::ListValue> GetUILanguageList( | 323 scoped_ptr<base::ListValue> GetUILanguageList( |
| 278 const std::vector<std::string>* most_relevant_language_codes, | 324 const std::vector<std::string>* most_relevant_language_codes, |
| 279 const std::string& selected) { | 325 const std::string& selected) { |
| 280 ComponentExtensionIMEManager* manager = | 326 ComponentExtensionIMEManager* manager = |
| 281 input_method::InputMethodManager::Get()-> | 327 input_method::InputMethodManager::Get()-> |
| 282 GetComponentExtensionIMEManager(); | 328 GetComponentExtensionIMEManager(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 | 398 |
| 353 for (std::vector<std::string>::const_iterator i = | 399 for (std::vector<std::string>::const_iterator i = |
| 354 hardware_login_input_methods.begin(); | 400 hardware_login_input_methods.begin(); |
| 355 i != hardware_login_input_methods.end(); | 401 i != hardware_login_input_methods.end(); |
| 356 ++i) { | 402 ++i) { |
| 357 const input_method::InputMethodDescriptor* ime = | 403 const input_method::InputMethodDescriptor* ime = |
| 358 util->GetInputMethodDescriptorFromId(*i); | 404 util->GetInputMethodDescriptorFromId(*i); |
| 359 // Do not crash in case of misconfiguration. | 405 // Do not crash in case of misconfiguration. |
| 360 if (ime) { | 406 if (ime) { |
| 361 input_methods_added.insert(*i); | 407 input_methods_added.insert(*i); |
| 362 input_methods_list->Append(CreateInputMethodsEntry(*ime, selected)); | 408 input_methods_list->Append( |
| 409 CreateInputMethodsEntry(*ime, selected).release()); |
| 363 } else { | 410 } else { |
| 364 NOTREACHED(); | 411 NOTREACHED(); |
| 365 } | 412 } |
| 366 } | 413 } |
| 367 | 414 |
| 368 bool optgroup_added = false; | 415 bool optgroup_added = false; |
| 369 for (size_t i = 0; i < input_methods->size(); ++i) { | 416 for (size_t i = 0; i < input_methods->size(); ++i) { |
| 370 // Makes sure the id is in legacy xkb id format. | 417 // Makes sure the id is in legacy xkb id format. |
| 371 const std::string& ime_id = (*input_methods)[i].id(); | 418 const std::string& ime_id = (*input_methods)[i].id(); |
| 372 if (!InsertString(ime_id, input_methods_added)) | 419 if (!InsertString(ime_id, input_methods_added)) |
| 373 continue; | 420 continue; |
| 374 if (!optgroup_added) { | 421 if (!optgroup_added) { |
| 375 optgroup_added = true; | 422 optgroup_added = true; |
| 376 AddOptgroupOtherLayouts(input_methods_list.get()); | 423 AddOptgroupOtherLayouts(input_methods_list.get()); |
| 377 } | 424 } |
| 378 input_methods_list->Append(CreateInputMethodsEntry((*input_methods)[i], | 425 input_methods_list->Append(CreateInputMethodsEntry((*input_methods)[i], |
| 379 selected)); | 426 selected).release()); |
| 380 } | 427 } |
| 381 | 428 |
| 382 // "xkb:us::eng" should always be in the list of available layouts. | 429 // "xkb:us::eng" should always be in the list of available layouts. |
| 383 const std::string us_keyboard_id = | 430 const std::string us_keyboard_id = |
| 384 util->GetFallbackInputMethodDescriptor().id(); | 431 util->GetFallbackInputMethodDescriptor().id(); |
| 385 if (input_methods_added.find(us_keyboard_id) == input_methods_added.end()) { | 432 if (input_methods_added.find(us_keyboard_id) == input_methods_added.end()) { |
| 386 const input_method::InputMethodDescriptor* us_eng_descriptor = | 433 const input_method::InputMethodDescriptor* us_eng_descriptor = |
| 387 util->GetInputMethodDescriptorFromId(us_keyboard_id); | 434 util->GetInputMethodDescriptorFromId(us_keyboard_id); |
| 388 DCHECK(us_eng_descriptor); | 435 DCHECK(us_eng_descriptor); |
| 389 if (!optgroup_added) { | 436 if (!optgroup_added) { |
| 390 optgroup_added = true; | 437 optgroup_added = true; |
| 391 AddOptgroupOtherLayouts(input_methods_list.get()); | 438 AddOptgroupOtherLayouts(input_methods_list.get()); |
| 392 } | 439 } |
| 393 input_methods_list->Append(CreateInputMethodsEntry(*us_eng_descriptor, | 440 input_methods_list->Append(CreateInputMethodsEntry(*us_eng_descriptor, |
| 394 selected)); | 441 selected).release()); |
| 395 } | 442 } |
| 396 return input_methods_list.Pass(); | 443 return input_methods_list.Pass(); |
| 397 } | 444 } |
| 398 | 445 |
| 399 scoped_ptr<base::ListValue> GetKeyboardLayoutsForLocale( | 446 void GetKeyboardLayoutsForLocale( |
| 447 const GetKeyboardLayoutsForLocaleCallback& callback, |
| 400 const std::string& locale) { | 448 const std::string& locale) { |
| 401 input_method::InputMethodUtil* util = | 449 base::SequencedWorkerPool* worker_pool = |
| 402 input_method::InputMethodManager::Get()->GetInputMethodUtil(); | 450 content::BrowserThread::GetBlockingPool(); |
| 403 std::vector<std::string> layouts = util->GetHardwareInputMethodIds(); | 451 scoped_refptr<base::SequencedTaskRunner> background_task_runner = |
| 404 std::vector<std::string> layouts_from_locale; | 452 worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
| 405 util->GetInputMethodIdsFromLanguageCode( | 453 worker_pool->GetNamedSequenceToken(kSequenceToken), |
| 406 l10n_util::GetApplicationLocale(locale), | 454 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 407 input_method::kKeyboardLayoutsOnly, | |
| 408 &layouts_from_locale); | |
| 409 layouts.insert(layouts.end(), layouts_from_locale.begin(), | |
| 410 layouts_from_locale.end()); | |
| 411 | 455 |
| 412 std::string selected; | 456 // Resolve |locale| on a background thread, then continue on the current |
| 413 if (!layouts_from_locale.empty()) { | 457 // thread. |
| 414 selected = | 458 base::PostTaskAndReplyWithResult( |
| 415 util->GetInputMethodDescriptorFromId(layouts_from_locale[0])->id(); | 459 background_task_runner, |
| 416 } | 460 FROM_HERE, |
| 461 base::Bind(&l10n_util::GetApplicationLocale, |
| 462 locale), |
| 463 base::Bind(&GetKeyboardLayoutsForResolvedLocale, |
| 464 callback)); |
| 465 } |
| 417 | 466 |
| 418 scoped_ptr<base::ListValue> input_methods_list(new base::ListValue); | 467 scoped_ptr<base::DictionaryValue> GetCurrentKeyboardLayout() { |
| 419 std::set<std::string> input_methods_added; | 468 const input_method::InputMethodDescriptor current_input_method = |
| 420 for (std::vector<std::string>::const_iterator it = layouts.begin(); | 469 input_method::InputMethodManager::Get()->GetCurrentInputMethod(); |
| 421 it != layouts.end(); ++it) { | 470 return CreateInputMethodsEntry(current_input_method, |
| 422 const input_method::InputMethodDescriptor* ime = | 471 current_input_method.id()); |
| 423 util->GetInputMethodDescriptorFromId(*it); | |
| 424 if (!InsertString(ime->id(), input_methods_added)) | |
| 425 continue; | |
| 426 input_methods_list->Append(CreateInputMethodsEntry(*ime, selected)); | |
| 427 } | |
| 428 return input_methods_list.Pass(); | |
| 429 } | 472 } |
| 430 | 473 |
| 431 } // namespace chromeos | 474 } // namespace chromeos |
| OLD | NEW |