blob: 3746b803d7e17b77469b22f3e84c512fb9b82e5b [file] [log] [blame]
// 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 "chrome/browser/api/prefs/pref_member.h"
#include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace input_method {
namespace {
void RegisterTestPrefs(PrefService* prefs) {
prefs->RegisterStringPref(prefs::kLanguagePreviousInputMethod,
"",
PrefService::UNSYNCABLE_PREF);
prefs->RegisterStringPref(prefs::kLanguageCurrentInputMethod,
"",
PrefService::UNSYNCABLE_PREF);
}
class TestableBrowserStateMonitor : public BrowserStateMonitor {
public:
using BrowserStateMonitor::InputMethodChanged;
using BrowserStateMonitor::Observe;
explicit TestableBrowserStateMonitor(InputMethodManager* manager)
: BrowserStateMonitor(manager) {
ResetCounters();
}
virtual ~TestableBrowserStateMonitor() {
}
void ResetCounters() {
update_local_state_count_ = 0;
last_local_state_.clear();
update_user_pref_count_ = 0;
last_user_pref_.clear();
}
int update_local_state_count() const { return update_local_state_count_; }
const std::string& last_local_state() const { return last_local_state_; }
int update_user_pref_count() const { return update_user_pref_count_; }
const std::string& last_user_pref() const { return last_user_pref_; }
protected:
virtual void UpdateLocalState(
const std::string& current_input_method) OVERRIDE {
++update_local_state_count_;
last_local_state_ = current_input_method;
// Do not call the parent class' method since it depends on the global
// browser object which is a bit difficult to mock. This should be okay
// since the method is really simple.
}
virtual void UpdateUserPreferences(
const std::string& current_input_method) OVERRIDE {
++update_user_pref_count_;
last_user_pref_ = current_input_method;
BrowserStateMonitor::UpdateUserPreferences(current_input_method);
}
private:
int update_local_state_count_;
std::string last_local_state_;
int update_user_pref_count_;
std::string last_user_pref_;
DISALLOW_COPY_AND_ASSIGN(TestableBrowserStateMonitor);
};
} // anonymous namespace
TEST(BrowserStateMonitorTest, TestConstruction) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
// Check the initial state of the |mock_manager| and |monitor| objects.
EXPECT_EQ(1, mock_manager.add_observer_count_);
EXPECT_EQ(1, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_LOGIN_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_LOGIN_SCREEN, monitor.state());
}
TEST(BrowserStateMonitorTest, TestDestruction) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
{
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
}
EXPECT_EQ(1, mock_manager.remove_observer_count_);
}
TEST(BrowserStateMonitorTest, TestObserveLoginUserChanged) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// Check if the state of the |mock_manager| as well as the |monitor| are both
// changed.
EXPECT_EQ(2, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
}
TEST(BrowserStateMonitorTest, TestObserveSessionStarted) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// Check if the state of the |mock_manager| as well as the |monitor| are both
// changed.
EXPECT_EQ(2, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
}
TEST(BrowserStateMonitorTest, TestObserveLoginUserChangedThenSessionStarted) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// Check if the state of the |mock_manager| as well as the |monitor| are both
// changed.
EXPECT_EQ(2, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
monitor.Observe(chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// The second notification should be nop.
EXPECT_EQ(2, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
}
TEST(BrowserStateMonitorTest, TestObserveScreenLockUnlock) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(2, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(2, mock_manager.set_state_count_);
bool locked = true;
monitor.Observe(chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
content::NotificationService::AllSources(),
content::Details<bool>(&locked));
EXPECT_EQ(3, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_LOCK_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_LOCK_SCREEN, monitor.state());
// When the screen is locked, the monitor should ignore input method changes.
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
locked = false;
monitor.Observe(chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
content::NotificationService::AllSources(),
content::Details<bool>(&locked));
EXPECT_EQ(4, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(1, monitor.update_user_pref_count());
}
TEST(BrowserStateMonitorTest, TestObserveAppTerminating) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// Check if the state of the |mock_manager| as well as the |monitor| are both
// changed.
EXPECT_EQ(2, mock_manager.set_state_count_);
EXPECT_EQ(InputMethodManager::STATE_TERMINATING,
mock_manager.last_state_);
EXPECT_EQ(InputMethodManager::STATE_TERMINATING, monitor.state());
// In the terminating state, the monitor should ignore input method changes.
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
}
TEST(BrowserStateMonitorTest, TestObservePrefChanged) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(1, mock_manager.set_state_count_);
monitor.Observe(chrome::NOTIFICATION_PREF_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
// NOTIFICATION_PREF_CHANGED should be ignored.
EXPECT_EQ(1, mock_manager.set_state_count_);
}
TEST(BrowserStateMonitorTest, TestUpdatePrefOnLoginScreen) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(InputMethodManager::STATE_LOGIN_SCREEN, monitor.state());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(1, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(2, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
}
TEST(BrowserStateMonitorTest, TestUpdatePrefOnBrowserScreen) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
monitor.Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(1, monitor.update_user_pref_count());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(2, monitor.update_user_pref_count());
monitor.Observe(chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(3, monitor.update_user_pref_count());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(4, monitor.update_user_pref_count());
}
TEST(BrowserStateMonitorTest, TestUpdatePrefOnLoginScreenDetails) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
EXPECT_EQ(InputMethodManager::STATE_LOGIN_SCREEN, monitor.state());
std::string input_method_id = "xkb:us:dvorak:eng";
mock_manager.SetCurrentInputMethodId(input_method_id);
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(1, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id, monitor.last_local_state());
input_method_id = "xkb:us:colemak:eng";
mock_manager.SetCurrentInputMethodId(input_method_id);
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(2, monitor.update_local_state_count());
EXPECT_EQ(0, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id, monitor.last_local_state());
}
TEST(BrowserStateMonitorTest, TestUpdatePrefOnBrowserScreenDetails) {
TestingPrefService prefs;
RegisterTestPrefs(&prefs);
MockInputMethodManager mock_manager;
TestableBrowserStateMonitor monitor(&mock_manager);
monitor.SetPrefServiceForTesting(&prefs);
StringPrefMember previous;
previous.Init(prefs::kLanguagePreviousInputMethod, &prefs, NULL);
EXPECT_EQ("", previous.GetValue());
StringPrefMember current;
current.Init(prefs::kLanguageCurrentInputMethod, &prefs, NULL);
EXPECT_EQ("", current.GetValue());
monitor.Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
monitor.Observe(chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
EXPECT_EQ(InputMethodManager::STATE_BROWSER_SCREEN, monitor.state());
const std::string input_method_id = "xkb:us:dvorak:eng";
mock_manager.SetCurrentInputMethodId(input_method_id);
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(1, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id, monitor.last_user_pref());
EXPECT_EQ("", previous.GetValue());
EXPECT_EQ(input_method_id, current.GetValue());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(2, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id, monitor.last_user_pref());
EXPECT_EQ("", previous.GetValue());
EXPECT_EQ(input_method_id, current.GetValue());
const std::string input_method_id_2 = "xkb:us:colemak:eng";
mock_manager.SetCurrentInputMethodId(input_method_id_2);
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(3, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id_2, monitor.last_user_pref());
EXPECT_EQ(input_method_id, previous.GetValue());
EXPECT_EQ(input_method_id_2, current.GetValue());
const std::string input_method_id_3 = "xkb:us::eng";
mock_manager.SetCurrentInputMethodId(input_method_id_3);
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(4, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id_3, monitor.last_user_pref());
EXPECT_EQ(input_method_id_2, previous.GetValue());
EXPECT_EQ(input_method_id_3, current.GetValue());
monitor.InputMethodChanged(&mock_manager, false);
EXPECT_EQ(0, monitor.update_local_state_count());
EXPECT_EQ(5, monitor.update_user_pref_count());
EXPECT_EQ(input_method_id_3, monitor.last_user_pref());
EXPECT_EQ(input_method_id_2, previous.GetValue());
EXPECT_EQ(input_method_id_3, current.GetValue());
}
} // namespace input_method
} // namespace chromeos