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