| Index: chrome/browser/chromeos/input_method/browser_state_monitor.cc
|
| diff --git a/chrome/browser/chromeos/input_method/browser_state_monitor.cc b/chrome/browser/chromeos/input_method/browser_state_monitor.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cc5636e4f9b368cdd2d01c3f1c371cde45bc2a69
|
| --- /dev/null
|
| +++ b/chrome/browser/chromeos/input_method/browser_state_monitor.cc
|
| @@ -0,0 +1,203 @@
|
| +// 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/input_method/browser_state_monitor.h"
|
| +
|
| +#include "ash/ash_switches.h"
|
| +#include "base/command_line.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/chromeos/input_method/input_method_util.h"
|
| +#include "chrome/browser/chromeos/language_preferences.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/browser/profiles/profile_manager.h"
|
| +#include "chrome/common/chrome_notification_types.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "content/public/browser/notification_service.h"
|
| +
|
| +namespace chromeos {
|
| +namespace input_method {
|
| +namespace {
|
| +
|
| +PrefService* GetPrefService() {
|
| + Profile* profile = ProfileManager::GetDefaultProfile();
|
| + if (profile)
|
| + return profile->GetPrefs();
|
| + return NULL;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BrowserStateMonitor::BrowserStateMonitor(InputMethodManager* manager)
|
| + : manager_(manager),
|
| + state_(InputMethodManager::STATE_LOGIN_SCREEN),
|
| + initialized_(false) {
|
| + // On R19, when Uber Tray is disabled, the IME status button will update the
|
| + // Preferences.
|
| + // TODO(yusukes): Remove all Preferences code from the button on R20.
|
| + if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| + ash::switches::kDisableAshUberTray))
|
| + return;
|
| +
|
| + notification_registrar_.Add(this,
|
| + chrome::NOTIFICATION_LOGIN_USER_CHANGED,
|
| + content::NotificationService::AllSources());
|
| + notification_registrar_.Add(this,
|
| + chrome::NOTIFICATION_SESSION_STARTED,
|
| + content::NotificationService::AllSources());
|
| + notification_registrar_.Add(this,
|
| + chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
|
| + content::NotificationService::AllSources());
|
| + // We should not use APP_EXITING here since logout might be canceled by
|
| + // JavaScript after APP_EXITING is sent (crosbug.com/11055).
|
| + notification_registrar_.Add(this,
|
| + content::NOTIFICATION_APP_TERMINATING,
|
| + content::NotificationService::AllSources());
|
| +
|
| + // TODO(yusukes): Tell the initial state to the manager.
|
| + manager_->AddPreLoginPreferenceObserver(this);
|
| + manager_->AddPostLoginPreferenceObserver(this);
|
| +}
|
| +
|
| +BrowserStateMonitor::~BrowserStateMonitor() {
|
| + manager_->RemovePostLoginPreferenceObserver(this);
|
| + manager_->RemovePreLoginPreferenceObserver(this);
|
| +}
|
| +
|
| +void BrowserStateMonitor::UpdateLocalState(
|
| + const std::string& current_input_method) {
|
| + if (!InputMethodUtil::IsKeyboardLayout(current_input_method)) {
|
| + LOG(ERROR) << "Only keyboard layouts are supported: "
|
| + << current_input_method;
|
| + return;
|
| + }
|
| +
|
| + if (!g_browser_process || !g_browser_process->local_state())
|
| + return;
|
| +
|
| + g_browser_process->local_state()->SetString(
|
| + language_prefs::kPreferredKeyboardLayout,
|
| + current_input_method);
|
| +}
|
| +
|
| +void BrowserStateMonitor::UpdateUserPreferences(
|
| + const std::string& current_input_method) {
|
| + InitializePrefMembers();
|
| + const std::string current_input_method_on_pref =
|
| + current_input_method_pref_.GetValue();
|
| + if (current_input_method_on_pref == current_input_method)
|
| + return;
|
| + previous_input_method_pref_.SetValue(current_input_method_on_pref);
|
| + current_input_method_pref_.SetValue(current_input_method);
|
| +}
|
| +
|
| +void BrowserStateMonitor::PreferenceUpdateNeeded(
|
| + input_method::InputMethodManager* manager,
|
| + const input_method::InputMethodDescriptor& previous_input_method,
|
| + const input_method::InputMethodDescriptor& current_input_method) {
|
| + DCHECK_EQ(manager_, manager);
|
| + // Save the new input method id depending on the current browser state.
|
| + switch (state_) {
|
| + case InputMethodManager::STATE_LOGIN_SCREEN:
|
| + UpdateLocalState(current_input_method.id());
|
| + return;
|
| + case InputMethodManager::STATE_BROWSER_SCREEN:
|
| + UpdateUserPreferences(current_input_method.id());
|
| + return;
|
| + case InputMethodManager::STATE_LOGGING_IN:
|
| + // Do not update the prefs since Preferences::NotifyPrefChanged() will
|
| + // notify the current/previous input method IDs to the manager.
|
| + return;
|
| + case InputMethodManager::STATE_LOCK_SCREEN:
|
| + // We use a special set of input methods on the screen. Do not update.
|
| + return;
|
| + case InputMethodManager::STATE_TERMINATING:
|
| + return;
|
| + }
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void BrowserStateMonitor::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + switch (type) {
|
| + case content::NOTIFICATION_APP_TERMINATING: {
|
| + SetState(InputMethodManager::STATE_TERMINATING);
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_LOGIN_USER_CHANGED: {
|
| + // The user logged in, but the browser window for user session is not yet
|
| + // ready. An initial input method hasn't been set to the manager.
|
| + // Note that the notification is also sent when Chrome crashes/restarts.
|
| + SetState(InputMethodManager::STATE_LOGGING_IN);
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_SESSION_STARTED: {
|
| + // The user logged in, and the browser window for user session is ready.
|
| + // An initial input method has already been set.
|
| + // We should NOT call InitializePrefMembers() here since the notification
|
| + // is sent in the PreProfileInit phase in case when Chrome crashes and
|
| + // restarts.
|
| + SetState(InputMethodManager::STATE_BROWSER_SCREEN);
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: {
|
| + const bool is_screen_locked = *content::Details<bool>(details).ptr();
|
| + SetState(is_screen_locked ? InputMethodManager::STATE_LOCK_SCREEN :
|
| + InputMethodManager::STATE_BROWSER_SCREEN);
|
| + break;
|
| + }
|
| + case chrome::NOTIFICATION_PREF_CHANGED: {
|
| + break; // just ignore the notification.
|
| + }
|
| + default: {
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // TODO(yusukes): On R20, we should handle Chrome crash/restart correctly.
|
| + // Currently, a wrong input method could be selected when Chrome crashes and
|
| + // restarts.
|
| + //
|
| + // Normal login sequence:
|
| + // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED is sent.
|
| + // 2. Preferences::NotifyPrefChanged() is called. preload_engines (which
|
| + // might change the current input method) and current/previous input method
|
| + // are sent to the manager.
|
| + // 3. chrome::NOTIFICATION_SESSION_STARTED is sent.
|
| + //
|
| + // Chrome crash/restart (after logging in) sequence:
|
| + // 1. chrome::NOTIFICATION_LOGIN_USER_CHANGED is sent.
|
| + // 2. chrome::NOTIFICATION_SESSION_STARTED is sent.
|
| + // 3. Preferences::NotifyPrefChanged() is called. preload_engines (which
|
| + // might change the current input method) and current/previous input method
|
| + // are sent to the manager. When preload_engines are sent to the manager,
|
| + // UpdateUserPreferences() might be accidentally called.
|
| +}
|
| +
|
| +void BrowserStateMonitor::SetState(InputMethodManager::State new_state) {
|
| + const InputMethodManager::State old_state = state_;
|
| + state_ = new_state;
|
| + if (old_state != state_) {
|
| + // TODO(yusukes): Tell the new state to the manager.
|
| + }
|
| +}
|
| +
|
| +void BrowserStateMonitor::InitializePrefMembers() {
|
| + if (initialized_)
|
| + return;
|
| +
|
| + initialized_ = true;
|
| + PrefService* pref_service = GetPrefService();
|
| + DCHECK(pref_service);
|
| + DCHECK_EQ(InputMethodManager::STATE_BROWSER_SCREEN, state_);
|
| + previous_input_method_pref_.Init(
|
| + prefs::kLanguagePreviousInputMethod, pref_service, this);
|
| + current_input_method_pref_.Init(
|
| + prefs::kLanguageCurrentInputMethod, pref_service, this);
|
| +}
|
| +
|
| +} // namespace input_method
|
| +} // namespace chromeos
|
|
|