1// Copyright 2013 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/shelf/shelf.h"
6#include "ash/shelf/shelf_view.h"
7#include "ash/shell.h"
8#include "ash/test/shelf_test_api.h"
9#include "base/command_line.h"
10#include "base/message_loop/message_loop.h"
11#include "chrome/browser/lifetime/application_lifetime.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_list.h"
14#include "chrome/browser/ui/browser_window.h"
15#include "chrome/test/base/in_process_browser_test.h"
16#include "ui/aura/window_event_dispatcher.h"
17#include "ui/base/test/ui_controls.h"
18#include "ui/events/test/event_generator.h"
19#include "ui/views/controls/menu/menu_controller.h"
20#include "ui/views/view.h"
21#include "ui/views/view_model.h"
22
23namespace {
24
25class WindowSizerTest : public InProcessBrowserTest {
26 public:
27  WindowSizerTest() {}
28  virtual ~WindowSizerTest() {}
29
30  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
31    InProcessBrowserTest::SetUpCommandLine(command_line);
32    // Make screens sufficiently wide to host 2 browsers side by side.
33    command_line->AppendSwitchASCII("ash-host-window-bounds",
34                                    "600x600,601+0-600x600");
35  }
36
37 private:
38  DISALLOW_COPY_AND_ASSIGN(WindowSizerTest);
39};
40
41void CloseBrowser(Browser* browser) {
42  browser->window()->Close();
43  base::MessageLoop::current()->RunUntilIdle();
44}
45
46gfx::Rect GetChromeIconBoundsForRootWindow(aura::Window* root_window) {
47  ash::Shelf* shelf = ash::Shelf::ForWindow(root_window);
48  const ash::ShelfView* shelf_view =
49      ash::test::ShelfTestAPI(shelf).shelf_view();
50  const views::ViewModel* view_model = shelf_view->view_model_for_test();
51
52  EXPECT_EQ(2, view_model->view_size());
53  return view_model->view_at(1)->GetBoundsInScreen();
54}
55
56void OpenBrowserUsingShelfOnRootWindow(aura::Window* root_window) {
57  ui::test::EventGenerator generator(root_window);
58  gfx::Point center =
59      GetChromeIconBoundsForRootWindow(root_window).CenterPoint();
60  gfx::Display display =
61      ash::Shell::GetScreen()->GetDisplayNearestWindow(root_window);
62  const gfx::Point& origin = display.bounds().origin();
63  center.Offset(- origin.x(), - origin.y());
64  generator.MoveMouseTo(center);
65  generator.ClickLeftButton();
66}
67
68}  // namespace
69
70#if !defined(OS_CHROMEOS)
71#define MAYBE_OpenBrowserUsingShelfOnOtherDisplay DISABLED_OpenBrowserUsingShelfOnOtherDisplay
72#define MAYBE_OpenBrowserUsingContextMenuOnOtherDisplay DISABLED_OpenBrowserUsingContextMenuOnOtherDisplay
73#else
74#define MAYBE_OpenBrowserUsingShelfOnOtherDisplay OpenBrowserUsingShelfOnOtherDisplay
75#define MAYBE_OpenBrowserUsingContextMenuOnOtherDisplay OpenBrowserUsingContextMenuOnOtherDisplay
76#endif
77
78IN_PROC_BROWSER_TEST_F(WindowSizerTest,
79                       MAYBE_OpenBrowserUsingShelfOnOtherDisplay) {
80  // Don't shutdown when closing the last browser window.
81  chrome::IncrementKeepAliveCount();
82
83  aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
84
85  BrowserList* browser_list =
86      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
87
88  EXPECT_EQ(1u, browser_list->size());
89  // Close the browser window so that clicking icon will create a new window.
90  CloseBrowser(browser_list->get(0));
91  EXPECT_EQ(0u, browser_list->size());
92  EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow());
93
94  OpenBrowserUsingShelfOnRootWindow(root_windows[1]);
95
96  // A new browser must be created on 2nd display.
97  EXPECT_EQ(1u, browser_list->size());
98  EXPECT_EQ(root_windows[1],
99            browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
100  EXPECT_EQ(root_windows[1], ash::Shell::GetTargetRootWindow());
101
102  // Close the browser window so that clicking icon will create a new window.
103  CloseBrowser(browser_list->get(0));
104  EXPECT_EQ(0u, browser_list->size());
105
106  OpenBrowserUsingShelfOnRootWindow(root_windows[0]);
107
108  // A new browser must be created on 1st display.
109  EXPECT_EQ(1u, browser_list->size());
110  EXPECT_EQ(root_windows[0],
111            browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
112  EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow());
113
114  // Balanced with the chrome::IncrementKeepAliveCount above.
115  chrome::DecrementKeepAliveCount();
116}
117
118namespace {
119
120class WindowSizerContextMenuTest : public WindowSizerTest {
121 public:
122  WindowSizerContextMenuTest() {}
123  virtual ~WindowSizerContextMenuTest() {}
124
125  static void Step1(gfx::Point release_point) {
126    ui_controls::SendMouseEventsNotifyWhenDone(
127        ui_controls::RIGHT, ui_controls::DOWN,
128        base::Bind(&WindowSizerContextMenuTest::Step2, release_point));
129  }
130
131  static void Step2(gfx::Point release_point) {
132    ui_controls::SendMouseMoveNotifyWhenDone(
133        release_point.x(), release_point.y(),
134        base::Bind(&WindowSizerContextMenuTest::Step3));
135  }
136
137  static void Step3() {
138    ui_controls::SendMouseEventsNotifyWhenDone(
139        ui_controls::RIGHT, ui_controls::UP,
140        base::Bind(&WindowSizerContextMenuTest::QuitLoop));
141  }
142
143  static void QuitLoop() {
144    base::MessageLoop::current()->PostTask(
145        FROM_HERE,
146        base::MessageLoop::QuitWhenIdleClosure());
147  }
148
149 private:
150  DISALLOW_COPY_AND_ASSIGN(WindowSizerContextMenuTest);
151};
152
153void OpenBrowserUsingContextMenuOnRootWindow(aura::Window* root_window) {
154  gfx::Point chrome_icon =
155      GetChromeIconBoundsForRootWindow(root_window).CenterPoint();
156  gfx::Point release_point = chrome_icon;
157  release_point.Offset(50, -120);
158  ui_controls::SendMouseMoveNotifyWhenDone(
159      chrome_icon.x(), chrome_icon.y(),
160      base::Bind(&WindowSizerContextMenuTest::Step1, release_point));
161  base::MessageLoop::current()->Run();
162}
163
164}  // namespace
165
166IN_PROC_BROWSER_TEST_F(WindowSizerContextMenuTest,
167                       MAYBE_OpenBrowserUsingContextMenuOnOtherDisplay) {
168  // Don't shutdown when closing the last browser window.
169  chrome::IncrementKeepAliveCount();
170
171  views::MenuController::TurnOffMenuSelectionHoldForTest();
172
173  aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
174
175  BrowserList* browser_list =
176      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
177
178  ASSERT_EQ(1u, browser_list->size());
179  EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow());
180  CloseBrowser(browser_list->get(0));
181
182  OpenBrowserUsingContextMenuOnRootWindow(root_windows[1]);
183
184  // A new browser must be created on 2nd display.
185  ASSERT_EQ(1u, browser_list->size());
186  EXPECT_EQ(root_windows[1],
187            browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
188  EXPECT_EQ(root_windows[1], ash::Shell::GetTargetRootWindow());
189
190  OpenBrowserUsingContextMenuOnRootWindow(root_windows[0]);
191
192  // Next new browser must be created on 1st display.
193  ASSERT_EQ(2u, browser_list->size());
194  EXPECT_EQ(root_windows[0],
195            browser_list->get(1)->window()->GetNativeWindow()->GetRootWindow());
196  EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow());
197
198  // Balanced with the chrome::IncrementKeepAliveCount above.
199  chrome::DecrementKeepAliveCount();
200}
201