OLD | NEW |
| (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 } | |
OLD | NEW |