blob: 8c0cfbaf15ab9e731b6b49df6b28ce39a1c2686f [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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
Ben Murdoch2385ea32013-08-06 11:01:04 +01007#include "apps/native_app_window.h"
Ben Murdocheb525c52013-07-10 11:40:50 +01008#include "apps/shell_window.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01009#include "ash/ash_switches.h"
10#include "ash/display/display_controller.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "ash/launcher/launcher.h"
12#include "ash/launcher/launcher_model.h"
13#include "ash/launcher/launcher_util.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010014#include "ash/launcher/launcher_view.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "ash/shell.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010016#include "ash/test/launcher_view_test_api.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "ash/test/shell_test_api.h"
18#include "ash/wm/window_util.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010019#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "chrome/browser/automation/automation_util.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010021#include "chrome/browser/chrome_notification_types.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000022#include "chrome/browser/extensions/extension_apitest.h"
23#include "chrome/browser/extensions/extension_browsertest.h"
24#include "chrome/browser/extensions/extension_function_test_utils.h"
25#include "chrome/browser/extensions/extension_service.h"
26#include "chrome/browser/extensions/extension_system.h"
27#include "chrome/browser/extensions/extension_test_message_listener.h"
28#include "chrome/browser/extensions/platform_app_browsertest_util.h"
29#include "chrome/browser/extensions/shell_window_registry.h"
30#include "chrome/browser/profiles/profile.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010031#include "chrome/browser/ui/app_list/app_list_service.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010032#include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000033#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"
Ben Murdochbb1529c2013-08-08 10:24:53 +010038#include "chrome/browser/ui/browser_list.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000039#include "chrome/browser/ui/browser_window.h"
40#include "chrome/browser/ui/extensions/application_launch.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000041#include "chrome/browser/ui/host_desktop.h"
42#include "chrome/browser/ui/tabs/tab_strip_model.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000043#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"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010049#include "extensions/common/switches.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000050#include "testing/gtest/include/gtest/gtest.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010051#include "ui/app_list/views/apps_grid_view.h"
52#include "ui/aura/test/event_generator.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000053#include "ui/aura/window.h"
54#include "ui/base/events/event.h"
55
Ben Murdocheb525c52013-07-10 11:40:50 +010056using apps::ShellWindow;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000057using extensions::Extension;
58using content::WebContents;
59
60namespace {
61
62class 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
74class TestShellWindowRegistryObserver
75 : public extensions::ShellWindowRegistry::Observer {
76 public:
77 explicit TestShellWindowRegistryObserver(Profile* profile)
78 : profile_(profile),
79 icon_updates_(0) {
80 extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
81 }
82
83 virtual ~TestShellWindowRegistryObserver() {
84 extensions::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.
109class 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100164 // Activate the launcher item with the given |id|.
165 void ActivateLauncherItem(int id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100166 launcher_->ActivateLauncherItem(id);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100167 }
168
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 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.
179class 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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100198 LauncherItemController* item_controller =
199 controller->GetBrowserShortcutLauncherItemController();
200 int items = item_controller->GetApplicationList(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000201 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100249 // Activate the launcher item with the given |id|.
250 void ActivateLauncherItem(int id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100251 launcher_->ActivateLauncherItem(id);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100252 }
253
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000254 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.
264class 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100280// Since the default for minimizing on click might change, I added both classes
281// to either get the minimize on click or not.
282class 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
299typedef LauncherPlatformPerAppAppBrowserTest
300 LauncherPerAppAppBrowserMinimizeOnClick;
301
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000302// Test that we can launch a platform app and get a running item.
303IN_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.
318IN_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
349IN_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
387IN_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.
435IN_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
472IN_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.
516IN_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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100544 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000545 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100552 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000553 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100567 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000568 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
569 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100570 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
571 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000572
573 // Activate the second app again
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100574 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000575 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100580 ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
581 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100583 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000584
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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100600IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserNoMinimizeOnClick,
601 AppClickBehavior) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000602 // 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);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100612 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());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000618 // 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);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100623 // Clicking the item should activate the window.
624 item1_controller->Clicked(click_event);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000625 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();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100631 item1_controller->Clicked(click_event);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000632 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
633 EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
634 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
635}
636
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100637// Confirm the minimizing click behavior for apps.
638IN_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.
696IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest,
697 AppPanelClickBehavior) {
698 // Enable experimental APIs to allow panel creation.
699 CommandLine::ForCurrentProcess()->AppendSwitch(
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100700 extensions::switches::kEnableExperimentalExtensionApis);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100701 // 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
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000732IN_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
752IN_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(
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100757 extensions::switches::kEnableExperimentalExtensionApis);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000758
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.
797IN_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);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100802 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000803 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.
816IN_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.
836IN_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.
847IN_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");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100862 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000863 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
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100870 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000871 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.
875IN_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.
888IN_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.
901IN_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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100911 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000912 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100917 ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000918 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100925 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000926 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100942 ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000943 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100949 ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000950 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.
958IN_PROC_BROWSER_TEST_F(LauncherPerAppAppBrowserTest, Navigation) {
959 ash::LauncherID shortcut_id = CreateShortcut("app1");
960 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100961 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000962 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
975IN_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");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100979 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000980 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001005 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001006 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1007 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
1008}
1009
1010IN_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");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001016 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001017 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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001045 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001046 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
1047 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
1048}
1049
1050IN_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.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001072 ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001073 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.
1081IN_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.
1126IN_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.
1158IN_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.
1180IN_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}
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001201
1202// Check that the keyboard activation of a launcher item tabs properly through
1203// the items at hand.
1204IN_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.
1260IN_PROC_BROWSER_TEST_F(LauncherPlatformPerAppAppBrowserTest,
1261 AltNumberAppsTabbing) {
1262 // First run app.
1263 const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001264 ui::BaseWindow* window1 = CreateShellWindow(extension1)->GetBaseWindow();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001265 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");
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001273 ui::BaseWindow* window2 = CreateShellWindow(extension2)->GetBaseWindow();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001274
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
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001283 ui::BaseWindow* window1a = CreateShellWindow(extension1)->GetBaseWindow();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001284
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.
1294IN_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.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001299 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001300 EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
1301 // A second activation should not create a new instance.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001302 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001303 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.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001314 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001315 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001316 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001317 EXPECT_EQ(window2, ash::wm::GetActiveWindow());
1318
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001319 // 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
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001329 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001330 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001331 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001332 EXPECT_EQ(window2, ash::wm::GetActiveWindow());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001333 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001334 EXPECT_EQ(window3, ash::wm::GetActiveWindow());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001335 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001336 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
1337
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001338 // 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.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001344 launcher_->ActivateLauncherItem(0);
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001345 EXPECT_EQ(window1, ash::wm::GetActiveWindow());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001346}
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001347
Ben Murdochbb1529c2013-08-08 10:24:53 +01001348// Checks that after a session restore, we do not start applications on an
1349// activation.
1350IN_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
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001408// Do various drag and drop interaction tests between the application list and
1409// the launcher.
1410IN_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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001426 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001427 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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001448 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001449 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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001460 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001461
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
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001466 // 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();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001470 EXPECT_EQ(2, model_->item_count());
1471 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1472
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001473 // Dropping it should keep the launcher as it originally was.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001474 generator.ReleaseLeftButton();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001475 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001476 EXPECT_EQ(2, model_->item_count());
1477 // There are a few animations which need finishing before we can continue.
1478 test.RunMessageLoopUntilAnimationsDone();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001479 // Move the mouse outside of the launcher.
1480 generator.MoveMouseTo(0, 0);
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001481
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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001489 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001490 EXPECT_EQ(3, model_->item_count());
1491 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
1492 generator.ReleaseLeftButton();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001493 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001494 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());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001505 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001506 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();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001509 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001510 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}
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001513
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001514// Check that clicking on an app launcher item launches a new browser.
1515IN_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
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001550// Check LauncherItemController of Browser Shortcut functionality.
1551IN_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}