tab_drag_controller_interactive_uitest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h" 6 7#include "ash/wm/window_state.h" 8#include "base/bind.h" 9#include "base/callback.h" 10#include "base/command_line.h" 11#include "base/run_loop.h" 12#include "base/strings/string_number_conversions.h" 13#include "chrome/browser/chrome_notification_types.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/ui/browser_commands.h" 16#include "chrome/browser/ui/browser_iterator.h" 17#include "chrome/browser/ui/browser_list.h" 18#include "chrome/browser/ui/host_desktop.h" 19#include "chrome/browser/ui/tabs/tab_strip_model.h" 20#include "chrome/browser/ui/views/frame/browser_view.h" 21#include "chrome/browser/ui/views/frame/native_browser_frame_factory.h" 22#include "chrome/browser/ui/views/tabs/tab.h" 23#include "chrome/browser/ui/views/tabs/tab_drag_controller.h" 24#include "chrome/browser/ui/views/tabs/tab_strip.h" 25#include "chrome/common/chrome_switches.h" 26#include "chrome/test/base/in_process_browser_test.h" 27#include "chrome/test/base/interactive_test_utils.h" 28#include "chrome/test/base/ui_test_utils.h" 29#include "content/public/browser/notification_details.h" 30#include "content/public/browser/notification_observer.h" 31#include "content/public/browser/notification_service.h" 32#include "content/public/browser/notification_source.h" 33#include "content/public/browser/web_contents.h" 34#include "ui/base/test/ui_controls.h" 35#include "ui/gfx/screen.h" 36#include "ui/views/view.h" 37#include "ui/views/widget/widget.h" 38 39#if defined(USE_AURA) && !defined(OS_CHROMEOS) 40#include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h" 41#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 42#endif 43 44#if defined(USE_ASH) 45#include "ash/ash_switches.h" 46#include "ash/display/display_controller.h" 47#include "ash/display/display_manager.h" 48#include "ash/shell.h" 49#include "ash/test/cursor_manager_test_api.h" 50#include "ash/wm/coordinate_conversion.h" 51#include "ash/wm/window_state.h" 52#include "ash/wm/window_util.h" 53#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" 54#include "ui/aura/client/screen_position_client.h" 55#include "ui/aura/root_window.h" 56#include "ui/aura/test/event_generator.h" 57#endif 58 59using content::WebContents; 60 61namespace test { 62 63namespace { 64 65const char kTabDragControllerInteractiveUITestUserDataKey[] = 66 "TabDragControllerInteractiveUITestUserData"; 67 68class TabDragControllerInteractiveUITestUserData 69 : public base::SupportsUserData::Data { 70 public: 71 explicit TabDragControllerInteractiveUITestUserData(int id) : id_(id) {} 72 virtual ~TabDragControllerInteractiveUITestUserData() {} 73 int id() { return id_; } 74 75 private: 76 int id_; 77}; 78 79} // namespace 80 81class QuitDraggingObserver : public content::NotificationObserver { 82 public: 83 QuitDraggingObserver() { 84 registrar_.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, 85 content::NotificationService::AllSources()); 86 } 87 88 virtual void Observe(int type, 89 const content::NotificationSource& source, 90 const content::NotificationDetails& details) OVERRIDE { 91 DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, type); 92 base::MessageLoopForUI::current()->Quit(); 93 delete this; 94 } 95 96 private: 97 virtual ~QuitDraggingObserver() {} 98 99 content::NotificationRegistrar registrar_; 100 101 DISALLOW_COPY_AND_ASSIGN(QuitDraggingObserver); 102}; 103 104gfx::Point GetCenterInScreenCoordinates(const views::View* view) { 105 gfx::Point center(view->width() / 2, view->height() / 2); 106 views::View::ConvertPointToScreen(view, ¢er); 107 return center; 108} 109 110void SetID(WebContents* web_contents, int id) { 111 web_contents->SetUserData(&kTabDragControllerInteractiveUITestUserDataKey, 112 new TabDragControllerInteractiveUITestUserData(id)); 113} 114 115void ResetIDs(TabStripModel* model, int start) { 116 for (int i = 0; i < model->count(); ++i) 117 SetID(model->GetWebContentsAt(i), start + i); 118} 119 120std::string IDString(TabStripModel* model) { 121 std::string result; 122 for (int i = 0; i < model->count(); ++i) { 123 if (i != 0) 124 result += " "; 125 WebContents* contents = model->GetWebContentsAt(i); 126 TabDragControllerInteractiveUITestUserData* user_data = 127 static_cast<TabDragControllerInteractiveUITestUserData*>( 128 contents->GetUserData( 129 &kTabDragControllerInteractiveUITestUserDataKey)); 130 if (user_data) 131 result += base::IntToString(user_data->id()); 132 else 133 result += "?"; 134 } 135 return result; 136} 137 138// Creates a listener that quits the message loop when no longer dragging. 139void QuitWhenNotDraggingImpl() { 140 new QuitDraggingObserver(); // QuitDraggingObserver deletes itself. 141} 142 143TabStrip* GetTabStripForBrowser(Browser* browser) { 144 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 145 return static_cast<TabStrip*>(browser_view->tabstrip()); 146} 147 148} // namespace test 149 150using test::GetCenterInScreenCoordinates; 151using test::SetID; 152using test::ResetIDs; 153using test::IDString; 154using test::GetTabStripForBrowser; 155 156TabDragControllerTest::TabDragControllerTest() 157 : native_browser_list(BrowserList::GetInstance( 158 chrome::HOST_DESKTOP_TYPE_NATIVE)) { 159} 160 161TabDragControllerTest::~TabDragControllerTest() { 162} 163 164void TabDragControllerTest::SetUp() { 165 // TODO(danakj): Remove this when the tests are not flaky (crbug.com/270065) 166 // or we use test contexts in the renderer to keep things fast enough to 167 // avoid the flake (crbug.com/270918). 168 UseRealGLBindings(); 169 170 InProcessBrowserTest::SetUp(); 171} 172 173void TabDragControllerTest::StopAnimating(TabStrip* tab_strip) { 174 tab_strip->StopAnimating(true); 175} 176 177void TabDragControllerTest::AddTabAndResetBrowser(Browser* browser) { 178 AddBlankTabAndShow(browser); 179 StopAnimating(GetTabStripForBrowser(browser)); 180 ResetIDs(browser->tab_strip_model(), 0); 181} 182 183Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() { 184 // Create another browser. 185 Browser* browser2 = CreateBrowser(browser()->profile()); 186 ResetIDs(browser2->tab_strip_model(), 100); 187 188 // Resize the two windows so they're right next to each other. 189 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 190 browser()->window()->GetNativeWindow()).work_area(); 191 gfx::Size half_size = 192 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10); 193 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size)); 194 browser2->window()->SetBounds(gfx::Rect( 195 work_area.x() + half_size.width(), work_area.y(), 196 half_size.width(), half_size.height())); 197 return browser2; 198} 199 200namespace { 201 202enum InputSource { 203 INPUT_SOURCE_MOUSE = 0, 204 INPUT_SOURCE_TOUCH = 1 205}; 206 207int GetDetachY(TabStrip* tab_strip) { 208 return std::max(TabDragController::kTouchVerticalDetachMagnetism, 209 TabDragController::kVerticalDetachMagnetism) + 210 tab_strip->height() + 1; 211} 212 213bool GetTrackedByWorkspace(Browser* browser) { 214#if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash) 215 return true; 216#else 217 return ash::wm::GetWindowState(browser->window()->GetNativeWindow())-> 218 tracked_by_workspace(); 219#endif 220} 221 222} // namespace 223 224#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 225class ScreenEventGeneratorDelegate : public aura::test::EventGeneratorDelegate { 226 public: 227 explicit ScreenEventGeneratorDelegate(aura::Window* root_window) 228 : root_window_(root_window) {} 229 virtual ~ScreenEventGeneratorDelegate() {} 230 231 // EventGeneratorDelegate overrides: 232 virtual aura::RootWindow* GetRootWindowAt( 233 const gfx::Point& point) const OVERRIDE { 234 return root_window_->GetDispatcher(); 235 } 236 237 virtual aura::client::ScreenPositionClient* GetScreenPositionClient( 238 const aura::Window* window) const OVERRIDE { 239 return aura::client::GetScreenPositionClient(root_window_); 240 } 241 242 private: 243 aura::Window* root_window_; 244 245 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate); 246}; 247 248#endif 249 250#if defined(USE_AURA) && !defined(OS_CHROMEOS) 251 252// Following classes verify a crash scenario. Specifically on Windows when focus 253// changes it can trigger capture being lost. This was causing a crash in tab 254// dragging as it wasn't set up to handle this scenario. These classes 255// synthesize this scenario. 256 257// Allows making ClearNativeFocus() invoke ReleaseCapture(). 258class TestDesktopBrowserFrameAura : public DesktopBrowserFrameAura { 259 public: 260 TestDesktopBrowserFrameAura( 261 BrowserFrame* browser_frame, 262 BrowserView* browser_view) 263 : DesktopBrowserFrameAura(browser_frame, browser_view), 264 release_capture_(false) {} 265 virtual ~TestDesktopBrowserFrameAura() {} 266 267 void ReleaseCaptureOnNextClear() { 268 release_capture_ = true; 269 } 270 271 virtual void ClearNativeFocus() OVERRIDE { 272 views::DesktopNativeWidgetAura::ClearNativeFocus(); 273 if (release_capture_) { 274 release_capture_ = false; 275 GetWidget()->ReleaseCapture(); 276 } 277 } 278 279 private: 280 // If true ReleaseCapture() is invoked in ClearNativeFocus(). 281 bool release_capture_; 282 283 DISALLOW_COPY_AND_ASSIGN(TestDesktopBrowserFrameAura); 284}; 285 286// Factory for creating a TestDesktopBrowserFrameAura. 287class TestNativeBrowserFrameFactory : public NativeBrowserFrameFactory { 288 public: 289 TestNativeBrowserFrameFactory() {} 290 virtual ~TestNativeBrowserFrameFactory() {} 291 292 virtual NativeBrowserFrame* Create( 293 BrowserFrame* browser_frame, 294 BrowserView* browser_view) OVERRIDE { 295 return new TestDesktopBrowserFrameAura(browser_frame, browser_view); 296 } 297 298 private: 299 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory); 300}; 301 302class TabDragCaptureLostTest : public TabDragControllerTest { 303 public: 304 TabDragCaptureLostTest() { 305 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory); 306 } 307 308 private: 309 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest); 310}; 311 312// See description above for details. 313IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest, ReleaseCaptureOnDrag) { 314 AddTabAndResetBrowser(browser()); 315 316 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 317 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1))); 318 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center) && 319 ui_test_utils::SendMouseEventsSync( 320 ui_controls::LEFT, ui_controls::DOWN)); 321 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 322 TestDesktopBrowserFrameAura* frame = 323 static_cast<TestDesktopBrowserFrameAura*>( 324 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()-> 325 native_widget_private()); 326 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus 327 // changes capture is released and the drag cancels. 328 frame->ReleaseCaptureOnNextClear(); 329 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center)); 330 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 331} 332 333#endif 334 335class DetachToBrowserTabDragControllerTest 336 : public TabDragControllerTest, 337 public ::testing::WithParamInterface<const char*> { 338 public: 339 DetachToBrowserTabDragControllerTest() {} 340 341 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 342 command_line->AppendSwitch(switches::kTabBrowserDragging); 343#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 344 if (docked_windows_enabled()) { 345 CommandLine::ForCurrentProcess()->AppendSwitch( 346 ash::switches::kAshEnableDockedWindows); 347 } 348#endif 349 } 350 351 virtual void SetUpOnMainThread() OVERRIDE { 352#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 353 event_generator_.reset(new aura::test::EventGenerator( 354 ash::Shell::GetPrimaryRootWindow())); 355#endif 356 } 357 358 InputSource input_source() const { 359 return strstr(GetParam(), "mouse") ? 360 INPUT_SOURCE_MOUSE : INPUT_SOURCE_TOUCH; 361 } 362 363 bool docked_windows_enabled() const { 364 return (strstr(GetParam(), "docked") != NULL); 365 } 366 367 // Set root window from a point in screen coordinates 368 void SetEventGeneratorRootWindow(const gfx::Point& point) { 369 if (input_source() == INPUT_SOURCE_MOUSE) 370 return; 371#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 372 event_generator_.reset(new aura::test::EventGenerator( 373 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point)))); 374#endif 375 } 376 377 // The following methods update one of the mouse or touch input depending upon 378 // the InputSource. 379 bool PressInput(const gfx::Point& location) { 380 if (input_source() == INPUT_SOURCE_MOUSE) { 381 return ui_test_utils::SendMouseMoveSync(location) && 382 ui_test_utils::SendMouseEventsSync( 383 ui_controls::LEFT, ui_controls::DOWN); 384 } 385#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 386 event_generator_->set_current_location(location); 387 event_generator_->PressTouch(); 388#else 389 NOTREACHED(); 390#endif 391 return true; 392 } 393 394 bool PressInput2() { 395 // Second touch input is only used for touch sequence tests. 396 EXPECT_EQ(INPUT_SOURCE_TOUCH, input_source()); 397#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 398 event_generator_->set_current_location( 399 event_generator_->current_location()); 400 event_generator_->PressTouchId(1); 401#else 402 NOTREACHED(); 403#endif 404 return true; 405 } 406 407 bool DragInputTo(const gfx::Point& location) { 408 if (input_source() == INPUT_SOURCE_MOUSE) 409 return ui_test_utils::SendMouseMoveSync(location); 410#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 411 event_generator_->MoveTouch(location); 412#else 413 NOTREACHED(); 414#endif 415 return true; 416 } 417 418 bool DragInputToAsync(const gfx::Point& location) { 419 if (input_source() == INPUT_SOURCE_MOUSE) 420 return ui_controls::SendMouseMove(location.x(), location.y()); 421#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 422 event_generator_->MoveTouch(location); 423#else 424 NOTREACHED(); 425#endif 426 return true; 427 } 428 429 bool DragInputToNotifyWhenDone(int x, 430 int y, 431 const base::Closure& task) { 432 if (input_source() == INPUT_SOURCE_MOUSE) 433 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 434#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 435 base::MessageLoop::current()->PostTask(FROM_HERE, task); 436 event_generator_->MoveTouch(gfx::Point(x, y)); 437#else 438 NOTREACHED(); 439#endif 440 return true; 441 } 442 443 bool DragInputToDelayedNotifyWhenDone(int x, 444 int y, 445 const base::Closure& task, 446 base::TimeDelta delay) { 447 if (input_source() == INPUT_SOURCE_MOUSE) 448 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 449#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 450 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, task, delay); 451 event_generator_->MoveTouch(gfx::Point(x, y)); 452#else 453 NOTREACHED(); 454#endif 455 return true; 456 } 457 458 bool DragInput2ToNotifyWhenDone(int x, 459 int y, 460 const base::Closure& task) { 461 if (input_source() == INPUT_SOURCE_MOUSE) 462 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 463#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 464 base::MessageLoop::current()->PostTask(FROM_HERE, task); 465 event_generator_->MoveTouchId(gfx::Point(x, y), 1); 466#else 467 NOTREACHED(); 468#endif 469 return true; 470 } 471 472 bool ReleaseInput() { 473 if (input_source() == INPUT_SOURCE_MOUSE) { 474 return ui_test_utils::SendMouseEventsSync( 475 ui_controls::LEFT, ui_controls::UP); 476 } 477#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 478 event_generator_->ReleaseTouch(); 479#else 480 NOTREACHED(); 481#endif 482 return true; 483 } 484 485 bool ReleaseInput2() { 486 if (input_source() == INPUT_SOURCE_MOUSE) { 487 return ui_test_utils::SendMouseEventsSync( 488 ui_controls::LEFT, ui_controls::UP); 489 } 490#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 491 event_generator_->ReleaseTouchId(1); 492#else 493 NOTREACHED(); 494#endif 495 return true; 496 } 497 498 bool ReleaseMouseAsync() { 499 return input_source() == INPUT_SOURCE_MOUSE && 500 ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP); 501 } 502 503 void QuitWhenNotDragging() { 504 if (input_source() == INPUT_SOURCE_MOUSE) { 505 // Schedule observer to quit message loop when done dragging. This has to 506 // be async so the message loop can run. 507 test::QuitWhenNotDraggingImpl(); 508 base::MessageLoop::current()->Run(); 509 } else { 510 // Touch events are sync, so we know we're not in a drag session. But some 511 // tests rely on the browser fully closing, which is async. So, run all 512 // pending tasks. 513 base::RunLoop run_loop; 514 run_loop.RunUntilIdle(); 515 } 516 } 517 518 void AddBlankTabAndShow(Browser* browser) { 519 InProcessBrowserTest::AddBlankTabAndShow(browser); 520 } 521 522 Browser* browser() const { return InProcessBrowserTest::browser(); } 523 524 private: 525#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 526 scoped_ptr<aura::test::EventGenerator> event_generator_; 527#endif 528 529 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest); 530}; 531 532// Creates a browser with two tabs, drags the second to the first. 533// TODO(sky): this won't work with touch as it requires a long press. 534IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 535 DISABLED_DragInSameWindow) { 536 AddTabAndResetBrowser(browser()); 537 538 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 539 TabStripModel* model = browser()->tab_strip_model(); 540 541 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1))); 542 ASSERT_TRUE(PressInput(tab_1_center)); 543 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 544 ASSERT_TRUE(DragInputTo(tab_0_center)); 545 ASSERT_TRUE(ReleaseInput()); 546 EXPECT_EQ("1 0", IDString(model)); 547 EXPECT_FALSE(TabDragController::IsActive()); 548 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 549} 550 551namespace { 552 553// Invoked from the nested message loop. 554void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 555 TabStrip* not_attached_tab_strip, 556 TabStrip* target_tab_strip) { 557 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 558 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 559 ASSERT_TRUE(TabDragController::IsActive()); 560 561 // Drag to target_tab_strip. This should stop the nested loop from dragging 562 // the window. 563 gfx::Point target_point(target_tab_strip->width() -1, 564 target_tab_strip->height() / 2); 565 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 566 ASSERT_TRUE(test->DragInputToAsync(target_point)); 567} 568 569} // namespace 570 571// Creates two browsers, drags from first into second. 572IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 573 DragToSeparateWindow) { 574 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 575 576 // Add another tab to browser(). 577 AddTabAndResetBrowser(browser()); 578 579 // Create another browser. 580 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 581 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 582 583 // Move to the first tab and drag it enough so that it detaches, but not 584 // enough that it attaches to browser2. 585 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 586 ASSERT_TRUE(PressInput(tab_0_center)); 587 ASSERT_TRUE(DragInputToNotifyWhenDone( 588 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 589 base::Bind(&DragToSeparateWindowStep2, 590 this, tab_strip, tab_strip2))); 591 QuitWhenNotDragging(); 592 593 // Should now be attached to tab_strip2. 594 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 595 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 596 ASSERT_TRUE(TabDragController::IsActive()); 597 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 598 599 // Release the mouse, stopping the drag session. 600 ASSERT_TRUE(ReleaseInput()); 601 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 602 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 603 ASSERT_FALSE(TabDragController::IsActive()); 604 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 605 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 606 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 607 608 // Both windows should not be maximized 609 EXPECT_FALSE(browser()->window()->IsMaximized()); 610 EXPECT_FALSE(browser2->window()->IsMaximized()); 611} 612 613namespace { 614 615void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest* test) { 616 if (test->input_source() == INPUT_SOURCE_TOUCH) 617 ASSERT_TRUE(test->ReleaseInput()); 618} 619 620#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 621bool IsWindowPositionManaged(aura::Window* window) { 622 return ash::wm::GetWindowState(window)->window_position_managed(); 623} 624bool HasUserChangedWindowPositionOrSize(aura::Window* window) { 625 return ash::wm::GetWindowState(window)->bounds_changed_by_user(); 626} 627#else 628bool IsWindowPositionManaged(gfx::NativeWindow window) { 629 return true; 630} 631bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window) { 632 return false; 633} 634#endif 635 636} // namespace 637 638// Drags from browser to separate window and releases mouse. 639IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 640 DetachToOwnWindow) { 641 const gfx::Rect initial_bounds(browser()->window()->GetBounds()); 642 // Add another tab. 643 AddTabAndResetBrowser(browser()); 644 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 645 646 // Move to the first tab and drag it enough so that it detaches. 647 gfx::Point tab_0_center( 648 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 649 ASSERT_TRUE(PressInput(tab_0_center)); 650 ASSERT_TRUE(DragInputToNotifyWhenDone( 651 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 652 base::Bind(&DetachToOwnWindowStep2, this))); 653 if (input_source() == INPUT_SOURCE_MOUSE) { 654 ASSERT_TRUE(ReleaseMouseAsync()); 655 QuitWhenNotDragging(); 656 } 657 658 // Should no longer be dragging. 659 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 660 ASSERT_FALSE(TabDragController::IsActive()); 661 662 // There should now be another browser. 663 ASSERT_EQ(2u, native_browser_list->size()); 664 Browser* new_browser = native_browser_list->get(1); 665 ASSERT_TRUE(new_browser->window()->IsActive()); 666 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 667 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 668 669 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 670 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 671 672 // The bounds of the initial window should not have changed. 673 EXPECT_EQ(initial_bounds.ToString(), 674 browser()->window()->GetBounds().ToString()); 675 676 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 677 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 678 // After this both windows should still be manageable. 679 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 680 EXPECT_TRUE(IsWindowPositionManaged( 681 new_browser->window()->GetNativeWindow())); 682 683 // Both windows should not be maximized 684 EXPECT_FALSE(browser()->window()->IsMaximized()); 685 EXPECT_FALSE(new_browser->window()->IsMaximized()); 686} 687 688// Drags from browser to separate window and releases mouse. 689IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 690 DetachToOwnWindowFromMaximizedWindow) { 691 if (!TabDragController::ShouldDetachIntoNewBrowser()) { 692 VLOG(1) 693 << "Skipping DetachToOwnWindowFromMaximizedWindow on this platform."; 694 return; 695 } 696 697 // Maximize the initial browser window. 698 browser()->window()->Maximize(); 699 ASSERT_TRUE(browser()->window()->IsMaximized()); 700 701 // Add another tab. 702 AddTabAndResetBrowser(browser()); 703 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 704 705 // Move to the first tab and drag it enough so that it detaches. 706 gfx::Point tab_0_center( 707 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 708 ASSERT_TRUE(PressInput(tab_0_center)); 709 ASSERT_TRUE(DragInputToNotifyWhenDone( 710 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 711 base::Bind(&DetachToOwnWindowStep2, this))); 712 if (input_source() == INPUT_SOURCE_MOUSE) { 713 ASSERT_TRUE(ReleaseMouseAsync()); 714 QuitWhenNotDragging(); 715 } 716 717 // Should no longer be dragging. 718 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 719 ASSERT_FALSE(TabDragController::IsActive()); 720 721 // There should now be another browser. 722 ASSERT_EQ(2u, native_browser_list->size()); 723 Browser* new_browser = native_browser_list->get(1); 724 ASSERT_TRUE(new_browser->window()->IsActive()); 725 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 726 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 727 728 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 729 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 730 731 // The bounds of the initial window should not have changed. 732 EXPECT_TRUE(browser()->window()->IsMaximized()); 733 734 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 735 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 736 // After this both windows should still be manageable. 737 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 738 EXPECT_TRUE(IsWindowPositionManaged( 739 new_browser->window()->GetNativeWindow())); 740 741 // The new window should be maximized. 742 EXPECT_TRUE(new_browser->window()->IsMaximized()); 743} 744 745// Deletes a tab being dragged before the user moved enough to start a drag. 746IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 747 DeleteBeforeStartedDragging) { 748 // Add another tab. 749 AddTabAndResetBrowser(browser()); 750 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 751 752 // Click on the first tab, but don't move it. 753 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 754 ASSERT_TRUE(PressInput(tab_0_center)); 755 756 // Should be dragging. 757 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 758 ASSERT_TRUE(TabDragController::IsActive()); 759 760 // Delete the tab being dragged. 761 delete browser()->tab_strip_model()->GetWebContentsAt(0); 762 763 // Should have canceled dragging. 764 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 765 ASSERT_FALSE(TabDragController::IsActive()); 766 767 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 768 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 769} 770 771// Deletes a tab being dragged while still attached. 772IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 773 DeleteTabWhileAttached) { 774 // Add another tab. 775 AddTabAndResetBrowser(browser()); 776 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 777 778 // Click on the first tab and move it enough so that it starts dragging but is 779 // still attached. 780 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 781 ASSERT_TRUE(PressInput(tab_0_center)); 782 ASSERT_TRUE(DragInputTo( 783 gfx::Point(tab_0_center.x() + 20, tab_0_center.y()))); 784 785 // Should be dragging. 786 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 787 ASSERT_TRUE(TabDragController::IsActive()); 788 789 // Delete the tab being dragged. 790 delete browser()->tab_strip_model()->GetWebContentsAt(0); 791 792 // Should have canceled dragging. 793 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 794 ASSERT_FALSE(TabDragController::IsActive()); 795 796 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 797 798 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 799} 800 801namespace { 802 803void DeleteWhileDetachedStep2(WebContents* tab) { 804 delete tab; 805} 806 807} // namespace 808 809// Deletes a tab being dragged after dragging a tab so that a new window is 810// created. 811IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 812 DeleteTabWhileDetached) { 813 // Add another tab. 814 AddTabAndResetBrowser(browser()); 815 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 816 817 // Move to the first tab and drag it enough so that it detaches. 818 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 819 WebContents* to_delete = 820 browser()->tab_strip_model()->GetWebContentsAt(0); 821 ASSERT_TRUE(PressInput(tab_0_center)); 822 ASSERT_TRUE(DragInputToNotifyWhenDone( 823 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 824 base::Bind(&DeleteWhileDetachedStep2, to_delete))); 825 QuitWhenNotDragging(); 826 827 // Should not be dragging. 828 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 829 ASSERT_FALSE(TabDragController::IsActive()); 830 831 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 832 833 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 834} 835 836namespace { 837 838void DeleteSourceDetachedStep2(WebContents* tab, 839 const BrowserList* browser_list) { 840 ASSERT_EQ(2u, browser_list->size()); 841 Browser* new_browser = browser_list->get(1); 842 // This ends up closing the source window. 843 delete tab; 844 // Cancel the drag. 845 ui_controls::SendKeyPress(new_browser->window()->GetNativeWindow(), 846 ui::VKEY_ESCAPE, false, false, false, false); 847} 848 849} // namespace 850 851// Detaches a tab and while detached deletes a tab from the source so that the 852// source window closes then presses escape to cancel the drag. 853IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 854 DeleteSourceDetached) { 855 // Add another tab. 856 AddTabAndResetBrowser(browser()); 857 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 858 859 // Move to the first tab and drag it enough so that it detaches. 860 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 861 WebContents* to_delete = browser()->tab_strip_model()->GetWebContentsAt(1); 862 ASSERT_TRUE(PressInput(tab_0_center)); 863 ASSERT_TRUE(DragInputToNotifyWhenDone( 864 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 865 base::Bind(&DeleteSourceDetachedStep2, to_delete, native_browser_list))); 866 QuitWhenNotDragging(); 867 868 // Should not be dragging. 869 ASSERT_EQ(1u, native_browser_list->size()); 870 Browser* new_browser = native_browser_list->get(0); 871 ASSERT_FALSE(GetTabStripForBrowser(new_browser)->IsDragSessionActive()); 872 ASSERT_FALSE(TabDragController::IsActive()); 873 874 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 875 876 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 877 878 // Remaining browser window should not be maximized 879 EXPECT_FALSE(new_browser->window()->IsMaximized()); 880} 881 882namespace { 883 884void PressEscapeWhileDetachedStep2(const BrowserList* browser_list) { 885 ASSERT_EQ(2u, browser_list->size()); 886 Browser* new_browser = browser_list->get(1); 887 ui_controls::SendKeyPress( 888 new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, 889 false, false); 890} 891 892} // namespace 893 894// This is disabled until NativeViewHost::Detach really detaches. 895// Detaches a tab and while detached presses escape to revert the drag. 896IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 897 PressEscapeWhileDetached) { 898 // Add another tab. 899 AddTabAndResetBrowser(browser()); 900 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 901 902 // Move to the first tab and drag it enough so that it detaches. 903 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 904 ASSERT_TRUE(PressInput(tab_0_center)); 905 ASSERT_TRUE(DragInputToNotifyWhenDone( 906 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 907 base::Bind(&PressEscapeWhileDetachedStep2, native_browser_list))); 908 QuitWhenNotDragging(); 909 910 // Should not be dragging. 911 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 912 ASSERT_FALSE(TabDragController::IsActive()); 913 914 // And there should only be one window. 915 EXPECT_EQ(1u, native_browser_list->size()); 916 917 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 918 919 // Remaining browser window should not be maximized 920 EXPECT_FALSE(browser()->window()->IsMaximized()); 921} 922 923namespace { 924 925void DragAllStep2(DetachToBrowserTabDragControllerTest* test, 926 const BrowserList* browser_list) { 927 // Should only be one window. 928 ASSERT_EQ(1u, browser_list->size()); 929 if (test->input_source() == INPUT_SOURCE_TOUCH) { 930 ASSERT_TRUE(test->ReleaseInput()); 931 } else { 932 ASSERT_TRUE(test->ReleaseMouseAsync()); 933 } 934} 935 936} // namespace 937 938// Selects multiple tabs and starts dragging the window. 939IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragAll) { 940 // Add another tab. 941 AddTabAndResetBrowser(browser()); 942 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 943 browser()->tab_strip_model()->AddTabAtToSelection(0); 944 browser()->tab_strip_model()->AddTabAtToSelection(1); 945 946 // Move to the first tab and drag it enough so that it would normally 947 // detach. 948 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 949 ASSERT_TRUE(PressInput(tab_0_center)); 950 ASSERT_TRUE(DragInputToNotifyWhenDone( 951 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 952 base::Bind(&DragAllStep2, this, native_browser_list))); 953 QuitWhenNotDragging(); 954 955 // Should not be dragging. 956 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 957 ASSERT_FALSE(TabDragController::IsActive()); 958 959 // And there should only be one window. 960 EXPECT_EQ(1u, native_browser_list->size()); 961 962 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 963 964 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 965 966 // Remaining browser window should not be maximized 967 EXPECT_FALSE(browser()->window()->IsMaximized()); 968} 969 970namespace { 971 972// Invoked from the nested message loop. 973void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 974 TabStrip* attached_tab_strip, 975 TabStrip* target_tab_strip, 976 const BrowserList* browser_list) { 977 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 978 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 979 ASSERT_TRUE(TabDragController::IsActive()); 980 ASSERT_EQ(2u, browser_list->size()); 981 982 // Drag to target_tab_strip. This should stop the nested loop from dragging 983 // the window. 984 gfx::Point target_point(target_tab_strip->width() - 1, 985 target_tab_strip->height() / 2); 986 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 987 ASSERT_TRUE(test->DragInputToAsync(target_point)); 988} 989 990} // namespace 991 992// Creates two browsers, selects all tabs in first and drags into second. 993IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 994 DragAllToSeparateWindow) { 995 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 996 997 // Add another tab to browser(). 998 AddTabAndResetBrowser(browser()); 999 1000 // Create another browser. 1001 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1002 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1003 1004 browser()->tab_strip_model()->AddTabAtToSelection(0); 1005 browser()->tab_strip_model()->AddTabAtToSelection(1); 1006 1007 // Move to the first tab and drag it enough so that it detaches, but not 1008 // enough that it attaches to browser2. 1009 gfx::Point tab_0_center( 1010 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1011 ASSERT_TRUE(PressInput(tab_0_center)); 1012 ASSERT_TRUE(DragInputToNotifyWhenDone( 1013 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1014 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 1015 native_browser_list))); 1016 QuitWhenNotDragging(); 1017 1018 // Should now be attached to tab_strip2. 1019 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1020 ASSERT_TRUE(TabDragController::IsActive()); 1021 ASSERT_EQ(1u, native_browser_list->size()); 1022 1023 // Release the mouse, stopping the drag session. 1024 ASSERT_TRUE(ReleaseInput()); 1025 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1026 ASSERT_FALSE(TabDragController::IsActive()); 1027 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 1028 1029 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 1030 1031 // Remaining browser window should not be maximized 1032 EXPECT_FALSE(browser2->window()->IsMaximized()); 1033} 1034 1035namespace { 1036 1037// Invoked from the nested message loop. 1038void DragAllToSeparateWindowAndCancelStep2( 1039 DetachToBrowserTabDragControllerTest* test, 1040 TabStrip* attached_tab_strip, 1041 TabStrip* target_tab_strip, 1042 const BrowserList* browser_list) { 1043 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 1044 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1045 ASSERT_TRUE(TabDragController::IsActive()); 1046 ASSERT_EQ(2u, browser_list->size()); 1047 1048 // Drag to target_tab_strip. This should stop the nested loop from dragging 1049 // the window. 1050 gfx::Point target_point(target_tab_strip->width() - 1, 1051 target_tab_strip->height() / 2); 1052 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 1053 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1054} 1055 1056} // namespace 1057 1058// Creates two browsers, selects all tabs in first, drags into second, then hits 1059// escape. 1060IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1061 DragAllToSeparateWindowAndCancel) { 1062 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1063 1064 // Add another tab to browser(). 1065 AddTabAndResetBrowser(browser()); 1066 1067 // Create another browser. 1068 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1069 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1070 1071 browser()->tab_strip_model()->AddTabAtToSelection(0); 1072 browser()->tab_strip_model()->AddTabAtToSelection(1); 1073 1074 // Move to the first tab and drag it enough so that it detaches, but not 1075 // enough that it attaches to browser2. 1076 gfx::Point tab_0_center( 1077 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1078 ASSERT_TRUE(PressInput(tab_0_center)); 1079 ASSERT_TRUE(DragInputToNotifyWhenDone( 1080 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1081 base::Bind(&DragAllToSeparateWindowAndCancelStep2, this, 1082 tab_strip, tab_strip2, native_browser_list))); 1083 QuitWhenNotDragging(); 1084 1085 // Should now be attached to tab_strip2. 1086 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1087 ASSERT_TRUE(TabDragController::IsActive()); 1088 ASSERT_EQ(1u, native_browser_list->size()); 1089 1090 // Cancel the drag. 1091 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 1092 browser2, ui::VKEY_ESCAPE, false, false, false, false)); 1093 1094 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1095 ASSERT_FALSE(TabDragController::IsActive()); 1096 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 1097 1098 // browser() will have been destroyed, but browser2 should remain. 1099 ASSERT_EQ(1u, native_browser_list->size()); 1100 1101 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 1102 1103 // Remaining browser window should not be maximized 1104 EXPECT_FALSE(browser2->window()->IsMaximized()); 1105} 1106 1107// Creates two browsers, drags from first into the second in such a way that 1108// no detaching should happen. 1109IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1110 DragDirectlyToSecondWindow) { 1111 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1112 1113 // Add another tab to browser(). 1114 AddTabAndResetBrowser(browser()); 1115 1116 // Create another browser. 1117 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1118 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1119 1120 // Move the tabstrip down enough so that we can detach. 1121 gfx::Rect bounds(browser2->window()->GetBounds()); 1122 bounds.Offset(0, 100); 1123 browser2->window()->SetBounds(bounds); 1124 1125 // Move to the first tab and drag it enough so that it detaches, but not 1126 // enough that it attaches to browser2. 1127 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1128 ASSERT_TRUE(PressInput(tab_0_center)); 1129 1130 gfx::Point b2_location(5, 0); 1131 views::View::ConvertPointToScreen(tab_strip2, &b2_location); 1132 ASSERT_TRUE(DragInputTo(b2_location)); 1133 1134 // Should now be attached to tab_strip2. 1135 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1136 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1137 ASSERT_TRUE(TabDragController::IsActive()); 1138 1139 // Release the mouse, stopping the drag session. 1140 ASSERT_TRUE(ReleaseInput()); 1141 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1142 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1143 ASSERT_FALSE(TabDragController::IsActive()); 1144 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1145 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1146 1147 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 1148 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 1149 1150 // Both windows should not be maximized 1151 EXPECT_FALSE(browser()->window()->IsMaximized()); 1152 EXPECT_FALSE(browser2->window()->IsMaximized()); 1153} 1154 1155// Creates two browsers, the first browser has a single tab and drags into the 1156// second browser. 1157IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1158 DragSingleTabToSeparateWindow) { 1159 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1160 1161 ResetIDs(browser()->tab_strip_model(), 0); 1162 1163 // Create another browser. 1164 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1165 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1166 const gfx::Rect initial_bounds(browser2->window()->GetBounds()); 1167 1168 // Move to the first tab and drag it enough so that it detaches, but not 1169 // enough that it attaches to browser2. 1170 gfx::Point tab_0_center( 1171 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1172 ASSERT_TRUE(PressInput(tab_0_center)); 1173 ASSERT_TRUE(DragInputToNotifyWhenDone( 1174 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1175 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 1176 native_browser_list))); 1177 QuitWhenNotDragging(); 1178 1179 // Should now be attached to tab_strip2. 1180 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1181 ASSERT_TRUE(TabDragController::IsActive()); 1182 ASSERT_EQ(1u, native_browser_list->size()); 1183 1184 // Release the mouse, stopping the drag session. 1185 ASSERT_TRUE(ReleaseInput()); 1186 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1187 ASSERT_FALSE(TabDragController::IsActive()); 1188 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 1189 1190 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 1191 1192 // Remaining browser window should not be maximized 1193 EXPECT_FALSE(browser2->window()->IsMaximized()); 1194 1195 // Make sure that the window is still managed and not user moved. 1196 EXPECT_TRUE(IsWindowPositionManaged(browser2->window()->GetNativeWindow())); 1197 EXPECT_FALSE(HasUserChangedWindowPositionOrSize( 1198 browser2->window()->GetNativeWindow())); 1199 // Also make sure that the drag to window position has not changed. 1200 EXPECT_EQ(initial_bounds.ToString(), 1201 browser2->window()->GetBounds().ToString()); 1202} 1203 1204namespace { 1205 1206// Invoked from the nested message loop. 1207void CancelOnNewTabWhenDraggingStep2( 1208 DetachToBrowserTabDragControllerTest* test, 1209 const BrowserList* browser_list) { 1210 ASSERT_TRUE(TabDragController::IsActive()); 1211 ASSERT_EQ(2u, browser_list->size()); 1212 1213 // Add another tab. This should trigger exiting the nested loop. 1214 test->AddBlankTabAndShow(browser_list->GetLastActive()); 1215} 1216 1217} // namespace 1218 1219// Adds another tab, detaches into separate window, adds another tab and 1220// verifies the run loop ends. 1221IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1222 CancelOnNewTabWhenDragging) { 1223 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1224 1225 // Add another tab to browser(). 1226 AddTabAndResetBrowser(browser()); 1227 1228 // Move to the first tab and drag it enough so that it detaches. 1229 gfx::Point tab_0_center( 1230 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1231 ASSERT_TRUE(PressInput(tab_0_center)); 1232 ASSERT_TRUE(DragInputToNotifyWhenDone( 1233 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1234 base::Bind(&CancelOnNewTabWhenDraggingStep2, this, native_browser_list))); 1235 QuitWhenNotDragging(); 1236 1237 // Should be two windows and not dragging. 1238 ASSERT_FALSE(TabDragController::IsActive()); 1239 ASSERT_EQ(2u, native_browser_list->size()); 1240 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 1241 EXPECT_TRUE(GetTrackedByWorkspace(*it)); 1242 // Should not be maximized 1243 EXPECT_FALSE(it->window()->IsMaximized()); 1244 } 1245} 1246 1247#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 1248 1249namespace { 1250 1251void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest* test, 1252 Browser* browser, 1253 TabStrip* tab_strip, 1254 const BrowserList* browser_list) { 1255 // There should be another browser. 1256 ASSERT_EQ(2u, browser_list->size()); 1257 Browser* new_browser = browser_list->get(1); 1258 EXPECT_NE(browser, new_browser); 1259 ASSERT_TRUE(new_browser->window()->IsActive()); 1260 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1261 1262 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1263 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1264 1265 // Both windows should be visible. 1266 EXPECT_TRUE(tab_strip->GetWidget()->IsVisible()); 1267 EXPECT_TRUE(tab_strip2->GetWidget()->IsVisible()); 1268 1269 // Stops dragging. 1270 ASSERT_TRUE(test->ReleaseInput()); 1271} 1272 1273} // namespace 1274 1275// Creates a browser with two tabs, maximizes it, drags the tab out. 1276IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1277 DragInMaximizedWindow) { 1278 AddTabAndResetBrowser(browser()); 1279 browser()->window()->Maximize(); 1280 1281 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1282 1283 // Move to the first tab and drag it enough so that it detaches. 1284 gfx::Point tab_0_center( 1285 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1286 ASSERT_TRUE(PressInput(tab_0_center)); 1287 ASSERT_TRUE(DragInputToNotifyWhenDone( 1288 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1289 base::Bind(&DragInMaximizedWindowStep2, this, browser(), tab_strip, 1290 native_browser_list))); 1291 QuitWhenNotDragging(); 1292 1293 ASSERT_FALSE(TabDragController::IsActive()); 1294 1295 // Should be two browsers. 1296 ASSERT_EQ(2u, native_browser_list->size()); 1297 Browser* new_browser = native_browser_list->get(1); 1298 ASSERT_TRUE(new_browser->window()->IsActive()); 1299 1300 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible()); 1301 EXPECT_TRUE(new_browser->window()->GetNativeWindow()->IsVisible()); 1302 1303 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 1304 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 1305 1306 // The source window should be maximized. 1307 EXPECT_TRUE(browser()->window()->IsMaximized()); 1308 // The new window should be maximized. 1309 EXPECT_TRUE(new_browser->window()->IsMaximized()); 1310} 1311 1312// Subclass of DetachToBrowserTabDragControllerTest that 1313// creates multiple displays. 1314class DetachToBrowserInSeparateDisplayTabDragControllerTest 1315 : public DetachToBrowserTabDragControllerTest { 1316 public: 1317 DetachToBrowserInSeparateDisplayTabDragControllerTest() {} 1318 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {} 1319 1320 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1321 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1322 // Make screens sufficiently wide to host 2 browsers side by side. 1323 command_line->AppendSwitchASCII("ash-host-window-bounds", 1324 "0+0-600x600,601+0-600x600"); 1325 } 1326 1327 private: 1328 DISALLOW_COPY_AND_ASSIGN( 1329 DetachToBrowserInSeparateDisplayTabDragControllerTest); 1330}; 1331 1332// Subclass of DetachToBrowserTabDragControllerTest that runs tests only with 1333// touch input. 1334class DetachToBrowserTabDragControllerTestTouch 1335 : public DetachToBrowserTabDragControllerTest { 1336 public: 1337 DetachToBrowserTabDragControllerTestTouch() {} 1338 virtual ~DetachToBrowserTabDragControllerTestTouch() {} 1339 1340 private: 1341 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch); 1342}; 1343 1344namespace { 1345 1346void DragSingleTabToSeparateWindowInSecondDisplayStep3( 1347 DetachToBrowserTabDragControllerTest* test) { 1348 ASSERT_TRUE(test->ReleaseInput()); 1349} 1350 1351void DragSingleTabToSeparateWindowInSecondDisplayStep2( 1352 DetachToBrowserTabDragControllerTest* test, 1353 const gfx::Point& target_point) { 1354 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1355 target_point.x(), target_point.y(), 1356 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3, test))); 1357} 1358 1359} // namespace 1360 1361// Drags from browser to a second display and releases input. 1362IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1363 DragSingleTabToSeparateWindowInSecondDisplay) { 1364 // Add another tab. 1365 AddTabAndResetBrowser(browser()); 1366 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1367 1368 // Move to the first tab and drag it enough so that it detaches. 1369 // Then drag it to the final destination on the second screen. 1370 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1371 ASSERT_TRUE(PressInput(tab_0_center)); 1372 ASSERT_TRUE(DragInputToNotifyWhenDone( 1373 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1374 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2, 1375 this, gfx::Point(600 + tab_0_center.x(), 1376 tab_0_center.y() 1377 + GetDetachY(tab_strip))))); 1378 QuitWhenNotDragging(); 1379 1380 // Should no longer be dragging. 1381 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1382 ASSERT_FALSE(TabDragController::IsActive()); 1383 1384 // There should now be another browser. 1385 ASSERT_EQ(2u, native_browser_list->size()); 1386 Browser* new_browser = native_browser_list->get(1); 1387 ASSERT_TRUE(new_browser->window()->IsActive()); 1388 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1389 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1390 1391 // This other browser should be on the second screen (with mouse drag) 1392 // With the touch input the browser cannot be dragged from one screen 1393 // to another and the window stays on the first screen. 1394 if (input_source() == INPUT_SOURCE_MOUSE) { 1395 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1396 ASSERT_EQ(2u, roots.size()); 1397 aura::RootWindow* second_root = roots[1]; 1398 EXPECT_EQ(second_root, 1399 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1400 } 1401 1402 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 1403 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1404 1405 // Both windows should not be maximized 1406 EXPECT_FALSE(browser()->window()->IsMaximized()); 1407 EXPECT_FALSE(new_browser->window()->IsMaximized()); 1408} 1409 1410namespace { 1411 1412// Invoked from the nested message loop. 1413void DragTabToWindowInSeparateDisplayStep2( 1414 DetachToBrowserTabDragControllerTest* test, 1415 TabStrip* not_attached_tab_strip, 1416 TabStrip* target_tab_strip) { 1417 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1418 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1419 ASSERT_TRUE(TabDragController::IsActive()); 1420 1421 // Drag to target_tab_strip. This should stop the nested loop from dragging 1422 // the window. 1423 gfx::Point target_point( 1424 GetCenterInScreenCoordinates(target_tab_strip->tab_at(0))); 1425 1426 // Move it close to the beginning of the target tabstrip. 1427 target_point.set_x( 1428 target_point.x() - target_tab_strip->tab_at(0)->width() / 2 + 10); 1429 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1430} 1431 1432} // namespace 1433 1434// Drags from browser to another browser on a second display and releases input. 1435IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1436 DragTabToWindowInSeparateDisplay) { 1437 // Add another tab. 1438 AddTabAndResetBrowser(browser()); 1439 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1440 1441 // Create another browser. 1442 Browser* browser2 = CreateBrowser(browser()->profile()); 1443 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1444 ResetIDs(browser2->tab_strip_model(), 100); 1445 1446 // Move the second browser to the second display. 1447 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1448 ASSERT_EQ(2u, roots.size()); 1449 aura::RootWindow* second_root = roots[1]; 1450 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1451 second_root).work_area(); 1452 browser2->window()->SetBounds(work_area); 1453 EXPECT_EQ(second_root, 1454 browser2->window()->GetNativeWindow()->GetRootWindow()); 1455 1456 // Move to the first tab and drag it enough so that it detaches, but not 1457 // enough that it attaches to browser2. 1458 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1459 ASSERT_TRUE(PressInput(tab_0_center)); 1460 ASSERT_TRUE(DragInputToNotifyWhenDone( 1461 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1462 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1463 this, tab_strip, tab_strip2))); 1464 QuitWhenNotDragging(); 1465 1466 // Should now be attached to tab_strip2. 1467 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1468 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1469 ASSERT_TRUE(TabDragController::IsActive()); 1470 1471 // Release the mouse, stopping the drag session. 1472 ASSERT_TRUE(ReleaseInput()); 1473 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1474 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1475 ASSERT_FALSE(TabDragController::IsActive()); 1476 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1477 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1478 1479 // Both windows should not be maximized 1480 EXPECT_FALSE(browser()->window()->IsMaximized()); 1481 EXPECT_FALSE(browser2->window()->IsMaximized()); 1482} 1483 1484// Drags from browser to another browser on a second display and releases input. 1485IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1486 DragTabToWindowOnSecondDisplay) { 1487 // Add another tab. 1488 AddTabAndResetBrowser(browser()); 1489 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1490 1491 // Create another browser. 1492 Browser* browser2 = CreateBrowser(browser()->profile()); 1493 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1494 ResetIDs(browser2->tab_strip_model(), 100); 1495 1496 // Move both browsers to the second display. 1497 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1498 ASSERT_EQ(2u, roots.size()); 1499 aura::RootWindow* second_root = roots[1]; 1500 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1501 second_root).work_area(); 1502 browser()->window()->SetBounds(work_area); 1503 1504 // position both browser windows side by side on the second screen. 1505 gfx::Rect work_area2(work_area); 1506 work_area.set_width(work_area.width()/2); 1507 browser()->window()->SetBounds(work_area); 1508 work_area2.set_x(work_area2.x() + work_area2.width()/2); 1509 work_area2.set_width(work_area2.width()/2); 1510 browser2->window()->SetBounds(work_area2); 1511 EXPECT_EQ(second_root, 1512 browser()->window()->GetNativeWindow()->GetRootWindow()); 1513 EXPECT_EQ(second_root, 1514 browser2->window()->GetNativeWindow()->GetRootWindow()); 1515 1516 // Move to the first tab and drag it enough so that it detaches, but not 1517 // enough that it attaches to browser2. 1518 // SetEventGeneratorRootWindow sets correct (second) RootWindow 1519 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1520 SetEventGeneratorRootWindow(tab_0_center); 1521 ASSERT_TRUE(PressInput(tab_0_center)); 1522 ASSERT_TRUE(DragInputToNotifyWhenDone( 1523 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1524 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1525 this, tab_strip, tab_strip2))); 1526 QuitWhenNotDragging(); 1527 1528 // Should now be attached to tab_strip2. 1529 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1530 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1531 ASSERT_TRUE(TabDragController::IsActive()); 1532 1533 // Release the mouse, stopping the drag session. 1534 ASSERT_TRUE(ReleaseInput()); 1535 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1536 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1537 ASSERT_FALSE(TabDragController::IsActive()); 1538 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1539 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1540 1541 // Both windows should not be maximized 1542 EXPECT_FALSE(browser()->window()->IsMaximized()); 1543 EXPECT_FALSE(browser2->window()->IsMaximized()); 1544} 1545 1546// Drags from a maximized browser to another non-maximized browser on a second 1547// display and releases input. 1548IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1549 DragMaxTabToNonMaxWindowInSeparateDisplay) { 1550 // Add another tab. 1551 AddTabAndResetBrowser(browser()); 1552 browser()->window()->Maximize(); 1553 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1554 1555 // Create another browser on the second display. 1556 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1557 ASSERT_EQ(2u, roots.size()); 1558 aura::RootWindow* first_root = roots[0]; 1559 aura::RootWindow* second_root = roots[1]; 1560 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1561 second_root).work_area(); 1562 work_area.Inset(20,20,20,60); 1563 Browser::CreateParams params(browser()->profile(), 1564 browser()->host_desktop_type()); 1565 params.initial_show_state = ui::SHOW_STATE_NORMAL; 1566 params.initial_bounds = work_area; 1567 Browser* browser2 = new Browser(params); 1568 AddBlankTabAndShow(browser2); 1569 1570 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1571 ResetIDs(browser2->tab_strip_model(), 100); 1572 1573 EXPECT_EQ(second_root, 1574 browser2->window()->GetNativeWindow()->GetRootWindow()); 1575 EXPECT_EQ(first_root, 1576 browser()->window()->GetNativeWindow()->GetRootWindow()); 1577 EXPECT_EQ(2, tab_strip->tab_count()); 1578 EXPECT_EQ(1, tab_strip2->tab_count()); 1579 1580 // Move to the first tab and drag it enough so that it detaches, but not 1581 // enough that it attaches to browser2. 1582 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1583 ASSERT_TRUE(PressInput(tab_0_center)); 1584 ASSERT_TRUE(DragInputToNotifyWhenDone( 1585 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1586 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1587 this, tab_strip, tab_strip2))); 1588 QuitWhenNotDragging(); 1589 1590 // Should now be attached to tab_strip2. 1591 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1592 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1593 ASSERT_TRUE(TabDragController::IsActive()); 1594 1595 // Release the mouse, stopping the drag session. 1596 ASSERT_TRUE(ReleaseInput()); 1597 1598 // tab should have moved 1599 EXPECT_EQ(1, tab_strip->tab_count()); 1600 EXPECT_EQ(2, tab_strip2->tab_count()); 1601 1602 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1603 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1604 ASSERT_FALSE(TabDragController::IsActive()); 1605 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1606 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1607 1608 // Source browser should still be maximized, target should not 1609 EXPECT_TRUE(browser()->window()->IsMaximized()); 1610 EXPECT_FALSE(browser2->window()->IsMaximized()); 1611} 1612 1613// Immersive fullscreen is ChromeOS only. 1614#if defined(OS_CHROMEOS) 1615// Drags from a restored browser to an immersive fullscreen browser on a 1616// second display and releases input. 1617IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1618 DragTabToImmersiveBrowserOnSeparateDisplay) { 1619 // Add another tab. 1620 AddTabAndResetBrowser(browser()); 1621 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1622 1623 // Create another browser. 1624 Browser* browser2 = CreateBrowser(browser()->profile()); 1625 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1626 ResetIDs(browser2->tab_strip_model(), 100); 1627 1628 // Move the second browser to the second display. 1629 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1630 ASSERT_EQ(2u, roots.size()); 1631 aura::RootWindow* second_root = roots[1]; 1632 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1633 second_root).work_area(); 1634 browser2->window()->SetBounds(work_area); 1635 EXPECT_EQ(second_root, 1636 browser2->window()->GetNativeWindow()->GetRootWindow()); 1637 1638 // Put the second browser into immersive fullscreen. 1639 BrowserView* browser_view2 = BrowserView::GetBrowserViewForBrowser(browser2); 1640 ImmersiveModeController* immersive_controller2 = 1641 browser_view2->immersive_mode_controller(); 1642 immersive_controller2->SetupForTest(); 1643 chrome::ToggleFullscreenMode(browser2); 1644 ASSERT_TRUE(immersive_controller2->IsEnabled()); 1645 ASSERT_FALSE(immersive_controller2->IsRevealed()); 1646 ASSERT_TRUE(tab_strip2->IsImmersiveStyle()); 1647 1648 // Move to the first tab and drag it enough so that it detaches, but not 1649 // enough that it attaches to browser2. 1650 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1651 ASSERT_TRUE(PressInput(tab_0_center)); 1652 ASSERT_TRUE(DragInputToNotifyWhenDone( 1653 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1654 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1655 this, tab_strip, tab_strip2))); 1656 QuitWhenNotDragging(); 1657 1658 // Should now be attached to tab_strip2. 1659 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1660 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1661 ASSERT_TRUE(TabDragController::IsActive()); 1662 1663 // browser2's top chrome should be revealed and the tab strip should be 1664 // at normal height while user is tragging tabs_strip2's tabs. 1665 ASSERT_TRUE(immersive_controller2->IsRevealed()); 1666 ASSERT_FALSE(tab_strip2->IsImmersiveStyle()); 1667 1668 // Release the mouse, stopping the drag session. 1669 ASSERT_TRUE(ReleaseInput()); 1670 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1671 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1672 ASSERT_FALSE(TabDragController::IsActive()); 1673 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1674 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1675 1676 // The first browser window should not be in immersive fullscreen. 1677 // browser2 should still be in immersive fullscreen, but the top chrome should 1678 // no longer be revealed. 1679 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 1680 EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); 1681 1682 EXPECT_TRUE(immersive_controller2->IsEnabled()); 1683 EXPECT_FALSE(immersive_controller2->IsRevealed()); 1684 EXPECT_TRUE(tab_strip2->IsImmersiveStyle()); 1685} 1686#endif // OS_CHROMEOS 1687 1688// Subclass of DetachToBrowserTabDragControllerTest that 1689// creates multiple displays with different device scale factors. 1690class DifferentDeviceScaleFactorDisplayTabDragControllerTest 1691 : public DetachToBrowserTabDragControllerTest { 1692 public: 1693 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {} 1694 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {} 1695 1696 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1697 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1698 command_line->AppendSwitchASCII("ash-host-window-bounds", 1699 "400x400,0+400-800x800*2"); 1700 } 1701 1702 float GetCursorDeviceScaleFactor() const { 1703 ash::test::CursorManagerTestApi cursor_test_api( 1704 ash::Shell::GetInstance()->cursor_manager()); 1705 return cursor_test_api.GetDisplay().device_scale_factor(); 1706 } 1707 1708 private: 1709 DISALLOW_COPY_AND_ASSIGN( 1710 DifferentDeviceScaleFactorDisplayTabDragControllerTest); 1711}; 1712 1713namespace { 1714 1715// The points where a tab is dragged in CursorDeviceScaleFactorStep. 1716const struct DragPoint { 1717 int x; 1718 int y; 1719} kDragPoints[] = { 1720 {300, 200}, 1721 {399, 200}, 1722 {500, 200}, 1723 {400, 200}, 1724 {300, 200}, 1725}; 1726 1727// The expected device scale factors before the cursor is moved to the 1728// corresponding kDragPoints in CursorDeviceScaleFactorStep. 1729const float kDeviceScaleFactorExpectations[] = { 1730 1.0f, 1731 1.0f, 1732 2.0f, 1733 2.0f, 1734 1.0f, 1735}; 1736 1737COMPILE_ASSERT( 1738 arraysize(kDragPoints) == arraysize(kDeviceScaleFactorExpectations), 1739 kDragPoints_and_kDeviceScaleFactorExpectations_must_have_same_size); 1740 1741// Drags tab to |kDragPoints[index]|, then calls the next step function. 1742void CursorDeviceScaleFactorStep( 1743 DifferentDeviceScaleFactorDisplayTabDragControllerTest* test, 1744 TabStrip* not_attached_tab_strip, 1745 size_t index) { 1746 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1747 ASSERT_TRUE(TabDragController::IsActive()); 1748 1749 if (index < arraysize(kDragPoints)) { 1750 EXPECT_EQ(kDeviceScaleFactorExpectations[index], 1751 test->GetCursorDeviceScaleFactor()); 1752 const DragPoint p = kDragPoints[index]; 1753 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1754 p.x, p.y, base::Bind(&CursorDeviceScaleFactorStep, 1755 test, not_attached_tab_strip, index + 1))); 1756 } else { 1757 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag. 1758 EXPECT_EQ(1.0f, test->GetCursorDeviceScaleFactor()); 1759 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1760 ui_controls::LEFT, ui_controls::UP)); 1761 } 1762} 1763 1764} // namespace 1765 1766// Verifies cursor's device scale factor is updated when a tab is moved across 1767// displays with different device scale factors (http://crbug.com/154183). 1768IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest, 1769 CursorDeviceScaleFactor) { 1770 // Add another tab. 1771 AddTabAndResetBrowser(browser()); 1772 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1773 1774 // Move the second browser to the second display. 1775 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1776 ASSERT_EQ(2u, roots.size()); 1777 1778 // Move to the first tab and drag it enough so that it detaches. 1779 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1780 ASSERT_TRUE(PressInput(tab_0_center)); 1781 ASSERT_TRUE(DragInputToNotifyWhenDone( 1782 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1783 base::Bind(&CursorDeviceScaleFactorStep, 1784 this, tab_strip, 0))); 1785 QuitWhenNotDragging(); 1786} 1787 1788namespace { 1789 1790class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest 1791 : public TabDragControllerTest { 1792 public: 1793 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {} 1794 1795 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1796 TabDragControllerTest::SetUpCommandLine(command_line); 1797 command_line->AppendSwitchASCII("ash-host-window-bounds", 1798 "0+0-250x250,251+0-250x250"); 1799 } 1800 1801 bool Press(const gfx::Point& position) { 1802 return ui_test_utils::SendMouseMoveSync(position) && 1803 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, 1804 ui_controls::DOWN); 1805 } 1806 1807 bool DragTabAndExecuteTaskWhenDone(const gfx::Point& position, 1808 const base::Closure& task) { 1809 return ui_controls::SendMouseMoveNotifyWhenDone( 1810 position.x(), position.y(), task); 1811 } 1812 1813 void QuitWhenNotDragging() { 1814 test::QuitWhenNotDraggingImpl(); 1815 base::MessageLoop::current()->Run(); 1816 } 1817 1818 private: 1819 DISALLOW_COPY_AND_ASSIGN( 1820 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest); 1821}; 1822 1823// Invoked from the nested message loop. 1824void CancelDragTabToWindowInSeparateDisplayStep3( 1825 TabStrip* tab_strip, 1826 const BrowserList* browser_list) { 1827 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1828 ASSERT_TRUE(TabDragController::IsActive()); 1829 ASSERT_EQ(2u, browser_list->size()); 1830 1831 // Switching display mode should cancel the drag operation. 1832 ash::internal::DisplayManager* display_manager = 1833 ash::Shell::GetInstance()->display_manager(); 1834 display_manager->AddRemoveDisplay(); 1835} 1836 1837// Invoked from the nested message loop. 1838void CancelDragTabToWindowInSeparateDisplayStep2( 1839 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest* test, 1840 TabStrip* tab_strip, 1841 aura::RootWindow* current_root, 1842 gfx::Point final_destination, 1843 const BrowserList* browser_list) { 1844 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1845 ASSERT_TRUE(TabDragController::IsActive()); 1846 ASSERT_EQ(2u, browser_list->size()); 1847 1848 Browser* new_browser = browser_list->get(1); 1849 EXPECT_EQ(current_root, 1850 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1851 1852 ASSERT_TRUE(test->DragTabAndExecuteTaskWhenDone( 1853 final_destination, 1854 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3, 1855 tab_strip, browser_list))); 1856} 1857 1858} // namespace 1859 1860// Drags from browser to a second display and releases input. 1861IN_PROC_BROWSER_TEST_F( 1862 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 1863 CancelDragTabToWindowIn2ndDisplay) { 1864 // Add another tab. 1865 AddTabAndResetBrowser(browser()); 1866 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1867 1868 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1869 1870 // Move the second browser to the second display. 1871 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1872 ASSERT_EQ(2u, roots.size()); 1873 gfx::Point final_destination = 1874 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1875 roots[1]).work_area().CenterPoint(); 1876 1877 // Move to the first tab and drag it enough so that it detaches, but not 1878 // enough to move to another display. 1879 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1880 ASSERT_TRUE(Press(tab_0_dst)); 1881 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 1882 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 1883 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 1884 this, tab_strip, roots[0], final_destination, 1885 native_browser_list))); 1886 QuitWhenNotDragging(); 1887 1888 ASSERT_EQ(1u, native_browser_list->size()); 1889 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1890 ASSERT_FALSE(TabDragController::IsActive()); 1891 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1892 1893 // Release the mouse 1894 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1895 ui_controls::LEFT, ui_controls::UP)); 1896} 1897 1898// Drags from browser from a second display to primary and releases input. 1899IN_PROC_BROWSER_TEST_F( 1900 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 1901 CancelDragTabToWindowIn1stDisplay) { 1902 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1903 ASSERT_EQ(2u, roots.size()); 1904 1905 // Add another tab. 1906 AddTabAndResetBrowser(browser()); 1907 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1908 1909 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1910 EXPECT_EQ(roots[0], browser()->window()->GetNativeWindow()->GetRootWindow()); 1911 1912 gfx::Rect work_area = gfx::Screen::GetNativeScreen()-> 1913 GetDisplayNearestWindow(roots[1]).work_area(); 1914 browser()->window()->SetBounds(work_area); 1915 EXPECT_EQ(roots[1], browser()->window()->GetNativeWindow()->GetRootWindow()); 1916 1917 // Move the second browser to the display. 1918 gfx::Point final_destination = 1919 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1920 roots[0]).work_area().CenterPoint(); 1921 1922 // Move to the first tab and drag it enough so that it detaches, but not 1923 // enough to move to another display. 1924 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1925 ASSERT_TRUE(Press(tab_0_dst)); 1926 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 1927 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 1928 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 1929 this, tab_strip, roots[1], final_destination, 1930 native_browser_list))); 1931 QuitWhenNotDragging(); 1932 1933 ASSERT_EQ(1u, native_browser_list->size()); 1934 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1935 ASSERT_FALSE(TabDragController::IsActive()); 1936 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1937 1938 // Release the mouse 1939 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1940 ui_controls::LEFT, ui_controls::UP)); 1941} 1942 1943namespace { 1944 1945void DetachToOwnWindowTwoFingersDragStep5( 1946 DetachToBrowserTabDragControllerTest* test) { 1947 ASSERT_EQ(2u, test->native_browser_list->size()); 1948 Browser* new_browser = test->native_browser_list->get(1); 1949 ASSERT_TRUE(new_browser->window()->IsActive()); 1950 1951 ASSERT_TRUE(test->ReleaseInput()); 1952 ASSERT_TRUE(test->ReleaseInput2()); 1953 ASSERT_TRUE(new_browser->window()->IsActive()); 1954} 1955 1956void DetachToOwnWindowTwoFingersDragStep4( 1957 DetachToBrowserTabDragControllerTest* test, 1958 const gfx::Point& target_point) { 1959 ASSERT_EQ(2u, test->native_browser_list->size()); 1960 Browser* new_browser = test->native_browser_list->get(1); 1961 ASSERT_TRUE(new_browser->window()->IsActive()); 1962 1963 ASSERT_TRUE(test->DragInput2ToNotifyWhenDone( 1964 target_point.x(), target_point.y(), 1965 base::Bind(&DetachToOwnWindowTwoFingersDragStep5, test))); 1966} 1967 1968void DetachToOwnWindowTwoFingersDragStep3( 1969 DetachToBrowserTabDragControllerTest* test, 1970 const gfx::Point& target_point) { 1971 ASSERT_TRUE(test->PressInput2()); 1972 1973 ASSERT_EQ(2u, test->native_browser_list->size()); 1974 Browser* new_browser = test->native_browser_list->get(1); 1975 ASSERT_TRUE(new_browser->window()->IsActive()); 1976 1977 ASSERT_TRUE(test->DragInputToDelayedNotifyWhenDone( 1978 target_point.x(), target_point.y(), 1979 base::Bind(&DetachToOwnWindowTwoFingersDragStep4, 1980 test, 1981 target_point), 1982 base::TimeDelta::FromMilliseconds(60))); 1983} 1984 1985void DetachToOwnWindowTwoFingersDragStep2( 1986 DetachToBrowserTabDragControllerTest* test, 1987 const gfx::Point& target_point) { 1988 ASSERT_EQ(2u, test->native_browser_list->size()); 1989 Browser* new_browser = test->native_browser_list->get(1); 1990 ASSERT_TRUE(new_browser->window()->IsActive()); 1991 1992 ASSERT_TRUE(test->DragInputToDelayedNotifyWhenDone( 1993 target_point.x(), target_point.y(), 1994 base::Bind(&DetachToOwnWindowTwoFingersDragStep3, 1995 test, 1996 target_point + gfx::Vector2d(-2, 1)), 1997 base::TimeDelta::FromMilliseconds(60))); 1998} 1999 2000} // namespace 2001 2002// Drags from browser to separate window starting with one finger and 2003// then continuing with two fingers. 2004IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch, 2005 DetachToOwnWindowTwoFingers) { 2006 gfx::Rect bounds(browser()->window()->GetBounds()); 2007 // Add another tab. 2008 AddTabAndResetBrowser(browser()); 2009 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 2010 2011 // Move to the first tab and drag it enough so that it detaches. 2012 gfx::Point tab_0_center( 2013 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2014 ASSERT_TRUE(PressInput(tab_0_center)); 2015 // Drags in this test are very short to avoid fling. 2016 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone( 2017 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 2018 base::Bind(&DetachToOwnWindowTwoFingersDragStep2, 2019 this, gfx::Point(5 + tab_0_center.x(), 2020 1 + tab_0_center.y() 2021 + GetDetachY(tab_strip))), 2022 base::TimeDelta::FromMilliseconds(60))); 2023 // Continue dragging, first with one finger, then with two fingers. 2024 QuitWhenNotDragging(); 2025 2026 // There should now be another browser. 2027 ASSERT_EQ(2u, native_browser_list->size()); 2028 Browser* new_browser = native_browser_list->get(1); 2029 ASSERT_TRUE(new_browser->window()->IsActive()); 2030 // The sequence of drags should successfully move the browser window. 2031 bounds += gfx::Vector2d(5 - 2, 1 + 1 + GetDetachY(tab_strip)); 2032 EXPECT_EQ(bounds.ToString(), 2033 new_browser->window()->GetNativeWindow()->bounds().ToString()); 2034} 2035 2036// Subclass of DetachToBrowserTabDragControllerTest that runs tests with 2037// docked windows enabled and disabled. 2038class DetachToDockedTabDragControllerTest 2039 : public DetachToBrowserTabDragControllerTest { 2040 public: 2041 DetachToDockedTabDragControllerTest() {} 2042 virtual ~DetachToDockedTabDragControllerTest() {} 2043 2044 private: 2045 DISALLOW_COPY_AND_ASSIGN(DetachToDockedTabDragControllerTest); 2046}; 2047 2048namespace { 2049 2050void DetachToDockedWindowNextStep( 2051 DetachToDockedTabDragControllerTest* test, 2052 const gfx::Point& target_point, 2053 int iteration) { 2054 ASSERT_EQ(2u, test->native_browser_list->size()); 2055 Browser* new_browser = test->native_browser_list->get(1); 2056 ASSERT_TRUE(new_browser->window()->IsActive()); 2057 2058 if (!iteration) { 2059 ASSERT_TRUE(test->ReleaseInput()); 2060 return; 2061 } 2062 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 2063 target_point.x(), target_point.y(), 2064 base::Bind(&DetachToDockedWindowNextStep, 2065 test, 2066 gfx::Point(target_point.x(), 1 + target_point.y()), 2067 iteration - 1))); 2068} 2069 2070} // namespace 2071 2072// Drags from browser to separate window, docks that window and releases mouse. 2073IN_PROC_BROWSER_TEST_P(DetachToDockedTabDragControllerTest, 2074 DetachToDockedWindowFromMaximizedWindow) { 2075 if (!TabDragController::ShouldDetachIntoNewBrowser()) { 2076 VLOG(1) 2077 << "Skipping DetachToDockedWindowFromMaximizedWindow on this platform."; 2078 return; 2079 } 2080 2081 // Maximize the initial browser window. 2082 browser()->window()->Maximize(); 2083 ASSERT_TRUE(browser()->window()->IsMaximized()); 2084 2085 // Add another tab. 2086 AddTabAndResetBrowser(browser()); 2087 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 2088 2089 // Move to the first tab and drag it enough so that it detaches. 2090 gfx::Point tab_0_center( 2091 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2092 ASSERT_TRUE(PressInput(tab_0_center)); 2093 2094 // The following matches kMovesBeforeAdjust in snap_sizer.cc 2095 const int kNumIterations = 25 * 5 + 10; 2096 ASSERT_TRUE(DragInputToNotifyWhenDone( 2097 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 2098 base::Bind(&DetachToDockedWindowNextStep, this, 2099 gfx::Point(0, tab_0_center.y() + GetDetachY(tab_strip)), 2100 kNumIterations))); 2101 // Continue dragging enough times to go through snapping sequence and dock 2102 // the window. 2103 QuitWhenNotDragging(); 2104 // Should no longer be dragging. 2105 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 2106 ASSERT_FALSE(TabDragController::IsActive()); 2107 2108 // There should now be another browser. 2109 ASSERT_EQ(2u, native_browser_list->size()); 2110 Browser* new_browser = native_browser_list->get(1); 2111 ASSERT_TRUE(new_browser->window()->IsActive()); 2112 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 2113 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 2114 2115 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 2116 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 2117 2118 // The bounds of the initial window should not have changed. 2119 EXPECT_TRUE(browser()->window()->IsMaximized()); 2120 2121 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 2122 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 2123 // After this both windows should still be manageable. 2124 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 2125 EXPECT_TRUE(IsWindowPositionManaged( 2126 new_browser->window()->GetNativeWindow())); 2127 2128 // The new window should be docked and not maximized if docking is allowed. 2129 ash::wm::WindowState* window_state = 2130 ash::wm::GetWindowState(new_browser->window()->GetNativeWindow()); 2131 if (docked_windows_enabled()) { 2132 EXPECT_FALSE(new_browser->window()->IsMaximized()); 2133 EXPECT_TRUE(window_state->IsDocked()); 2134 } else { 2135 EXPECT_TRUE(new_browser->window()->IsMaximized()); 2136 EXPECT_FALSE(window_state->IsDocked()); 2137 } 2138} 2139 2140 2141#endif 2142 2143#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 2144INSTANTIATE_TEST_CASE_P(TabDragging, 2145 DetachToBrowserInSeparateDisplayTabDragControllerTest, 2146 ::testing::Values("mouse", "touch")); 2147INSTANTIATE_TEST_CASE_P(TabDragging, 2148 DifferentDeviceScaleFactorDisplayTabDragControllerTest, 2149 ::testing::Values("mouse")); 2150INSTANTIATE_TEST_CASE_P(TabDragging, 2151 DetachToBrowserTabDragControllerTest, 2152 ::testing::Values("mouse", "touch")); 2153INSTANTIATE_TEST_CASE_P(TabDragging, 2154 DetachToDockedTabDragControllerTest, 2155 ::testing::Values("mouse", "mouse docked")); 2156INSTANTIATE_TEST_CASE_P(TabDragging, 2157 DetachToBrowserTabDragControllerTestTouch, 2158 ::testing::Values("touch", "touch docked")); 2159#else 2160INSTANTIATE_TEST_CASE_P(TabDragging, 2161 DetachToBrowserTabDragControllerTest, 2162 ::testing::Values("mouse")); 2163#endif 2164