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.
5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
7 #include "apps/shell_window.h"
8 #include "apps/shell_window_registry.h"
9 #include "apps/ui/native_app_window.h"
10 #include "ash/ash_switches.h"
11 #include "ash/display/display_controller.h"
12 #include "ash/launcher/launcher.h"
13 #include "ash/launcher/launcher_button.h"
14 #include "ash/launcher/launcher_model.h"
15 #include "ash/shelf/shelf_model_util.h"
16 #include "ash/shelf/shelf_view.h"
17 #include "ash/shell.h"
18 #include "ash/test/app_list_controller_test_api.h"
19 #include "ash/test/launcher_test_api.h"
20 #include "ash/test/shelf_view_test_api.h"
21 #include "ash/test/shell_test_api.h"
22 #include "ash/wm/window_state.h"
23 #include "ash/wm/window_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "chrome/browser/apps/app_browsertest_util.h"
27 #include "chrome/browser/automation/automation_util.h"
28 #include "chrome/browser/chrome_notification_types.h"
29 #include "chrome/browser/extensions/extension_apitest.h"
30 #include "chrome/browser/extensions/extension_browsertest.h"
31 #include "chrome/browser/extensions/extension_function_test_utils.h"
32 #include "chrome/browser/extensions/extension_service.h"
33 #include "chrome/browser/extensions/extension_system.h"
34 #include "chrome/browser/extensions/extension_test_message_listener.h"
35 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/ui/app_list/app_list_service.h"
37 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
38 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
39 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
40 #include "chrome/browser/ui/browser.h"
41 #include "chrome/browser/ui/browser_commands.h"
42 #include "chrome/browser/ui/browser_finder.h"
43 #include "chrome/browser/ui/browser_list.h"
44 #include "chrome/browser/ui/browser_window.h"
45 #include "chrome/browser/ui/extensions/application_launch.h"
46 #include "chrome/browser/ui/host_desktop.h"
47 #include "chrome/browser/ui/tabs/tab_strip_model.h"
48 #include "chrome/common/chrome_switches.h"
49 #include "chrome/common/extensions/extension_constants.h"
50 #include "chrome/test/base/ui_test_utils.h"
51 #include "content/public/browser/notification_service.h"
52 #include "content/public/browser/notification_source.h"
53 #include "content/public/browser/web_contents.h"
54 #include "content/public/test/browser_test_utils.h"
55 #include "extensions/common/switches.h"
56 #include "testing/gtest/include/gtest/gtest.h"
57 #include "ui/app_list/views/apps_grid_view.h"
58 #include "ui/aura/client/aura_constants.h"
59 #include "ui/aura/test/event_generator.h"
60 #include "ui/aura/window.h"
61 #include "ui/events/event.h"
63 using apps::ShellWindow;
64 using extensions::Extension;
65 using content::WebContents;
69 class TestEvent : public ui::Event {
71 explicit TestEvent(ui::EventType type)
72 : ui::Event(type, base::TimeDelta(), 0) {
74 virtual ~TestEvent() {
78 DISALLOW_COPY_AND_ASSIGN(TestEvent);
81 class TestShellWindowRegistryObserver
82 : public apps::ShellWindowRegistry::Observer {
84 explicit TestShellWindowRegistryObserver(Profile* profile)
87 apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
90 virtual ~TestShellWindowRegistryObserver() {
91 apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
94 // Overridden from ShellWindowRegistry::Observer:
95 virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {}
97 virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {
101 virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {}
103 int icon_updates() { return icon_updates_; }
109 DISALLOW_COPY_AND_ASSIGN(TestShellWindowRegistryObserver);
114 class LauncherPlatformAppBrowserTest
115 : public extensions::PlatformAppBrowserTest {
117 LauncherPlatformAppBrowserTest() : launcher_(NULL), controller_(NULL) {
120 virtual ~LauncherPlatformAppBrowserTest() {}
122 virtual void RunTestOnMainThreadLoop() OVERRIDE {
123 launcher_ = ash::Launcher::ForPrimaryDisplay();
124 controller_ = ChromeLauncherController::instance();
125 return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop();
128 ash::LauncherModel* launcher_model() {
129 return ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model();
132 ash::LauncherID CreateAppShortcutLauncherItem(const std::string& name) {
133 return controller_->CreateAppShortcutLauncherItem(
134 name, controller_->model()->item_count());
137 const ash::LauncherItem& GetLastLauncherItem() {
138 // Unless there are any panels, the item at index [count - 1] will be
140 return launcher_model()->items()[launcher_model()->item_count() - 1];
143 const ash::LauncherItem& GetLastLauncherPanelItem() {
144 // Panels show up on the right side of the launcher, so the desired item
145 // will be the last one.
146 return launcher_model()->items()[launcher_model()->item_count() - 1];
149 LauncherItemController* GetItemController(ash::LauncherID id) {
150 return controller_->id_to_item_controller_map_[id];
153 // Returns the number of menu items, ignoring separators.
154 int GetNumApplicationMenuItems(const ash::LauncherItem& item) {
155 const int event_flags = 0;
156 scoped_ptr<ash::LauncherMenuModel> menu(
157 new LauncherApplicationMenuItemModel(
158 controller_->GetApplicationList(item, event_flags)));
160 for (int i = 0; i < menu->GetItemCount(); ++i) {
161 if (menu->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR)
167 // Activate the launcher item with the given |id|.
168 void ActivateLauncherItem(int id) {
169 launcher_->ActivateLauncherItem(id);
172 ash::Launcher* launcher_;
173 ChromeLauncherController* controller_;
177 DISALLOW_COPY_AND_ASSIGN(LauncherPlatformAppBrowserTest);
181 // Drag the item off the shelf and let the mouse go.
183 // Drag the item off the shelf, move the mouse back and then let go.
184 RIP_OFF_ITEM_AND_RETURN,
185 // Drag the item off the shelf and then issue a cancel command.
186 RIP_OFF_ITEM_AND_CANCEL,
187 // Drag the item off the shelf and do not release the mouse.
188 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE,
191 class LauncherAppBrowserTest : public ExtensionBrowserTest {
193 LauncherAppBrowserTest() : launcher_(NULL), model_(NULL), controller_(NULL) {
196 virtual ~LauncherAppBrowserTest() {}
198 virtual void RunTestOnMainThreadLoop() OVERRIDE {
199 launcher_ = ash::Launcher::ForPrimaryDisplay();
201 ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model();
202 controller_ = ChromeLauncherController::instance();
203 return ExtensionBrowserTest::RunTestOnMainThreadLoop();
206 size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) {
207 LauncherItemController* item_controller =
208 controller_->GetBrowserShortcutLauncherItemController();
209 int items = item_controller->GetApplicationList(
210 show_all_tabs ? ui::EF_SHIFT_DOWN : 0).size();
211 // If we have at least one item, we have also a title which we remove here.
212 return items ? (items - 1) : 0;
215 const Extension* LoadAndLaunchExtension(
217 extension_misc::LaunchContainer container,
218 WindowOpenDisposition disposition) {
219 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name)));
221 ExtensionService* service = extensions::ExtensionSystem::Get(
222 profile())->extension_service();
223 const Extension* extension =
224 service->GetExtensionById(last_loaded_extension_id(), false);
225 EXPECT_TRUE(extension);
227 OpenApplication(AppLaunchParams(profile(),
234 ash::LauncherID CreateShortcut(const char* name) {
235 ExtensionService* service = extensions::ExtensionSystem::Get(
236 profile())->extension_service();
237 LoadExtension(test_data_dir_.AppendASCII(name));
240 const Extension* extension =
241 service->GetExtensionById(last_loaded_extension_id(), false);
242 const std::string app_id = extension->id();
244 // Then create a shortcut.
245 int item_count = model_->item_count();
246 ash::LauncherID shortcut_id = controller_->CreateAppShortcutLauncherItem(
249 controller_->PersistPinnedState();
250 EXPECT_EQ(++item_count, model_->item_count());
251 const ash::LauncherItem& item = *model_->ItemByID(shortcut_id);
252 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
256 void RemoveShortcut(ash::LauncherID id) {
257 controller_->Unpin(id);
260 // Activate the launcher item with the given |id|.
261 void ActivateLauncherItem(int id) {
262 launcher_->ActivateLauncherItem(id);
265 ash::LauncherID PinFakeApp(const std::string& name) {
266 return controller_->CreateAppShortcutLauncherItem(
267 name, model_->item_count());
270 // Get the index of an item which has the given type.
271 int GetIndexOfShelfItemType(ash::LauncherItemType type) {
272 return ash::GetShelfItemIndexForType(type, *model_);
275 // Try to rip off |item_index|.
276 void RipOffItemIndex(int index,
277 aura::test::EventGenerator* generator,
278 ash::test::ShelfViewTestAPI* test,
279 RipOffCommand command) {
280 ash::internal::LauncherButton* button = test->GetButton(index);
281 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
282 gfx::Point rip_off_point(start_point.x(), 0);
283 generator->MoveMouseTo(start_point.x(), start_point.y());
284 base::MessageLoop::current()->RunUntilIdle();
285 generator->PressLeftButton();
286 base::MessageLoop::current()->RunUntilIdle();
287 generator->MoveMouseTo(rip_off_point.x(), rip_off_point.y());
288 base::MessageLoop::current()->RunUntilIdle();
289 test->RunMessageLoopUntilAnimationsDone();
290 if (command == RIP_OFF_ITEM_AND_RETURN) {
291 generator->MoveMouseTo(start_point.x(), start_point.y());
292 base::MessageLoop::current()->RunUntilIdle();
293 test->RunMessageLoopUntilAnimationsDone();
294 } else if (command == RIP_OFF_ITEM_AND_CANCEL) {
295 // This triggers an internal cancel. Using VKEY_ESCAPE was too unreliable.
296 button->OnMouseCaptureLost();
298 if (command != RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE) {
299 generator->ReleaseLeftButton();
300 test->RunMessageLoopUntilAnimationsDone();
304 ash::Launcher* launcher_;
305 ash::LauncherModel* model_;
306 ChromeLauncherController* controller_;
310 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTest);
313 class LauncherAppBrowserTestNoDefaultBrowser : public LauncherAppBrowserTest {
315 LauncherAppBrowserTestNoDefaultBrowser() {}
316 virtual ~LauncherAppBrowserTestNoDefaultBrowser() {}
318 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
319 LauncherAppBrowserTest::SetUpCommandLine(command_line);
320 command_line->AppendSwitch(switches::kNoStartupWindow);
325 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTestNoDefaultBrowser);
328 // Since the default for minimizing on click might change, I added both classes
329 // to either get the minimize on click or not.
330 class LauncherAppBrowserNoMinimizeOnClick
331 : public LauncherPlatformAppBrowserTest {
333 LauncherAppBrowserNoMinimizeOnClick() {}
334 virtual ~LauncherAppBrowserNoMinimizeOnClick() {}
336 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
337 LauncherPlatformAppBrowserTest::SetUpCommandLine(command_line);
338 command_line->AppendSwitch(
339 switches::kDisableMinimizeOnSecondLauncherItemClick);
344 DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserNoMinimizeOnClick);
347 typedef LauncherPlatformAppBrowserTest LauncherAppBrowserMinimizeOnClick;
349 // Test that we can launch a platform app and get a running item.
350 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) {
351 int item_count = launcher_model()->item_count();
352 const Extension* extension = LoadAndLaunchPlatformApp("launch");
353 ShellWindow* window = CreateShellWindow(extension);
355 ASSERT_EQ(item_count, launcher_model()->item_count());
356 const ash::LauncherItem& item = GetLastLauncherItem();
357 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
358 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
359 CloseShellWindow(window);
361 EXPECT_EQ(item_count, launcher_model()->item_count());
364 // Test that we can launch a platform app that already has a shortcut.
365 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) {
366 int item_count = launcher_model()->item_count();
369 const Extension* extension = LoadAndLaunchPlatformApp("launch");
370 const std::string app_id = extension->id();
372 // Then create a shortcut.
373 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
375 ASSERT_EQ(item_count, launcher_model()->item_count());
376 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id);
377 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
378 EXPECT_EQ(ash::STATUS_CLOSED, item.status);
380 // Open a window. Confirm the item is now running.
381 ShellWindow* window = CreateShellWindow(extension);
382 ash::wm::ActivateWindow(window->GetNativeWindow());
383 ASSERT_EQ(item_count, launcher_model()->item_count());
384 item = *launcher_model()->ItemByID(shortcut_id);
385 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
386 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
388 // Then close it, make sure there's still an item.
389 CloseShellWindow(window);
390 ASSERT_EQ(item_count, launcher_model()->item_count());
391 item = *launcher_model()->ItemByID(shortcut_id);
392 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
393 EXPECT_EQ(ash::STATUS_CLOSED, item.status);
396 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) {
398 int item_count = launcher_model()->item_count();
399 const Extension* extension = LoadAndLaunchPlatformApp("launch");
400 ShellWindow* window = CreateShellWindow(extension);
402 ASSERT_EQ(item_count, launcher_model()->item_count());
403 const ash::LauncherItem& item1 = GetLastLauncherItem();
404 ash::LauncherID id = item1.id;
405 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
406 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
408 // Create a shortcut. The app item should be after it.
409 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
411 ASSERT_EQ(item_count, launcher_model()->item_count());
412 EXPECT_LT(launcher_model()->ItemIndexByID(foo_id),
413 launcher_model()->ItemIndexByID(id));
415 // Pin the app. The item should remain.
416 controller_->Pin(id);
417 ASSERT_EQ(item_count, launcher_model()->item_count());
418 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(id);
419 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type);
420 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
422 // New shortcuts should come after the item.
423 ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar");
425 ASSERT_EQ(item_count, launcher_model()->item_count());
426 EXPECT_LT(launcher_model()->ItemIndexByID(id),
427 launcher_model()->ItemIndexByID(bar_id));
429 // Then close it, make sure the item remains.
430 CloseShellWindow(window);
431 ASSERT_EQ(item_count, launcher_model()->item_count());
434 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) {
435 int item_count = launcher_model()->item_count();
438 const Extension* extension = LoadAndLaunchPlatformApp("launch");
439 const std::string app_id = extension->id();
441 // Then create a shortcut.
442 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
444 ASSERT_EQ(item_count, launcher_model()->item_count());
445 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id);
446 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
447 EXPECT_EQ(ash::STATUS_CLOSED, item.status);
449 // Create a second shortcut. This will be needed to force the first one to
450 // move once it gets unpinned.
451 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
453 ASSERT_EQ(item_count, launcher_model()->item_count());
454 EXPECT_LT(launcher_model()->ItemIndexByID(shortcut_id),
455 launcher_model()->ItemIndexByID(foo_id));
457 // Open a window. Confirm the item is now running.
458 ShellWindow* window = CreateShellWindow(extension);
459 ash::wm::ActivateWindow(window->GetNativeWindow());
460 ASSERT_EQ(item_count, launcher_model()->item_count());
461 item = *launcher_model()->ItemByID(shortcut_id);
462 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
463 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
465 // Unpin the app. The item should remain.
466 controller_->Unpin(shortcut_id);
467 ASSERT_EQ(item_count, launcher_model()->item_count());
468 item = *launcher_model()->ItemByID(shortcut_id);
469 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
470 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
471 // The item should have moved after the other shortcuts.
472 EXPECT_GT(launcher_model()->ItemIndexByID(shortcut_id),
473 launcher_model()->ItemIndexByID(foo_id));
475 // Then close it, make sure the item's gone.
476 CloseShellWindow(window);
478 ASSERT_EQ(item_count, launcher_model()->item_count());
481 // Test that we can launch a platform app with more than one window.
482 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) {
483 int item_count = launcher_model()->item_count();
486 const Extension* extension = LoadAndLaunchPlatformApp("launch");
487 ShellWindow* window1 = CreateShellWindow(extension);
489 ASSERT_EQ(item_count, launcher_model()->item_count());
490 const ash::LauncherItem& item1 = GetLastLauncherItem();
491 ash::LauncherID item_id = item1.id;
492 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
493 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
494 EXPECT_EQ(2, GetNumApplicationMenuItems(item1)); // Title + 1 window
496 // Add second window.
497 ShellWindow* window2 = CreateShellWindow(extension);
498 // Confirm item stays.
499 ASSERT_EQ(item_count, launcher_model()->item_count());
500 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(item_id);
501 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
502 EXPECT_EQ(3, GetNumApplicationMenuItems(item2)); // Title + 2 windows
504 // Close second window.
505 CloseShellWindow(window2);
506 // Confirm item stays.
507 ASSERT_EQ(item_count, launcher_model()->item_count());
508 const ash::LauncherItem& item3 = *launcher_model()->ItemByID(item_id);
509 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status);
510 EXPECT_EQ(2, GetNumApplicationMenuItems(item3)); // Title + 1 window
512 // Close first window.
513 CloseShellWindow(window1);
514 // Confirm item is removed.
516 ASSERT_EQ(item_count, launcher_model()->item_count());
519 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) {
520 int item_count = launcher_model()->item_count();
523 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
524 ShellWindow* window1 = CreateShellWindow(extension1);
526 ASSERT_EQ(item_count, launcher_model()->item_count());
527 const ash::LauncherItem& item1 = GetLastLauncherItem();
528 ash::LauncherID item_id1 = item1.id;
529 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
530 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
532 // Then run second app.
533 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
534 ShellWindow* window2 = CreateShellWindow(extension2);
536 ASSERT_EQ(item_count, launcher_model()->item_count());
537 const ash::LauncherItem& item2 = GetLastLauncherItem();
538 ash::LauncherID item_id2 = item2.id;
539 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
540 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
542 EXPECT_NE(item_id1, item_id2);
543 EXPECT_EQ(ash::STATUS_RUNNING,
544 launcher_model()->ItemByID(item_id1)->status);
547 CloseShellWindow(window2);
549 ASSERT_EQ(item_count, launcher_model()->item_count());
550 // First app should be active again.
551 EXPECT_EQ(ash::STATUS_ACTIVE,
552 launcher_model()->ItemByID(item_id1)->status);
555 CloseShellWindow(window1);
557 ASSERT_EQ(item_count, launcher_model()->item_count());
560 // Confirm that app windows can be reactivated by clicking their icons and that
561 // the correct activation order is maintained.
562 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowActivation) {
563 int item_count = launcher_model()->item_count();
566 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
567 ShellWindow* window1 = CreateShellWindow(extension1);
569 ASSERT_EQ(item_count, launcher_model()->item_count());
570 const ash::LauncherItem& item1 = GetLastLauncherItem();
571 ash::LauncherID item_id1 = item1.id;
572 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
573 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
575 // Then run second app.
576 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
577 ShellWindow* window2 = CreateShellWindow(extension2);
579 ASSERT_EQ(item_count, launcher_model()->item_count());
580 const ash::LauncherItem& item2 = GetLastLauncherItem();
581 ash::LauncherID item_id2 = item2.id;
582 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
583 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
585 EXPECT_NE(item_id1, item_id2);
586 EXPECT_EQ(ash::STATUS_RUNNING,
587 launcher_model()->ItemByID(item_id1)->status);
589 // Activate first one.
590 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
591 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status);
592 EXPECT_EQ(ash::STATUS_RUNNING,
593 launcher_model()->ItemByID(item_id2)->status);
594 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
595 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
597 // Activate second one.
598 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
599 EXPECT_EQ(ash::STATUS_RUNNING,
600 launcher_model()->ItemByID(item_id1)->status);
601 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id2)->status);
602 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
603 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
605 // Add window for app1. This will activate it.
606 ShellWindow* window1b = CreateShellWindow(extension1);
607 ash::wm::ActivateWindow(window1b->GetNativeWindow());
608 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
609 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
610 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
612 // Activate launcher item for app1, this will activate the first app window.
613 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
614 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
615 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
616 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
617 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
619 // Activate the second app again
620 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
621 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
622 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
623 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
625 // Activate the first app again
626 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
627 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
628 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
629 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
632 CloseShellWindow(window2);
634 EXPECT_EQ(item_count, launcher_model()->item_count());
635 // First app should be active again.
636 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status);
639 CloseShellWindow(window1b);
640 CloseShellWindow(window1);
642 EXPECT_EQ(item_count, launcher_model()->item_count());
645 // Confirm that Click behavior for app windows is correnct.
646 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserNoMinimizeOnClick,
648 // Launch a platform app and create a window for it.
649 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
650 ShellWindow* window1 = CreateShellWindow(extension1);
651 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
652 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
653 // Confirm that a controller item was created and is the correct state.
654 const ash::LauncherItem& item1 = GetLastLauncherItem();
655 LauncherItemController* item1_controller = GetItemController(item1.id);
656 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
657 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
658 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type());
659 // Clicking the item should have no effect.
660 TestEvent click_event(ui::ET_MOUSE_PRESSED);
661 item1_controller->ItemSelected(click_event);
662 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
663 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
664 // Minimize the window and confirm that the controller item is updated.
665 window1->GetBaseWindow()->Minimize();
666 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible());
667 EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
668 EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
669 // Clicking the item should activate the window.
670 item1_controller->ItemSelected(click_event);
671 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
672 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
673 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
674 // Maximizing a window should preserve state after minimize + click.
675 window1->GetBaseWindow()->Maximize();
676 window1->GetBaseWindow()->Minimize();
677 item1_controller->ItemSelected(click_event);
678 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
679 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
680 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
683 // Confirm the minimizing click behavior for apps.
684 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserMinimizeOnClick,
685 PackagedAppClickBehaviorInMinimizeMode) {
686 // Launch one platform app and create a window for it.
687 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
688 ShellWindow* window1 = CreateShellWindow(extension1);
689 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
690 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
692 // Confirm that a controller item was created and is the correct state.
693 const ash::LauncherItem& item1 = GetLastLauncherItem();
694 LauncherItemController* item1_controller = GetItemController(item1.id);
695 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
696 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
697 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type());
698 // Since it is already active, clicking it should minimize.
699 TestEvent click_event(ui::ET_MOUSE_PRESSED);
700 item1_controller->ItemSelected(click_event);
701 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible());
702 EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
703 EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized());
704 EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
705 // Clicking the item again should activate the window again.
706 item1_controller->ItemSelected(click_event);
707 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
708 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
709 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
710 // Maximizing a window should preserve state after minimize + click.
711 window1->GetBaseWindow()->Maximize();
712 window1->GetBaseWindow()->Minimize();
713 item1_controller->ItemSelected(click_event);
714 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
715 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
716 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
717 window1->GetBaseWindow()->Restore();
718 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
719 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
720 EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized());
722 // Creating a second window of the same type should change the behavior so
723 // that a click does not change the activation state.
724 ShellWindow* window1a = CreateShellWindow(extension1);
725 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
726 EXPECT_TRUE(window1a->GetBaseWindow()->IsActive());
727 // The first click does nothing.
728 item1_controller->ItemSelected(click_event);
729 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
730 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
731 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
732 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive());
733 // The second neither.
734 item1_controller->ItemSelected(click_event);
735 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
736 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
737 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
738 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive());
741 // Confirm that click behavior for app panels is correct.
742 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) {
743 // Enable experimental APIs to allow panel creation.
744 CommandLine::ForCurrentProcess()->AppendSwitch(
745 extensions::switches::kEnableExperimentalExtensionApis);
746 // Launch a platform app and create a panel window for it.
747 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
748 ShellWindow::CreateParams params;
749 params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
750 params.focused = false;
751 ShellWindow* panel = CreateShellWindowFromParams(extension1, params);
752 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
753 // Panels should not be active by default.
754 EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
755 // Confirm that a controller item was created and is the correct state.
756 const ash::LauncherItem& item1 = GetLastLauncherPanelItem();
757 LauncherItemController* item1_controller = GetItemController(item1.id);
758 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type);
759 EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
760 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item1_controller->type());
761 // Click the item and confirm that the panel is activated.
762 TestEvent click_event(ui::ET_MOUSE_PRESSED);
763 item1_controller->ItemSelected(click_event);
764 EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
765 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
766 // Click the item again and confirm that the panel is minimized.
767 item1_controller->ItemSelected(click_event);
768 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized());
769 EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
770 // Click the item again and confirm that the panel is activated.
771 item1_controller->ItemSelected(click_event);
772 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
773 EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
774 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
777 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) {
778 int item_count = launcher_model()->item_count();
781 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
782 CreateShellWindow(extension1);
784 ASSERT_EQ(item_count, launcher_model()->item_count());
785 const ash::LauncherItem& item1 = GetLastLauncherItem();
786 ash::LauncherID item_id1 = item1.id;
787 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
788 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
790 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow());
791 EXPECT_EQ(ash::STATUS_RUNNING,
792 launcher_model()->ItemByID(item_id1)->status);
795 // Test that opening an app sets the correct icon
796 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, SetIcon) {
797 TestShellWindowRegistryObserver test_observer(browser()->profile());
799 // Enable experimental APIs to allow panel creation.
800 CommandLine::ForCurrentProcess()->AppendSwitch(
801 extensions::switches::kEnableExperimentalExtensionApis);
803 int base_launcher_item_count = launcher_model()->item_count();
804 ExtensionTestMessageListener launched_listener("Launched", false);
805 ExtensionTestMessageListener completed_listener("Completed", false);
806 LoadAndLaunchPlatformApp("app_icon");
807 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
808 ASSERT_TRUE(completed_listener.WaitUntilSatisfied());
810 // Now wait until the WebContent has decoded the icons and chrome has
811 // processed it. This needs to be in a loop since the renderer runs in a
812 // different process.
813 while (test_observer.icon_updates() < 3) {
814 base::RunLoop run_loop;
815 run_loop.RunUntilIdle();
818 // This test creates one shell window and one panel window.
819 int launcher_item_count = launcher_model()->item_count();
820 ASSERT_EQ(base_launcher_item_count + 2, launcher_item_count);
821 // The Panel will be the last item, the app second-to-last.
822 const ash::LauncherItem& app_item =
823 launcher_model()->items()[launcher_item_count - 2];
824 const ash::LauncherItem& panel_item =
825 launcher_model()->items()[launcher_item_count - 1];
826 const LauncherItemController* app_item_controller =
827 GetItemController(app_item.id);
828 const LauncherItemController* panel_item_controller =
829 GetItemController(panel_item.id);
830 // Icons for Apps are set by the ShellWindowLauncherController, so
831 // image_set_by_controller() should be set.
832 EXPECT_TRUE(app_item_controller->image_set_by_controller());
833 EXPECT_TRUE(panel_item_controller->image_set_by_controller());
834 // Ensure icon heights are correct (see test.js in app_icon/ test directory)
835 EXPECT_EQ(48, app_item.image.height());
836 EXPECT_EQ(64, panel_item.image.height());
839 // Test that we can launch an app with a shortcut.
840 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchPinned) {
841 TabStripModel* tab_strip = browser()->tab_strip_model();
842 int tab_count = tab_strip->count();
843 ash::LauncherID shortcut_id = CreateShortcut("app1");
844 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
845 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
846 EXPECT_EQ(++tab_count, tab_strip->count());
847 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
848 WebContents* tab = tab_strip->GetActiveWebContents();
849 content::WebContentsDestroyedWatcher destroyed_watcher(tab);
850 browser()->tab_strip_model()->CloseSelectedTabs();
851 destroyed_watcher.Wait();
852 EXPECT_EQ(--tab_count, tab_strip->count());
853 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
856 // Launch the app first and then create the shortcut.
857 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchUnpinned) {
858 TabStripModel* tab_strip = browser()->tab_strip_model();
859 int tab_count = tab_strip->count();
860 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB,
862 EXPECT_EQ(++tab_count, tab_strip->count());
863 ash::LauncherID shortcut_id = CreateShortcut("app1");
864 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
865 WebContents* tab = tab_strip->GetActiveWebContents();
866 content::WebContentsDestroyedWatcher destroyed_watcher(tab);
867 browser()->tab_strip_model()->CloseSelectedTabs();
868 destroyed_watcher.Wait();
869 EXPECT_EQ(--tab_count, tab_strip->count());
870 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
873 // Launches an app in the background and then tries to open it. This is test for
875 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchInBackground) {
876 TabStripModel* tab_strip = browser()->tab_strip_model();
877 int tab_count = tab_strip->count();
878 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB,
880 EXPECT_EQ(++tab_count, tab_strip->count());
881 ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id(),
882 ash::LAUNCH_FROM_UNKNOWN,
886 // Confirm that clicking a icon for an app running in one of 2 maxmized windows
887 // activates the right window.
888 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchMaximized) {
889 aura::Window* window1 = browser()->window()->GetNativeWindow();
890 ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1);
891 window1_state->Maximize();
892 content::WindowedNotificationObserver open_observer(
893 chrome::NOTIFICATION_BROWSER_WINDOW_READY,
894 content::NotificationService::AllSources());
895 chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH);
896 open_observer.Wait();
897 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr();
898 aura::Window* window2 = browser2->window()->GetNativeWindow();
899 TabStripModel* tab_strip = browser2->tab_strip_model();
900 int tab_count = tab_strip->count();
901 ash::wm::GetWindowState(window2)->Maximize();
903 ash::LauncherID shortcut_id = CreateShortcut("app1");
904 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
905 EXPECT_EQ(++tab_count, tab_strip->count());
906 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
909 window1_state->Activate();
910 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
912 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
913 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
916 // Activating the same app multiple times should launch only a single copy.
917 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateApp) {
918 TabStripModel* tab_strip = browser()->tab_strip_model();
919 int tab_count = tab_strip->count();
920 const Extension* extension =
921 LoadExtension(test_data_dir_.AppendASCII("app1"));
923 ChromeLauncherController::instance()->ActivateApp(extension->id(),
924 ash::LAUNCH_FROM_UNKNOWN,
926 EXPECT_EQ(++tab_count, tab_strip->count());
927 ChromeLauncherController::instance()->ActivateApp(extension->id(),
928 ash::LAUNCH_FROM_UNKNOWN,
930 EXPECT_EQ(tab_count, tab_strip->count());
933 // Launching the same app multiple times should launch a copy for each call.
934 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchApp) {
935 TabStripModel* tab_strip = browser()->tab_strip_model();
936 int tab_count = tab_strip->count();
937 const Extension* extension =
938 LoadExtension(test_data_dir_.AppendASCII("app1"));
940 ChromeLauncherController::instance()->LaunchApp(extension->id(),
941 ash::LAUNCH_FROM_UNKNOWN,
943 EXPECT_EQ(++tab_count, tab_strip->count());
944 ChromeLauncherController::instance()->LaunchApp(extension->id(),
945 ash::LAUNCH_FROM_UNKNOWN,
947 EXPECT_EQ(++tab_count, tab_strip->count());
950 // Launch 2 apps and toggle which is active.
951 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleApps) {
952 int item_count = model_->item_count();
953 TabStripModel* tab_strip = browser()->tab_strip_model();
954 int tab_count = tab_strip->count();
955 ash::LauncherID shortcut1 = CreateShortcut("app1");
956 EXPECT_EQ(++item_count, model_->item_count());
957 ash::LauncherID shortcut2 = CreateShortcut("app2");
958 EXPECT_EQ(++item_count, model_->item_count());
961 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
962 EXPECT_EQ(++tab_count, tab_strip->count());
963 WebContents* tab1 = tab_strip->GetActiveWebContents();
964 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
966 // Launch second app.
967 ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
968 EXPECT_EQ(++tab_count, tab_strip->count());
969 WebContents* tab2 = tab_strip->GetActiveWebContents();
970 ASSERT_NE(tab1, tab2);
971 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
972 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
974 // Reactivate first app.
975 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
976 EXPECT_EQ(tab_count, tab_strip->count());
977 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
978 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
979 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
981 // Open second tab for second app. This should activate it.
982 ui_test_utils::NavigateToURLWithDisposition(
984 GURL("http://www.example.com/path3/foo.html"),
987 EXPECT_EQ(++tab_count, tab_strip->count());
988 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
989 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
991 // Reactivate first app.
992 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
993 EXPECT_EQ(tab_count, tab_strip->count());
994 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
995 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
996 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
998 // And second again. This time the second tab should become active.
999 ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
1000 EXPECT_EQ(tab_count, tab_strip->count());
1001 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2);
1002 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
1003 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
1006 // Confirm that a page can be navigated from and to while maintaining the
1007 // correct running state.
1008 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, Navigation) {
1009 ash::LauncherID shortcut_id = CreateShortcut("app1");
1010 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
1011 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1012 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
1015 ui_test_utils::NavigateToURL(
1016 browser(), GURL("http://www.example.com/path0/bar.html"));
1017 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
1020 ui_test_utils::NavigateToURL(
1021 browser(), GURL("http://www.example.com/path1/foo.html"));
1022 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
1025 // Confirm that a tab can be moved between browsers while maintaining the
1026 // correct running state.
1027 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, TabDragAndDrop) {
1028 TabStripModel* tab_strip_model1 = browser()->tab_strip_model();
1029 EXPECT_EQ(1, tab_strip_model1->count());
1030 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
1031 EXPECT_TRUE(browser_index >= 0);
1032 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
1034 // Create a shortcut for app1.
1035 ash::LauncherID shortcut_id = CreateShortcut("app1");
1036 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1037 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
1039 // Activate app1 and check its item status.
1040 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1041 EXPECT_EQ(2, tab_strip_model1->count());
1042 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
1043 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
1045 // Create a new browser with blank tab.
1046 Browser* browser2 = CreateBrowser(profile());
1047 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
1048 TabStripModel* tab_strip_model2 = browser2->tab_strip_model();
1049 EXPECT_EQ(1, tab_strip_model2->count());
1050 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1051 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
1053 // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an
1054 // active tab at index 1 to |tab_strip_model2|.
1055 content::WebContents* detached_tab = tab_strip_model1->DetachWebContentsAt(1);
1056 tab_strip_model2->InsertWebContentsAt(1,
1058 TabStripModel::ADD_ACTIVE);
1059 EXPECT_EQ(1, tab_strip_model1->count());
1060 EXPECT_EQ(2, tab_strip_model2->count());
1061 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
1062 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
1064 tab_strip_model1->CloseAllTabs();
1065 tab_strip_model2->CloseAllTabs();
1068 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleOwnedTabs) {
1069 TabStripModel* tab_strip = browser()->tab_strip_model();
1070 int tab_count = tab_strip->count();
1071 ash::LauncherID shortcut_id = CreateShortcut("app1");
1072 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1073 EXPECT_EQ(++tab_count, tab_strip->count());
1074 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1075 WebContents* first_tab = tab_strip->GetActiveWebContents();
1077 // Create new tab owned by app.
1078 ui_test_utils::NavigateToURLWithDisposition(
1080 GURL("http://www.example.com/path2/bar.html"),
1082 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1083 EXPECT_EQ(++tab_count, tab_strip->count());
1084 // Confirm app is still active.
1085 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1087 // Create new tab not owned by app.
1088 ui_test_utils::NavigateToURLWithDisposition(
1090 GURL("http://www.example.com/path3/foo.html"),
1093 EXPECT_EQ(++tab_count, tab_strip->count());
1094 // No longer active.
1095 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
1097 // Activating app makes first tab active again.
1098 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1099 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1100 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
1103 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilter) {
1104 TabStripModel* tab_strip = browser()->tab_strip_model();
1105 int tab_count = tab_strip->count();
1106 ash::LauncherID shortcut_id = CreateShortcut("app1");
1107 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1108 EXPECT_EQ(++tab_count, tab_strip->count());
1109 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1110 WebContents* first_tab = tab_strip->GetActiveWebContents();
1112 controller_->SetRefocusURLPatternForTest(
1113 shortcut_id, GURL("http://www.example.com/path1/*"));
1114 // Create new tab owned by app.
1115 ui_test_utils::NavigateToURLWithDisposition(
1117 GURL("http://www.example.com/path2/bar.html"),
1119 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1120 EXPECT_EQ(++tab_count, tab_strip->count());
1121 // Confirm app is still active.
1122 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1124 // Create new tab not owned by app.
1125 ui_test_utils::NavigateToURLWithDisposition(
1127 GURL("http://www.example.com/path3/foo.html"),
1130 EXPECT_EQ(++tab_count, tab_strip->count());
1131 // No longer active.
1132 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
1134 // Activating app makes first tab active again, because second tab isn't
1135 // in its refocus url path.
1136 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1137 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1138 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
1141 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilterLaunch) {
1142 TabStripModel* tab_strip = browser()->tab_strip_model();
1143 int tab_count = tab_strip->count();
1144 ash::LauncherID shortcut_id = CreateShortcut("app1");
1145 controller_->SetRefocusURLPatternForTest(
1146 shortcut_id, GURL("http://www.example.com/path1/*"));
1149 ui_test_utils::NavigateToURLWithDisposition(
1151 GURL("http://www.example2.com/path2/bar.html"),
1153 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1154 EXPECT_EQ(++tab_count, tab_strip->count());
1155 WebContents* first_tab = tab_strip->GetActiveWebContents();
1156 // Confirm app is not active.
1157 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1159 // Activating app should launch new tab, because second tab isn't
1160 // in its refocus url path.
1161 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
1162 EXPECT_EQ(++tab_count, tab_strip->count());
1163 WebContents* second_tab = tab_strip->GetActiveWebContents();
1164 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1165 EXPECT_NE(first_tab, second_tab);
1166 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab);
1169 // Check the launcher activation state for applications and browser.
1170 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivationStateCheck) {
1171 TabStripModel* tab_strip = browser()->tab_strip_model();
1172 // Get the browser item index
1173 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
1174 EXPECT_TRUE(browser_index >= 0);
1176 // Even though we are just comming up, the browser should be active.
1177 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1179 ash::LauncherID shortcut_id = CreateShortcut("app1");
1180 controller_->SetRefocusURLPatternForTest(
1181 shortcut_id, GURL("http://www.example.com/path1/*"));
1183 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1184 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1186 // Create new tab which would be the running app.
1187 ui_test_utils::NavigateToURLWithDisposition(
1189 GURL("http://www.example.com/path1/bar.html"),
1191 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1193 // There should never be two items active at the same time.
1194 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1195 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
1197 tab_strip->ActivateTabAt(0, false);
1198 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
1199 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1201 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
1202 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1203 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
1205 ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow());
1206 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1207 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
1210 // Check that the launcher activation state for a V1 application stays closed
1211 // even after an asynchronous browser event comes in after the tab got
1213 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AsyncActivationStateCheck) {
1214 TabStripModel* tab_strip = browser()->tab_strip_model();
1216 ash::LauncherID shortcut_id = CreateShortcut("app1");
1217 controller_->SetRefocusURLPatternForTest(
1218 shortcut_id, GURL("http://www.example.com/path1/*"));
1220 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1222 // Create new tab which would be the running app.
1223 ui_test_utils::NavigateToURLWithDisposition(
1225 GURL("http://www.example.com/path1/bar.html"),
1227 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1229 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1230 // To address the issue of crbug.com/174050, the tab we are about to close
1231 // has to be active.
1232 tab_strip->ActivateTabAt(1, false);
1233 EXPECT_EQ(1, tab_strip->active_index());
1235 // Close the web contents.
1236 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
1237 // The status should now be set to closed.
1238 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
1241 // Checks that a windowed application does not add an item to the browser list.
1242 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
1243 WindowedAppDoesNotAddToBrowser) {
1244 // Get the number of items in the browser menu.
1245 size_t items = NumberOfDetectedLauncherBrowsers(false);
1246 size_t running_browser = chrome::GetTotalBrowserCount();
1247 EXPECT_EQ(0u, items);
1248 EXPECT_EQ(0u, running_browser);
1250 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_WINDOW, NEW_WINDOW);
1252 // No new browser should get detected, even though one more is running.
1253 EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false));
1254 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount());
1256 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW);
1258 // A new browser should get detected and one more should be running.
1259 EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u);
1260 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount());
1263 // Checks the functionality to enumerate all browsers vs. all tabs.
1264 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
1265 EnumerateALlBrowsersAndTabs) {
1266 // Create at least one browser.
1267 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW);
1268 size_t browsers = NumberOfDetectedLauncherBrowsers(false);
1269 size_t tabs = NumberOfDetectedLauncherBrowsers(true);
1271 // Create a second browser.
1272 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW);
1274 EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false));
1275 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true));
1277 // Create only a tab.
1278 LoadAndLaunchExtension("app1",
1279 extension_misc::LAUNCH_TAB,
1280 NEW_FOREGROUND_TAB);
1282 EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false));
1283 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true));
1286 // Check that the keyboard activation of a launcher item tabs properly through
1287 // the items at hand.
1288 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AltNumberTabsTabbing) {
1289 TabStripModel* tab_strip = browser()->tab_strip_model();
1291 ash::LauncherID shortcut_id = CreateShortcut("app");
1292 controller_->SetRefocusURLPatternForTest(
1293 shortcut_id, GURL("http://www.example.com/path/*"));
1294 std::string url = "http://www.example.com/path/bla";
1296 int shortcut_index = model_->ItemIndexByID(shortcut_id);
1298 // Create an application handled browser tab.
1299 ui_test_utils::NavigateToURLWithDisposition(
1303 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1305 content::WebContents* content1 = tab_strip->GetActiveWebContents();
1307 // Create some other browser tab.
1308 ui_test_utils::NavigateToURLWithDisposition(
1310 GURL("http://www.test.com"),
1312 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1313 content::WebContents* content1a = tab_strip->GetActiveWebContents();
1315 // Make sure that the active tab is now our handled tab.
1316 EXPECT_NE(content1a, content1);
1318 // The active tab should still be the unnamed tab. Then we switch and reach
1319 // the first app and stay there.
1320 EXPECT_EQ(content1a, tab_strip->GetActiveWebContents());
1321 ActivateLauncherItem(shortcut_index);
1322 EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
1323 ActivateLauncherItem(shortcut_index);
1324 EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
1326 ui_test_utils::NavigateToURLWithDisposition(
1330 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1331 content::WebContents* content2 = tab_strip->GetActiveWebContents();
1333 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
1334 ActivateLauncherItem(shortcut_index);
1335 EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents());
1336 ActivateLauncherItem(shortcut_index);
1337 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
1340 // Check that the keyboard activation of a launcher item tabs properly through
1341 // the items at hand.
1342 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest,
1343 AltNumberAppsTabbing) {
1345 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
1346 ui::BaseWindow* window1 = CreateShellWindow(extension1)->GetBaseWindow();
1347 const ash::LauncherItem& item1 = GetLastLauncherItem();
1348 ash::LauncherID app_id = item1.id;
1349 int app_index = launcher_model()->ItemIndexByID(app_id);
1351 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
1352 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
1354 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
1355 ui::BaseWindow* window2 = CreateShellWindow(extension2)->GetBaseWindow();
1357 // By now the browser should be active. Issue Alt keystrokes several times to
1358 // see that we stay on that application.
1359 EXPECT_TRUE(window2->IsActive());
1360 ActivateLauncherItem(app_index);
1361 EXPECT_TRUE(window1->IsActive());
1362 ActivateLauncherItem(app_index);
1363 EXPECT_TRUE(window1->IsActive());
1365 ui::BaseWindow* window1a = CreateShellWindow(extension1)->GetBaseWindow();
1367 EXPECT_TRUE(window1a->IsActive());
1368 EXPECT_FALSE(window1->IsActive());
1369 ActivateLauncherItem(app_index);
1370 EXPECT_TRUE(window1->IsActive());
1371 ActivateLauncherItem(app_index);
1372 EXPECT_TRUE(window1a->IsActive());
1375 // Test that we can launch a platform app panel and get a running item.
1376 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) {
1377 int item_count = launcher_model()->item_count();
1378 const Extension* extension = LoadAndLaunchPlatformApp("launch");
1379 ShellWindow::CreateParams params;
1380 params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
1381 params.focused = false;
1382 ShellWindow* window = CreateShellWindowFromParams(extension, params);
1384 ASSERT_EQ(item_count, launcher_model()->item_count());
1385 const ash::LauncherItem& item = GetLastLauncherPanelItem();
1386 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
1387 // Opening a panel does not activate it.
1388 EXPECT_EQ(ash::STATUS_RUNNING, item.status);
1389 CloseShellWindow(window);
1391 EXPECT_EQ(item_count, launcher_model()->item_count());
1394 // Test attention states of windows.
1395 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) {
1396 const Extension* extension = LoadAndLaunchPlatformApp("launch");
1397 ShellWindow::CreateParams params;
1398 params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
1399 params.focused = false;
1400 ShellWindow* panel = CreateShellWindowFromParams(extension, params);
1401 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
1402 // Panels should not be active by default.
1403 EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
1404 // Confirm that a controller item was created and is the correct state.
1405 const ash::LauncherItem& item = GetLastLauncherPanelItem();
1406 LauncherItemController* item_controller = GetItemController(item.id);
1407 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
1408 EXPECT_EQ(ash::STATUS_RUNNING, item.status);
1409 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item_controller->type());
1411 // App windows should go to attention state.
1412 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
1413 EXPECT_EQ(ash::STATUS_ATTENTION, item.status);
1415 // Click the item and confirm that the panel is activated.
1416 TestEvent click_event(ui::ET_MOUSE_PRESSED);
1417 item_controller->ItemSelected(click_event);
1418 EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
1419 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
1421 // Active windows don't show attention.
1422 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
1423 EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
1426 // Checks that the browser Alt "tabbing" is properly done.
1427 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
1428 AltNumberBrowserTabbing) {
1429 // Get the number of items in the browser menu.
1430 EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
1431 // The first activation should create a browser at index 1 (App List @ 0).
1432 launcher_->ActivateLauncherItem(1);
1433 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
1434 // A second activation should not create a new instance.
1435 launcher_->ActivateLauncherItem(1);
1436 Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
1437 EXPECT_TRUE(browser1);
1438 aura::Window* window1 = browser1->window()->GetNativeWindow();
1439 Browser* browser2 = CreateBrowser(profile());
1440 aura::Window* window2 = browser2->window()->GetNativeWindow();
1442 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
1443 EXPECT_NE(window1, window2);
1444 EXPECT_EQ(window2, ash::wm::GetActiveWindow());
1446 // Activate multiple times the switcher to see that the windows get activated.
1447 launcher_->ActivateLauncherItem(1);
1448 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
1449 launcher_->ActivateLauncherItem(1);
1450 EXPECT_EQ(window2, ash::wm::GetActiveWindow());
1452 // Create a third browser - make sure that we do not toggle simply between
1454 Browser* browser3 = CreateBrowser(profile());
1455 aura::Window* window3 = browser3->window()->GetNativeWindow();
1457 EXPECT_EQ(3u, chrome::GetTotalBrowserCount());
1458 EXPECT_NE(window1, window3);
1459 EXPECT_NE(window2, window3);
1460 EXPECT_EQ(window3, ash::wm::GetActiveWindow());
1462 launcher_->ActivateLauncherItem(1);
1463 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
1464 launcher_->ActivateLauncherItem(1);
1465 EXPECT_EQ(window2, ash::wm::GetActiveWindow());
1466 launcher_->ActivateLauncherItem(1);
1467 EXPECT_EQ(window3, ash::wm::GetActiveWindow());
1468 launcher_->ActivateLauncherItem(1);
1469 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
1471 // Create anther app and make sure that none of our browsers is active.
1472 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW);
1473 EXPECT_NE(window1, ash::wm::GetActiveWindow());
1474 EXPECT_NE(window2, ash::wm::GetActiveWindow());
1476 // After activation our browser should be active again.
1477 launcher_->ActivateLauncherItem(1);
1478 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
1481 // Checks that after a session restore, we do not start applications on an
1483 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateAfterSessionRestore) {
1484 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
1486 // Create a known application.
1487 ash::LauncherID shortcut_id = CreateShortcut("app1");
1489 // Create a new browser - without activating it - and load an "app" into it.
1490 Browser::CreateParams params =
1491 Browser::CreateParams(profile(), chrome::GetActiveDesktop());
1492 params.initial_show_state = ui::SHOW_STATE_INACTIVE;
1493 Browser* browser2 = new Browser(params);
1494 controller_->SetRefocusURLPatternForTest(
1495 shortcut_id, GURL("http://www.example.com/path/*"));
1496 std::string url = "http://www.example.com/path/bla";
1497 ui_test_utils::NavigateToURLWithDisposition(
1501 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1503 // Remember the number of tabs for each browser.
1504 TabStripModel* tab_strip = browser()->tab_strip_model();
1505 int tab_count1 = tab_strip->count();
1506 TabStripModel* tab_strip2 = browser2->tab_strip_model();
1507 int tab_count2 = tab_strip2->count();
1509 // Check that we have two browsers and the inactive browser remained inactive.
1510 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
1511 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()),
1513 // Check that the LRU browser list does only contain the original browser.
1514 BrowserList* ash_browser_list =
1515 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1516 BrowserList::const_reverse_iterator it =
1517 ash_browser_list->begin_last_active();
1518 EXPECT_EQ(*it, browser());
1520 EXPECT_EQ(it, ash_browser_list->end_last_active());
1522 // Now request to either activate an existing app or create a new one.
1523 LauncherItemController* item_controller =
1524 controller_->GetLauncherItemController(shortcut_id);
1525 item_controller->ItemSelected(ui::KeyEvent(ui::ET_KEY_RELEASED,
1530 // Check that we have set focus on the existing application and nothing new
1532 EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
1533 EXPECT_EQ(tab_count1, tab_strip->count());
1534 EXPECT_EQ(tab_count2, tab_strip2->count());
1535 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()),
1539 // Do various drag and drop interaction tests between the application list and
1541 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragAndDrop) {
1542 // Get a number of interfaces we need.
1543 aura::test::EventGenerator generator(
1544 ash::Shell::GetPrimaryRootWindow(), gfx::Point());
1545 ash::test::ShelfViewTestAPI test(
1546 ash::test::LauncherTestAPI(launcher_).shelf_view());
1547 AppListService* service = AppListService::Get(chrome::GetActiveDesktop());
1549 // There should be two items in our launcher by this time.
1550 EXPECT_EQ(2, model_->item_count());
1551 EXPECT_FALSE(service->IsAppListVisible());
1553 // Open the app list menu and check that the drag and drop host was set.
1554 gfx::Rect app_list_bounds =
1555 test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen();
1556 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(),
1557 app_list_bounds.CenterPoint().y());
1558 base::MessageLoop::current()->RunUntilIdle();
1559 generator.ClickLeftButton();
1561 EXPECT_TRUE(service->IsAppListVisible());
1562 app_list::AppsGridView* grid_view =
1563 ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).
1565 ASSERT_TRUE(grid_view);
1566 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test());
1568 // There should be 2 items in our application list.
1569 const views::ViewModel* vm_grid = grid_view->view_model_for_test();
1570 EXPECT_EQ(2, vm_grid->view_size());
1572 // Test #1: Drag an app list which does not exist yet item into the
1573 // launcher. Keeping it dragged, see that a new item gets created. Continuing
1574 // to drag it out should remove it again.
1576 // Get over item #1 of the application list and press the mouse button.
1577 views::View* item1 = vm_grid->view_at(1);
1578 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen();
1579 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1580 bounds_grid_1.CenterPoint().y());
1581 base::MessageLoop::current()->RunUntilIdle();
1582 generator.PressLeftButton();
1584 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1586 // Drag the item into the launcher and check that a new item gets created.
1587 const views::ViewModel* vm_launcher =
1588 test.shelf_view()->view_model_for_test();
1589 views::View* launcher1 = vm_launcher->view_at(1);
1590 gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen();
1591 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
1592 bounds_launcher_1.CenterPoint().y());
1593 base::MessageLoop::current()->RunUntilIdle();
1595 // Check that a new item got created.
1596 EXPECT_EQ(3, model_->item_count());
1597 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1599 // Move it where the item originally was and check that it disappears again.
1600 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1601 bounds_grid_1.CenterPoint().y());
1602 base::MessageLoop::current()->RunUntilIdle();
1603 EXPECT_EQ(2, model_->item_count());
1604 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1606 // Dropping it should keep the launcher as it originally was.
1607 generator.ReleaseLeftButton();
1608 base::MessageLoop::current()->RunUntilIdle();
1609 EXPECT_EQ(2, model_->item_count());
1610 // There are a few animations which need finishing before we can continue.
1611 test.RunMessageLoopUntilAnimationsDone();
1612 // Move the mouse outside of the launcher.
1613 generator.MoveMouseTo(0, 0);
1615 // Test #2: Check that the unknown item dropped into the launcher will
1616 // create a new item.
1617 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1618 bounds_grid_1.CenterPoint().y());
1619 generator.PressLeftButton();
1620 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
1621 bounds_launcher_1.CenterPoint().y());
1622 base::MessageLoop::current()->RunUntilIdle();
1623 EXPECT_EQ(3, model_->item_count());
1624 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1625 generator.ReleaseLeftButton();
1626 base::MessageLoop::current()->RunUntilIdle();
1627 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1628 EXPECT_EQ(3, model_->item_count()); // It should be still there.
1629 test.RunMessageLoopUntilAnimationsDone();
1631 // Test #3: Check that the now known item dropped into the launcher will
1632 // not create a new item.
1633 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1634 bounds_grid_1.CenterPoint().y());
1635 generator.PressLeftButton();
1636 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
1637 bounds_launcher_1.CenterPoint().y());
1638 base::MessageLoop::current()->RunUntilIdle();
1639 EXPECT_EQ(3, model_->item_count()); // No new item got added.
1640 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1641 generator.ReleaseLeftButton();
1642 base::MessageLoop::current()->RunUntilIdle();
1643 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1644 EXPECT_EQ(3, model_->item_count()); // And it remains that way.
1646 // Test #4: Check that by pressing ESC the operation gets cancelled.
1647 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1648 bounds_grid_1.CenterPoint().y());
1649 generator.PressLeftButton();
1650 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
1651 bounds_launcher_1.CenterPoint().y());
1652 base::MessageLoop::current()->RunUntilIdle();
1653 // Issue an ESC and see that the operation gets cancelled.
1654 generator.PressKey(ui::VKEY_ESCAPE, 0);
1655 generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
1656 EXPECT_FALSE(grid_view->dragging());
1657 EXPECT_FALSE(grid_view->has_dragged_view());
1658 generator.ReleaseLeftButton();
1661 // Do tests for removal of items from the shelf by dragging.
1662 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragOffShelf) {
1663 aura::test::EventGenerator generator(
1664 ash::Shell::GetPrimaryRootWindow(), gfx::Point());
1665 ash::test::ShelfViewTestAPI test(
1666 ash::test::LauncherTestAPI(launcher_).shelf_view());
1668 // Create a known application and check that we have 3 items in the launcher.
1669 CreateShortcut("app1");
1670 EXPECT_EQ(3, model_->item_count());
1672 // Test #1: Ripping out the browser item should not change anything.
1673 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
1674 EXPECT_LE(0, browser_index);
1675 RipOffItemIndex(browser_index, &generator, &test, RIP_OFF_ITEM);
1676 // => It should not have been removed and the location should be unchanged.
1677 EXPECT_EQ(3, model_->item_count());
1678 EXPECT_EQ(browser_index,
1679 GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT));
1680 // Make sure that the hide state has been unset after the snap back animation
1682 ash::internal::LauncherButton* button = test.GetButton(browser_index);
1683 EXPECT_FALSE(button->state() & ash::internal::LauncherButton::STATE_HIDDEN);
1685 // Test #2: Ripping out the application and canceling the operation should
1686 // not change anything.
1687 int app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
1688 EXPECT_LE(0, app_index);
1689 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_CANCEL);
1690 // => It should not have been removed and the location should be unchanged.
1691 ASSERT_EQ(3, model_->item_count());
1692 EXPECT_EQ(app_index, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
1694 // Test #3: Ripping out the application and moving it back in should not
1696 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_RETURN);
1697 // => It should not have been removed and the location should be unchanged.
1698 ASSERT_EQ(3, model_->item_count());
1699 // Through the operation the index might have changed.
1700 app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
1702 // Test #4: Ripping out the application should remove the item.
1703 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
1704 // => It should not have been removed and the location should be unchanged.
1705 EXPECT_EQ(2, model_->item_count());
1706 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
1708 // Test #5: Uninstalling an application while it is being ripped off should
1710 ash::LauncherID app_id = CreateShortcut("app2");
1711 int app2_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
1712 EXPECT_EQ(3, model_->item_count()); // And it remains that way.
1713 RipOffItemIndex(app2_index,
1716 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE);
1717 RemoveShortcut(app_id);
1718 EXPECT_EQ(2, model_->item_count()); // The item should now be gone.
1719 generator.ReleaseLeftButton();
1720 base::MessageLoop::current()->RunUntilIdle();
1721 EXPECT_EQ(2, model_->item_count()); // And it remains that way.
1722 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
1724 // Test #6: Ripping out the application when the overflow button exists.
1725 // After ripping out, overflow button should be removed.
1726 int items_added = 0;
1727 EXPECT_FALSE(test.IsOverflowButtonVisible());
1729 // Create fake app shortcuts until overflow button is created.
1730 while (!test.IsOverflowButtonVisible()) {
1731 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
1732 PinFakeApp(fake_app_id);
1735 ASSERT_LT(items_added, 10000);
1737 // Make one more item after creating a overflow button.
1738 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
1739 PinFakeApp(fake_app_id);
1741 int total_count = model_->item_count();
1742 app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
1743 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
1744 // When an item is ripped off from the launcher that has overflow button
1745 // (see crbug.com/3050787), it was hidden accidentally and was then
1746 // suppressing any further events. If handled correctly the operation will
1747 // however correctly done and the item will get removed (as well as the
1748 // overflow button).
1749 EXPECT_EQ(total_count - 1, model_->item_count());
1750 EXPECT_TRUE(test.IsOverflowButtonVisible());
1752 // Rip off again and the overflow button should has disappeared.
1753 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
1754 EXPECT_EQ(total_count - 2, model_->item_count());
1755 EXPECT_FALSE(test.IsOverflowButtonVisible());
1758 // Check that clicking on an app launcher item launches a new browser.
1759 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ClickItem) {
1760 // Get a number of interfaces we need.
1761 aura::test::EventGenerator generator(
1762 ash::Shell::GetPrimaryRootWindow(), gfx::Point());
1763 ash::test::ShelfViewTestAPI test(
1764 ash::test::LauncherTestAPI(launcher_).shelf_view());
1765 AppListService* service = AppListService::Get(chrome::GetActiveDesktop());
1766 // There should be two items in our launcher by this time.
1767 EXPECT_EQ(2, model_->item_count());
1768 EXPECT_FALSE(service->IsAppListVisible());
1770 // Open the app list menu and check that the drag and drop host was set.
1771 gfx::Rect app_list_bounds =
1772 test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen();
1773 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(),
1774 app_list_bounds.CenterPoint().y());
1775 generator.ClickLeftButton();
1776 base::MessageLoop::current()->RunUntilIdle();
1778 EXPECT_TRUE(service->IsAppListVisible());
1779 app_list::AppsGridView* grid_view =
1780 ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).
1782 ASSERT_TRUE(grid_view);
1783 const views::ViewModel* vm_grid = grid_view->view_model_for_test();
1784 EXPECT_EQ(2, vm_grid->view_size());
1785 gfx::Rect bounds_grid_1 = vm_grid->view_at(1)->GetBoundsInScreen();
1786 // Test now that a click does create a new application tab.
1787 TabStripModel* tab_strip = browser()->tab_strip_model();
1788 int tab_count = tab_strip->count();
1789 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
1790 bounds_grid_1.CenterPoint().y());
1791 generator.ClickLeftButton();
1792 base::MessageLoop::current()->RunUntilIdle();
1793 EXPECT_EQ(tab_count + 1, tab_strip->count());
1796 // Check LauncherItemController of Browser Shortcut functionality.
1797 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
1798 BrowserShortcutLauncherItemController) {
1799 LauncherItemController* item_controller =
1800 controller_->GetBrowserShortcutLauncherItemController();
1802 // Get the number of browsers.
1803 size_t running_browser = chrome::GetTotalBrowserCount();
1804 EXPECT_EQ(0u, running_browser);
1805 EXPECT_FALSE(item_controller->IsOpen());
1807 // Activate. This creates new browser
1808 item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
1809 // New Window is created.
1810 running_browser = chrome::GetTotalBrowserCount();
1811 EXPECT_EQ(1u, running_browser);
1812 EXPECT_TRUE(item_controller->IsOpen());
1815 ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState();
1816 window_state->Minimize();
1817 EXPECT_TRUE(window_state->IsMinimized());
1819 // Activate again. This doesn't create new browser.
1820 // It activates window.
1821 item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
1822 running_browser = chrome::GetTotalBrowserCount();
1823 EXPECT_EQ(1u, running_browser);
1824 EXPECT_TRUE(item_controller->IsOpen());
1825 EXPECT_FALSE(window_state->IsMinimized());
1828 // Check that GetIDByWindow() returns |LauncherID| of the active tab.
1829 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MatchingLauncherIDandActiveTab) {
1830 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
1831 EXPECT_EQ(1, browser()->tab_strip_model()->count());
1832 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
1833 EXPECT_EQ(2, model_->item_count());
1835 aura::Window* window = browser()->window()->GetNativeWindow();
1837 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
1838 ash::LauncherID browser_id = model_->items()[browser_index].id;
1839 EXPECT_EQ(browser_id, controller_->GetIDByWindow(window));
1841 ash::LauncherID app_id = CreateShortcut("app1");
1842 EXPECT_EQ(3, model_->item_count());
1844 // Creates a new tab for "app1" and checks that GetIDByWindow() returns
1845 // |LauncherID| of "app1".
1846 ActivateLauncherItem(model_->ItemIndexByID(app_id));
1847 EXPECT_EQ(2, browser()->tab_strip_model()->count());
1848 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
1849 EXPECT_EQ(app_id, controller_->GetIDByWindow(window));
1851 // Makes tab at index 0(NTP) as an active tab and checks that GetIDByWindow()
1852 // returns |LauncherID| of browser shortcut.
1853 browser()->tab_strip_model()->ActivateTabAt(0, false);
1854 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
1855 EXPECT_EQ(browser_id, controller_->GetIDByWindow(window));
1858 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, OverflowBubble) {
1859 // Make sure to have a browser window
1860 chrome::NewTab(browser());
1863 EXPECT_FALSE(launcher_->IsShowingOverflowBubble());
1865 ash::test::ShelfViewTestAPI test(
1866 ash::test::LauncherTestAPI(launcher_).shelf_view());
1868 int items_added = 0;
1869 while (!test.IsOverflowButtonVisible()) {
1870 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
1871 PinFakeApp(fake_app_id);
1874 ASSERT_LT(items_added, 10000);
1877 // Now show overflow bubble.
1878 test.ShowOverflowBubble();
1879 EXPECT_TRUE(launcher_->IsShowingOverflowBubble());
1881 // Unpin first pinned app and there should be no crash.
1882 controller_->UnpinAppWithID(std::string("fake_app_0"));
1884 test.RunMessageLoopUntilAnimationsDone();
1885 EXPECT_FALSE(launcher_->IsShowingOverflowBubble());