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