• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/test/base/view_event_test_base.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/test/base/chrome_unit_test_suite.h"
12 #include "chrome/test/base/interactive_test_utils.h"
13 #include "chrome/test/base/testing_browser_process.h"
14 #include "chrome/test/base/ui_test_utils.h"
15 #include "ui/aura/client/event_client.h"
16 #include "ui/aura/env.h"
17 #include "ui/aura/test/aura_test_helper.h"
18 #include "ui/aura/window_event_dispatcher.h"
19 #include "ui/aura/window_tree_host.h"
20 #include "ui/base/ime/input_method_initializer.h"
21 #include "ui/base/test/ui_controls.h"
22 #include "ui/compositor/test/context_factories_for_test.h"
23 #include "ui/compositor/test/context_factories_for_test.h"
24 #include "ui/message_center/message_center.h"
25 #include "ui/views/view.h"
26 #include "ui/views/widget/widget.h"
27 #include "ui/wm/core/default_activation_client.h"
28 #include "ui/wm/core/wm_state.h"
29 
30 #if defined(USE_ASH)
31 #include "ash/shell.h"
32 #include "ash/shell_init_params.h"
33 #include "ash/test/test_session_state_delegate.h"
34 #include "ash/test/test_shell_delegate.h"
35 #endif
36 
37 #if defined(OS_CHROMEOS)
38 #include "chromeos/audio/cras_audio_handler.h"
39 #include "chromeos/dbus/dbus_thread_manager.h"
40 #include "chromeos/network/network_handler.h"
41 #else  // !defined(OS_CHROMEOS)
42 #include "ui/views/widget/desktop_aura/desktop_screen.h"
43 #endif
44 
45 namespace {
46 
47 // View subclass that allows you to specify the preferred size.
48 class TestView : public views::View {
49  public:
TestView()50   TestView() {}
51 
SetPreferredSize(const gfx::Size & size)52   void SetPreferredSize(const gfx::Size& size) {
53     preferred_size_ = size;
54     PreferredSizeChanged();
55   }
56 
GetPreferredSize() const57   virtual gfx::Size GetPreferredSize() const OVERRIDE {
58     if (!preferred_size_.IsEmpty())
59       return preferred_size_;
60     return View::GetPreferredSize();
61   }
62 
Layout()63   virtual void Layout() OVERRIDE {
64     View* child_view = child_at(0);
65     child_view->SetBounds(0, 0, width(), height());
66   }
67 
68  private:
69   gfx::Size preferred_size_;
70 
71   DISALLOW_COPY_AND_ASSIGN(TestView);
72 };
73 
74 // Delay in background thread before posting mouse move.
75 const int kMouseMoveDelayMS = 200;
76 
77 }  // namespace
78 
ViewEventTestBase()79 ViewEventTestBase::ViewEventTestBase()
80   : window_(NULL),
81     content_view_(NULL) {
82   // The TestingBrowserProcess must be created in the constructor because there
83   // are tests that require it before SetUp() is called.
84   TestingBrowserProcess::CreateInstance();
85 }
86 
Done()87 void ViewEventTestBase::Done() {
88   base::MessageLoop::current()->Quit();
89 
90   // If we're in a nested message loop, as is the case with menus, we
91   // need to quit twice. The second quit does that for us. Finish all
92   // pending UI events before posting closure because events it may be
93   // executed before UI events are executed.
94   ui_controls::RunClosureAfterAllPendingUIEvents(
95       base::MessageLoop::QuitClosure());
96 }
97 
SetUpTestCase()98 void ViewEventTestBase::SetUpTestCase() {
99   ChromeUnitTestSuite::InitializeProviders();
100   ChromeUnitTestSuite::InitializeResourceBundle();
101 }
102 
SetUp()103 void ViewEventTestBase::SetUp() {
104   wm_state_.reset(new wm::WMState);
105 
106   views::ViewsDelegate::views_delegate = &views_delegate_;
107   ui::InitializeInputMethodForTesting();
108   gfx::NativeView context = NULL;
109 
110   // The ContextFactory must exist before any Compositors are created.
111   bool enable_pixel_output = false;
112   ui::ContextFactory* context_factory =
113       ui::InitializeContextFactoryForTests(enable_pixel_output);
114 
115 #if defined(OS_CHROMEOS)
116   // Ash Shell can't just live on its own without a browser process, we need to
117   // also create the message center.
118   message_center::MessageCenter::Initialize();
119   chromeos::DBusThreadManager::InitializeWithStub();
120   chromeos::CrasAudioHandler::InitializeForTesting();
121   chromeos::NetworkHandler::Initialize();
122   ash::test::TestShellDelegate* shell_delegate =
123       new ash::test::TestShellDelegate();
124   ash::ShellInitParams init_params;
125   init_params.delegate = shell_delegate;
126   init_params.context_factory = context_factory;
127   ash::Shell::CreateInstance(init_params);
128   shell_delegate->test_session_state_delegate()
129       ->SetActiveUserSessionStarted(true);
130   context = ash::Shell::GetPrimaryRootWindow();
131   context->GetHost()->Show();
132 #elif defined(USE_ASH)
133   // http://crbug.com/154081 use ash::Shell code path below on win_ash bots when
134   // interactive_ui_tests is brought up on that platform.
135   gfx::Screen::SetScreenInstance(
136       gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
137   aura::Env::CreateInstance(true);
138   aura::Env::GetInstance()->set_context_factory(context_factory);
139 #elif defined(USE_AURA)
140   // Instead of using the ash shell, use an AuraTestHelper to create and manage
141   // the test screen.
142   aura_test_helper_.reset(
143       new aura::test::AuraTestHelper(base::MessageLoopForUI::current()));
144   aura_test_helper_->SetUp(context_factory);
145   new wm::DefaultActivationClient(aura_test_helper_->root_window());
146   context = aura_test_helper_->root_window();
147 #endif
148 
149   window_ = views::Widget::CreateWindowWithContext(this, context);
150 }
151 
TearDown()152 void ViewEventTestBase::TearDown() {
153   if (window_) {
154     window_->Close();
155     content::RunAllPendingInMessageLoop();
156     window_ = NULL;
157   }
158 
159   ui::Clipboard::DestroyClipboardForCurrentThread();
160 
161 #if defined(USE_ASH)
162 #if defined(OS_CHROMEOS)
163   ash::Shell::DeleteInstance();
164   chromeos::NetworkHandler::Shutdown();
165   chromeos::CrasAudioHandler::Shutdown();
166   chromeos::DBusThreadManager::Shutdown();
167   // Ash Shell can't just live on its own without a browser process, we need to
168   // also shut down the message center.
169   message_center::MessageCenter::Shutdown();
170 #endif
171   aura::Env::DeleteInstance();
172 #elif defined(USE_AURA)
173   aura_test_helper_->TearDown();
174 #endif  // !USE_ASH && USE_AURA
175 
176   ui::TerminateContextFactoryForTests();
177 
178   ui::ShutdownInputMethodForTesting();
179   views::ViewsDelegate::views_delegate = NULL;
180 
181   wm_state_.reset();
182 }
183 
CanResize() const184 bool ViewEventTestBase::CanResize() const {
185   return true;
186 }
187 
GetContentsView()188 views::View* ViewEventTestBase::GetContentsView() {
189   if (!content_view_) {
190     // Wrap the real view (as returned by CreateContentsView) in a View so
191     // that we can customize the preferred size.
192     TestView* test_view = new TestView();
193     test_view->SetPreferredSize(GetPreferredSize());
194     test_view->AddChildView(CreateContentsView());
195     content_view_ = test_view;
196   }
197   return content_view_;
198 }
199 
GetWidget() const200 const views::Widget* ViewEventTestBase::GetWidget() const {
201   return content_view_->GetWidget();
202 }
203 
GetWidget()204 views::Widget* ViewEventTestBase::GetWidget() {
205   return content_view_->GetWidget();
206 }
207 
~ViewEventTestBase()208 ViewEventTestBase::~ViewEventTestBase() {
209   TestingBrowserProcess::DeleteInstance();
210 }
211 
StartMessageLoopAndRunTest()212 void ViewEventTestBase::StartMessageLoopAndRunTest() {
213   ASSERT_TRUE(
214       ui_test_utils::ShowAndFocusNativeWindow(window_->GetNativeWindow()));
215 
216   // Flush any pending events to make sure we start with a clean slate.
217   content::RunAllPendingInMessageLoop();
218 
219   // Schedule a task that starts the test. Need to do this as we're going to
220   // run the message loop.
221   base::MessageLoop::current()->PostTask(
222       FROM_HERE, base::Bind(&ViewEventTestBase::DoTestOnMessageLoop, this));
223 
224   content::RunMessageLoop();
225 }
226 
GetPreferredSize() const227 gfx::Size ViewEventTestBase::GetPreferredSize() const {
228   return gfx::Size();
229 }
230 
ScheduleMouseMoveInBackground(int x,int y)231 void ViewEventTestBase::ScheduleMouseMoveInBackground(int x, int y) {
232   if (!dnd_thread_.get()) {
233     dnd_thread_.reset(new base::Thread("mouse-move-thread"));
234     dnd_thread_->Start();
235   }
236   dnd_thread_->message_loop()->PostDelayedTask(
237       FROM_HERE,
238       base::Bind(base::IgnoreResult(&ui_controls::SendMouseMove), x, y),
239       base::TimeDelta::FromMilliseconds(kMouseMoveDelayMS));
240 }
241 
StopBackgroundThread()242 void ViewEventTestBase::StopBackgroundThread() {
243   dnd_thread_.reset(NULL);
244 }
245 
RunTestMethod(const base::Closure & task)246 void ViewEventTestBase::RunTestMethod(const base::Closure& task) {
247   StopBackgroundThread();
248 
249   task.Run();
250   if (HasFatalFailure())
251     Done();
252 }
253