1// Copyright (c) 2010 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 "base/command_line.h"
6#include "base/file_util.h"
7#include "chrome/app/chrome_command_ids.h"
8#include "chrome/browser/ui/view_ids.h"
9#include "chrome/common/chrome_paths.h"
10#include "chrome/test/automation/tab_proxy.h"
11#include "chrome/test/automation/browser_proxy.h"
12#include "chrome/test/automation/window_proxy.h"
13#include "chrome/test/ui/ui_test.h"
14#include "googleurl/src/gurl.h"
15#include "net/base/net_util.h"
16#include "ui/gfx/rect.h"
17#include "views/events/event.h"
18
19#if defined(OS_LINUX)
20// This test doesn't make sense on chromeos as chromeos doesn't allow dragging
21// tabs out.
22#define MAYBE_Tab2OutOfTabStrip DISABLED_Tab2OutOfTabStrip
23#else
24// Flaky, http://crbug.com/62311.
25#define MAYBE_Tab2OutOfTabStrip FLAKY_Tab2OutOfTabStrip
26#endif
27
28#if defined(OS_LINUX)
29// Disabled on Toolkit views bot. See http://crbug.com/42614
30#define MAYBE_Tab1Tab3Escape DISABLED_Tab1Tab3Escape
31#elif defined(OS_WIN)
32// Disabled on Windows. See http://crbug.com/57687
33#define MAYBE_Tab1Tab3Escape DISABLED_Tab1Tab3Escape
34#else
35#define MAYBE_Tab1Tab3Escape Tab1Tab3Escape
36#endif
37
38// These tests fail on Linux because we haven't implemented all of tab dragging
39// (it's not needed on chromeos). See http://crbug.com/10941
40#if defined(OS_LINUX)
41#define MAYBE_Tab1Tab2 DISABLED_Tab1Tab2
42#define MAYBE_Tab1Tab3 DISABLED_Tab1Tab3
43#else
44// Flaky, http://crbug.com/62311.
45#define MAYBE_Tab1Tab2 FLAKY_Tab1Tab2
46#define MAYBE_Tab1Tab3 FLAKY_Tab1Tab3
47#endif
48
49class TabDraggingTest : public UITest {
50 protected:
51  TabDraggingTest() {
52    show_window_ = true;
53  }
54};
55
56// Automated UI test to open three tabs in a new window, and drag Tab_1 into
57// the position of Tab_2.
58TEST_F(TabDraggingTest, MAYBE_Tab1Tab2) {
59  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
60  ASSERT_TRUE(browser.get());
61  scoped_refptr<WindowProxy> window(browser->GetWindow());
62  ASSERT_TRUE(window.get());
63
64  // Get initial tab count.
65  int initial_tab_count = 0;
66  ASSERT_TRUE(browser->GetTabCount(&initial_tab_count));
67  ASSERT_TRUE(1 == initial_tab_count);
68
69  // Get Tab_1 which comes with the browser window.
70  scoped_refptr<TabProxy> tab1(browser->GetTab(0));
71  ASSERT_TRUE(tab1.get());
72  GURL tab1_url;
73  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url));
74
75  // Add Tab_2.
76  GURL tab2_url("about:");
77  ASSERT_TRUE(browser->AppendTab(tab2_url));
78  scoped_refptr<TabProxy> tab2(browser->GetTab(1));
79  ASSERT_TRUE(tab2.get());
80
81  // Add Tab_3.
82  GURL tab3_url("about:plugins");
83  ASSERT_TRUE(browser->AppendTab(tab3_url));
84  scoped_refptr<TabProxy> tab3(browser->GetTab(2));
85  ASSERT_TRUE(tab3.get());
86
87  // Make sure 3 tabs are open.
88  ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2));
89
90  // Get bounds for the tabs.
91  gfx::Rect bounds1;
92  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false));
93  EXPECT_LT(0, bounds1.x());
94  EXPECT_LT(0, bounds1.width());
95  EXPECT_LT(0, bounds1.height());
96
97  gfx::Rect bounds2;
98  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false));
99  EXPECT_LT(0, bounds2.width());
100  EXPECT_LT(0, bounds2.height());
101  EXPECT_LT(bounds1.x(), bounds2.x());
102  EXPECT_EQ(bounds2.y(), bounds1.y());
103
104  gfx::Rect bounds3;
105  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false));
106  EXPECT_LT(0, bounds3.width());
107  EXPECT_LT(0, bounds3.height());
108  EXPECT_LT(bounds2.x(), bounds3.x());
109  EXPECT_EQ(bounds3.y(), bounds2.y());
110
111  // Get url Bar bounds.
112  gfx::Rect urlbar_bounds;
113  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds,
114                                    false));
115  EXPECT_LT(0, urlbar_bounds.x());
116  EXPECT_LT(0, urlbar_bounds.y());
117  EXPECT_LT(0, urlbar_bounds.width());
118  EXPECT_LT(0, urlbar_bounds.height());
119
120  /*
121    TEST: Move Tab_1 to the position of Tab_2
122     ____________   ____________   ____________
123    /            \ /            \ /            \
124   |    Tab_1     |     Tab_2    |    Tab_3     |
125    ---- ---- ---- ---- ---- ---- ---- ---- ----
126           x---- ---->
127                ____________
128               /     X      \
129              |    Tab_1     |
130               ---- ---- ----
131  */
132
133  gfx::Point start(bounds1.x() + bounds1.width() / 2,
134                   bounds1.y() + bounds1.height() / 2);
135  gfx::Point end(start.x() + 2 * bounds1.width() / 3, start.y());
136  ASSERT_TRUE(browser->SimulateDrag(start, end,
137                                    ui::EF_LEFT_BUTTON_DOWN,
138                                    false));
139
140  // Now check for expected results.
141  tab1 = browser->GetTab(0);
142  ASSERT_TRUE(tab1.get());
143  GURL tab1_new_url;
144  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
145
146  tab2 = browser->GetTab(1);
147  ASSERT_TRUE(tab2.get());
148  GURL tab2_new_url;
149  ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
150
151  EXPECT_EQ(tab1_url.spec(), tab2_new_url.spec());
152  EXPECT_EQ(tab2_url.spec(), tab1_new_url.spec());
153}
154
155// Drag Tab_1 into the position of Tab_3.
156TEST_F(TabDraggingTest, MAYBE_Tab1Tab3) {
157  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
158  ASSERT_TRUE(browser.get());
159  scoped_refptr<WindowProxy> window(browser->GetWindow());
160  ASSERT_TRUE(window.get());
161
162  // Get initial tab count.
163  int initial_tab_count = 0;
164  ASSERT_TRUE(browser->GetTabCount(&initial_tab_count));
165  ASSERT_TRUE(1 == initial_tab_count);
166
167  // Get Tab_1 which comes with the browser window.
168  scoped_refptr<TabProxy> tab1(browser->GetTab(0));
169  ASSERT_TRUE(tab1.get());
170  GURL tab1_url;
171  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url));
172
173  // Add Tab_2.
174  GURL tab2_url("about:");
175  ASSERT_TRUE(browser->AppendTab(tab2_url));
176  scoped_refptr<TabProxy> tab2(browser->GetTab(1));
177  ASSERT_TRUE(tab2.get());
178
179  // Add Tab_3.
180  GURL tab3_url("about:plugins");
181  ASSERT_TRUE(browser->AppendTab(tab3_url));
182  scoped_refptr<TabProxy> tab3(browser->GetTab(2));
183  ASSERT_TRUE(tab3.get());
184
185  // Make sure 3 tabs are open.
186  ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2));
187
188  // Get bounds for the tabs.
189  gfx::Rect bounds1;
190  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false));
191  EXPECT_LT(0, bounds1.x());
192  EXPECT_LT(0, bounds1.width());
193  EXPECT_LT(0, bounds1.height());
194
195  gfx::Rect bounds2;
196  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false));
197  EXPECT_LT(0, bounds2.width());
198  EXPECT_LT(0, bounds2.height());
199  EXPECT_LT(bounds1.x(), bounds2.x());
200  EXPECT_EQ(bounds2.y(), bounds1.y());
201
202  gfx::Rect bounds3;
203  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false));
204  EXPECT_LT(0, bounds3.width());
205  EXPECT_LT(0, bounds3.height());
206  EXPECT_LT(bounds2.x(), bounds3.x());
207  EXPECT_EQ(bounds3.y(), bounds2.y());
208
209  // Get url Bar bounds.
210  gfx::Rect urlbar_bounds;
211  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds,
212                                    false));
213  EXPECT_LT(0, urlbar_bounds.x());
214  EXPECT_LT(0, urlbar_bounds.y());
215  EXPECT_LT(0, urlbar_bounds.width());
216  EXPECT_LT(0, urlbar_bounds.height());
217
218  /*
219   TEST: Move Tab_1 to the middle position of Tab_3
220     ____________   ____________   ____________
221    /            \ /            \ /            \
222   |    Tab_1     |     Tab_2    |    Tab_3     |
223    ---- ---- ---- ---- ---- ---- ---- ---- ----
224           x---- ---- ---- ---- ---- ---->
225                                    ____________
226                                   /     X      \
227                                  |    Tab_1     |
228                                   ---- ---- ----
229  */
230
231  gfx::Point start(bounds1.x() + bounds1.width() / 2,
232                   bounds1.y() + bounds1.height() / 2);
233  gfx::Point end(start.x() + bounds1.width() / 2 + bounds2.width() +
234                     bounds3.width() / 2,
235                 start.y());
236  ASSERT_TRUE(browser->SimulateDrag(start, end,
237                                    ui::EF_LEFT_BUTTON_DOWN,
238                                    false));
239
240  // Now check for expected results.
241  tab1 = browser->GetTab(0);
242  ASSERT_TRUE(tab1.get());
243  GURL tab1_new_url;
244  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
245
246  tab2 = browser->GetTab(1);
247  ASSERT_TRUE(tab2.get());
248  GURL tab2_new_url;
249  ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
250
251  tab3 = browser->GetTab(2);
252  ASSERT_TRUE(tab3.get());
253  GURL tab3_new_url;
254  ASSERT_TRUE(tab3->GetCurrentURL(&tab3_new_url));
255
256  EXPECT_EQ(tab1_new_url.spec(), tab2_url.spec());
257  EXPECT_EQ(tab2_new_url.spec(), tab3_url.spec());
258  EXPECT_EQ(tab3_new_url.spec(), tab1_url.spec());
259}
260
261// Drag Tab_1 into the position of Tab_3, and press ESCAPE before releasing the
262// left mouse button.
263TEST_F(TabDraggingTest, MAYBE_Tab1Tab3Escape) {
264  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
265  ASSERT_TRUE(browser.get());
266  scoped_refptr<WindowProxy> window(browser->GetWindow());
267  ASSERT_TRUE(window.get());
268
269  // Get initial tab count.
270  int initial_tab_count = 0;
271  ASSERT_TRUE(browser->GetTabCount(&initial_tab_count));
272  ASSERT_TRUE(1 == initial_tab_count);
273
274  // Get Tab_1 which comes with the browser window.
275  scoped_refptr<TabProxy> tab1(browser->GetTab(0));
276  ASSERT_TRUE(tab1.get());
277  GURL tab1_url;
278  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url));
279
280  // Add Tab_2.
281  GURL tab2_url("about:blank");
282  ASSERT_TRUE(browser->AppendTab(tab2_url));
283  scoped_refptr<TabProxy> tab2(browser->GetTab(1));
284  ASSERT_TRUE(tab2.get());
285
286  // Add Tab_3.
287  GURL tab3_url("about:plugins");
288  ASSERT_TRUE(browser->AppendTab(tab3_url));
289  scoped_refptr<TabProxy> tab3(browser->GetTab(2));
290  ASSERT_TRUE(tab3.get());
291
292  // Make sure 3 tabs are open.
293  ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2));
294
295  // Get bounds for the tabs.
296  gfx::Rect bounds1;
297  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false));
298  EXPECT_LT(0, bounds1.x());
299  EXPECT_LT(0, bounds1.width());
300  EXPECT_LT(0, bounds1.height());
301
302  gfx::Rect bounds2;
303  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false));
304  EXPECT_LT(0, bounds2.width());
305  EXPECT_LT(0, bounds2.height());
306  EXPECT_LT(bounds1.x(), bounds2.x());
307  EXPECT_EQ(bounds2.y(), bounds1.y());
308
309  gfx::Rect bounds3;
310  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false));
311  EXPECT_LT(0, bounds3.width());
312  EXPECT_LT(0, bounds3.height());
313  EXPECT_LT(bounds2.x(), bounds3.x());
314  EXPECT_EQ(bounds3.y(), bounds2.y());
315
316  // Get url Bar bounds.
317  gfx::Rect urlbar_bounds;
318  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds,
319                                    false));
320  EXPECT_LT(0, urlbar_bounds.x());
321  EXPECT_LT(0, urlbar_bounds.y());
322  EXPECT_LT(0, urlbar_bounds.width());
323  EXPECT_LT(0, urlbar_bounds.height());
324
325  /*
326   TEST: Move Tab_1 to the middle position of Tab_3
327     ____________   ____________   ____________
328    /            \ /            \ /            \
329   |    Tab_1     |     Tab_2    |    Tab_3     |
330    ---- ---- ---- ---- ---- ---- ---- ---- ----
331           x---- ---- ---- ---- ---- ----> + ESCAPE
332                                    ____________
333                                   /     X      \
334                                  |    Tab_1     |
335                                   ---- ---- ----
336  */
337
338  gfx::Point start(bounds1.x() + bounds1.width() / 2,
339                   bounds1.y() + bounds1.height() / 2);
340  gfx::Point end(start.x() + bounds1.width() / 2 + bounds2.width() +
341                     bounds3.width() / 2,
342                 start.y());
343
344  // Simulate drag with 'true' as the last parameter. This will interrupt
345  // in-flight with Escape.
346  ASSERT_TRUE(browser->SimulateDrag(start, end,
347                                    ui::EF_LEFT_BUTTON_DOWN,
348                                    true));
349
350  // Now check for expected results.
351  tab1 = browser->GetTab(0);
352  ASSERT_TRUE(tab1.get());
353  GURL tab1_new_url;
354  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
355
356  tab2 = browser->GetTab(1);
357  ASSERT_TRUE(tab2.get());
358  GURL tab2_new_url;
359  ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
360
361  tab3 = browser->GetTab(2);
362  ASSERT_TRUE(tab3.get());
363  GURL tab3_new_url;
364  ASSERT_TRUE(tab3->GetCurrentURL(&tab3_new_url));
365
366  // The tabs should be in their original positions.
367  EXPECT_EQ(tab1_new_url.spec(), tab1_url.spec());
368  EXPECT_EQ(tab2_new_url.spec(), tab2_url.spec());
369  EXPECT_EQ(tab3_new_url.spec(), tab3_url.spec());
370}
371
372// Drag Tab_2 out of the Tab strip. A new window should open with this tab.
373TEST_F(TabDraggingTest, MAYBE_Tab2OutOfTabStrip) {
374  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
375  ASSERT_TRUE(browser.get());
376  scoped_refptr<WindowProxy> window(browser->GetWindow());
377  ASSERT_TRUE(window.get());
378
379  // Get initial tab count.
380  int initial_tab_count = 0;
381  ASSERT_TRUE(browser->GetTabCount(&initial_tab_count));
382  ASSERT_TRUE(1 == initial_tab_count);
383
384  // Get Tab_1 which comes with the browser window.
385  scoped_refptr<TabProxy> tab1(browser->GetTab(0));
386  ASSERT_TRUE(tab1.get());
387  GURL tab1_url;
388  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url));
389
390  // Add Tab_2.
391  GURL tab2_url("about:version");
392  ASSERT_TRUE(browser->AppendTab(tab2_url));
393  scoped_refptr<TabProxy> tab2(browser->GetTab(1));
394  ASSERT_TRUE(tab2.get());
395
396  // Add Tab_3.
397  GURL tab3_url("about:plugins");
398  ASSERT_TRUE(browser->AppendTab(tab3_url));
399  scoped_refptr<TabProxy> tab3(browser->GetTab(2));
400  ASSERT_TRUE(tab3.get());
401
402  // Make sure 3 tabs are opened.
403  ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2));
404
405  // Make sure all the tab URL specs are different.
406  ASSERT_TRUE(tab1_url != tab2_url);
407  ASSERT_TRUE(tab1_url != tab3_url);
408  ASSERT_TRUE(tab2_url != tab3_url);
409
410  // Get bounds for the tabs.
411  gfx::Rect bounds1;
412  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false));
413  EXPECT_LT(0, bounds1.x());
414  EXPECT_LT(0, bounds1.width());
415  EXPECT_LT(0, bounds1.height());
416
417  gfx::Rect bounds2;
418  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false));
419  EXPECT_LT(0, bounds2.width());
420  EXPECT_LT(0, bounds2.height());
421  EXPECT_LT(bounds1.x(), bounds2.x());
422  EXPECT_EQ(bounds2.y(), bounds1.y());
423
424  gfx::Rect bounds3;
425  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false));
426  EXPECT_LT(0, bounds3.width());
427  EXPECT_LT(0, bounds3.height());
428  EXPECT_LT(bounds2.x(), bounds3.x());
429  EXPECT_EQ(bounds3.y(), bounds2.y());
430
431  // Get url Bar bounds.
432  gfx::Rect urlbar_bounds;
433  ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds,
434                                    false));
435  EXPECT_LT(0, urlbar_bounds.x());
436  EXPECT_LT(0, urlbar_bounds.y());
437  EXPECT_LT(0, urlbar_bounds.width());
438  EXPECT_LT(0, urlbar_bounds.height());
439
440  /*
441   TEST: Move Tab_2 down, out of the tab strip.
442   This should result in the following:
443    1- Tab_3 shift left in place of Tab_2 in Window 1
444    2- Tab_1 to remain in its place
445    3- Tab_2 openes in a new window
446
447     ____________   ____________   ____________
448    /            \ /            \ /            \
449    |    Tab_1     |     Tab_2    |    Tab_3     |
450    ---- ---- ---- ---- ---- ---- ---- ---- ----
451                         x
452                         |
453                         |  (Drag this below, out of tab strip)
454                         V
455                    ____________
456                   /     X      \
457                  |    Tab_2     |   (New Window)
458                  ---- ---- ---- ---- ---- ---- ----
459  */
460
461  gfx::Point start(bounds2.x() + bounds2.width() / 2,
462                   bounds2.y() + bounds2.height() / 2);
463  gfx::Point end(start.x(),
464                 start.y() + 3 * urlbar_bounds.height());
465
466  // Simulate tab drag.
467  ASSERT_TRUE(browser->SimulateDrag(start, end,
468                                    ui::EF_LEFT_BUTTON_DOWN,
469                                    false));
470
471  // Now, first make sure that the old window has only two tabs remaining.
472  int new_tab_count = 0;
473  ASSERT_TRUE(browser->GetTabCount(&new_tab_count));
474  ASSERT_EQ(2, new_tab_count);
475
476  // Get the two tabs - they are called Tab_1 and Tab_2 in the old window.
477  tab1 = browser->GetTab(0);
478  ASSERT_TRUE(tab1.get());
479  GURL tab1_new_url;
480  ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
481
482  tab2 = browser->GetTab(1);
483  ASSERT_TRUE(tab2.get());
484  GURL tab2_new_url;
485  ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
486
487  // Now check for proper shifting of tabs; i.e., Tab_3 in window 1 should
488  // shift left to the position of Tab_2; Tab_1 should stay where it was.
489  EXPECT_EQ(tab1_new_url.spec(), tab1_url.spec());
490  EXPECT_EQ(tab2_new_url.spec(), tab3_url.spec());
491
492  // Now check to make sure a new window has opened.
493  scoped_refptr<BrowserProxy> browser2(automation()->GetBrowserWindow(1));
494  ASSERT_TRUE(browser2.get());
495  scoped_refptr<WindowProxy> window2(browser2->GetWindow());
496  ASSERT_TRUE(window2.get());
497
498  // Make sure that the new window has only one tab.
499  int tab_count_window_2 = 0;
500  ASSERT_TRUE(browser2->GetTabCount(&tab_count_window_2));
501  ASSERT_EQ(1, tab_count_window_2);
502
503  // Get Tab_1_2 which should be Tab_1 in Window 2.
504  scoped_refptr<TabProxy> tab1_2(browser2->GetTab(0));
505  ASSERT_TRUE(tab1_2.get());
506  GURL tab1_2_url;
507  ASSERT_TRUE(tab1_2->GetCurrentURL(&tab1_2_url));
508
509  // Tab_1_2 of Window 2 should essentially be Tab_2 of Window 1.
510  EXPECT_EQ(tab1_2_url.spec(), tab2_url.spec());
511  EXPECT_NE(tab1_2_url.spec(), tab1_url.spec());
512  EXPECT_NE(tab1_2_url.spec(), tab3_url.spec());
513}
514