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

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

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

Powered by Google App Engine
This is Rietveld 408576698