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 "ash/ash_switches.h" 8 #include "ash/display/display_controller.h" 9 #include "ash/shelf/shelf.h" 10 #include "ash/shelf/shelf_button.h" 11 #include "ash/shelf/shelf_constants.h" 12 #include "ash/shelf/shelf_model.h" 13 #include "ash/shelf/shelf_util.h" 14 #include "ash/shelf/shelf_view.h" 15 #include "ash/shell.h" 16 #include "ash/test/app_list_controller_test_api.h" 17 #include "ash/test/shelf_test_api.h" 18 #include "ash/test/shelf_view_test_api.h" 19 #include "ash/test/shell_test_api.h" 20 #include "ash/wm/window_state.h" 21 #include "ash/wm/window_util.h" 22 #include "base/strings/stringprintf.h" 23 #include "base/strings/utf_string_conversions.h" 24 #include "chrome/browser/apps/app_browsertest_util.h" 25 #include "chrome/browser/chrome_notification_types.h" 26 #include "chrome/browser/extensions/extension_apitest.h" 27 #include "chrome/browser/extensions/extension_browsertest.h" 28 #include "chrome/browser/extensions/extension_function_test_utils.h" 29 #include "chrome/browser/extensions/extension_service.h" 30 #include "chrome/browser/profiles/profile.h" 31 #include "chrome/browser/ui/app_list/app_list_service.h" 32 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h" 33 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" 34 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" 35 #include "chrome/browser/ui/browser.h" 36 #include "chrome/browser/ui/browser_commands.h" 37 #include "chrome/browser/ui/browser_finder.h" 38 #include "chrome/browser/ui/browser_list.h" 39 #include "chrome/browser/ui/browser_window.h" 40 #include "chrome/browser/ui/chrome_pages.h" 41 #include "chrome/browser/ui/extensions/application_launch.h" 42 #include "chrome/browser/ui/host_desktop.h" 43 #include "chrome/browser/ui/settings_window_manager.h" 44 #include "chrome/browser/ui/tabs/tab_strip_model.h" 45 #include "chrome/common/chrome_switches.h" 46 #include "chrome/test/base/ui_test_utils.h" 47 #include "content/public/browser/notification_service.h" 48 #include "content/public/browser/notification_source.h" 49 #include "content/public/browser/web_contents.h" 50 #include "content/public/test/browser_test_utils.h" 51 #include "extensions/browser/app_window/app_window.h" 52 #include "extensions/browser/app_window/app_window_registry.h" 53 #include "extensions/browser/app_window/native_app_window.h" 54 #include "extensions/browser/extension_system.h" 55 #include "extensions/common/constants.h" 56 #include "extensions/common/switches.h" 57 #include "extensions/test/extension_test_message_listener.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/window.h" 62 #include "ui/events/event.h" 63 #include "ui/events/test/event_generator.h" 64 65 using extensions::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 84 : public extensions::AppWindowRegistry::Observer { 85 public: 86 explicit TestAppWindowRegistryObserver(Profile* profile) 87 : profile_(profile), icon_updates_(0) { 88 extensions::AppWindowRegistry::Get(profile_)->AddObserver(this); 89 } 90 91 virtual ~TestAppWindowRegistryObserver() { 92 extensions::AppWindowRegistry::Get(profile_)->RemoveObserver(this); 93 } 94 95 // Overridden from AppWindowRegistry::Observer: 96 virtual void OnAppWindowIconChanged(AppWindow* app_window) OVERRIDE { 97 ++icon_updates_; 98 } 99 100 int icon_updates() { return icon_updates_; } 101 102 private: 103 Profile* profile_; 104 int icon_updates_; 105 106 DISALLOW_COPY_AND_ASSIGN(TestAppWindowRegistryObserver); 107 }; 108 109 } // namespace 110 111 class LauncherPlatformAppBrowserTest 112 : public extensions::PlatformAppBrowserTest { 113 protected: 114 LauncherPlatformAppBrowserTest() : shelf_(NULL), controller_(NULL) { 115 } 116 117 virtual ~LauncherPlatformAppBrowserTest() {} 118 119 virtual void RunTestOnMainThreadLoop() OVERRIDE { 120 shelf_ = ash::Shelf::ForPrimaryDisplay(); 121 controller_ = ChromeLauncherController::instance(); 122 return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop(); 123 } 124 125 ash::ShelfModel* shelf_model() { 126 return ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model(); 127 } 128 129 ash::ShelfID CreateAppShortcutLauncherItem(const std::string& name) { 130 return controller_->CreateAppShortcutLauncherItem( 131 name, controller_->model()->item_count()); 132 } 133 134 const ash::ShelfItem& GetLastLauncherItem() { 135 // Unless there are any panels, the item at index [count - 1] will be 136 // the desired item. 137 return shelf_model()->items()[shelf_model()->item_count() - 1]; 138 } 139 140 const ash::ShelfItem& GetLastLauncherPanelItem() { 141 // Panels show up on the right side of the shelf, so the desired item 142 // will be the last one. 143 return shelf_model()->items()[shelf_model()->item_count() - 1]; 144 } 145 146 LauncherItemController* GetItemController(ash::ShelfID id) { 147 return controller_->id_to_item_controller_map_[id]; 148 } 149 150 // Returns the number of menu items, ignoring separators. 151 int GetNumApplicationMenuItems(const ash::ShelfItem& item) { 152 const int event_flags = 0; 153 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel( 154 controller_->GetApplicationList(item, event_flags))); 155 int num_items = 0; 156 for (int i = 0; i < menu->GetItemCount(); ++i) { 157 if (menu->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) 158 ++num_items; 159 } 160 return num_items; 161 } 162 163 // Activate the shelf item with the given |id|. 164 void ActivateShelfItem(int id) { 165 shelf_->ActivateShelfItem(id); 166 } 167 168 ash::Shelf* shelf_; 169 ChromeLauncherController* controller_; 170 171 private: 172 173 DISALLOW_COPY_AND_ASSIGN(LauncherPlatformAppBrowserTest); 174 }; 175 176 enum RipOffCommand { 177 // Drag the item off the shelf and let the mouse go. 178 RIP_OFF_ITEM, 179 // Drag the item off the shelf, move the mouse back and then let go. 180 RIP_OFF_ITEM_AND_RETURN, 181 // Drag the item off the shelf and then issue a cancel command. 182 RIP_OFF_ITEM_AND_CANCEL, 183 // Drag the item off the shelf and do not release the mouse. 184 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE, 185 }; 186 187 class ShelfAppBrowserTest : public ExtensionBrowserTest { 188 protected: 189 ShelfAppBrowserTest() : shelf_(NULL), model_(NULL), controller_(NULL) { 190 } 191 192 virtual ~ShelfAppBrowserTest() {} 193 194 virtual void RunTestOnMainThreadLoop() OVERRIDE { 195 shelf_ = ash::Shelf::ForPrimaryDisplay(); 196 model_ = ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model(); 197 controller_ = ChromeLauncherController::instance(); 198 return ExtensionBrowserTest::RunTestOnMainThreadLoop(); 199 } 200 201 size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) { 202 LauncherItemController* item_controller = 203 controller_->GetBrowserShortcutLauncherItemController(); 204 int items = item_controller->GetApplicationList( 205 show_all_tabs ? ui::EF_SHIFT_DOWN : 0).size(); 206 // If we have at least one item, we have also a title which we remove here. 207 return items ? (items - 1) : 0; 208 } 209 210 const Extension* LoadAndLaunchExtension( 211 const char* name, 212 extensions::LaunchContainer container, 213 WindowOpenDisposition disposition) { 214 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name))); 215 216 ExtensionService* service = extensions::ExtensionSystem::Get( 217 profile())->extension_service(); 218 const Extension* extension = 219 service->GetExtensionById(last_loaded_extension_id(), false); 220 EXPECT_TRUE(extension); 221 222 OpenApplication(AppLaunchParams(profile(), 223 extension, 224 container, 225 disposition)); 226 return extension; 227 } 228 229 ash::ShelfID CreateShortcut(const char* name) { 230 ExtensionService* service = extensions::ExtensionSystem::Get( 231 profile())->extension_service(); 232 LoadExtension(test_data_dir_.AppendASCII(name)); 233 234 // First get app_id. 235 const Extension* extension = 236 service->GetExtensionById(last_loaded_extension_id(), false); 237 const std::string app_id = extension->id(); 238 239 // Then create a shortcut. 240 int item_count = model_->item_count(); 241 ash::ShelfID shortcut_id = controller_->CreateAppShortcutLauncherItem( 242 app_id, 243 item_count); 244 controller_->PersistPinnedState(); 245 EXPECT_EQ(++item_count, model_->item_count()); 246 const ash::ShelfItem& item = *model_->ItemByID(shortcut_id); 247 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 248 return item.id; 249 } 250 251 void RemoveShortcut(ash::ShelfID id) { 252 controller_->Unpin(id); 253 } 254 255 // Activate the shelf item with the given |id|. 256 void ActivateShelfItem(int id) { 257 shelf_->ActivateShelfItem(id); 258 } 259 260 ash::ShelfID PinFakeApp(const std::string& name) { 261 return controller_->CreateAppShortcutLauncherItem( 262 name, model_->item_count()); 263 } 264 265 // Get the index of an item which has the given type. 266 int GetIndexOfShelfItemType(ash::ShelfItemType type) { 267 return model_->GetItemIndexForType(type); 268 } 269 270 // Try to rip off |item_index|. 271 void RipOffItemIndex(int index, 272 ui::test::EventGenerator* generator, 273 ash::test::ShelfViewTestAPI* test, 274 RipOffCommand command) { 275 ash::ShelfButton* button = test->GetButton(index); 276 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint(); 277 gfx::Point rip_off_point(start_point.x(), 0); 278 generator->MoveMouseTo(start_point.x(), start_point.y()); 279 base::MessageLoop::current()->RunUntilIdle(); 280 generator->PressLeftButton(); 281 base::MessageLoop::current()->RunUntilIdle(); 282 generator->MoveMouseTo(rip_off_point.x(), rip_off_point.y()); 283 base::MessageLoop::current()->RunUntilIdle(); 284 test->RunMessageLoopUntilAnimationsDone(); 285 if (command == RIP_OFF_ITEM_AND_RETURN) { 286 generator->MoveMouseTo(start_point.x(), start_point.y()); 287 base::MessageLoop::current()->RunUntilIdle(); 288 test->RunMessageLoopUntilAnimationsDone(); 289 } else if (command == RIP_OFF_ITEM_AND_CANCEL) { 290 // This triggers an internal cancel. Using VKEY_ESCAPE was too unreliable. 291 button->OnMouseCaptureLost(); 292 } 293 if (command != RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE) { 294 generator->ReleaseLeftButton(); 295 base::MessageLoop::current()->RunUntilIdle(); 296 test->RunMessageLoopUntilAnimationsDone(); 297 } 298 } 299 300 ash::Shelf* shelf_; 301 ash::ShelfModel* model_; 302 ChromeLauncherController* controller_; 303 304 private: 305 306 DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserTest); 307 }; 308 309 class ShelfAppBrowserTestNoDefaultBrowser : public ShelfAppBrowserTest { 310 protected: 311 ShelfAppBrowserTestNoDefaultBrowser() {} 312 virtual ~ShelfAppBrowserTestNoDefaultBrowser() {} 313 314 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 315 ShelfAppBrowserTest::SetUpCommandLine(command_line); 316 command_line->AppendSwitch(switches::kNoStartupWindow); 317 } 318 319 private: 320 321 DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserTestNoDefaultBrowser); 322 }; 323 324 // Since the default for minimizing on click might change, I added both classes 325 // to either get the minimize on click or not. 326 class ShelfAppBrowserNoMinimizeOnClick : public LauncherPlatformAppBrowserTest { 327 protected: 328 ShelfAppBrowserNoMinimizeOnClick() {} 329 virtual ~ShelfAppBrowserNoMinimizeOnClick() {} 330 331 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 332 LauncherPlatformAppBrowserTest::SetUpCommandLine(command_line); 333 command_line->AppendSwitch( 334 switches::kDisableMinimizeOnSecondLauncherItemClick); 335 } 336 337 private: 338 339 DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserNoMinimizeOnClick); 340 }; 341 342 typedef LauncherPlatformAppBrowserTest ShelfAppBrowserMinimizeOnClick; 343 344 // Test that we can launch a platform app and get a running item. 345 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) { 346 int item_count = shelf_model()->item_count(); 347 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 348 AppWindow* window = CreateAppWindow(extension); 349 ++item_count; 350 ASSERT_EQ(item_count, shelf_model()->item_count()); 351 const ash::ShelfItem& item = GetLastLauncherItem(); 352 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); 353 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 354 CloseAppWindow(window); 355 --item_count; 356 EXPECT_EQ(item_count, shelf_model()->item_count()); 357 } 358 359 // Test that we can launch a platform app that already has a shortcut. 360 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) { 361 int item_count = shelf_model()->item_count(); 362 363 // First get app_id. 364 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 365 const std::string app_id = extension->id(); 366 367 // Then create a shortcut. 368 ash::ShelfID shortcut_id = CreateAppShortcutLauncherItem(app_id); 369 ++item_count; 370 ASSERT_EQ(item_count, shelf_model()->item_count()); 371 ash::ShelfItem item = *shelf_model()->ItemByID(shortcut_id); 372 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 373 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 374 375 // Open a window. Confirm the item is now running. 376 AppWindow* window = CreateAppWindow(extension); 377 ash::wm::ActivateWindow(window->GetNativeWindow()); 378 ASSERT_EQ(item_count, shelf_model()->item_count()); 379 item = *shelf_model()->ItemByID(shortcut_id); 380 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 381 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 382 383 // Then close it, make sure there's still an item. 384 CloseAppWindow(window); 385 ASSERT_EQ(item_count, shelf_model()->item_count()); 386 item = *shelf_model()->ItemByID(shortcut_id); 387 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 388 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 389 } 390 391 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) { 392 // Run. 393 int item_count = shelf_model()->item_count(); 394 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 395 AppWindow* window = CreateAppWindow(extension); 396 ++item_count; 397 ASSERT_EQ(item_count, shelf_model()->item_count()); 398 const ash::ShelfItem& item1 = GetLastLauncherItem(); 399 ash::ShelfID id = item1.id; 400 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 401 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 402 403 // Create a shortcut. The app item should be after it. 404 ash::ShelfID foo_id = CreateAppShortcutLauncherItem("foo"); 405 ++item_count; 406 ASSERT_EQ(item_count, shelf_model()->item_count()); 407 EXPECT_LT(shelf_model()->ItemIndexByID(foo_id), 408 shelf_model()->ItemIndexByID(id)); 409 410 // Pin the app. The item should remain. 411 controller_->Pin(id); 412 ASSERT_EQ(item_count, shelf_model()->item_count()); 413 const ash::ShelfItem& item2 = *shelf_model()->ItemByID(id); 414 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type); 415 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 416 417 // New shortcuts should come after the item. 418 ash::ShelfID bar_id = CreateAppShortcutLauncherItem("bar"); 419 ++item_count; 420 ASSERT_EQ(item_count, shelf_model()->item_count()); 421 EXPECT_LT(shelf_model()->ItemIndexByID(id), 422 shelf_model()->ItemIndexByID(bar_id)); 423 424 // Then close it, make sure the item remains. 425 CloseAppWindow(window); 426 ASSERT_EQ(item_count, shelf_model()->item_count()); 427 } 428 429 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) { 430 int item_count = shelf_model()->item_count(); 431 432 // First get app_id. 433 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 434 const std::string app_id = extension->id(); 435 436 // Then create a shortcut. 437 ash::ShelfID shortcut_id = CreateAppShortcutLauncherItem(app_id); 438 ++item_count; 439 ASSERT_EQ(item_count, shelf_model()->item_count()); 440 ash::ShelfItem item = *shelf_model()->ItemByID(shortcut_id); 441 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 442 EXPECT_EQ(ash::STATUS_CLOSED, item.status); 443 444 // Create a second shortcut. This will be needed to force the first one to 445 // move once it gets unpinned. 446 ash::ShelfID foo_id = CreateAppShortcutLauncherItem("foo"); 447 ++item_count; 448 ASSERT_EQ(item_count, shelf_model()->item_count()); 449 EXPECT_LT(shelf_model()->ItemIndexByID(shortcut_id), 450 shelf_model()->ItemIndexByID(foo_id)); 451 452 // Open a window. Confirm the item is now running. 453 AppWindow* window = CreateAppWindow(extension); 454 ash::wm::ActivateWindow(window->GetNativeWindow()); 455 ASSERT_EQ(item_count, shelf_model()->item_count()); 456 item = *shelf_model()->ItemByID(shortcut_id); 457 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); 458 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 459 460 // Unpin the app. The item should remain. 461 controller_->Unpin(shortcut_id); 462 ASSERT_EQ(item_count, shelf_model()->item_count()); 463 item = *shelf_model()->ItemByID(shortcut_id); 464 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); 465 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 466 // The item should have moved after the other shortcuts. 467 EXPECT_GT(shelf_model()->ItemIndexByID(shortcut_id), 468 shelf_model()->ItemIndexByID(foo_id)); 469 470 // Then close it, make sure the item's gone. 471 CloseAppWindow(window); 472 --item_count; 473 ASSERT_EQ(item_count, shelf_model()->item_count()); 474 } 475 476 // Test that we can launch a platform app with more than one window. 477 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) { 478 int item_count = shelf_model()->item_count(); 479 480 // First run app. 481 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 482 AppWindow* window1 = CreateAppWindow(extension); 483 ++item_count; 484 ASSERT_EQ(item_count, shelf_model()->item_count()); 485 const ash::ShelfItem& item1 = GetLastLauncherItem(); 486 ash::ShelfID item_id = item1.id; 487 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 488 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 489 EXPECT_EQ(2, GetNumApplicationMenuItems(item1)); // Title + 1 window 490 491 // Add second window. 492 AppWindow* window2 = CreateAppWindow(extension); 493 // Confirm item stays. 494 ASSERT_EQ(item_count, shelf_model()->item_count()); 495 const ash::ShelfItem& item2 = *shelf_model()->ItemByID(item_id); 496 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 497 EXPECT_EQ(3, GetNumApplicationMenuItems(item2)); // Title + 2 windows 498 499 // Close second window. 500 CloseAppWindow(window2); 501 // Confirm item stays. 502 ASSERT_EQ(item_count, shelf_model()->item_count()); 503 const ash::ShelfItem& item3 = *shelf_model()->ItemByID(item_id); 504 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status); 505 EXPECT_EQ(2, GetNumApplicationMenuItems(item3)); // Title + 1 window 506 507 // Close first window. 508 CloseAppWindow(window1); 509 // Confirm item is removed. 510 --item_count; 511 ASSERT_EQ(item_count, shelf_model()->item_count()); 512 } 513 514 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) { 515 int item_count = shelf_model()->item_count(); 516 517 // First run app. 518 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 519 AppWindow* window1 = CreateAppWindow(extension1); 520 ++item_count; 521 ASSERT_EQ(item_count, shelf_model()->item_count()); 522 const ash::ShelfItem& item1 = GetLastLauncherItem(); 523 ash::ShelfID item_id1 = item1.id; 524 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 525 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 526 527 // Then run second app. 528 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", 529 "Launched"); 530 AppWindow* window2 = CreateAppWindow(extension2); 531 ++item_count; 532 ASSERT_EQ(item_count, shelf_model()->item_count()); 533 const ash::ShelfItem& item2 = GetLastLauncherItem(); 534 ash::ShelfID item_id2 = item2.id; 535 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); 536 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 537 538 EXPECT_NE(item_id1, item_id2); 539 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 540 541 // Close second app. 542 CloseAppWindow(window2); 543 --item_count; 544 ASSERT_EQ(item_count, shelf_model()->item_count()); 545 // First app should be active again. 546 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 547 548 // Close first app. 549 CloseAppWindow(window1); 550 --item_count; 551 ASSERT_EQ(item_count, shelf_model()->item_count()); 552 } 553 554 // Confirm that app windows can be reactivated by clicking their icons and that 555 // the correct activation order is maintained. 556 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowActivation) { 557 int item_count = shelf_model()->item_count(); 558 559 // First run app. 560 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 561 AppWindow* window1 = CreateAppWindow(extension1); 562 ++item_count; 563 ASSERT_EQ(item_count, shelf_model()->item_count()); 564 const ash::ShelfItem& item1 = GetLastLauncherItem(); 565 ash::ShelfID item_id1 = item1.id; 566 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 567 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 568 569 // Then run second app. 570 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", 571 "Launched"); 572 AppWindow* window2 = CreateAppWindow(extension2); 573 ++item_count; 574 ASSERT_EQ(item_count, shelf_model()->item_count()); 575 const ash::ShelfItem& item2 = GetLastLauncherItem(); 576 ash::ShelfID item_id2 = item2.id; 577 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); 578 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); 579 580 EXPECT_NE(item_id1, item_id2); 581 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 582 583 // Activate first one. 584 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); 585 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 586 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id2)->status); 587 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 588 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 589 590 // Activate second one. 591 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2)); 592 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 593 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id2)->status); 594 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 595 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 596 597 // Add window for app1. This will activate it. 598 AppWindow* window1b = CreateAppWindow(extension1); 599 ash::wm::ActivateWindow(window1b->GetNativeWindow()); 600 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 601 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 602 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 603 604 // Activate launcher item for app1, this will activate the first app window. 605 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); 606 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 607 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 608 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); 609 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 610 611 // Activate the second app again 612 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2)); 613 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 614 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 615 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 616 617 // Activate the first app again 618 ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); 619 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); 620 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); 621 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); 622 623 // Close second app. 624 CloseAppWindow(window2); 625 --item_count; 626 EXPECT_EQ(item_count, shelf_model()->item_count()); 627 // First app should be active again. 628 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); 629 630 // Close first app. 631 CloseAppWindow(window1b); 632 CloseAppWindow(window1); 633 --item_count; 634 EXPECT_EQ(item_count, shelf_model()->item_count()); 635 } 636 637 // Verify that ChromeLauncherController::CanInstall() returns true for ephemeral 638 // apps and false when the app is promoted to a regular installed app. 639 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, InstallEphemeralApp) { 640 int item_count = shelf_model()->item_count(); 641 642 // Sanity check to verify that ChromeLauncherController::CanInstall() returns 643 // false for apps that are fully installed. 644 const Extension* app = LoadAndLaunchPlatformApp("launch", "Launched"); 645 ASSERT_TRUE(app); 646 CreateAppWindow(app); 647 ++item_count; 648 ASSERT_EQ(item_count, shelf_model()->item_count()); 649 const ash::ShelfItem& app_item = GetLastLauncherItem(); 650 ash::ShelfID app_id = app_item.id; 651 EXPECT_FALSE(controller_->CanInstall(app_id)); 652 653 // Add an ephemeral app. 654 const Extension* ephemeral_app = InstallEphemeralAppWithSourceAndFlags( 655 test_data_dir_.AppendASCII("platform_apps").AppendASCII("launch_2"), 656 1, 657 extensions::Manifest::INTERNAL, 658 Extension::NO_FLAGS); 659 ASSERT_TRUE(ephemeral_app); 660 CreateAppWindow(ephemeral_app); 661 ++item_count; 662 ASSERT_EQ(item_count, shelf_model()->item_count()); 663 const ash::ShelfItem& ephemeral_item = GetLastLauncherItem(); 664 ash::ShelfID ephemeral_id = ephemeral_item.id; 665 666 // Verify that the shelf item for the ephemeral app can be installed. 667 EXPECT_TRUE(controller_->CanInstall(ephemeral_id)); 668 669 // Promote the ephemeral app to a regular installed app. 670 ExtensionService* service = 671 extensions::ExtensionSystem::Get(profile())->extension_service(); 672 service->PromoteEphemeralApp(ephemeral_app, false); 673 674 // Verify that the shelf item for the app can no longer be installed. 675 EXPECT_FALSE(controller_->CanInstall(ephemeral_id)); 676 } 677 678 // Confirm that Click behavior for app windows is correnct. 679 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserNoMinimizeOnClick, AppClickBehavior) { 680 // Launch a platform app and create a window for it. 681 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 682 AppWindow* window1 = CreateAppWindow(extension1); 683 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 684 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 685 // Confirm that a controller item was created and is the correct state. 686 const ash::ShelfItem& item1 = GetLastLauncherItem(); 687 LauncherItemController* item1_controller = GetItemController(item1.id); 688 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 689 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 690 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); 691 // Clicking the item should have no effect. 692 TestEvent click_event(ui::ET_MOUSE_PRESSED); 693 item1_controller->ItemSelected(click_event); 694 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 695 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 696 // Minimize the window and confirm that the controller item is updated. 697 window1->GetBaseWindow()->Minimize(); 698 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); 699 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); 700 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 701 // Clicking the item should activate the window. 702 item1_controller->ItemSelected(click_event); 703 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 704 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 705 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 706 // Maximizing a window should preserve state after minimize + click. 707 window1->GetBaseWindow()->Maximize(); 708 window1->GetBaseWindow()->Minimize(); 709 item1_controller->ItemSelected(click_event); 710 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 711 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 712 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); 713 } 714 715 // Confirm the minimizing click behavior for apps. 716 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserMinimizeOnClick, 717 PackagedAppClickBehaviorInMinimizeMode) { 718 // Launch one platform app and create a window for it. 719 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 720 AppWindow* window1 = CreateAppWindow(extension1); 721 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 722 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 723 724 // Confirm that a controller item was created and is the correct state. 725 const ash::ShelfItem& item1 = GetLastLauncherItem(); 726 LauncherItemController* item1_controller = GetItemController(item1.id); 727 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 728 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 729 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); 730 // Since it is already active, clicking it should minimize. 731 TestEvent click_event(ui::ET_MOUSE_PRESSED); 732 item1_controller->ItemSelected(click_event); 733 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); 734 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); 735 EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized()); 736 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 737 // Clicking the item again should activate the window again. 738 item1_controller->ItemSelected(click_event); 739 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 740 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 741 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 742 // Maximizing a window should preserve state after minimize + click. 743 window1->GetBaseWindow()->Maximize(); 744 window1->GetBaseWindow()->Minimize(); 745 item1_controller->ItemSelected(click_event); 746 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 747 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 748 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); 749 window1->GetBaseWindow()->Restore(); 750 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 751 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 752 EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized()); 753 754 // Creating a second window of the same type should change the behavior so 755 // that a click does not change the activation state. 756 AppWindow* window1a = CreateAppWindow(extension1); 757 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 758 EXPECT_TRUE(window1a->GetBaseWindow()->IsActive()); 759 // The first click does nothing. 760 item1_controller->ItemSelected(click_event); 761 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 762 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 763 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 764 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); 765 // The second neither. 766 item1_controller->ItemSelected(click_event); 767 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); 768 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); 769 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); 770 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); 771 } 772 773 // Confirm that click behavior for app panels is correct. 774 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) { 775 // Enable experimental APIs to allow panel creation. 776 CommandLine::ForCurrentProcess()->AppendSwitch( 777 extensions::switches::kEnableExperimentalExtensionApis); 778 // Launch a platform app and create a panel window for it. 779 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 780 AppWindow::CreateParams params; 781 params.window_type = AppWindow::WINDOW_TYPE_PANEL; 782 params.focused = false; 783 AppWindow* panel = CreateAppWindowFromParams(extension1, params); 784 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 785 // Panels should not be active by default. 786 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); 787 // Confirm that a controller item was created and is the correct state. 788 const ash::ShelfItem& item1 = GetLastLauncherPanelItem(); 789 LauncherItemController* item1_controller = GetItemController(item1.id); 790 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type); 791 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 792 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item1_controller->type()); 793 // Click the item and confirm that the panel is activated. 794 TestEvent click_event(ui::ET_MOUSE_PRESSED); 795 item1_controller->ItemSelected(click_event); 796 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 797 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 798 // Click the item again and confirm that the panel is minimized. 799 item1_controller->ItemSelected(click_event); 800 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized()); 801 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); 802 // Click the item again and confirm that the panel is activated. 803 item1_controller->ItemSelected(click_event); 804 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 805 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 806 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 807 } 808 809 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) { 810 int item_count = shelf_model()->item_count(); 811 812 // First run app. 813 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 814 CreateAppWindow(extension1); 815 ++item_count; 816 ASSERT_EQ(item_count, shelf_model()->item_count()); 817 const ash::ShelfItem& item1 = GetLastLauncherItem(); 818 ash::ShelfID item_id1 = item1.id; 819 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 820 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 821 822 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow()); 823 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); 824 } 825 826 // Test that opening an app sets the correct icon 827 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, SetIcon) { 828 TestAppWindowRegistryObserver test_observer(browser()->profile()); 829 830 // Enable experimental APIs to allow panel creation. 831 CommandLine::ForCurrentProcess()->AppendSwitch( 832 extensions::switches::kEnableExperimentalExtensionApis); 833 834 int base_shelf_item_count = shelf_model()->item_count(); 835 ExtensionTestMessageListener completed_listener("Completed", false); 836 LoadAndLaunchPlatformApp("app_icon", "Launched"); 837 ASSERT_TRUE(completed_listener.WaitUntilSatisfied()); 838 839 // Now wait until the WebContent has decoded the icons and chrome has 840 // processed it. This needs to be in a loop since the renderer runs in a 841 // different process. 842 while (test_observer.icon_updates() < 3) { 843 base::RunLoop run_loop; 844 run_loop.RunUntilIdle(); 845 } 846 847 // This test creates one app window and one panel window. 848 int shelf_item_count = shelf_model()->item_count(); 849 ASSERT_EQ(base_shelf_item_count + 2, shelf_item_count); 850 // The Panel will be the last item, the app second-to-last. 851 const ash::ShelfItem& app_item = 852 shelf_model()->items()[shelf_item_count - 2]; 853 const ash::ShelfItem& panel_item = 854 shelf_model()->items()[shelf_item_count - 1]; 855 const LauncherItemController* app_item_controller = 856 GetItemController(app_item.id); 857 const LauncherItemController* panel_item_controller = 858 GetItemController(panel_item.id); 859 // Icons for Apps are set by the AppWindowLauncherController, so 860 // image_set_by_controller() should be set. 861 EXPECT_TRUE(app_item_controller->image_set_by_controller()); 862 EXPECT_TRUE(panel_item_controller->image_set_by_controller()); 863 // Ensure icon heights are correct (see test.js in app_icon/ test directory) 864 EXPECT_EQ(ash::kShelfSize, app_item.image.height()); 865 EXPECT_EQ(64, panel_item.image.height()); 866 } 867 868 // Test that we can launch an app with a shortcut. 869 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchPinned) { 870 TabStripModel* tab_strip = browser()->tab_strip_model(); 871 int tab_count = tab_strip->count(); 872 ash::ShelfID shortcut_id = CreateShortcut("app1"); 873 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 874 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 875 EXPECT_EQ(++tab_count, tab_strip->count()); 876 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 877 WebContents* tab = tab_strip->GetActiveWebContents(); 878 content::WebContentsDestroyedWatcher destroyed_watcher(tab); 879 browser()->tab_strip_model()->CloseSelectedTabs(); 880 destroyed_watcher.Wait(); 881 EXPECT_EQ(--tab_count, tab_strip->count()); 882 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 883 } 884 885 // Launch the app first and then create the shortcut. 886 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchUnpinned) { 887 TabStripModel* tab_strip = browser()->tab_strip_model(); 888 int tab_count = tab_strip->count(); 889 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 890 NEW_FOREGROUND_TAB); 891 EXPECT_EQ(++tab_count, tab_strip->count()); 892 ash::ShelfID shortcut_id = CreateShortcut("app1"); 893 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 894 WebContents* tab = tab_strip->GetActiveWebContents(); 895 content::WebContentsDestroyedWatcher destroyed_watcher(tab); 896 browser()->tab_strip_model()->CloseSelectedTabs(); 897 destroyed_watcher.Wait(); 898 EXPECT_EQ(--tab_count, tab_strip->count()); 899 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 900 } 901 902 // Launches an app in the background and then tries to open it. This is test for 903 // a crash we had. 904 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchInBackground) { 905 TabStripModel* tab_strip = browser()->tab_strip_model(); 906 int tab_count = tab_strip->count(); 907 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 908 NEW_BACKGROUND_TAB); 909 EXPECT_EQ(++tab_count, tab_strip->count()); 910 ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id(), 911 ash::LAUNCH_FROM_UNKNOWN, 912 0); 913 } 914 915 // Confirm that clicking a icon for an app running in one of 2 maxmized windows 916 // activates the right window. 917 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchMaximized) { 918 aura::Window* window1 = browser()->window()->GetNativeWindow(); 919 ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1); 920 window1_state->Maximize(); 921 content::WindowedNotificationObserver open_observer( 922 chrome::NOTIFICATION_BROWSER_WINDOW_READY, 923 content::NotificationService::AllSources()); 924 chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH); 925 open_observer.Wait(); 926 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr(); 927 aura::Window* window2 = browser2->window()->GetNativeWindow(); 928 TabStripModel* tab_strip = browser2->tab_strip_model(); 929 int tab_count = tab_strip->count(); 930 ash::wm::GetWindowState(window2)->Maximize(); 931 932 ash::ShelfID shortcut_id = CreateShortcut("app1"); 933 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 934 EXPECT_EQ(++tab_count, tab_strip->count()); 935 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 936 937 window1->Show(); 938 window1_state->Activate(); 939 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); 940 941 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 942 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 943 } 944 945 // Activating the same app multiple times should launch only a single copy. 946 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ActivateApp) { 947 TabStripModel* tab_strip = browser()->tab_strip_model(); 948 int tab_count = tab_strip->count(); 949 const Extension* extension = 950 LoadExtension(test_data_dir_.AppendASCII("app1")); 951 952 ChromeLauncherController::instance()->ActivateApp(extension->id(), 953 ash::LAUNCH_FROM_UNKNOWN, 954 0); 955 EXPECT_EQ(++tab_count, tab_strip->count()); 956 ChromeLauncherController::instance()->ActivateApp(extension->id(), 957 ash::LAUNCH_FROM_UNKNOWN, 958 0); 959 EXPECT_EQ(tab_count, tab_strip->count()); 960 } 961 962 // Launching the same app multiple times should launch a copy for each call. 963 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchApp) { 964 TabStripModel* tab_strip = browser()->tab_strip_model(); 965 int tab_count = tab_strip->count(); 966 const Extension* extension = 967 LoadExtension(test_data_dir_.AppendASCII("app1")); 968 969 ChromeLauncherController::instance()->LaunchApp(extension->id(), 970 ash::LAUNCH_FROM_UNKNOWN, 971 0); 972 EXPECT_EQ(++tab_count, tab_strip->count()); 973 ChromeLauncherController::instance()->LaunchApp(extension->id(), 974 ash::LAUNCH_FROM_UNKNOWN, 975 0); 976 EXPECT_EQ(++tab_count, tab_strip->count()); 977 } 978 979 // Launch 2 apps and toggle which is active. 980 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultipleApps) { 981 int item_count = model_->item_count(); 982 TabStripModel* tab_strip = browser()->tab_strip_model(); 983 int tab_count = tab_strip->count(); 984 ash::ShelfID shortcut1 = CreateShortcut("app1"); 985 EXPECT_EQ(++item_count, model_->item_count()); 986 ash::ShelfID shortcut2 = CreateShortcut("app2"); 987 EXPECT_EQ(++item_count, model_->item_count()); 988 989 // Launch first app. 990 ActivateShelfItem(model_->ItemIndexByID(shortcut1)); 991 EXPECT_EQ(++tab_count, tab_strip->count()); 992 WebContents* tab1 = tab_strip->GetActiveWebContents(); 993 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 994 995 // Launch second app. 996 ActivateShelfItem(model_->ItemIndexByID(shortcut2)); 997 EXPECT_EQ(++tab_count, tab_strip->count()); 998 WebContents* tab2 = tab_strip->GetActiveWebContents(); 999 ASSERT_NE(tab1, tab2); 1000 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 1001 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 1002 1003 // Reactivate first app. 1004 ActivateShelfItem(model_->ItemIndexByID(shortcut1)); 1005 EXPECT_EQ(tab_count, tab_strip->count()); 1006 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); 1007 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 1008 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); 1009 1010 // Open second tab for second app. This should activate it. 1011 ui_test_utils::NavigateToURLWithDisposition( 1012 browser(), 1013 GURL("http://www.example.com/path3/foo.html"), 1014 NEW_FOREGROUND_TAB, 1015 0); 1016 EXPECT_EQ(++tab_count, tab_strip->count()); 1017 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 1018 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 1019 1020 // Reactivate first app. 1021 ActivateShelfItem(model_->ItemIndexByID(shortcut1)); 1022 EXPECT_EQ(tab_count, tab_strip->count()); 1023 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); 1024 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); 1025 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); 1026 1027 // And second again. This time the second tab should become active. 1028 ActivateShelfItem(model_->ItemIndexByID(shortcut2)); 1029 EXPECT_EQ(tab_count, tab_strip->count()); 1030 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2); 1031 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); 1032 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); 1033 } 1034 1035 // Confirm that a page can be navigated from and to while maintaining the 1036 // correct running state. 1037 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, Navigation) { 1038 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1039 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1040 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1041 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1042 1043 // Navigate away. 1044 ui_test_utils::NavigateToURL( 1045 browser(), GURL("http://www.example.com/path0/bar.html")); 1046 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1047 1048 // Navigate back. 1049 ui_test_utils::NavigateToURL( 1050 browser(), GURL("http://www.example.com/path1/foo.html")); 1051 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1052 } 1053 1054 // Confirm that a tab can be moved between browsers while maintaining the 1055 // correct running state. 1056 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, TabDragAndDrop) { 1057 TabStripModel* tab_strip_model1 = browser()->tab_strip_model(); 1058 EXPECT_EQ(1, tab_strip_model1->count()); 1059 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1060 EXPECT_TRUE(browser_index >= 0); 1061 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1062 1063 // Create a shortcut for app1. 1064 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1065 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1066 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); 1067 1068 // Activate app1 and check its item status. 1069 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1070 EXPECT_EQ(2, tab_strip_model1->count()); 1071 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1072 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1073 1074 // Create a new browser with blank tab. 1075 Browser* browser2 = CreateBrowser(profile()); 1076 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1077 TabStripModel* tab_strip_model2 = browser2->tab_strip_model(); 1078 EXPECT_EQ(1, tab_strip_model2->count()); 1079 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1080 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); 1081 1082 // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an 1083 // active tab at index 1 to |tab_strip_model2|. 1084 content::WebContents* detached_tab = tab_strip_model1->DetachWebContentsAt(1); 1085 tab_strip_model2->InsertWebContentsAt(1, 1086 detached_tab, 1087 TabStripModel::ADD_ACTIVE); 1088 EXPECT_EQ(1, tab_strip_model1->count()); 1089 EXPECT_EQ(2, tab_strip_model2->count()); 1090 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1091 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); 1092 1093 tab_strip_model1->CloseAllTabs(); 1094 tab_strip_model2->CloseAllTabs(); 1095 } 1096 1097 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultipleOwnedTabs) { 1098 TabStripModel* tab_strip = browser()->tab_strip_model(); 1099 int tab_count = tab_strip->count(); 1100 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1101 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1102 EXPECT_EQ(++tab_count, tab_strip->count()); 1103 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1104 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1105 1106 // Create new tab owned by app. 1107 ui_test_utils::NavigateToURLWithDisposition( 1108 browser(), 1109 GURL("http://www.example.com/path2/bar.html"), 1110 NEW_FOREGROUND_TAB, 1111 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1112 EXPECT_EQ(++tab_count, tab_strip->count()); 1113 // Confirm app is still active. 1114 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1115 1116 // Create new tab not owned by app. 1117 ui_test_utils::NavigateToURLWithDisposition( 1118 browser(), 1119 GURL("http://www.example.com/path3/foo.html"), 1120 NEW_FOREGROUND_TAB, 1121 0); 1122 EXPECT_EQ(++tab_count, tab_strip->count()); 1123 // No longer active. 1124 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1125 1126 // Activating app makes first tab active again. 1127 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1128 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1129 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); 1130 } 1131 1132 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, RefocusFilter) { 1133 TabStripModel* tab_strip = browser()->tab_strip_model(); 1134 int tab_count = tab_strip->count(); 1135 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1136 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1137 EXPECT_EQ(++tab_count, tab_strip->count()); 1138 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1139 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1140 1141 controller_->SetRefocusURLPatternForTest( 1142 shortcut_id, GURL("http://www.example.com/path1/*")); 1143 // Create new tab owned by app. 1144 ui_test_utils::NavigateToURLWithDisposition( 1145 browser(), 1146 GURL("http://www.example.com/path2/bar.html"), 1147 NEW_FOREGROUND_TAB, 1148 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1149 EXPECT_EQ(++tab_count, tab_strip->count()); 1150 // Confirm app is still active. 1151 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1152 1153 // Create new tab not owned by app. 1154 ui_test_utils::NavigateToURLWithDisposition( 1155 browser(), 1156 GURL("http://www.example.com/path3/foo.html"), 1157 NEW_FOREGROUND_TAB, 1158 0); 1159 EXPECT_EQ(++tab_count, tab_strip->count()); 1160 // No longer active. 1161 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1162 1163 // Activating app makes first tab active again, because second tab isn't 1164 // in its refocus url path. 1165 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1166 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1167 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); 1168 } 1169 1170 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, RefocusFilterLaunch) { 1171 TabStripModel* tab_strip = browser()->tab_strip_model(); 1172 int tab_count = tab_strip->count(); 1173 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1174 controller_->SetRefocusURLPatternForTest( 1175 shortcut_id, GURL("http://www.example.com/path1/*")); 1176 1177 // Create new tab. 1178 ui_test_utils::NavigateToURLWithDisposition( 1179 browser(), 1180 GURL("http://www.example2.com/path2/bar.html"), 1181 NEW_FOREGROUND_TAB, 1182 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1183 EXPECT_EQ(++tab_count, tab_strip->count()); 1184 WebContents* first_tab = tab_strip->GetActiveWebContents(); 1185 // Confirm app is not active. 1186 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1187 1188 // Activating app should launch new tab, because second tab isn't 1189 // in its refocus url path. 1190 ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); 1191 EXPECT_EQ(++tab_count, tab_strip->count()); 1192 WebContents* second_tab = tab_strip->GetActiveWebContents(); 1193 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1194 EXPECT_NE(first_tab, second_tab); 1195 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); 1196 } 1197 1198 // Check the launcher activation state for applications and browser. 1199 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ActivationStateCheck) { 1200 TabStripModel* tab_strip = browser()->tab_strip_model(); 1201 // Get the browser item index 1202 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); 1203 EXPECT_TRUE(browser_index >= 0); 1204 1205 // Even though we are just comming up, the browser should be active. 1206 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1207 1208 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1209 controller_->SetRefocusURLPatternForTest( 1210 shortcut_id, GURL("http://www.example.com/path1/*")); 1211 1212 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1213 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1214 1215 // Create new tab which would be the running app. 1216 ui_test_utils::NavigateToURLWithDisposition( 1217 browser(), 1218 GURL("http://www.example.com/path1/bar.html"), 1219 NEW_FOREGROUND_TAB, 1220 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1221 1222 // There should never be two items active at the same time. 1223 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1224 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1225 1226 tab_strip->ActivateTabAt(0, false); 1227 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); 1228 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1229 1230 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); 1231 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1232 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); 1233 1234 ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow()); 1235 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1236 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); 1237 } 1238 1239 // Check that the launcher activation state for a V1 application stays closed 1240 // even after an asynchronous browser event comes in after the tab got 1241 // destroyed. 1242 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, AsyncActivationStateCheck) { 1243 TabStripModel* tab_strip = browser()->tab_strip_model(); 1244 1245 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1246 controller_->SetRefocusURLPatternForTest( 1247 shortcut_id, GURL("http://www.example.com/path1/*")); 1248 1249 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1250 1251 // Create new tab which would be the running app. 1252 ui_test_utils::NavigateToURLWithDisposition( 1253 browser(), 1254 GURL("http://www.example.com/path1/bar.html"), 1255 NEW_FOREGROUND_TAB, 1256 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1257 1258 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); 1259 // To address the issue of crbug.com/174050, the tab we are about to close 1260 // has to be active. 1261 tab_strip->ActivateTabAt(1, false); 1262 EXPECT_EQ(1, tab_strip->active_index()); 1263 1264 // Close the web contents. 1265 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); 1266 // The status should now be set to closed. 1267 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); 1268 } 1269 1270 // Checks that a windowed application does not add an item to the browser list. 1271 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, 1272 WindowedAppDoesNotAddToBrowser) { 1273 // Get the number of items in the browser menu. 1274 size_t items = NumberOfDetectedLauncherBrowsers(false); 1275 size_t running_browser = chrome::GetTotalBrowserCount(); 1276 EXPECT_EQ(0u, items); 1277 EXPECT_EQ(0u, running_browser); 1278 1279 LoadAndLaunchExtension( 1280 "app1", extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW); 1281 1282 // No new browser should get detected, even though one more is running. 1283 EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false)); 1284 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); 1285 1286 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1287 1288 // A new browser should get detected and one more should be running. 1289 EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u); 1290 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); 1291 } 1292 1293 // Checks the functionality to enumerate all browsers vs. all tabs. 1294 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, 1295 EnumerateALlBrowsersAndTabs) { 1296 // Create at least one browser. 1297 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1298 size_t browsers = NumberOfDetectedLauncherBrowsers(false); 1299 size_t tabs = NumberOfDetectedLauncherBrowsers(true); 1300 1301 // Create a second browser. 1302 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1303 1304 EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false)); 1305 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); 1306 1307 // Create only a tab. 1308 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, 1309 NEW_FOREGROUND_TAB); 1310 1311 EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false)); 1312 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); 1313 } 1314 1315 // Check that the keyboard activation of a launcher item tabs properly through 1316 // the items at hand. 1317 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, AltNumberTabsTabbing) { 1318 TabStripModel* tab_strip = browser()->tab_strip_model(); 1319 1320 ash::ShelfID shortcut_id = CreateShortcut("app"); 1321 controller_->SetRefocusURLPatternForTest( 1322 shortcut_id, GURL("http://www.example.com/path/*")); 1323 std::string url = "http://www.example.com/path/bla"; 1324 1325 int shortcut_index = model_->ItemIndexByID(shortcut_id); 1326 1327 // Create an application handled browser tab. 1328 ui_test_utils::NavigateToURLWithDisposition( 1329 browser(), 1330 GURL(url), 1331 NEW_FOREGROUND_TAB, 1332 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1333 1334 content::WebContents* content1 = tab_strip->GetActiveWebContents(); 1335 1336 // Create some other browser tab. 1337 ui_test_utils::NavigateToURLWithDisposition( 1338 browser(), 1339 GURL("http://www.test.com"), 1340 NEW_FOREGROUND_TAB, 1341 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1342 content::WebContents* content1a = tab_strip->GetActiveWebContents(); 1343 1344 // Make sure that the active tab is now our handled tab. 1345 EXPECT_NE(content1a, content1); 1346 1347 // The active tab should still be the unnamed tab. Then we switch and reach 1348 // the first app and stay there. 1349 EXPECT_EQ(content1a, tab_strip->GetActiveWebContents()); 1350 ActivateShelfItem(shortcut_index); 1351 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); 1352 ActivateShelfItem(shortcut_index); 1353 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); 1354 1355 ui_test_utils::NavigateToURLWithDisposition( 1356 browser(), 1357 GURL(url), 1358 NEW_FOREGROUND_TAB, 1359 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1360 content::WebContents* content2 = tab_strip->GetActiveWebContents(); 1361 1362 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); 1363 ActivateShelfItem(shortcut_index); 1364 EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents()); 1365 ActivateShelfItem(shortcut_index); 1366 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); 1367 } 1368 1369 // Check that the keyboard activation of a launcher item tabs properly through 1370 // the items at hand. 1371 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, 1372 AltNumberAppsTabbing) { 1373 // First run app. 1374 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); 1375 ui::BaseWindow* window1 = CreateAppWindow(extension1)->GetBaseWindow(); 1376 const ash::ShelfItem& item1 = GetLastLauncherItem(); 1377 ash::ShelfID app_id = item1.id; 1378 int app_index = shelf_model()->ItemIndexByID(app_id); 1379 1380 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); 1381 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); 1382 1383 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", 1384 "Launched"); 1385 ui::BaseWindow* window2 = CreateAppWindow(extension2)->GetBaseWindow(); 1386 1387 // By now the browser should be active. Issue Alt keystrokes several times to 1388 // see that we stay on that application. 1389 EXPECT_TRUE(window2->IsActive()); 1390 ActivateShelfItem(app_index); 1391 EXPECT_TRUE(window1->IsActive()); 1392 ActivateShelfItem(app_index); 1393 EXPECT_TRUE(window1->IsActive()); 1394 1395 ui::BaseWindow* window1a = CreateAppWindow(extension1)->GetBaseWindow(); 1396 1397 EXPECT_TRUE(window1a->IsActive()); 1398 EXPECT_FALSE(window1->IsActive()); 1399 ActivateShelfItem(app_index); 1400 EXPECT_TRUE(window1->IsActive()); 1401 ActivateShelfItem(app_index); 1402 EXPECT_TRUE(window1a->IsActive()); 1403 } 1404 1405 // Test that we can launch a platform app panel and get a running item. 1406 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) { 1407 int item_count = shelf_model()->item_count(); 1408 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 1409 AppWindow::CreateParams params; 1410 params.window_type = AppWindow::WINDOW_TYPE_PANEL; 1411 params.focused = false; 1412 AppWindow* window = CreateAppWindowFromParams(extension, params); 1413 ++item_count; 1414 ASSERT_EQ(item_count, shelf_model()->item_count()); 1415 const ash::ShelfItem& item = GetLastLauncherPanelItem(); 1416 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); 1417 // Opening a panel does not activate it. 1418 EXPECT_EQ(ash::STATUS_RUNNING, item.status); 1419 CloseAppWindow(window); 1420 --item_count; 1421 EXPECT_EQ(item_count, shelf_model()->item_count()); 1422 } 1423 1424 // Test that we get correct shelf presence with hidden app windows. 1425 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, HiddenAppWindows) { 1426 int item_count = shelf_model()->item_count(); 1427 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 1428 AppWindow::CreateParams params; 1429 1430 // Create a hidden window. 1431 params.hidden = true; 1432 AppWindow* window_1 = CreateAppWindowFromParams(extension, params); 1433 EXPECT_EQ(item_count, shelf_model()->item_count()); 1434 1435 // Create a visible window. 1436 params.hidden = false; 1437 AppWindow* window_2 = CreateAppWindowFromParams(extension, params); 1438 ++item_count; 1439 EXPECT_EQ(item_count, shelf_model()->item_count()); 1440 1441 // Minimize the visible window. 1442 window_2->Minimize(); 1443 EXPECT_EQ(item_count, shelf_model()->item_count()); 1444 1445 // Hide the visible window. 1446 window_2->Hide(); 1447 --item_count; 1448 EXPECT_EQ(item_count, shelf_model()->item_count()); 1449 1450 // Show the originally hidden window. 1451 window_1->Show(AppWindow::SHOW_ACTIVE); 1452 ++item_count; 1453 EXPECT_EQ(item_count, shelf_model()->item_count()); 1454 1455 // Close the originally hidden window. 1456 CloseAppWindow(window_1); 1457 --item_count; 1458 EXPECT_EQ(item_count, shelf_model()->item_count()); 1459 } 1460 1461 // Test attention states of windows. 1462 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) { 1463 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); 1464 AppWindow::CreateParams params; 1465 params.window_type = AppWindow::WINDOW_TYPE_PANEL; 1466 params.focused = false; 1467 AppWindow* panel = CreateAppWindowFromParams(extension, params); 1468 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); 1469 // Panels should not be active by default. 1470 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); 1471 // Confirm that a controller item was created and is the correct state. 1472 const ash::ShelfItem& item = GetLastLauncherPanelItem(); 1473 LauncherItemController* item_controller = GetItemController(item.id); 1474 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); 1475 EXPECT_EQ(ash::STATUS_RUNNING, item.status); 1476 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item_controller->type()); 1477 1478 // App windows should go to attention state. 1479 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); 1480 EXPECT_EQ(ash::STATUS_ATTENTION, item.status); 1481 1482 // Click the item and confirm that the panel is activated. 1483 TestEvent click_event(ui::ET_MOUSE_PRESSED); 1484 item_controller->ItemSelected(click_event); 1485 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); 1486 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 1487 1488 // Active windows don't show attention. 1489 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); 1490 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); 1491 } 1492 1493 // Checks that the browser Alt "tabbing" is properly done. 1494 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, 1495 AltNumberBrowserTabbing) { 1496 // Get the number of items in the browser menu. 1497 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); 1498 // The first activation should create a browser at index 1 (App List @ 0). 1499 shelf_->ActivateShelfItem(1); 1500 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1501 // A second activation should not create a new instance. 1502 shelf_->ActivateShelfItem(1); 1503 Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()); 1504 EXPECT_TRUE(browser1); 1505 aura::Window* window1 = browser1->window()->GetNativeWindow(); 1506 Browser* browser2 = CreateBrowser(profile()); 1507 aura::Window* window2 = browser2->window()->GetNativeWindow(); 1508 1509 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1510 EXPECT_NE(window1, window2); 1511 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1512 1513 // Activate multiple times the switcher to see that the windows get activated. 1514 shelf_->ActivateShelfItem(1); 1515 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1516 shelf_->ActivateShelfItem(1); 1517 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1518 1519 // Create a third browser - make sure that we do not toggle simply between 1520 // two windows. 1521 Browser* browser3 = CreateBrowser(profile()); 1522 aura::Window* window3 = browser3->window()->GetNativeWindow(); 1523 1524 EXPECT_EQ(3u, chrome::GetTotalBrowserCount()); 1525 EXPECT_NE(window1, window3); 1526 EXPECT_NE(window2, window3); 1527 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); 1528 1529 shelf_->ActivateShelfItem(1); 1530 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1531 shelf_->ActivateShelfItem(1); 1532 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); 1533 shelf_->ActivateShelfItem(1); 1534 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); 1535 shelf_->ActivateShelfItem(1); 1536 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1537 1538 // Create anther app and make sure that none of our browsers is active. 1539 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW); 1540 EXPECT_NE(window1, ash::wm::GetActiveWindow()); 1541 EXPECT_NE(window2, ash::wm::GetActiveWindow()); 1542 1543 // After activation our browser should be active again. 1544 shelf_->ActivateShelfItem(1); 1545 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); 1546 } 1547 1548 // Checks that after a session restore, we do not start applications on an 1549 // activation. 1550 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ActivateAfterSessionRestore) { 1551 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 1552 1553 // Create a known application. 1554 ash::ShelfID shortcut_id = CreateShortcut("app1"); 1555 1556 // Create a new browser - without activating it - and load an "app" into it. 1557 Browser::CreateParams params = 1558 Browser::CreateParams(profile(), chrome::GetActiveDesktop()); 1559 params.initial_show_state = ui::SHOW_STATE_INACTIVE; 1560 Browser* browser2 = new Browser(params); 1561 controller_->SetRefocusURLPatternForTest( 1562 shortcut_id, GURL("http://www.example.com/path/*")); 1563 std::string url = "http://www.example.com/path/bla"; 1564 ui_test_utils::NavigateToURLWithDisposition( 1565 browser2, 1566 GURL(url), 1567 NEW_FOREGROUND_TAB, 1568 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 1569 1570 // Remember the number of tabs for each browser. 1571 TabStripModel* tab_strip = browser()->tab_strip_model(); 1572 int tab_count1 = tab_strip->count(); 1573 TabStripModel* tab_strip2 = browser2->tab_strip_model(); 1574 int tab_count2 = tab_strip2->count(); 1575 1576 // Check that we have two browsers and the inactive browser remained inactive. 1577 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); 1578 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), 1579 browser()); 1580 // Check that the LRU browser list does only contain the original browser. 1581 BrowserList* ash_browser_list = 1582 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 1583 BrowserList::const_reverse_iterator it = 1584 ash_browser_list->begin_last_active(); 1585 EXPECT_EQ(*it, browser()); 1586 ++it; 1587 EXPECT_EQ(it, ash_browser_list->end_last_active()); 1588 1589 // Now request to either activate an existing app or create a new one. 1590 LauncherItemController* item_controller = 1591 controller_->GetLauncherItemController(shortcut_id); 1592 item_controller->ItemSelected(ui::KeyEvent(ui::ET_KEY_RELEASED, 1593 ui::VKEY_RETURN, 1594 ui::EF_NONE)); 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 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), 1611 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 ui::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 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), 1836 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 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), 1939 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(extensions::kWebStoreAppId); 2070 ash::ShelfID id = controller_->GetShelfIDForAppID( 2071 extensions::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(extensions::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