OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | |
6 | |
7 #include "apps/native_app_window.h" | |
8 #include "apps/shell_window.h" | |
9 #include "apps/shell_window_registry.h" | |
10 #include "ash/ash_switches.h" | |
11 #include "ash/display/display_controller.h" | |
12 #include "ash/launcher/launcher.h" | |
13 #include "ash/launcher/launcher_model.h" | |
14 #include "ash/launcher/launcher_util.h" | |
15 #include "ash/launcher/launcher_view.h" | |
16 #include "ash/shell.h" | |
17 #include "ash/test/launcher_view_test_api.h" | |
18 #include "ash/test/shell_test_api.h" | |
19 #include "ash/wm/window_util.h" | |
20 #include "base/strings/utf_string_conversions.h" | |
21 #include "chrome/browser/apps/app_browsertest_util.h" | |
22 #include "chrome/browser/automation/automation_util.h" | |
23 #include "chrome/browser/chrome_notification_types.h" | |
24 #include "chrome/browser/extensions/extension_apitest.h" | |
25 #include "chrome/browser/extensions/extension_browsertest.h" | |
26 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
27 #include "chrome/browser/extensions/extension_service.h" | |
28 #include "chrome/browser/extensions/extension_system.h" | |
29 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
30 #include "chrome/browser/profiles/profile.h" | |
31 #include "chrome/browser/ui/app_list/app_list_service.h" | |
32 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controll
er.h" | |
33 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h" | |
34 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" | |
35 #include "chrome/browser/ui/browser.h" | |
36 #include "chrome/browser/ui/browser_commands.h" | |
37 #include "chrome/browser/ui/browser_finder.h" | |
38 #include "chrome/browser/ui/browser_list.h" | |
39 #include "chrome/browser/ui/browser_window.h" | |
40 #include "chrome/browser/ui/extensions/application_launch.h" | |
41 #include "chrome/browser/ui/host_desktop.h" | |
42 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
43 #include "chrome/common/chrome_switches.h" | |
44 #include "chrome/common/extensions/extension_constants.h" | |
45 #include "chrome/test/base/ui_test_utils.h" | |
46 #include "content/public/browser/notification_service.h" | |
47 #include "content/public/browser/notification_source.h" | |
48 #include "content/public/browser/web_contents.h" | |
49 #include "extensions/common/switches.h" | |
50 #include "testing/gtest/include/gtest/gtest.h" | |
51 #include "ui/app_list/views/apps_grid_view.h" | |
52 #include "ui/aura/test/event_generator.h" | |
53 #include "ui/aura/window.h" | |
54 #include "ui/base/events/event.h" | |
55 | |
56 using apps::ShellWindow; | |
57 using extensions::Extension; | |
58 using content::WebContents; | |
59 | |
60 namespace { | |
61 | |
62 class TestEvent : public ui::Event { | |
63 public: | |
64 explicit TestEvent(ui::EventType type) | |
65 : ui::Event(type, base::TimeDelta(), 0) { | |
66 } | |
67 virtual ~TestEvent() { | |
68 } | |
69 | |
70 private: | |
71 DISALLOW_COPY_AND_ASSIGN(TestEvent); | |
72 }; | |
73 | |
74 class TestShellWindowRegistryObserver | |
75 : public apps::ShellWindowRegistry::Observer { | |
76 public: | |
77 explicit TestShellWindowRegistryObserver(Profile* profile) | |
78 : profile_(profile), | |
79 icon_updates_(0) { | |
80 apps::ShellWindowRegistry::Get(profile_)->AddObserver(this); | |
81 } | |
82 | |
83 virtual ~TestShellWindowRegistryObserver() { | |
84 apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this); | |
85 } | |
86 | |
87 // Overridden from ShellWindowRegistry::Observer: | |
88 virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {} | |
89 | |
90 virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE { | |
91 ++icon_updates_; | |
92 } | |
93 | |
94 virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {} | |
95 | |
96 int icon_updates() { return icon_updates_; } | |
97 | |
98 private: | |
99 Profile* profile_; | |
100 int icon_updates_; | |
101 | |
102 DISALLOW_COPY_AND_ASSIGN(TestShellWindowRegistryObserver); | |
103 }; | |
104 | |
105 } // namespace | |
106 | |
107 // TODO(skuhne): Change name back to LauncherPlatformAppBrowserTest when the | |
108 // old launcher gets ripped out. | |
109 class LauncherPlatformPerAppAppBrowserTest | |
110 : public extensions::PlatformAppBrowserTest { | |
111 protected: | |
112 LauncherPlatformPerAppAppBrowserTest() | |
113 : launcher_(NULL), | |
114 controller_(NULL) { | |
115 } | |
116 | |
117 virtual ~LauncherPlatformPerAppAppBrowserTest() {} | |
118 | |
119 virtual void RunTestOnMainThreadLoop() OVERRIDE { | |
120 launcher_ = ash::Launcher::ForPrimaryDisplay(); | |
121 controller_ = | |
122 static_cast<ChromeLauncherControllerPerApp*>(launcher_->delegate()); | |
123 return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop(); | |
124 } | |
125 | |
126 ash::LauncherModel* launcher_model() { | |
127 return ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model(); | |
128 } | |
129 | |
130 ash::LauncherID CreateAppShortcutLauncherItem(const std::string& name) { | |
131 return controller_->CreateAppShortcutLauncherItem( | |
132 name, controller_->model()->item_count()); | |
133 } | |
134 | |
135 const ash::LauncherItem& GetLastLauncherItem() { | |
136 // Unless there are any panels, the item at index [count - 1] will be | |
137 // the app list, and the item at [count - 2] will be the desired item. | |
138 return launcher_model()->items()[launcher_model()->item_count() - 2]; | |
139 } | |
140 | |
141 const ash::LauncherItem& GetLastLauncherPanelItem() { | |
142 // Panels show up on the right side of the launcher, so the desired item | |
143 // will be the last one. | |
144 return launcher_model()->items()[launcher_model()->item_count() - 1]; | |
145 } | |
146 | |
147 LauncherItemController* GetItemController(ash::LauncherID id) { | |
148 return controller_->id_to_item_controller_map_[id]; | |
149 } | |
150 | |
151 // Returns the number of menu items, ignoring separators. | |
152 int GetNumApplicationMenuItems(const ash::LauncherItem& item) { | |
153 const int event_flags = 0; | |
154 scoped_ptr<ash::LauncherMenuModel> menu( | |
155 controller_->CreateApplicationMenu(item, event_flags)); | |
156 int num_items = 0; | |
157 for (int i = 0; i < menu->GetItemCount(); ++i) { | |
158 if (menu->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR) | |
159 ++num_items; | |
160 } | |
161 return num_items; | |
162 } | |
163 | |
164 // Activate the launcher item with the given |id|. | |
165 void ActivateLauncherItem(int id) { | |
166 launcher_->ActivateLauncherItem(id); | |
167 } | |
168 | |
169 ash::Launcher* launcher_; | |
170 ChromeLauncherControllerPerApp* controller_; | |
171 | |
172 private: | |
173 | |
174 DISALLOW_COPY_AND_ASSIGN(LauncherPlatformPerAppAppBrowserTest); | |
175 }; | |
176 | |
177 // TODO(skuhne): Change name back to LauncherAppBrowserTest when the | |
178 // old launcher gets ripped out. | |
179 class LauncherPerAppAppBrowserTest : public ExtensionBrowserTest { | |
180 protected: | |
181 LauncherPerAppAppBrowserTest() | |
182 : launcher_(NULL), | |
183 model_(NULL) { | |
184 } | |
185 | |
186 virtual ~LauncherPerAppAppBrowserTest() {} | |
187 | |
188 virtual void RunTestOnMainThreadLoop() OVERRIDE { | |
189 launcher_ = ash::Launcher::ForPrimaryDisplay(); | |
190 model_ = | |
191 ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model(); | |
192 return ExtensionBrowserTest::RunTestOnMainThreadLoop(); | |
193 } | |
194 | |
195 size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) { | |
196 ChromeLauncherControllerPerApp* controller = | |
197 static_cast<ChromeLauncherControllerPerApp*>(launcher_->delegate()); | |
198 LauncherItemController* item_controller = | |
199 controller->GetBrowserShortcutLauncherItemController(); | |
200 int items = item_controller->GetApplicationList( | |
201 show_all_tabs ? ui::EF_SHIFT_DOWN : 0).size(); | |
202 // If we have at least one item, we have also a title which we remove here. | |
203 return items ? (items - 1) : 0; | |
204 } | |
205 | |
206 const Extension* LoadAndLaunchExtension( | |
207 const char* name, | |
208 extension_misc::LaunchContainer container, | |
209 WindowOpenDisposition disposition) { | |
210 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name))); | |
211 | |
212 ExtensionService* service = extensions::ExtensionSystem::Get( | |
213 profile())->extension_service(); | |
214 const Extension* extension = | |
215 service->GetExtensionById(last_loaded_extension_id_, false); | |
216 EXPECT_TRUE(extension); | |
217 | |
218 chrome::OpenApplication(chrome::AppLaunchParams(profile(), | |
219 extension, | |
220 container, | |
221 disposition)); | |
222 return extension; | |
223 } | |
224 | |
225 ash::LauncherID CreateShortcut(const char* name) { | |
226 ExtensionService* service = extensions::ExtensionSystem::Get( | |
227 profile())->extension_service(); | |
228 LoadExtension(test_data_dir_.AppendASCII(name)); | |
229 | |
230 // First get app_id. | |
231 const Extension* extension = | |
232 service->GetExtensionById(last_loaded_extension_id_, false); | |
233 const std::string app_id = extension->id(); | |
234 | |
235 // Then create a shortcut. | |
236 ChromeLauncherController* controller = | |
237 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
238 int item_count = model_->item_count(); | |
239 ash::LauncherID shortcut_id = controller->CreateAppShortcutLauncherItem( | |
240 app_id, | |
241 item_count); | |
242 controller->PersistPinnedState(); | |
243 EXPECT_EQ(++item_count, model_->item_count()); | |
244 const ash::LauncherItem& item = *model_->ItemByID(shortcut_id); | |
245 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
246 return item.id; | |
247 } | |
248 | |
249 // Activate the launcher item with the given |id|. | |
250 void ActivateLauncherItem(int id) { | |
251 launcher_->ActivateLauncherItem(id); | |
252 } | |
253 | |
254 ash::Launcher* launcher_; | |
255 ash::LauncherModel* model_; | |
256 | |
257 private: | |
258 | |
259 DISALLOW_COPY_AND_ASSIGN(LauncherPerAppAppBrowserTest); | |
260 }; | |
261 | |
262 // TODO(skuhne): Change name to LauncherAppBrowserTestNoBrowser when the | |
263 // old launcher gets ripped out. | |
264 class LauncherPerAppAppBrowserTestNoDefaultBrowser | |
265 : public LauncherPerAppAppBrowserTest { | |
266 protected: | |
267 LauncherPerAppAppBrowserTestNoDefaultBrowser() {} | |
268 virtual ~LauncherPerAppAppBrowserTestNoDefaultBrowser() {} | |
269 | |
270 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
271 LauncherPerAppAppBrowserTest::SetUpCommandLine(command_line); | |
272 command_line->AppendSwitch(switches::kNoStartupWindow); | |
273 } | |
274 | |
275 private: | |
276 | |
277 DISALLOW_COPY_AND_ASSIGN(LauncherPerAppAppBrowserTestNoDefaultBrowser); | |
278 }; | |
279 | |
280 // Since the default for minimizing on click might change, I added both classes | |
281 // to either get the minimize on click or not. | |
282 class LauncherPerAppAppBrowserNoMinimizeOnClick | |
283 : public LauncherPlatformPerAppAppBrowserTest { | |
284 protected: | |
285 LauncherPerAppAppBrowserNoMinimizeOnClick() {} | |
286 virtual ~LauncherPerAppAppBrowserNoMinimizeOnClick() {} | |
287 | |
288 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
289 LauncherPlatformPerAppAppBrowserTest::SetUpCommandLine(command_line); | |
290 command_line->AppendSwitch( | |
291 switches::kDisableMinimizeOnSecondLauncherItemClick); | |
292 } | |
293 | |
294 private: | |
295 | |
296 DISALLOW_COPY_AND_ASSIGN(LauncherPerAppAppBrowserNoMinimizeOnClick); | |
297 }; | |
298 | |
299 typedef LauncherPlatformPerAppAppBrowserTest | |
300 LauncherPerAppAppBrowserMinimizeOnClick; | |
301 | |
302 // Test that we can launch a platform app and get a running item. | |
303 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, LaunchUnpinned) { | |
304 int item_count = launcher_model()->item_count(); | |
305 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
306 ShellWindow* window = CreateShellWindow(extension); | |
307 ++item_count; | |
308 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
309 const ash::LauncherItem& item = GetLastLauncherItem(); | |
310 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); | |
311 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
312 CloseShellWindow(window); | |
313 --item_count; | |
314 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
315 } | |
316 | |
317 // Test that we can launch a platform app that already has a shortcut. | |
318 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, LaunchPinned) { | |
319 int item_count = launcher_model()->item_count(); | |
320 | |
321 // First get app_id. | |
322 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
323 const std::string app_id = extension->id(); | |
324 | |
325 // Then create a shortcut. | |
326 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); | |
327 ++item_count; | |
328 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
329 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id); | |
330 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
331 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
332 | |
333 // Open a window. Confirm the item is now running. | |
334 ShellWindow* window = CreateShellWindow(extension); | |
335 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
336 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
337 item = *launcher_model()->ItemByID(shortcut_id); | |
338 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
339 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
340 | |
341 // Then close it, make sure there's still an item. | |
342 CloseShellWindow(window); | |
343 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
344 item = *launcher_model()->ItemByID(shortcut_id); | |
345 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
346 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
347 } | |
348 | |
349 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, PinRunning) { | |
350 // Run. | |
351 int item_count = launcher_model()->item_count(); | |
352 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
353 ShellWindow* window = CreateShellWindow(extension); | |
354 ++item_count; | |
355 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
356 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
357 ash::LauncherID id = item1.id; | |
358 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
359 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
360 | |
361 // Create a shortcut. The app item should be after it. | |
362 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); | |
363 ++item_count; | |
364 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
365 EXPECT_LT(launcher_model()->ItemIndexByID(foo_id), | |
366 launcher_model()->ItemIndexByID(id)); | |
367 | |
368 // Pin the app. The item should remain. | |
369 controller_->Pin(id); | |
370 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
371 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(id); | |
372 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type); | |
373 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
374 | |
375 // New shortcuts should come after the item. | |
376 ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar"); | |
377 ++item_count; | |
378 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
379 EXPECT_LT(launcher_model()->ItemIndexByID(id), | |
380 launcher_model()->ItemIndexByID(bar_id)); | |
381 | |
382 // Then close it, make sure the item remains. | |
383 CloseShellWindow(window); | |
384 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
385 } | |
386 | |
387 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, UnpinRunning) { | |
388 int item_count = launcher_model()->item_count(); | |
389 | |
390 // First get app_id. | |
391 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
392 const std::string app_id = extension->id(); | |
393 | |
394 // Then create a shortcut. | |
395 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); | |
396 ++item_count; | |
397 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
398 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id); | |
399 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
400 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
401 | |
402 // Create a second shortcut. This will be needed to force the first one to | |
403 // move once it gets unpinned. | |
404 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); | |
405 ++item_count; | |
406 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
407 EXPECT_LT(launcher_model()->ItemIndexByID(shortcut_id), | |
408 launcher_model()->ItemIndexByID(foo_id)); | |
409 | |
410 // Open a window. Confirm the item is now running. | |
411 ShellWindow* window = CreateShellWindow(extension); | |
412 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
413 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
414 item = *launcher_model()->ItemByID(shortcut_id); | |
415 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
416 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
417 | |
418 // Unpin the app. The item should remain. | |
419 controller_->Unpin(shortcut_id); | |
420 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
421 item = *launcher_model()->ItemByID(shortcut_id); | |
422 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); | |
423 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
424 // The item should have moved after the other shortcuts. | |
425 EXPECT_GT(launcher_model()->ItemIndexByID(shortcut_id), | |
426 launcher_model()->ItemIndexByID(foo_id)); | |
427 | |
428 // Then close it, make sure the item's gone. | |
429 CloseShellWindow(window); | |
430 --item_count; | |
431 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
432 } | |
433 | |
434 // Test that we can launch a platform app with more than one window. | |
435 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, MultipleWindows) { | |
436 int item_count = launcher_model()->item_count(); | |
437 | |
438 // First run app. | |
439 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
440 ShellWindow* window1 = CreateShellWindow(extension); | |
441 ++item_count; | |
442 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
443 const ash::LauncherItem& item = GetLastLauncherItem(); | |
444 ash::LauncherID item_id = item.id; | |
445 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); | |
446 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
447 EXPECT_EQ(2, GetNumApplicationMenuItems(item)); // Title + 1 window | |
448 | |
449 // Add second window. | |
450 ShellWindow* window2 = CreateShellWindow(extension); | |
451 // Confirm item stays. | |
452 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
453 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(item_id); | |
454 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
455 EXPECT_EQ(3, GetNumApplicationMenuItems(item2)); // Title + 2 windows | |
456 | |
457 // Close second window. | |
458 CloseShellWindow(window2); | |
459 // Confirm item stays. | |
460 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
461 const ash::LauncherItem& item3 = *launcher_model()->ItemByID(item_id); | |
462 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status); | |
463 EXPECT_EQ(2, GetNumApplicationMenuItems(item3)); // Title + 1 window | |
464 | |
465 // Close first window. | |
466 CloseShellWindow(window1); | |
467 // Confirm item is removed. | |
468 --item_count; | |
469 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
470 } | |
471 | |
472 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, MultipleApps) { | |
473 int item_count = launcher_model()->item_count(); | |
474 | |
475 // First run app. | |
476 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
477 ShellWindow* window1 = CreateShellWindow(extension1); | |
478 ++item_count; | |
479 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
480 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
481 ash::LauncherID item_id1 = item1.id; | |
482 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
483 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
484 | |
485 // Then run second app. | |
486 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); | |
487 ShellWindow* window2 = CreateShellWindow(extension2); | |
488 ++item_count; | |
489 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
490 const ash::LauncherItem& item2 = GetLastLauncherItem(); | |
491 ash::LauncherID item_id2 = item2.id; | |
492 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); | |
493 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
494 | |
495 EXPECT_NE(item_id1, item_id2); | |
496 EXPECT_EQ(ash::STATUS_RUNNING, | |
497 launcher_model()->ItemByID(item_id1)->status); | |
498 | |
499 // Close second app. | |
500 CloseShellWindow(window2); | |
501 --item_count; | |
502 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
503 // First app should be active again. | |
504 EXPECT_EQ(ash::STATUS_ACTIVE, | |
505 launcher_model()->ItemByID(item_id1)->status); | |
506 | |
507 // Close first app. | |
508 CloseShellWindow(window1); | |
509 --item_count; | |
510 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
511 | |
512 } | |
513 | |
514 // Confirm that app windows can be reactivated by clicking their icons and that | |
515 // the correct activation order is maintained. | |
516 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, WindowActivation) { | |
517 int item_count = launcher_model()->item_count(); | |
518 | |
519 // First run app. | |
520 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
521 ShellWindow* window1 = CreateShellWindow(extension1); | |
522 ++item_count; | |
523 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
524 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
525 ash::LauncherID item_id1 = item1.id; | |
526 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
527 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
528 | |
529 // Then run second app. | |
530 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); | |
531 ShellWindow* window2 = CreateShellWindow(extension2); | |
532 ++item_count; | |
533 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
534 const ash::LauncherItem& item2 = GetLastLauncherItem(); | |
535 ash::LauncherID item_id2 = item2.id; | |
536 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); | |
537 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
538 | |
539 EXPECT_NE(item_id1, item_id2); | |
540 EXPECT_EQ(ash::STATUS_RUNNING, | |
541 launcher_model()->ItemByID(item_id1)->status); | |
542 | |
543 // Activate first one. | |
544 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
545 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status); | |
546 EXPECT_EQ(ash::STATUS_RUNNING, | |
547 launcher_model()->ItemByID(item_id2)->status); | |
548 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
549 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
550 | |
551 // Activate second one. | |
552 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2)); | |
553 EXPECT_EQ(ash::STATUS_RUNNING, | |
554 launcher_model()->ItemByID(item_id1)->status); | |
555 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id2)->status); | |
556 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
557 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
558 | |
559 // Add window for app1. This will activate it. | |
560 ShellWindow* window1b = CreateShellWindow(extension1); | |
561 ash::wm::ActivateWindow(window1b->GetNativeWindow()); | |
562 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
563 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
564 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
565 | |
566 // Activate launcher item for app1, this will activate the first app window. | |
567 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
568 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
569 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
570 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
571 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
572 | |
573 // Activate the second app again | |
574 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2)); | |
575 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
576 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
577 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
578 | |
579 // Activate the first app again | |
580 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
581 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
582 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
583 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
584 | |
585 // Close second app. | |
586 CloseShellWindow(window2); | |
587 --item_count; | |
588 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
589 // First app should be active again. | |
590 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status); | |
591 | |
592 // Close first app. | |
593 CloseShellWindow(window1b); | |
594 CloseShellWindow(window1); | |
595 --item_count; | |
596 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
597 } | |
598 | |
599 // Confirm that Click behavior for app windows is correnct. | |
600 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserNoMinimizeOnClick, | |
601 AppClickBehavior) { | |
602 // Launch a platform app and create a window for it. | |
603 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
604 ShellWindow* window1 = CreateShellWindow(extension1); | |
605 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
606 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
607 // Confirm that a controller item was created and is the correct state. | |
608 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
609 LauncherItemController* item1_controller = GetItemController(item1.id); | |
610 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
611 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
612 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); | |
613 // Clicking the item should have no effect. | |
614 TestEvent click_event(ui::ET_MOUSE_PRESSED); | |
615 item1_controller->Clicked(click_event); | |
616 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
617 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
618 // Minimize the window and confirm that the controller item is updated. | |
619 window1->GetBaseWindow()->Minimize(); | |
620 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); | |
621 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); | |
622 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
623 // Clicking the item should activate the window. | |
624 item1_controller->Clicked(click_event); | |
625 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
626 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
627 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
628 // Maximizing a window should preserve state after minimize + click. | |
629 window1->GetBaseWindow()->Maximize(); | |
630 window1->GetBaseWindow()->Minimize(); | |
631 item1_controller->Clicked(click_event); | |
632 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
633 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
634 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); | |
635 } | |
636 | |
637 // Confirm the minimizing click behavior for apps. | |
638 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserMinimizeOnClick, | |
639 PackagedAppClickBehaviorInMinimizeMode) { | |
640 // Launch one platform app and create a window for it. | |
641 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
642 ShellWindow* window1 = CreateShellWindow(extension1); | |
643 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
644 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
645 | |
646 // Confirm that a controller item was created and is the correct state. | |
647 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
648 LauncherItemController* item1_controller = GetItemController(item1.id); | |
649 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
650 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
651 EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type()); | |
652 // Since it is already active, clicking it should minimize. | |
653 TestEvent click_event(ui::ET_MOUSE_PRESSED); | |
654 item1_controller->Clicked(click_event); | |
655 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); | |
656 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); | |
657 EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized()); | |
658 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
659 // Clicking the item again should activate the window again. | |
660 item1_controller->Clicked(click_event); | |
661 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
662 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
663 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
664 // Maximizing a window should preserve state after minimize + click. | |
665 window1->GetBaseWindow()->Maximize(); | |
666 window1->GetBaseWindow()->Minimize(); | |
667 item1_controller->Clicked(click_event); | |
668 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
669 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
670 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); | |
671 window1->GetBaseWindow()->Restore(); | |
672 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
673 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
674 EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized()); | |
675 | |
676 // Creating a second window of the same type should change the behavior so | |
677 // that a click does not change the activation state. | |
678 ShellWindow* window1a = CreateShellWindow(extension1); | |
679 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
680 EXPECT_TRUE(window1a->GetBaseWindow()->IsActive()); | |
681 // The first click does nothing. | |
682 item1_controller->Clicked(click_event); | |
683 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
684 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
685 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
686 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); | |
687 // The second neither. | |
688 item1_controller->Clicked(click_event); | |
689 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
690 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
691 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
692 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); | |
693 } | |
694 | |
695 // Confirm that click behavior for app panels is correct. | |
696 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, | |
697 AppPanelClickBehavior) { | |
698 // Enable experimental APIs to allow panel creation. | |
699 CommandLine::ForCurrentProcess()->AppendSwitch( | |
700 extensions::switches::kEnableExperimentalExtensionApis); | |
701 // Launch a platform app and create a panel window for it. | |
702 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
703 ShellWindow::CreateParams params; | |
704 params.window_type = ShellWindow::WINDOW_TYPE_PANEL; | |
705 params.focused = false; | |
706 ShellWindow* panel = CreateShellWindowFromParams(extension1, params); | |
707 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
708 // Panels should not be active by default. | |
709 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); | |
710 // Confirm that a controller item was created and is the correct state. | |
711 const ash::LauncherItem& item1 = GetLastLauncherPanelItem(); | |
712 LauncherItemController* item1_controller = GetItemController(item1.id); | |
713 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type); | |
714 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
715 EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item1_controller->type()); | |
716 // Click the item and confirm that the panel is activated. | |
717 TestEvent click_event(ui::ET_MOUSE_PRESSED); | |
718 item1_controller->Clicked(click_event); | |
719 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
720 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
721 // Click the item again and confirm that the panel is minimized. | |
722 item1_controller->Clicked(click_event); | |
723 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized()); | |
724 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
725 // Click the item again and confirm that the panel is activated. | |
726 item1_controller->Clicked(click_event); | |
727 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
728 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
729 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
730 } | |
731 | |
732 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, | |
733 BrowserActivation) { | |
734 int item_count = launcher_model()->item_count(); | |
735 | |
736 // First run app. | |
737 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
738 CreateShellWindow(extension1); | |
739 ++item_count; | |
740 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
741 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
742 ash::LauncherID item_id1 = item1.id; | |
743 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
744 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
745 | |
746 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow()); | |
747 EXPECT_EQ(ash::STATUS_RUNNING, | |
748 launcher_model()->ItemByID(item_id1)->status); | |
749 } | |
750 | |
751 // Test that opening an app sets the correct icon | |
752 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, SetIcon) { | |
753 TestShellWindowRegistryObserver test_observer(browser()->profile()); | |
754 | |
755 // Enable experimental APIs to allow panel creation. | |
756 CommandLine::ForCurrentProcess()->AppendSwitch( | |
757 extensions::switches::kEnableExperimentalExtensionApis); | |
758 | |
759 int base_launcher_item_count = launcher_model()->item_count(); | |
760 ExtensionTestMessageListener launched_listener("Launched", false); | |
761 ExtensionTestMessageListener completed_listener("Completed", false); | |
762 LoadAndLaunchPlatformApp("app_icon"); | |
763 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
764 ASSERT_TRUE(completed_listener.WaitUntilSatisfied()); | |
765 | |
766 // Now wait until the WebContent has decoded the icons and chrome has | |
767 // processed it. This needs to be in a loop since the renderer runs in a | |
768 // different process. | |
769 while (test_observer.icon_updates() < 3) { | |
770 base::RunLoop run_loop; | |
771 run_loop.RunUntilIdle(); | |
772 } | |
773 | |
774 // This test creates one shell window and one panel window. | |
775 int launcher_item_count = launcher_model()->item_count(); | |
776 ASSERT_EQ(base_launcher_item_count + 2, launcher_item_count); | |
777 // The Panel will be the last item, the app list second-to-last, the app | |
778 // third from last. | |
779 const ash::LauncherItem& app_item = | |
780 launcher_model()->items()[launcher_item_count - 3]; | |
781 const ash::LauncherItem& panel_item = | |
782 launcher_model()->items()[launcher_item_count - 1]; | |
783 const LauncherItemController* app_item_controller = | |
784 GetItemController(app_item.id); | |
785 const LauncherItemController* panel_item_controller = | |
786 GetItemController(panel_item.id); | |
787 // Icons for Apps are set by the ShellWindowLauncherController, so | |
788 // image_set_by_controller() should be set. | |
789 EXPECT_TRUE(app_item_controller->image_set_by_controller()); | |
790 EXPECT_TRUE(panel_item_controller->image_set_by_controller()); | |
791 // Ensure icon heights are correct (see test.js in app_icon/ test directory) | |
792 EXPECT_EQ(48, app_item.image.height()); | |
793 EXPECT_EQ(64, panel_item.image.height()); | |
794 } | |
795 | |
796 // Test that we can launch an app with a shortcut. | |
797 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, LaunchPinned) { | |
798 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
799 int tab_count = tab_strip->count(); | |
800 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
801 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
802 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
803 EXPECT_EQ(++tab_count, tab_strip->count()); | |
804 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
805 WebContents* tab = tab_strip->GetActiveWebContents(); | |
806 content::WindowedNotificationObserver close_observer( | |
807 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
808 content::Source<WebContents>(tab)); | |
809 browser()->tab_strip_model()->CloseSelectedTabs(); | |
810 close_observer.Wait(); | |
811 EXPECT_EQ(--tab_count, tab_strip->count()); | |
812 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
813 } | |
814 | |
815 // Launch the app first and then create the shortcut. | |
816 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, LaunchUnpinned) { | |
817 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
818 int tab_count = tab_strip->count(); | |
819 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, | |
820 NEW_FOREGROUND_TAB); | |
821 EXPECT_EQ(++tab_count, tab_strip->count()); | |
822 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
823 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
824 WebContents* tab = tab_strip->GetActiveWebContents(); | |
825 content::WindowedNotificationObserver close_observer( | |
826 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
827 content::Source<WebContents>(tab)); | |
828 browser()->tab_strip_model()->CloseSelectedTabs(); | |
829 close_observer.Wait(); | |
830 EXPECT_EQ(--tab_count, tab_strip->count()); | |
831 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
832 } | |
833 | |
834 // Launches an app in the background and then tries to open it. This is test for | |
835 // a crash we had. | |
836 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, LaunchInBackground) { | |
837 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
838 int tab_count = tab_strip->count(); | |
839 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, | |
840 NEW_BACKGROUND_TAB); | |
841 EXPECT_EQ(++tab_count, tab_strip->count()); | |
842 ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id_, 0); | |
843 } | |
844 | |
845 // Confirm that clicking a icon for an app running in one of 2 maxmized windows | |
846 // activates the right window. | |
847 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, LaunchMaximized) { | |
848 aura::Window* window1 = browser()->window()->GetNativeWindow(); | |
849 ash::wm::MaximizeWindow(window1); | |
850 content::WindowedNotificationObserver open_observer( | |
851 chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
852 content::NotificationService::AllSources()); | |
853 chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH); | |
854 open_observer.Wait(); | |
855 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr(); | |
856 aura::Window* window2 = browser2->window()->GetNativeWindow(); | |
857 TabStripModel* tab_strip = browser2->tab_strip_model(); | |
858 int tab_count = tab_strip->count(); | |
859 ash::wm::MaximizeWindow(window2); | |
860 | |
861 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
862 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
863 EXPECT_EQ(++tab_count, tab_strip->count()); | |
864 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
865 | |
866 window1->Show(); | |
867 ash::wm::ActivateWindow(window1); | |
868 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); | |
869 | |
870 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
871 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
872 } | |
873 | |
874 // Activating the same app multiple times should launch only a single copy. | |
875 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, ActivateApp) { | |
876 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
877 int tab_count = tab_strip->count(); | |
878 const Extension* extension = | |
879 LoadExtension(test_data_dir_.AppendASCII("app1")); | |
880 | |
881 ChromeLauncherController::instance()->ActivateApp(extension->id(), 0); | |
882 EXPECT_EQ(++tab_count, tab_strip->count()); | |
883 ChromeLauncherController::instance()->ActivateApp(extension->id(), 0); | |
884 EXPECT_EQ(tab_count, tab_strip->count()); | |
885 } | |
886 | |
887 // Launching the same app multiple times should launch a copy for each call. | |
888 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, LaunchApp) { | |
889 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
890 int tab_count = tab_strip->count(); | |
891 const Extension* extension = | |
892 LoadExtension(test_data_dir_.AppendASCII("app1")); | |
893 | |
894 ChromeLauncherController::instance()->LaunchApp(extension->id(), 0); | |
895 EXPECT_EQ(++tab_count, tab_strip->count()); | |
896 ChromeLauncherController::instance()->LaunchApp(extension->id(), 0); | |
897 EXPECT_EQ(++tab_count, tab_strip->count()); | |
898 } | |
899 | |
900 // Launch 2 apps and toggle which is active. | |
901 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, MultipleApps) { | |
902 int item_count = model_->item_count(); | |
903 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
904 int tab_count = tab_strip->count(); | |
905 ash::LauncherID shortcut1 = CreateShortcut("app1"); | |
906 EXPECT_EQ(++item_count, model_->item_count()); | |
907 ash::LauncherID shortcut2 = CreateShortcut("app2"); | |
908 EXPECT_EQ(++item_count, model_->item_count()); | |
909 | |
910 // Launch first app. | |
911 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
912 EXPECT_EQ(++tab_count, tab_strip->count()); | |
913 WebContents* tab1 = tab_strip->GetActiveWebContents(); | |
914 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
915 | |
916 // Launch second app. | |
917 ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); | |
918 EXPECT_EQ(++tab_count, tab_strip->count()); | |
919 WebContents* tab2 = tab_strip->GetActiveWebContents(); | |
920 ASSERT_NE(tab1, tab2); | |
921 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
922 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
923 | |
924 // Reactivate first app. | |
925 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
926 EXPECT_EQ(tab_count, tab_strip->count()); | |
927 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
928 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
929 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
930 | |
931 // Open second tab for second app. This should activate it. | |
932 ui_test_utils::NavigateToURLWithDisposition( | |
933 browser(), | |
934 GURL("http://www.example.com/path3/foo.html"), | |
935 NEW_FOREGROUND_TAB, | |
936 0); | |
937 EXPECT_EQ(++tab_count, tab_strip->count()); | |
938 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
939 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
940 | |
941 // Reactivate first app. | |
942 ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
943 EXPECT_EQ(tab_count, tab_strip->count()); | |
944 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
945 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
946 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
947 | |
948 // And second again. This time the second tab should become active. | |
949 ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); | |
950 EXPECT_EQ(tab_count, tab_strip->count()); | |
951 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2); | |
952 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
953 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
954 } | |
955 | |
956 // Confirm that a page can be navigated from and to while maintaining the | |
957 // correct running state. | |
958 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, Navigation) { | |
959 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
960 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
961 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
962 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
963 | |
964 // Navigate away. | |
965 ui_test_utils::NavigateToURL( | |
966 browser(), GURL("http://www.example.com/path0/bar.html")); | |
967 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
968 | |
969 // Navigate back. | |
970 ui_test_utils::NavigateToURL( | |
971 browser(), GURL("http://www.example.com/path1/foo.html")); | |
972 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
973 } | |
974 | |
975 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, MultipleOwnedTabs) { | |
976 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
977 int tab_count = tab_strip->count(); | |
978 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
979 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
980 EXPECT_EQ(++tab_count, tab_strip->count()); | |
981 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
982 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
983 | |
984 // Create new tab owned by app. | |
985 ui_test_utils::NavigateToURLWithDisposition( | |
986 browser(), | |
987 GURL("http://www.example.com/path2/bar.html"), | |
988 NEW_FOREGROUND_TAB, | |
989 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
990 EXPECT_EQ(++tab_count, tab_strip->count()); | |
991 // Confirm app is still active. | |
992 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
993 | |
994 // Create new tab not owned by app. | |
995 ui_test_utils::NavigateToURLWithDisposition( | |
996 browser(), | |
997 GURL("http://www.example.com/path3/foo.html"), | |
998 NEW_FOREGROUND_TAB, | |
999 0); | |
1000 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1001 // No longer active. | |
1002 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
1003 | |
1004 // Activating app makes first tab active again. | |
1005 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
1006 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1007 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); | |
1008 } | |
1009 | |
1010 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, RefocusFilter) { | |
1011 ChromeLauncherController* controller = | |
1012 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1013 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1014 int tab_count = tab_strip->count(); | |
1015 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
1016 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
1017 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1018 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1019 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
1020 | |
1021 controller->SetRefocusURLPatternForTest( | |
1022 shortcut_id, GURL("http://www.example.com/path1/*")); | |
1023 // Create new tab owned by app. | |
1024 ui_test_utils::NavigateToURLWithDisposition( | |
1025 browser(), | |
1026 GURL("http://www.example.com/path2/bar.html"), | |
1027 NEW_FOREGROUND_TAB, | |
1028 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1029 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1030 // Confirm app is still active. | |
1031 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1032 | |
1033 // Create new tab not owned by app. | |
1034 ui_test_utils::NavigateToURLWithDisposition( | |
1035 browser(), | |
1036 GURL("http://www.example.com/path3/foo.html"), | |
1037 NEW_FOREGROUND_TAB, | |
1038 0); | |
1039 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1040 // No longer active. | |
1041 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
1042 | |
1043 // Activating app makes first tab active again, because second tab isn't | |
1044 // in its refocus url path. | |
1045 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
1046 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1047 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); | |
1048 } | |
1049 | |
1050 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, RefocusFilterLaunch) { | |
1051 ChromeLauncherController* controller = | |
1052 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1053 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1054 int tab_count = tab_strip->count(); | |
1055 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
1056 controller->SetRefocusURLPatternForTest( | |
1057 shortcut_id, GURL("http://www.example.com/path1/*")); | |
1058 | |
1059 // Create new tab. | |
1060 ui_test_utils::NavigateToURLWithDisposition( | |
1061 browser(), | |
1062 GURL("http://www.example2.com/path2/bar.html"), | |
1063 NEW_FOREGROUND_TAB, | |
1064 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1065 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1066 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
1067 // Confirm app is not active. | |
1068 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1069 | |
1070 // Activating app should launch new tab, because second tab isn't | |
1071 // in its refocus url path. | |
1072 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
1073 EXPECT_EQ(++tab_count, tab_strip->count()); | |
1074 WebContents* second_tab = tab_strip->GetActiveWebContents(); | |
1075 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1076 EXPECT_NE(first_tab, second_tab); | |
1077 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); | |
1078 } | |
1079 | |
1080 // Check the launcher activation state for applications and browser. | |
1081 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, ActivationStateCheck) { | |
1082 ChromeLauncherController* controller = | |
1083 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1084 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1085 // Get the browser item index | |
1086 int browser_index = ash::launcher::GetBrowserItemIndex(*controller->model()); | |
1087 EXPECT_TRUE(browser_index >= 0); | |
1088 | |
1089 // Even though we are just comming up, the browser should be active. | |
1090 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
1091 | |
1092 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
1093 controller->SetRefocusURLPatternForTest( | |
1094 shortcut_id, GURL("http://www.example.com/path1/*")); | |
1095 | |
1096 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1097 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
1098 | |
1099 // Create new tab which would be the running app. | |
1100 ui_test_utils::NavigateToURLWithDisposition( | |
1101 browser(), | |
1102 GURL("http://www.example.com/path1/bar.html"), | |
1103 NEW_FOREGROUND_TAB, | |
1104 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1105 | |
1106 // There should never be two items active at the same time. | |
1107 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1108 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
1109 | |
1110 tab_strip->ActivateTabAt(0, false); | |
1111 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
1112 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
1113 | |
1114 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); | |
1115 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1116 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
1117 | |
1118 ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow()); | |
1119 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1120 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
1121 } | |
1122 | |
1123 // Check that the launcher activation state for a V1 application stays closed | |
1124 // even after an asynchronous browser event comes in after the tab got | |
1125 // destroyed. | |
1126 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, | |
1127 AsyncActivationStateCheck) { | |
1128 ChromeLauncherController* controller = | |
1129 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1130 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1131 | |
1132 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
1133 controller->SetRefocusURLPatternForTest( | |
1134 shortcut_id, GURL("http://www.example.com/path1/*")); | |
1135 | |
1136 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1137 | |
1138 // Create new tab which would be the running app. | |
1139 ui_test_utils::NavigateToURLWithDisposition( | |
1140 browser(), | |
1141 GURL("http://www.example.com/path1/bar.html"), | |
1142 NEW_FOREGROUND_TAB, | |
1143 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1144 | |
1145 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
1146 // To address the issue of crbug.com/174050, the tab we are about to close | |
1147 // has to be active. | |
1148 tab_strip->ActivateTabAt(1, false); | |
1149 EXPECT_EQ(1, tab_strip->active_index()); | |
1150 | |
1151 // Close the web contents. | |
1152 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); | |
1153 // The status should now be set to closed. | |
1154 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
1155 } | |
1156 | |
1157 // Checks that a windowed application does not add an item to the browser list. | |
1158 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTestNoDefaultBrowser, | |
1159 WindowedAppDoesNotAddToBrowser) { | |
1160 // Get the number of items in the browser menu. | |
1161 size_t items = NumberOfDetectedLauncherBrowsers(false); | |
1162 size_t running_browser = chrome::GetTotalBrowserCount(); | |
1163 EXPECT_EQ(0u, items); | |
1164 EXPECT_EQ(0u, running_browser); | |
1165 | |
1166 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_WINDOW, NEW_WINDOW); | |
1167 | |
1168 // No new browser should get detected, even though one more is running. | |
1169 EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false)); | |
1170 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); | |
1171 | |
1172 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW); | |
1173 | |
1174 // A new browser should get detected and one more should be running. | |
1175 EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u); | |
1176 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); | |
1177 } | |
1178 | |
1179 // Checks the functionality to enumerate all browsers vs. all tabs. | |
1180 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTestNoDefaultBrowser, | |
1181 EnumerateALlBrowsersAndTabs) { | |
1182 // Create at least one browser. | |
1183 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW); | |
1184 size_t browsers = NumberOfDetectedLauncherBrowsers(false); | |
1185 size_t tabs = NumberOfDetectedLauncherBrowsers(true); | |
1186 | |
1187 // Create a second browser. | |
1188 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW); | |
1189 | |
1190 EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false)); | |
1191 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); | |
1192 | |
1193 // Create only a tab. | |
1194 LoadAndLaunchExtension("app1", | |
1195 extension_misc::LAUNCH_TAB, | |
1196 NEW_FOREGROUND_TAB); | |
1197 | |
1198 EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false)); | |
1199 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); | |
1200 } | |
1201 | |
1202 // Check that the keyboard activation of a launcher item tabs properly through | |
1203 // the items at hand. | |
1204 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, AltNumberTabsTabbing) { | |
1205 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1206 ChromeLauncherController* controller = | |
1207 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1208 | |
1209 ash::LauncherID shortcut_id = CreateShortcut("app"); | |
1210 controller->SetRefocusURLPatternForTest( | |
1211 shortcut_id, GURL("http://www.example.com/path/*")); | |
1212 std::string url = "http://www.example.com/path/bla"; | |
1213 | |
1214 int shortcut_index = model_->ItemIndexByID(shortcut_id); | |
1215 | |
1216 // Create an application handled browser tab. | |
1217 ui_test_utils::NavigateToURLWithDisposition( | |
1218 browser(), | |
1219 GURL(url), | |
1220 NEW_FOREGROUND_TAB, | |
1221 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1222 | |
1223 content::WebContents* content1 = tab_strip->GetActiveWebContents(); | |
1224 | |
1225 // Create some other browser tab. | |
1226 ui_test_utils::NavigateToURLWithDisposition( | |
1227 browser(), | |
1228 GURL("http://www.test.com"), | |
1229 NEW_FOREGROUND_TAB, | |
1230 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1231 content::WebContents* content1a = tab_strip->GetActiveWebContents(); | |
1232 | |
1233 // Make sure that the active tab is now our handled tab. | |
1234 EXPECT_NE(content1a, content1); | |
1235 | |
1236 // The active tab should still be the unnamed tab. Then we switch and reach | |
1237 // the first app and stay there. | |
1238 EXPECT_EQ(content1a, tab_strip->GetActiveWebContents()); | |
1239 ActivateLauncherItem(shortcut_index); | |
1240 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); | |
1241 ActivateLauncherItem(shortcut_index); | |
1242 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); | |
1243 | |
1244 ui_test_utils::NavigateToURLWithDisposition( | |
1245 browser(), | |
1246 GURL(url), | |
1247 NEW_FOREGROUND_TAB, | |
1248 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1249 content::WebContents* content2 = tab_strip->GetActiveWebContents(); | |
1250 | |
1251 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); | |
1252 ActivateLauncherItem(shortcut_index); | |
1253 EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents()); | |
1254 ActivateLauncherItem(shortcut_index); | |
1255 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); | |
1256 } | |
1257 | |
1258 // Check that the keyboard activation of a launcher item tabs properly through | |
1259 // the items at hand. | |
1260 IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest, | |
1261 AltNumberAppsTabbing) { | |
1262 // First run app. | |
1263 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
1264 ui::BaseWindow* window1 = CreateShellWindow(extension1)->GetBaseWindow(); | |
1265 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
1266 ash::LauncherID app_id = item1.id; | |
1267 int app_index = launcher_model()->ItemIndexByID(app_id); | |
1268 | |
1269 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
1270 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
1271 | |
1272 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); | |
1273 ui::BaseWindow* window2 = CreateShellWindow(extension2)->GetBaseWindow(); | |
1274 | |
1275 // By now the browser should be active. Issue Alt keystrokes several times to | |
1276 // see that we stay on that application. | |
1277 EXPECT_TRUE(window2->IsActive()); | |
1278 ActivateLauncherItem(app_index); | |
1279 EXPECT_TRUE(window1->IsActive()); | |
1280 ActivateLauncherItem(app_index); | |
1281 EXPECT_TRUE(window1->IsActive()); | |
1282 | |
1283 ui::BaseWindow* window1a = CreateShellWindow(extension1)->GetBaseWindow(); | |
1284 | |
1285 EXPECT_TRUE(window1a->IsActive()); | |
1286 EXPECT_FALSE(window1->IsActive()); | |
1287 ActivateLauncherItem(app_index); | |
1288 EXPECT_TRUE(window1->IsActive()); | |
1289 ActivateLauncherItem(app_index); | |
1290 EXPECT_TRUE(window1a->IsActive()); | |
1291 } | |
1292 | |
1293 // Checks that the browser Alt "tabbing" is properly done. | |
1294 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTestNoDefaultBrowser, | |
1295 AltNumberBrowserTabbing) { | |
1296 // Get the number of items in the browser menu. | |
1297 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); | |
1298 // The first activation should create a browser. | |
1299 launcher_->ActivateLauncherItem(0); | |
1300 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
1301 // A second activation should not create a new instance. | |
1302 launcher_->ActivateLauncherItem(0); | |
1303 Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()); | |
1304 EXPECT_TRUE(browser1); | |
1305 aura::Window* window1 = browser1->window()->GetNativeWindow(); | |
1306 Browser* browser2 = CreateBrowser(profile()); | |
1307 aura::Window* window2 = browser2->window()->GetNativeWindow(); | |
1308 | |
1309 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
1310 EXPECT_NE(window1, window2); | |
1311 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
1312 | |
1313 // Activate multiple times the switcher to see that the windows get activated. | |
1314 launcher_->ActivateLauncherItem(0); | |
1315 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
1316 launcher_->ActivateLauncherItem(0); | |
1317 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
1318 | |
1319 // Create a third browser - make sure that we do not toggle simply between | |
1320 // two windows. | |
1321 Browser* browser3 = CreateBrowser(profile()); | |
1322 aura::Window* window3 = browser3->window()->GetNativeWindow(); | |
1323 | |
1324 EXPECT_EQ(3u, chrome::GetTotalBrowserCount()); | |
1325 EXPECT_NE(window1, window3); | |
1326 EXPECT_NE(window2, window3); | |
1327 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); | |
1328 | |
1329 launcher_->ActivateLauncherItem(0); | |
1330 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
1331 launcher_->ActivateLauncherItem(0); | |
1332 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
1333 launcher_->ActivateLauncherItem(0); | |
1334 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); | |
1335 launcher_->ActivateLauncherItem(0); | |
1336 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
1337 | |
1338 // Create anther app and make sure that none of our browsers is active. | |
1339 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, NEW_WINDOW); | |
1340 EXPECT_NE(window1, ash::wm::GetActiveWindow()); | |
1341 EXPECT_NE(window2, ash::wm::GetActiveWindow()); | |
1342 | |
1343 // After activation our browser should be active again. | |
1344 launcher_->ActivateLauncherItem(0); | |
1345 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
1346 } | |
1347 | |
1348 // Checks that after a session restore, we do not start applications on an | |
1349 // activation. | |
1350 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, | |
1351 ActivateAfterSessionRestore) { | |
1352 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
1353 | |
1354 // Create a known application. | |
1355 ChromeLauncherController* controller = | |
1356 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
1357 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
1358 | |
1359 // Create a new browser - without activating it - and load an "app" into it. | |
1360 Browser::CreateParams params = | |
1361 Browser::CreateParams(profile(), chrome::GetActiveDesktop()); | |
1362 params.initial_show_state = ui::SHOW_STATE_INACTIVE; | |
1363 Browser* browser2 = new Browser(params); | |
1364 controller->SetRefocusURLPatternForTest( | |
1365 shortcut_id, GURL("http://www.example.com/path/*")); | |
1366 std::string url = "http://www.example.com/path/bla"; | |
1367 ui_test_utils::NavigateToURLWithDisposition( | |
1368 browser2, | |
1369 GURL(url), | |
1370 NEW_FOREGROUND_TAB, | |
1371 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
1372 | |
1373 // Remember the number of tabs for each browser. | |
1374 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1375 int tab_count1 = tab_strip->count(); | |
1376 TabStripModel* tab_strip2 = browser2->tab_strip_model(); | |
1377 int tab_count2 = tab_strip2->count(); | |
1378 | |
1379 // Check that we have two browsers and the inactive browser remained inactive. | |
1380 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
1381 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), | |
1382 browser()); | |
1383 // Check that the LRU browser list does only contain the original browser. | |
1384 BrowserList* ash_browser_list = | |
1385 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); | |
1386 BrowserList::const_reverse_iterator it = | |
1387 ash_browser_list->begin_last_active(); | |
1388 EXPECT_EQ(*it, browser()); | |
1389 ++it; | |
1390 EXPECT_EQ(it, ash_browser_list->end_last_active()); | |
1391 | |
1392 // Now request to either activate an existing app or create a new one. | |
1393 controller->ItemSelected(*model_->ItemByID(shortcut_id), | |
1394 ui::KeyEvent(ui::ET_KEY_RELEASED, | |
1395 ui::VKEY_RETURN, | |
1396 0, | |
1397 false)); | |
1398 | |
1399 // Check that we have set focus on the existing application and nothing new | |
1400 // was created. | |
1401 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
1402 EXPECT_EQ(tab_count1, tab_strip->count()); | |
1403 EXPECT_EQ(tab_count2, tab_strip2->count()); | |
1404 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), | |
1405 browser2); | |
1406 } | |
1407 | |
1408 // Do various drag and drop interaction tests between the application list and | |
1409 // the launcher. | |
1410 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, DragAndDrop) { | |
1411 // Get a number of interfaces we need. | |
1412 aura::test::EventGenerator generator( | |
1413 ash::Shell::GetPrimaryRootWindow(), gfx::Point()); | |
1414 ash::test::LauncherViewTestAPI test(launcher_->GetLauncherViewForTest()); | |
1415 AppListService* service = AppListService::Get(); | |
1416 | |
1417 // There should be two items in our launcher by this time. | |
1418 EXPECT_EQ(2, model_->item_count()); | |
1419 EXPECT_FALSE(service->IsAppListVisible()); | |
1420 | |
1421 // Open the app list menu and check that the drag and drop host was set. | |
1422 gfx::Rect app_list_bounds = | |
1423 test.launcher_view()->GetAppListButtonView()->GetBoundsInScreen(); | |
1424 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), | |
1425 app_list_bounds.CenterPoint().y()); | |
1426 base::MessageLoop::current()->RunUntilIdle(); | |
1427 generator.ClickLeftButton(); | |
1428 | |
1429 EXPECT_TRUE(service->IsAppListVisible()); | |
1430 app_list::AppsGridView* grid_view = | |
1431 app_list::AppsGridView::GetLastGridViewForTest(); | |
1432 ASSERT_TRUE(grid_view); | |
1433 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test()); | |
1434 | |
1435 // There should be 2 items in our application list. | |
1436 const views::ViewModel* vm_grid = grid_view->view_model_for_test(); | |
1437 EXPECT_EQ(2, vm_grid->view_size()); | |
1438 | |
1439 // Test #1: Drag an app list which does not exist yet item into the | |
1440 // launcher. Keeping it dragged, see that a new item gets created. Continuing | |
1441 // to drag it out should remove it again. | |
1442 | |
1443 // Get over item #1 of the application list and press the mouse button. | |
1444 views::View* item1 = vm_grid->view_at(1); | |
1445 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen(); | |
1446 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
1447 bounds_grid_1.CenterPoint().y()); | |
1448 base::MessageLoop::current()->RunUntilIdle(); | |
1449 generator.PressLeftButton(); | |
1450 | |
1451 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1452 | |
1453 // Drag the item into the launcher and check that a new item gets created. | |
1454 const views::ViewModel* vm_launcher = | |
1455 test.launcher_view()->view_model_for_test(); | |
1456 views::View* launcher1 = vm_launcher->view_at(1); | |
1457 gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen(); | |
1458 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), | |
1459 bounds_launcher_1.CenterPoint().y()); | |
1460 base::MessageLoop::current()->RunUntilIdle(); | |
1461 | |
1462 // Check that a new item got created. | |
1463 EXPECT_EQ(3, model_->item_count()); | |
1464 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1465 | |
1466 // Move it where the item originally was and check that it disappears again. | |
1467 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
1468 bounds_grid_1.CenterPoint().y()); | |
1469 base::MessageLoop::current()->RunUntilIdle(); | |
1470 EXPECT_EQ(2, model_->item_count()); | |
1471 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1472 | |
1473 // Dropping it should keep the launcher as it originally was. | |
1474 generator.ReleaseLeftButton(); | |
1475 base::MessageLoop::current()->RunUntilIdle(); | |
1476 EXPECT_EQ(2, model_->item_count()); | |
1477 // There are a few animations which need finishing before we can continue. | |
1478 test.RunMessageLoopUntilAnimationsDone(); | |
1479 // Move the mouse outside of the launcher. | |
1480 generator.MoveMouseTo(0, 0); | |
1481 | |
1482 // Test #2: Check that the unknown item dropped into the launcher will | |
1483 // create a new item. | |
1484 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
1485 bounds_grid_1.CenterPoint().y()); | |
1486 generator.PressLeftButton(); | |
1487 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), | |
1488 bounds_launcher_1.CenterPoint().y()); | |
1489 base::MessageLoop::current()->RunUntilIdle(); | |
1490 EXPECT_EQ(3, model_->item_count()); | |
1491 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1492 generator.ReleaseLeftButton(); | |
1493 base::MessageLoop::current()->RunUntilIdle(); | |
1494 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1495 EXPECT_EQ(3, model_->item_count()); // It should be still there. | |
1496 test.RunMessageLoopUntilAnimationsDone(); | |
1497 | |
1498 // Test #3: Check that the now known item dropped into the launcher will | |
1499 // not create a new item. | |
1500 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
1501 bounds_grid_1.CenterPoint().y()); | |
1502 generator.PressLeftButton(); | |
1503 generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(), | |
1504 bounds_launcher_1.CenterPoint().y()); | |
1505 base::MessageLoop::current()->RunUntilIdle(); | |
1506 EXPECT_EQ(3, model_->item_count()); // No new item got added. | |
1507 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1508 generator.ReleaseLeftButton(); | |
1509 base::MessageLoop::current()->RunUntilIdle(); | |
1510 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
1511 EXPECT_EQ(3, model_->item_count()); // And it remains that way. | |
1512 } | |
1513 | |
1514 // Check that clicking on an app launcher item launches a new browser. | |
1515 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, ClickItem) { | |
1516 // Get a number of interfaces we need. | |
1517 aura::test::EventGenerator generator( | |
1518 ash::Shell::GetPrimaryRootWindow(), gfx::Point()); | |
1519 ash::test::LauncherViewTestAPI test(launcher_->GetLauncherViewForTest()); | |
1520 AppListService* service = AppListService::Get(); | |
1521 // There should be two items in our launcher by this time. | |
1522 EXPECT_EQ(2, model_->item_count()); | |
1523 EXPECT_FALSE(service->IsAppListVisible()); | |
1524 | |
1525 // Open the app list menu and check that the drag and drop host was set. | |
1526 gfx::Rect app_list_bounds = | |
1527 test.launcher_view()->GetAppListButtonView()->GetBoundsInScreen(); | |
1528 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), | |
1529 app_list_bounds.CenterPoint().y()); | |
1530 generator.ClickLeftButton(); | |
1531 base::MessageLoop::current()->RunUntilIdle(); | |
1532 | |
1533 EXPECT_TRUE(service->IsAppListVisible()); | |
1534 app_list::AppsGridView* grid_view = | |
1535 app_list::AppsGridView::GetLastGridViewForTest(); | |
1536 ASSERT_TRUE(grid_view); | |
1537 const views::ViewModel* vm_grid = grid_view->view_model_for_test(); | |
1538 EXPECT_EQ(2, vm_grid->view_size()); | |
1539 gfx::Rect bounds_grid_1 = vm_grid->view_at(1)->GetBoundsInScreen(); | |
1540 // Test now that a click does create a new application tab. | |
1541 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
1542 int tab_count = tab_strip->count(); | |
1543 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
1544 bounds_grid_1.CenterPoint().y()); | |
1545 generator.ClickLeftButton(); | |
1546 base::MessageLoop::current()->RunUntilIdle(); | |
1547 EXPECT_EQ(tab_count + 1, tab_strip->count()); | |
1548 } | |
1549 | |
1550 // Check LauncherItemController of Browser Shortcut functionality. | |
1551 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTestNoDefaultBrowser, | |
1552 BrowserShortcutLauncherItemController) { | |
1553 ChromeLauncherControllerPerApp* controller = | |
1554 static_cast<ChromeLauncherControllerPerApp*>(launcher_->delegate()); | |
1555 LauncherItemController* item_controller = | |
1556 controller->GetBrowserShortcutLauncherItemController(); | |
1557 | |
1558 // Get the number of browsers. | |
1559 size_t running_browser = chrome::GetTotalBrowserCount(); | |
1560 EXPECT_EQ(0u, running_browser); | |
1561 EXPECT_FALSE(item_controller->IsOpen()); | |
1562 | |
1563 // Activate. This creates new browser | |
1564 item_controller->Activate(); | |
1565 // New Window is created. | |
1566 running_browser = chrome::GetTotalBrowserCount(); | |
1567 EXPECT_EQ(1u, running_browser); | |
1568 EXPECT_TRUE(item_controller->IsOpen()); | |
1569 | |
1570 // Minimize Window. | |
1571 aura::Window* window = ash::wm::GetActiveWindow(); | |
1572 ash::wm::MinimizeWindow(window); | |
1573 EXPECT_TRUE(ash::wm::IsWindowMinimized(window)); | |
1574 | |
1575 // Activate again. This doesn't create new browser. | |
1576 // It activates window. | |
1577 item_controller->Activate(); | |
1578 running_browser = chrome::GetTotalBrowserCount(); | |
1579 EXPECT_EQ(1u, running_browser); | |
1580 EXPECT_TRUE(item_controller->IsOpen()); | |
1581 EXPECT_FALSE(ash::wm::IsWindowMinimized(window)); | |
1582 } | |
1583 | |
1584 // Check that GetIDByWindow() returns |LauncherID| of the active tab. | |
1585 IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, | |
1586 MatchingLauncherIDandActiveTab) { | |
1587 ChromeLauncherControllerPerApp* controller = | |
1588 static_cast<ChromeLauncherControllerPerApp*>(launcher_->delegate()); | |
1589 | |
1590 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
1591 EXPECT_EQ(1, browser()->tab_strip_model()->count()); | |
1592 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); | |
1593 EXPECT_EQ(2, model_->item_count()); | |
1594 | |
1595 aura::Window* window = browser()->window()->GetNativeWindow(); | |
1596 | |
1597 int browser_index = ash::launcher::GetBrowserItemIndex(*model_); | |
1598 ash::LauncherID browser_id = model_->items()[browser_index].id; | |
1599 EXPECT_EQ(browser_id, controller->GetIDByWindow(window)); | |
1600 | |
1601 ash::LauncherID app_id = CreateShortcut("app1"); | |
1602 EXPECT_EQ(3, model_->item_count()); | |
1603 | |
1604 // Creates a new tab for "app1" and checks that GetIDByWindow() returns | |
1605 // |LauncherID| of "app1". | |
1606 ActivateLauncherItem(model_->ItemIndexByID(app_id)); | |
1607 EXPECT_EQ(2, browser()->tab_strip_model()->count()); | |
1608 EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); | |
1609 EXPECT_EQ(app_id, controller->GetIDByWindow(window)); | |
1610 | |
1611 // Makes tab at index 0(NTP) as an active tab and checks that GetIDByWindow() | |
1612 // returns |LauncherID| of browser shortcut. | |
1613 browser()->tab_strip_model()->ActivateTabAt(0, false); | |
1614 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); | |
1615 EXPECT_EQ(browser_id, controller->GetIDByWindow(window)); | |
1616 } | |
OLD | NEW |