ash_test_base.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/test/ash_test_base.h"
6
7#include <string>
8#include <vector>
9
10#include "ash/ash_switches.h"
11#include "ash/display/display_controller.h"
12#include "ash/shell.h"
13#include "ash/shell/toplevel_window.h"
14#include "ash/test/ash_test_helper.h"
15#include "ash/test/display_manager_test_api.h"
16#include "ash/test/test_session_state_delegate.h"
17#include "ash/test/test_shell_delegate.h"
18#include "ash/test/test_system_tray_delegate.h"
19#include "ash/wm/coordinate_conversion.h"
20#include "ash/wm/window_positioner.h"
21#include "base/command_line.h"
22#include "ui/aura/client/aura_constants.h"
23#include "ui/aura/client/screen_position_client.h"
24#include "ui/aura/client/window_tree_client.h"
25#include "ui/aura/test/event_generator.h"
26#include "ui/aura/test/test_window_delegate.h"
27#include "ui/aura/window.h"
28#include "ui/aura/window_delegate.h"
29#include "ui/aura/window_tree_host.h"
30#include "ui/base/ime/input_method_initializer.h"
31#include "ui/events/gestures/gesture_configuration.h"
32#include "ui/gfx/display.h"
33#include "ui/gfx/point.h"
34#include "ui/gfx/screen.h"
35
36#if defined(OS_CHROMEOS)
37#include "ash/system/chromeos/tray_display.h"
38#endif
39
40#if defined(OS_WIN)
41#include "ash/test/test_metro_viewer_process_host.h"
42#include "base/test/test_process_killer_win.h"
43#include "base/win/metro.h"
44#include "base/win/windows_version.h"
45#include "ui/aura/remote_window_tree_host_win.h"
46#include "ui/aura/window_tree_host_win.h"
47#include "win8/test/test_registrar_constants.h"
48#endif
49
50#if defined(USE_X11)
51#include "ui/gfx/x/x11_connection.h"
52#endif
53
54namespace ash {
55namespace test {
56namespace {
57
58class AshEventGeneratorDelegate
59    : public aura::test::EventGeneratorDelegateAura {
60 public:
61  AshEventGeneratorDelegate() {}
62  virtual ~AshEventGeneratorDelegate() {}
63
64  // aura::test::EventGeneratorDelegateAura overrides:
65  virtual aura::WindowTreeHost* GetHostAt(
66      const gfx::Point& point_in_screen) const OVERRIDE {
67    gfx::Screen* screen = Shell::GetScreen();
68    gfx::Display display = screen->GetDisplayNearestPoint(point_in_screen);
69    return Shell::GetInstance()->display_controller()->
70        GetRootWindowForDisplayId(display.id())->GetHost();
71  }
72
73  virtual aura::client::ScreenPositionClient* GetScreenPositionClient(
74      const aura::Window* window) const OVERRIDE {
75    return aura::client::GetScreenPositionClient(window->GetRootWindow());
76  }
77
78 private:
79  DISALLOW_COPY_AND_ASSIGN(AshEventGeneratorDelegate);
80};
81
82}  // namespace
83
84/////////////////////////////////////////////////////////////////////////////
85
86AshTestBase::AshTestBase()
87    : setup_called_(false),
88      teardown_called_(false),
89      start_session_(true) {
90#if defined(USE_X11)
91  // This is needed for tests which use this base class but are run in browser
92  // test binaries so don't get the default initialization in the unit test
93  // suite.
94  gfx::InitializeThreadedX11();
95#endif
96
97  thread_bundle_.reset(new content::TestBrowserThreadBundle);
98  // Must initialize |ash_test_helper_| here because some tests rely on
99  // AshTestBase methods before they call AshTestBase::SetUp().
100  ash_test_helper_.reset(new AshTestHelper(base::MessageLoopForUI::current()));
101}
102
103AshTestBase::~AshTestBase() {
104  CHECK(setup_called_)
105      << "You have overridden SetUp but never called AshTestBase::SetUp";
106  CHECK(teardown_called_)
107      << "You have overridden TearDown but never called AshTestBase::TearDown";
108}
109
110void AshTestBase::SetUp() {
111  setup_called_ = true;
112
113  // Clears the saved state so that test doesn't use on the wrong
114  // default state.
115  shell::ToplevelWindow::ClearSavedStateForTest();
116
117  // TODO(jamescook): Can we do this without changing command line?
118  // Use the origin (1,1) so that it doesn't over
119  // lap with the native mouse cursor.
120  CommandLine* command_line = CommandLine::ForCurrentProcess();
121  if (!command_line->HasSwitch(switches::kAshHostWindowBounds)) {
122    command_line->AppendSwitchASCII(
123        switches::kAshHostWindowBounds, "1+1-800x600");
124  }
125#if defined(OS_WIN)
126  aura::test::SetUsePopupAsRootWindowForTest(true);
127#endif
128  ash_test_helper_->SetUp(start_session_);
129
130  Shell::GetPrimaryRootWindow()->Show();
131  Shell::GetPrimaryRootWindow()->GetHost()->Show();
132  // Move the mouse cursor to far away so that native events doesn't
133  // interfere test expectations.
134  Shell::GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(-1000, -1000));
135  ash::Shell::GetInstance()->cursor_manager()->EnableMouseEvents();
136
137  // Changing GestureConfiguration shouldn't make tests fail.
138  ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(5);
139
140#if defined(OS_WIN)
141  if (!command_line->HasSwitch(ash::switches::kForceAshToDesktop)) {
142    if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
143      ipc_thread_.reset(new base::Thread("test_metro_viewer_ipc_thread"));
144      base::Thread::Options options;
145      options.message_loop_type = base::MessageLoop::TYPE_IO;
146      ipc_thread_->StartWithOptions(options);
147      metro_viewer_host_.reset(
148          new TestMetroViewerProcessHost(ipc_thread_->message_loop_proxy()));
149      CHECK(metro_viewer_host_->LaunchViewerAndWaitForConnection(
150          win8::test::kDefaultTestAppUserModelId));
151      aura::RemoteWindowTreeHostWin* window_tree_host =
152          aura::RemoteWindowTreeHostWin::Instance();
153      CHECK(window_tree_host != NULL);
154    }
155    ash::WindowPositioner::SetMaximizeFirstWindow(true);
156  }
157#endif
158}
159
160void AshTestBase::TearDown() {
161  teardown_called_ = true;
162  // Flush the message loop to finish pending release tasks.
163  RunAllPendingInMessageLoop();
164
165#if defined(OS_WIN)
166  if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
167      !CommandLine::ForCurrentProcess()->HasSwitch(
168          ash::switches::kForceAshToDesktop)) {
169    // Check that our viewer connection is still established.
170    CHECK(!metro_viewer_host_->closed_unexpectedly());
171  }
172#endif
173
174  ash_test_helper_->TearDown();
175#if defined(OS_WIN)
176  aura::test::SetUsePopupAsRootWindowForTest(false);
177  // Kill the viewer process if we spun one up.
178  metro_viewer_host_.reset();
179
180  // Clean up any dangling viewer processes as the metro APIs sometimes leave
181  // zombies behind. A default browser process in metro will have the
182  // following command line arg so use that to avoid killing all processes named
183  // win8::test::kDefaultTestExePath.
184  const wchar_t kViewerProcessArgument[] = L"DefaultBrowserServer";
185  base::KillAllNamedProcessesWithArgument(win8::test::kDefaultTestExePath,
186                                          kViewerProcessArgument);
187#endif
188
189  event_generator_.reset();
190  // Some tests set an internal display id,
191  // reset it here, so other tests will continue in a clean environment.
192  gfx::Display::SetInternalDisplayId(gfx::Display::kInvalidDisplayID);
193}
194
195ui::test::EventGenerator& AshTestBase::GetEventGenerator() {
196  if (!event_generator_) {
197    event_generator_.reset(
198        new ui::test::EventGenerator(new AshEventGeneratorDelegate()));
199  }
200  return *event_generator_.get();
201}
202
203bool AshTestBase::SupportsMultipleDisplays() {
204  return AshTestHelper::SupportsMultipleDisplays();
205}
206
207bool AshTestBase::SupportsHostWindowResize() {
208  return AshTestHelper::SupportsHostWindowResize();
209}
210
211void AshTestBase::UpdateDisplay(const std::string& display_specs) {
212  DisplayManagerTestApi display_manager_test_api(
213      Shell::GetInstance()->display_manager());
214  display_manager_test_api.UpdateDisplay(display_specs);
215}
216
217aura::Window* AshTestBase::CurrentContext() {
218  return ash_test_helper_->CurrentContext();
219}
220
221aura::Window* AshTestBase::CreateTestWindowInShellWithId(int id) {
222  return CreateTestWindowInShellWithDelegate(NULL, id, gfx::Rect());
223}
224
225aura::Window* AshTestBase::CreateTestWindowInShellWithBounds(
226    const gfx::Rect& bounds) {
227  return CreateTestWindowInShellWithDelegate(NULL, 0, bounds);
228}
229
230aura::Window* AshTestBase::CreateTestWindowInShell(SkColor color,
231                                                   int id,
232                                                   const gfx::Rect& bounds) {
233  return CreateTestWindowInShellWithDelegate(
234      new aura::test::ColorTestWindowDelegate(color), id, bounds);
235}
236
237aura::Window* AshTestBase::CreateTestWindowInShellWithDelegate(
238    aura::WindowDelegate* delegate,
239    int id,
240    const gfx::Rect& bounds) {
241  return CreateTestWindowInShellWithDelegateAndType(
242      delegate, ui::wm::WINDOW_TYPE_NORMAL, id, bounds);
243}
244
245aura::Window* AshTestBase::CreateTestWindowInShellWithDelegateAndType(
246    aura::WindowDelegate* delegate,
247    ui::wm::WindowType type,
248    int id,
249    const gfx::Rect& bounds) {
250  aura::Window* window = new aura::Window(delegate);
251  window->set_id(id);
252  window->SetType(type);
253  window->Init(aura::WINDOW_LAYER_TEXTURED);
254  window->Show();
255
256  if (bounds.IsEmpty()) {
257    ParentWindowInPrimaryRootWindow(window);
258  } else {
259    gfx::Display display =
260        Shell::GetScreen()->GetDisplayMatching(bounds);
261    aura::Window* root = ash::Shell::GetInstance()->display_controller()->
262        GetRootWindowForDisplayId(display.id());
263    gfx::Point origin = bounds.origin();
264    wm::ConvertPointFromScreen(root, &origin);
265    window->SetBounds(gfx::Rect(origin, bounds.size()));
266    aura::client::ParentWindowWithContext(window, root, bounds);
267  }
268  window->SetProperty(aura::client::kCanMaximizeKey, true);
269  return window;
270}
271
272void AshTestBase::ParentWindowInPrimaryRootWindow(aura::Window* window) {
273  aura::client::ParentWindowWithContext(
274      window, Shell::GetPrimaryRootWindow(), gfx::Rect());
275}
276
277void AshTestBase::RunAllPendingInMessageLoop() {
278  ash_test_helper_->RunAllPendingInMessageLoop();
279}
280
281TestScreenshotDelegate* AshTestBase::GetScreenshotDelegate() {
282  return ash_test_helper_->test_screenshot_delegate();
283}
284
285TestSystemTrayDelegate* AshTestBase::GetSystemTrayDelegate() {
286  return static_cast<TestSystemTrayDelegate*>(
287      Shell::GetInstance()->system_tray_delegate());
288}
289
290void AshTestBase::SetSessionStarted(bool session_started) {
291  ash_test_helper_->test_shell_delegate()->test_session_state_delegate()->
292      SetActiveUserSessionStarted(session_started);
293}
294
295void AshTestBase::SetUserLoggedIn(bool user_logged_in) {
296  ash_test_helper_->test_shell_delegate()->test_session_state_delegate()->
297      SetHasActiveUser(user_logged_in);
298}
299
300void AshTestBase::SetCanLockScreen(bool can_lock_screen) {
301  ash_test_helper_->test_shell_delegate()->test_session_state_delegate()->
302      SetCanLockScreen(can_lock_screen);
303}
304
305void AshTestBase::SetShouldLockScreenBeforeSuspending(bool should_lock) {
306  ash_test_helper_->test_shell_delegate()->test_session_state_delegate()->
307      SetShouldLockScreenBeforeSuspending(should_lock);
308}
309
310void AshTestBase::SetUserAddingScreenRunning(bool user_adding_screen_running) {
311  ash_test_helper_->test_shell_delegate()->test_session_state_delegate()->
312      SetUserAddingScreenRunning(user_adding_screen_running);
313}
314
315void AshTestBase::BlockUserSession(UserSessionBlockReason block_reason) {
316  switch (block_reason) {
317    case BLOCKED_BY_LOCK_SCREEN:
318      SetSessionStarted(true);
319      SetUserAddingScreenRunning(false);
320      Shell::GetInstance()->session_state_delegate()->LockScreen();
321      break;
322    case BLOCKED_BY_LOGIN_SCREEN:
323      SetUserAddingScreenRunning(false);
324      SetSessionStarted(false);
325      break;
326    case BLOCKED_BY_USER_ADDING_SCREEN:
327      SetUserAddingScreenRunning(true);
328      SetSessionStarted(true);
329      break;
330    default:
331      NOTREACHED();
332      break;
333  }
334}
335
336void AshTestBase::UnblockUserSession() {
337  Shell::GetInstance()->session_state_delegate()->UnlockScreen();
338  SetSessionStarted(true);
339  SetUserAddingScreenRunning(false);
340}
341
342
343}  // namespace test
344}  // namespace ash
345