Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc

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

Powered by Google App Engine
This is Rietveld 408576698