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