blob: d98b4a66a4d77b3d9c3b8a2edc3c9541c62017b5 [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 "ash/test/ash_test_base.h"
#include <string>
#include <vector>
#include "ash/common/session/session_controller.h"
#include "ash/common/test/test_session_controller_client.h"
#include "ash/common/test/test_system_tray_delegate.h"
#include "ash/common/wm/window_positioner.h"
#include "ash/common/wm_shell.h"
#include "ash/common/wm_window.h"
#include "ash/display/extended_mouse_warp_controller.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/display/unified_mouse_warp_controller.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/ime/input_method_event_handler.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/shell/toplevel_window.h"
#include "ash/test/ash_test_environment.h"
#include "ash/test/ash_test_helper.h"
#include "ash/test/test_shell_delegate.h"
#include "base/command_line.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/test/event_generator_delegate_aura.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/input_method_initializer.h"
#include "ui/display/display.h"
#include "ui/display/display_switches.h"
#include "ui/display/screen.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/gfx/geometry/point.h"
#include "ui/wm/core/coordinate_conversion.h"
#if defined(USE_X11)
#include "ui/gfx/x/x11_connection.h" // nogncheck
#endif
namespace ash {
namespace test {
namespace {
class AshEventGeneratorDelegate
: public aura::test::EventGeneratorDelegateAura {
public:
AshEventGeneratorDelegate() {}
~AshEventGeneratorDelegate() override {}
// aura::test::EventGeneratorDelegateAura overrides:
aura::WindowTreeHost* GetHostAt(
const gfx::Point& point_in_screen) const override {
display::Screen* screen = display::Screen::GetScreen();
display::Display display = screen->GetDisplayNearestPoint(point_in_screen);
return WmShell::Get()
->GetRootWindowForDisplayId(display.id())
->aura_window()
->GetHost();
}
aura::client::ScreenPositionClient* GetScreenPositionClient(
const aura::Window* window) const override {
return aura::client::GetScreenPositionClient(window->GetRootWindow());
}
void DispatchKeyEventToIME(ui::EventTarget* target,
ui::KeyEvent* event) override {
// In Ash environment, the key event will be processed by event rewriters
// first.
}
private:
DISALLOW_COPY_AND_ASSIGN(AshEventGeneratorDelegate);
};
} // namespace
/////////////////////////////////////////////////////////////////////////////
AshTestBase::AshTestBase()
: setup_called_(false), teardown_called_(false), start_session_(true) {
#if defined(USE_X11)
// This is needed for tests which use this base class but are run in browser
// test binaries so don't get the default initialization in the unit test
// suite.
gfx::InitializeThreadedX11();
#endif
ash_test_environment_ = AshTestEnvironment::Create();
// Must initialize |ash_test_helper_| here because some tests rely on
// AshTestBase methods before they call AshTestBase::SetUp().
ash_test_helper_.reset(new AshTestHelper(ash_test_environment_.get()));
}
AshTestBase::~AshTestBase() {
CHECK(setup_called_)
<< "You have overridden SetUp but never called AshTestBase::SetUp";
CHECK(teardown_called_)
<< "You have overridden TearDown but never called AshTestBase::TearDown";
}
void AshTestBase::SetUp() {
setup_called_ = true;
// Clears the saved state so that test doesn't use on the wrong
// default state.
shell::ToplevelWindow::ClearSavedStateForTest();
// TODO(jamescook): Can we do this without changing command line?
// Use the origin (1,1) so that it doesn't over
// lap with the native mouse cursor.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(::switches::kHostWindowBounds)) {
command_line->AppendSwitchASCII(::switches::kHostWindowBounds,
"1+1-800x600");
}
ash_test_helper_->SetUp(start_session_);
Shell::GetPrimaryRootWindow()->Show();
Shell::GetPrimaryRootWindow()->GetHost()->Show();
// Move the mouse cursor to far away so that native events doesn't
// interfere test expectations.
Shell::GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(-1000, -1000));
// TODO: mash needs to support CursorManager. http://crbug.com/637853.
if (!WmShell::Get()->IsRunningInMash())
Shell::GetInstance()->cursor_manager()->EnableMouseEvents();
// Changing GestureConfiguration shouldn't make tests fail. These values
// prevent unexpected events from being generated during tests. Such as
// delayed events which create race conditions on slower tests.
ui::GestureConfiguration* gesture_config =
ui::GestureConfiguration::GetInstance();
gesture_config->set_max_touch_down_duration_for_click_in_ms(800);
gesture_config->set_long_press_time_in_ms(1000);
gesture_config->set_max_touch_move_in_pixels_for_click(5);
}
void AshTestBase::TearDown() {
teardown_called_ = true;
Shell::GetInstance()->OnAppTerminating();
// Flush the message loop to finish pending release tasks.
RunAllPendingInMessageLoop();
ash_test_helper_->TearDown();
event_generator_.reset();
// Some tests set an internal display id,
// reset it here, so other tests will continue in a clean environment.
display::Display::SetInternalDisplayId(display::kInvalidDisplayId);
}
// static
WmShelf* AshTestBase::GetPrimaryShelf() {
return WmShell::Get()
->GetPrimaryRootWindow()
->GetRootWindowController()
->GetShelf();
}
// static
SystemTray* AshTestBase::GetPrimarySystemTray() {
return Shell::GetInstance()->GetPrimarySystemTray();
}
ui::test::EventGenerator& AshTestBase::GetEventGenerator() {
if (!event_generator_) {
event_generator_.reset(
new ui::test::EventGenerator(new AshEventGeneratorDelegate()));
}
return *event_generator_.get();
}
// static
display::Display::Rotation AshTestBase::GetActiveDisplayRotation(int64_t id) {
return Shell::GetInstance()
->display_manager()
->GetDisplayInfo(id)
.GetActiveRotation();
}
// static
display::Display::Rotation AshTestBase::GetCurrentInternalDisplayRotation() {
return GetActiveDisplayRotation(display::Display::InternalDisplayId());
}
// static
void AshTestBase::UpdateDisplay(const std::string& display_specs) {
if (WmShell::Get()->IsRunningInMash()) {
ash_test_helper_->UpdateDisplayForMash(display_specs);
} else {
display::test::DisplayManagerTestApi(
Shell::GetInstance()->display_manager())
.UpdateDisplay(display_specs);
}
}
aura::Window* AshTestBase::CurrentContext() {
return ash_test_helper_->CurrentContext();
}
// static
std::unique_ptr<views::Widget> AshTestBase::CreateTestWidget(
views::WidgetDelegate* delegate,
int container_id,
const gfx::Rect& bounds) {
std::unique_ptr<views::Widget> widget(new views::Widget);
views::Widget::InitParams params;
params.delegate = delegate;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = bounds;
WmShell::Get()
->GetPrimaryRootWindow()
->GetRootWindowController()
->ConfigureWidgetInitParamsForContainer(widget.get(), container_id,
&params);
widget->Init(params);
widget->Show();
return widget;
}
aura::Window* AshTestBase::CreateTestWindowInShellWithId(int id) {
return CreateTestWindowInShellWithDelegate(NULL, id, gfx::Rect());
}
aura::Window* AshTestBase::CreateTestWindowInShellWithBounds(
const gfx::Rect& bounds) {
return CreateTestWindowInShellWithDelegate(NULL, 0, bounds);
}
aura::Window* AshTestBase::CreateTestWindowInShell(SkColor color,
int id,
const gfx::Rect& bounds) {
return CreateTestWindowInShellWithDelegate(
new aura::test::ColorTestWindowDelegate(color), id, bounds);
}
aura::Window* AshTestBase::CreateTestWindowInShellWithDelegate(
aura::WindowDelegate* delegate,
int id,
const gfx::Rect& bounds) {
return CreateTestWindowInShellWithDelegateAndType(
delegate, ui::wm::WINDOW_TYPE_NORMAL, id, bounds);
}
aura::Window* AshTestBase::CreateTestWindowInShellWithDelegateAndType(
aura::WindowDelegate* delegate,
ui::wm::WindowType type,
int id,
const gfx::Rect& bounds) {
aura::Window* window = new aura::Window(delegate);
window->set_id(id);
window->SetType(type);
window->Init(ui::LAYER_TEXTURED);
window->Show();
if (bounds.IsEmpty()) {
ParentWindowInPrimaryRootWindow(window);
} else {
display::Display display =
display::Screen::GetScreen()->GetDisplayMatching(bounds);
aura::Window* root =
WmShell::Get()->GetRootWindowForDisplayId(display.id())->aura_window();
gfx::Point origin = bounds.origin();
::wm::ConvertPointFromScreen(root, &origin);
window->SetBounds(gfx::Rect(origin, bounds.size()));
aura::client::ParentWindowWithContext(window, root, bounds);
}
window->SetProperty(aura::client::kResizeBehaviorKey,
ui::mojom::kResizeBehaviorCanMaximize |
ui::mojom::kResizeBehaviorCanMinimize |
ui::mojom::kResizeBehaviorCanResize);
return window;
}
void AshTestBase::ParentWindowInPrimaryRootWindow(aura::Window* window) {
aura::client::ParentWindowWithContext(window, Shell::GetPrimaryRootWindow(),
gfx::Rect());
}
void AshTestBase::RunAllPendingInMessageLoop() {
ash_test_helper_->RunAllPendingInMessageLoop();
}
TestScreenshotDelegate* AshTestBase::GetScreenshotDelegate() {
return ash_test_helper_->test_screenshot_delegate();
}
TestSessionControllerClient* AshTestBase::GetSessionControllerClient() {
return ash_test_helper_->test_session_controller_client();
}
TestSystemTrayDelegate* AshTestBase::GetSystemTrayDelegate() {
return static_cast<TestSystemTrayDelegate*>(
Shell::Get()->system_tray_delegate());
}
void AshTestBase::SetSessionStarted(bool session_started) {
if (session_started)
GetSessionControllerClient()->CreatePredefinedUserSessions(1);
else
GetSessionControllerClient()->Reset();
}
void AshTestBase::SetUserLoggedIn(bool user_logged_in) {
SetSessionStarted(user_logged_in);
}
void AshTestBase::SetCanLockScreen(bool can_lock) {
GetSessionControllerClient()->SetCanLockScreen(can_lock);
}
void AshTestBase::SetShouldLockScreenAutomatically(bool should_lock) {
GetSessionControllerClient()->SetShouldLockScreenAutomatically(should_lock);
}
void AshTestBase::SetUserAddingScreenRunning(bool user_adding_screen_running) {
GetSessionControllerClient()->SetSessionState(
user_adding_screen_running
? session_manager::SessionState::LOGIN_SECONDARY
: session_manager::SessionState::ACTIVE);
}
void AshTestBase::BlockUserSession(UserSessionBlockReason block_reason) {
switch (block_reason) {
case BLOCKED_BY_LOCK_SCREEN:
SetSessionStarted(true);
Shell::Get()->session_controller()->LockScreenAndFlushForTest();
Shell::GetInstance()->OnLockStateChanged(true);
break;
case BLOCKED_BY_LOGIN_SCREEN:
SetSessionStarted(false);
break;
case BLOCKED_BY_USER_ADDING_SCREEN:
SetUserAddingScreenRunning(true);
break;
default:
NOTREACHED();
break;
}
}
void AshTestBase::UnblockUserSession() {
SetSessionStarted(true);
GetSessionControllerClient()->UnlockScreen();
}
void AshTestBase::DisableIME() {
// WindowTreeHostManager isn't applicable to mash and IME is routed
// differently in mash.
if (WmShell::Get()->IsRunningInMash())
return;
Shell::GetInstance()->RemovePreTargetHandler(
Shell::GetInstance()
->window_tree_host_manager()
->input_method_event_handler());
}
display::DisplayManager* AshTestBase::display_manager() {
return Shell::GetInstance()->display_manager();
}
bool AshTestBase::TestIfMouseWarpsAt(ui::test::EventGenerator& event_generator,
const gfx::Point& point_in_screen) {
DCHECK(!Shell::GetInstance()->display_manager()->IsInUnifiedMode());
static_cast<ExtendedMouseWarpController*>(
Shell::GetInstance()
->mouse_cursor_filter()
->mouse_warp_controller_for_test())
->allow_non_native_event_for_test();
display::Screen* screen = display::Screen::GetScreen();
display::Display original_display =
screen->GetDisplayNearestPoint(point_in_screen);
event_generator.MoveMouseTo(point_in_screen);
return original_display.id() !=
screen
->GetDisplayNearestPoint(
aura::Env::GetInstance()->last_mouse_location())
.id();
}
void AshTestBase::SwapPrimaryDisplay() {
if (display::Screen::GetScreen()->GetNumDisplays() <= 1)
return;
Shell::GetInstance()->window_tree_host_manager()->SetPrimaryDisplayId(
display_manager()->GetSecondaryDisplay().id());
}
display::Display AshTestBase::GetSecondaryDisplay() {
return ash_test_helper_->GetSecondaryDisplay();
}
} // namespace test
} // namespace ash