summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoralemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-13 20:08:43 +0000
committeralemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-13 20:08:43 +0000
commitfcb10a48bfc2b89f71d239efa2028a06455d7b89 (patch)
tree5924f942f66a6a63ae9d46e1a62ef405bce9ba6f /chrome
parentdb546e9d54332be583e30a1f0f0a99ba7e6628a2 (diff)
downloadchromium_src-fcb10a48bfc2b89f71d239efa2028a06455d7b89.zip
chromium_src-fcb10a48bfc2b89f71d239efa2028a06455d7b89.tar.gz
chromium_src-fcb10a48bfc2b89f71d239efa2028a06455d7b89.tar.bz2
Reload ResourceBundle on locale change through BlockingPool (no IO on UI thread
anymore). Move all SwitchLocale() code to chrome/browser/chromeos/base/locale_util.* (Drop unused language_switch_menu.*) BUG=126950 TEST=manual Review URL: https://codereview.chromium.org/27032004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234882 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chromeos/base/locale_util.cc90
-rw-r--r--chrome/browser/chromeos/base/locale_util.h47
-rw-r--r--chrome/browser/chromeos/login/fake_user_manager.cc7
-rw-r--r--chrome/browser/chromeos/login/fake_user_manager.h6
-rw-r--r--chrome/browser/chromeos/login/input_events_blocker.cc39
-rw-r--r--chrome/browser/chromeos/login/input_events_blocker.h32
-rw-r--r--chrome/browser/chromeos/login/language_switch_menu.cc203
-rw-r--r--chrome/browser/chromeos/login/language_switch_menu.h76
-rw-r--r--chrome/browser/chromeos/login/login_display_host_impl.cc135
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc72
-rw-r--r--chrome/browser/chromeos/login/mock_user_manager.cc7
-rw-r--r--chrome/browser/chromeos/login/mock_user_manager.h6
-rw-r--r--chrome/browser/chromeos/login/screens/network_screen.h1
-rw-r--r--chrome/browser/chromeos/login/user_manager.h9
-rw-r--r--chrome/browser/chromeos/login/user_manager_impl.cc24
-rw-r--r--chrome/browser/chromeos/login/user_manager_impl.h6
-rw-r--r--chrome/browser/chromeos/login/wizard_controller_browsertest.cc45
-rw-r--r--chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc57
-rw-r--r--chrome/browser/ui/webui/chromeos/login/network_screen_handler.h11
-rw-r--r--chrome/chrome_browser_chromeos.gypi6
20 files changed, 506 insertions, 373 deletions
diff --git a/chrome/browser/chromeos/base/locale_util.cc b/chrome/browser/chromeos/base/locale_util.cc
new file mode 100644
index 0000000..4a931fe
--- /dev/null
+++ b/chrome/browser/chromeos/base/locale_util.cc
@@ -0,0 +1,90 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/base/locale_util.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chromeos/ime/input_method_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/platform_font_pango.h"
+
+namespace chromeos {
+
+namespace {
+
+struct SwitchLanguageData {
+ SwitchLanguageData(const std::string& locale,
+ const bool enableLocaleKeyboardLayouts,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback)
+ : callback(callback.Pass()),
+ locale(locale),
+ enableLocaleKeyboardLayouts(enableLocaleKeyboardLayouts),
+ success(false) {}
+
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback;
+
+ const std::string locale;
+ const bool enableLocaleKeyboardLayouts;
+ std::string loaded_locale;
+ bool success;
+};
+
+// Runs on SequencedWorkerPool thread under PostTaskAndReply().
+// So data is owned by "Reply" part of PostTaskAndReply() process.
+void SwitchLanguageDoReloadLocale(SwitchLanguageData* data) {
+ DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ data->loaded_locale =
+ ResourceBundle::GetSharedInstance().ReloadLocaleResources(data->locale);
+
+ data->success = !data->loaded_locale.empty();
+
+ ResourceBundle::GetSharedInstance().ReloadFonts();
+}
+
+// Callback after SwitchLanguageDoReloadLocale() back in UI thread.
+void FinishSwitchLanguage(scoped_ptr<SwitchLanguageData> data) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (data->success) {
+ g_browser_process->SetApplicationLocale(data->loaded_locale);
+
+ if (data->enableLocaleKeyboardLayouts) {
+ // If we have switched the locale, enable the keyboard layouts that
+ // are necessary for the new locale. Change the current input method
+ // to the hardware keyboard layout since the input method currently in
+ // use may not be supported by the new locale (3rd parameter).
+ input_method::InputMethodManager* manager =
+ input_method::InputMethodManager::Get();
+ manager->EnableLayouts(
+ data->locale,
+ manager->GetInputMethodUtil()->GetHardwareInputMethodId());
+ }
+ }
+ gfx::PlatformFontPango::ReloadDefaultFont();
+ if (data->callback)
+ data->callback->Run(data->locale, data->loaded_locale, data->success);
+}
+
+} // namespace
+
+namespace locale_util {
+
+void SwitchLanguage(const std::string& locale,
+ bool enableLocaleKeyboardLayouts,
+ scoped_ptr<SwitchLanguageCallback> callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ scoped_ptr<SwitchLanguageData> data(new SwitchLanguageData(
+ locale, enableLocaleKeyboardLayouts, callback.Pass()));
+ base::Closure reloader(
+ base::Bind(&SwitchLanguageDoReloadLocale, base::Unretained(data.get())));
+ content::BrowserThread::PostBlockingPoolTaskAndReply(
+ FROM_HERE,
+ reloader,
+ base::Bind(&FinishSwitchLanguage, base::Passed(data.Pass())));
+}
+
+} // namespace locale_util
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/base/locale_util.h b/chrome/browser/chromeos/base/locale_util.h
new file mode 100644
index 0000000..e260c20
--- /dev/null
+++ b/chrome/browser/chromeos/base/locale_util.h
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains utility functions for locale change.
+
+#ifndef CHROME_BROWSER_CHROMEOS_BASE_LOCALE_UTIL_H_
+#define CHROME_BROWSER_CHROMEOS_BASE_LOCALE_UTIL_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace base {
+
+template <typename T>
+class Callback;
+
+} // namespace base
+
+namespace chromeos {
+namespace locale_util {
+
+// This callback is called on UI thread, when ReloadLocaleResources() is
+// completed on BlockingPool.
+// Arguments:
+// locale - (copy of) locale argument to SwitchLanguage(). Expected locale.
+// loaded_locale - actual locale name loaded.
+// success - if locale load succeeded.
+// (const std::string* locale, const std::string* loaded_locale, bool success)
+typedef base::Callback<void(const std::string&, const std::string&, bool)>
+ SwitchLanguageCallback;
+
+// This function updates input methods only if requested. In general you want
+// "enableLocaleKeyboardLayouts=true".
+// Note: in case of "enableLocaleKeyboardLayouts=false" the input
+// method currently in use may not be supported by the new locale. (i.e.
+// using new locale with unsupported input method may lead to undefined
+// behavior; use "enableLocaleKeyboardLayouts=false" with caution)
+void SwitchLanguage(const std::string& locale,
+ bool enableLocaleKeyboardLayouts,
+ scoped_ptr<SwitchLanguageCallback> callback);
+
+} // namespace locale_util
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_BASE_LOCALE_UTIL_H_
diff --git a/chrome/browser/chromeos/login/fake_user_manager.cc b/chrome/browser/chromeos/login/fake_user_manager.cc
index f32cc85..f5ce9df 100644
--- a/chrome/browser/chromeos/login/fake_user_manager.cc
+++ b/chrome/browser/chromeos/login/fake_user_manager.cc
@@ -274,8 +274,11 @@ base::FilePath FakeUserManager::GetUserProfileDir(
return base::FilePath();
}
-void FakeUserManager::RespectLocalePreference(Profile* profile,
- const User* user) const {
+bool FakeUserManager::RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
+ return false;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/fake_user_manager.h b/chrome/browser/chromeos/login/fake_user_manager.h
index 8c126d1..c124a30 100644
--- a/chrome/browser/chromeos/login/fake_user_manager.h
+++ b/chrome/browser/chromeos/login/fake_user_manager.h
@@ -115,8 +115,10 @@ class FakeUserManager : public UserManager {
virtual bool AreLocallyManagedUsersAllowed() const OVERRIDE;
virtual base::FilePath GetUserProfileDir(const std::string& email) const
OVERRIDE;
- virtual void RespectLocalePreference(Profile* profile, const User* user) const
- OVERRIDE;
+ virtual bool RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const OVERRIDE;
void set_owner_email(const std::string& owner_email) {
owner_email_ = owner_email;
diff --git a/chrome/browser/chromeos/login/input_events_blocker.cc b/chrome/browser/chromeos/login/input_events_blocker.cc
new file mode 100644
index 0000000..bd261bc
--- /dev/null
+++ b/chrome/browser/chromeos/login/input_events_blocker.cc
@@ -0,0 +1,39 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/input_events_blocker.h"
+
+#include "ash/shell.h"
+#include "base/logging.h"
+#include "ui/events/event.h"
+
+namespace chromeos {
+
+InputEventsBlocker::InputEventsBlocker() {
+ ash::Shell::GetInstance()->PrependPreTargetHandler(this);
+ VLOG(1) << "InputEventsBlocker " << this << " created.";
+}
+
+InputEventsBlocker::~InputEventsBlocker() {
+ ash::Shell::GetInstance()->RemovePreTargetHandler(this);
+ VLOG(1) << "InputEventsBlocker " << this << " destroyed.";
+}
+
+void InputEventsBlocker::OnKeyEvent(ui::KeyEvent* event) {
+ event->StopPropagation();
+}
+
+void InputEventsBlocker::OnMouseEvent(ui::MouseEvent* event) {
+ event->StopPropagation();
+}
+
+void InputEventsBlocker::OnTouchEvent(ui::TouchEvent* event) {
+ event->StopPropagation();
+}
+
+void InputEventsBlocker::OnGestureEvent(ui::GestureEvent* event) {
+ event->StopPropagation();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/input_events_blocker.h b/chrome/browser/chromeos/login/input_events_blocker.h
new file mode 100644
index 0000000..c788642
--- /dev/null
+++ b/chrome/browser/chromeos/login/input_events_blocker.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_INPUT_EVENTS_BLOCKER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_INPUT_EVENTS_BLOCKER_H_
+
+#include "base/compiler_specific.h"
+#include "ui/events/event_handler.h"
+
+namespace chromeos {
+
+// A simple input events blocker that just makes device unresponsive.
+// Should be used only for a (very) short time lock as it's confusing to the
+// user.
+class InputEventsBlocker : public ui::EventHandler {
+ public:
+ InputEventsBlocker();
+ virtual ~InputEventsBlocker();
+
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputEventsBlocker);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_LOGIN_INPUT_EVENTS_BLOCKER_H_
diff --git a/chrome/browser/chromeos/login/language_switch_menu.cc b/chrome/browser/chromeos/login/language_switch_menu.cc
deleted file mode 100644
index c30a968..0000000
--- a/chrome/browser/chromeos/login/language_switch_menu.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
-
-#include "ash/shell.h"
-#include "base/i18n/rtl.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/login/language_list.h"
-#include "chrome/browser/chromeos/login/screens/screen_observer.h"
-#include "chrome/common/pref_names.h"
-#include "chromeos/ime/input_method_manager.h"
-#include "grit/generated_resources.h"
-#include "grit/platform_locale_settings.h"
-#include "ui/aura/root_window.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/platform_font_pango.h"
-#include "ui/views/controls/button/menu_button.h"
-#include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/menu/submenu_view.h"
-#include "ui/views/widget/widget.h"
-
-namespace {
-
-const int kLanguageMainMenuSize = 5;
-// TODO(glotov): need to specify the list as a part of the image customization.
-const char kLanguagesTopped[] = "es,it,de,fr,en-US";
-const int kMoreLanguagesSubMenu = 200;
-
-// Notifies all views::Widgets attached to |window|'s hierarchy that their
-// locale has changed.
-void NotifyLocaleChanged(aura::Window* window) {
- views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
- if (widget)
- widget->LocaleChanged();
-
- const aura::Window::Windows& children = window->children();
- for (aura::Window::Windows::const_iterator it = children.begin();
- it != children.end(); ++it) {
- NotifyLocaleChanged(*it);
- }
-}
-
-} // namespace
-
-namespace chromeos {
-
-LanguageSwitchMenu::LanguageSwitchMenu()
- : menu_(new views::MenuItemView(this)),
- menu_runner_(new views::MenuRunner(menu_)) {
-}
-
-LanguageSwitchMenu::~LanguageSwitchMenu() {}
-
-void LanguageSwitchMenu::InitLanguageMenu() {
- // Update LanguageList to contain entries in current locale.
- language_list_.reset(new LanguageList);
- language_list_->CopySpecifiedLanguagesUp(kLanguagesTopped);
-
- // Clear older menu items.
- if (menu_->HasSubmenu()) {
- const int old_count = menu_->GetSubmenu()->child_count();
- for (int i = 0; i < old_count; ++i)
- menu_->RemoveMenuItemAt(0);
- }
-
- // Fill menu items with updated items.
- for (int line = 0; line != kLanguageMainMenuSize; line++) {
- menu_->AppendMenuItemWithLabel(line,
- language_list_->GetLanguageNameAt(line));
- }
-
- menu_->AppendSeparator();
- views::MenuItemView* submenu = menu_->AppendSubMenu(
- kMoreLanguagesSubMenu,
- l10n_util::GetStringUTF16(IDS_LANGUAGES_MORE));
-
- for (int line = kLanguageMainMenuSize;
- line != language_list_->languages_count(); ++line) {
- submenu->AppendMenuItemWithLabel(line,
- language_list_->GetLanguageNameAt(line));
- }
-
- menu_->ChildrenChanged();
-}
-
-string16 LanguageSwitchMenu::GetCurrentLocaleName() const {
- DCHECK(g_browser_process);
- const std::string locale = g_browser_process->GetApplicationLocale();
- int index = language_list_->GetIndexFromLocale(locale);
- CHECK_NE(-1, index) << "Unknown locale: " << locale;
- return language_list_->GetLanguageNameAt(index);
-};
-
-void LanguageSwitchMenu::SetFirstLevelMenuWidth(int width) {
- DCHECK(menu_ != NULL);
-
- menu_->GetSubmenu()->set_minimum_preferred_width(width);
-}
-
-// static
-bool LanguageSwitchMenu::SwitchLanguage(const std::string& locale) {
- DCHECK(g_browser_process);
- if (g_browser_process->GetApplicationLocale() == locale) {
- return false;
- }
- // TODO(markusheintz): Change the if condition to prefs->IsUserModifiable()
- // once Mattias landed his pending patch.
- if (!g_browser_process->local_state()->
- IsManagedPreference(prefs::kApplicationLocale)) {
- std::string loaded_locale;
- {
- // Reloading resource bundle causes us to do blocking IO on UI thread.
- // Temporarily allow it until we fix http://crosbug.com/11102
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- // Switch the locale.
- loaded_locale =
- ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
- }
- CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
-
- LoadFontsForCurrentLocale();
-
- // The following line does not seem to affect locale anyhow. Maybe in
- // future..
- g_browser_process->SetApplicationLocale(locale);
-
- PrefService* prefs = g_browser_process->local_state();
- prefs->SetString(prefs::kApplicationLocale, locale);
-
- return true;
- }
- return false;
-}
-
-// static
-void LanguageSwitchMenu::LoadFontsForCurrentLocale() {
- // Switch the font.
- gfx::PlatformFontPango::ReloadDefaultFont();
- ResourceBundle::GetSharedInstance().ReloadFonts();
-}
-
-// static
-void LanguageSwitchMenu::SwitchLanguageAndEnableKeyboardLayouts(
- const std::string& locale) {
- if (SwitchLanguage(locale)) {
- // If we have switched the locale, enable the keyboard layouts that
- // are necessary for the new locale. Change the current input method
- // to the hardware keyboard layout since the input method currently in
- // use may not be supported by the new locale (3rd parameter).
- input_method::InputMethodManager* manager =
- input_method::InputMethodManager::Get();
- manager->EnableLayouts(
- locale,
- manager->GetInputMethodUtil()->GetHardwareInputMethodId());
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// views::MenuButtonListener implementation.
-
-void LanguageSwitchMenu::OnMenuButtonClicked(views::View* source,
- const gfx::Point& point) {
- DCHECK(menu_ != NULL);
- views::MenuButton* button = static_cast<views::MenuButton*>(source);
-
- // We align on the left edge of the button for non RTL case.
- // MenuButton passes in |point| the lower left corner for RTL and the
- // lower right corner for non-RTL (with menu_offset applied).
- const int reverse_offset = button->width() + button->menu_offset().x() * 2;
- gfx::Point new_pt(point);
- if (base::i18n::IsRTL())
- new_pt.set_x(point.x() + reverse_offset);
- else
- new_pt.set_x(point.x() - reverse_offset);
-
- if (menu_runner_->RunMenuAt(button->GetWidget(), button,
- gfx::Rect(new_pt, gfx::Size()), views::MenuItemView::TOPLEFT,
- ui::MENU_SOURCE_NONE, views::MenuRunner::HAS_MNEMONICS) ==
- views::MenuRunner::MENU_DELETED)
- return;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// views::MenuDelegate implementation.
-
-void LanguageSwitchMenu::ExecuteCommand(int command_id, int event_flags) {
- const std::string locale = language_list_->GetLocaleFromIndex(command_id);
- // Here, we should enable keyboard layouts associated with the locale so
- // that users can use those keyboard layouts on the login screen.
- SwitchLanguageAndEnableKeyboardLayouts(locale);
- InitLanguageMenu();
- NotifyLocaleChanged(ash::Shell::GetPrimaryRootWindow());
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/language_switch_menu.h b/chrome/browser/chromeos/login/language_switch_menu.h
deleted file mode 100644
index e95f7fa..0000000
--- a/chrome/browser/chromeos/login/language_switch_menu.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LANGUAGE_SWITCH_MENU_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_LANGUAGE_SWITCH_MENU_H_
-
-#include <string>
-
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/views/controls/button/menu_button_listener.h"
-#include "ui/views/controls/menu/menu_delegate.h"
-#include "ui/views/view.h"
-
-class WizardControllerTest_SwitchLanguage_Test;
-
-namespace views {
-class MenuItemView;
-class MenuRunner;
-} // namespace views
-
-namespace chromeos {
-
-class LanguageList;
-
-class LanguageSwitchMenu : public views::MenuButtonListener,
- public views::MenuDelegate {
- public:
- LanguageSwitchMenu();
- virtual ~LanguageSwitchMenu();
-
- // Initializes language selection menu contents.
- void InitLanguageMenu();
-
- // Returns current locale name to be placed on the language menu-button.
- string16 GetCurrentLocaleName() const;
-
- // Sets the minimum width of the first level menu to be shown.
- void SetFirstLevelMenuWidth(int width);
-
- // Switches the current locale, saves the new locale in preferences.
- // Returns true if it has switched the current locale.
- static bool SwitchLanguage(const std::string& locale);
-
- // Switches the current locale, saves the new locale in preferences.
- // Enables the keyboard layouts associated with the new locale.
- static void SwitchLanguageAndEnableKeyboardLayouts(
- const std::string& locale);
-
- static void LoadFontsForCurrentLocale();
-
- private:
- // Overridden from views::MenuButtonListener:
- virtual void OnMenuButtonClicked(views::View* source,
- const gfx::Point& point) OVERRIDE;
-
- // Overridden from views::MenuDelegate:
- virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
-
- // The menu.
- views::MenuItemView* menu_;
-
- // Runs and owns |menu_|.
- scoped_ptr<views::MenuRunner> menu_runner_;
-
- // Language locale name storage.
- scoped_ptr<LanguageList> language_list_;
-
- FRIEND_TEST(::WizardControllerTest, SwitchLanguage);
- DISALLOW_COPY_AND_ASSIGN(LanguageSwitchMenu);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_LOGIN_LANGUAGE_SWITCH_MENU_H_
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc
index ac337c7..19e100e 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/login_display_host_impl.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/first_run/drive_first_run_controller.h"
@@ -34,8 +35,8 @@
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
+#include "chrome/browser/chromeos/login/input_events_blocker.h"
#include "chrome/browser/chromeos/login/keyboard_driven_oobe_key_handler.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/oobe_display.h"
@@ -177,6 +178,61 @@ void PlayStartupSoundHelper(bool startup_sound_honors_spoken_feedback) {
}
}
+// ShowLoginWizard is split into two parts. This function is sometimes called
+// from ShowLoginWizard(), and sometimes from OnLanguageSwitchedCallback()
+// (if locale was updated).
+void ShowLoginWizardFinish(
+ const std::string& first_screen_name,
+ const chromeos::StartupCustomizationDocument* startup_manifest,
+ chromeos::LoginDisplayHost* display_host) {
+ scoped_ptr<DictionaryValue> params;
+ display_host->StartWizard(first_screen_name, params.Pass());
+
+ chromeos::DBusThreadManager::Get()->
+ GetSessionManagerClient()->
+ EmitLoginPromptReady();
+ TRACE_EVENT0("chromeos", "ShowLoginWizard::EmitLoginPromptReady");
+
+ // Set initial timezone if specified by customization.
+ const std::string timezone_name = startup_manifest->initial_timezone();
+ VLOG(1) << "Initial time zone: " << timezone_name;
+ // Apply locale customizations only once to preserve whatever locale
+ // user has changed to during OOBE.
+ if (!timezone_name.empty()) {
+ chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
+ UTF8ToUTF16(timezone_name));
+ }
+}
+
+struct ShowLoginWizardSwitchLanguageCallbackData {
+ explicit ShowLoginWizardSwitchLanguageCallbackData(
+ const std::string& first_screen_name,
+ const chromeos::StartupCustomizationDocument* startup_manifest,
+ chromeos::LoginDisplayHost* display_host)
+ : first_screen_name(first_screen_name),
+ startup_manifest(startup_manifest),
+ display_host(display_host) {}
+
+ const std::string first_screen_name;
+ const chromeos::StartupCustomizationDocument* const startup_manifest;
+ chromeos::LoginDisplayHost* const display_host;
+
+ // lock UI while resource bundle is being reloaded.
+ chromeos::InputEventsBlocker events_blocker;
+};
+
+void OnLanguageSwitchedCallback(
+ scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> self,
+ const std::string& locale,
+ const std::string& loaded_locale,
+ const bool success) {
+ if (!success)
+ LOG(WARNING) << "Locale could not be found for '" << locale << "'";
+
+ ShowLoginWizardFinish(
+ self->first_screen_name, self->startup_manifest, self->display_host);
+}
+
} // namespace
namespace chromeos {
@@ -1104,58 +1160,41 @@ void ShowLoginWizard(const std::string& first_screen_name) {
const std::string current_locale =
prefs->GetString(prefs::kApplicationLocale);
VLOG(1) << "Current locale: " << current_locale;
- std::string locale;
- if (current_locale.empty()) {
- locale = startup_manifest->initial_locale();
- std::string layout = startup_manifest->keyboard_layout();
- VLOG(1) << "Initial locale: " << locale
- << "keyboard layout " << layout;
- if (!locale.empty()) {
- // Save initial locale from VPD/customization manifest as current
- // Chrome locale. Otherwise it will be lost if Chrome restarts.
- // Don't need to schedule pref save because setting initial local
- // will enforce preference saving.
- prefs->SetString(prefs::kApplicationLocale, locale);
- chromeos::StartupUtils::SetInitialLocale(locale);
- // Determine keyboard layout from OEM customization (if provided) or
- // initial locale and save it in preferences.
- DetermineAndSaveHardwareKeyboard(locale, layout);
- // Then, enable the hardware keyboard.
- manager->EnableLayouts(
- locale,
- manager->GetInputMethodUtil()->GetHardwareInputMethodId());
- // Reloading resource bundle causes us to do blocking IO on UI thread.
- // Temporarily allow it until we fix http://crosbug.com/11102
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- const std::string loaded_locale =
- ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
- CHECK(!loaded_locale.empty()) << "Locale could not be found for "
- << locale;
- // Set the application locale here so that the language switch
- // menu works properly with the newly loaded locale.
- g_browser_process->SetApplicationLocale(loaded_locale);
+ std::string locale = startup_manifest->initial_locale();
- // Reload font settings here to use correct font for initial_locale.
- LanguageSwitchMenu::LoadFontsForCurrentLocale();
- }
+ if (!current_locale.empty() || locale.empty()) {
+ ShowLoginWizardFinish(first_screen_name, startup_manifest, display_host);
+ return;
}
- scoped_ptr<DictionaryValue> params;
- display_host->StartWizard(first_screen_name, params.Pass());
+ std::string layout = startup_manifest->keyboard_layout();
+ VLOG(1) << "Initial locale: " << locale << "keyboard layout " << layout;
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
- ->EmitLoginPromptReady();
- TRACE_EVENT0("chromeos", "ShowLoginWizard::EmitLoginPromptReady");
+ // Save initial locale from VPD/customization manifest as current
+ // Chrome locale. Otherwise it will be lost if Chrome restarts.
+ // Don't need to schedule pref save because setting initial local
+ // will enforce preference saving.
+ prefs->SetString(prefs::kApplicationLocale, locale);
+ chromeos::StartupUtils::SetInitialLocale(locale);
- // Set initial timezone if specified by customization.
- const std::string timezone_name = startup_manifest->initial_timezone();
- VLOG(1) << "Initial time zone: " << timezone_name;
- // Apply locale customizations only once to preserve whatever locale
- // user has changed to during OOBE.
- if (!timezone_name.empty()) {
- chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
- UTF8ToUTF16(timezone_name));
- }
+ // Determine keyboard layout from OEM customization (if provided) or
+ // initial locale and save it in preferences.
+ DetermineAndSaveHardwareKeyboard(locale, layout);
+
+ // Then, enable the hardware keyboard.
+ manager->EnableLayouts(
+ locale, manager->GetInputMethodUtil()->GetHardwareInputMethodId());
+
+ scoped_ptr<ShowLoginWizardSwitchLanguageCallbackData> data(
+ new ShowLoginWizardSwitchLanguageCallbackData(
+ first_screen_name, startup_manifest, display_host));
+
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback(
+ new locale_util::SwitchLanguageCallback(
+ base::Bind(&OnLanguageSwitchedCallback, base::Passed(data.Pass()))));
+
+ // Do not load locale keyboards here.
+ locale_util::SwitchLanguage(locale, false, callback.Pass());
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index aaebc25..6fdf2b0 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <vector>
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
@@ -35,6 +36,7 @@
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/chrome_restart_request.h"
+#include "chrome/browser/chromeos/login/input_events_blocker.h"
#include "chrome/browser/chromeos/login/login_display_host.h"
#include "chrome/browser/chromeos/login/oauth2_login_manager.h"
#include "chrome/browser/chromeos/login/oauth2_login_manager_factory.h"
@@ -98,6 +100,8 @@ base::FilePath GetRlzDisabledFlagPath() {
} // namespace
+struct DoBrowserLaunchOnLocaleLoadedData;
+
class LoginUtilsImpl
: public LoginUtils,
public OAuth2LoginManager::Observer,
@@ -147,6 +151,18 @@ class LoginUtilsImpl
net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
private:
+ // DoBrowserLaunch is split into two parts.
+ // This one is called after anynchronous locale switch.
+ void DoBrowserLaunchOnLocaleLoadedImpl(Profile* profile,
+ LoginDisplayHost* login_host);
+
+ // Callback for locale_util::SwitchLanguage().
+ static void DoBrowserLaunchOnLocaleLoaded(
+ scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> context,
+ const std::string& locale,
+ const std::string& loaded_locale,
+ const bool success);
+
// Restarts OAuth session authentication check.
void KickStartAuthentication(Profile* profile);
@@ -245,15 +261,38 @@ class LoginUtilsWrapper {
DISALLOW_COPY_AND_ASSIGN(LoginUtilsWrapper);
};
-void LoginUtilsImpl::DoBrowserLaunch(Profile* profile,
- LoginDisplayHost* login_host) {
- if (browser_shutdown::IsTryingToQuit())
- return;
+struct DoBrowserLaunchOnLocaleLoadedData {
+ DoBrowserLaunchOnLocaleLoadedData(LoginUtilsImpl* login_utils_impl,
+ Profile* profile,
+ LoginDisplayHost* display_host)
+ : login_utils_impl(login_utils_impl),
+ profile(profile),
+ display_host(display_host) {}
+
+ LoginUtilsImpl* login_utils_impl;
+ Profile* profile;
+ chromeos::LoginDisplayHost* display_host;
- User* user = UserManager::Get()->GetUserByProfile(profile);
- if (user != NULL)
- UserManager::Get()->RespectLocalePreference(profile, user);
+ // Block UI events untill ResourceBundle is reloaded.
+ InputEventsBlocker input_events_blocker;
+};
+// static
+void LoginUtilsImpl::DoBrowserLaunchOnLocaleLoaded(
+ scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> context,
+ const std::string& /* locale */,
+ const std::string& /* loaded_locale */,
+ const bool /* success */) {
+ context->login_utils_impl->DoBrowserLaunchOnLocaleLoadedImpl(
+ context->profile, context->display_host);
+}
+
+// Called from DoBrowserLaunch() or from
+// DoBrowserLaunchOnLocaleLoaded() depending on
+// if locale switch was needed.
+void LoginUtilsImpl::DoBrowserLaunchOnLocaleLoadedImpl(
+ Profile* profile,
+ LoginDisplayHost* login_host) {
if (!UserManager::Get()->GetCurrentUserFlow()->ShouldLaunchBrowser()) {
UserManager::Get()->GetCurrentUserFlow()->LaunchExtraSteps(profile);
return;
@@ -310,6 +349,25 @@ void LoginUtilsImpl::DoBrowserLaunch(Profile* profile,
UserManager::Get()->SessionStarted();
}
+void LoginUtilsImpl::DoBrowserLaunch(Profile* profile,
+ LoginDisplayHost* login_host) {
+ if (browser_shutdown::IsTryingToQuit())
+ return;
+
+ User* const user = UserManager::Get()->GetUserByProfile(profile);
+ scoped_ptr<DoBrowserLaunchOnLocaleLoadedData> data(
+ new DoBrowserLaunchOnLocaleLoadedData(this, profile, login_host));
+
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback(
+ new locale_util::SwitchLanguageCallback(
+ base::Bind(&LoginUtilsImpl::DoBrowserLaunchOnLocaleLoaded,
+ base::Passed(data.Pass()))));
+ if (!UserManager::Get()->
+ RespectLocalePreference(profile, user, callback.Pass())) {
+ DoBrowserLaunchOnLocaleLoadedImpl(profile, login_host);
+ }
+}
+
void LoginUtilsImpl::PrepareProfile(
const UserContext& user_context,
const std::string& display_email,
diff --git a/chrome/browser/chromeos/login/mock_user_manager.cc b/chrome/browser/chromeos/login/mock_user_manager.cc
index 9d0b674..31a24e7 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.cc
+++ b/chrome/browser/chromeos/login/mock_user_manager.cc
@@ -92,8 +92,11 @@ void MockUserManager::ClearUserList() {
user_list_.clear();
}
-void MockUserManager::RespectLocalePreference(Profile* profile,
- const User* user) const {
+bool MockUserManager::RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
+ return false;
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/mock_user_manager.h b/chrome/browser/chromeos/login/mock_user_manager.h
index c003769..5a37eec 100644
--- a/chrome/browser/chromeos/login/mock_user_manager.h
+++ b/chrome/browser/chromeos/login/mock_user_manager.h
@@ -100,8 +100,10 @@ class MockUserManager : public UserManager {
virtual UserFlow* GetCurrentUserFlow() const OVERRIDE;
virtual UserFlow* GetUserFlow(const std::string&) const OVERRIDE;
- virtual void RespectLocalePreference(Profile* profile, const User* user) const
- OVERRIDE;
+ virtual bool RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const OVERRIDE;
// Sets a new User instance. Users previously created by this MockUserManager
// become invalid.
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h
index 0faa8ac..7de34d9 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.h
+++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -9,7 +9,6 @@
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/timer/timer.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/screens/network_screen_actor.h"
#include "chrome/browser/chromeos/login/screens/wizard_screen.h"
#include "chromeos/network/network_state_handler_observer.h"
diff --git a/chrome/browser/chromeos/login/user_manager.h b/chrome/browser/chromeos/login/user_manager.h
index 4e59d37..415ef7d 100644
--- a/chrome/browser/chromeos/login/user_manager.h
+++ b/chrome/browser/chromeos/login/user_manager.h
@@ -7,6 +7,7 @@
#include <string>
+#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_flow.h"
@@ -326,9 +327,11 @@ class UserManager {
const = 0;
// Changes browser locale (selects best suitable locale from different
- // user settings).
- virtual void RespectLocalePreference(Profile* profile,
- const User* user) const = 0;
+ // user settings). Returns true if callback will be called.
+ virtual bool RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const = 0;
private:
friend class ScopedUserManagerEnabler;
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 3f77240..5c99f48 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -27,10 +27,10 @@
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/login/auth_sync_observer.h"
#include "chrome/browser/chromeos/login/auth_sync_observer_factory.h"
#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_display.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/multi_profile_first_run_notification.h"
@@ -737,21 +737,25 @@ std::string UserManagerImpl::GetUserDisplayEmail(
// TODO(alemate): http://crbug.com/288941 : Respect preferred language list in
// the Google user profile.
-void UserManagerImpl::RespectLocalePreference(Profile* profile,
- const User* user) const {
+//
+// Returns true if callback will be called.
+bool UserManagerImpl::RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const {
if (g_browser_process == NULL)
- return;
+ return false;
if ((user == NULL) || (user != GetPrimaryUser()) ||
(!user->is_profile_created()))
- return;
+ return false;
// In case of Multi Profile mode we don't apply profile locale because it is
// unsafe.
if (GetLoggedInUsers().size() != 1)
- return;
+ return false;
const PrefService* prefs = profile->GetPrefs();
if (prefs == NULL)
- return;
+ return false;
std::string pref_locale;
const std::string pref_app_locale =
@@ -766,7 +770,7 @@ void UserManagerImpl::RespectLocalePreference(Profile* profile,
const std::string* account_locale = NULL;
if (pref_locale.empty() && user->has_gaia_account()) {
if (user->GetAccountLocale() == NULL)
- return; // wait until Account profile is loaded.
+ return false; // wait until Account profile is loaded.
account_locale = user->GetAccountLocale();
pref_locale = *account_locale;
}
@@ -790,7 +794,9 @@ void UserManagerImpl::RespectLocalePreference(Profile* profile,
// is different from the login screen UI language, is not desirable. Note
// that input method preferences are synced, so users can use their
// farovite input methods as soon as the preferences are synced.
- chromeos::LanguageSwitchMenu::SwitchLanguage(pref_locale);
+ locale_util::SwitchLanguage(pref_locale, false, callback.Pass());
+
+ return true;
}
Profile* UserManagerImpl::GetProfileByUser(const User* user) const {
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index df38699..50316a0 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -143,8 +143,10 @@ class UserManagerImpl
virtual void OnPolicyUpdated(const std::string& user_id) OVERRIDE;
virtual void OnDeviceLocalAccountsChanged() OVERRIDE;
- virtual void RespectLocalePreference(Profile* profile, const User* user) const
- OVERRIDE;
+ virtual bool RespectLocalePreference(
+ Profile* profile,
+ const User* user,
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback) const OVERRIDE;
private:
friend class SupervisedUserManagerImpl;
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 23e68ca..b22c9fd 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -15,10 +15,10 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
#include "chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/mock_authenticator.h"
#include "chrome/browser/chromeos/login/mock_login_status_consumer.h"
@@ -79,6 +79,45 @@ class PrefStoreStub : public TestingPrefStore {
virtual ~PrefStoreStub() {}
};
+struct SwitchLanguageTestData {
+ SwitchLanguageTestData() : success(false), done(false) {}
+
+ std::string requested_locale;
+ std::string loaded_locale;
+ bool success;
+ bool done;
+};
+
+void OnLocaleSwitched(SwitchLanguageTestData* self,
+ const std::string& locale,
+ const std::string& loaded_locale,
+ const bool success) {
+ self->requested_locale = locale;
+ self->loaded_locale = loaded_locale;
+ self->success = success;
+ self->done = true;
+}
+
+void RunSwitchLanguageTest(const std::string& locale,
+ const std::string& expected_locale,
+ const bool expect_success) {
+ SwitchLanguageTestData data;
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback(
+ new locale_util::SwitchLanguageCallback(
+ base::Bind(&OnLocaleSwitched, base::Unretained(&data))));
+ locale_util::SwitchLanguage(locale, true, callback.Pass());
+
+ // Token writing moves control to BlockingPool and back.
+ base::RunLoop().RunUntilIdle();
+ content::BrowserThread::GetBlockingPool()->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(data.done, true);
+ EXPECT_EQ(data.requested_locale, locale);
+ EXPECT_EQ(data.loaded_locale, expected_locale);
+ EXPECT_EQ(data.success, expect_success);
+}
+
} // namespace
using ::testing::_;
@@ -128,7 +167,7 @@ IN_PROC_BROWSER_TEST_F(WizardControllerTest, SwitchLanguage) {
const std::wstring en_str =
UTF16ToWide(l10n_util::GetStringUTF16(IDS_NETWORK_SELECTION_TITLE));
- LanguageSwitchMenu::SwitchLanguage("fr");
+ RunSwitchLanguageTest("fr", "fr", true);
EXPECT_EQ("fr", g_browser_process->GetApplicationLocale());
EXPECT_STREQ("fr", icu::Locale::getDefault().getLanguage());
EXPECT_FALSE(base::i18n::IsRTL());
@@ -137,7 +176,7 @@ IN_PROC_BROWSER_TEST_F(WizardControllerTest, SwitchLanguage) {
EXPECT_NE(en_str, fr_str);
- LanguageSwitchMenu::SwitchLanguage("ar");
+ RunSwitchLanguageTest("ar", "ar", true);
EXPECT_EQ("ar", g_browser_process->GetApplicationLocale());
EXPECT_STREQ("ar", icu::Locale::getDefault().getLanguage());
EXPECT_TRUE(base::i18n::IsRTL());
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
index 6f6de2c..93531f3 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -4,12 +4,16 @@
#include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/base/locale_util.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
-#include "chrome/browser/chromeos/login/language_switch_menu.h"
+#include "chrome/browser/chromeos/login/input_events_blocker.h"
#include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
#include "chrome/browser/chromeos/system/input_device_settings.h"
#include "chrome/browser/chromeos/system/timezone_util.h"
@@ -43,7 +47,8 @@ NetworkScreenHandler::NetworkScreenHandler(CoreOobeActor* core_oobe_actor)
screen_(NULL),
core_oobe_actor_(core_oobe_actor),
is_continue_enabled_(false),
- show_on_init_(false) {
+ show_on_init_(false),
+ weak_ptr_factory_(this) {
DCHECK(core_oobe_actor_);
}
@@ -159,21 +164,51 @@ void NetworkScreenHandler::HandleOnExit() {
screen_->OnContinuePressed();
}
-void NetworkScreenHandler::HandleOnLanguageChanged(const std::string& locale) {
- const std::string app_locale = g_browser_process->GetApplicationLocale();
- if (app_locale == locale)
+struct NetworkScreenHandlerOnLanguageChangedCallbackData {
+ explicit NetworkScreenHandlerOnLanguageChangedCallbackData(
+ base::WeakPtr<NetworkScreenHandler>& handler)
+ : handler_(handler) {}
+
+ base::WeakPtr<NetworkScreenHandler> handler_;
+
+ // Block UI while resource bundle is being reloaded.
+ chromeos::InputEventsBlocker input_events_blocker;
+};
+
+// static
+void NetworkScreenHandler::OnLanguageChangedCallback(
+ scoped_ptr<NetworkScreenHandlerOnLanguageChangedCallbackData> context,
+ const std::string& /*requested locale*/,
+ const std::string& /*loaded_locale*/,
+ const bool /*success*/) {
+ if (!context or !context->handler_)
return;
- // TODO(altimofeev): make language change async.
- LanguageSwitchMenu::SwitchLanguageAndEnableKeyboardLayouts(locale);
+ NetworkScreenHandler* const self = context->handler_.get();
DictionaryValue localized_strings;
- static_cast<OobeUI*>(web_ui()->GetController())->GetLocalizedStrings(
- &localized_strings);
- core_oobe_actor_->ReloadContent(localized_strings);
+ static_cast<OobeUI*>(self->web_ui()->GetController())
+ ->GetLocalizedStrings(&localized_strings);
+ self->core_oobe_actor_->ReloadContent(localized_strings);
// Buttons are recreated, updated "Continue" button state.
- EnableContinue(is_continue_enabled_);
+ self->EnableContinue(self->is_continue_enabled_);
+}
+
+void NetworkScreenHandler::HandleOnLanguageChanged(const std::string& locale) {
+ const std::string app_locale = g_browser_process->GetApplicationLocale();
+ if (app_locale == locale)
+ return;
+
+ base::WeakPtr<NetworkScreenHandler> weak_self =
+ weak_ptr_factory_.GetWeakPtr();
+ scoped_ptr<NetworkScreenHandlerOnLanguageChangedCallbackData> callback_data(
+ new NetworkScreenHandlerOnLanguageChangedCallbackData(weak_self));
+ scoped_ptr<locale_util::SwitchLanguageCallback> callback(
+ new locale_util::SwitchLanguageCallback(
+ base::Bind(&NetworkScreenHandler::OnLanguageChangedCallback,
+ base::Passed(callback_data.Pass()))));
+ locale_util::SwitchLanguage(locale, true, callback.Pass());
}
void NetworkScreenHandler::HandleOnInputMethodChanged(const std::string& id) {
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
index b57489d..a19486b 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
@@ -17,6 +17,8 @@ namespace chromeos {
class CoreOobeActor;
+struct NetworkScreenHandlerOnLanguageChangedCallbackData;
+
// WebUI implementation of NetworkScreenActor. It is used to interact with
// the welcome screen (part of the page) of the OOBE.
class NetworkScreenHandler : public NetworkScreenActor,
@@ -51,6 +53,13 @@ class NetworkScreenHandler : public NetworkScreenActor,
// Handles change of the language.
void HandleOnLanguageChanged(const std::string& locale);
+ // Async callback after ReloadResourceBundle(locale) completed.
+ static void OnLanguageChangedCallback(
+ scoped_ptr<NetworkScreenHandlerOnLanguageChangedCallbackData> context,
+ const std::string& requested_locale,
+ const std::string& loaded_locale,
+ const bool success);
+
// Handles change of the input method.
void HandleOnInputMethodChanged(const std::string& id);
@@ -84,6 +93,8 @@ class NetworkScreenHandler : public NetworkScreenActor,
scoped_ptr<CrosSettings::ObserverSubscription> timezone_subscription_;
+ base::WeakPtrFactory<NetworkScreenHandler> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkScreenHandler);
};
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 10b5beb..0844b7a 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -156,6 +156,8 @@
'browser/chromeos/background/ash_user_wallpaper_delegate.h',
'browser/chromeos/bluetooth/bluetooth_pairing_dialog.cc',
'browser/chromeos/bluetooth/bluetooth_pairing_dialog.h',
+ 'browser/chromeos/base/locale_util.cc',
+ 'browser/chromeos/base/locale_util.h',
'browser/chromeos/boot_times_loader.cc',
'browser/chromeos/boot_times_loader.h',
'browser/chromeos/camera_detector.cc',
@@ -478,6 +480,8 @@
'browser/chromeos/login/enrollment/enrollment_screen_actor.h',
'browser/chromeos/login/existing_user_controller.cc',
'browser/chromeos/login/existing_user_controller.h',
+ 'browser/chromeos/login/input_events_blocker.h',
+ 'browser/chromeos/login/input_events_blocker.cc',
'browser/chromeos/login/keyboard_driven_oobe_key_handler.cc',
'browser/chromeos/login/keyboard_driven_oobe_key_handler.h',
'browser/chromeos/login/help_app_launcher.cc',
@@ -488,8 +492,6 @@
'browser/chromeos/login/hwid_checker.h',
'browser/chromeos/login/language_list.cc',
'browser/chromeos/login/language_list.h',
- 'browser/chromeos/login/language_switch_menu.cc',
- 'browser/chromeos/login/language_switch_menu.h',
'browser/chromeos/login/lock_window.cc',
'browser/chromeos/login/lock_window.h',
'browser/chromeos/login/lock_window_aura.cc',