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