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