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/launcher/launcher.h" | |
12 #include "ash/launcher/launcher_model.h" | |
13 #include "ash/shell.h" | |
14 #include "ash/test/launcher_view_test_api.h" | |
15 #include "ash/test/shell_test_api.h" | |
16 #include "ash/wm/window_util.h" | |
17 #include "base/command_line.h" | |
18 #include "base/strings/stringprintf.h" | |
19 #include "base/strings/utf_string_conversions.h" | |
20 #include "chrome/browser/apps/app_browsertest_util.h" | |
21 #include "chrome/browser/automation/automation_util.h" | |
22 #include "chrome/browser/chrome_notification_types.h" | |
23 #include "chrome/browser/extensions/extension_apitest.h" | |
24 #include "chrome/browser/extensions/extension_browsertest.h" | |
25 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
26 #include "chrome/browser/extensions/extension_service.h" | |
27 #include "chrome/browser/extensions/extension_system.h" | |
28 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
29 #include "chrome/browser/profiles/profile.h" | |
30 #include "chrome/browser/ui/browser.h" | |
31 #include "chrome/browser/ui/browser_commands.h" | |
32 #include "chrome/browser/ui/browser_window.h" | |
33 #include "chrome/browser/ui/extensions/application_launch.h" | |
34 #include "chrome/browser/ui/host_desktop.h" | |
35 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
36 #include "chrome/common/chrome_switches.h" | |
37 #include "chrome/common/extensions/extension_constants.h" | |
38 #include "chrome/test/base/ui_test_utils.h" | |
39 #include "content/public/browser/notification_service.h" | |
40 #include "content/public/browser/notification_source.h" | |
41 #include "content/public/browser/web_contents.h" | |
42 #include "testing/gtest/include/gtest/gtest.h" | |
43 #include "ui/aura/client/aura_constants.h" | |
44 #include "ui/aura/window.h" | |
45 | |
46 using apps::ShellWindow; | |
47 using extensions::Extension; | |
48 using content::WebContents; | |
49 | |
50 class LauncherPlatformAppBrowserTest | |
51 : public extensions::PlatformAppBrowserTest { | |
52 protected: | |
53 LauncherPlatformAppBrowserTest() | |
54 : launcher_(NULL), | |
55 controller_(NULL) { | |
56 } | |
57 | |
58 virtual ~LauncherPlatformAppBrowserTest() {} | |
59 | |
60 ash::LauncherModel* launcher_model() { | |
61 return ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model(); | |
62 } | |
63 | |
64 virtual void RunTestOnMainThreadLoop() OVERRIDE { | |
65 launcher_ = ash::Launcher::ForPrimaryDisplay(); | |
66 controller_ = static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
67 return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop(); | |
68 } | |
69 | |
70 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
71 PlatformAppBrowserTest::SetUpCommandLine(command_line); | |
72 command_line->AppendSwitch(ash::switches::kAshDisablePerAppLauncher); | |
73 } | |
74 | |
75 ash::LauncherID CreateAppShortcutLauncherItem(const std::string& name) { | |
76 return controller_->CreateAppShortcutLauncherItem( | |
77 name, controller_->model()->item_count()); | |
78 } | |
79 | |
80 const ash::LauncherItem& GetLastLauncherItem() { | |
81 // Unless there are any panels, the item at index [count - 1] will be | |
82 // the app list, and the item at [count - 2] will be the desited item. | |
83 return launcher_model()->items()[launcher_model()->item_count() - 2]; | |
84 } | |
85 | |
86 const ash::LauncherItem& GetLastLauncherPanelItem() { | |
87 // Panels show up on the right side of the launcher, so the desired item | |
88 // will be the last one. | |
89 return launcher_model()->items()[launcher_model()->item_count() - 1]; | |
90 } | |
91 | |
92 ash::Launcher* launcher_; | |
93 ChromeLauncherController* controller_; | |
94 }; | |
95 | |
96 class LauncherAppBrowserTest : public ExtensionBrowserTest { | |
97 protected: | |
98 LauncherAppBrowserTest() | |
99 : launcher_(NULL), | |
100 model_(NULL) { | |
101 } | |
102 | |
103 virtual ~LauncherAppBrowserTest() {} | |
104 | |
105 virtual void RunTestOnMainThreadLoop() OVERRIDE { | |
106 launcher_ = ash::Launcher::ForPrimaryDisplay(); | |
107 model_ = | |
108 ash::test::ShellTestApi(ash::Shell::GetInstance()).launcher_model(); | |
109 return ExtensionBrowserTest::RunTestOnMainThreadLoop(); | |
110 } | |
111 | |
112 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
113 ExtensionBrowserTest::SetUpCommandLine(command_line); | |
114 command_line->AppendSwitch(ash::switches::kAshDisablePerAppLauncher); | |
115 } | |
116 | |
117 const Extension* LoadAndLaunchExtension( | |
118 const char* name, | |
119 extension_misc::LaunchContainer container, | |
120 WindowOpenDisposition disposition) { | |
121 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name))); | |
122 | |
123 ExtensionService* service = extensions::ExtensionSystem::Get( | |
124 browser()->profile())->extension_service(); | |
125 const Extension* extension = | |
126 service->GetExtensionById(last_loaded_extension_id_, false); | |
127 EXPECT_TRUE(extension); | |
128 | |
129 chrome::OpenApplication(chrome::AppLaunchParams( | |
130 browser()->profile(), extension, container, disposition)); | |
131 return extension; | |
132 } | |
133 | |
134 ash::LauncherID CreateShortcut(const char* name) { | |
135 ExtensionService* service = extensions::ExtensionSystem::Get( | |
136 browser()->profile())->extension_service(); | |
137 LoadExtension(test_data_dir_.AppendASCII(name)); | |
138 | |
139 // First get app_id. | |
140 const Extension* extension = | |
141 service->GetExtensionById(last_loaded_extension_id_, false); | |
142 const std::string app_id = extension->id(); | |
143 | |
144 // Then create a shortcut. | |
145 ChromeLauncherController* controller = | |
146 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
147 int item_count = model_->item_count(); | |
148 ash::LauncherID shortcut_id = controller->CreateAppShortcutLauncherItem( | |
149 app_id, item_count); | |
150 controller->PersistPinnedState(); | |
151 EXPECT_EQ(++item_count, model_->item_count()); | |
152 ash::LauncherItem item = *model_->ItemByID(shortcut_id); | |
153 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
154 return item.id; | |
155 } | |
156 | |
157 ash::LauncherID PinFakeApp(const std::string& name) { | |
158 ChromeLauncherController* controller = | |
159 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
160 return controller->CreateAppShortcutLauncherItem( | |
161 name, model_->item_count()); | |
162 } | |
163 | |
164 ash::Launcher* launcher_; | |
165 ash::LauncherModel* model_; | |
166 }; | |
167 | |
168 // Test that we can launch a platform app and get a running item. | |
169 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) { | |
170 int item_count = launcher_model()->item_count(); | |
171 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
172 ShellWindow* window = CreateShellWindow(extension); | |
173 ++item_count; | |
174 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
175 const ash::LauncherItem& item = GetLastLauncherItem(); | |
176 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); | |
177 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
178 CloseShellWindow(window); | |
179 --item_count; | |
180 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
181 } | |
182 | |
183 // Test that we can launch a platform app that already has a shortcut. | |
184 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) { | |
185 int item_count = launcher_model()->item_count(); | |
186 | |
187 // First get app_id. | |
188 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
189 const std::string app_id = extension->id(); | |
190 | |
191 // Then create a shortcut. | |
192 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); | |
193 ++item_count; | |
194 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
195 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id); | |
196 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
197 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
198 | |
199 // Open a window. Confirm the item is now running. | |
200 ShellWindow* window = CreateShellWindow(extension); | |
201 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
202 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
203 item = *launcher_model()->ItemByID(shortcut_id); | |
204 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
205 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
206 | |
207 // Then close it, make sure there's still an item. | |
208 CloseShellWindow(window); | |
209 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
210 item = *launcher_model()->ItemByID(shortcut_id); | |
211 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
212 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
213 } | |
214 | |
215 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) { | |
216 // Run. | |
217 int item_count = launcher_model()->item_count(); | |
218 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
219 ShellWindow* window = CreateShellWindow(extension); | |
220 ++item_count; | |
221 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
222 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
223 ash::LauncherID id = item1.id; | |
224 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
225 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
226 | |
227 // Create a shortcut. The app item should be after it. | |
228 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); | |
229 ++item_count; | |
230 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
231 EXPECT_LT(launcher_model()->ItemIndexByID(foo_id), | |
232 launcher_model()->ItemIndexByID(id)); | |
233 | |
234 // Pin the app. The item should remain. | |
235 controller_->Pin(id); | |
236 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
237 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(id); | |
238 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type); | |
239 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
240 | |
241 // New shortcuts should come after the item. | |
242 ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar"); | |
243 ++item_count; | |
244 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
245 EXPECT_LT(launcher_model()->ItemIndexByID(id), | |
246 launcher_model()->ItemIndexByID(bar_id)); | |
247 | |
248 // Then close it, make sure the item remains. | |
249 CloseShellWindow(window); | |
250 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
251 } | |
252 | |
253 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) { | |
254 int item_count = launcher_model()->item_count(); | |
255 | |
256 // First get app_id. | |
257 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
258 const std::string app_id = extension->id(); | |
259 | |
260 // Then create a shortcut. | |
261 ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id); | |
262 ++item_count; | |
263 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
264 ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id); | |
265 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
266 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
267 | |
268 // Create a second shortcut. This will be needed to force the first one to | |
269 // move once it gets unpinned. | |
270 ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo"); | |
271 ++item_count; | |
272 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
273 EXPECT_LT(launcher_model()->ItemIndexByID(shortcut_id), | |
274 launcher_model()->ItemIndexByID(foo_id)); | |
275 | |
276 // Open a window. Confirm the item is now running. | |
277 ShellWindow* window = CreateShellWindow(extension); | |
278 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
279 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
280 item = *launcher_model()->ItemByID(shortcut_id); | |
281 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type); | |
282 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
283 | |
284 // Unpin the app. The item should remain. | |
285 controller_->Unpin(shortcut_id); | |
286 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
287 item = *launcher_model()->ItemByID(shortcut_id); | |
288 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type); | |
289 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
290 // The item should have moved after the other shortcuts. | |
291 EXPECT_GT(launcher_model()->ItemIndexByID(shortcut_id), | |
292 launcher_model()->ItemIndexByID(foo_id)); | |
293 | |
294 // Then close it, make sure the item's gone. | |
295 CloseShellWindow(window); | |
296 --item_count; | |
297 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
298 } | |
299 | |
300 // Test that we can launch a platform app with more than one window. | |
301 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) { | |
302 int item_count = launcher_model()->item_count(); | |
303 | |
304 // First run app. | |
305 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
306 ShellWindow* window1 = CreateShellWindow(extension); | |
307 ++item_count; | |
308 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
309 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
310 ash::LauncherID item_id = item1.id; | |
311 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
312 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
313 | |
314 // Add second window. | |
315 ShellWindow* window2 = CreateShellWindow(extension); | |
316 // Confirm item stays. | |
317 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
318 const ash::LauncherItem& item2 = *launcher_model()->ItemByID(item_id); | |
319 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
320 | |
321 // Close second window. | |
322 CloseShellWindow(window2); | |
323 // Confirm item stays. | |
324 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
325 const ash::LauncherItem& item3 = *launcher_model()->ItemByID(item_id); | |
326 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status); | |
327 | |
328 // Close first window. | |
329 CloseShellWindow(window1); | |
330 // Confirm item is removed. | |
331 --item_count; | |
332 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
333 } | |
334 | |
335 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) { | |
336 int item_count = launcher_model()->item_count(); | |
337 | |
338 // First run app. | |
339 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
340 ShellWindow* window1 = CreateShellWindow(extension1); | |
341 ++item_count; | |
342 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
343 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
344 ash::LauncherID item_id1 = item1.id; | |
345 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
346 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
347 | |
348 // Then run second app. | |
349 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); | |
350 ShellWindow* window2 = CreateShellWindow(extension2); | |
351 ++item_count; | |
352 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
353 const ash::LauncherItem& item2 = GetLastLauncherItem(); | |
354 ash::LauncherID item_id2 = item2.id; | |
355 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); | |
356 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
357 | |
358 EXPECT_NE(item_id1, item_id2); | |
359 EXPECT_EQ(ash::STATUS_RUNNING, | |
360 launcher_model()->ItemByID(item_id1)->status); | |
361 | |
362 // Close second app. | |
363 CloseShellWindow(window2); | |
364 --item_count; | |
365 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
366 // First app should be active again. | |
367 EXPECT_EQ(ash::STATUS_ACTIVE, | |
368 launcher_model()->ItemByID(item_id1)->status); | |
369 | |
370 // Close first app. | |
371 CloseShellWindow(window1); | |
372 --item_count; | |
373 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
374 } | |
375 | |
376 // Test that we can launch a platform app panel and get a running item. | |
377 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) { | |
378 int item_count = launcher_model()->item_count(); | |
379 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
380 ShellWindow::CreateParams params; | |
381 params.window_type = ShellWindow::WINDOW_TYPE_PANEL; | |
382 params.focused = false; | |
383 ShellWindow* window = CreateShellWindowFromParams(extension, params); | |
384 ++item_count; | |
385 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
386 const ash::LauncherItem& item = GetLastLauncherPanelItem(); | |
387 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); | |
388 // Opening a panel does not activate it. | |
389 EXPECT_EQ(ash::STATUS_RUNNING, item.status); | |
390 CloseShellWindow(window); | |
391 --item_count; | |
392 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
393 } | |
394 | |
395 #if defined(OS_CHROMEOS) | |
396 #define MAYBE_WindowActivation DISABLED_WindowActivation | |
397 #else | |
398 #define MAYBE_WindowActivation WindowActivation | |
399 #endif | |
400 // Confirm that app windows can be reactivated by clicking their icons and that | |
401 // the correct activation order is maintained. | |
402 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MAYBE_WindowActivation) { | |
403 int item_count = launcher_model()->item_count(); | |
404 | |
405 // First run app. | |
406 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
407 ShellWindow* window1 = CreateShellWindow(extension1); | |
408 ++item_count; | |
409 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
410 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
411 ash::LauncherID item_id1 = item1.id; | |
412 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
413 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
414 | |
415 // Then run second app. | |
416 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2"); | |
417 ShellWindow* window2 = CreateShellWindow(extension2); | |
418 ++item_count; | |
419 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
420 const ash::LauncherItem& item2 = GetLastLauncherItem(); | |
421 ash::LauncherID item_id2 = item2.id; | |
422 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type); | |
423 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
424 | |
425 EXPECT_NE(item_id1, item_id2); | |
426 EXPECT_EQ(ash::STATUS_RUNNING, | |
427 launcher_model()->ItemByID(item_id1)->status); | |
428 | |
429 // Activate first one. | |
430 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
431 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status); | |
432 EXPECT_EQ(ash::STATUS_RUNNING, | |
433 launcher_model()->ItemByID(item_id2)->status); | |
434 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
435 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
436 | |
437 // Activate second one. | |
438 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2)); | |
439 EXPECT_EQ(ash::STATUS_RUNNING, | |
440 launcher_model()->ItemByID(item_id1)->status); | |
441 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id2)->status); | |
442 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
443 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
444 | |
445 // Add window for app1. This will activate it. | |
446 ShellWindow* window1b = CreateShellWindow(extension1); | |
447 ash::wm::ActivateWindow(window1b->GetNativeWindow()); | |
448 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
449 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
450 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
451 | |
452 // Activate launcher item for app1, this will activate the first app window. | |
453 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
454 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
455 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
456 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
457 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
458 | |
459 // Activate the second app again | |
460 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2)); | |
461 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
462 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
463 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
464 | |
465 // Activate the first app again | |
466 launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1)); | |
467 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
468 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
469 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
470 | |
471 // Close second app. | |
472 CloseShellWindow(window2); | |
473 --item_count; | |
474 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
475 // First app should be active again. | |
476 EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status); | |
477 | |
478 // Close first app. | |
479 CloseShellWindow(window1b); | |
480 CloseShellWindow(window1); | |
481 --item_count; | |
482 EXPECT_EQ(item_count, launcher_model()->item_count()); | |
483 } | |
484 | |
485 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) { | |
486 int item_count = launcher_model()->item_count(); | |
487 | |
488 // First run app. | |
489 const Extension* extension1 = LoadAndLaunchPlatformApp("launch"); | |
490 CreateShellWindow(extension1); | |
491 ++item_count; | |
492 ASSERT_EQ(item_count, launcher_model()->item_count()); | |
493 const ash::LauncherItem& item1 = GetLastLauncherItem(); | |
494 ash::LauncherID item_id1 = item1.id; | |
495 EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type); | |
496 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
497 | |
498 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow()); | |
499 EXPECT_EQ(ash::STATUS_RUNNING, | |
500 launcher_model()->ItemByID(item_id1)->status); | |
501 } | |
502 | |
503 // Test that draw attention sets the launcher item status. | |
504 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, DrawAttention) { | |
505 const Extension* extension = LoadAndLaunchPlatformApp("launch"); | |
506 ShellWindow* shell_window = CreateShellWindow(extension); | |
507 const ash::LauncherItem& item = GetLastLauncherItem(); | |
508 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
509 // Set Minimize window to deactivate the launcher item. | |
510 shell_window->GetBaseWindow()->Minimize(); | |
511 EXPECT_EQ(ash::STATUS_RUNNING, item.status); | |
512 // Set DrawAttention property. | |
513 shell_window->GetNativeWindow()->SetProperty( | |
514 aura::client::kDrawAttentionKey, true); | |
515 EXPECT_EQ(ash::STATUS_ATTENTION, item.status); | |
516 // Activate window, should clear DrawAttention. | |
517 shell_window->GetBaseWindow()->Activate(); | |
518 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
519 EXPECT_FALSE(shell_window->GetNativeWindow()->GetProperty( | |
520 aura::client::kDrawAttentionKey)); | |
521 } | |
522 | |
523 // Test that we can launch an app with a shortcut. | |
524 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchPinned) { | |
525 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
526 int tab_count = tab_strip->count(); | |
527 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
528 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
529 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
530 EXPECT_EQ(++tab_count, tab_strip->count()); | |
531 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
532 WebContents* tab = tab_strip->GetActiveWebContents(); | |
533 content::WindowedNotificationObserver close_observer( | |
534 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
535 content::Source<WebContents>(tab)); | |
536 browser()->tab_strip_model()->CloseSelectedTabs(); | |
537 close_observer.Wait(); | |
538 EXPECT_EQ(--tab_count, tab_strip->count()); | |
539 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
540 } | |
541 | |
542 // Launch the app first and then create the shortcut. | |
543 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchUnpinned) { | |
544 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
545 int tab_count = tab_strip->count(); | |
546 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, | |
547 NEW_FOREGROUND_TAB); | |
548 EXPECT_EQ(++tab_count, tab_strip->count()); | |
549 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
550 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
551 WebContents* tab = tab_strip->GetActiveWebContents(); | |
552 content::WindowedNotificationObserver close_observer( | |
553 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
554 content::Source<WebContents>(tab)); | |
555 browser()->tab_strip_model()->CloseSelectedTabs(); | |
556 close_observer.Wait(); | |
557 EXPECT_EQ(--tab_count, tab_strip->count()); | |
558 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
559 } | |
560 | |
561 // Launches an app in the background and then tries to open it. This is test for | |
562 // a crash we had. | |
563 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchInBackground) { | |
564 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
565 int tab_count = tab_strip->count(); | |
566 LoadAndLaunchExtension("app1", extension_misc::LAUNCH_TAB, | |
567 NEW_BACKGROUND_TAB); | |
568 EXPECT_EQ(++tab_count, tab_strip->count()); | |
569 ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id_, 0); | |
570 } | |
571 | |
572 // Confirm that clicking a icon for an app running in one of 2 maxmized windows | |
573 // activates the right window. | |
574 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchMaximized) { | |
575 aura::Window* window1 = browser()->window()->GetNativeWindow(); | |
576 ash::wm::MaximizeWindow(window1); | |
577 content::WindowedNotificationObserver open_observer( | |
578 chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
579 content::NotificationService::AllSources()); | |
580 chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH); | |
581 open_observer.Wait(); | |
582 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr(); | |
583 aura::Window* window2 = browser2->window()->GetNativeWindow(); | |
584 TabStripModel* tab_strip = browser2->tab_strip_model(); | |
585 int tab_count = tab_strip->count(); | |
586 ash::wm::MaximizeWindow(window2); | |
587 | |
588 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
589 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
590 EXPECT_EQ(++tab_count, tab_strip->count()); | |
591 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
592 | |
593 window1->Show(); | |
594 ash::wm::ActivateWindow(window1); | |
595 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); | |
596 | |
597 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
598 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
599 } | |
600 | |
601 // Activating the same app multiple times should launch only a single copy. | |
602 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateApp) { | |
603 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
604 int tab_count = tab_strip->count(); | |
605 const Extension* extension = | |
606 LoadExtension(test_data_dir_.AppendASCII("app1")); | |
607 | |
608 ChromeLauncherController::instance()->ActivateApp(extension->id(), 0); | |
609 EXPECT_EQ(++tab_count, tab_strip->count()); | |
610 ChromeLauncherController::instance()->ActivateApp(extension->id(), 0); | |
611 EXPECT_EQ(tab_count, tab_strip->count()); | |
612 } | |
613 | |
614 // Launching the same app multiple times should launch a copy for each call. | |
615 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchApp) { | |
616 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
617 int tab_count = tab_strip->count(); | |
618 const Extension* extension = | |
619 LoadExtension(test_data_dir_.AppendASCII("app1")); | |
620 | |
621 ChromeLauncherController::instance()->LaunchApp(extension->id(), 0); | |
622 EXPECT_EQ(++tab_count, tab_strip->count()); | |
623 ChromeLauncherController::instance()->LaunchApp(extension->id(), 0); | |
624 EXPECT_EQ(++tab_count, tab_strip->count()); | |
625 } | |
626 | |
627 // Launch 2 apps and toggle which is active. | |
628 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleApps) { | |
629 int item_count = model_->item_count(); | |
630 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
631 int tab_count = tab_strip->count(); | |
632 ash::LauncherID shortcut1 = CreateShortcut("app1"); | |
633 EXPECT_EQ(++item_count, model_->item_count()); | |
634 ash::LauncherID shortcut2 = CreateShortcut("app2"); | |
635 EXPECT_EQ(++item_count, model_->item_count()); | |
636 | |
637 // Launch first app. | |
638 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
639 EXPECT_EQ(++tab_count, tab_strip->count()); | |
640 WebContents* tab1 = tab_strip->GetActiveWebContents(); | |
641 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
642 | |
643 // Launch second app. | |
644 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); | |
645 EXPECT_EQ(++tab_count, tab_strip->count()); | |
646 WebContents* tab2 = tab_strip->GetActiveWebContents(); | |
647 ASSERT_NE(tab1, tab2); | |
648 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
649 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
650 | |
651 // Reactivate first app. | |
652 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
653 EXPECT_EQ(tab_count, tab_strip->count()); | |
654 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
655 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
656 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
657 | |
658 // Open second tab for second app. This should activate it. | |
659 ui_test_utils::NavigateToURLWithDisposition( | |
660 browser(), | |
661 GURL("http://www.example.com/path3/foo.html"), | |
662 NEW_FOREGROUND_TAB, | |
663 0); | |
664 EXPECT_EQ(++tab_count, tab_strip->count()); | |
665 WebContents* tab3 = tab_strip->GetActiveWebContents(); | |
666 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
667 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
668 | |
669 // Reactivate first app. | |
670 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut1)); | |
671 EXPECT_EQ(tab_count, tab_strip->count()); | |
672 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
673 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
674 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
675 | |
676 // And second again. This time the second tab should become active. | |
677 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut2)); | |
678 EXPECT_EQ(tab_count, tab_strip->count()); | |
679 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab3); | |
680 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
681 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
682 } | |
683 | |
684 // Confirm that a page can be navigated from and to while maintaining the | |
685 // correct running state. | |
686 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, Navigation) { | |
687 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
688 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
689 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
690 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
691 | |
692 // Navigate away. | |
693 ui_test_utils::NavigateToURL( | |
694 browser(), GURL("http://www.example.com/path0/bar.html")); | |
695 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
696 | |
697 // Navigate back. | |
698 ui_test_utils::NavigateToURL( | |
699 browser(), GURL("http://www.example.com/path1/foo.html")); | |
700 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
701 } | |
702 | |
703 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleOwnedTabs) { | |
704 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
705 int tab_count = tab_strip->count(); | |
706 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
707 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
708 EXPECT_EQ(++tab_count, tab_strip->count()); | |
709 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
710 | |
711 // Create new tab owned by app. | |
712 ui_test_utils::NavigateToURLWithDisposition( | |
713 browser(), | |
714 GURL("http://www.example.com/path2/bar.html"), | |
715 NEW_FOREGROUND_TAB, | |
716 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
717 EXPECT_EQ(++tab_count, tab_strip->count()); | |
718 // Confirm app is still active. | |
719 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
720 WebContents* second_tab = tab_strip->GetActiveWebContents(); | |
721 | |
722 // Create new tab not owned by app. | |
723 ui_test_utils::NavigateToURLWithDisposition( | |
724 browser(), | |
725 GURL("http://www.example.com/path3/foo.html"), | |
726 NEW_FOREGROUND_TAB, | |
727 0); | |
728 EXPECT_EQ(++tab_count, tab_strip->count()); | |
729 // No longer active. | |
730 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
731 | |
732 // Activating app makes second tab active again. | |
733 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
734 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
735 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); | |
736 } | |
737 | |
738 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilter) { | |
739 ChromeLauncherController* controller = | |
740 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
741 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
742 int tab_count = tab_strip->count(); | |
743 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
744 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
745 EXPECT_EQ(++tab_count, tab_strip->count()); | |
746 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
747 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
748 | |
749 controller->SetRefocusURLPatternForTest( | |
750 shortcut_id, GURL("http://www.example.com/path1/*")); | |
751 // Create new tab owned by app. | |
752 ui_test_utils::NavigateToURLWithDisposition( | |
753 browser(), | |
754 GURL("http://www.example.com/path2/bar.html"), | |
755 NEW_FOREGROUND_TAB, | |
756 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
757 EXPECT_EQ(++tab_count, tab_strip->count()); | |
758 // Confirm app is still active. | |
759 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
760 | |
761 // Create new tab not owned by app. | |
762 ui_test_utils::NavigateToURLWithDisposition( | |
763 browser(), | |
764 GURL("http://www.example.com/path3/foo.html"), | |
765 NEW_FOREGROUND_TAB, | |
766 0); | |
767 EXPECT_EQ(++tab_count, tab_strip->count()); | |
768 // No longer active. | |
769 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
770 | |
771 // Activating app makes first tab active again, because second tab isn't | |
772 // in its refocus url path. | |
773 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
774 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
775 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); | |
776 } | |
777 | |
778 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilterLaunch) { | |
779 ChromeLauncherController* controller = | |
780 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
781 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
782 int tab_count = tab_strip->count(); | |
783 ash::LauncherID shortcut_id = CreateShortcut("app1"); | |
784 controller->SetRefocusURLPatternForTest( | |
785 shortcut_id, GURL("http://www.example.com/path1/*")); | |
786 | |
787 // Create new tab owned by app. | |
788 ui_test_utils::NavigateToURLWithDisposition( | |
789 browser(), | |
790 GURL("http://www.example.com/path2/bar.html"), | |
791 NEW_FOREGROUND_TAB, | |
792 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
793 EXPECT_EQ(++tab_count, tab_strip->count()); | |
794 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
795 // Confirm app is active. | |
796 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
797 | |
798 // Activating app should launch new tab, because second tab isn't | |
799 // in its refocus url path. | |
800 launcher_->ActivateLauncherItem(model_->ItemIndexByID(shortcut_id)); | |
801 EXPECT_EQ(++tab_count, tab_strip->count()); | |
802 WebContents* second_tab = tab_strip->GetActiveWebContents(); | |
803 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
804 EXPECT_NE(first_tab, second_tab); | |
805 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); | |
806 } | |
807 | |
808 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, OverflowBubble) { | |
809 // Make sure to have a browser window | |
810 chrome::NewTab(browser()); | |
811 | |
812 // No overflow yet. | |
813 EXPECT_FALSE(launcher_->IsShowingOverflowBubble()); | |
814 | |
815 ash::test::LauncherViewTestAPI test(launcher_->GetLauncherViewForTest()); | |
816 | |
817 int items_added = 0; | |
818 while (!test.IsOverflowButtonVisible()) { | |
819 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); | |
820 PinFakeApp(fake_app_id); | |
821 | |
822 ++items_added; | |
823 ASSERT_LT(items_added, 10000); | |
824 } | |
825 | |
826 // Now show overflow bubble. | |
827 test.ShowOverflowBubble(); | |
828 EXPECT_TRUE(launcher_->IsShowingOverflowBubble()); | |
829 | |
830 // Unpin first pinned app and there should be no crash. | |
831 ChromeLauncherController* controller = | |
832 static_cast<ChromeLauncherController*>(launcher_->delegate()); | |
833 controller->UnpinAppsWithID(std::string("fake_app_0")); | |
834 | |
835 test.RunMessageLoopUntilAnimationsDone(); | |
836 EXPECT_FALSE(launcher_->IsShowingOverflowBubble()); | |
837 } | |
OLD | NEW |