15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/view_event_test_base.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/test/base/chrome_unit_test_suite.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/interactive_test_utils.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/test/base/testing_browser_process.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/test/base/view_event_test_platform_part.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/base/ime/input_method_initializer.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/test/ui_controls.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/compositor/test/context_factories_for_test.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// View subclass that allows you to specify the preferred size.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestView : public views::View {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestView() {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPreferredSize(const gfx::Size& size) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preferred_size_ = size;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PreferredSizeChanged();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() const OVERRIDE {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!preferred_size_.IsEmpty())
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return preferred_size_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return View::GetPreferredSize();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Layout() OVERRIDE {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    View* child_view = child_at(0);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child_view->SetBounds(0, 0, width(), height());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size preferred_size_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestView);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay in background thread before posting mouse move.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMouseMoveDelayMS = 200;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewEventTestBase::ViewEventTestBase()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : window_(NULL),
55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    content_view_(NULL) {
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The TestingBrowserProcess must be created in the constructor because there
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // are tests that require it before SetUp() is called.
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TestingBrowserProcess::CreateInstance();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::Done() {
62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::MessageLoop::current()->Quit();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're in a nested message loop, as is the case with menus, we
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to quit twice. The second quit does that for us. Finish all
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending UI events before posting closure because events it may be
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // executed before UI events are executed.
68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ui_controls::RunClosureAfterAllPendingUIEvents(
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::MessageLoop::QuitClosure());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ViewEventTestBase::SetUpTestCase() {
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ChromeUnitTestSuite::InitializeProviders();
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ChromeUnitTestSuite::InitializeResourceBundle();
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::SetUp() {
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  views::ViewsDelegate::views_delegate = &views_delegate_;
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui::InitializeInputMethodForTesting();
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The ContextFactory must exist before any Compositors are created.
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool enable_pixel_output = false;
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ui::ContextFactory* context_factory =
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ui::InitializeContextFactoryForTests(enable_pixel_output);
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  platform_part_.reset(ViewEventTestPlatformPart::Create(context_factory));
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  gfx::NativeWindow context = platform_part_->GetContext();
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window_ = views::Widget::CreateWindowWithContext(this, context);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::TearDown() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_->Close();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RunAllPendingInMessageLoop();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_ = NULL;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::Clipboard::DestroyClipboardForCurrentThread();
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  platform_part_.reset();
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::TerminateContextFactoryForTests();
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui::ShutdownInputMethodForTesting();
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  views::ViewsDelegate::views_delegate = NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewEventTestBase::CanResize() const {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::View* ViewEventTestBase::GetContentsView() {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!content_view_) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wrap the real view (as returned by CreateContentsView) in a View so
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that we can customize the preferred size.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestView* test_view = new TestView();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_view->SetPreferredSize(GetPreferredSize());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_view->AddChildView(CreateContentsView());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content_view_ = test_view;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return content_view_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const views::Widget* ViewEventTestBase::GetWidget() const {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return content_view_->GetWidget();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)views::Widget* ViewEventTestBase::GetWidget() {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return content_view_->GetWidget();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewEventTestBase::~ViewEventTestBase() {
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TestingBrowserProcess::DeleteInstance();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::StartMessageLoopAndRunTest() {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui_test_utils::ShowAndFocusNativeWindow(window_->GetNativeWindow()));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush any pending events to make sure we start with a clean slate.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RunAllPendingInMessageLoop();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule a task that starts the test. Need to do this as we're going to
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // run the message loop.
144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      FROM_HERE, base::Bind(&ViewEventTestBase::DoTestOnMessageLoop, this));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RunMessageLoop();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ViewEventTestBase::GetPreferredSize() const {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Size();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::ScheduleMouseMoveInBackground(int x, int y) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dnd_thread_.get()) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dnd_thread_.reset(new base::Thread("mouse-move-thread"));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dnd_thread_->Start();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dnd_thread_->message_loop()->PostDelayedTask(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(base::IgnoreResult(&ui_controls::SendMouseMove), x, y),
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMouseMoveDelayMS));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::StopBackgroundThread() {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dnd_thread_.reset(NULL);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewEventTestBase::RunTestMethod(const base::Closure& task) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopBackgroundThread();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  task.Run();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasFatalFailure())
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Done();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
176