blob: e047731b39a309b63b581d421b156aba0f436074 [file] [log] [blame]
// 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 <algorithm>
#include "ash/shell.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/input_method/mode_indicator_controller.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/ime/component_extension_ime_manager.h"
#include "chromeos/ime/extension_ime_util.h"
#include "chromeos/ime/input_method_manager.h"
#include "chromeos/ime/input_method_whitelist.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ime/chromeos/ime_bridge.h"
#include "ui/base/ime/input_method_factory.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace chromeos {
namespace input_method {
class ScopedModeIndicatorObserverForTesting :
public ModeIndicatorObserverInterface {
public:
ScopedModeIndicatorObserverForTesting()
: max_widget_list_size_(0) {
ModeIndicatorController::SetModeIndicatorObserverForTesting(this);
}
virtual ~ScopedModeIndicatorObserverForTesting() {
for (size_t i = 0; i < widget_list_.size(); ++i) {
widget_list_[i]->RemoveObserver(this);
}
ModeIndicatorController::SetModeIndicatorObserverForTesting(NULL);
}
gfx::Rect last_bounds() const {
return last_bounds_;
}
bool is_displayed() const {
return is_displayed_;
}
const std::vector<views::Widget*>& widget_list() const {
return widget_list_;
}
size_t widget_list_size() const {
return widget_list_.size();
}
size_t max_widget_list_size() const {
return max_widget_list_size_;
}
// ModeIndicatorObserverInterface override:
virtual void AddModeIndicatorWidget(views::Widget* widget) OVERRIDE {
widget_list_.push_back(widget);
max_widget_list_size_ =
std::max(max_widget_list_size_, widget_list_.size());
widget->AddObserver(this);
}
// views::WidgetObserver override:
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
std::vector<views::Widget*>::iterator it =
std::find(widget_list_.begin(), widget_list_.end(), widget);
if (it != widget_list_.end())
widget_list_.erase(it);
}
// views::WidgetObserver override:
virtual void OnWidgetVisibilityChanged(views::Widget* widget,
bool visible) OVERRIDE {
last_bounds_ = widget->GetWindowBoundsInScreen();
is_displayed_ |= visible;
}
private:
bool is_displayed_;
gfx::Rect last_bounds_;
size_t max_widget_list_size_;
std::vector<views::Widget*> widget_list_;
};
class ModeIndicatorBrowserTest : public InProcessBrowserTest {
public:
ModeIndicatorBrowserTest()
: InProcessBrowserTest() {}
virtual ~ModeIndicatorBrowserTest() {}
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
ui::SetUpInputMethodFactoryForTesting();
}
void InitializeIMF() {
InputMethodManager::Get()
->GetInputMethodUtil()
->InitXkbInputMethodsForTesting();
// Make sure ComponentExtensionIMEManager is initialized.
// ComponentExtensionIMEManagerImpl::InitializeAsync posts
// ReadComponentExtensionsInfo to the FILE thread for the
// initialization. If it is never initialized for some reasons,
// the test is timed out and failed.
ComponentExtensionIMEManager* ceimm =
InputMethodManager::Get()->GetComponentExtensionIMEManager();
while (!ceimm->IsInitialized()) {
content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
}
}
private:
DISALLOW_COPY_AND_ASSIGN(ModeIndicatorBrowserTest);
};
namespace {
// 43 is the designed size of the inner contents.
// This value corresponds with kMinSize defined in
// mode_indicator_delegate_view.cc.
const int kInnerSize = 43;
} // namespace
IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest, Bounds) {
InitializeIMF();
InputMethodManager* imm = InputMethodManager::Get();
ASSERT_TRUE(imm);
std::vector<std::string> keyboard_layouts;
keyboard_layouts.push_back(
extension_ime_util::GetInputMethodIDByEngineID("xkb:fr::fra"));
// Add keyboard layouts to enable the mode indicator.
imm->EnableLoginLayouts("fr", keyboard_layouts);
ASSERT_LT(1UL, imm->GetNumActiveInputMethods());
chromeos::IMECandidateWindowHandlerInterface* candidate_window =
chromeos::IMEBridge::Get()->GetCandidateWindowHandler();
candidate_window->FocusStateChanged(true);
// Check if the size of the mode indicator is expected.
gfx::Rect cursor1_bounds(100, 100, 1, 20);
gfx::Rect mi1_bounds;
{
ScopedModeIndicatorObserverForTesting observer;
candidate_window->SetCursorBounds(cursor1_bounds, cursor1_bounds);
EXPECT_TRUE(imm->SwitchToNextInputMethod());
mi1_bounds = observer.last_bounds();
// The bounds should be bigger than the inner size.
EXPECT_LE(kInnerSize, mi1_bounds.width());
EXPECT_LE(kInnerSize, mi1_bounds.height());
EXPECT_TRUE(observer.is_displayed());
}
// Check if the location of the mode indicator is coresponded to
// the cursor bounds.
gfx::Rect cursor2_bounds(50, 200, 1, 20);
gfx::Rect mi2_bounds;
{
ScopedModeIndicatorObserverForTesting observer;
candidate_window->SetCursorBounds(cursor2_bounds, cursor2_bounds);
EXPECT_TRUE(imm->SwitchToNextInputMethod());
mi2_bounds = observer.last_bounds();
EXPECT_TRUE(observer.is_displayed());
}
EXPECT_EQ(cursor1_bounds.x() - cursor2_bounds.x(),
mi1_bounds.x() - mi2_bounds.x());
EXPECT_EQ(cursor1_bounds.y() - cursor2_bounds.y(),
mi1_bounds.y() - mi2_bounds.y());
EXPECT_EQ(mi1_bounds.width(), mi2_bounds.width());
EXPECT_EQ(mi1_bounds.height(), mi2_bounds.height());
const gfx::Rect screen_bounds =
ash::Shell::GetScreen()->GetDisplayMatching(cursor1_bounds).work_area();
// Check if the location of the mode indicator is concidered with
// the screen size.
const gfx::Rect cursor3_bounds(100, screen_bounds.bottom() - 25, 1, 20);
gfx::Rect mi3_bounds;
{
ScopedModeIndicatorObserverForTesting observer;
candidate_window->SetCursorBounds(cursor3_bounds, cursor3_bounds);
EXPECT_TRUE(imm->SwitchToNextInputMethod());
mi3_bounds = observer.last_bounds();
EXPECT_TRUE(observer.is_displayed());
EXPECT_LT(mi3_bounds.bottom(), screen_bounds.bottom());
}
}
IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest, NumOfWidgets) {
InitializeIMF();
InputMethodManager* imm = InputMethodManager::Get();
ASSERT_TRUE(imm);
std::vector<std::string> keyboard_layouts;
keyboard_layouts.push_back(
extension_ime_util::GetInputMethodIDByEngineID("xkb:fr::fra"));
// Add keyboard layouts to enable the mode indicator.
imm->EnableLoginLayouts("fr", keyboard_layouts);
ASSERT_LT(1UL, imm->GetNumActiveInputMethods());
chromeos::IMECandidateWindowHandlerInterface* candidate_window =
chromeos::IMEBridge::Get()->GetCandidateWindowHandler();
candidate_window->FocusStateChanged(true);
{
ScopedModeIndicatorObserverForTesting observer;
EXPECT_TRUE(imm->SwitchToNextInputMethod());
EXPECT_EQ(1UL, observer.max_widget_list_size());
const views::Widget* widget1 = observer.widget_list()[0];
EXPECT_TRUE(imm->SwitchToNextInputMethod());
EXPECT_EQ(2UL, observer.max_widget_list_size());
// When a new mode indicator is displayed, the previous one should be
// closed.
content::RunAllPendingInMessageLoop();
EXPECT_EQ(1UL, observer.widget_list_size());
const views::Widget* widget2 = observer.widget_list()[0];
EXPECT_NE(widget1, widget2);
}
}
} // namespace input_method
} // namespace chromeos