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