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