1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" 6 7 #include "apps/shell_window.h" 8 #include "apps/shell_window_registry.h" 9 #include "apps/ui/native_app_window.h" 10 #include "ash/ash_switches.h" 11 #include "ash/display/display_controller.h" 12 #include "ash/launcher/launcher.h" 13 #include "ash/shelf/shelf_button.h" 14 #include "ash/shelf/shelf_model.h" 15 #include "ash/shelf/shelf_util.h" 16 #include "ash/shelf/shelf_view.h" 17 #include "ash/shell.h" 18 #include "ash/test/app_list_controller_test_api.h" 19 #include "ash/test/launcher_test_api.h" 20 #include "ash/test/shelf_view_test_api.h" 21 #include "ash/test/shell_test_api.h" 22 #include "ash/wm/window_state.h" 23 #include "ash/wm/window_util.h" 24 #include "base/strings/stringprintf.h" 25 #include "base/strings/utf_string_conversions.h" 26 #include "chrome/browser/apps/app_browsertest_util.h" 27 #include "chrome/browser/automation/automation_util.h" 28 #include "chrome/browser/chrome_notification_types.h" 29 #include "chrome/browser/extensions/extension_apitest.h" 30 #include "chrome/browser/extensions/extension_browsertest.h" 31 #include "chrome/browser/extensions/extension_function_test_utils.h" 32 #include "chrome/browser/extensions/extension_service.h" 33 #include "chrome/browser/extensions/extension_system.h" 34 #include "chrome/browser/extensions/extension_test_message_listener.h" 35 #include "chrome/browser/profiles/profile.h" 36 #include "chrome/browser/ui/app_list/app_list_service.h" 37 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h" 38 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" 39 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" 40 #include "chrome/browser/ui/browser.h" 41 #include "chrome/browser/ui/browser_commands.h" 42 #include "chrome/browser/ui/browser_finder.h" 43 #include "chrome/browser/ui/browser_list.h" 44 #include "chrome/browser/ui/browser_window.h" 45 #include "chrome/browser/ui/extensions/application_launch.h" 46 #include "chrome/browser/ui/host_desktop.h" 47 #include "chrome/browser/ui/tabs/tab_strip_model.h" 48 #include "chrome/common/chrome_switches.h" 49 #include "chrome/test/base/ui_test_utils.h" 50 #include "content/public/browser/notification_service.h" 51 #include "content/public/browser/notification_source.h" 52 #include "content/public/browser/web_contents.h" 53 #include "content/public/test/browser_test_utils.h" 54 #include "extensions/common/constants.h" 55 #include "extensions/common/switches.h" 56 #include "testing/gtest/include/gtest/gtest.h" 57 #include "ui/app_list/views/apps_grid_view.h" 58 #include "ui/aura/client/aura_constants.h" 59 #include "ui/aura/test/event_generator.h" 60 #include "ui/aura/window.h" 61 #include "ui/events/event.h" 62 63 using apps::ShellWindow; 64 using extensions::Extension; 65 using content::WebContents; 66 67 namespace { 68 69 class TestEvent : public ui::Event { 70 public: 71 explicit TestEvent(ui::EventType type) 72 : ui::Event(type, base::TimeDelta(), 0) { 73 } 74 virtual ~TestEvent() { 75 } 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(TestEvent); 79 }; 80 81 class TestShellWindowRegistryObserver 82 : public apps::ShellWindowRegistry::Observer { 83 public: 84 explicit TestShellWindowRegistryObserver(Profile* profile) 85 : profile_(profile), 86 icon_updates_(0) { 87 apps::ShellWindowRegistry::Get(profile_)->AddObserver(this); 88 } 89 90 virtual ~TestShellWindowRegistryObserver() { 91 apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this); 92 } 93 94 // Overridden from ShellWindowRegistry::Observer: 95 virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {} 96 97 virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE { 98 ++icon_updates_; 99 } 100 101 virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {} 102 103 int icon_updates() { return icon_updates_; } 104 105 private: 106 Profile* profile_; 107 int icon_updates_; 108 109 DISALLOW_COPY_AND_ASSIGN(TestShellWindowRegistryObserver); 110 }; 111 112 } // namespace 113 114 class LauncherPlatformAppBrowserTest 115 : public extensions::PlatformAppBrowserTest { 116 protected: 117 LauncherPlatformAppBrowserTest() : launcher_(NULL), controller_(NULL) { 118 } 119 120 virtual ~LauncherPlatformAppBrowserTest() {} 121 122 virtual void RunTestOnMainThreadLoop() OVERRIDE { 123 launcher_ = ash::Launcher::ForPrimaryDisplay(); 124 controller_ = ChromeLauncherController::instance(); 125 return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop(); 126 } 127 128 ash::ShelfModel* shelf_model() { 129 return ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model(); 130 } 131 132 ash::LauncherID CreateAppShortcutLauncherItem(const std::string& name) { 133 return controller_->CreateAppShortcutLauncherItem( 134 name, controller_->model()->item_count()); 135 } 136 137 const ash::LauncherItem& GetLastLauncherItem() { 138 // Unless there are any panels, the item at index [count - 1] will be 139 // the desired item. 140 return shelf_model()->items()[shelf_model()->item_count() - 1]; 141 } 142 143 const ash::LauncherItem& GetLastLauncherPanelItem() { 144 // Panels show up on the right side of the launcher, so the desired item 145 // will be the last one. 146 return shelf_model()->items()[shelf_model()->item_count() - 1]; 147 } 148 149 LauncherItemController* GetItemController(ash::LauncherID id) { 150 return controller_->id_to_item_controller_map_[id]; 151 } 152 153 // Returns the number of menu items, ignoring separators. 154 int GetNumApplicationMenuItems(const ash::LauncherItem& item) { 155 const int event_flags = 0; 156 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel( 157 controller_->GetApplicationList(item, event_flags))); 158 int num_items = 0; 159 for (int i = 0; i < menu->GetItemCount(); ++i) { 160 if (menu->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) 161 ++num_items; 162 } 163 return num_items; 164 } 165 166 // Activate the launcher item with the given |id|. 167 void ActivateLauncherItem(int id) { 168 launcher_->ActivateLauncherItem(id); 169 } 170 171 ash::Launcher* launcher_; 172 ChromeLauncherController* controller_; 173 174 private: 175 176 DISALLOW_COPY_AND_ASSIGN(LauncherPlatformAppBrowserTest); 177 }; 178 179 enum RipOffCommand { 180 // Drag the item off the shelf and let the mouse go. 181 RIP_OFF_ITEM, 182 // Drag the item off the shelf, move the mouse back and then let go. 183 RIP_OFF_ITEM_AND_RETURN, 184 // Drag the item off the shelf and then issue a cancel command. 185 RIP_OFF_ITEM_AND_CANCEL, 186 // Drag the item off the shelf and do not release the mouse. 187 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE, 188 }; 189 190 class LauncherAppBrowserTest : public ExtensionBrowserTest { 191 protected: 192 LauncherAppBrowserTest() : launcher_(NULL), model_(NULL), controller_(NULL) { 193 } 194 195 virtual ~LauncherAppBrowserTest() {} 196 197 virtual void RunTestOnMainThreadLoop() OVERRIDE { 198 launcher_ = ash::Launcher::ForPrimaryDisplay(); 199 model_ = ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model(); 200 controller_ = ChromeLauncherController::instance(); 201 return ExtensionBrowserTest::RunTestOnMainThreadLoop(); 202 } 203 204 size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) { 205 LauncherItemController* item_controller = 206 controller_->GetBrowserShortcutLauncherItemController(); 207 int items = item_controller->GetApplicationList( 208 show_all_tabs ? ui::EF_SHIFT_DOWN : 0).size(); 209 // If we have at least one item, we have also a title which we remove here. 210 return items ? (items - 1) : 0; 211 } 212 213 const Extension* LoadAndLaunchExtension( 214 const char* name, 215 extensions::LaunchContainer container, 216 WindowOpenDisposition disposition) { 217 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name))); 218 219 ExtensionService* service = extensions::ExtensionSystem::Get( 220 profile())->extension_service(); 221 const Extension* extension = 222 service->GetExtensionById(last_loaded_extension_id(), false); 223 EXPECT_TRUE(extension); 224 225 OpenApplication(AppLaunchParams(profile(), 226 extension, 227 container, 228 disposition)); 229 return extension; 230 } 231 232 ash::LauncherID CreateShortcut(const char* name) { 233 ExtensionService* service = extensions::ExtensionSystem::Get( 234 profile())->extension_service(); 235 LoadExtension(test_data_dir_.AppendASCII(name)); 236 237 // First get app_id. 238 const Extension* extension = 239 service->GetExtensionById(last_loaded_extension_id(), false); 240 const std::string app_id = extension->id(); 241 242 // Then create a shortcut. 243 int item_count = model_->item_count(); 244 ash::LauncherID shortcut_id = controller_->CreateAppShortcutLauncherItem( 245 app_id, 246 item_count); 247 controller_->PersistPinnedState(); 248 EXPECT_EQ(++item_count, model_->item_count()); 249 const ash::LauncherItem& item = *model_->ItemByID(shortcut_id); 250 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 251 return item.id; 252 } 253 254 void RemoveShortcut(ash::LauncherID id) { 255 controller_->Unpin(id); 256 } 257 258 // Activate the launcher item with the given |id|. 259 void ActivateLauncherItem(int id) { 260 launcher_->ActivateLauncherItem(id); 261 } 262 263 ash::LauncherID PinFakeApp(const std::string& name) { 264 return controller_->CreateAppShortcutLauncherItem( 265 name, model_->item_count()); 266 } 267 268 // Get the index of an item which has the given type. 269 int GetIndexOfShelfItemType(ash::LauncherItemType type) { 270 return model_->GetItemIndexForType(type); 271 } 272 273 // Try to rip off |item_index|. 274 void RipOffItemIndex(int index, 275 aura::test::EventGenerator* generator, 276 ash::test::ShelfViewTestAPI* test, 277 RipOffCommand command) { 278 ash::internal::ShelfButton* button = test->GetButton(index); 279 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint(); 280 gfx::Point rip_off_point(start_point.x(), 0); 281 generator->MoveMouseTo(start_point.x(), start_point.y()); 282 base::MessageLoop::current()->RunUntilIdle(); 283 generator->PressLeftButton(); 284 base::MessageLoop::current()->RunUntilIdle(); 285 generator->MoveMouseTo(rip_off_point.x(), rip_off_point.y()); 286 base::MessageLoop::current()->RunUntilIdle(); 287 test->RunMessageLoopUntilAnimationsDone(); 288 if (command == RIP_OFF_ITEM_AND_RETURN) { 289 generator->MoveMouseTo(start_point.x(), start_point.y()); 290 base::MessageLoop::current()->RunUntilIdle(); 291 test->RunMessageLoopUntilAnimationsDone(); 292 } else if (command == RIP_OFF_ITEM_AND_CANCEL) { 293 // This triggers an internal cancel. Using VKEY_ESCAPE was too unreliable. 294 button->OnMouseCaptureLost(); 295 } 296 if (command != RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE) { 297 generator->ReleaseLeftButton(); 298 base::MessageLoop::current()->RunUntilIdle(); 299 test->RunMessageLoopUntilAnimationsDone(); 300 } 301 } 302 303 ash::Launcher* launcher_; 304 ash::ShelfModel* model_; 305 ChromeLauncherController* controller_; 306 307 private: 308 309 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTest); 310 }; 311 312 class LauncherAppBrowserTestNoDefaultBrowser : public LauncherAppBrowserTest { 313 protected: 314 LauncherAppBrowserTestNoDefaultBrowser() {} 315 virtual ~LauncherAppBrowserTestNoDefaultBrowser() {} 316 317 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 318 LauncherAppBrowserTest::SetUpCommandLine(command_line); 319 command_line->AppendSwitch(switches::kNoStartupWindow); 320 } 321 322 private: 323 324 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTestNoDefaultBrowser); 325 }; 326 327 // Since the default for minimizing on click might change, I added both classes 328 // to either get the minimize on click or not. 329 class LauncherAppBrowserNoMinimizeOnClick 330 : public LauncherPlatformAppBrowserTest { 331 protected: 332 LauncherAppBrowserNoMinimizeOnClick() {} 333 virtual ~LauncherAppBrowserNoMinimizeOnClick() {} 334 335 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 336 LauncherPlatformAppBrowserTest::SetUpCommandLine(command_line); 337 command_line->AppendSwitch( 338 switches::kDisableMinimizeOnSecondLauncherItemClick); 339 } 340 341 private: 342 343 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserNoMinimizeOnClick); 344 }; 345 346 typedef LauncherPlatformAppBrowserTest LauncherAppBrowserMinimizeOnClick; 347 348 // Test that we can launch a platform app and get a running item. 349 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) { 350 int item_count = shelf_model()->item_count(); 351 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 352 ShellWindow* window = CreateShellWindow(extension); 353 ++item_count; 354 ASSERT_EQ(item_count, shelf_model()->item_count()); 355 const ash::LauncherItem& item = GetLastLauncherItem(); 356 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); 357 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 358 CloseShellWindow(window); 359 --item_count; 360 EXPECT_EQ(item_count, shelf_model()->item_count()); 361 } 362 363 // Test that we can launch a platform app that already has a shortcut. 364 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) { 365 int item_count = shelf_model()->item_count(); 366 367 // First get app_id. 368 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 369 const std::string app_id = extension->id(); 370 371 // Then create a shortcut. 372 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); 373 ++item_count; 374 ASSERT_EQ(item_count, shelf_model()->item_count()); 375 ash::LauncherItem item = *shelf_model()->ItemByID(shortcut_id); 376 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 377 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 378 379 // Open a window. Confirm the item is now running. 380 ShellWindow* window = CreateShellWindow(extension); 381 ash::wm::ActivateWindow(window->GetNativeWindow()); 382 ASSERT_EQ(item_count, shelf_model()->item_count()); 383 item = *shelf_model()->ItemByID(shortcut_id); 384 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 385 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 386 387 // Then close it, make sure there's still an item. 388 CloseShellWindow(window); 389 ASSERT_EQ(item_count, shelf_model()->item_count()); 390 item = *shelf_model()->ItemByID(shortcut_id); 391 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 392 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 393 } 394 395 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) { 396 // Run. 397 int item_count = shelf_model()->item_count(); 398 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 399 ShellWindow* window = CreateShellWindow(extension); 400 ++item_count; 401 ASSERT_EQ(item_count, shelf_model()->item_count()); 402 const ash::LauncherItem& item1 = GetLastLauncherItem(); 403 ash::LauncherID id = item1.id; 404 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 405 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 406 407 // Create a shortcut. The app item should be after it. 408 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); 409 ++item_count; 410 ASSERT_EQ(item_count, shelf_model()->item_count()); 411 EXPECT_LT(shelf_model()->ItemIndexByID(foo_id), 412 shelf_model()->ItemIndexByID(id)); 413 414 // Pin the app. The item should remain. 415 controller_->Pin(id); 416 ASSERT_EQ(item_count, shelf_model()->item_count()); 417 const ash::LauncherItem& item2 = *shelf_model()->ItemByID(id); 418 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type); 419 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 420 421 // New shortcuts should come after the item. 422 ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar"); 423 ++item_count; 424 ASSERT_EQ(item_count, shelf_model()->item_count()); 425 EXPECT_LT(shelf_model()->ItemIndexByID(id), 426 shelf_model()->ItemIndexByID(bar_id)); 427 428 // Then close it, make sure the item remains. 429 CloseShellWindow(window); 430 ASSERT_EQ(item_count, shelf_model()->item_count()); 431 } 432 433 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) { 434 int item_count = shelf_model()->item_count(); 435 436 // First get app_id. 437 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 438 const std::string app_id = extension->id(); 439 440 // Then create a shortcut. 441 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); 442 ++item_count; 443 ASSERT_EQ(item_count, shelf_model()->item_count()); 444 ash::LauncherItem item = *shelf_model()->ItemByID(shortcut_id); 445 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 446 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 447 448 // Create a second shortcut. This will be needed to force the first one to 449 // move once it gets unpinned. 450 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); 451 ++item_count; 452 ASSERT_EQ(item_count, shelf_model()->item_count()); 453 EXPECT_LT(shelf_model()->ItemIndexByID(shortcut_id), 454 shelf_model()->ItemIndexByID(foo_id)); 455 456 // Open a window. Confirm the item is now running. 457 ShellWindow* window = CreateShellWindow(extension); 458 ash::wm::ActivateWindow(window->GetNativeWindow()); 459 ASSERT_EQ(item_count, shelf_model()->item_count()); 460 item = *shelf_model()->ItemByID(shortcut_id); 461 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 462 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 463 464 // Unpin the app. The item should remain. 465 controller_->Unpin(shortcut_id); 466 ASSERT_EQ(item_count, shelf_model()->item_count()); 467 item = *shelf_model()->ItemByID(shortcut_id); 468 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); 469 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 470 // The item should have moved after the other shortcuts. 471 EXPECT_GT(shelf_model()->ItemIndexByID(shortcut_id), 472 shelf_model()->ItemIndexByID(foo_id)); 473 474 // Then close it, make sure the item's gone. 475 CloseShellWindow(window); 476 --item_count; 477 ASSERT_EQ(item_count, shelf_model()->item_count()); 478 } 479 480 // Test that we can launch a platform app with more than one window. 481 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) { 482 int item_count = shelf_model()->item_count(); 483 484 // First run app. 485 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 486 ShellWindow* window1 = CreateShellWindow(extension); 487 ++item_count; 488 ASSERT_EQ(item_count, shelf_model()->item_count()); 489 const ash::LauncherItem& item1 = GetLastLauncherItem(); 490 ash::LauncherID item_id = item1.id; 491 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 492 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 493 EXPECT_EQ(2, GetNumApplicationMenuItems(item1)); // Title + 1 window 494 495 // Add second window. 496 ShellWindow* window2 = CreateShellWindow(extension); 497 // Confirm item stays. 498 ASSERT_EQ(item_count, shelf_model()->item_count()); 499 const ash::LauncherItem& item2 = *shelf_model()->ItemByID(item_id); 500 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 501 EXPECT_EQ(3, GetNumApplicationMenuItems(item2)); // Title + 2 windows 502 503 // Close second window. 504 CloseShellWindow(window2); 505 // Confirm item stays. 506 ASSERT_EQ(item_count, shelf_model()->item_count()); 507 const ash::LauncherItem& item3 = *shelf_model()->ItemByID(item_id); 508 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status); 509 EXPECT_EQ(2, GetNumApplicationMenuItems(item3)); // Title + 1 window 510 511 // Close first window. 512 CloseShellWindow(window1); 513 // Confirm item is removed. 514 --item_count; 515 ASSERT_EQ(item_count, shelf_model()->item_count()); 516 } 517 518 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) { 519 int item_count = shelf_model()->item_count(); 520 521 // First run app. 522 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 523 ShellWindow* window1 = CreateShellWindow(extension1); 524 ++item_count; 525 ASSERT_EQ(item_count, shelf_model()->item_count()); 526 const ash::LauncherItem& item1 = GetLastLauncherItem(); 527 ash::LauncherID item_id1 = item1.id; 528 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 529 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 530 531 // Then run second app. 532 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); 533 ShellWindow* window2 = CreateShellWindow(extension2); 534 ++item_count; 535 ASSERT_EQ(item_count, shelf_model()->item_count()); 536 const ash::LauncherItem& item2 = GetLastLauncherItem(); 537 ash::LauncherID item_id2 = item2.id; 538 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); 539 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 540 541 EXPECT_NE(item_id1, item_id2); 542 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 543 544 // Close second app. 545 CloseShellWindow(window2); 546 --item_count; 547 ASSERT_EQ(item_count, shelf_model()->item_count()); 548 // First app should be active again. 549 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 550 551 // Close first app. 552 CloseShellWindow(window1); 553 --item_count; 554 ASSERT_EQ(item_count, shelf_model()->item_count()); 555 } 556 557 // Confirm that app windows can be reactivated by clicking their icons and that 558 // the correct activation order is maintained. 559 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowActivation) { 560 int item_count = shelf_model()->item_count(); 561 562 // First run app. 563 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 564 ShellWindow* window1 = CreateShellWindow(extension1); 565 ++item_count; 566 ASSERT_EQ(item_count, shelf_model()->item_count()); 567 const ash::LauncherItem& item1 = GetLastLauncherItem(); 568 ash::LauncherID item_id1 = item1.id; 569 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 570 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 571 572 // Then run second app. 573 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); 574 ShellWindow* window2 = CreateShellWindow(extension2); 575 ++item_count; 576 ASSERT_EQ(item_count, shelf_model()->item_count()); 577 const ash::LauncherItem& item2 = GetLastLauncherItem(); 578 ash::LauncherID item_id2 = item2.id; 579 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); 580 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 581 582 EXPECT_NE(item_id1, item_id2); 583 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 584 585 // Activate first one. 586 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1)); 587 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 588 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id2)->status); 589 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 590 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 591 592 // Activate second one. 593 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id2)); 594 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 595 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id2)->status); 596 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 597 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 598 599 // Add window for app1. This will activate it. 600 ShellWindow* window1b = CreateShellWindow(extension1); 601 ash::wm::ActivateWindow(window1b->GetNativeWindow()); 602 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 603 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 604 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 605 606 // Activate launcher item for app1, this will activate the first app window. 607 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1)); 608 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 609 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 610 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1)); 611 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 612 613 // Activate the second app again 614 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id2)); 615 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 616 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 617 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 618 619 // Activate the first app again 620 ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1)); 621 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 622 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 623 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 624 625 // Close second app. 626 CloseShellWindow(window2); 627 --item_count; 628 EXPECT_EQ(item_count, shelf_model()->item_count()); 629 // First app should be active again. 630 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 631 632 // Close first app. 633 CloseShellWindow(window1b); 634 CloseShellWindow(window1); 635 --item_count; 636 EXPECT_EQ(item_count, shelf_model()->item_count()); 637 } 638 639 // Confirm that Click behavior for app windows is correnct. 640 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserNoMinimizeOnClick, 641 AppClickBehavior) { 642 // Launch a platform app and create a window for it. 643 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 644 ShellWindow* window1 = CreateShellWindow(extension1); 645 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 646 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 647 // Confirm that a controller item was created and is the correct state. 648 const ash::LauncherItem& item1 = GetLastLauncherItem(); 649 LauncherItemController* item1_controller = GetItemController(item1.id); 650 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 651 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 652 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); 653 // Clicking the item should have no effect. 654 TestEvent click_event(ui::ET_MOUSE_PRESSED); 655 item1_controller->ItemSelected(click_event); 656 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 657 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 658 // Minimize the window and confirm that the controller item is updated. 659 window1->GetBaseWindow()->Minimize(); 660 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); 661 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); 662 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 663 // Clicking the item should activate the window. 664 item1_controller->ItemSelected(click_event); 665 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 666 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 667 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 668 // Maximizing a window should preserve state after minimize + click. 669 window1->GetBaseWindow()->Maximize(); 670 window1->GetBaseWindow()->Minimize(); 671 item1_controller->ItemSelected(click_event); 672 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 673 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 674 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); 675 } 676 677 // Confirm the minimizing click behavior for apps. 678 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserMinimizeOnClick, 679 PackagedAppClickBehaviorInMinimizeMode) { 680 // Launch one platform app and create a window for it. 681 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 682 ShellWindow* window1 = CreateShellWindow(extension1); 683 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 684 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 685 686 // Confirm that a controller item was created and is the correct state. 687 const ash::LauncherItem& item1 = GetLastLauncherItem(); 688 LauncherItemController* item1_controller = GetItemController(item1.id); 689 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 690 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 691 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); 692 // Since it is already active, clicking it should minimize. 693 TestEvent click_event(ui::ET_MOUSE_PRESSED); 694 item1_controller->ItemSelected(click_event); 695 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); 696 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); 697 EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized()); 698 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 699 // Clicking the item again should activate the window again. 700 item1_controller->ItemSelected(click_event); 701 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 702 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 703 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 704 // Maximizing a window should preserve state after minimize + click. 705 window1->GetBaseWindow()->Maximize(); 706 window1->GetBaseWindow()->Minimize(); 707 item1_controller->ItemSelected(click_event); 708 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 709 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 710 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); 711 window1->GetBaseWindow()->Restore(); 712 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 713 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 714 EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized()); 715 716 // Creating a second window of the same type should change the behavior so 717 // that a click does not change the activation state. 718 ShellWindow* window1a = CreateShellWindow(extension1); 719 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 720 EXPECT_TRUE(window1a->GetBaseWindow()->IsActive()); 721 // The first click does nothing. 722 item1_controller->ItemSelected(click_event); 723 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 724 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 725 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 726 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); 727 // The second neither. 728 item1_controller->ItemSelected(click_event); 729 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 730 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 731 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 732 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); 733 } 734 735 // Confirm that click behavior for app panels is correct. 736 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) { 737 // Enable experimental APIs to allow panel creation. 738 CommandLine::ForCurrentProcess()->AppendSwitch( 739 extensions::switches::kEnableExperimentalExtensionApis); 740 // Launch a platform app and create a panel window for it. 741 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 742 ShellWindow::CreateParams params; 743 params.window_type = ShellWindow::WINDOW_TYPE_PANEL; 744 params.focused = false; 745 ShellWindow* panel = CreateShellWindowFromParams(extension1, params); 746 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 747 // Panels should not be active by default. 748 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); 749 // Confirm that a controller item was created and is the correct state. 750 const ash::LauncherItem& item1 = GetLastLauncherPanelItem(); 751 LauncherItemController* item1_controller = GetItemController(item1.id); 752 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type); 753 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 754 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item1_controller->type()); 755 // Click the item and confirm that the panel is activated. 756 TestEvent click_event(ui::ET_MOUSE_PRESSED); 757 item1_controller->ItemSelected(click_event); 758 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 759 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 760 // Click the item again and confirm that the panel is minimized. 761 item1_controller->ItemSelected(click_event); 762 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized()); 763 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 764 // Click the item again and confirm that the panel is activated. 765 item1_controller->ItemSelected(click_event); 766 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 767 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 768 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 769 } 770 771 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) { 772 int item_count = shelf_model()->item_count(); 773 774 // First run app. 775 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 776 CreateShellWindow(extension1); 777 ++item_count; 778 ASSERT_EQ(item_count, shelf_model()->item_count()); 779 const ash::LauncherItem& item1 = GetLastLauncherItem(); 780 ash::LauncherID item_id1 = item1.id; 781 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 782 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 783 784 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow()); 785 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 786 } 787 788 // Test that opening an app sets the correct icon 789 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, SetIcon) { 790 TestShellWindowRegistryObserver test_observer(browser()->profile()); 791 792 // Enable experimental APIs to allow panel creation. 793 CommandLine::ForCurrentProcess()->AppendSwitch( 794 extensions::switches::kEnableExperimentalExtensionApis); 795 796 int base_launcher_item_count = shelf_model()->item_count(); 797 ExtensionTestMessageListener launched_listener("Launched", false); 798 ExtensionTestMessageListener completed_listener("Completed", false); 799 LoadAndLaunchPlatformApp("app_icon"); 800 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); 801 ASSERT_TRUE(completed_listener.WaitUntilSatisfied()); 802 803 // Now wait until the WebContent has decoded the icons and chrome has 804 // processed it. This needs to be in a loop since the renderer runs in a 805 // different process. 806 while (test_observer.icon_updates() < 3) { 807 base::RunLoop run_loop; 808 run_loop.RunUntilIdle(); 809 } 810 811 // This test creates one shell window and one panel window. 812 int launcher_item_count = shelf_model()->item_count(); 813 ASSERT_EQ(base_launcher_item_count + 2, launcher_item_count); 814 // The Panel will be the last item, the app second-to-last. 815 const ash::LauncherItem& app_item = 816 shelf_model()->items()[launcher_item_count - 2]; 817 const ash::LauncherItem& panel_item = 818 shelf_model()->items()[launcher_item_count - 1]; 819 const LauncherItemController* app_item_controller = 820 GetItemController(app_item.id); 821 const LauncherItemController* panel_item_controller = 822 GetItemController(panel_item.id); 823 // Icons for Apps are set by the ShellWindowLauncherController, so 824 // image_set_by_controller() should be set. 825 EXPECT_TRUE(app_item_controller->image_set_by_controller()); 826 EXPECT_TRUE(panel_item_controller->image_set_by_controller()); 827 // Ensure icon heights are correct (see test.js in app_icon/ test directory) 828 EXPECT_EQ(48, app_item.image.height()); 829 EXPECT_EQ(64, panel_item.image.height()); 830 } 831 832 // Test that we can launch an app with a shortcut. 833 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchPinned) { 834 TabStripModel* tab_strip = browser()->tab_strip_model(); 835 int tab_count = tab_strip->count(); 836 ash::LauncherID shortcut_id = CreateShortcut("app1"); 837 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 838 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 839 EXPECT_EQ(++tab_count, tab_strip->count()); 840 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 841 WebContents* tab = tab_strip->GetActiveWebContents(); 842 content::WebContentsDestroyedWatcher destroyed_watcher(tab); 843 browser()->tab_strip_model()->CloseSelectedTabs(); 844 destroyed_watcher.Wait(); 845 EXPECT_EQ(--tab_count, tab_strip->count()); 846 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 847 } 848 849 // Launch the app first and then create the shortcut. 850 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchUnpinned) { 851 TabStripModel* tab_strip = browser()->tab_strip_model(); 852 int tab_count = tab_strip->count(); 853 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 854 NEW_FOREGROUND_TAB); 855 EXPECT_EQ(++tab_count, tab_strip->count()); 856 ash::LauncherID shortcut_id = CreateShortcut("app1"); 857 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 858 WebContents* tab = tab_strip->GetActiveWebContents(); 859 content::WebContentsDestroyedWatcher destroyed_watcher(tab); 860 browser()->tab_strip_model()->CloseSelectedTabs(); 861 destroyed_watcher.Wait(); 862 EXPECT_EQ(--tab_count, tab_strip->count()); 863 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 864 } 865 866 // Launches an app in the background and then tries to open it. This is test for 867 // a crash we had. 868 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchInBackground) { 869 TabStripModel* tab_strip = browser()->tab_strip_model(); 870 int tab_count = tab_strip->count(); 871 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 872 NEW_BACKGROUND_TAB); 873 EXPECT_EQ(++tab_count, tab_strip->count()); 874 ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id(), 875 ash::LAUNCH_FROM_UNKNOWN, 876 0); 877 } 878 879 // Confirm that clicking a icon for an app running in one of 2 maxmized windows 880 // activates the right window. 881 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchMaximized) { 882 aura::Window* window1 = browser()->window()->GetNativeWindow(); 883 ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1); 884 window1_state->Maximize(); 885 content::WindowedNotificationObserver open_observer( 886 chrome::NOTIFICATION_BROWSER_WINDOW_READY, 887 content::NotificationService::AllSources()); 888 chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH); 889 open_observer.Wait(); 890 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr(); 891 aura::Window* window2 = browser2->window()->GetNativeWindow(); 892 TabStripModel* tab_strip = browser2->tab_strip_model(); 893 int tab_count = tab_strip->count(); 894 ash::wm::GetWindowState(window2)->Maximize(); 895 896 ash::LauncherID shortcut_id = CreateShortcut("app1"); 897 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 898 EXPECT_EQ(++tab_count, tab_strip->count()); 899 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 900 901 window1->Show(); 902 window1_state->Activate(); 903 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); 904 905 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 906 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 907 } 908 909 // Activating the same app multiple times should launch only a single copy. 910 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateApp) { 911 TabStripModel* tab_strip = browser()->tab_strip_model(); 912 int tab_count = tab_strip->count(); 913 const Extension* extension = 914 LoadExtension(test_data_dir_.AppendASCII("app1")); 915 916 ChromeLauncherController::instance()->ActivateApp(extension->id(), 917 ash::LAUNCH_FROM_UNKNOWN, 918 0); 919 EXPECT_EQ(++tab_count, tab_strip->count()); 920 ChromeLauncherController::instance()->ActivateApp(extension->id(), 921 ash::LAUNCH_FROM_UNKNOWN, 922 0); 923 EXPECT_EQ(tab_count, tab_strip->count()); 924 } 925 926 // Launching the same app multiple times should launch a copy for each call. 927 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchApp) { 928 TabStripModel* tab_strip = browser()->tab_strip_model(); 929 int tab_count = tab_strip->count(); 930 const Extension* extension = 931 LoadExtension(test_data_dir_.AppendASCII("app1")); 932 933 ChromeLauncherController::instance()->LaunchApp(extension->id(), 934 ash::LAUNCH_FROM_UNKNOWN, 935 0); 936 EXPECT_EQ(++tab_count, tab_strip->count()); 937 ChromeLauncherController::instance()->LaunchApp(extension->id(), 938 ash::LAUNCH_FROM_UNKNOWN, 939 0); 940 EXPECT_EQ(++tab_count, tab_strip->count()); 941 } 942 943 // Launch 2 apps and toggle which is active. 944 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleApps) { 945 int item_count = model_->item_count(); 946 TabStripModel* tab_strip = browser()->tab_strip_model(); 947 int tab_count = tab_strip->count(); 948 ash::LauncherID shortcut1 = CreateShortcut("app1"); 949 EXPECT_EQ(++item_count, model_->item_count()); 950 ash::LauncherID shortcut2 = CreateShortcut("app2"); 951 EXPECT_EQ(++item_count, model_->item_count()); 952 953 // Launch first app. 954 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); 955 EXPECT_EQ(++tab_count, tab_strip->count()); 956 WebContents* tab1 = tab_strip->GetActiveWebContents(); 957 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 958 959 // Launch second app. 960 ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); 961 EXPECT_EQ(++tab_count, tab_strip->count()); 962 WebContents* tab2 = tab_strip->GetActiveWebContents(); 963 ASSERT_NE(tab1, tab2); 964 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 965 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 966 967 // Reactivate first app. 968 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); 969 EXPECT_EQ(tab_count, tab_strip->count()); 970 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); 971 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 972 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); 973 974 // Open second tab for second app. This should activate it. 975 ui_test_utils::NavigateToURLWithDisposition( 976 browser(), 977 GURL("http://www.example.com/path3/foo.html"), 978 NEW_FOREGROUND_TAB, 979 0); 980 EXPECT_EQ(++tab_count, tab_strip->count()); 981 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 982 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 983 984 // Reactivate first app. 985 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); 986 EXPECT_EQ(tab_count, tab_strip->count()); 987 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); 988 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 989 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); 990 991 // And second again. This time the second tab should become active. 992 ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); 993 EXPECT_EQ(tab_count, tab_strip->count()); 994 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2); 995 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 996 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 997 } 998 999 // Confirm that a page can be navigated from and to while maintaining the 1000 // correct running state. 1001 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, Navigation) { 1002 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1003 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1004 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1005 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1006 1007 // Navigate away. 1008 ui_test_utils::NavigateToURL( 1009 browser(), GURL("http://www.example.com/path0/bar.html")); 1010 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1011 1012 // Navigate back. 1013 ui_test_utils::NavigateToURL( 1014 browser(), GURL("http://www.example.com/path1/foo.html")); 1015 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1016 } 1017 1018 // Confirm that a tab can be moved between browsers while maintaining the 1019 // correct running state. 1020 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, TabDragAndDrop) { 1021 TabStripModel* tab_strip_model1 = browser()->tab_strip_model(); 1022 EXPECT_EQ(1, tab_strip_model1->count()); 1023 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1024 EXPECT_TRUE(browser_index >= 0); 1025 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1026 1027 // Create a shortcut for app1. 1028 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1029 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1030 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1031 1032 // Activate app1 and check its item status. 1033 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1034 EXPECT_EQ(2, tab_strip_model1->count()); 1035 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1036 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1037 1038 // Create a new browser with blank tab. 1039 Browser* browser2 = CreateBrowser(profile()); 1040 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1041 TabStripModel* tab_strip_model2 = browser2->tab_strip_model(); 1042 EXPECT_EQ(1, tab_strip_model2->count()); 1043 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1044 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); 1045 1046 // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an 1047 // active tab at index 1 to |tab_strip_model2|. 1048 content::WebContents* detached_tab = tab_strip_model1->DetachWebContentsAt(1); 1049 tab_strip_model2->InsertWebContentsAt(1, 1050 detached_tab, 1051 TabStripModel::ADD_ACTIVE); 1052 EXPECT_EQ(1, tab_strip_model1->count()); 1053 EXPECT_EQ(2, tab_strip_model2->count()); 1054 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1055 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1056 1057 tab_strip_model1->CloseAllTabs(); 1058 tab_strip_model2->CloseAllTabs(); 1059 } 1060 1061 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleOwnedTabs) { 1062 TabStripModel* tab_strip = browser()->tab_strip_model(); 1063 int tab_count = tab_strip->count(); 1064 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1065 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1066 EXPECT_EQ(++tab_count, tab_strip->count()); 1067 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1068 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1069 1070 // Create new tab owned by app. 1071 ui_test_utils::NavigateToURLWithDisposition( 1072 browser(), 1073 GURL("http://www.example.com/path2/bar.html"), 1074 NEW_FOREGROUND_TAB, 1075 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1076 EXPECT_EQ(++tab_count, tab_strip->count()); 1077 // Confirm app is still active. 1078 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1079 1080 // Create new tab not owned by app. 1081 ui_test_utils::NavigateToURLWithDisposition( 1082 browser(), 1083 GURL("http://www.example.com/path3/foo.html"), 1084 NEW_FOREGROUND_TAB, 1085 0); 1086 EXPECT_EQ(++tab_count, tab_strip->count()); 1087 // No longer active. 1088 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1089 1090 // Activating app makes first tab active again. 1091 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1092 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1093 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); 1094 } 1095 1096 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilter) { 1097 TabStripModel* tab_strip = browser()->tab_strip_model(); 1098 int tab_count = tab_strip->count(); 1099 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1100 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1101 EXPECT_EQ(++tab_count, tab_strip->count()); 1102 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1103 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1104 1105 controller_->SetRefocusURLPatternForTest( 1106 shortcut_id, GURL("http://www.example.com/path1/*")); 1107 // Create new tab owned by app. 1108 ui_test_utils::NavigateToURLWithDisposition( 1109 browser(), 1110 GURL("http://www.example.com/path2/bar.html"), 1111 NEW_FOREGROUND_TAB, 1112 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1113 EXPECT_EQ(++tab_count, tab_strip->count()); 1114 // Confirm app is still active. 1115 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1116 1117 // Create new tab not owned by app. 1118 ui_test_utils::NavigateToURLWithDisposition( 1119 browser(), 1120 GURL("http://www.example.com/path3/foo.html"), 1121 NEW_FOREGROUND_TAB, 1122 0); 1123 EXPECT_EQ(++tab_count, tab_strip->count()); 1124 // No longer active. 1125 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1126 1127 // Activating app makes first tab active again, because second tab isn't 1128 // in its refocus url path. 1129 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1130 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1131 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); 1132 } 1133 1134 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilterLaunch) { 1135 TabStripModel* tab_strip = browser()->tab_strip_model(); 1136 int tab_count = tab_strip->count(); 1137 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1138 controller_->SetRefocusURLPatternForTest( 1139 shortcut_id, GURL("http://www.example.com/path1/*")); 1140 1141 // Create new tab. 1142 ui_test_utils::NavigateToURLWithDisposition( 1143 browser(), 1144 GURL("http://www.example2.com/path2/bar.html"), 1145 NEW_FOREGROUND_TAB, 1146 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1147 EXPECT_EQ(++tab_count, tab_strip->count()); 1148 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1149 // Confirm app is not active. 1150 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1151 1152 // Activating app should launch new tab, because second tab isn't 1153 // in its refocus url path. 1154 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); 1155 EXPECT_EQ(++tab_count, tab_strip->count()); 1156 WebContents* second_tab = tab_strip->GetActiveWebContents(); 1157 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1158 EXPECT_NE(first_tab, second_tab); 1159 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); 1160 } 1161 1162 // Check the launcher activation state for applications and browser. 1163 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivationStateCheck) { 1164 TabStripModel* tab_strip = browser()->tab_strip_model(); 1165 // Get the browser item index 1166 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1167 EXPECT_TRUE(browser_index >= 0); 1168 1169 // Even though we are just comming up, the browser should be active. 1170 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1171 1172 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1173 controller_->SetRefocusURLPatternForTest( 1174 shortcut_id, GURL("http://www.example.com/path1/*")); 1175 1176 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1177 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1178 1179 // Create new tab which would be the running app. 1180 ui_test_utils::NavigateToURLWithDisposition( 1181 browser(), 1182 GURL("http://www.example.com/path1/bar.html"), 1183 NEW_FOREGROUND_TAB, 1184 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1185 1186 // There should never be two items active at the same time. 1187 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1188 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1189 1190 tab_strip->ActivateTabAt(0, false); 1191 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1192 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1193 1194 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); 1195 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1196 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1197 1198 ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow()); 1199 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1200 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1201 } 1202 1203 // Check that the launcher activation state for a V1 application stays closed 1204 // even after an asynchronous browser event comes in after the tab got 1205 // destroyed. 1206 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AsyncActivationStateCheck) { 1207 TabStripModel* tab_strip = browser()->tab_strip_model(); 1208 1209 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1210 controller_->SetRefocusURLPatternForTest( 1211 shortcut_id, GURL("http://www.example.com/path1/*")); 1212 1213 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1214 1215 // Create new tab which would be the running app. 1216 ui_test_utils::NavigateToURLWithDisposition( 1217 browser(), 1218 GURL("http://www.example.com/path1/bar.html"), 1219 NEW_FOREGROUND_TAB, 1220 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1221 1222 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1223 // To address the issue of crbug.com/174050, the tab we are about to close 1224 // has to be active. 1225 tab_strip->ActivateTabAt(1, false); 1226 EXPECT_EQ(1, tab_strip->active_index()); 1227 1228 // Close the web contents. 1229 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); 1230 // The status should now be set to closed. 1231 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1232 } 1233 1234 // Checks that a windowed application does not add an item to the browser list. 1235 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser, 1236 WindowedAppDoesNotAddToBrowser) { 1237 // Get the number of items in the browser menu. 1238 size_t items = NumberOfDetectedLauncherBrowsers(false); 1239 size_t running_browser = chrome::GetTotalBrowserCount(); 1240 EXPECT_EQ(0u, items); 1241 EXPECT_EQ(0u, running_browser); 1242 1243 LoadAndLaunchExtension( 1244 "app1", extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW); 1245 1246 // No new browser should get detected, even though one more is running. 1247 EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false)); 1248 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); 1249 1250 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1251 1252 // A new browser should get detected and one more should be running. 1253 EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u); 1254 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); 1255 } 1256 1257 // Checks the functionality to enumerate all browsers vs. all tabs. 1258 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser, 1259 EnumerateALlBrowsersAndTabs) { 1260 // Create at least one browser. 1261 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1262 size_t browsers = NumberOfDetectedLauncherBrowsers(false); 1263 size_t tabs = NumberOfDetectedLauncherBrowsers(true); 1264 1265 // Create a second browser. 1266 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1267 1268 EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false)); 1269 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); 1270 1271 // Create only a tab. 1272 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 1273 NEW_FOREGROUND_TAB); 1274 1275 EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false)); 1276 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); 1277 } 1278 1279 // Check that the keyboard activation of a launcher item tabs properly through 1280 // the items at hand. 1281 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AltNumberTabsTabbing) { 1282 TabStripModel* tab_strip = browser()->tab_strip_model(); 1283 1284 ash::LauncherID shortcut_id = CreateShortcut("app"); 1285 controller_->SetRefocusURLPatternForTest( 1286 shortcut_id, GURL("http://www.example.com/path/*")); 1287 std::string url = "http://www.example.com/path/bla"; 1288 1289 int shortcut_index = model_->ItemIndexByID(shortcut_id); 1290 1291 // Create an application handled browser tab. 1292 ui_test_utils::NavigateToURLWithDisposition( 1293 browser(), 1294 GURL(url), 1295 NEW_FOREGROUND_TAB, 1296 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1297 1298 content::WebContents* content1 = tab_strip->GetActiveWebContents(); 1299 1300 // Create some other browser tab. 1301 ui_test_utils::NavigateToURLWithDisposition( 1302 browser(), 1303 GURL("http://www.test.com"), 1304 NEW_FOREGROUND_TAB, 1305 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1306 content::WebContents* content1a = tab_strip->GetActiveWebContents(); 1307 1308 // Make sure that the active tab is now our handled tab. 1309 EXPECT_NE(content1a, content1); 1310 1311 // The active tab should still be the unnamed tab. Then we switch and reach 1312 // the first app and stay there. 1313 EXPECT_EQ(content1a, tab_strip->GetActiveWebContents()); 1314 ActivateLauncherItem(shortcut_index); 1315 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); 1316 ActivateLauncherItem(shortcut_index); 1317 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); 1318 1319 ui_test_utils::NavigateToURLWithDisposition( 1320 browser(), 1321 GURL(url), 1322 NEW_FOREGROUND_TAB, 1323 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1324 content::WebContents* content2 = tab_strip->GetActiveWebContents(); 1325 1326 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); 1327 ActivateLauncherItem(shortcut_index); 1328 EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents()); 1329 ActivateLauncherItem(shortcut_index); 1330 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); 1331 } 1332 1333 // Check that the keyboard activation of a launcher item tabs properly through 1334 // the items at hand. 1335 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, 1336 AltNumberAppsTabbing) { 1337 // First run app. 1338 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); 1339 ui::BaseWindow* window1 = CreateShellWindow(extension1)->GetBaseWindow(); 1340 const ash::LauncherItem& item1 = GetLastLauncherItem(); 1341 ash::LauncherID app_id = item1.id; 1342 int app_index = shelf_model()->ItemIndexByID(app_id); 1343 1344 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 1345 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 1346 1347 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); 1348 ui::BaseWindow* window2 = CreateShellWindow(extension2)->GetBaseWindow(); 1349 1350 // By now the browser should be active. Issue Alt keystrokes several times to 1351 // see that we stay on that application. 1352 EXPECT_TRUE(window2->IsActive()); 1353 ActivateLauncherItem(app_index); 1354 EXPECT_TRUE(window1->IsActive()); 1355 ActivateLauncherItem(app_index); 1356 EXPECT_TRUE(window1->IsActive()); 1357 1358 ui::BaseWindow* window1a = CreateShellWindow(extension1)->GetBaseWindow(); 1359 1360 EXPECT_TRUE(window1a->IsActive()); 1361 EXPECT_FALSE(window1->IsActive()); 1362 ActivateLauncherItem(app_index); 1363 EXPECT_TRUE(window1->IsActive()); 1364 ActivateLauncherItem(app_index); 1365 EXPECT_TRUE(window1a->IsActive()); 1366 } 1367 1368 // Test that we can launch a platform app panel and get a running item. 1369 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) { 1370 int item_count = shelf_model()->item_count(); 1371 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 1372 ShellWindow::CreateParams params; 1373 params.window_type = ShellWindow::WINDOW_TYPE_PANEL; 1374 params.focused = false; 1375 ShellWindow* window = CreateShellWindowFromParams(extension, params); 1376 ++item_count; 1377 ASSERT_EQ(item_count, shelf_model()->item_count()); 1378 const ash::LauncherItem& item = GetLastLauncherPanelItem(); 1379 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); 1380 // Opening a panel does not activate it. 1381 EXPECT_EQ(ash::STATUS_RUNNING, item.status); 1382 CloseShellWindow(window); 1383 --item_count; 1384 EXPECT_EQ(item_count, shelf_model()->item_count()); 1385 } 1386 1387 // Test attention states of windows. 1388 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) { 1389 const Extension* extension = LoadAndLaunchPlatformApp("launch"); 1390 ShellWindow::CreateParams params; 1391 params.window_type = ShellWindow::WINDOW_TYPE_PANEL; 1392 params.focused = false; 1393 ShellWindow* panel = CreateShellWindowFromParams(extension, params); 1394 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 1395 // Panels should not be active by default. 1396 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); 1397 // Confirm that a controller item was created and is the correct state. 1398 const ash::LauncherItem& item = GetLastLauncherPanelItem(); 1399 LauncherItemController* item_controller = GetItemController(item.id); 1400 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); 1401 EXPECT_EQ(ash::STATUS_RUNNING, item.status); 1402 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item_controller->type()); 1403 1404 // App windows should go to attention state. 1405 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); 1406 EXPECT_EQ(ash::STATUS_ATTENTION, item.status); 1407 1408 // Click the item and confirm that the panel is activated. 1409 TestEvent click_event(ui::ET_MOUSE_PRESSED); 1410 item_controller->ItemSelected(click_event); 1411 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 1412 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 1413 1414 // Active windows don't show attention. 1415 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); 1416 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 1417 } 1418 1419 // Checks that the browser Alt "tabbing" is properly done. 1420 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser, 1421 AltNumberBrowserTabbing) { 1422 // Get the number of items in the browser menu. 1423 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); 1424 // The first activation should create a browser at index 1 (App List @ 0). 1425 launcher_->ActivateLauncherItem(1); 1426 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1427 // A second activation should not create a new instance. 1428 launcher_->ActivateLauncherItem(1); 1429 Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()); 1430 EXPECT_TRUE(browser1); 1431 aura::Window* window1 = browser1->window()->GetNativeWindow(); 1432 Browser* browser2 = CreateBrowser(profile()); 1433 aura::Window* window2 = browser2->window()->GetNativeWindow(); 1434 1435 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1436 EXPECT_NE(window1, window2); 1437 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1438 1439 // Activate multiple times the switcher to see that the windows get activated. 1440 launcher_->ActivateLauncherItem(1); 1441 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1442 launcher_->ActivateLauncherItem(1); 1443 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1444 1445 // Create a third browser - make sure that we do not toggle simply between 1446 // two windows. 1447 Browser* browser3 = CreateBrowser(profile()); 1448 aura::Window* window3 = browser3->window()->GetNativeWindow(); 1449 1450 EXPECT_EQ(3u, chrome::GetTotalBrowserCount()); 1451 EXPECT_NE(window1, window3); 1452 EXPECT_NE(window2, window3); 1453 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); 1454 1455 launcher_->ActivateLauncherItem(1); 1456 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1457 launcher_->ActivateLauncherItem(1); 1458 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1459 launcher_->ActivateLauncherItem(1); 1460 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); 1461 launcher_->ActivateLauncherItem(1); 1462 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1463 1464 // Create anther app and make sure that none of our browsers is active. 1465 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1466 EXPECT_NE(window1, ash::wm::GetActiveWindow()); 1467 EXPECT_NE(window2, ash::wm::GetActiveWindow()); 1468 1469 // After activation our browser should be active again. 1470 launcher_->ActivateLauncherItem(1); 1471 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1472 } 1473 1474 // Checks that after a session restore, we do not start applications on an 1475 // activation. 1476 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateAfterSessionRestore) { 1477 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1478 1479 // Create a known application. 1480 ash::LauncherID shortcut_id = CreateShortcut("app1"); 1481 1482 // Create a new browser - without activating it - and load an "app" into it. 1483 Browser::CreateParams params = 1484 Browser::CreateParams(profile(), chrome::GetActiveDesktop()); 1485 params.initial_show_state = ui::SHOW_STATE_INACTIVE; 1486 Browser* browser2 = new Browser(params); 1487 controller_->SetRefocusURLPatternForTest( 1488 shortcut_id, GURL("http://www.example.com/path/*")); 1489 std::string url = "http://www.example.com/path/bla"; 1490 ui_test_utils::NavigateToURLWithDisposition( 1491 browser2, 1492 GURL(url), 1493 NEW_FOREGROUND_TAB, 1494 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1495 1496 // Remember the number of tabs for each browser. 1497 TabStripModel* tab_strip = browser()->tab_strip_model(); 1498 int tab_count1 = tab_strip->count(); 1499 TabStripModel* tab_strip2 = browser2->tab_strip_model(); 1500 int tab_count2 = tab_strip2->count(); 1501 1502 // Check that we have two browsers and the inactive browser remained inactive. 1503 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1504 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), 1505 browser()); 1506 // Check that the LRU browser list does only contain the original browser. 1507 BrowserList* ash_browser_list = 1508 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 1509 BrowserList::const_reverse_iterator it = 1510 ash_browser_list->begin_last_active(); 1511 EXPECT_EQ(*it, browser()); 1512 ++it; 1513 EXPECT_EQ(it, ash_browser_list->end_last_active()); 1514 1515 // Now request to either activate an existing app or create a new one. 1516 LauncherItemController* item_controller = 1517 controller_->GetLauncherItemController(shortcut_id); 1518 item_controller->ItemSelected(ui::KeyEvent(ui::ET_KEY_RELEASED, 1519 ui::VKEY_RETURN, 1520 0, 1521 false)); 1522 1523 // Check that we have set focus on the existing application and nothing new 1524 // was created. 1525 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1526 EXPECT_EQ(tab_count1, tab_strip->count()); 1527 EXPECT_EQ(tab_count2, tab_strip2->count()); 1528 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), 1529 browser2); 1530 } 1531 1532 // Do various drag and drop interaction tests between the application list and 1533 // the launcher. 1534 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragAndDrop) { 1535 // Get a number of interfaces we need. 1536 aura::test::EventGenerator generator( 1537 ash::Shell::GetPrimaryRootWindow(), gfx::Point()); 1538 ash::test::ShelfViewTestAPI test( 1539 ash::test::LauncherTestAPI(launcher_).shelf_view()); 1540 AppListService* service = AppListService::Get(chrome::GetActiveDesktop()); 1541 1542 // There should be two items in our launcher by this time. 1543 EXPECT_EQ(2, model_->item_count()); 1544 EXPECT_FALSE(service->IsAppListVisible()); 1545 1546 // Open the app list menu and check that the drag and drop host was set. 1547 gfx::Rect app_list_bounds = 1548 test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen(); 1549 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), 1550 app_list_bounds.CenterPoint().y()); 1551 base::MessageLoop::current()->RunUntilIdle(); 1552 generator.ClickLeftButton(); 1553 1554 EXPECT_TRUE(service->IsAppListVisible()); 1555 app_list::AppsGridView* grid_view = 1556 ash::test::AppListControllerTestApi(ash::Shell::GetInstance()). 1557 GetRootGridView(); 1558 ASSERT_TRUE(grid_view); 1559 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test()); 1560 1561 // There should be 2 items in our application list. 1562 const views::ViewModel* vm_grid = grid_view->view_model_for_test(); 1563 EXPECT_EQ(2, vm_grid->view_size()); 1564 1565 // Test #1: Drag an app list which does not exist yet item into the 1566 // launcher. Keeping it dragged, see that a new item gets created. Continuing 1567 // to drag it out should remove it again. 1568 1569 // Get over item #1 of the application list and press the mouse button. 1570 views::View* item1 = vm_grid->view_at(1); 1571 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen(); 1572 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1573 bounds_grid_1.CenterPoint().y()); 1574 base::MessageLoop::current()->RunUntilIdle(); 1575 generator.PressLeftButton(); 1576 1577 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1578 1579 // Drag the item into the launcher and check that a new item gets created. 1580 const views::ViewModel* vm_launcher = 1581 test.shelf_view()->view_model_for_test(); 1582 views::View* launcher1 = vm_launcher->view_at(1); 1583 gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen(); 1584 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), 1585 bounds_launcher_1.CenterPoint().y()); 1586 base::MessageLoop::current()->RunUntilIdle(); 1587 1588 // Check that a new item got created. 1589 EXPECT_EQ(3, model_->item_count()); 1590 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1591 1592 // Move it where the item originally was and check that it disappears again. 1593 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1594 bounds_grid_1.CenterPoint().y()); 1595 base::MessageLoop::current()->RunUntilIdle(); 1596 EXPECT_EQ(2, model_->item_count()); 1597 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1598 1599 // Dropping it should keep the launcher as it originally was. 1600 generator.ReleaseLeftButton(); 1601 base::MessageLoop::current()->RunUntilIdle(); 1602 EXPECT_EQ(2, model_->item_count()); 1603 // There are a few animations which need finishing before we can continue. 1604 test.RunMessageLoopUntilAnimationsDone(); 1605 // Move the mouse outside of the launcher. 1606 generator.MoveMouseTo(0, 0); 1607 1608 // Test #2: Check that the unknown item dropped into the launcher will 1609 // create a new item. 1610 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1611 bounds_grid_1.CenterPoint().y()); 1612 generator.PressLeftButton(); 1613 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), 1614 bounds_launcher_1.CenterPoint().y()); 1615 base::MessageLoop::current()->RunUntilIdle(); 1616 EXPECT_EQ(3, model_->item_count()); 1617 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1618 generator.ReleaseLeftButton(); 1619 base::MessageLoop::current()->RunUntilIdle(); 1620 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1621 EXPECT_EQ(3, model_->item_count()); // It should be still there. 1622 test.RunMessageLoopUntilAnimationsDone(); 1623 1624 // Test #3: Check that the now known item dropped into the launcher will 1625 // not create a new item. 1626 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1627 bounds_grid_1.CenterPoint().y()); 1628 generator.PressLeftButton(); 1629 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), 1630 bounds_launcher_1.CenterPoint().y()); 1631 base::MessageLoop::current()->RunUntilIdle(); 1632 EXPECT_EQ(3, model_->item_count()); // No new item got added. 1633 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1634 generator.ReleaseLeftButton(); 1635 base::MessageLoop::current()->RunUntilIdle(); 1636 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1637 EXPECT_EQ(3, model_->item_count()); // And it remains that way. 1638 1639 // Test #4: Check that by pressing ESC the operation gets cancelled. 1640 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1641 bounds_grid_1.CenterPoint().y()); 1642 generator.PressLeftButton(); 1643 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), 1644 bounds_launcher_1.CenterPoint().y()); 1645 base::MessageLoop::current()->RunUntilIdle(); 1646 // Issue an ESC and see that the operation gets cancelled. 1647 generator.PressKey(ui::VKEY_ESCAPE, 0); 1648 generator.ReleaseKey(ui::VKEY_ESCAPE, 0); 1649 EXPECT_FALSE(grid_view->dragging()); 1650 EXPECT_FALSE(grid_view->has_dragged_view()); 1651 generator.ReleaseLeftButton(); 1652 } 1653 1654 #if !defined(OS_WIN) 1655 // Used to test drag & drop an item between app list and shelf with multi 1656 // display environment. 1657 class LauncherAppBrowserTestWithMultiMonitor 1658 : public LauncherAppBrowserTestNoDefaultBrowser { 1659 protected: 1660 LauncherAppBrowserTestWithMultiMonitor() {} 1661 virtual ~LauncherAppBrowserTestWithMultiMonitor() {} 1662 1663 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1664 LauncherAppBrowserTestNoDefaultBrowser::SetUpCommandLine(command_line); 1665 command_line->AppendSwitchASCII("ash-host-window-bounds", 1666 "800x600,801+0-800x600"); 1667 } 1668 1669 private: 1670 1671 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTestWithMultiMonitor); 1672 }; 1673 1674 // Do basic drag and drop interaction tests between the application list and 1675 // the launcher in the secondary monitor. 1676 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestWithMultiMonitor, 1677 BasicDragAndDrop) { 1678 // Get a number of interfaces we need. 1679 DCHECK_EQ(ash::Shell::GetAllRootWindows().size(), 2U); 1680 aura::Window* secondary_root_window = ash::Shell::GetAllRootWindows()[1]; 1681 ash::Launcher* secondary_launcher = 1682 ash::Launcher::ForWindow(secondary_root_window); 1683 1684 aura::test::EventGenerator generator(secondary_root_window, gfx::Point()); 1685 ash::test::ShelfViewTestAPI test( 1686 ash::test::LauncherTestAPI(secondary_launcher).shelf_view()); 1687 AppListService* service = AppListService::Get(chrome::GetActiveDesktop()); 1688 1689 // There should be two items in our launcher by this time. 1690 EXPECT_EQ(2, model_->item_count()); 1691 EXPECT_FALSE(service->IsAppListVisible()); 1692 1693 // Open the app list menu and check that the drag and drop host was set. 1694 gfx::Rect app_list_bounds = 1695 test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen(); 1696 gfx::Display display = 1697 ash::Shell::GetScreen()->GetDisplayNearestWindow(secondary_root_window); 1698 const gfx::Point& origin = display.bounds().origin(); 1699 app_list_bounds.Offset(-origin.x(), -origin.y()); 1700 1701 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), 1702 app_list_bounds.CenterPoint().y()); 1703 base::MessageLoop::current()->RunUntilIdle(); 1704 generator.ClickLeftButton(); 1705 1706 EXPECT_TRUE(service->IsAppListVisible()); 1707 app_list::AppsGridView* grid_view = 1708 ash::test::AppListControllerTestApi(ash::Shell::GetInstance()). 1709 GetRootGridView(); 1710 ASSERT_TRUE(grid_view); 1711 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test()); 1712 1713 // There should be 2 items in our application list. 1714 const views::ViewModel* vm_grid = grid_view->view_model_for_test(); 1715 EXPECT_EQ(2, vm_grid->view_size()); 1716 1717 // Drag an app list item which does not exist yet in the launcher. 1718 // Keeping it dragged, see that a new item gets created. 1719 // Continuing to drag it out should remove it again. 1720 1721 // Get over item #1 of the application list and press the mouse button. 1722 views::View* item1 = vm_grid->view_at(1); 1723 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen(); 1724 bounds_grid_1.Offset(-origin.x(), -origin.y()); 1725 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1726 bounds_grid_1.CenterPoint().y()); 1727 base::MessageLoop::current()->RunUntilIdle(); 1728 generator.PressLeftButton(); 1729 1730 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1731 1732 // Drag the item into the launcher and check that a new item gets created. 1733 const views::ViewModel* vm_launcher = 1734 test.shelf_view()->view_model_for_test(); 1735 views::View* launcher1 = vm_launcher->view_at(1); 1736 gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen(); 1737 bounds_launcher_1.Offset(-origin.x(), -origin.y()); 1738 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), 1739 bounds_launcher_1.CenterPoint().y()); 1740 base::MessageLoop::current()->RunUntilIdle(); 1741 1742 // Check that a new item got created. 1743 EXPECT_EQ(3, model_->item_count()); 1744 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1745 1746 // Move it where the item originally was and check that it disappears again. 1747 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1748 bounds_grid_1.CenterPoint().y()); 1749 base::MessageLoop::current()->RunUntilIdle(); 1750 EXPECT_EQ(2, model_->item_count()); 1751 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); 1752 1753 // Dropping it should keep the launcher as it originally was. 1754 generator.ReleaseLeftButton(); 1755 base::MessageLoop::current()->RunUntilIdle(); 1756 EXPECT_EQ(2, model_->item_count()); 1757 } 1758 #endif 1759 1760 // Do tests for removal of items from the shelf by dragging. 1761 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragOffShelf) { 1762 aura::test::EventGenerator generator( 1763 ash::Shell::GetPrimaryRootWindow(), gfx::Point()); 1764 ash::test::ShelfViewTestAPI test( 1765 ash::test::LauncherTestAPI(launcher_).shelf_view()); 1766 test.SetAnimationDuration(1); // Speed up animations for test. 1767 // Create a known application and check that we have 3 items in the launcher. 1768 CreateShortcut("app1"); 1769 test.RunMessageLoopUntilAnimationsDone(); 1770 EXPECT_EQ(3, model_->item_count()); 1771 1772 // Test #1: Ripping out the browser item should not change anything. 1773 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1774 EXPECT_LE(0, browser_index); 1775 RipOffItemIndex(browser_index, &generator, &test, RIP_OFF_ITEM); 1776 // => It should not have been removed and the location should be unchanged. 1777 EXPECT_EQ(3, model_->item_count()); 1778 EXPECT_EQ(browser_index, 1779 GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT)); 1780 // Make sure that the hide state has been unset after the snap back animation 1781 // finished. 1782 ash::internal::ShelfButton* button = test.GetButton(browser_index); 1783 EXPECT_FALSE(button->state() & ash::internal::ShelfButton::STATE_HIDDEN); 1784 1785 // Test #2: Ripping out the application and canceling the operation should 1786 // not change anything. 1787 int app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT); 1788 EXPECT_LE(0, app_index); 1789 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_CANCEL); 1790 // => It should not have been removed and the location should be unchanged. 1791 ASSERT_EQ(3, model_->item_count()); 1792 EXPECT_EQ(app_index, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT)); 1793 1794 // Test #3: Ripping out the application and moving it back in should not 1795 // change anything. 1796 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_RETURN); 1797 // => It should not have been removed and the location should be unchanged. 1798 ASSERT_EQ(3, model_->item_count()); 1799 // Through the operation the index might have changed. 1800 app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT); 1801 1802 // Test #4: Ripping out the application should remove the item. 1803 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); 1804 // => It should not have been removed and the location should be unchanged. 1805 EXPECT_EQ(2, model_->item_count()); 1806 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT)); 1807 1808 // Test #5: Uninstalling an application while it is being ripped off should 1809 // not crash. 1810 ash::LauncherID app_id = CreateShortcut("app2"); 1811 test.RunMessageLoopUntilAnimationsDone(); 1812 int app2_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT); 1813 EXPECT_EQ(3, model_->item_count()); // And it remains that way. 1814 RipOffItemIndex(app2_index, 1815 &generator, 1816 &test, 1817 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE); 1818 RemoveShortcut(app_id); 1819 test.RunMessageLoopUntilAnimationsDone(); 1820 EXPECT_EQ(2, model_->item_count()); // The item should now be gone. 1821 generator.ReleaseLeftButton(); 1822 base::MessageLoop::current()->RunUntilIdle(); 1823 EXPECT_EQ(2, model_->item_count()); // And it remains that way. 1824 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT)); 1825 1826 // Test #6: Ripping out the application when the overflow button exists. 1827 // After ripping out, overflow button should be removed. 1828 int items_added = 0; 1829 EXPECT_FALSE(test.IsOverflowButtonVisible()); 1830 1831 // Create fake app shortcuts until overflow button is created. 1832 while (!test.IsOverflowButtonVisible()) { 1833 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); 1834 PinFakeApp(fake_app_id); 1835 test.RunMessageLoopUntilAnimationsDone(); 1836 1837 ++items_added; 1838 ASSERT_LT(items_added, 10000); 1839 } 1840 // Make one more item after creating a overflow button. 1841 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); 1842 PinFakeApp(fake_app_id); 1843 test.RunMessageLoopUntilAnimationsDone(); 1844 1845 int total_count = model_->item_count(); 1846 app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT); 1847 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); 1848 // When an item is ripped off from the launcher that has overflow button 1849 // (see crbug.com/3050787), it was hidden accidentally and was then 1850 // suppressing any further events. If handled correctly the operation will 1851 // however correctly done and the item will get removed (as well as the 1852 // overflow button). 1853 EXPECT_EQ(total_count - 1, model_->item_count()); 1854 EXPECT_TRUE(test.IsOverflowButtonVisible()); 1855 1856 // Rip off again and the overflow button should has disappeared. 1857 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); 1858 EXPECT_EQ(total_count - 2, model_->item_count()); 1859 EXPECT_FALSE(test.IsOverflowButtonVisible()); 1860 } 1861 1862 // Check that clicking on an app launcher item launches a new browser. 1863 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ClickItem) { 1864 // Get a number of interfaces we need. 1865 aura::test::EventGenerator generator( 1866 ash::Shell::GetPrimaryRootWindow(), gfx::Point()); 1867 ash::test::ShelfViewTestAPI test( 1868 ash::test::LauncherTestAPI(launcher_).shelf_view()); 1869 AppListService* service = AppListService::Get(chrome::GetActiveDesktop()); 1870 // There should be two items in our launcher by this time. 1871 EXPECT_EQ(2, model_->item_count()); 1872 EXPECT_FALSE(service->IsAppListVisible()); 1873 1874 // Open the app list menu and check that the drag and drop host was set. 1875 gfx::Rect app_list_bounds = 1876 test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen(); 1877 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), 1878 app_list_bounds.CenterPoint().y()); 1879 generator.ClickLeftButton(); 1880 base::MessageLoop::current()->RunUntilIdle(); 1881 1882 EXPECT_TRUE(service->IsAppListVisible()); 1883 app_list::AppsGridView* grid_view = 1884 ash::test::AppListControllerTestApi(ash::Shell::GetInstance()). 1885 GetRootGridView(); 1886 ASSERT_TRUE(grid_view); 1887 const views::ViewModel* vm_grid = grid_view->view_model_for_test(); 1888 EXPECT_EQ(2, vm_grid->view_size()); 1889 gfx::Rect bounds_grid_1 = vm_grid->view_at(1)->GetBoundsInScreen(); 1890 // Test now that a click does create a new application tab. 1891 TabStripModel* tab_strip = browser()->tab_strip_model(); 1892 int tab_count = tab_strip->count(); 1893 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), 1894 bounds_grid_1.CenterPoint().y()); 1895 generator.ClickLeftButton(); 1896 base::MessageLoop::current()->RunUntilIdle(); 1897 EXPECT_EQ(tab_count + 1, tab_strip->count()); 1898 } 1899 1900 // Check LauncherItemController of Browser Shortcut functionality. 1901 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser, 1902 BrowserShortcutLauncherItemController) { 1903 LauncherItemController* item_controller = 1904 controller_->GetBrowserShortcutLauncherItemController(); 1905 1906 // Get the number of browsers. 1907 size_t running_browser = chrome::GetTotalBrowserCount(); 1908 EXPECT_EQ(0u, running_browser); 1909 EXPECT_FALSE(item_controller->IsOpen()); 1910 1911 // Activate. This creates new browser 1912 item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN); 1913 // New Window is created. 1914 running_browser = chrome::GetTotalBrowserCount(); 1915 EXPECT_EQ(1u, running_browser); 1916 EXPECT_TRUE(item_controller->IsOpen()); 1917 1918 // Minimize Window. 1919 ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState(); 1920 window_state->Minimize(); 1921 EXPECT_TRUE(window_state->IsMinimized()); 1922 1923 // Activate again. This doesn't create new browser. 1924 // It activates window. 1925 item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN); 1926 running_browser = chrome::GetTotalBrowserCount(); 1927 EXPECT_EQ(1u, running_browser); 1928 EXPECT_TRUE(item_controller->IsOpen()); 1929 EXPECT_FALSE(window_state->IsMinimized()); 1930 } 1931 1932 // Check that GetLauncherIDForWindow() returns |LauncherID| of the active tab. 1933 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MatchingLauncherIDandActiveTab) { 1934 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1935 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 1936 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); 1937 EXPECT_EQ(2, model_->item_count()); 1938 1939 aura::Window* window = browser()->window()->GetNativeWindow(); 1940 1941 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1942 ash::LauncherID browser_id = model_->items()[browser_index].id; 1943 EXPECT_EQ(browser_id, ash::GetLauncherIDForWindow(window)); 1944 1945 ash::LauncherID app_id = CreateShortcut("app1"); 1946 EXPECT_EQ(3, model_->item_count()); 1947 1948 // Creates a new tab for "app1" and checks that GetLauncherIDForWindow() 1949 // returns |LauncherID| of "app1". 1950 ActivateLauncherItem(model_->ItemIndexByID(app_id)); 1951 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 1952 EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); 1953 EXPECT_EQ(app_id, ash::GetLauncherIDForWindow(window)); 1954 1955 // Makes tab at index 0(NTP) as an active tab and checks that 1956 // GetLauncherIDForWindow() returns |LauncherID| of browser shortcut. 1957 browser()->tab_strip_model()->ActivateTabAt(0, false); 1958 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); 1959 EXPECT_EQ(browser_id, ash::GetLauncherIDForWindow(window)); 1960 } 1961 1962 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, OverflowBubble) { 1963 // Make sure to have a browser window 1964 chrome::NewTab(browser()); 1965 1966 // No overflow yet. 1967 EXPECT_FALSE(launcher_->IsShowingOverflowBubble()); 1968 1969 ash::test::ShelfViewTestAPI test( 1970 ash::test::LauncherTestAPI(launcher_).shelf_view()); 1971 1972 int items_added = 0; 1973 while (!test.IsOverflowButtonVisible()) { 1974 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); 1975 PinFakeApp(fake_app_id); 1976 1977 ++items_added; 1978 ASSERT_LT(items_added, 10000); 1979 } 1980 1981 // Now show overflow bubble. 1982 test.ShowOverflowBubble(); 1983 EXPECT_TRUE(launcher_->IsShowingOverflowBubble()); 1984 1985 // Unpin first pinned app and there should be no crash. 1986 controller_->UnpinAppWithID(std::string("fake_app_0")); 1987 1988 test.RunMessageLoopUntilAnimationsDone(); 1989 EXPECT_FALSE(launcher_->IsShowingOverflowBubble()); 1990 } 1991 1992 // Check that a windowed V1 application can navigate away from its domain, but 1993 // still gets detected properly. 1994 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, V1AppNavigation) { 1995 // We assume that the web store is always there (which it apparently is). 1996 controller_->PinAppWithID(extension_misc::kWebStoreAppId); 1997 ash::LauncherID id = controller_->GetLauncherIDForAppID( 1998 extension_misc::kWebStoreAppId); 1999 ASSERT_NE(0, id); 2000 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status); 2001 2002 // Create a windowed application. 2003 AppLaunchParams params( 2004 profile(), 2005 controller_->GetExtensionForAppID(extension_misc::kWebStoreAppId), 2006 0, 2007 chrome::HOST_DESKTOP_TYPE_ASH); 2008 params.container = extensions::LAUNCH_CONTAINER_WINDOW; 2009 OpenApplication(params); 2010 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status); 2011 2012 // Find the browser which holds our app. 2013 Browser* app_browser = NULL; 2014 const BrowserList* ash_browser_list = 2015 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 2016 for (BrowserList::const_reverse_iterator it = 2017 ash_browser_list->begin_last_active(); 2018 it != ash_browser_list->end_last_active() && !app_browser; ++it) { 2019 if ((*it)->is_app()) { 2020 app_browser = *it; 2021 break; 2022 } 2023 } 2024 ASSERT_TRUE(app_browser); 2025 2026 // After navigating away in the app, we should still be active. 2027 ui_test_utils::NavigateToURL(app_browser, 2028 GURL("http://www.foo.com/bar.html")); 2029 // Make sure the navigation was entirely performed. 2030 base::MessageLoop::current()->RunUntilIdle(); 2031 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status); 2032 app_browser->tab_strip_model()->CloseWebContentsAt(0, 2033 TabStripModel::CLOSE_NONE); 2034 // Make sure that the app is really gone. 2035 base::MessageLoop::current()->RunUntilIdle(); 2036 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status); 2037 } 2038