Home | History | Annotate | Download | only in base
      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:
     50   TestView() {}
     51 
     52   void SetPreferredSize(const gfx::Size& size) {
     53     preferred_size_ = size;
     54     PreferredSizeChanged();
     55   }
     56 
     57   virtual gfx::Size GetPreferredSize() const OVERRIDE {
     58     if (!preferred_size_.IsEmpty())
     59       return preferred_size_;
     60     return View::GetPreferredSize();
     61   }
     62 
     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 
     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 
     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 
     98 void ViewEventTestBase::SetUpTestCase() {
     99   ChromeUnitTestSuite::InitializeProviders();
    100   ChromeUnitTestSuite::InitializeResourceBundle();
    101 }
    102 
    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 
    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 
    184 bool ViewEventTestBase::CanResize() const {
    185   return true;
    186 }
    187 
    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 
    200 const views::Widget* ViewEventTestBase::GetWidget() const {
    201   return content_view_->GetWidget();
    202 }
    203 
    204 views::Widget* ViewEventTestBase::GetWidget() {
    205   return content_view_->GetWidget();
    206 }
    207 
    208 ViewEventTestBase::~ViewEventTestBase() {
    209   TestingBrowserProcess::DeleteInstance();
    210 }
    211 
    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 
    227 gfx::Size ViewEventTestBase::GetPreferredSize() const {
    228   return gfx::Size();
    229 }
    230 
    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 
    242 void ViewEventTestBase::StopBackgroundThread() {
    243   dnd_thread_.reset(NULL);
    244 }
    245 
    246 void ViewEventTestBase::RunTestMethod(const base::Closure& task) {
    247   StopBackgroundThread();
    248 
    249   task.Run();
    250   if (HasFatalFailure())
    251     Done();
    252 }
    253