| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include "ash/public/cpp/app_launch_id.h" | |
| 10 #include "ash/public/cpp/shelf_item_delegate.h" | |
| 11 #include "ash/public/cpp/window_properties.h" | |
| 12 #include "ash/shelf/app_list_button.h" | |
| 13 #include "ash/shelf/shelf_button.h" | |
| 14 #include "ash/shelf/shelf_constants.h" | |
| 15 #include "ash/shelf/shelf_model.h" | |
| 16 #include "ash/shelf/shelf_view.h" | |
| 17 #include "ash/shelf/shelf_widget.h" | |
| 18 #include "ash/shelf/wm_shelf.h" | |
| 19 #include "ash/shell.h" | |
| 20 #include "ash/shell_port.h" | |
| 21 #include "ash/test/shelf_view_test_api.h" | |
| 22 #include "ash/wm/window_properties.h" | |
| 23 #include "ash/wm/window_state.h" | |
| 24 #include "ash/wm/window_state_aura.h" | |
| 25 #include "ash/wm/window_util.h" | |
| 26 #include "ash/wm_window.h" | |
| 27 #include "base/macros.h" | |
| 28 #include "base/run_loop.h" | |
| 29 #include "base/strings/stringprintf.h" | |
| 30 #include "base/strings/utf_string_conversions.h" | |
| 31 #include "build/build_config.h" | |
| 32 #include "chrome/browser/apps/app_browsertest_util.h" | |
| 33 #include "chrome/browser/chrome_notification_types.h" | |
| 34 #include "chrome/browser/extensions/extension_apitest.h" | |
| 35 #include "chrome/browser/extensions/extension_browsertest.h" | |
| 36 #include "chrome/browser/extensions/extension_function_test_utils.h" | |
| 37 #include "chrome/browser/extensions/extension_service.h" | |
| 38 #include "chrome/browser/extensions/launch_util.h" | |
| 39 #include "chrome/browser/profiles/profile.h" | |
| 40 #include "chrome/browser/ui/app_list/app_list_service.h" | |
| 41 #include "chrome/browser/ui/ash/app_list/test/app_list_service_ash_test_api.h" | |
| 42 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controll
er.h" | |
| 43 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" | |
| 44 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" | |
| 45 #include "chrome/browser/ui/ash/session_controller_client.h" | |
| 46 #include "chrome/browser/ui/browser.h" | |
| 47 #include "chrome/browser/ui/browser_commands.h" | |
| 48 #include "chrome/browser/ui/browser_finder.h" | |
| 49 #include "chrome/browser/ui/browser_list.h" | |
| 50 #include "chrome/browser/ui/browser_window.h" | |
| 51 #include "chrome/browser/ui/chrome_pages.h" | |
| 52 #include "chrome/browser/ui/extensions/app_launch_params.h" | |
| 53 #include "chrome/browser/ui/extensions/application_launch.h" | |
| 54 #include "chrome/browser/ui/settings_window_manager.h" | |
| 55 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
| 56 #include "chrome/browser/web_applications/web_app.h" | |
| 57 #include "chrome/common/chrome_switches.h" | |
| 58 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | |
| 59 #include "chrome/test/base/ui_test_utils.h" | |
| 60 #include "content/public/browser/notification_service.h" | |
| 61 #include "content/public/browser/notification_source.h" | |
| 62 #include "content/public/browser/web_contents.h" | |
| 63 #include "content/public/test/browser_test_utils.h" | |
| 64 #include "extensions/browser/app_window/app_window.h" | |
| 65 #include "extensions/browser/app_window/app_window_registry.h" | |
| 66 #include "extensions/browser/app_window/native_app_window.h" | |
| 67 #include "extensions/browser/extension_system.h" | |
| 68 #include "extensions/common/constants.h" | |
| 69 #include "extensions/common/switches.h" | |
| 70 #include "extensions/test/extension_test_message_listener.h" | |
| 71 #include "testing/gtest/include/gtest/gtest.h" | |
| 72 #include "ui/app_list/app_list_switches.h" | |
| 73 #include "ui/app_list/views/app_list_item_view.h" | |
| 74 #include "ui/app_list/views/apps_grid_view.h" | |
| 75 #include "ui/app_list/views/start_page_view.h" | |
| 76 #include "ui/app_list/views/tile_item_view.h" | |
| 77 #include "ui/aura/client/aura_constants.h" | |
| 78 #include "ui/aura/window.h" | |
| 79 #include "ui/base/window_open_disposition.h" | |
| 80 #include "ui/display/test/display_manager_test_api.h" | |
| 81 #include "ui/events/base_event_utils.h" | |
| 82 #include "ui/events/event.h" | |
| 83 #include "ui/events/event_constants.h" | |
| 84 #include "ui/events/test/event_generator.h" | |
| 85 | |
| 86 using ash::WmShelf; | |
| 87 using extensions::AppWindow; | |
| 88 using extensions::Extension; | |
| 89 using content::WebContents; | |
| 90 | |
| 91 namespace { | |
| 92 | |
| 93 ChromeLauncherControllerImpl* GetChromeLauncherControllerImpl() { | |
| 94 return static_cast<ChromeLauncherControllerImpl*>( | |
| 95 ChromeLauncherController::instance()); | |
| 96 } | |
| 97 | |
| 98 // A callback that records the action taken when a shelf item is selected. | |
| 99 void SelectItemCallback(ash::ShelfAction* action_taken, | |
| 100 base::RunLoop* run_loop, | |
| 101 ash::ShelfAction action, | |
| 102 base::Optional<ash::MenuItemList>) { | |
| 103 *action_taken = action; | |
| 104 run_loop->Quit(); | |
| 105 } | |
| 106 | |
| 107 // Calls ShelfItemDelegate::SelectItem with an event type and default arguments. | |
| 108 ash::ShelfAction SelectItem(ash::ShelfItemDelegate* delegate, | |
| 109 ui::EventType event_type) { | |
| 110 std::unique_ptr<ui::Event> event; | |
| 111 if (event_type == ui::ET_MOUSE_PRESSED) { | |
| 112 event = | |
| 113 base::MakeUnique<ui::MouseEvent>(event_type, gfx::Point(), gfx::Point(), | |
| 114 ui::EventTimeForNow(), ui::EF_NONE, 0); | |
| 115 } else if (event_type == ui::ET_KEY_RELEASED) { | |
| 116 event = base::MakeUnique<ui::KeyEvent>(event_type, ui::VKEY_UNKNOWN, | |
| 117 ui::EF_NONE); | |
| 118 } | |
| 119 | |
| 120 base::RunLoop run_loop; | |
| 121 ash::ShelfAction action = ash::SHELF_ACTION_NONE; | |
| 122 delegate->ItemSelected(std::move(event), display::kInvalidDisplayId, | |
| 123 ash::LAUNCH_FROM_UNKNOWN, | |
| 124 base::Bind(&SelectItemCallback, &action, &run_loop)); | |
| 125 run_loop.Run(); | |
| 126 return action; | |
| 127 } | |
| 128 | |
| 129 class TestEvent : public ui::Event { | |
| 130 public: | |
| 131 explicit TestEvent(ui::EventType type) | |
| 132 : ui::Event(type, base::TimeTicks(), 0) {} | |
| 133 ~TestEvent() override {} | |
| 134 | |
| 135 private: | |
| 136 DISALLOW_COPY_AND_ASSIGN(TestEvent); | |
| 137 }; | |
| 138 | |
| 139 class TestAppWindowRegistryObserver | |
| 140 : public extensions::AppWindowRegistry::Observer { | |
| 141 public: | |
| 142 explicit TestAppWindowRegistryObserver(Profile* profile) | |
| 143 : profile_(profile), icon_updates_(0) { | |
| 144 extensions::AppWindowRegistry::Get(profile_)->AddObserver(this); | |
| 145 } | |
| 146 | |
| 147 ~TestAppWindowRegistryObserver() override { | |
| 148 extensions::AppWindowRegistry::Get(profile_)->RemoveObserver(this); | |
| 149 } | |
| 150 | |
| 151 // Overridden from AppWindowRegistry::Observer: | |
| 152 void OnAppWindowIconChanged(AppWindow* app_window) override { | |
| 153 ++icon_updates_; | |
| 154 } | |
| 155 | |
| 156 int icon_updates() { return icon_updates_; } | |
| 157 | |
| 158 private: | |
| 159 Profile* profile_; | |
| 160 int icon_updates_; | |
| 161 | |
| 162 DISALLOW_COPY_AND_ASSIGN(TestAppWindowRegistryObserver); | |
| 163 }; | |
| 164 | |
| 165 // Click the "All Apps" button from the app launcher start page. Assumes that | |
| 166 // the app launcher is open to the start page. | |
| 167 // |display_origin| is the top-left corner of the active display, in screen | |
| 168 // coordinates. | |
| 169 void ClickAllAppsButtonFromStartPage(ui::test::EventGenerator* generator, | |
| 170 const gfx::Point& display_origin) { | |
| 171 AppListServiceAshTestApi service_test; | |
| 172 | |
| 173 app_list::StartPageView* start_page_view = service_test.GetStartPageView(); | |
| 174 DCHECK(start_page_view); | |
| 175 | |
| 176 app_list::TileItemView* all_apps_button = start_page_view->all_apps_button(); | |
| 177 gfx::Rect all_apps_rect = all_apps_button->GetBoundsInScreen(); | |
| 178 all_apps_rect.Offset(-display_origin.x(), -display_origin.y()); | |
| 179 generator->MoveMouseTo(all_apps_rect.CenterPoint().x(), | |
| 180 all_apps_rect.CenterPoint().y()); | |
| 181 generator->ClickLeftButton(); | |
| 182 base::RunLoop().RunUntilIdle(); | |
| 183 // Run Layout() to effectively complete the animation to the apps page. | |
| 184 service_test.LayoutContentsView(); | |
| 185 } | |
| 186 | |
| 187 // Find the browser that associated with |app_name|. | |
| 188 Browser* FindBrowserForApp(const std::string& app_name) { | |
| 189 for (auto* browser : *BrowserList::GetInstance()) { | |
| 190 std::string browser_app_name = | |
| 191 web_app::GetExtensionIdFromApplicationName(browser->app_name()); | |
| 192 if (browser_app_name == app_name) | |
| 193 return browser; | |
| 194 } | |
| 195 return nullptr; | |
| 196 } | |
| 197 | |
| 198 // Close |app_browser| and wait until it's closed. | |
| 199 void CloseAppBrowserWindow(Browser* app_browser) { | |
| 200 content::WindowedNotificationObserver close_observer( | |
| 201 chrome::NOTIFICATION_BROWSER_CLOSED, | |
| 202 content::Source<Browser>(app_browser)); | |
| 203 app_browser->window()->Close(); | |
| 204 close_observer.Wait(); | |
| 205 } | |
| 206 | |
| 207 // Close browsers from context menu | |
| 208 void CloseBrowserWindow(Browser* browser, | |
| 209 LauncherContextMenu* menu, | |
| 210 int close_command) { | |
| 211 content::WindowedNotificationObserver close_observer( | |
| 212 chrome::NOTIFICATION_BROWSER_CLOSED, content::Source<Browser>(browser)); | |
| 213 // Note that event_flag is never used inside function ExecuteCommand. | |
| 214 menu->ExecuteCommand(close_command, ui::EventFlags::EF_NONE); | |
| 215 close_observer.Wait(); | |
| 216 } | |
| 217 | |
| 218 } // namespace | |
| 219 | |
| 220 class LauncherPlatformAppBrowserTest | |
| 221 : public extensions::PlatformAppBrowserTest { | |
| 222 protected: | |
| 223 LauncherPlatformAppBrowserTest() : controller_(nullptr) {} | |
| 224 | |
| 225 ~LauncherPlatformAppBrowserTest() override {} | |
| 226 | |
| 227 void SetUpOnMainThread() override { | |
| 228 // Ensure ash starts the session and creates the shelf and controller. | |
| 229 SessionControllerClient::FlushForTesting(); | |
| 230 | |
| 231 controller_ = GetChromeLauncherControllerImpl(); | |
| 232 ASSERT_TRUE(controller_); | |
| 233 extensions::PlatformAppBrowserTest::SetUpOnMainThread(); | |
| 234 } | |
| 235 | |
| 236 ash::ShelfModel* shelf_model() { return ash::Shell::Get()->shelf_model(); } | |
| 237 | |
| 238 ash::ShelfID CreateAppShortcutLauncherItem( | |
| 239 const ash::AppLaunchId& app_launch_id) { | |
| 240 return controller_->CreateAppShortcutLauncherItem( | |
| 241 app_launch_id, shelf_model()->item_count()); | |
| 242 } | |
| 243 | |
| 244 const ash::ShelfItem& GetLastLauncherItem() { | |
| 245 // Unless there are any panels, the item at index [count - 1] will be | |
| 246 // the desired item. | |
| 247 return shelf_model()->items()[shelf_model()->item_count() - 1]; | |
| 248 } | |
| 249 | |
| 250 const ash::ShelfItem& GetLastLauncherPanelItem() { | |
| 251 // Panels show up on the right side of the shelf, so the desired item | |
| 252 // will be the last one. | |
| 253 return shelf_model()->items()[shelf_model()->item_count() - 1]; | |
| 254 } | |
| 255 | |
| 256 ash::ShelfItemDelegate* GetShelfItemDelegate(ash::ShelfID id) { | |
| 257 return shelf_model()->GetShelfItemDelegate(id); | |
| 258 } | |
| 259 | |
| 260 ChromeLauncherControllerImpl* controller_; | |
| 261 | |
| 262 private: | |
| 263 DISALLOW_COPY_AND_ASSIGN(LauncherPlatformAppBrowserTest); | |
| 264 }; | |
| 265 | |
| 266 enum RipOffCommand { | |
| 267 // Drag the item off the shelf and let the mouse go. | |
| 268 RIP_OFF_ITEM, | |
| 269 // Drag the item off the shelf, move the mouse back and then let go. | |
| 270 RIP_OFF_ITEM_AND_RETURN, | |
| 271 // Drag the item off the shelf and then issue a cancel command. | |
| 272 RIP_OFF_ITEM_AND_CANCEL, | |
| 273 // Drag the item off the shelf and do not release the mouse. | |
| 274 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE, | |
| 275 }; | |
| 276 | |
| 277 class ShelfAppBrowserTest : public ExtensionBrowserTest { | |
| 278 protected: | |
| 279 ShelfAppBrowserTest() : shelf_(NULL), model_(NULL), controller_(NULL) { | |
| 280 } | |
| 281 | |
| 282 ~ShelfAppBrowserTest() override {} | |
| 283 | |
| 284 void SetUpOnMainThread() override { | |
| 285 // Ensure ash starts the session and creates the shelf and controller. | |
| 286 SessionControllerClient::FlushForTesting(); | |
| 287 | |
| 288 shelf_ = | |
| 289 ash::WmShelf::ForWindow(ash::ShellPort::Get()->GetPrimaryRootWindow()); | |
| 290 model_ = ash::Shell::Get()->shelf_model(); | |
| 291 controller_ = GetChromeLauncherControllerImpl(); | |
| 292 ASSERT_TRUE(controller_); | |
| 293 ExtensionBrowserTest::SetUpOnMainThread(); | |
| 294 } | |
| 295 | |
| 296 size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) { | |
| 297 ash::ShelfItemDelegate* item_controller = | |
| 298 controller_->GetBrowserShortcutLauncherItemController(); | |
| 299 return item_controller | |
| 300 ->GetAppMenuItems(show_all_tabs ? ui::EF_SHIFT_DOWN : 0) | |
| 301 .size(); | |
| 302 } | |
| 303 | |
| 304 const Extension* LoadAndLaunchExtension( | |
| 305 const char* name, | |
| 306 extensions::LaunchContainer container, | |
| 307 WindowOpenDisposition disposition) { | |
| 308 EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name))); | |
| 309 | |
| 310 ExtensionService* service = extensions::ExtensionSystem::Get( | |
| 311 profile())->extension_service(); | |
| 312 const Extension* extension = | |
| 313 service->GetExtensionById(last_loaded_extension_id(), false); | |
| 314 EXPECT_TRUE(extension); | |
| 315 | |
| 316 OpenApplication(AppLaunchParams(profile(), extension, container, | |
| 317 disposition, extensions::SOURCE_TEST)); | |
| 318 return extension; | |
| 319 } | |
| 320 | |
| 321 ash::ShelfID CreateShortcut(const char* name) { | |
| 322 ExtensionService* service = extensions::ExtensionSystem::Get( | |
| 323 profile())->extension_service(); | |
| 324 LoadExtension(test_data_dir_.AppendASCII(name)); | |
| 325 | |
| 326 // First get app_id. | |
| 327 const Extension* extension = | |
| 328 service->GetExtensionById(last_loaded_extension_id(), false); | |
| 329 const std::string app_id = extension->id(); | |
| 330 | |
| 331 // Then create a shortcut. | |
| 332 int item_count = model_->item_count(); | |
| 333 ash::ShelfID shortcut_id = controller_->CreateAppShortcutLauncherItem( | |
| 334 ash::AppLaunchId(app_id), item_count); | |
| 335 controller_->SyncPinPosition(shortcut_id); | |
| 336 EXPECT_EQ(++item_count, model_->item_count()); | |
| 337 const ash::ShelfItem& item = *model_->ItemByID(shortcut_id); | |
| 338 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 339 return item.id; | |
| 340 } | |
| 341 | |
| 342 ash::ShelfID PinFakeApp(const std::string& app_id) { | |
| 343 return controller_->CreateAppShortcutLauncherItem(ash::AppLaunchId(app_id), | |
| 344 model_->item_count()); | |
| 345 } | |
| 346 | |
| 347 // Get the index of an item which has the given type. | |
| 348 int GetIndexOfShelfItemType(ash::ShelfItemType type) { | |
| 349 return model_->GetItemIndexForType(type); | |
| 350 } | |
| 351 | |
| 352 // Try to rip off |item_index|. | |
| 353 void RipOffItemIndex(int index, | |
| 354 ui::test::EventGenerator* generator, | |
| 355 ash::test::ShelfViewTestAPI* test, | |
| 356 RipOffCommand command) { | |
| 357 ash::ShelfButton* button = test->GetButton(index); | |
| 358 gfx::Point start_point = button->GetBoundsInScreen().CenterPoint(); | |
| 359 gfx::Point rip_off_point(start_point.x(), 0); | |
| 360 generator->MoveMouseTo(start_point.x(), start_point.y()); | |
| 361 base::RunLoop().RunUntilIdle(); | |
| 362 generator->PressLeftButton(); | |
| 363 base::RunLoop().RunUntilIdle(); | |
| 364 generator->MoveMouseTo(rip_off_point.x(), rip_off_point.y()); | |
| 365 base::RunLoop().RunUntilIdle(); | |
| 366 test->RunMessageLoopUntilAnimationsDone(); | |
| 367 if (command == RIP_OFF_ITEM_AND_RETURN) { | |
| 368 generator->MoveMouseTo(start_point.x(), start_point.y()); | |
| 369 base::RunLoop().RunUntilIdle(); | |
| 370 test->RunMessageLoopUntilAnimationsDone(); | |
| 371 } else if (command == RIP_OFF_ITEM_AND_CANCEL) { | |
| 372 // This triggers an internal cancel. Using VKEY_ESCAPE was too unreliable. | |
| 373 button->OnMouseCaptureLost(); | |
| 374 } | |
| 375 if (command != RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE) { | |
| 376 generator->ReleaseLeftButton(); | |
| 377 base::RunLoop().RunUntilIdle(); | |
| 378 test->RunMessageLoopUntilAnimationsDone(); | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 // Creates a context menu for the existing browser shortcut item. | |
| 383 std::unique_ptr<LauncherContextMenu> CreateBrowserItemContextMenu() { | |
| 384 int index = model_->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT); | |
| 385 DCHECK_GE(index, 0); | |
| 386 ash::ShelfItem item = model_->items()[index]; | |
| 387 ash::WmShelf* shelf = | |
| 388 ash::WmShelf::ForWindow(ash::WmWindow::Get(CurrentContext())); | |
| 389 std::unique_ptr<LauncherContextMenu> menu( | |
| 390 LauncherContextMenu::Create(controller_, &item, shelf)); | |
| 391 return menu; | |
| 392 } | |
| 393 | |
| 394 aura::Window* CurrentContext() { | |
| 395 aura::Window* root_window = ash::Shell::GetRootWindowForNewWindows(); | |
| 396 DCHECK(root_window); | |
| 397 return root_window; | |
| 398 } | |
| 399 | |
| 400 bool IsItemPresentInMenu(LauncherContextMenu* menu, int command_id) { | |
| 401 return menu->GetIndexOfCommandId(command_id) != -1; | |
| 402 } | |
| 403 | |
| 404 ash::WmShelf* shelf_; | |
| 405 ash::ShelfModel* model_; | |
| 406 ChromeLauncherControllerImpl* controller_; | |
| 407 | |
| 408 private: | |
| 409 DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserTest); | |
| 410 }; | |
| 411 | |
| 412 class ShelfAppBrowserTestNoDefaultBrowser : public ShelfAppBrowserTest { | |
| 413 protected: | |
| 414 ShelfAppBrowserTestNoDefaultBrowser() {} | |
| 415 ~ShelfAppBrowserTestNoDefaultBrowser() override {} | |
| 416 | |
| 417 void SetUpCommandLine(base::CommandLine* command_line) override { | |
| 418 ShelfAppBrowserTest::SetUpCommandLine(command_line); | |
| 419 command_line->AppendSwitch(switches::kNoStartupWindow); | |
| 420 } | |
| 421 | |
| 422 private: | |
| 423 DISALLOW_COPY_AND_ASSIGN(ShelfAppBrowserTestNoDefaultBrowser); | |
| 424 }; | |
| 425 | |
| 426 // Test that we can launch a platform app and get a running item. | |
| 427 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) { | |
| 428 int item_count = shelf_model()->item_count(); | |
| 429 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 430 AppWindow* window = CreateAppWindow(browser()->profile(), extension); | |
| 431 ++item_count; | |
| 432 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 433 const ash::ShelfItem& item = GetLastLauncherItem(); | |
| 434 EXPECT_EQ(ash::TYPE_APP, item.type); | |
| 435 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 436 CloseAppWindow(window); | |
| 437 --item_count; | |
| 438 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 439 } | |
| 440 | |
| 441 // Test that we can launch a platform app that already has a shortcut. | |
| 442 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) { | |
| 443 int item_count = shelf_model()->item_count(); | |
| 444 | |
| 445 // First get app_id. | |
| 446 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 447 const std::string app_id = extension->id(); | |
| 448 | |
| 449 // Then create a shortcut. | |
| 450 ash::ShelfID shortcut_id = | |
| 451 CreateAppShortcutLauncherItem(ash::AppLaunchId(app_id)); | |
| 452 ++item_count; | |
| 453 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 454 ash::ShelfItem item = *shelf_model()->ItemByID(shortcut_id); | |
| 455 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 456 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
| 457 | |
| 458 // Open a window. Confirm the item is now running. | |
| 459 AppWindow* window = CreateAppWindow(browser()->profile(), extension); | |
| 460 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
| 461 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 462 item = *shelf_model()->ItemByID(shortcut_id); | |
| 463 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 464 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 465 | |
| 466 // Then close it, make sure there's still an item. | |
| 467 CloseAppWindow(window); | |
| 468 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 469 item = *shelf_model()->ItemByID(shortcut_id); | |
| 470 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 471 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
| 472 } | |
| 473 | |
| 474 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) { | |
| 475 // Run. | |
| 476 int item_count = shelf_model()->item_count(); | |
| 477 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 478 AppWindow* window = CreateAppWindow(browser()->profile(), extension); | |
| 479 ++item_count; | |
| 480 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 481 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 482 ash::ShelfID id = item1.id; | |
| 483 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 484 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 485 | |
| 486 // Create a shortcut. The app item should be after it. | |
| 487 ash::ShelfID foo_id = CreateAppShortcutLauncherItem(ash::AppLaunchId("foo")); | |
| 488 ++item_count; | |
| 489 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 490 EXPECT_LT(shelf_model()->ItemIndexByID(foo_id), | |
| 491 shelf_model()->ItemIndexByID(id)); | |
| 492 | |
| 493 // Pin the app. The item should remain. | |
| 494 controller_->PinAppWithID(extension->id()); | |
| 495 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 496 const ash::ShelfItem& item2 = *shelf_model()->ItemByID(id); | |
| 497 EXPECT_EQ(ash::TYPE_PINNED_APP, item2.type); | |
| 498 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
| 499 | |
| 500 // New shortcuts should come after the item. | |
| 501 ash::ShelfID bar_id = CreateAppShortcutLauncherItem(ash::AppLaunchId("bar")); | |
| 502 ++item_count; | |
| 503 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 504 EXPECT_LT(shelf_model()->ItemIndexByID(id), | |
| 505 shelf_model()->ItemIndexByID(bar_id)); | |
| 506 | |
| 507 // Then close it, make sure the item remains. | |
| 508 CloseAppWindow(window); | |
| 509 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 510 } | |
| 511 | |
| 512 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) { | |
| 513 int item_count = shelf_model()->item_count(); | |
| 514 | |
| 515 // First get app_id. | |
| 516 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 517 const std::string app_id = extension->id(); | |
| 518 | |
| 519 // Then create a shortcut. | |
| 520 ash::ShelfID shortcut_id = | |
| 521 CreateAppShortcutLauncherItem(ash::AppLaunchId(app_id)); | |
| 522 ++item_count; | |
| 523 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 524 ash::ShelfItem item = *shelf_model()->ItemByID(shortcut_id); | |
| 525 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 526 EXPECT_EQ(ash::STATUS_CLOSED, item.status); | |
| 527 | |
| 528 // Create a second shortcut. This will be needed to force the first one to | |
| 529 // move once it gets unpinned. | |
| 530 ash::ShelfID foo_id = CreateAppShortcutLauncherItem(ash::AppLaunchId("foo")); | |
| 531 ++item_count; | |
| 532 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 533 EXPECT_LT(shelf_model()->ItemIndexByID(shortcut_id), | |
| 534 shelf_model()->ItemIndexByID(foo_id)); | |
| 535 | |
| 536 // Open a window. Confirm the item is now running. | |
| 537 AppWindow* window = CreateAppWindow(browser()->profile(), extension); | |
| 538 ash::wm::ActivateWindow(window->GetNativeWindow()); | |
| 539 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 540 item = *shelf_model()->ItemByID(shortcut_id); | |
| 541 EXPECT_EQ(ash::TYPE_PINNED_APP, item.type); | |
| 542 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 543 | |
| 544 // Unpin the app. The item should remain. | |
| 545 controller_->UnpinAppWithID(app_id); | |
| 546 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 547 item = *shelf_model()->ItemByID(shortcut_id); | |
| 548 EXPECT_EQ(ash::TYPE_APP, item.type); | |
| 549 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 550 // The item should have moved after the other shortcuts. | |
| 551 EXPECT_GT(shelf_model()->ItemIndexByID(shortcut_id), | |
| 552 shelf_model()->ItemIndexByID(foo_id)); | |
| 553 | |
| 554 // Then close it, make sure the item's gone. | |
| 555 CloseAppWindow(window); | |
| 556 --item_count; | |
| 557 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 558 } | |
| 559 | |
| 560 // Test that we can launch a platform app with more than one window. | |
| 561 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) { | |
| 562 int item_count = shelf_model()->item_count(); | |
| 563 | |
| 564 // Run the application; a shelf item should be added with one app menu item. | |
| 565 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 566 AppWindow* window1 = CreateAppWindow(browser()->profile(), extension); | |
| 567 ASSERT_EQ(item_count + 1, shelf_model()->item_count()); | |
| 568 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 569 ash::ShelfID item_id = item1.id; | |
| 570 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 571 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 572 EXPECT_EQ(1u, controller_->GetAppMenuItemsForTesting(item1).size()); | |
| 573 | |
| 574 // Add a second window; confirm the shelf item stays; check the app menu. | |
| 575 AppWindow* window2 = CreateAppWindow(browser()->profile(), extension); | |
| 576 ASSERT_EQ(item_count + 1, shelf_model()->item_count()); | |
| 577 const ash::ShelfItem& item2 = *shelf_model()->ItemByID(item_id); | |
| 578 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
| 579 EXPECT_EQ(2u, controller_->GetAppMenuItemsForTesting(item2).size()); | |
| 580 | |
| 581 // Close the second window; confirm the shelf item stays; check the app menu. | |
| 582 CloseAppWindow(window2); | |
| 583 ASSERT_EQ(item_count + 1, shelf_model()->item_count()); | |
| 584 const ash::ShelfItem& item3 = *shelf_model()->ItemByID(item_id); | |
| 585 EXPECT_EQ(ash::STATUS_ACTIVE, item3.status); | |
| 586 EXPECT_EQ(1u, controller_->GetAppMenuItemsForTesting(item3).size()); | |
| 587 | |
| 588 // Close the first window; the shelf item should be removed. | |
| 589 CloseAppWindow(window1); | |
| 590 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 591 } | |
| 592 | |
| 593 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) { | |
| 594 int item_count = shelf_model()->item_count(); | |
| 595 | |
| 596 // First run app. | |
| 597 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 598 AppWindow* window1 = CreateAppWindow(browser()->profile(), extension1); | |
| 599 ++item_count; | |
| 600 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 601 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 602 ash::ShelfID item_id1 = item1.id; | |
| 603 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 604 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 605 | |
| 606 // Then run second app. | |
| 607 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", | |
| 608 "Launched"); | |
| 609 AppWindow* window2 = CreateAppWindow(browser()->profile(), extension2); | |
| 610 ++item_count; | |
| 611 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 612 const ash::ShelfItem& item2 = GetLastLauncherItem(); | |
| 613 ash::ShelfID item_id2 = item2.id; | |
| 614 EXPECT_EQ(ash::TYPE_APP, item2.type); | |
| 615 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
| 616 | |
| 617 EXPECT_NE(item_id1, item_id2); | |
| 618 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); | |
| 619 | |
| 620 // Close second app. | |
| 621 CloseAppWindow(window2); | |
| 622 --item_count; | |
| 623 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 624 // First app should be active again. | |
| 625 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); | |
| 626 | |
| 627 // Close first app. | |
| 628 CloseAppWindow(window1); | |
| 629 --item_count; | |
| 630 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 631 } | |
| 632 | |
| 633 // Confirm that app windows can be reactivated by clicking their icons and that | |
| 634 // the correct activation order is maintained. | |
| 635 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowActivation) { | |
| 636 int item_count = shelf_model()->item_count(); | |
| 637 | |
| 638 // First run app. | |
| 639 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 640 AppWindow* window1 = CreateAppWindow(browser()->profile(), extension1); | |
| 641 ++item_count; | |
| 642 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 643 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 644 ash::ShelfID item_id1 = item1.id; | |
| 645 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 646 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 647 | |
| 648 // Then run second app. | |
| 649 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", | |
| 650 "Launched"); | |
| 651 AppWindow* window2 = CreateAppWindow(browser()->profile(), extension2); | |
| 652 ++item_count; | |
| 653 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 654 const ash::ShelfItem& item2 = GetLastLauncherItem(); | |
| 655 ash::ShelfID item_id2 = item2.id; | |
| 656 EXPECT_EQ(ash::TYPE_APP, item2.type); | |
| 657 EXPECT_EQ(ash::STATUS_ACTIVE, item2.status); | |
| 658 | |
| 659 EXPECT_NE(item_id1, item_id2); | |
| 660 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); | |
| 661 | |
| 662 // Activate first one. | |
| 663 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); | |
| 664 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); | |
| 665 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id2)->status); | |
| 666 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 667 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
| 668 | |
| 669 // Activate second one. | |
| 670 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2)); | |
| 671 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); | |
| 672 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id2)->status); | |
| 673 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 674 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
| 675 | |
| 676 // Add window for app1. This will activate it. | |
| 677 AppWindow* window1b = CreateAppWindow(browser()->profile(), extension1); | |
| 678 ash::wm::ActivateWindow(window1b->GetNativeWindow()); | |
| 679 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 680 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
| 681 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
| 682 | |
| 683 // Activate launcher item for app1, this will activate the first app window. | |
| 684 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); | |
| 685 EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 686 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
| 687 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); | |
| 688 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
| 689 | |
| 690 // Activate the second app again | |
| 691 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id2)); | |
| 692 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 693 EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
| 694 EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
| 695 | |
| 696 // Activate the first app again | |
| 697 WmShelf::ActivateShelfItem(shelf_model()->ItemIndexByID(item_id1)); | |
| 698 EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow())); | |
| 699 EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow())); | |
| 700 EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow())); | |
| 701 | |
| 702 // Close second app. | |
| 703 CloseAppWindow(window2); | |
| 704 --item_count; | |
| 705 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 706 // First app should be active again. | |
| 707 EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status); | |
| 708 | |
| 709 // Close first app. | |
| 710 CloseAppWindow(window1b); | |
| 711 CloseAppWindow(window1); | |
| 712 --item_count; | |
| 713 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 714 } | |
| 715 | |
| 716 // Confirm the minimizing click behavior for apps. | |
| 717 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, | |
| 718 PackagedAppClickBehaviorInMinimizeMode) { | |
| 719 // Launch one platform app and create a window for it. | |
| 720 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 721 AppWindow* window1 = CreateAppWindow(browser()->profile(), extension1); | |
| 722 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 723 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 724 | |
| 725 // Confirm that a controller item was created and is the correct state. | |
| 726 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 727 ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id); | |
| 728 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 729 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 730 // Since it is already active, clicking it should minimize. | |
| 731 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 732 EXPECT_FALSE(window1->GetNativeWindow()->IsVisible()); | |
| 733 EXPECT_FALSE(window1->GetBaseWindow()->IsActive()); | |
| 734 EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized()); | |
| 735 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
| 736 // Clicking the item again should activate the window again. | |
| 737 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 738 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 739 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 740 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 741 // Maximizing a window should preserve state after minimize + click. | |
| 742 window1->GetBaseWindow()->Maximize(); | |
| 743 window1->GetBaseWindow()->Minimize(); | |
| 744 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 745 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 746 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 747 EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized()); | |
| 748 window1->GetBaseWindow()->Restore(); | |
| 749 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 750 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 751 EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized()); | |
| 752 | |
| 753 // Creating a second window of the same type should change the behavior so | |
| 754 // that a click does not change the activation state. | |
| 755 AppWindow* window1a = CreateAppWindow(browser()->profile(), extension1); | |
| 756 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
| 757 EXPECT_TRUE(window1a->GetBaseWindow()->IsActive()); | |
| 758 // The first click does nothing. | |
| 759 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 760 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 761 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
| 762 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 763 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); | |
| 764 // The second neither. | |
| 765 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 766 EXPECT_TRUE(window1->GetNativeWindow()->IsVisible()); | |
| 767 EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible()); | |
| 768 EXPECT_TRUE(window1->GetBaseWindow()->IsActive()); | |
| 769 EXPECT_FALSE(window1a->GetBaseWindow()->IsActive()); | |
| 770 } | |
| 771 | |
| 772 // Confirm that ash::ShelfWindowWatcher correctly handles app panels. | |
| 773 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanel) { | |
| 774 // Enable experimental APIs to allow panel creation. | |
| 775 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 776 extensions::switches::kEnableExperimentalExtensionApis); | |
| 777 // Launch a platform app and create a panel window for it. | |
| 778 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 779 AppWindow::CreateParams params; | |
| 780 params.window_type = AppWindow::WINDOW_TYPE_PANEL; | |
| 781 params.focused = false; | |
| 782 AppWindow* panel = | |
| 783 CreateAppWindowFromParams(browser()->profile(), extension1, params); | |
| 784 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
| 785 // Panels should not be active by default. | |
| 786 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); | |
| 787 // Confirm that an item delegate was created and is in the correct state. | |
| 788 const ash::ShelfItem& item1 = GetLastLauncherPanelItem(); | |
| 789 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type); | |
| 790 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
| 791 ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id); | |
| 792 EXPECT_EQ(ash::TYPE_APP_PANEL, | |
| 793 panel->GetNativeWindow()->GetProperty(ash::kShelfItemTypeKey)); | |
| 794 // Click the item and confirm that the panel is activated. | |
| 795 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 796 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
| 797 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 798 // Click the item again and confirm that the panel is minimized. | |
| 799 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 800 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized()); | |
| 801 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
| 802 // Click the item again and confirm that the panel is activated. | |
| 803 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 804 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
| 805 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
| 806 EXPECT_FALSE(panel->GetBaseWindow()->IsMinimized()); | |
| 807 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 808 } | |
| 809 | |
| 810 // Confirm that click behavior for app panels is correct. | |
| 811 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) { | |
| 812 // Enable experimental APIs to allow panel creation. | |
| 813 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 814 extensions::switches::kEnableExperimentalExtensionApis); | |
| 815 // Launch a platform app and create a panel window for it. | |
| 816 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 817 AppWindow::CreateParams params; | |
| 818 params.window_type = AppWindow::WINDOW_TYPE_PANEL; | |
| 819 params.focused = false; | |
| 820 AppWindow* panel = | |
| 821 CreateAppWindowFromParams(browser()->profile(), extension1, params); | |
| 822 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
| 823 // Panels should not be active by default. | |
| 824 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); | |
| 825 // Confirm that an item delegate was created and is in the correct state. | |
| 826 const ash::ShelfItem& item1 = GetLastLauncherPanelItem(); | |
| 827 EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type); | |
| 828 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
| 829 ash::ShelfItemDelegate* item1_delegate = GetShelfItemDelegate(item1.id); | |
| 830 EXPECT_EQ(ash::TYPE_APP_PANEL, | |
| 831 panel->GetNativeWindow()->GetProperty(ash::kShelfItemTypeKey)); | |
| 832 // Click the item and confirm that the panel is activated. | |
| 833 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 834 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
| 835 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 836 // Click the item again and confirm that the panel is minimized. | |
| 837 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 838 EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized()); | |
| 839 EXPECT_EQ(ash::STATUS_RUNNING, item1.status); | |
| 840 // Click the item again and confirm that the panel is activated. | |
| 841 SelectItem(item1_delegate, ui::ET_MOUSE_PRESSED); | |
| 842 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
| 843 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
| 844 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 845 } | |
| 846 | |
| 847 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) { | |
| 848 int item_count = shelf_model()->item_count(); | |
| 849 | |
| 850 // First run app. | |
| 851 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 852 CreateAppWindow(browser()->profile(), extension1); | |
| 853 ++item_count; | |
| 854 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 855 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 856 ash::ShelfID item_id1 = item1.id; | |
| 857 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 858 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 859 | |
| 860 ash::wm::ActivateWindow(browser()->window()->GetNativeWindow()); | |
| 861 EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status); | |
| 862 } | |
| 863 | |
| 864 // Test that opening an app sets the correct icon | |
| 865 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, SetIcon) { | |
| 866 TestAppWindowRegistryObserver test_observer(browser()->profile()); | |
| 867 | |
| 868 // Enable experimental APIs to allow panel creation. | |
| 869 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 870 extensions::switches::kEnableExperimentalExtensionApis); | |
| 871 | |
| 872 int base_shelf_item_count = shelf_model()->item_count(); | |
| 873 ExtensionTestMessageListener completed_listener("Completed", false); | |
| 874 LoadAndLaunchPlatformApp("app_icon", "Launched"); | |
| 875 | |
| 876 ASSERT_TRUE(completed_listener.WaitUntilSatisfied()); | |
| 877 | |
| 878 // Now wait until the WebContent has decoded the icons and chrome has | |
| 879 // processed it. This needs to be in a loop since the renderer runs in a | |
| 880 // different process. | |
| 881 while (test_observer.icon_updates() < 4) { | |
| 882 base::RunLoop run_loop; | |
| 883 run_loop.RunUntilIdle(); | |
| 884 } | |
| 885 | |
| 886 // This test creates one app window, one app window with custom icon and one | |
| 887 // panel window. | |
| 888 int shelf_item_count = shelf_model()->item_count(); | |
| 889 ASSERT_EQ(base_shelf_item_count + 3, shelf_item_count); | |
| 890 // The Panel will be the last item, the app second-to-last. | |
| 891 const ash::ShelfItem& app_item = shelf_model()->items()[shelf_item_count - 3]; | |
| 892 const ash::ShelfItem& app_custom_icon_item = | |
| 893 shelf_model()->items()[shelf_item_count - 2]; | |
| 894 const ash::ShelfItem& panel_item = | |
| 895 shelf_model()->items()[shelf_item_count - 1]; | |
| 896 | |
| 897 // Icons for Apps are set by the AppWindowLauncherController, so | |
| 898 // image_set_by_controller() should be set. | |
| 899 const ash::ShelfItemDelegate* app_item_delegate = | |
| 900 GetShelfItemDelegate(app_item.id); | |
| 901 ASSERT_TRUE(app_item_delegate); | |
| 902 EXPECT_FALSE(app_item_delegate->image_set_by_controller()); | |
| 903 | |
| 904 const ash::ShelfItemDelegate* app_custom_icon_item_delegate = | |
| 905 GetShelfItemDelegate(app_custom_icon_item.id); | |
| 906 ASSERT_TRUE(app_custom_icon_item_delegate); | |
| 907 EXPECT_TRUE(app_custom_icon_item_delegate->image_set_by_controller()); | |
| 908 | |
| 909 // Ensure icon heights are correct (see test.js in app_icon/ test directory) | |
| 910 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALL, app_item.image.height()); | |
| 911 EXPECT_EQ(extension_misc::EXTENSION_ICON_LARGE, | |
| 912 app_custom_icon_item.image.height()); | |
| 913 EXPECT_EQ(64, panel_item.image.height()); | |
| 914 } | |
| 915 | |
| 916 // Test that we can launch an app with a shortcut. | |
| 917 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchPinned) { | |
| 918 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 919 int tab_count = tab_strip->count(); | |
| 920 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 921 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 922 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 923 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 924 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 925 WebContents* tab = tab_strip->GetActiveWebContents(); | |
| 926 content::WebContentsDestroyedWatcher destroyed_watcher(tab); | |
| 927 browser()->tab_strip_model()->CloseSelectedTabs(); | |
| 928 destroyed_watcher.Wait(); | |
| 929 EXPECT_EQ(--tab_count, tab_strip->count()); | |
| 930 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 931 } | |
| 932 | |
| 933 // Launch the app first and then create the shortcut. | |
| 934 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchUnpinned) { | |
| 935 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 936 int tab_count = tab_strip->count(); | |
| 937 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 938 WindowOpenDisposition::NEW_FOREGROUND_TAB); | |
| 939 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 940 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 941 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 942 WebContents* tab = tab_strip->GetActiveWebContents(); | |
| 943 content::WebContentsDestroyedWatcher destroyed_watcher(tab); | |
| 944 browser()->tab_strip_model()->CloseSelectedTabs(); | |
| 945 destroyed_watcher.Wait(); | |
| 946 EXPECT_EQ(--tab_count, tab_strip->count()); | |
| 947 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 948 } | |
| 949 | |
| 950 // Launches an app in the background and then tries to open it. This is test for | |
| 951 // a crash we had. | |
| 952 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchInBackground) { | |
| 953 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 954 int tab_count = tab_strip->count(); | |
| 955 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 956 WindowOpenDisposition::NEW_BACKGROUND_TAB); | |
| 957 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 958 controller_->LaunchApp(ash::AppLaunchId(last_loaded_extension_id()), | |
| 959 ash::LAUNCH_FROM_UNKNOWN, 0); | |
| 960 } | |
| 961 | |
| 962 // Confirm that clicking a icon for an app running in one of 2 maxmized windows | |
| 963 // activates the right window. | |
| 964 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchMaximized) { | |
| 965 aura::Window* window1 = browser()->window()->GetNativeWindow(); | |
| 966 ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1); | |
| 967 window1_state->Maximize(); | |
| 968 content::WindowedNotificationObserver open_observer( | |
| 969 chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
| 970 content::NotificationService::AllSources()); | |
| 971 chrome::NewEmptyWindow(browser()->profile()); | |
| 972 open_observer.Wait(); | |
| 973 Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr(); | |
| 974 aura::Window* window2 = browser2->window()->GetNativeWindow(); | |
| 975 TabStripModel* tab_strip = browser2->tab_strip_model(); | |
| 976 int tab_count = tab_strip->count(); | |
| 977 ash::wm::GetWindowState(window2)->Maximize(); | |
| 978 | |
| 979 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 980 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 981 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 982 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 983 | |
| 984 window1->Show(); | |
| 985 window1_state->Activate(); | |
| 986 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); | |
| 987 | |
| 988 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 989 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 990 } | |
| 991 | |
| 992 // Activating the same app multiple times should launch only a single copy. | |
| 993 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ActivateApp) { | |
| 994 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 995 int tab_count = tab_strip->count(); | |
| 996 const Extension* extension = | |
| 997 LoadExtension(test_data_dir_.AppendASCII("app1")); | |
| 998 | |
| 999 controller_->ActivateApp(extension->id(), ash::LAUNCH_FROM_UNKNOWN, 0); | |
| 1000 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1001 controller_->ActivateApp(extension->id(), ash::LAUNCH_FROM_UNKNOWN, 0); | |
| 1002 EXPECT_EQ(tab_count, tab_strip->count()); | |
| 1003 } | |
| 1004 | |
| 1005 // Launching the same app multiple times should launch a copy for each call. | |
| 1006 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, LaunchApp) { | |
| 1007 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1008 int tab_count = tab_strip->count(); | |
| 1009 ash::AppLaunchId id(LoadExtension(test_data_dir_.AppendASCII("app1"))->id()); | |
| 1010 controller_->LaunchApp(id, ash::LAUNCH_FROM_UNKNOWN, 0); | |
| 1011 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1012 controller_->LaunchApp(id, ash::LAUNCH_FROM_UNKNOWN, 0); | |
| 1013 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1014 } | |
| 1015 | |
| 1016 // Launch 2 apps and toggle which is active. | |
| 1017 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultipleApps) { | |
| 1018 int item_count = model_->item_count(); | |
| 1019 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1020 int tab_count = tab_strip->count(); | |
| 1021 ash::ShelfID shortcut1 = CreateShortcut("app1"); | |
| 1022 EXPECT_EQ(++item_count, model_->item_count()); | |
| 1023 ash::ShelfID shortcut2 = CreateShortcut("app2"); | |
| 1024 EXPECT_EQ(++item_count, model_->item_count()); | |
| 1025 | |
| 1026 // Launch first app. | |
| 1027 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1)); | |
| 1028 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1029 WebContents* tab1 = tab_strip->GetActiveWebContents(); | |
| 1030 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
| 1031 | |
| 1032 // Launch second app. | |
| 1033 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut2)); | |
| 1034 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1035 WebContents* tab2 = tab_strip->GetActiveWebContents(); | |
| 1036 ASSERT_NE(tab1, tab2); | |
| 1037 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
| 1038 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
| 1039 | |
| 1040 // Reactivate first app. | |
| 1041 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1)); | |
| 1042 EXPECT_EQ(tab_count, tab_strip->count()); | |
| 1043 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
| 1044 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
| 1045 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
| 1046 | |
| 1047 // Open second tab for second app. This should activate it. | |
| 1048 ui_test_utils::NavigateToURLWithDisposition( | |
| 1049 browser(), GURL("http://www.example.com/path3/foo.html"), | |
| 1050 WindowOpenDisposition::NEW_FOREGROUND_TAB, 0); | |
| 1051 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1052 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
| 1053 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
| 1054 | |
| 1055 // Reactivate first app. | |
| 1056 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut1)); | |
| 1057 EXPECT_EQ(tab_count, tab_strip->count()); | |
| 1058 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1); | |
| 1059 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status); | |
| 1060 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status); | |
| 1061 | |
| 1062 // And second again. This time the second tab should become active. | |
| 1063 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut2)); | |
| 1064 EXPECT_EQ(tab_count, tab_strip->count()); | |
| 1065 EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2); | |
| 1066 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status); | |
| 1067 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status); | |
| 1068 } | |
| 1069 | |
| 1070 // Confirm that a page can be navigated from and to while maintaining the | |
| 1071 // correct running state. | |
| 1072 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, Navigation) { | |
| 1073 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1074 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 1075 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1076 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 1077 | |
| 1078 // Navigate away. | |
| 1079 ui_test_utils::NavigateToURL( | |
| 1080 browser(), GURL("http://www.example.com/path0/bar.html")); | |
| 1081 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 1082 | |
| 1083 // Navigate back. | |
| 1084 ui_test_utils::NavigateToURL( | |
| 1085 browser(), GURL("http://www.example.com/path1/foo.html")); | |
| 1086 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 1087 } | |
| 1088 | |
| 1089 // Confirm that a tab can be moved between browsers while maintaining the | |
| 1090 // correct running state. | |
| 1091 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, TabDragAndDrop) { | |
| 1092 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
| 1093 TabStripModel* tab_strip_model1 = browser()->tab_strip_model(); | |
| 1094 EXPECT_EQ(1, tab_strip_model1->count()); | |
| 1095 const int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); | |
| 1096 EXPECT_GE(browser_index, 0); | |
| 1097 | |
| 1098 // Create a shortcut for app1. | |
| 1099 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1100 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1101 EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status); | |
| 1102 | |
| 1103 // Activate app1 and check its item status. | |
| 1104 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1105 EXPECT_EQ(2, tab_strip_model1->count()); | |
| 1106 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
| 1107 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 1108 | |
| 1109 // Create a new browser with blank tab. | |
| 1110 Browser* browser2 = CreateBrowser(profile()); | |
| 1111 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
| 1112 TabStripModel* tab_strip_model2 = browser2->tab_strip_model(); | |
| 1113 EXPECT_EQ(1, tab_strip_model2->count()); | |
| 1114 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1115 EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status); | |
| 1116 | |
| 1117 // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an | |
| 1118 // active tab at index 1 to |tab_strip_model2|. | |
| 1119 content::WebContents* detached_tab = tab_strip_model1->DetachWebContentsAt(1); | |
| 1120 tab_strip_model2->InsertWebContentsAt(1, | |
| 1121 detached_tab, | |
| 1122 TabStripModel::ADD_ACTIVE); | |
| 1123 EXPECT_EQ(1, tab_strip_model1->count()); | |
| 1124 EXPECT_EQ(2, tab_strip_model2->count()); | |
| 1125 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
| 1126 EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status); | |
| 1127 | |
| 1128 tab_strip_model1->CloseAllTabs(); | |
| 1129 tab_strip_model2->CloseAllTabs(); | |
| 1130 } | |
| 1131 | |
| 1132 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultipleOwnedTabs) { | |
| 1133 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1134 int tab_count = tab_strip->count(); | |
| 1135 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1136 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1137 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1138 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1139 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
| 1140 | |
| 1141 // Create new tab owned by app. | |
| 1142 ui_test_utils::NavigateToURLWithDisposition( | |
| 1143 browser(), GURL("http://www.example.com/path2/bar.html"), | |
| 1144 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1145 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1146 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1147 // Confirm app is still active. | |
| 1148 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1149 | |
| 1150 // Create new tab not owned by app. | |
| 1151 ui_test_utils::NavigateToURLWithDisposition( | |
| 1152 browser(), GURL("http://www.example.com/path3/foo.html"), | |
| 1153 WindowOpenDisposition::NEW_FOREGROUND_TAB, 0); | |
| 1154 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1155 // No longer active. | |
| 1156 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
| 1157 | |
| 1158 // Activating app makes first tab active again. | |
| 1159 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1160 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1161 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); | |
| 1162 } | |
| 1163 | |
| 1164 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, RefocusFilter) { | |
| 1165 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1166 int tab_count = tab_strip->count(); | |
| 1167 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1168 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1169 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1170 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1171 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
| 1172 | |
| 1173 controller_->SetRefocusURLPatternForTest( | |
| 1174 shortcut_id, GURL("http://www.example.com/path1/*")); | |
| 1175 // Create new tab owned by app. | |
| 1176 ui_test_utils::NavigateToURLWithDisposition( | |
| 1177 browser(), GURL("http://www.example.com/path2/bar.html"), | |
| 1178 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1179 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1180 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1181 // Confirm app is still active. | |
| 1182 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1183 | |
| 1184 // Create new tab not owned by app. | |
| 1185 ui_test_utils::NavigateToURLWithDisposition( | |
| 1186 browser(), GURL("http://www.example.com/path3/foo.html"), | |
| 1187 WindowOpenDisposition::NEW_FOREGROUND_TAB, 0); | |
| 1188 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1189 // No longer active. | |
| 1190 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
| 1191 | |
| 1192 // Activating app makes first tab active again, because second tab isn't | |
| 1193 // in its refocus url path. | |
| 1194 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1195 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1196 EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab); | |
| 1197 } | |
| 1198 | |
| 1199 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, RefocusFilterLaunch) { | |
| 1200 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1201 int tab_count = tab_strip->count(); | |
| 1202 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1203 controller_->SetRefocusURLPatternForTest( | |
| 1204 shortcut_id, GURL("http://www.example.com/path1/*")); | |
| 1205 | |
| 1206 // Create new tab. | |
| 1207 ui_test_utils::NavigateToURLWithDisposition( | |
| 1208 browser(), GURL("http://www.example2.com/path2/bar.html"), | |
| 1209 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1210 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1211 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1212 WebContents* first_tab = tab_strip->GetActiveWebContents(); | |
| 1213 // Confirm app is not active. | |
| 1214 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1215 | |
| 1216 // Activating app should launch new tab, because second tab isn't | |
| 1217 // in its refocus url path. | |
| 1218 WmShelf::ActivateShelfItem(model_->ItemIndexByID(shortcut_id)); | |
| 1219 EXPECT_EQ(++tab_count, tab_strip->count()); | |
| 1220 WebContents* second_tab = tab_strip->GetActiveWebContents(); | |
| 1221 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1222 EXPECT_NE(first_tab, second_tab); | |
| 1223 EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab); | |
| 1224 } | |
| 1225 | |
| 1226 // Check the launcher activation state for applications and browser. | |
| 1227 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, DISABLED_ActivationStateCheck) { | |
| 1228 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1229 // Get the browser item index | |
| 1230 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); | |
| 1231 EXPECT_TRUE(browser_index >= 0); | |
| 1232 | |
| 1233 // Even though we are just comming up, the browser should be active. | |
| 1234 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1235 | |
| 1236 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1237 controller_->SetRefocusURLPatternForTest( | |
| 1238 shortcut_id, GURL("http://www.example.com/path1/*")); | |
| 1239 | |
| 1240 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1241 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1242 | |
| 1243 // Create new tab which would be the running app. | |
| 1244 ui_test_utils::NavigateToURLWithDisposition( | |
| 1245 browser(), GURL("http://www.example.com/path1/bar.html"), | |
| 1246 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1247 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1248 | |
| 1249 // There should never be two items active at the same time. | |
| 1250 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1251 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
| 1252 | |
| 1253 tab_strip->ActivateTabAt(0, false); | |
| 1254 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status); | |
| 1255 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1256 | |
| 1257 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); | |
| 1258 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1259 EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status); | |
| 1260 | |
| 1261 ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow()); | |
| 1262 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1263 EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status); | |
| 1264 } | |
| 1265 | |
| 1266 // Check that the launcher activation state for a V1 application stays closed | |
| 1267 // even after an asynchronous browser event comes in after the tab got | |
| 1268 // destroyed. | |
| 1269 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, AsyncActivationStateCheck) { | |
| 1270 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1271 | |
| 1272 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1273 controller_->SetRefocusURLPatternForTest( | |
| 1274 shortcut_id, GURL("http://www.example.com/path1/*")); | |
| 1275 | |
| 1276 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1277 | |
| 1278 // Create new tab which would be the running app. | |
| 1279 ui_test_utils::NavigateToURLWithDisposition( | |
| 1280 browser(), GURL("http://www.example.com/path1/bar.html"), | |
| 1281 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1282 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1283 | |
| 1284 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status); | |
| 1285 // To address the issue of crbug.com/174050, the tab we are about to close | |
| 1286 // has to be active. | |
| 1287 tab_strip->ActivateTabAt(1, false); | |
| 1288 EXPECT_EQ(1, tab_strip->active_index()); | |
| 1289 | |
| 1290 // Close the web contents. | |
| 1291 tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); | |
| 1292 // The status should now be set to closed. | |
| 1293 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status); | |
| 1294 } | |
| 1295 | |
| 1296 // Test that the App window could restore to its previous window state from | |
| 1297 // before it was closed. | |
| 1298 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, AppWindowRestoreBehaviorTest) { | |
| 1299 // Open an App, maximized its window, and close it. | |
| 1300 const Extension* extension = | |
| 1301 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_WINDOW, | |
| 1302 WindowOpenDisposition::NEW_WINDOW); | |
| 1303 Browser* app_browser = FindBrowserForApp(extension->id()); | |
| 1304 ASSERT_TRUE(app_browser); | |
| 1305 aura::Window* window = app_browser->window()->GetNativeWindow(); | |
| 1306 EXPECT_FALSE(ash::wm::GetWindowState(window)->IsMaximized()); | |
| 1307 ash::wm::GetWindowState(window)->Maximize(); | |
| 1308 EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized()); | |
| 1309 CloseAppBrowserWindow(app_browser); | |
| 1310 | |
| 1311 // Reopen the App. It should start maximized. Un-maximize it and close it. | |
| 1312 extension = | |
| 1313 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_WINDOW, | |
| 1314 WindowOpenDisposition::NEW_WINDOW); | |
| 1315 app_browser = FindBrowserForApp(extension->id()); | |
| 1316 ASSERT_TRUE(app_browser); | |
| 1317 window = app_browser->window()->GetNativeWindow(); | |
| 1318 EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized()); | |
| 1319 | |
| 1320 ash::wm::GetWindowState(window)->Restore(); | |
| 1321 EXPECT_FALSE(ash::wm::GetWindowState(window)->IsMaximized()); | |
| 1322 app_browser->window()->Close(); | |
| 1323 CloseAppBrowserWindow(app_browser); | |
| 1324 | |
| 1325 // Reopen the App. It should start un-maximized. | |
| 1326 extension = | |
| 1327 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_WINDOW, | |
| 1328 WindowOpenDisposition::NEW_WINDOW); | |
| 1329 app_browser = FindBrowserForApp(extension->id()); | |
| 1330 ASSERT_TRUE(app_browser); | |
| 1331 window = app_browser->window()->GetNativeWindow(); | |
| 1332 EXPECT_FALSE(ash::wm::GetWindowState(window)->IsMaximized()); | |
| 1333 } | |
| 1334 | |
| 1335 // Checks that a windowed application does not add an item to the browser list. | |
| 1336 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, | |
| 1337 WindowedAppDoesNotAddToBrowser) { | |
| 1338 // Get the number of items in the browser menu. | |
| 1339 size_t items = NumberOfDetectedLauncherBrowsers(false); | |
| 1340 size_t running_browser = chrome::GetTotalBrowserCount(); | |
| 1341 EXPECT_EQ(0u, items); | |
| 1342 EXPECT_EQ(0u, running_browser); | |
| 1343 | |
| 1344 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_WINDOW, | |
| 1345 WindowOpenDisposition::NEW_WINDOW); | |
| 1346 | |
| 1347 // No new browser should get detected, even though one more is running. | |
| 1348 EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false)); | |
| 1349 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); | |
| 1350 | |
| 1351 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 1352 WindowOpenDisposition::NEW_WINDOW); | |
| 1353 | |
| 1354 // A new browser should get detected and one more should be running. | |
| 1355 EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u); | |
| 1356 EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount()); | |
| 1357 } | |
| 1358 | |
| 1359 // Checks the functionality to enumerate all browsers vs. all tabs. | |
| 1360 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, | |
| 1361 EnumerateAllBrowsersAndTabs) { | |
| 1362 // Create at least one browser. | |
| 1363 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 1364 WindowOpenDisposition::NEW_WINDOW); | |
| 1365 size_t browsers = NumberOfDetectedLauncherBrowsers(false); | |
| 1366 size_t tabs = NumberOfDetectedLauncherBrowsers(true); | |
| 1367 | |
| 1368 // Create a second browser. | |
| 1369 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 1370 WindowOpenDisposition::NEW_WINDOW); | |
| 1371 | |
| 1372 EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false)); | |
| 1373 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); | |
| 1374 | |
| 1375 // Create only a tab. | |
| 1376 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 1377 WindowOpenDisposition::NEW_FOREGROUND_TAB); | |
| 1378 | |
| 1379 EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false)); | |
| 1380 EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true)); | |
| 1381 } | |
| 1382 | |
| 1383 // Check that the keyboard activation of a launcher item tabs properly through | |
| 1384 // the items at hand. | |
| 1385 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, AltNumberTabsTabbing) { | |
| 1386 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1387 | |
| 1388 ash::ShelfID shortcut_id = CreateShortcut("app"); | |
| 1389 controller_->SetRefocusURLPatternForTest( | |
| 1390 shortcut_id, GURL("http://www.example.com/path/*")); | |
| 1391 std::string url = "http://www.example.com/path/bla"; | |
| 1392 | |
| 1393 int shortcut_index = model_->ItemIndexByID(shortcut_id); | |
| 1394 | |
| 1395 // Create an application handled browser tab. | |
| 1396 ui_test_utils::NavigateToURLWithDisposition( | |
| 1397 browser(), GURL(url), WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1398 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1399 | |
| 1400 content::WebContents* content1 = tab_strip->GetActiveWebContents(); | |
| 1401 | |
| 1402 // Create some other browser tab. | |
| 1403 ui_test_utils::NavigateToURLWithDisposition( | |
| 1404 browser(), GURL("http://www.test.com"), | |
| 1405 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1406 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1407 content::WebContents* content1a = tab_strip->GetActiveWebContents(); | |
| 1408 | |
| 1409 // Make sure that the active tab is now our handled tab. | |
| 1410 EXPECT_NE(content1a, content1); | |
| 1411 | |
| 1412 // The active tab should still be the unnamed tab. Then we switch and reach | |
| 1413 // the first app and stay there. | |
| 1414 EXPECT_EQ(content1a, tab_strip->GetActiveWebContents()); | |
| 1415 WmShelf::ActivateShelfItem(shortcut_index); | |
| 1416 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); | |
| 1417 WmShelf::ActivateShelfItem(shortcut_index); | |
| 1418 EXPECT_EQ(content1, tab_strip->GetActiveWebContents()); | |
| 1419 | |
| 1420 ui_test_utils::NavigateToURLWithDisposition( | |
| 1421 browser(), GURL(url), WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1422 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1423 content::WebContents* content2 = tab_strip->GetActiveWebContents(); | |
| 1424 | |
| 1425 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); | |
| 1426 WmShelf::ActivateShelfItem(shortcut_index); | |
| 1427 EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents()); | |
| 1428 WmShelf::ActivateShelfItem(shortcut_index); | |
| 1429 EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents()); | |
| 1430 } | |
| 1431 | |
| 1432 // Check that the keyboard activation of a launcher item tabs properly through | |
| 1433 // the items at hand. | |
| 1434 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, | |
| 1435 AltNumberAppsTabbing) { | |
| 1436 // First run app. | |
| 1437 const Extension* extension1 = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1438 ui::BaseWindow* window1 = | |
| 1439 CreateAppWindow(browser()->profile(), extension1)->GetBaseWindow(); | |
| 1440 const ash::ShelfItem& item1 = GetLastLauncherItem(); | |
| 1441 ash::ShelfID app_id = item1.id; | |
| 1442 int app_index = shelf_model()->ItemIndexByID(app_id); | |
| 1443 | |
| 1444 EXPECT_EQ(ash::TYPE_APP, item1.type); | |
| 1445 EXPECT_EQ(ash::STATUS_ACTIVE, item1.status); | |
| 1446 | |
| 1447 const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2", | |
| 1448 "Launched"); | |
| 1449 ui::BaseWindow* window2 = | |
| 1450 CreateAppWindow(browser()->profile(), extension2)->GetBaseWindow(); | |
| 1451 | |
| 1452 // By now the browser should be active. Issue Alt keystrokes several times to | |
| 1453 // see that we stay on that application. | |
| 1454 EXPECT_TRUE(window2->IsActive()); | |
| 1455 WmShelf::ActivateShelfItem(app_index); | |
| 1456 EXPECT_TRUE(window1->IsActive()); | |
| 1457 WmShelf::ActivateShelfItem(app_index); | |
| 1458 EXPECT_TRUE(window1->IsActive()); | |
| 1459 | |
| 1460 ui::BaseWindow* window1a = | |
| 1461 CreateAppWindow(browser()->profile(), extension1)->GetBaseWindow(); | |
| 1462 | |
| 1463 EXPECT_TRUE(window1a->IsActive()); | |
| 1464 EXPECT_FALSE(window1->IsActive()); | |
| 1465 WmShelf::ActivateShelfItem(app_index); | |
| 1466 EXPECT_TRUE(window1->IsActive()); | |
| 1467 WmShelf::ActivateShelfItem(app_index); | |
| 1468 EXPECT_TRUE(window1a->IsActive()); | |
| 1469 } | |
| 1470 | |
| 1471 // Test that we can launch a platform app panel and get a running item. | |
| 1472 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) { | |
| 1473 int item_count = shelf_model()->item_count(); | |
| 1474 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1475 AppWindow::CreateParams params; | |
| 1476 params.window_type = AppWindow::WINDOW_TYPE_PANEL; | |
| 1477 params.focused = false; | |
| 1478 AppWindow* window = | |
| 1479 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1480 ++item_count; | |
| 1481 ASSERT_EQ(item_count, shelf_model()->item_count()); | |
| 1482 const ash::ShelfItem& item = GetLastLauncherPanelItem(); | |
| 1483 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); | |
| 1484 // Opening a panel does not activate it. | |
| 1485 EXPECT_EQ(ash::STATUS_RUNNING, item.status); | |
| 1486 CloseAppWindow(window); | |
| 1487 --item_count; | |
| 1488 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1489 } | |
| 1490 | |
| 1491 // Test that we get correct shelf presence with hidden app windows. | |
| 1492 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, HiddenAppWindows) { | |
| 1493 int item_count = shelf_model()->item_count(); | |
| 1494 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1495 AppWindow::CreateParams params; | |
| 1496 | |
| 1497 // Create a hidden window. | |
| 1498 params.hidden = true; | |
| 1499 AppWindow* window_1 = | |
| 1500 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1501 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1502 | |
| 1503 // Create a visible window. | |
| 1504 params.hidden = false; | |
| 1505 AppWindow* window_2 = | |
| 1506 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1507 ++item_count; | |
| 1508 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1509 | |
| 1510 // Minimize the visible window. | |
| 1511 window_2->Minimize(); | |
| 1512 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1513 | |
| 1514 // Hide the visible window. | |
| 1515 window_2->Hide(); | |
| 1516 --item_count; | |
| 1517 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1518 | |
| 1519 // Show the originally hidden window. | |
| 1520 window_1->Show(AppWindow::SHOW_ACTIVE); | |
| 1521 ++item_count; | |
| 1522 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1523 | |
| 1524 // Close the originally hidden window. | |
| 1525 CloseAppWindow(window_1); | |
| 1526 --item_count; | |
| 1527 EXPECT_EQ(item_count, shelf_model()->item_count()); | |
| 1528 } | |
| 1529 | |
| 1530 // Test attention states of windows. | |
| 1531 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) { | |
| 1532 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1533 AppWindow::CreateParams params; | |
| 1534 params.window_type = AppWindow::WINDOW_TYPE_PANEL; | |
| 1535 params.focused = false; | |
| 1536 AppWindow* panel = | |
| 1537 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1538 EXPECT_TRUE(panel->GetNativeWindow()->IsVisible()); | |
| 1539 // Panels should not be active by default. | |
| 1540 EXPECT_FALSE(panel->GetBaseWindow()->IsActive()); | |
| 1541 // Confirm that a shelf item was created and is the correct state. | |
| 1542 const ash::ShelfItem& item = GetLastLauncherPanelItem(); | |
| 1543 ash::ShelfItemDelegate* shelf_item_delegate = GetShelfItemDelegate(item.id); | |
| 1544 EXPECT_NE(nullptr, shelf_item_delegate); | |
| 1545 EXPECT_EQ(ash::TYPE_APP_PANEL, item.type); | |
| 1546 EXPECT_EQ(ash::STATUS_RUNNING, item.status); | |
| 1547 | |
| 1548 // App windows should go to attention state. | |
| 1549 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); | |
| 1550 EXPECT_EQ(ash::STATUS_ATTENTION, item.status); | |
| 1551 | |
| 1552 // Click the item and confirm that the panel is activated. | |
| 1553 EXPECT_EQ(ash::SHELF_ACTION_WINDOW_ACTIVATED, | |
| 1554 SelectItem(shelf_item_delegate, ui::ET_MOUSE_PRESSED)); | |
| 1555 EXPECT_TRUE(panel->GetBaseWindow()->IsActive()); | |
| 1556 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 1557 | |
| 1558 // Active windows don't show attention. | |
| 1559 panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true); | |
| 1560 EXPECT_EQ(ash::STATUS_ACTIVE, item.status); | |
| 1561 } | |
| 1562 | |
| 1563 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, | |
| 1564 ShowInShelfWindowsWithWindowKeySet) { | |
| 1565 ash::ShelfModel* shelf_model = ash::Shell::Get()->shelf_model(); | |
| 1566 | |
| 1567 // Add a window with shelf True, close it | |
| 1568 int item_count = shelf_model->item_count(); | |
| 1569 const Extension* extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1570 AppWindow::CreateParams params; | |
| 1571 | |
| 1572 params.show_in_shelf = true; | |
| 1573 params.window_key = "window1"; | |
| 1574 AppWindow* window1 = | |
| 1575 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1576 // There should be only 1 item added to the shelf. | |
| 1577 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1578 CloseAppWindow(window1); | |
| 1579 EXPECT_EQ(item_count, shelf_model->item_count()); | |
| 1580 | |
| 1581 // Add a window with false, following one with true | |
| 1582 item_count = shelf_model->item_count(); | |
| 1583 extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1584 | |
| 1585 params.show_in_shelf = false; | |
| 1586 params.window_key = "window1"; | |
| 1587 window1 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1588 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1589 params.show_in_shelf = true; | |
| 1590 params.window_key = "window2"; | |
| 1591 AppWindow* window2 = | |
| 1592 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1593 // There should be 2 items added to the shelf: although window1 has | |
| 1594 // show_in_shelf set to false, it's the first window created so its icon must | |
| 1595 // show up in shelf. | |
| 1596 EXPECT_EQ(item_count + 2, shelf_model->item_count()); | |
| 1597 CloseAppWindow(window1); | |
| 1598 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1599 CloseAppWindow(window2); | |
| 1600 EXPECT_EQ(item_count, shelf_model->item_count()); | |
| 1601 | |
| 1602 // Open just one window with false | |
| 1603 item_count = shelf_model->item_count(); | |
| 1604 extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1605 | |
| 1606 params.show_in_shelf = false; | |
| 1607 params.window_key = "window1"; | |
| 1608 window1 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1609 // There should be 1 item added to the shelf: although show_in_shelf is false, | |
| 1610 // this is the first window created. | |
| 1611 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1612 CloseAppWindow(window1); | |
| 1613 EXPECT_EQ(item_count, shelf_model->item_count()); | |
| 1614 | |
| 1615 // Add a window with true, following one with false | |
| 1616 item_count = shelf_model->item_count(); | |
| 1617 extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1618 | |
| 1619 params.show_in_shelf = true; | |
| 1620 params.window_key = "window1"; | |
| 1621 window1 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1622 EXPECT_EQ(item_count + 1, shelf_model->item_count()); // main window | |
| 1623 params.show_in_shelf = false; | |
| 1624 params.window_key = "window2"; | |
| 1625 window2 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1626 EXPECT_EQ(item_count + 2, shelf_model->item_count()); | |
| 1627 CloseAppWindow(window1); | |
| 1628 // There should be 1 item added to the shelf as the second window | |
| 1629 // is set to show_in_shelf false | |
| 1630 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1631 CloseAppWindow(window2); | |
| 1632 EXPECT_EQ(item_count, shelf_model->item_count()); | |
| 1633 | |
| 1634 // Test closing windows in different order | |
| 1635 item_count = shelf_model->item_count(); | |
| 1636 extension = LoadAndLaunchPlatformApp("launch", "Launched"); | |
| 1637 | |
| 1638 params.show_in_shelf = false; | |
| 1639 params.window_key = "window1"; | |
| 1640 window1 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1641 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1642 params.show_in_shelf = false; | |
| 1643 params.window_key = "window2"; | |
| 1644 window2 = CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1645 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1646 params.show_in_shelf = true; | |
| 1647 params.window_key = "window3"; | |
| 1648 AppWindow* window3 = | |
| 1649 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1650 EXPECT_EQ(item_count + 2, shelf_model->item_count()); | |
| 1651 params.show_in_shelf = true; | |
| 1652 params.window_key = "window4"; | |
| 1653 AppWindow* window4 = | |
| 1654 CreateAppWindowFromParams(browser()->profile(), extension, params); | |
| 1655 // There should be 3 items added to the shelf. | |
| 1656 EXPECT_EQ(item_count + 3, shelf_model->item_count()); | |
| 1657 // Any window close order should be valid | |
| 1658 CloseAppWindow(window4); | |
| 1659 // Closed window4 that was shown in shelf. item_count would decrease | |
| 1660 EXPECT_EQ(item_count + 2, shelf_model->item_count()); | |
| 1661 CloseAppWindow(window1); | |
| 1662 // Closed window1 which was grouped together with window2 so item_count | |
| 1663 // would not decrease | |
| 1664 EXPECT_EQ(item_count + 2, shelf_model->item_count()); | |
| 1665 CloseAppWindow(window3); | |
| 1666 // Closed window3 that was shown in shelf. item_count would decrease | |
| 1667 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 1668 CloseAppWindow(window2); | |
| 1669 // Closed window2 - there is no other window in that group and item_count | |
| 1670 // would decrease | |
| 1671 EXPECT_EQ(item_count, shelf_model->item_count()); | |
| 1672 } | |
| 1673 | |
| 1674 // Checks that the browser Alt "tabbing" is properly done. | |
| 1675 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, | |
| 1676 AltNumberBrowserTabbing) { | |
| 1677 // Get the number of items in the browser menu. | |
| 1678 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); | |
| 1679 // The first activation should create a browser at index 1 (App List @ 0). | |
| 1680 WmShelf::ActivateShelfItem(1); | |
| 1681 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
| 1682 // A second activation should not create a new instance. | |
| 1683 WmShelf::ActivateShelfItem(1); | |
| 1684 Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()); | |
| 1685 EXPECT_TRUE(browser1); | |
| 1686 aura::Window* window1 = browser1->window()->GetNativeWindow(); | |
| 1687 Browser* browser2 = CreateBrowser(profile()); | |
| 1688 aura::Window* window2 = browser2->window()->GetNativeWindow(); | |
| 1689 | |
| 1690 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
| 1691 EXPECT_NE(window1, window2); | |
| 1692 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
| 1693 | |
| 1694 // Activate multiple times the switcher to see that the windows get activated. | |
| 1695 WmShelf::ActivateShelfItem(1); | |
| 1696 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
| 1697 WmShelf::ActivateShelfItem(1); | |
| 1698 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
| 1699 | |
| 1700 // Create a third browser - make sure that we do not toggle simply between | |
| 1701 // two windows. | |
| 1702 Browser* browser3 = CreateBrowser(profile()); | |
| 1703 aura::Window* window3 = browser3->window()->GetNativeWindow(); | |
| 1704 | |
| 1705 EXPECT_EQ(3u, chrome::GetTotalBrowserCount()); | |
| 1706 EXPECT_NE(window1, window3); | |
| 1707 EXPECT_NE(window2, window3); | |
| 1708 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); | |
| 1709 | |
| 1710 WmShelf::ActivateShelfItem(1); | |
| 1711 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
| 1712 WmShelf::ActivateShelfItem(1); | |
| 1713 EXPECT_EQ(window2, ash::wm::GetActiveWindow()); | |
| 1714 WmShelf::ActivateShelfItem(1); | |
| 1715 EXPECT_EQ(window3, ash::wm::GetActiveWindow()); | |
| 1716 WmShelf::ActivateShelfItem(1); | |
| 1717 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
| 1718 | |
| 1719 // Create anther app and make sure that none of our browsers is active. | |
| 1720 LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, | |
| 1721 WindowOpenDisposition::NEW_WINDOW); | |
| 1722 EXPECT_NE(window1, ash::wm::GetActiveWindow()); | |
| 1723 EXPECT_NE(window2, ash::wm::GetActiveWindow()); | |
| 1724 | |
| 1725 // After activation our browser should be active again. | |
| 1726 WmShelf::ActivateShelfItem(1); | |
| 1727 EXPECT_EQ(window1, ash::wm::GetActiveWindow()); | |
| 1728 } | |
| 1729 | |
| 1730 // Checks that after a session restore, we do not start applications on an | |
| 1731 // activation. | |
| 1732 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ActivateAfterSessionRestore) { | |
| 1733 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
| 1734 | |
| 1735 // Create a known application. | |
| 1736 ash::ShelfID shortcut_id = CreateShortcut("app1"); | |
| 1737 | |
| 1738 // Create a new browser - without activating it - and load an "app" into it. | |
| 1739 Browser::CreateParams params = Browser::CreateParams(profile(), true); | |
| 1740 params.initial_show_state = ui::SHOW_STATE_INACTIVE; | |
| 1741 Browser* browser2 = new Browser(params); | |
| 1742 controller_->SetRefocusURLPatternForTest( | |
| 1743 shortcut_id, GURL("http://www.example.com/path/*")); | |
| 1744 std::string url = "http://www.example.com/path/bla"; | |
| 1745 ui_test_utils::NavigateToURLWithDisposition( | |
| 1746 browser2, GURL(url), WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
| 1747 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
| 1748 | |
| 1749 // Remember the number of tabs for each browser. | |
| 1750 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 1751 int tab_count1 = tab_strip->count(); | |
| 1752 TabStripModel* tab_strip2 = browser2->tab_strip_model(); | |
| 1753 int tab_count2 = tab_strip2->count(); | |
| 1754 | |
| 1755 // Check that we have two browsers and the inactive browser remained inactive. | |
| 1756 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
| 1757 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), | |
| 1758 browser()); | |
| 1759 // Check that the LRU browser list does only contain the original browser. | |
| 1760 BrowserList* browser_list = BrowserList::GetInstance(); | |
| 1761 BrowserList::const_reverse_iterator it = browser_list->begin_last_active(); | |
| 1762 EXPECT_EQ(*it, browser()); | |
| 1763 ++it; | |
| 1764 EXPECT_EQ(it, browser_list->end_last_active()); | |
| 1765 | |
| 1766 // Now request to either activate an existing app or create a new one. | |
| 1767 ash::ShelfItemDelegate* item_delegate = | |
| 1768 model_->GetShelfItemDelegate(shortcut_id); | |
| 1769 SelectItem(item_delegate, ui::ET_KEY_RELEASED); | |
| 1770 | |
| 1771 // Check that we have set focus on the existing application and nothing new | |
| 1772 // was created. | |
| 1773 EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); | |
| 1774 EXPECT_EQ(tab_count1, tab_strip->count()); | |
| 1775 EXPECT_EQ(tab_count2, tab_strip2->count()); | |
| 1776 EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()), | |
| 1777 browser2); | |
| 1778 } | |
| 1779 | |
| 1780 // Do various drag and drop interaction tests between the application list and | |
| 1781 // the launcher. | |
| 1782 // TODO(skuhne): Test is flaky with a real compositor: crbug.com/331924 | |
| 1783 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, DISABLED_DragAndDrop) { | |
| 1784 // Get a number of interfaces we need. | |
| 1785 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), | |
| 1786 gfx::Point()); | |
| 1787 ash::test::ShelfViewTestAPI test(shelf_->GetShelfViewForTesting()); | |
| 1788 AppListService* service = AppListService::Get(); | |
| 1789 | |
| 1790 // There should be two items in our launcher by this time. | |
| 1791 EXPECT_EQ(2, model_->item_count()); | |
| 1792 EXPECT_FALSE(service->IsAppListVisible()); | |
| 1793 | |
| 1794 // Open the app list menu and check that the drag and drop host was set. | |
| 1795 gfx::Rect app_list_bounds = | |
| 1796 test.shelf_view()->GetAppListButton()->GetBoundsInScreen(); | |
| 1797 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), | |
| 1798 app_list_bounds.CenterPoint().y()); | |
| 1799 base::RunLoop().RunUntilIdle(); | |
| 1800 generator.ClickLeftButton(); | |
| 1801 | |
| 1802 EXPECT_TRUE(service->IsAppListVisible()); | |
| 1803 app_list::AppsGridView* grid_view = | |
| 1804 AppListServiceAshTestApi().GetRootGridView(); | |
| 1805 ASSERT_TRUE(grid_view); | |
| 1806 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test()); | |
| 1807 | |
| 1808 // There should be 2 items in our application list. | |
| 1809 const views::ViewModelT<app_list::AppListItemView>* vm_grid = | |
| 1810 grid_view->view_model_for_test(); | |
| 1811 EXPECT_EQ(2, vm_grid->view_size()); | |
| 1812 | |
| 1813 // Test #1: Drag an app list which does not exist yet item into the | |
| 1814 // launcher. Keeping it dragged, see that a new item gets created. Continuing | |
| 1815 // to drag it out should remove it again. | |
| 1816 | |
| 1817 // Get over item #1 of the application list and press the mouse button. | |
| 1818 views::View* item1 = vm_grid->view_at(1); | |
| 1819 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen(); | |
| 1820 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1821 bounds_grid_1.CenterPoint().y()); | |
| 1822 base::RunLoop().RunUntilIdle(); | |
| 1823 generator.PressLeftButton(); | |
| 1824 | |
| 1825 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1826 | |
| 1827 // Drag the item into the shelf and check that a new item gets created. | |
| 1828 const views::ViewModel* vm_shelf = test.shelf_view()->view_model_for_test(); | |
| 1829 views::View* shelf1 = vm_shelf->view_at(1); | |
| 1830 gfx::Rect bounds_shelf_1 = shelf1->GetBoundsInScreen(); | |
| 1831 generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(), | |
| 1832 bounds_shelf_1.CenterPoint().y()); | |
| 1833 base::RunLoop().RunUntilIdle(); | |
| 1834 | |
| 1835 // Check that a new item got created. | |
| 1836 EXPECT_EQ(3, model_->item_count()); | |
| 1837 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1838 | |
| 1839 // Move it where the item originally was and check that it disappears again. | |
| 1840 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1841 bounds_grid_1.CenterPoint().y()); | |
| 1842 base::RunLoop().RunUntilIdle(); | |
| 1843 EXPECT_EQ(2, model_->item_count()); | |
| 1844 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1845 | |
| 1846 // Dropping it should keep the launcher as it originally was. | |
| 1847 generator.ReleaseLeftButton(); | |
| 1848 base::RunLoop().RunUntilIdle(); | |
| 1849 EXPECT_EQ(2, model_->item_count()); | |
| 1850 // There are a few animations which need finishing before we can continue. | |
| 1851 test.RunMessageLoopUntilAnimationsDone(); | |
| 1852 // Move the mouse outside of the launcher. | |
| 1853 generator.MoveMouseTo(0, 0); | |
| 1854 | |
| 1855 // Test #2: Check that the unknown item dropped into the launcher will | |
| 1856 // create a new item. | |
| 1857 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1858 bounds_grid_1.CenterPoint().y()); | |
| 1859 generator.PressLeftButton(); | |
| 1860 generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(), | |
| 1861 bounds_shelf_1.CenterPoint().y()); | |
| 1862 base::RunLoop().RunUntilIdle(); | |
| 1863 EXPECT_EQ(3, model_->item_count()); | |
| 1864 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1865 generator.ReleaseLeftButton(); | |
| 1866 base::RunLoop().RunUntilIdle(); | |
| 1867 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1868 EXPECT_EQ(3, model_->item_count()); // It should be still there. | |
| 1869 test.RunMessageLoopUntilAnimationsDone(); | |
| 1870 | |
| 1871 // Test #3: Check that the now known item dropped into the launcher will | |
| 1872 // not create a new item. | |
| 1873 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1874 bounds_grid_1.CenterPoint().y()); | |
| 1875 generator.PressLeftButton(); | |
| 1876 generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(), | |
| 1877 bounds_shelf_1.CenterPoint().y()); | |
| 1878 base::RunLoop().RunUntilIdle(); | |
| 1879 EXPECT_EQ(3, model_->item_count()); // No new item got added. | |
| 1880 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1881 generator.ReleaseLeftButton(); | |
| 1882 base::RunLoop().RunUntilIdle(); | |
| 1883 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1884 EXPECT_EQ(3, model_->item_count()); // And it remains that way. | |
| 1885 | |
| 1886 // Test #4: Check that by pressing ESC the operation gets cancelled. | |
| 1887 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1888 bounds_grid_1.CenterPoint().y()); | |
| 1889 generator.PressLeftButton(); | |
| 1890 generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(), | |
| 1891 bounds_shelf_1.CenterPoint().y()); | |
| 1892 base::RunLoop().RunUntilIdle(); | |
| 1893 // Issue an ESC and see that the operation gets cancelled. | |
| 1894 generator.PressKey(ui::VKEY_ESCAPE, 0); | |
| 1895 generator.ReleaseKey(ui::VKEY_ESCAPE, 0); | |
| 1896 EXPECT_FALSE(grid_view->dragging()); | |
| 1897 EXPECT_FALSE(grid_view->has_dragged_view()); | |
| 1898 generator.ReleaseLeftButton(); | |
| 1899 } | |
| 1900 | |
| 1901 // Do basic drag and drop interaction tests between the application list and | |
| 1902 // the launcher in the secondary monitor. | |
| 1903 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MultiDisplayBasicDragAndDrop) { | |
| 1904 // Update the display configuration to add a secondary display. | |
| 1905 display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) | |
| 1906 .UpdateDisplay("800x800,801+0-800x800"); | |
| 1907 | |
| 1908 // Get a number of interfaces we need. | |
| 1909 DCHECK_EQ(ash::Shell::GetAllRootWindows().size(), 2U); | |
| 1910 aura::Window* secondary_root_window = ash::Shell::GetAllRootWindows()[1]; | |
| 1911 ash::WmShelf* secondary_shelf = | |
| 1912 ash::WmShelf::ForWindow(ash::WmWindow::Get(secondary_root_window)); | |
| 1913 | |
| 1914 ui::test::EventGenerator generator(secondary_root_window, gfx::Point()); | |
| 1915 ash::test::ShelfViewTestAPI test(secondary_shelf->GetShelfViewForTesting()); | |
| 1916 AppListService* service = AppListService::Get(); | |
| 1917 | |
| 1918 // There should be two items in our shelf by this time. | |
| 1919 EXPECT_EQ(2, model_->item_count()); | |
| 1920 EXPECT_FALSE(service->IsAppListVisible()); | |
| 1921 | |
| 1922 // Open the app list menu and check that the drag and drop host was set. | |
| 1923 gfx::Rect app_list_bounds = | |
| 1924 test.shelf_view()->GetAppListButton()->GetBoundsInScreen(); | |
| 1925 display::Display display = | |
| 1926 display::Screen::GetScreen()->GetDisplayNearestWindow( | |
| 1927 secondary_root_window); | |
| 1928 const gfx::Point& origin = display.bounds().origin(); | |
| 1929 app_list_bounds.Offset(-origin.x(), -origin.y()); | |
| 1930 | |
| 1931 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), | |
| 1932 app_list_bounds.CenterPoint().y()); | |
| 1933 generator.ClickLeftButton(); | |
| 1934 base::RunLoop().RunUntilIdle(); | |
| 1935 EXPECT_TRUE(service->IsAppListVisible()); | |
| 1936 | |
| 1937 // Click the "all apps" button on the start page. | |
| 1938 ClickAllAppsButtonFromStartPage(&generator, origin); | |
| 1939 EXPECT_TRUE(service->IsAppListVisible()); | |
| 1940 | |
| 1941 app_list::AppsGridView* grid_view = | |
| 1942 AppListServiceAshTestApi().GetRootGridView(); | |
| 1943 ASSERT_TRUE(grid_view); | |
| 1944 ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test()); | |
| 1945 | |
| 1946 // There should be 2 items in our application list. | |
| 1947 const views::ViewModelT<app_list::AppListItemView>* vm_grid = | |
| 1948 grid_view->view_model_for_test(); | |
| 1949 EXPECT_EQ(2, vm_grid->view_size()); | |
| 1950 | |
| 1951 // Drag an app list item which does not exist yet in the shelf. | |
| 1952 // Keeping it dragged, see that a new item gets created. | |
| 1953 // Continuing to drag it out should remove it again. | |
| 1954 | |
| 1955 // Get over item #1 of the application list and press the mouse button. | |
| 1956 views::View* item1 = vm_grid->view_at(1); | |
| 1957 gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen(); | |
| 1958 bounds_grid_1.Offset(-origin.x(), -origin.y()); | |
| 1959 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 1960 bounds_grid_1.CenterPoint().y()); | |
| 1961 base::RunLoop().RunUntilIdle(); | |
| 1962 generator.PressLeftButton(); | |
| 1963 | |
| 1964 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1965 | |
| 1966 // Drag the item into the shelf and check that a new item gets created. | |
| 1967 const views::ViewModel* vm_shelf = test.shelf_view()->view_model_for_test(); | |
| 1968 views::View* shelf1 = vm_shelf->view_at(1); | |
| 1969 gfx::Rect bounds_shelf_1 = shelf1->GetBoundsInScreen(); | |
| 1970 bounds_shelf_1.Offset(-origin.x(), -origin.y()); | |
| 1971 generator.MoveMouseTo(bounds_shelf_1.CenterPoint().x(), | |
| 1972 bounds_shelf_1.CenterPoint().y()); | |
| 1973 base::RunLoop().RunUntilIdle(); | |
| 1974 | |
| 1975 // Check that a new item got created. | |
| 1976 EXPECT_EQ(3, model_->item_count()); | |
| 1977 EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1978 | |
| 1979 // Move it to an empty slot on grid_view. | |
| 1980 gfx::Rect empty_slot_rect = bounds_grid_1; | |
| 1981 empty_slot_rect.Offset(0, grid_view->GetTotalTileSize().height()); | |
| 1982 generator.MoveMouseTo(empty_slot_rect.CenterPoint().x(), | |
| 1983 empty_slot_rect.CenterPoint().y()); | |
| 1984 base::RunLoop().RunUntilIdle(); | |
| 1985 EXPECT_EQ(2, model_->item_count()); | |
| 1986 EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test()); | |
| 1987 | |
| 1988 // Dropping it should keep the shelf as it originally was. | |
| 1989 generator.ReleaseLeftButton(); | |
| 1990 base::RunLoop().RunUntilIdle(); | |
| 1991 EXPECT_EQ(2, model_->item_count()); | |
| 1992 } | |
| 1993 | |
| 1994 // Do tests for removal of items from the shelf by dragging. | |
| 1995 // Disabled due to flake: http://crbug.com/448482 | |
| 1996 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, DISABLED_DragOffShelf) { | |
| 1997 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), | |
| 1998 gfx::Point()); | |
| 1999 ash::test::ShelfViewTestAPI test(shelf_->GetShelfViewForTesting()); | |
| 2000 test.SetAnimationDuration(1); // Speed up animations for test. | |
| 2001 // Create a known application and check that we have 3 items in the shelf. | |
| 2002 CreateShortcut("app1"); | |
| 2003 test.RunMessageLoopUntilAnimationsDone(); | |
| 2004 EXPECT_EQ(3, model_->item_count()); | |
| 2005 | |
| 2006 // Test #1: Ripping out the browser item should not change anything. | |
| 2007 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); | |
| 2008 EXPECT_LE(0, browser_index); | |
| 2009 RipOffItemIndex(browser_index, &generator, &test, RIP_OFF_ITEM); | |
| 2010 // => It should not have been removed and the location should be unchanged. | |
| 2011 EXPECT_EQ(3, model_->item_count()); | |
| 2012 EXPECT_EQ(browser_index, | |
| 2013 GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT)); | |
| 2014 // Make sure that the hide state has been unset after the snap back animation | |
| 2015 // finished. | |
| 2016 ash::ShelfButton* button = test.GetButton(browser_index); | |
| 2017 EXPECT_FALSE(button->state() & ash::ShelfButton::STATE_HIDDEN); | |
| 2018 | |
| 2019 // Test #2: Ripping out the application and canceling the operation should | |
| 2020 // not change anything. | |
| 2021 int app_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP); | |
| 2022 EXPECT_LE(0, app_index); | |
| 2023 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_CANCEL); | |
| 2024 // => It should not have been removed and the location should be unchanged. | |
| 2025 ASSERT_EQ(3, model_->item_count()); | |
| 2026 EXPECT_EQ(app_index, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP)); | |
| 2027 | |
| 2028 // Test #3: Ripping out the application and moving it back in should not | |
| 2029 // change anything. | |
| 2030 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_RETURN); | |
| 2031 // => It should not have been removed and the location should be unchanged. | |
| 2032 ASSERT_EQ(3, model_->item_count()); | |
| 2033 // Through the operation the index might have changed. | |
| 2034 app_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP); | |
| 2035 | |
| 2036 // Test #4: Ripping out the application should remove the item. | |
| 2037 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); | |
| 2038 // => It should not have been removed and the location should be unchanged. | |
| 2039 EXPECT_EQ(2, model_->item_count()); | |
| 2040 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP)); | |
| 2041 | |
| 2042 // Test #5: Uninstalling an application while it is being ripped off should | |
| 2043 // not crash. | |
| 2044 CreateShortcut("app2"); | |
| 2045 test.RunMessageLoopUntilAnimationsDone(); | |
| 2046 int app2_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP); | |
| 2047 EXPECT_EQ(3, model_->item_count()); // And it remains that way. | |
| 2048 RipOffItemIndex(app2_index, | |
| 2049 &generator, | |
| 2050 &test, | |
| 2051 RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE); | |
| 2052 controller_->UnpinAppWithID("app2"); | |
| 2053 test.RunMessageLoopUntilAnimationsDone(); | |
| 2054 EXPECT_EQ(2, model_->item_count()); // The item should now be gone. | |
| 2055 generator.ReleaseLeftButton(); | |
| 2056 base::RunLoop().RunUntilIdle(); | |
| 2057 EXPECT_EQ(2, model_->item_count()); // And it remains that way. | |
| 2058 EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_PINNED_APP)); | |
| 2059 | |
| 2060 // Test #6: Ripping out the application when the overflow button exists. | |
| 2061 // After ripping out, overflow button should be removed. | |
| 2062 int items_added = 0; | |
| 2063 EXPECT_FALSE(test.IsOverflowButtonVisible()); | |
| 2064 | |
| 2065 // Create fake app shortcuts until overflow button is created. | |
| 2066 while (!test.IsOverflowButtonVisible()) { | |
| 2067 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); | |
| 2068 PinFakeApp(fake_app_id); | |
| 2069 test.RunMessageLoopUntilAnimationsDone(); | |
| 2070 | |
| 2071 ++items_added; | |
| 2072 ASSERT_LT(items_added, 10000); | |
| 2073 } | |
| 2074 // Make one more item after creating a overflow button. | |
| 2075 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); | |
| 2076 PinFakeApp(fake_app_id); | |
| 2077 test.RunMessageLoopUntilAnimationsDone(); | |
| 2078 | |
| 2079 int total_count = model_->item_count(); | |
| 2080 app_index = GetIndexOfShelfItemType(ash::TYPE_PINNED_APP); | |
| 2081 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); | |
| 2082 // When an item is ripped off from the shelf that has overflow button | |
| 2083 // (see crbug.com/3050787), it was hidden accidentally and was then | |
| 2084 // suppressing any further events. If handled correctly the operation will | |
| 2085 // however correctly done and the item will get removed (as well as the | |
| 2086 // overflow button). | |
| 2087 EXPECT_EQ(total_count - 1, model_->item_count()); | |
| 2088 EXPECT_TRUE(test.IsOverflowButtonVisible()); | |
| 2089 | |
| 2090 // Rip off again and the overflow button should has disappeared. | |
| 2091 RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); | |
| 2092 EXPECT_EQ(total_count - 2, model_->item_count()); | |
| 2093 EXPECT_FALSE(test.IsOverflowButtonVisible()); | |
| 2094 } | |
| 2095 | |
| 2096 // Check that clicking on an app shelf item launches a new browser. | |
| 2097 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, ClickItem) { | |
| 2098 // Get a number of interfaces we need. | |
| 2099 ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), | |
| 2100 gfx::Point()); | |
| 2101 ash::test::ShelfViewTestAPI test(shelf_->GetShelfViewForTesting()); | |
| 2102 AppListService* service = AppListService::Get(); | |
| 2103 // There should be two items in our shelf by this time. | |
| 2104 EXPECT_EQ(2, model_->item_count()); | |
| 2105 EXPECT_FALSE(service->IsAppListVisible()); | |
| 2106 | |
| 2107 // Open the app list menu and check that the drag and drop host was set. | |
| 2108 gfx::Rect app_list_bounds = | |
| 2109 test.shelf_view()->GetAppListButton()->GetBoundsInScreen(); | |
| 2110 generator.MoveMouseTo(app_list_bounds.CenterPoint().x(), | |
| 2111 app_list_bounds.CenterPoint().y()); | |
| 2112 generator.ClickLeftButton(); | |
| 2113 base::RunLoop().RunUntilIdle(); | |
| 2114 EXPECT_TRUE(service->IsAppListVisible()); | |
| 2115 | |
| 2116 // Click the "all apps" button on the start page. | |
| 2117 ClickAllAppsButtonFromStartPage(&generator, gfx::Point()); | |
| 2118 EXPECT_TRUE(service->IsAppListVisible()); | |
| 2119 | |
| 2120 // Click an app icon in the app grid view. | |
| 2121 app_list::AppsGridView* grid_view = | |
| 2122 AppListServiceAshTestApi().GetRootGridView(); | |
| 2123 ASSERT_TRUE(grid_view); | |
| 2124 const views::ViewModelT<app_list::AppListItemView>* vm_grid = | |
| 2125 grid_view->view_model_for_test(); | |
| 2126 EXPECT_EQ(2, vm_grid->view_size()); | |
| 2127 gfx::Rect bounds_grid_1 = vm_grid->view_at(1)->GetBoundsInScreen(); | |
| 2128 // Test now that a click does create a new application tab. | |
| 2129 TabStripModel* tab_strip = browser()->tab_strip_model(); | |
| 2130 int tab_count = tab_strip->count(); | |
| 2131 generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(), | |
| 2132 bounds_grid_1.CenterPoint().y()); | |
| 2133 generator.ClickLeftButton(); | |
| 2134 base::RunLoop().RunUntilIdle(); | |
| 2135 EXPECT_EQ(tab_count + 1, tab_strip->count()); | |
| 2136 } | |
| 2137 | |
| 2138 // Check ash::ShelfItemDelegate of Browser Shortcut functionality. | |
| 2139 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTestNoDefaultBrowser, | |
| 2140 BrowserShortcutLauncherItemController) { | |
| 2141 ash::ShelfItemDelegate* item_controller = | |
| 2142 controller_->GetBrowserShortcutLauncherItemController(); | |
| 2143 const ash::ShelfID id = item_controller->shelf_id(); | |
| 2144 EXPECT_NE(ash::kInvalidShelfID, id); | |
| 2145 | |
| 2146 // Get the number of browsers. | |
| 2147 size_t running_browser = chrome::GetTotalBrowserCount(); | |
| 2148 EXPECT_EQ(0u, running_browser); | |
| 2149 EXPECT_FALSE(controller_->IsOpen(id)); | |
| 2150 | |
| 2151 // Activate. This creates new browser | |
| 2152 SelectItem(item_controller, ui::ET_UNKNOWN); | |
| 2153 // New Window is created. | |
| 2154 running_browser = chrome::GetTotalBrowserCount(); | |
| 2155 EXPECT_EQ(1u, running_browser); | |
| 2156 EXPECT_TRUE(controller_->IsOpen(id)); | |
| 2157 | |
| 2158 // Minimize Window. | |
| 2159 ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState(); | |
| 2160 window_state->Minimize(); | |
| 2161 EXPECT_TRUE(window_state->IsMinimized()); | |
| 2162 | |
| 2163 // Activate again. This doesn't create new browser, it activates the window. | |
| 2164 SelectItem(item_controller, ui::ET_UNKNOWN); | |
| 2165 running_browser = chrome::GetTotalBrowserCount(); | |
| 2166 EXPECT_EQ(1u, running_browser); | |
| 2167 EXPECT_TRUE(controller_->IsOpen(id)); | |
| 2168 EXPECT_FALSE(window_state->IsMinimized()); | |
| 2169 } | |
| 2170 | |
| 2171 // Check that the window's ShelfID property matches that of the active tab. | |
| 2172 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, MatchingShelfIDandActiveTab) { | |
| 2173 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); | |
| 2174 EXPECT_EQ(1, browser()->tab_strip_model()->count()); | |
| 2175 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); | |
| 2176 EXPECT_EQ(2, model_->item_count()); | |
| 2177 | |
| 2178 ash::WmWindow* window = | |
| 2179 ash::WmWindow::Get(browser()->window()->GetNativeWindow()); | |
| 2180 | |
| 2181 int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT); | |
| 2182 ash::ShelfID browser_id = model_->items()[browser_index].id; | |
| 2183 ash::ShelfID id = window->aura_window()->GetProperty(ash::kShelfIDKey); | |
| 2184 EXPECT_EQ(browser_id, id); | |
| 2185 | |
| 2186 ash::ShelfID app_id = CreateShortcut("app1"); | |
| 2187 EXPECT_EQ(3, model_->item_count()); | |
| 2188 | |
| 2189 // Create and activate a new tab for "app1" and expect an application ShelfID. | |
| 2190 WmShelf::ActivateShelfItem(model_->ItemIndexByID(app_id)); | |
| 2191 EXPECT_EQ(2, browser()->tab_strip_model()->count()); | |
| 2192 EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); | |
| 2193 id = window->aura_window()->GetProperty(ash::kShelfIDKey); | |
| 2194 EXPECT_EQ(app_id, id); | |
| 2195 | |
| 2196 // Activate the tab at index 0 (NTP) and expect a browser ShelfID. | |
| 2197 browser()->tab_strip_model()->ActivateTabAt(0, false); | |
| 2198 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); | |
| 2199 id = window->aura_window()->GetProperty(ash::kShelfIDKey); | |
| 2200 EXPECT_EQ(browser_id, id); | |
| 2201 } | |
| 2202 | |
| 2203 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, OverflowBubble) { | |
| 2204 // Make sure to have a browser window | |
| 2205 chrome::NewTab(browser()); | |
| 2206 | |
| 2207 // No overflow yet. | |
| 2208 EXPECT_FALSE(shelf_->shelf_widget()->IsShowingOverflowBubble()); | |
| 2209 | |
| 2210 ash::test::ShelfViewTestAPI test(shelf_->GetShelfViewForTesting()); | |
| 2211 | |
| 2212 int items_added = 0; | |
| 2213 while (!test.IsOverflowButtonVisible()) { | |
| 2214 std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); | |
| 2215 PinFakeApp(fake_app_id); | |
| 2216 | |
| 2217 ++items_added; | |
| 2218 ASSERT_LT(items_added, 10000); | |
| 2219 } | |
| 2220 | |
| 2221 // Now show overflow bubble. | |
| 2222 test.ShowOverflowBubble(); | |
| 2223 EXPECT_TRUE(shelf_->shelf_widget()->IsShowingOverflowBubble()); | |
| 2224 | |
| 2225 // Unpin first pinned app and there should be no crash. | |
| 2226 controller_->UnpinAppWithID("fake_app_0"); | |
| 2227 | |
| 2228 test.RunMessageLoopUntilAnimationsDone(); | |
| 2229 EXPECT_FALSE(shelf_->shelf_widget()->IsShowingOverflowBubble()); | |
| 2230 } | |
| 2231 | |
| 2232 // Check that a windowed V1 application can navigate away from its domain, but | |
| 2233 // still gets detected properly. | |
| 2234 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, V1AppNavigation) { | |
| 2235 // We assume that the web store is always there (which it apparently is). | |
| 2236 controller_->PinAppWithID(extensions::kWebStoreAppId); | |
| 2237 ash::ShelfID id = controller_->GetShelfIDForAppID(extensions::kWebStoreAppId); | |
| 2238 DCHECK_NE(id, ash::kInvalidShelfID); | |
| 2239 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status); | |
| 2240 | |
| 2241 // Create a windowed application. | |
| 2242 AppLaunchParams params = CreateAppLaunchParamsUserContainer( | |
| 2243 profile(), GetExtensionForAppID(extensions::kWebStoreAppId, profile()), | |
| 2244 WindowOpenDisposition::NEW_FOREGROUND_TAB, extensions::SOURCE_TEST); | |
| 2245 params.container = extensions::LAUNCH_CONTAINER_WINDOW; | |
| 2246 OpenApplication(params); | |
| 2247 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status); | |
| 2248 | |
| 2249 // Find the browser which holds our app. | |
| 2250 Browser* app_browser = NULL; | |
| 2251 const BrowserList* browser_list = BrowserList::GetInstance(); | |
| 2252 for (BrowserList::const_reverse_iterator it = | |
| 2253 browser_list->begin_last_active(); | |
| 2254 it != browser_list->end_last_active() && !app_browser; ++it) { | |
| 2255 if ((*it)->is_app()) { | |
| 2256 app_browser = *it; | |
| 2257 break; | |
| 2258 } | |
| 2259 } | |
| 2260 ASSERT_TRUE(app_browser); | |
| 2261 | |
| 2262 // After navigating away in the app, we should still be active. | |
| 2263 ui_test_utils::NavigateToURL(app_browser, | |
| 2264 GURL("http://www.foo.com/bar.html")); | |
| 2265 // Make sure the navigation was entirely performed. | |
| 2266 base::RunLoop().RunUntilIdle(); | |
| 2267 EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status); | |
| 2268 app_browser->tab_strip_model()->CloseWebContentsAt(0, | |
| 2269 TabStripModel::CLOSE_NONE); | |
| 2270 // Make sure that the app is really gone. | |
| 2271 base::RunLoop().RunUntilIdle(); | |
| 2272 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status); | |
| 2273 } | |
| 2274 | |
| 2275 // Checks that a opening a settings window creates a new launcher item. | |
| 2276 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, SettingsWindow) { | |
| 2277 chrome::SettingsWindowManager* settings_manager = | |
| 2278 chrome::SettingsWindowManager::GetInstance(); | |
| 2279 ash::ShelfModel* shelf_model = ash::Shell::Get()->shelf_model(); | |
| 2280 | |
| 2281 // Get the number of items in the shelf and browser menu. | |
| 2282 int item_count = shelf_model->item_count(); | |
| 2283 size_t browser_count = NumberOfDetectedLauncherBrowsers(false); | |
| 2284 | |
| 2285 // Open a settings window. Number of browser items should remain unchanged, | |
| 2286 // number of shelf items should increase. | |
| 2287 settings_manager->ShowChromePageForProfile( | |
| 2288 browser()->profile(), | |
| 2289 chrome::GetSettingsUrl(std::string())); | |
| 2290 Browser* settings_browser = | |
| 2291 settings_manager->FindBrowserForProfile(browser()->profile()); | |
| 2292 ASSERT_TRUE(settings_browser); | |
| 2293 EXPECT_EQ(browser_count, NumberOfDetectedLauncherBrowsers(false)); | |
| 2294 EXPECT_EQ(item_count + 1, shelf_model->item_count()); | |
| 2295 | |
| 2296 // TODO(stevenjb): Test multiprofile on Chrome OS when test support is addded. | |
| 2297 // crbug.com/230464. | |
| 2298 } | |
| 2299 | |
| 2300 // Check that tabbed hosted and bookmark apps have correct shelf presence. | |
| 2301 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, TabbedHostedAndBookmarkApps) { | |
| 2302 // Load and pin a hosted app. | |
| 2303 const Extension* hosted_app = | |
| 2304 LoadExtension(test_data_dir_.AppendASCII("app1/")); | |
| 2305 ASSERT_TRUE(hosted_app); | |
| 2306 controller_->PinAppWithID(hosted_app->id()); | |
| 2307 const ash::ShelfID hosted_app_shelf_id = | |
| 2308 controller_->GetShelfIDForAppID(hosted_app->id()); | |
| 2309 | |
| 2310 // Load and pin a bookmark app. | |
| 2311 const Extension* bookmark_app = InstallExtensionWithSourceAndFlags( | |
| 2312 test_data_dir_.AppendASCII("app2/"), 1, extensions::Manifest::INTERNAL, | |
| 2313 extensions::Extension::FROM_BOOKMARK); | |
| 2314 ASSERT_TRUE(bookmark_app); | |
| 2315 controller_->PinAppWithID(bookmark_app->id()); | |
| 2316 const ash::ShelfID bookmark_app_shelf_id = | |
| 2317 controller_->GetShelfIDForAppID(bookmark_app->id()); | |
| 2318 | |
| 2319 // The apps should be closed. | |
| 2320 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status); | |
| 2321 EXPECT_EQ(ash::STATUS_CLOSED, | |
| 2322 model_->ItemByID(bookmark_app_shelf_id)->status); | |
| 2323 | |
| 2324 // Navigate to the app's launch URLs in two tabs. | |
| 2325 ui_test_utils::NavigateToURL( | |
| 2326 browser(), extensions::AppLaunchInfo::GetLaunchWebURL(hosted_app)); | |
| 2327 ui_test_utils::NavigateToURLWithDisposition( | |
| 2328 browser(), extensions::AppLaunchInfo::GetLaunchWebURL(bookmark_app), | |
| 2329 WindowOpenDisposition::NEW_FOREGROUND_TAB, 0); | |
| 2330 | |
| 2331 // The apps should now be running, with the last opened app active. | |
| 2332 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(hosted_app_shelf_id)->status); | |
| 2333 EXPECT_EQ(ash::STATUS_ACTIVE, | |
| 2334 model_->ItemByID(bookmark_app_shelf_id)->status); | |
| 2335 | |
| 2336 // Now use the launcher controller to activate the apps. | |
| 2337 controller_->ActivateApp(hosted_app->id(), ash::LAUNCH_FROM_APP_LIST, 0); | |
| 2338 controller_->ActivateApp(bookmark_app->id(), ash::LAUNCH_FROM_APP_LIST, 0); | |
| 2339 | |
| 2340 // There should be no new browsers or tabs as both apps were already open. | |
| 2341 EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile())); | |
| 2342 EXPECT_EQ(2, browser()->tab_strip_model()->count()); | |
| 2343 } | |
| 2344 | |
| 2345 // Check that windowed hosted and bookmark apps have correct shelf presence. | |
| 2346 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, WindowedHostedAndBookmarkApps) { | |
| 2347 // Load and pin a hosted app. | |
| 2348 const Extension* hosted_app = | |
| 2349 LoadExtension(test_data_dir_.AppendASCII("app1/")); | |
| 2350 ASSERT_TRUE(hosted_app); | |
| 2351 controller_->PinAppWithID(hosted_app->id()); | |
| 2352 const ash::ShelfID hosted_app_shelf_id = | |
| 2353 controller_->GetShelfIDForAppID(hosted_app->id()); | |
| 2354 | |
| 2355 // Load and pin a bookmark app. | |
| 2356 const Extension* bookmark_app = InstallExtensionWithSourceAndFlags( | |
| 2357 test_data_dir_.AppendASCII("app2/"), 1, extensions::Manifest::INTERNAL, | |
| 2358 extensions::Extension::FROM_BOOKMARK); | |
| 2359 ASSERT_TRUE(bookmark_app); | |
| 2360 controller_->PinAppWithID(bookmark_app->id()); | |
| 2361 const ash::ShelfID bookmark_app_shelf_id = | |
| 2362 controller_->GetShelfIDForAppID(bookmark_app->id()); | |
| 2363 | |
| 2364 // Set both apps to open in windows. | |
| 2365 extensions::SetLaunchType(browser()->profile(), hosted_app->id(), | |
| 2366 extensions::LAUNCH_TYPE_WINDOW); | |
| 2367 extensions::SetLaunchType(browser()->profile(), bookmark_app->id(), | |
| 2368 extensions::LAUNCH_TYPE_WINDOW); | |
| 2369 | |
| 2370 // The apps should be closed. | |
| 2371 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status); | |
| 2372 EXPECT_EQ(ash::STATUS_CLOSED, | |
| 2373 model_->ItemByID(bookmark_app_shelf_id)->status); | |
| 2374 | |
| 2375 // Navigate to the app's launch URLs in two tabs. | |
| 2376 ui_test_utils::NavigateToURL( | |
| 2377 browser(), extensions::AppLaunchInfo::GetLaunchWebURL(hosted_app)); | |
| 2378 ui_test_utils::NavigateToURLWithDisposition( | |
| 2379 browser(), extensions::AppLaunchInfo::GetLaunchWebURL(bookmark_app), | |
| 2380 WindowOpenDisposition::NEW_FOREGROUND_TAB, 0); | |
| 2381 | |
| 2382 // The apps should still be closed. | |
| 2383 EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(hosted_app_shelf_id)->status); | |
| 2384 EXPECT_EQ(ash::STATUS_CLOSED, | |
| 2385 model_->ItemByID(bookmark_app_shelf_id)->status); | |
| 2386 | |
| 2387 // Now use the launcher controller to activate the apps. | |
| 2388 controller_->ActivateApp(hosted_app->id(), ash::LAUNCH_FROM_APP_LIST, 0); | |
| 2389 controller_->ActivateApp(bookmark_app->id(), ash::LAUNCH_FROM_APP_LIST, 0); | |
| 2390 | |
| 2391 // There should be two new browsers. | |
| 2392 EXPECT_EQ(3u, chrome::GetBrowserCount(browser()->profile())); | |
| 2393 | |
| 2394 // The apps should now be running, with the last opened app active. | |
| 2395 EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(hosted_app_shelf_id)->status); | |
| 2396 EXPECT_EQ(ash::STATUS_ACTIVE, | |
| 2397 model_->ItemByID(bookmark_app_shelf_id)->status); | |
| 2398 } | |
| 2399 | |
| 2400 // Test that "Close" is shown in the context menu when there are opened browsers | |
| 2401 // windows. | |
| 2402 IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, | |
| 2403 LauncherContextMenuVerifyCloseItemAppearance) { | |
| 2404 // Open a context menu for the existing browser window. | |
| 2405 std::unique_ptr<LauncherContextMenu> menu1 = CreateBrowserItemContextMenu(); | |
| 2406 // Check if "Close" is added to in the context menu. | |
| 2407 ASSERT_TRUE( | |
| 2408 IsItemPresentInMenu(menu1.get(), LauncherContextMenu::MENU_CLOSE)); | |
| 2409 | |
| 2410 // Close all windows via the menu item. | |
| 2411 CloseBrowserWindow(browser(), menu1.get(), LauncherContextMenu::MENU_CLOSE); | |
| 2412 EXPECT_EQ(0u, BrowserList::GetInstance()->size()); | |
| 2413 | |
| 2414 // Check if "Close" is removed from the context menu. | |
| 2415 std::unique_ptr<LauncherContextMenu> menu2 = CreateBrowserItemContextMenu(); | |
| 2416 ASSERT_FALSE( | |
| 2417 IsItemPresentInMenu(menu2.get(), LauncherContextMenu::MENU_CLOSE)); | |
| 2418 } | |
| OLD | NEW |