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