Home | History | Annotate | Download | only in launcher
      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.h"
      6 
      7 #include "apps/shell_window.h"
      8 #include "apps/shell_window_registry.h"
      9 #include "apps/ui/native_app_window.h"
     10 #include "ash/ash_switches.h"
     11 #include "ash/display/display_controller.h"
     12 #include "ash/launcher/launcher.h"
     13 #include "ash/shelf/shelf_button.h"
     14 #include "ash/shelf/shelf_model.h"
     15 #include "ash/shelf/shelf_util.h"
     16 #include "ash/shelf/shelf_view.h"
     17 #include "ash/shell.h"
     18 #include "ash/test/app_list_controller_test_api.h"
     19 #include "ash/test/launcher_test_api.h"
     20 #include "ash/test/shelf_view_test_api.h"
     21 #include "ash/test/shell_test_api.h"
     22 #include "ash/wm/window_state.h"
     23 #include "ash/wm/window_util.h"
     24 #include "base/strings/stringprintf.h"
     25 #include "base/strings/utf_string_conversions.h"
     26 #include "chrome/browser/apps/app_browsertest_util.h"
     27 #include "chrome/browser/automation/automation_util.h"
     28 #include "chrome/browser/chrome_notification_types.h"
     29 #include "chrome/browser/extensions/extension_apitest.h"
     30 #include "chrome/browser/extensions/extension_browsertest.h"
     31 #include "chrome/browser/extensions/extension_function_test_utils.h"
     32 #include "chrome/browser/extensions/extension_service.h"
     33 #include "chrome/browser/extensions/extension_system.h"
     34 #include "chrome/browser/extensions/extension_test_message_listener.h"
     35 #include "chrome/browser/profiles/profile.h"
     36 #include "chrome/browser/ui/app_list/app_list_service.h"
     37 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
     38 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
     39 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
     40 #include "chrome/browser/ui/browser.h"
     41 #include "chrome/browser/ui/browser_commands.h"
     42 #include "chrome/browser/ui/browser_finder.h"
     43 #include "chrome/browser/ui/browser_list.h"
     44 #include "chrome/browser/ui/browser_window.h"
     45 #include "chrome/browser/ui/extensions/application_launch.h"
     46 #include "chrome/browser/ui/host_desktop.h"
     47 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     48 #include "chrome/common/chrome_switches.h"
     49 #include "chrome/test/base/ui_test_utils.h"
     50 #include "content/public/browser/notification_service.h"
     51 #include "content/public/browser/notification_source.h"
     52 #include "content/public/browser/web_contents.h"
     53 #include "content/public/test/browser_test_utils.h"
     54 #include "extensions/common/constants.h"
     55 #include "extensions/common/switches.h"
     56 #include "testing/gtest/include/gtest/gtest.h"
     57 #include "ui/app_list/views/apps_grid_view.h"
     58 #include "ui/aura/client/aura_constants.h"
     59 #include "ui/aura/test/event_generator.h"
     60 #include "ui/aura/window.h"
     61 #include "ui/events/event.h"
     62 
     63 using apps::ShellWindow;
     64 using extensions::Extension;
     65 using content::WebContents;
     66 
     67 namespace {
     68 
     69 class TestEvent : public ui::Event {
     70  public:
     71   explicit TestEvent(ui::EventType type)
     72       : ui::Event(type, base::TimeDelta(), 0) {
     73   }
     74   virtual ~TestEvent() {
     75   }
     76 
     77  private:
     78   DISALLOW_COPY_AND_ASSIGN(TestEvent);
     79 };
     80 
     81 class TestShellWindowRegistryObserver
     82     : public apps::ShellWindowRegistry::Observer {
     83  public:
     84   explicit TestShellWindowRegistryObserver(Profile* profile)
     85       : profile_(profile),
     86         icon_updates_(0) {
     87     apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
     88   }
     89 
     90   virtual ~TestShellWindowRegistryObserver() {
     91     apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
     92   }
     93 
     94   // Overridden from ShellWindowRegistry::Observer:
     95   virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {}
     96 
     97   virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {
     98     ++icon_updates_;
     99   }
    100 
    101   virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {}
    102 
    103   int icon_updates() { return icon_updates_; }
    104 
    105  private:
    106   Profile* profile_;
    107   int icon_updates_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(TestShellWindowRegistryObserver);
    110 };
    111 
    112 }  // namespace
    113 
    114 class LauncherPlatformAppBrowserTest
    115     : public extensions::PlatformAppBrowserTest {
    116  protected:
    117   LauncherPlatformAppBrowserTest() : launcher_(NULL), controller_(NULL) {
    118   }
    119 
    120   virtual ~LauncherPlatformAppBrowserTest() {}
    121 
    122   virtual void RunTestOnMainThreadLoop() OVERRIDE {
    123     launcher_ = ash::Launcher::ForPrimaryDisplay();
    124     controller_ = ChromeLauncherController::instance();
    125     return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop();
    126   }
    127 
    128   ash::ShelfModel* shelf_model() {
    129     return ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model();
    130   }
    131 
    132   ash::LauncherID CreateAppShortcutLauncherItem(const std::string& name) {
    133     return controller_->CreateAppShortcutLauncherItem(
    134         name, controller_->model()->item_count());
    135   }
    136 
    137   const ash::LauncherItem& GetLastLauncherItem() {
    138     // Unless there are any panels, the item at index [count - 1] will be
    139     // the desired item.
    140     return shelf_model()->items()[shelf_model()->item_count() - 1];
    141   }
    142 
    143   const ash::LauncherItem& GetLastLauncherPanelItem() {
    144     // Panels show up on the right side of the launcher, so the desired item
    145     // will be the last one.
    146     return shelf_model()->items()[shelf_model()->item_count() - 1];
    147   }
    148 
    149   LauncherItemController* GetItemController(ash::LauncherID id) {
    150     return controller_->id_to_item_controller_map_[id];
    151   }
    152 
    153   // Returns the number of menu items, ignoring separators.
    154   int GetNumApplicationMenuItems(const ash::LauncherItem& item) {
    155     const int event_flags = 0;
    156     scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
    157         controller_->GetApplicationList(item, event_flags)));
    158     int num_items = 0;
    159     for (int i = 0; i < menu->GetItemCount(); ++i) {
    160       if (menu->GetTypeAt(i) != ui::MenuModel::TYPE_SEPARATOR)
    161         ++num_items;
    162     }
    163     return num_items;
    164   }
    165 
    166   // Activate the launcher item with the given |id|.
    167   void ActivateLauncherItem(int id) {
    168     launcher_->ActivateLauncherItem(id);
    169   }
    170 
    171   ash::Launcher* launcher_;
    172   ChromeLauncherController* controller_;
    173 
    174  private:
    175 
    176   DISALLOW_COPY_AND_ASSIGN(LauncherPlatformAppBrowserTest);
    177 };
    178 
    179 enum RipOffCommand {
    180   // Drag the item off the shelf and let the mouse go.
    181   RIP_OFF_ITEM,
    182   // Drag the item off the shelf, move the mouse back and then let go.
    183   RIP_OFF_ITEM_AND_RETURN,
    184   // Drag the item off the shelf and then issue a cancel command.
    185   RIP_OFF_ITEM_AND_CANCEL,
    186   // Drag the item off the shelf and do not release the mouse.
    187   RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE,
    188 };
    189 
    190 class LauncherAppBrowserTest : public ExtensionBrowserTest {
    191  protected:
    192   LauncherAppBrowserTest() : launcher_(NULL), model_(NULL), controller_(NULL) {
    193   }
    194 
    195   virtual ~LauncherAppBrowserTest() {}
    196 
    197   virtual void RunTestOnMainThreadLoop() OVERRIDE {
    198     launcher_ = ash::Launcher::ForPrimaryDisplay();
    199     model_ = ash::test::ShellTestApi(ash::Shell::GetInstance()).shelf_model();
    200     controller_ = ChromeLauncherController::instance();
    201     return ExtensionBrowserTest::RunTestOnMainThreadLoop();
    202   }
    203 
    204   size_t NumberOfDetectedLauncherBrowsers(bool show_all_tabs) {
    205     LauncherItemController* item_controller =
    206       controller_->GetBrowserShortcutLauncherItemController();
    207     int items = item_controller->GetApplicationList(
    208         show_all_tabs ? ui::EF_SHIFT_DOWN : 0).size();
    209     // If we have at least one item, we have also a title which we remove here.
    210     return items ? (items - 1) : 0;
    211   }
    212 
    213   const Extension* LoadAndLaunchExtension(
    214       const char* name,
    215       extensions::LaunchContainer container,
    216       WindowOpenDisposition disposition) {
    217     EXPECT_TRUE(LoadExtension(test_data_dir_.AppendASCII(name)));
    218 
    219     ExtensionService* service = extensions::ExtensionSystem::Get(
    220         profile())->extension_service();
    221     const Extension* extension =
    222         service->GetExtensionById(last_loaded_extension_id(), false);
    223     EXPECT_TRUE(extension);
    224 
    225     OpenApplication(AppLaunchParams(profile(),
    226                                     extension,
    227                                     container,
    228                                     disposition));
    229     return extension;
    230   }
    231 
    232   ash::LauncherID CreateShortcut(const char* name) {
    233     ExtensionService* service = extensions::ExtensionSystem::Get(
    234         profile())->extension_service();
    235     LoadExtension(test_data_dir_.AppendASCII(name));
    236 
    237     // First get app_id.
    238     const Extension* extension =
    239         service->GetExtensionById(last_loaded_extension_id(), false);
    240     const std::string app_id = extension->id();
    241 
    242     // Then create a shortcut.
    243     int item_count = model_->item_count();
    244     ash::LauncherID shortcut_id = controller_->CreateAppShortcutLauncherItem(
    245         app_id,
    246         item_count);
    247     controller_->PersistPinnedState();
    248     EXPECT_EQ(++item_count, model_->item_count());
    249     const ash::LauncherItem& item = *model_->ItemByID(shortcut_id);
    250     EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    251     return item.id;
    252   }
    253 
    254   void RemoveShortcut(ash::LauncherID id) {
    255     controller_->Unpin(id);
    256   }
    257 
    258   // Activate the launcher item with the given |id|.
    259   void ActivateLauncherItem(int id) {
    260     launcher_->ActivateLauncherItem(id);
    261   }
    262 
    263   ash::LauncherID PinFakeApp(const std::string& name) {
    264     return controller_->CreateAppShortcutLauncherItem(
    265         name, model_->item_count());
    266   }
    267 
    268   // Get the index of an item which has the given type.
    269   int GetIndexOfShelfItemType(ash::LauncherItemType type) {
    270     return model_->GetItemIndexForType(type);
    271   }
    272 
    273   // Try to rip off |item_index|.
    274   void RipOffItemIndex(int index,
    275                        aura::test::EventGenerator* generator,
    276                        ash::test::ShelfViewTestAPI* test,
    277                        RipOffCommand command) {
    278     ash::internal::ShelfButton* button = test->GetButton(index);
    279     gfx::Point start_point = button->GetBoundsInScreen().CenterPoint();
    280     gfx::Point rip_off_point(start_point.x(), 0);
    281     generator->MoveMouseTo(start_point.x(), start_point.y());
    282     base::MessageLoop::current()->RunUntilIdle();
    283     generator->PressLeftButton();
    284     base::MessageLoop::current()->RunUntilIdle();
    285     generator->MoveMouseTo(rip_off_point.x(), rip_off_point.y());
    286     base::MessageLoop::current()->RunUntilIdle();
    287     test->RunMessageLoopUntilAnimationsDone();
    288     if (command == RIP_OFF_ITEM_AND_RETURN) {
    289       generator->MoveMouseTo(start_point.x(), start_point.y());
    290       base::MessageLoop::current()->RunUntilIdle();
    291       test->RunMessageLoopUntilAnimationsDone();
    292     } else if (command == RIP_OFF_ITEM_AND_CANCEL) {
    293       // This triggers an internal cancel. Using VKEY_ESCAPE was too unreliable.
    294       button->OnMouseCaptureLost();
    295     }
    296     if (command != RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE) {
    297       generator->ReleaseLeftButton();
    298       base::MessageLoop::current()->RunUntilIdle();
    299       test->RunMessageLoopUntilAnimationsDone();
    300     }
    301   }
    302 
    303   ash::Launcher* launcher_;
    304   ash::ShelfModel* model_;
    305   ChromeLauncherController* controller_;
    306 
    307  private:
    308 
    309   DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTest);
    310 };
    311 
    312 class LauncherAppBrowserTestNoDefaultBrowser : public LauncherAppBrowserTest {
    313  protected:
    314   LauncherAppBrowserTestNoDefaultBrowser() {}
    315   virtual ~LauncherAppBrowserTestNoDefaultBrowser() {}
    316 
    317   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    318     LauncherAppBrowserTest::SetUpCommandLine(command_line);
    319     command_line->AppendSwitch(switches::kNoStartupWindow);
    320   }
    321 
    322  private:
    323 
    324   DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTestNoDefaultBrowser);
    325 };
    326 
    327 // Since the default for minimizing on click might change, I added both classes
    328 // to either get the minimize on click or not.
    329 class LauncherAppBrowserNoMinimizeOnClick
    330     : public LauncherPlatformAppBrowserTest {
    331  protected:
    332   LauncherAppBrowserNoMinimizeOnClick() {}
    333   virtual ~LauncherAppBrowserNoMinimizeOnClick() {}
    334 
    335   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    336     LauncherPlatformAppBrowserTest::SetUpCommandLine(command_line);
    337     command_line->AppendSwitch(
    338         switches::kDisableMinimizeOnSecondLauncherItemClick);
    339   }
    340 
    341  private:
    342 
    343   DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserNoMinimizeOnClick);
    344 };
    345 
    346 typedef LauncherPlatformAppBrowserTest LauncherAppBrowserMinimizeOnClick;
    347 
    348 // Test that we can launch a platform app and get a running item.
    349 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) {
    350   int item_count = shelf_model()->item_count();
    351   const Extension* extension = LoadAndLaunchPlatformApp("launch");
    352   ShellWindow* window = CreateShellWindow(extension);
    353   ++item_count;
    354   ASSERT_EQ(item_count, shelf_model()->item_count());
    355   const ash::LauncherItem& item = GetLastLauncherItem();
    356   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
    357   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
    358   CloseShellWindow(window);
    359   --item_count;
    360   EXPECT_EQ(item_count, shelf_model()->item_count());
    361 }
    362 
    363 // Test that we can launch a platform app that already has a shortcut.
    364 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) {
    365   int item_count = shelf_model()->item_count();
    366 
    367   // First get app_id.
    368   const Extension* extension = LoadAndLaunchPlatformApp("launch");
    369   const std::string app_id = extension->id();
    370 
    371   // Then create a shortcut.
    372   ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
    373   ++item_count;
    374   ASSERT_EQ(item_count, shelf_model()->item_count());
    375   ash::LauncherItem item = *shelf_model()->ItemByID(shortcut_id);
    376   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    377   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
    378 
    379   // Open a window. Confirm the item is now running.
    380   ShellWindow* window = CreateShellWindow(extension);
    381   ash::wm::ActivateWindow(window->GetNativeWindow());
    382   ASSERT_EQ(item_count, shelf_model()->item_count());
    383   item = *shelf_model()->ItemByID(shortcut_id);
    384   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    385   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
    386 
    387   // Then close it, make sure there's still an item.
    388   CloseShellWindow(window);
    389   ASSERT_EQ(item_count, shelf_model()->item_count());
    390   item = *shelf_model()->ItemByID(shortcut_id);
    391   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    392   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
    393 }
    394 
    395 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) {
    396   // Run.
    397   int item_count = shelf_model()->item_count();
    398   const Extension* extension = LoadAndLaunchPlatformApp("launch");
    399   ShellWindow* window = CreateShellWindow(extension);
    400   ++item_count;
    401   ASSERT_EQ(item_count, shelf_model()->item_count());
    402   const ash::LauncherItem& item1 = GetLastLauncherItem();
    403   ash::LauncherID id = item1.id;
    404   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    405   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    406 
    407   // Create a shortcut. The app item should be after it.
    408   ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
    409   ++item_count;
    410   ASSERT_EQ(item_count, shelf_model()->item_count());
    411   EXPECT_LT(shelf_model()->ItemIndexByID(foo_id),
    412             shelf_model()->ItemIndexByID(id));
    413 
    414   // Pin the app. The item should remain.
    415   controller_->Pin(id);
    416   ASSERT_EQ(item_count, shelf_model()->item_count());
    417   const ash::LauncherItem& item2 = *shelf_model()->ItemByID(id);
    418   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item2.type);
    419   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
    420 
    421   // New shortcuts should come after the item.
    422   ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar");
    423   ++item_count;
    424   ASSERT_EQ(item_count, shelf_model()->item_count());
    425   EXPECT_LT(shelf_model()->ItemIndexByID(id),
    426             shelf_model()->ItemIndexByID(bar_id));
    427 
    428   // Then close it, make sure the item remains.
    429   CloseShellWindow(window);
    430   ASSERT_EQ(item_count, shelf_model()->item_count());
    431 }
    432 
    433 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) {
    434   int item_count = shelf_model()->item_count();
    435 
    436   // First get app_id.
    437   const Extension* extension = LoadAndLaunchPlatformApp("launch");
    438   const std::string app_id = extension->id();
    439 
    440   // Then create a shortcut.
    441   ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
    442   ++item_count;
    443   ASSERT_EQ(item_count, shelf_model()->item_count());
    444   ash::LauncherItem item = *shelf_model()->ItemByID(shortcut_id);
    445   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    446   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
    447 
    448   // Create a second shortcut. This will be needed to force the first one to
    449   // move once it gets unpinned.
    450   ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
    451   ++item_count;
    452   ASSERT_EQ(item_count, shelf_model()->item_count());
    453   EXPECT_LT(shelf_model()->ItemIndexByID(shortcut_id),
    454             shelf_model()->ItemIndexByID(foo_id));
    455 
    456   // Open a window. Confirm the item is now running.
    457   ShellWindow* window = CreateShellWindow(extension);
    458   ash::wm::ActivateWindow(window->GetNativeWindow());
    459   ASSERT_EQ(item_count, shelf_model()->item_count());
    460   item = *shelf_model()->ItemByID(shortcut_id);
    461   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
    462   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
    463 
    464   // Unpin the app. The item should remain.
    465   controller_->Unpin(shortcut_id);
    466   ASSERT_EQ(item_count, shelf_model()->item_count());
    467   item = *shelf_model()->ItemByID(shortcut_id);
    468   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
    469   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
    470   // The item should have moved after the other shortcuts.
    471   EXPECT_GT(shelf_model()->ItemIndexByID(shortcut_id),
    472             shelf_model()->ItemIndexByID(foo_id));
    473 
    474   // Then close it, make sure the item's gone.
    475   CloseShellWindow(window);
    476   --item_count;
    477   ASSERT_EQ(item_count, shelf_model()->item_count());
    478 }
    479 
    480 // Test that we can launch a platform app with more than one window.
    481 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) {
    482   int item_count = shelf_model()->item_count();
    483 
    484   // First run app.
    485   const Extension* extension = LoadAndLaunchPlatformApp("launch");
    486   ShellWindow* window1 = CreateShellWindow(extension);
    487   ++item_count;
    488   ASSERT_EQ(item_count, shelf_model()->item_count());
    489   const ash::LauncherItem& item1 = GetLastLauncherItem();
    490   ash::LauncherID item_id = item1.id;
    491   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    492   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    493   EXPECT_EQ(2, GetNumApplicationMenuItems(item1));  // Title + 1 window
    494 
    495   // Add second window.
    496   ShellWindow* window2 = CreateShellWindow(extension);
    497   // Confirm item stays.
    498   ASSERT_EQ(item_count, shelf_model()->item_count());
    499   const ash::LauncherItem& item2 = *shelf_model()->ItemByID(item_id);
    500   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
    501   EXPECT_EQ(3, GetNumApplicationMenuItems(item2));  // Title + 2 windows
    502 
    503   // Close second window.
    504   CloseShellWindow(window2);
    505   // Confirm item stays.
    506   ASSERT_EQ(item_count, shelf_model()->item_count());
    507   const ash::LauncherItem& item3 = *shelf_model()->ItemByID(item_id);
    508   EXPECT_EQ(ash::STATUS_ACTIVE, item3.status);
    509   EXPECT_EQ(2, GetNumApplicationMenuItems(item3));  // Title + 1 window
    510 
    511   // Close first window.
    512   CloseShellWindow(window1);
    513   // Confirm item is removed.
    514   --item_count;
    515   ASSERT_EQ(item_count, shelf_model()->item_count());
    516 }
    517 
    518 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleApps) {
    519   int item_count = shelf_model()->item_count();
    520 
    521   // First run app.
    522   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    523   ShellWindow* window1 = CreateShellWindow(extension1);
    524   ++item_count;
    525   ASSERT_EQ(item_count, shelf_model()->item_count());
    526   const ash::LauncherItem& item1 = GetLastLauncherItem();
    527   ash::LauncherID item_id1 = item1.id;
    528   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    529   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    530 
    531   // Then run second app.
    532   const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
    533   ShellWindow* window2 = CreateShellWindow(extension2);
    534   ++item_count;
    535   ASSERT_EQ(item_count, shelf_model()->item_count());
    536   const ash::LauncherItem& item2 = GetLastLauncherItem();
    537   ash::LauncherID item_id2 = item2.id;
    538   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
    539   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
    540 
    541   EXPECT_NE(item_id1, item_id2);
    542   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
    543 
    544   // Close second app.
    545   CloseShellWindow(window2);
    546   --item_count;
    547   ASSERT_EQ(item_count, shelf_model()->item_count());
    548   // First app should be active again.
    549   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status);
    550 
    551   // Close first app.
    552   CloseShellWindow(window1);
    553   --item_count;
    554   ASSERT_EQ(item_count, shelf_model()->item_count());
    555 }
    556 
    557 // Confirm that app windows can be reactivated by clicking their icons and that
    558 // the correct activation order is maintained.
    559 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowActivation) {
    560   int item_count = shelf_model()->item_count();
    561 
    562   // First run app.
    563   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    564   ShellWindow* window1 = CreateShellWindow(extension1);
    565   ++item_count;
    566   ASSERT_EQ(item_count, shelf_model()->item_count());
    567   const ash::LauncherItem& item1 = GetLastLauncherItem();
    568   ash::LauncherID item_id1 = item1.id;
    569   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    570   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    571 
    572   // Then run second app.
    573   const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
    574   ShellWindow* window2 = CreateShellWindow(extension2);
    575   ++item_count;
    576   ASSERT_EQ(item_count, shelf_model()->item_count());
    577   const ash::LauncherItem& item2 = GetLastLauncherItem();
    578   ash::LauncherID item_id2 = item2.id;
    579   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
    580   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
    581 
    582   EXPECT_NE(item_id1, item_id2);
    583   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
    584 
    585   // Activate first one.
    586   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1));
    587   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status);
    588   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id2)->status);
    589   EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    590   EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
    591 
    592   // Activate second one.
    593   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id2));
    594   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
    595   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id2)->status);
    596   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    597   EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
    598 
    599   // Add window for app1. This will activate it.
    600   ShellWindow* window1b = CreateShellWindow(extension1);
    601   ash::wm::ActivateWindow(window1b->GetNativeWindow());
    602   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    603   EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
    604   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
    605 
    606   // Activate launcher item for app1, this will activate the first app window.
    607   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1));
    608   EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    609   EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
    610   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1));
    611   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
    612 
    613   // Activate the second app again
    614   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id2));
    615   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    616   EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
    617   EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
    618 
    619   // Activate the first app again
    620   ActivateLauncherItem(shelf_model()->ItemIndexByID(item_id1));
    621   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
    622   EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
    623   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
    624 
    625   // Close second app.
    626   CloseShellWindow(window2);
    627   --item_count;
    628   EXPECT_EQ(item_count, shelf_model()->item_count());
    629   // First app should be active again.
    630   EXPECT_EQ(ash::STATUS_ACTIVE, shelf_model()->ItemByID(item_id1)->status);
    631 
    632   // Close first app.
    633   CloseShellWindow(window1b);
    634   CloseShellWindow(window1);
    635   --item_count;
    636   EXPECT_EQ(item_count, shelf_model()->item_count());
    637 }
    638 
    639 // Confirm that Click behavior for app windows is correnct.
    640 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserNoMinimizeOnClick,
    641                        AppClickBehavior) {
    642   // Launch a platform app and create a window for it.
    643   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    644   ShellWindow* window1 = CreateShellWindow(extension1);
    645   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    646   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    647   // Confirm that a controller item was created and is the correct state.
    648   const ash::LauncherItem& item1 = GetLastLauncherItem();
    649   LauncherItemController* item1_controller = GetItemController(item1.id);
    650   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    651   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    652   EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type());
    653   // Clicking the item should have no effect.
    654   TestEvent click_event(ui::ET_MOUSE_PRESSED);
    655   item1_controller->ItemSelected(click_event);
    656   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    657   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    658   // Minimize the window and confirm that the controller item is updated.
    659   window1->GetBaseWindow()->Minimize();
    660   EXPECT_FALSE(window1->GetNativeWindow()->IsVisible());
    661   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
    662   EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
    663   // Clicking the item should activate the window.
    664   item1_controller->ItemSelected(click_event);
    665   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    666   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    667   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    668   // Maximizing a window should preserve state after minimize + click.
    669   window1->GetBaseWindow()->Maximize();
    670   window1->GetBaseWindow()->Minimize();
    671   item1_controller->ItemSelected(click_event);
    672   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    673   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    674   EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
    675 }
    676 
    677 // Confirm the minimizing click behavior for apps.
    678 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserMinimizeOnClick,
    679                        PackagedAppClickBehaviorInMinimizeMode) {
    680   // Launch one platform app and create a window for it.
    681   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    682   ShellWindow* window1 = CreateShellWindow(extension1);
    683   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    684   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    685 
    686   // Confirm that a controller item was created and is the correct state.
    687   const ash::LauncherItem& item1 = GetLastLauncherItem();
    688   LauncherItemController* item1_controller = GetItemController(item1.id);
    689   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    690   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    691   EXPECT_EQ(LauncherItemController::TYPE_APP, item1_controller->type());
    692   // Since it is already active, clicking it should minimize.
    693   TestEvent click_event(ui::ET_MOUSE_PRESSED);
    694   item1_controller->ItemSelected(click_event);
    695   EXPECT_FALSE(window1->GetNativeWindow()->IsVisible());
    696   EXPECT_FALSE(window1->GetBaseWindow()->IsActive());
    697   EXPECT_TRUE(window1->GetBaseWindow()->IsMinimized());
    698   EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
    699   // Clicking the item again should activate the window again.
    700   item1_controller->ItemSelected(click_event);
    701   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    702   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    703   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    704   // Maximizing a window should preserve state after minimize + click.
    705   window1->GetBaseWindow()->Maximize();
    706   window1->GetBaseWindow()->Minimize();
    707   item1_controller->ItemSelected(click_event);
    708   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    709   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    710   EXPECT_TRUE(window1->GetBaseWindow()->IsMaximized());
    711   window1->GetBaseWindow()->Restore();
    712   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    713   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    714   EXPECT_FALSE(window1->GetBaseWindow()->IsMaximized());
    715 
    716   // Creating a second window of the same type should change the behavior so
    717   // that a click does not change the activation state.
    718   ShellWindow* window1a = CreateShellWindow(extension1);
    719   EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
    720   EXPECT_TRUE(window1a->GetBaseWindow()->IsActive());
    721   // The first click does nothing.
    722   item1_controller->ItemSelected(click_event);
    723   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    724   EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
    725   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    726   EXPECT_FALSE(window1a->GetBaseWindow()->IsActive());
    727   // The second neither.
    728   item1_controller->ItemSelected(click_event);
    729   EXPECT_TRUE(window1->GetNativeWindow()->IsVisible());
    730   EXPECT_TRUE(window1a->GetNativeWindow()->IsVisible());
    731   EXPECT_TRUE(window1->GetBaseWindow()->IsActive());
    732   EXPECT_FALSE(window1a->GetBaseWindow()->IsActive());
    733 }
    734 
    735 // Confirm that click behavior for app panels is correct.
    736 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, AppPanelClickBehavior) {
    737   // Enable experimental APIs to allow panel creation.
    738   CommandLine::ForCurrentProcess()->AppendSwitch(
    739       extensions::switches::kEnableExperimentalExtensionApis);
    740   // Launch a platform app and create a panel window for it.
    741   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    742   ShellWindow::CreateParams params;
    743   params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
    744   params.focused = false;
    745   ShellWindow* panel = CreateShellWindowFromParams(extension1, params);
    746   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
    747   // Panels should not be active by default.
    748   EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
    749   // Confirm that a controller item was created and is the correct state.
    750   const ash::LauncherItem& item1 = GetLastLauncherPanelItem();
    751   LauncherItemController* item1_controller = GetItemController(item1.id);
    752   EXPECT_EQ(ash::TYPE_APP_PANEL, item1.type);
    753   EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
    754   EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item1_controller->type());
    755   // Click the item and confirm that the panel is activated.
    756   TestEvent click_event(ui::ET_MOUSE_PRESSED);
    757   item1_controller->ItemSelected(click_event);
    758   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
    759   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    760   // Click the item again and confirm that the panel is minimized.
    761   item1_controller->ItemSelected(click_event);
    762   EXPECT_TRUE(panel->GetBaseWindow()->IsMinimized());
    763   EXPECT_EQ(ash::STATUS_RUNNING, item1.status);
    764   // Click the item again and confirm that the panel is activated.
    765   item1_controller->ItemSelected(click_event);
    766   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
    767   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
    768   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    769 }
    770 
    771 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) {
    772   int item_count = shelf_model()->item_count();
    773 
    774   // First run app.
    775   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
    776   CreateShellWindow(extension1);
    777   ++item_count;
    778   ASSERT_EQ(item_count, shelf_model()->item_count());
    779   const ash::LauncherItem& item1 = GetLastLauncherItem();
    780   ash::LauncherID item_id1 = item1.id;
    781   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
    782   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
    783 
    784   ash::wm::ActivateWindow(browser()->window()->GetNativeWindow());
    785   EXPECT_EQ(ash::STATUS_RUNNING, shelf_model()->ItemByID(item_id1)->status);
    786 }
    787 
    788 // Test that opening an app sets the correct icon
    789 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, SetIcon) {
    790   TestShellWindowRegistryObserver test_observer(browser()->profile());
    791 
    792   // Enable experimental APIs to allow panel creation.
    793   CommandLine::ForCurrentProcess()->AppendSwitch(
    794       extensions::switches::kEnableExperimentalExtensionApis);
    795 
    796   int base_launcher_item_count = shelf_model()->item_count();
    797   ExtensionTestMessageListener launched_listener("Launched", false);
    798   ExtensionTestMessageListener completed_listener("Completed", false);
    799   LoadAndLaunchPlatformApp("app_icon");
    800   ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
    801   ASSERT_TRUE(completed_listener.WaitUntilSatisfied());
    802 
    803   // Now wait until the WebContent has decoded the icons and chrome has
    804   // processed it. This needs to be in a loop since the renderer runs in a
    805   // different process.
    806   while (test_observer.icon_updates() < 3) {
    807     base::RunLoop run_loop;
    808     run_loop.RunUntilIdle();
    809   }
    810 
    811   // This test creates one shell window and one panel window.
    812   int launcher_item_count = shelf_model()->item_count();
    813   ASSERT_EQ(base_launcher_item_count + 2, launcher_item_count);
    814   // The Panel will be the last item, the app second-to-last.
    815   const ash::LauncherItem& app_item =
    816       shelf_model()->items()[launcher_item_count - 2];
    817   const ash::LauncherItem& panel_item =
    818       shelf_model()->items()[launcher_item_count - 1];
    819   const LauncherItemController* app_item_controller =
    820       GetItemController(app_item.id);
    821   const LauncherItemController* panel_item_controller =
    822       GetItemController(panel_item.id);
    823   // Icons for Apps are set by the ShellWindowLauncherController, so
    824   // image_set_by_controller() should be set.
    825   EXPECT_TRUE(app_item_controller->image_set_by_controller());
    826   EXPECT_TRUE(panel_item_controller->image_set_by_controller());
    827   // Ensure icon heights are correct (see test.js in app_icon/ test directory)
    828   EXPECT_EQ(48, app_item.image.height());
    829   EXPECT_EQ(64, panel_item.image.height());
    830 }
    831 
    832 // Test that we can launch an app with a shortcut.
    833 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchPinned) {
    834   TabStripModel* tab_strip = browser()->tab_strip_model();
    835   int tab_count = tab_strip->count();
    836   ash::LauncherID shortcut_id = CreateShortcut("app1");
    837   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
    838   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
    839   EXPECT_EQ(++tab_count, tab_strip->count());
    840   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
    841   WebContents* tab = tab_strip->GetActiveWebContents();
    842   content::WebContentsDestroyedWatcher destroyed_watcher(tab);
    843   browser()->tab_strip_model()->CloseSelectedTabs();
    844   destroyed_watcher.Wait();
    845   EXPECT_EQ(--tab_count, tab_strip->count());
    846   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
    847 }
    848 
    849 // Launch the app first and then create the shortcut.
    850 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchUnpinned) {
    851   TabStripModel* tab_strip = browser()->tab_strip_model();
    852   int tab_count = tab_strip->count();
    853   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB,
    854                          NEW_FOREGROUND_TAB);
    855   EXPECT_EQ(++tab_count, tab_strip->count());
    856   ash::LauncherID shortcut_id = CreateShortcut("app1");
    857   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
    858   WebContents* tab = tab_strip->GetActiveWebContents();
    859   content::WebContentsDestroyedWatcher destroyed_watcher(tab);
    860   browser()->tab_strip_model()->CloseSelectedTabs();
    861   destroyed_watcher.Wait();
    862   EXPECT_EQ(--tab_count, tab_strip->count());
    863   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
    864 }
    865 
    866 // Launches an app in the background and then tries to open it. This is test for
    867 // a crash we had.
    868 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchInBackground) {
    869   TabStripModel* tab_strip = browser()->tab_strip_model();
    870   int tab_count = tab_strip->count();
    871   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB,
    872                          NEW_BACKGROUND_TAB);
    873   EXPECT_EQ(++tab_count, tab_strip->count());
    874   ChromeLauncherController::instance()->LaunchApp(last_loaded_extension_id(),
    875                                                   ash::LAUNCH_FROM_UNKNOWN,
    876                                                   0);
    877 }
    878 
    879 // Confirm that clicking a icon for an app running in one of 2 maxmized windows
    880 // activates the right window.
    881 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchMaximized) {
    882   aura::Window* window1 = browser()->window()->GetNativeWindow();
    883   ash::wm::WindowState* window1_state = ash::wm::GetWindowState(window1);
    884   window1_state->Maximize();
    885   content::WindowedNotificationObserver open_observer(
    886       chrome::NOTIFICATION_BROWSER_WINDOW_READY,
    887       content::NotificationService::AllSources());
    888   chrome::NewEmptyWindow(browser()->profile(), chrome::HOST_DESKTOP_TYPE_ASH);
    889   open_observer.Wait();
    890   Browser* browser2 = content::Source<Browser>(open_observer.source()).ptr();
    891   aura::Window* window2 = browser2->window()->GetNativeWindow();
    892   TabStripModel* tab_strip = browser2->tab_strip_model();
    893   int tab_count = tab_strip->count();
    894   ash::wm::GetWindowState(window2)->Maximize();
    895 
    896   ash::LauncherID shortcut_id = CreateShortcut("app1");
    897   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
    898   EXPECT_EQ(++tab_count, tab_strip->count());
    899   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
    900 
    901   window1->Show();
    902   window1_state->Activate();
    903   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
    904 
    905   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
    906   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
    907 }
    908 
    909 // Activating the same app multiple times should launch only a single copy.
    910 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateApp) {
    911   TabStripModel* tab_strip = browser()->tab_strip_model();
    912   int tab_count = tab_strip->count();
    913   const Extension* extension =
    914       LoadExtension(test_data_dir_.AppendASCII("app1"));
    915 
    916   ChromeLauncherController::instance()->ActivateApp(extension->id(),
    917                                                     ash::LAUNCH_FROM_UNKNOWN,
    918                                                     0);
    919   EXPECT_EQ(++tab_count, tab_strip->count());
    920   ChromeLauncherController::instance()->ActivateApp(extension->id(),
    921                                                     ash::LAUNCH_FROM_UNKNOWN,
    922                                                     0);
    923   EXPECT_EQ(tab_count, tab_strip->count());
    924 }
    925 
    926 // Launching the same app multiple times should launch a copy for each call.
    927 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, LaunchApp) {
    928   TabStripModel* tab_strip = browser()->tab_strip_model();
    929   int tab_count = tab_strip->count();
    930   const Extension* extension =
    931       LoadExtension(test_data_dir_.AppendASCII("app1"));
    932 
    933   ChromeLauncherController::instance()->LaunchApp(extension->id(),
    934                                                   ash::LAUNCH_FROM_UNKNOWN,
    935                                                   0);
    936   EXPECT_EQ(++tab_count, tab_strip->count());
    937   ChromeLauncherController::instance()->LaunchApp(extension->id(),
    938                                                   ash::LAUNCH_FROM_UNKNOWN,
    939                                                   0);
    940   EXPECT_EQ(++tab_count, tab_strip->count());
    941 }
    942 
    943 // Launch 2 apps and toggle which is active.
    944 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleApps) {
    945   int item_count = model_->item_count();
    946   TabStripModel* tab_strip = browser()->tab_strip_model();
    947   int tab_count = tab_strip->count();
    948   ash::LauncherID shortcut1 = CreateShortcut("app1");
    949   EXPECT_EQ(++item_count, model_->item_count());
    950   ash::LauncherID shortcut2 = CreateShortcut("app2");
    951   EXPECT_EQ(++item_count, model_->item_count());
    952 
    953   // Launch first app.
    954   ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
    955   EXPECT_EQ(++tab_count, tab_strip->count());
    956   WebContents* tab1 = tab_strip->GetActiveWebContents();
    957   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
    958 
    959   // Launch second app.
    960   ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
    961   EXPECT_EQ(++tab_count, tab_strip->count());
    962   WebContents* tab2 = tab_strip->GetActiveWebContents();
    963   ASSERT_NE(tab1, tab2);
    964   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
    965   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
    966 
    967   // Reactivate first app.
    968   ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
    969   EXPECT_EQ(tab_count, tab_strip->count());
    970   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
    971   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
    972   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
    973 
    974   // Open second tab for second app. This should activate it.
    975   ui_test_utils::NavigateToURLWithDisposition(
    976       browser(),
    977       GURL("http://www.example.com/path3/foo.html"),
    978       NEW_FOREGROUND_TAB,
    979       0);
    980   EXPECT_EQ(++tab_count, tab_strip->count());
    981   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
    982   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
    983 
    984   // Reactivate first app.
    985   ActivateLauncherItem(model_->ItemIndexByID(shortcut1));
    986   EXPECT_EQ(tab_count, tab_strip->count());
    987   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab1);
    988   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut1)).status);
    989   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut2)).status);
    990 
    991   // And second again. This time the second tab should become active.
    992   ActivateLauncherItem(model_->ItemIndexByID(shortcut2));
    993   EXPECT_EQ(tab_count, tab_strip->count());
    994   EXPECT_EQ(tab_strip->GetActiveWebContents(), tab2);
    995   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut1)).status);
    996   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut2)).status);
    997 }
    998 
    999 // Confirm that a page can be navigated from and to while maintaining the
   1000 // correct running state.
   1001 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, Navigation) {
   1002   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1003   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
   1004   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1005   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
   1006 
   1007   // Navigate away.
   1008   ui_test_utils::NavigateToURL(
   1009       browser(), GURL("http://www.example.com/path0/bar.html"));
   1010   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
   1011 
   1012   // Navigate back.
   1013   ui_test_utils::NavigateToURL(
   1014       browser(), GURL("http://www.example.com/path1/foo.html"));
   1015   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
   1016 }
   1017 
   1018 // Confirm that a tab can be moved between browsers while maintaining the
   1019 // correct running state.
   1020 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, TabDragAndDrop) {
   1021   TabStripModel* tab_strip_model1 = browser()->tab_strip_model();
   1022   EXPECT_EQ(1, tab_strip_model1->count());
   1023   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
   1024   EXPECT_TRUE(browser_index >= 0);
   1025   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   1026 
   1027   // Create a shortcut for app1.
   1028   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1029   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1030   EXPECT_EQ(ash::STATUS_CLOSED, (*model_->ItemByID(shortcut_id)).status);
   1031 
   1032   // Activate app1 and check its item status.
   1033   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1034   EXPECT_EQ(2, tab_strip_model1->count());
   1035   EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
   1036   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
   1037 
   1038   // Create a new browser with blank tab.
   1039   Browser* browser2 = CreateBrowser(profile());
   1040   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   1041   TabStripModel* tab_strip_model2 = browser2->tab_strip_model();
   1042   EXPECT_EQ(1, tab_strip_model2->count());
   1043   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1044   EXPECT_EQ(ash::STATUS_RUNNING, (*model_->ItemByID(shortcut_id)).status);
   1045 
   1046   // Detach a tab at index 1 (app1) from |tab_strip_model1| and insert it as an
   1047   // active tab at index 1 to |tab_strip_model2|.
   1048   content::WebContents* detached_tab = tab_strip_model1->DetachWebContentsAt(1);
   1049   tab_strip_model2->InsertWebContentsAt(1,
   1050                                         detached_tab,
   1051                                         TabStripModel::ADD_ACTIVE);
   1052   EXPECT_EQ(1, tab_strip_model1->count());
   1053   EXPECT_EQ(2, tab_strip_model2->count());
   1054   EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
   1055   EXPECT_EQ(ash::STATUS_ACTIVE, (*model_->ItemByID(shortcut_id)).status);
   1056 
   1057   tab_strip_model1->CloseAllTabs();
   1058   tab_strip_model2->CloseAllTabs();
   1059 }
   1060 
   1061 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MultipleOwnedTabs) {
   1062   TabStripModel* tab_strip = browser()->tab_strip_model();
   1063   int tab_count = tab_strip->count();
   1064   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1065   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1066   EXPECT_EQ(++tab_count, tab_strip->count());
   1067   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1068   WebContents* first_tab = tab_strip->GetActiveWebContents();
   1069 
   1070   // Create new tab owned by app.
   1071   ui_test_utils::NavigateToURLWithDisposition(
   1072       browser(),
   1073       GURL("http://www.example.com/path2/bar.html"),
   1074       NEW_FOREGROUND_TAB,
   1075       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1076   EXPECT_EQ(++tab_count, tab_strip->count());
   1077   // Confirm app is still active.
   1078   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1079 
   1080   // Create new tab not owned by app.
   1081   ui_test_utils::NavigateToURLWithDisposition(
   1082       browser(),
   1083       GURL("http://www.example.com/path3/foo.html"),
   1084       NEW_FOREGROUND_TAB,
   1085       0);
   1086   EXPECT_EQ(++tab_count, tab_strip->count());
   1087   // No longer active.
   1088   EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
   1089 
   1090   // Activating app makes first tab active again.
   1091   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1092   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1093   EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
   1094 }
   1095 
   1096 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilter) {
   1097   TabStripModel* tab_strip = browser()->tab_strip_model();
   1098   int tab_count = tab_strip->count();
   1099   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1100   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1101   EXPECT_EQ(++tab_count, tab_strip->count());
   1102   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1103   WebContents* first_tab = tab_strip->GetActiveWebContents();
   1104 
   1105   controller_->SetRefocusURLPatternForTest(
   1106       shortcut_id, GURL("http://www.example.com/path1/*"));
   1107   // Create new tab owned by app.
   1108   ui_test_utils::NavigateToURLWithDisposition(
   1109       browser(),
   1110       GURL("http://www.example.com/path2/bar.html"),
   1111       NEW_FOREGROUND_TAB,
   1112       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1113   EXPECT_EQ(++tab_count, tab_strip->count());
   1114   // Confirm app is still active.
   1115   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1116 
   1117   // Create new tab not owned by app.
   1118   ui_test_utils::NavigateToURLWithDisposition(
   1119       browser(),
   1120       GURL("http://www.example.com/path3/foo.html"),
   1121       NEW_FOREGROUND_TAB,
   1122       0);
   1123   EXPECT_EQ(++tab_count, tab_strip->count());
   1124   // No longer active.
   1125   EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
   1126 
   1127   // Activating app makes first tab active again, because second tab isn't
   1128   // in its refocus url path.
   1129   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1130   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1131   EXPECT_EQ(tab_strip->GetActiveWebContents(), first_tab);
   1132 }
   1133 
   1134 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, RefocusFilterLaunch) {
   1135   TabStripModel* tab_strip = browser()->tab_strip_model();
   1136   int tab_count = tab_strip->count();
   1137   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1138   controller_->SetRefocusURLPatternForTest(
   1139       shortcut_id, GURL("http://www.example.com/path1/*"));
   1140 
   1141   // Create new tab.
   1142   ui_test_utils::NavigateToURLWithDisposition(
   1143       browser(),
   1144       GURL("http://www.example2.com/path2/bar.html"),
   1145       NEW_FOREGROUND_TAB,
   1146       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1147   EXPECT_EQ(++tab_count, tab_strip->count());
   1148   WebContents* first_tab = tab_strip->GetActiveWebContents();
   1149   // Confirm app is not active.
   1150   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1151 
   1152   // Activating app should launch new tab, because second tab isn't
   1153   // in its refocus url path.
   1154   ActivateLauncherItem(model_->ItemIndexByID(shortcut_id));
   1155   EXPECT_EQ(++tab_count, tab_strip->count());
   1156   WebContents* second_tab = tab_strip->GetActiveWebContents();
   1157   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1158   EXPECT_NE(first_tab, second_tab);
   1159   EXPECT_EQ(tab_strip->GetActiveWebContents(), second_tab);
   1160 }
   1161 
   1162 // Check the launcher activation state for applications and browser.
   1163 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivationStateCheck) {
   1164   TabStripModel* tab_strip = browser()->tab_strip_model();
   1165   // Get the browser item index
   1166   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
   1167   EXPECT_TRUE(browser_index >= 0);
   1168 
   1169   // Even though we are just comming up, the browser should be active.
   1170   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1171 
   1172   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1173   controller_->SetRefocusURLPatternForTest(
   1174       shortcut_id, GURL("http://www.example.com/path1/*"));
   1175 
   1176   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1177   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1178 
   1179   // Create new tab which would be the running app.
   1180   ui_test_utils::NavigateToURLWithDisposition(
   1181       browser(),
   1182       GURL("http://www.example.com/path1/bar.html"),
   1183       NEW_FOREGROUND_TAB,
   1184       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1185 
   1186   // There should never be two items active at the same time.
   1187   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1188   EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
   1189 
   1190   tab_strip->ActivateTabAt(0, false);
   1191   EXPECT_EQ(ash::STATUS_RUNNING, model_->ItemByID(shortcut_id)->status);
   1192   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1193 
   1194   tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
   1195   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1196   EXPECT_EQ(ash::STATUS_ACTIVE, model_->items()[browser_index].status);
   1197 
   1198   ash::wm::DeactivateWindow(browser()->window()->GetNativeWindow());
   1199   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1200   EXPECT_EQ(ash::STATUS_RUNNING, model_->items()[browser_index].status);
   1201 }
   1202 
   1203 // Check that the launcher activation state for a V1 application stays closed
   1204 // even after an asynchronous browser event comes in after the tab got
   1205 // destroyed.
   1206 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AsyncActivationStateCheck) {
   1207   TabStripModel* tab_strip = browser()->tab_strip_model();
   1208 
   1209   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1210   controller_->SetRefocusURLPatternForTest(
   1211       shortcut_id, GURL("http://www.example.com/path1/*"));
   1212 
   1213   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1214 
   1215   // Create new tab which would be the running app.
   1216   ui_test_utils::NavigateToURLWithDisposition(
   1217       browser(),
   1218       GURL("http://www.example.com/path1/bar.html"),
   1219       NEW_FOREGROUND_TAB,
   1220       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1221 
   1222   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(shortcut_id)->status);
   1223   // To address the issue of crbug.com/174050, the tab we are about to close
   1224   // has to be active.
   1225   tab_strip->ActivateTabAt(1, false);
   1226   EXPECT_EQ(1, tab_strip->active_index());
   1227 
   1228   // Close the web contents.
   1229   tab_strip->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE);
   1230   // The status should now be set to closed.
   1231   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(shortcut_id)->status);
   1232 }
   1233 
   1234 // Checks that a windowed application does not add an item to the browser list.
   1235 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
   1236     WindowedAppDoesNotAddToBrowser) {
   1237   // Get the number of items in the browser menu.
   1238   size_t items = NumberOfDetectedLauncherBrowsers(false);
   1239   size_t running_browser = chrome::GetTotalBrowserCount();
   1240   EXPECT_EQ(0u, items);
   1241   EXPECT_EQ(0u, running_browser);
   1242 
   1243   LoadAndLaunchExtension(
   1244       "app1", extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW);
   1245 
   1246   // No new browser should get detected, even though one more is running.
   1247   EXPECT_EQ(0u, NumberOfDetectedLauncherBrowsers(false));
   1248   EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount());
   1249 
   1250   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW);
   1251 
   1252   // A new browser should get detected and one more should be running.
   1253   EXPECT_EQ(NumberOfDetectedLauncherBrowsers(false), 1u);
   1254   EXPECT_EQ(++running_browser, chrome::GetTotalBrowserCount());
   1255 }
   1256 
   1257 // Checks the functionality to enumerate all browsers vs. all tabs.
   1258 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
   1259     EnumerateALlBrowsersAndTabs) {
   1260   // Create at least one browser.
   1261   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW);
   1262   size_t browsers = NumberOfDetectedLauncherBrowsers(false);
   1263   size_t tabs = NumberOfDetectedLauncherBrowsers(true);
   1264 
   1265   // Create a second browser.
   1266   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW);
   1267 
   1268   EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false));
   1269   EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true));
   1270 
   1271   // Create only a tab.
   1272   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB,
   1273                          NEW_FOREGROUND_TAB);
   1274 
   1275   EXPECT_EQ(browsers, NumberOfDetectedLauncherBrowsers(false));
   1276   EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true));
   1277 }
   1278 
   1279 // Check that the keyboard activation of a launcher item tabs properly through
   1280 // the items at hand.
   1281 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, AltNumberTabsTabbing) {
   1282   TabStripModel* tab_strip = browser()->tab_strip_model();
   1283 
   1284   ash::LauncherID shortcut_id = CreateShortcut("app");
   1285   controller_->SetRefocusURLPatternForTest(
   1286       shortcut_id, GURL("http://www.example.com/path/*"));
   1287   std::string url = "http://www.example.com/path/bla";
   1288 
   1289   int shortcut_index = model_->ItemIndexByID(shortcut_id);
   1290 
   1291   // Create an application handled browser tab.
   1292   ui_test_utils::NavigateToURLWithDisposition(
   1293       browser(),
   1294       GURL(url),
   1295       NEW_FOREGROUND_TAB,
   1296       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1297 
   1298   content::WebContents* content1 = tab_strip->GetActiveWebContents();
   1299 
   1300   // Create some other browser tab.
   1301   ui_test_utils::NavigateToURLWithDisposition(
   1302       browser(),
   1303       GURL("http://www.test.com"),
   1304       NEW_FOREGROUND_TAB,
   1305       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1306   content::WebContents* content1a = tab_strip->GetActiveWebContents();
   1307 
   1308   // Make sure that the active tab is now our handled tab.
   1309   EXPECT_NE(content1a, content1);
   1310 
   1311   // The active tab should still be the unnamed tab. Then we switch and reach
   1312   // the first app and stay there.
   1313   EXPECT_EQ(content1a, tab_strip->GetActiveWebContents());
   1314   ActivateLauncherItem(shortcut_index);
   1315   EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
   1316   ActivateLauncherItem(shortcut_index);
   1317   EXPECT_EQ(content1, tab_strip->GetActiveWebContents());
   1318 
   1319   ui_test_utils::NavigateToURLWithDisposition(
   1320       browser(),
   1321       GURL(url),
   1322       NEW_FOREGROUND_TAB,
   1323       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1324   content::WebContents* content2 = tab_strip->GetActiveWebContents();
   1325 
   1326   EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
   1327   ActivateLauncherItem(shortcut_index);
   1328   EXPECT_EQ(content1, browser()->tab_strip_model()->GetActiveWebContents());
   1329   ActivateLauncherItem(shortcut_index);
   1330   EXPECT_EQ(content2, browser()->tab_strip_model()->GetActiveWebContents());
   1331 }
   1332 
   1333 // Check that the keyboard activation of a launcher item tabs properly through
   1334 // the items at hand.
   1335 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest,
   1336                        AltNumberAppsTabbing) {
   1337   // First run app.
   1338   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
   1339   ui::BaseWindow* window1 = CreateShellWindow(extension1)->GetBaseWindow();
   1340   const ash::LauncherItem& item1 = GetLastLauncherItem();
   1341   ash::LauncherID app_id = item1.id;
   1342   int app_index = shelf_model()->ItemIndexByID(app_id);
   1343 
   1344   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
   1345   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
   1346 
   1347   const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
   1348   ui::BaseWindow* window2 = CreateShellWindow(extension2)->GetBaseWindow();
   1349 
   1350   // By now the browser should be active. Issue Alt keystrokes several times to
   1351   // see that we stay on that application.
   1352   EXPECT_TRUE(window2->IsActive());
   1353   ActivateLauncherItem(app_index);
   1354   EXPECT_TRUE(window1->IsActive());
   1355   ActivateLauncherItem(app_index);
   1356   EXPECT_TRUE(window1->IsActive());
   1357 
   1358   ui::BaseWindow* window1a = CreateShellWindow(extension1)->GetBaseWindow();
   1359 
   1360   EXPECT_TRUE(window1a->IsActive());
   1361   EXPECT_FALSE(window1->IsActive());
   1362   ActivateLauncherItem(app_index);
   1363   EXPECT_TRUE(window1->IsActive());
   1364   ActivateLauncherItem(app_index);
   1365   EXPECT_TRUE(window1a->IsActive());
   1366 }
   1367 
   1368 // Test that we can launch a platform app panel and get a running item.
   1369 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPanelWindow) {
   1370   int item_count = shelf_model()->item_count();
   1371   const Extension* extension = LoadAndLaunchPlatformApp("launch");
   1372   ShellWindow::CreateParams params;
   1373   params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
   1374   params.focused = false;
   1375   ShellWindow* window = CreateShellWindowFromParams(extension, params);
   1376   ++item_count;
   1377   ASSERT_EQ(item_count, shelf_model()->item_count());
   1378   const ash::LauncherItem& item = GetLastLauncherPanelItem();
   1379   EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
   1380   // Opening a panel does not activate it.
   1381   EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   1382   CloseShellWindow(window);
   1383   --item_count;
   1384   EXPECT_EQ(item_count, shelf_model()->item_count());
   1385 }
   1386 
   1387 // Test attention states of windows.
   1388 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, WindowAttentionStatus) {
   1389   const Extension* extension = LoadAndLaunchPlatformApp("launch");
   1390   ShellWindow::CreateParams params;
   1391   params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
   1392   params.focused = false;
   1393   ShellWindow* panel = CreateShellWindowFromParams(extension, params);
   1394   EXPECT_TRUE(panel->GetNativeWindow()->IsVisible());
   1395   // Panels should not be active by default.
   1396   EXPECT_FALSE(panel->GetBaseWindow()->IsActive());
   1397   // Confirm that a controller item was created and is the correct state.
   1398   const ash::LauncherItem& item = GetLastLauncherPanelItem();
   1399   LauncherItemController* item_controller = GetItemController(item.id);
   1400   EXPECT_EQ(ash::TYPE_APP_PANEL, item.type);
   1401   EXPECT_EQ(ash::STATUS_RUNNING, item.status);
   1402   EXPECT_EQ(LauncherItemController::TYPE_APP_PANEL, item_controller->type());
   1403 
   1404   // App windows should go to attention state.
   1405   panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
   1406   EXPECT_EQ(ash::STATUS_ATTENTION, item.status);
   1407 
   1408   // Click the item and confirm that the panel is activated.
   1409   TestEvent click_event(ui::ET_MOUSE_PRESSED);
   1410   item_controller->ItemSelected(click_event);
   1411   EXPECT_TRUE(panel->GetBaseWindow()->IsActive());
   1412   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   1413 
   1414   // Active windows don't show attention.
   1415   panel->GetNativeWindow()->SetProperty(aura::client::kDrawAttentionKey, true);
   1416   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   1417 }
   1418 
   1419 // Checks that the browser Alt "tabbing" is properly done.
   1420 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
   1421     AltNumberBrowserTabbing) {
   1422   // Get the number of items in the browser menu.
   1423   EXPECT_EQ(0u, chrome::GetTotalBrowserCount());
   1424   // The first activation should create a browser at index 1 (App List @ 0).
   1425   launcher_->ActivateLauncherItem(1);
   1426   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   1427   // A second activation should not create a new instance.
   1428   launcher_->ActivateLauncherItem(1);
   1429   Browser* browser1 = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
   1430   EXPECT_TRUE(browser1);
   1431   aura::Window* window1 = browser1->window()->GetNativeWindow();
   1432   Browser* browser2 = CreateBrowser(profile());
   1433   aura::Window* window2 = browser2->window()->GetNativeWindow();
   1434 
   1435   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   1436   EXPECT_NE(window1, window2);
   1437   EXPECT_EQ(window2, ash::wm::GetActiveWindow());
   1438 
   1439   // Activate multiple times the switcher to see that the windows get activated.
   1440   launcher_->ActivateLauncherItem(1);
   1441   EXPECT_EQ(window1, ash::wm::GetActiveWindow());
   1442   launcher_->ActivateLauncherItem(1);
   1443   EXPECT_EQ(window2, ash::wm::GetActiveWindow());
   1444 
   1445   // Create a third browser - make sure that we do not toggle simply between
   1446   // two windows.
   1447   Browser* browser3 = CreateBrowser(profile());
   1448   aura::Window* window3 = browser3->window()->GetNativeWindow();
   1449 
   1450   EXPECT_EQ(3u, chrome::GetTotalBrowserCount());
   1451   EXPECT_NE(window1, window3);
   1452   EXPECT_NE(window2, window3);
   1453   EXPECT_EQ(window3, ash::wm::GetActiveWindow());
   1454 
   1455   launcher_->ActivateLauncherItem(1);
   1456   EXPECT_EQ(window1, ash::wm::GetActiveWindow());
   1457   launcher_->ActivateLauncherItem(1);
   1458   EXPECT_EQ(window2, ash::wm::GetActiveWindow());
   1459   launcher_->ActivateLauncherItem(1);
   1460   EXPECT_EQ(window3, ash::wm::GetActiveWindow());
   1461   launcher_->ActivateLauncherItem(1);
   1462   EXPECT_EQ(window1, ash::wm::GetActiveWindow());
   1463 
   1464   // Create anther app and make sure that none of our browsers is active.
   1465   LoadAndLaunchExtension("app1", extensions::LAUNCH_CONTAINER_TAB, NEW_WINDOW);
   1466   EXPECT_NE(window1, ash::wm::GetActiveWindow());
   1467   EXPECT_NE(window2, ash::wm::GetActiveWindow());
   1468 
   1469   // After activation our browser should be active again.
   1470   launcher_->ActivateLauncherItem(1);
   1471   EXPECT_EQ(window1, ash::wm::GetActiveWindow());
   1472 }
   1473 
   1474 // Checks that after a session restore, we do not start applications on an
   1475 // activation.
   1476 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ActivateAfterSessionRestore) {
   1477   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   1478 
   1479   // Create a known application.
   1480   ash::LauncherID shortcut_id = CreateShortcut("app1");
   1481 
   1482   // Create a new browser - without activating it - and load an "app" into it.
   1483   Browser::CreateParams params =
   1484       Browser::CreateParams(profile(), chrome::GetActiveDesktop());
   1485   params.initial_show_state = ui::SHOW_STATE_INACTIVE;
   1486   Browser* browser2 = new Browser(params);
   1487   controller_->SetRefocusURLPatternForTest(
   1488       shortcut_id, GURL("http://www.example.com/path/*"));
   1489   std::string url = "http://www.example.com/path/bla";
   1490   ui_test_utils::NavigateToURLWithDisposition(
   1491       browser2,
   1492       GURL(url),
   1493       NEW_FOREGROUND_TAB,
   1494       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   1495 
   1496   // Remember the number of tabs for each browser.
   1497   TabStripModel* tab_strip = browser()->tab_strip_model();
   1498   int tab_count1 = tab_strip->count();
   1499   TabStripModel* tab_strip2 = browser2->tab_strip_model();
   1500   int tab_count2 = tab_strip2->count();
   1501 
   1502   // Check that we have two browsers and the inactive browser remained inactive.
   1503   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   1504   EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()),
   1505             browser());
   1506   // Check that the LRU browser list does only contain the original browser.
   1507   BrowserList* ash_browser_list =
   1508       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
   1509   BrowserList::const_reverse_iterator it =
   1510       ash_browser_list->begin_last_active();
   1511   EXPECT_EQ(*it, browser());
   1512   ++it;
   1513   EXPECT_EQ(it, ash_browser_list->end_last_active());
   1514 
   1515   // Now request to either activate an existing app or create a new one.
   1516   LauncherItemController* item_controller =
   1517       controller_->GetLauncherItemController(shortcut_id);
   1518   item_controller->ItemSelected(ui::KeyEvent(ui::ET_KEY_RELEASED,
   1519                                         ui::VKEY_RETURN,
   1520                                         0,
   1521                                         false));
   1522 
   1523   // Check that we have set focus on the existing application and nothing new
   1524   // was created.
   1525   EXPECT_EQ(2u, chrome::GetTotalBrowserCount());
   1526   EXPECT_EQ(tab_count1, tab_strip->count());
   1527   EXPECT_EQ(tab_count2, tab_strip2->count());
   1528   EXPECT_EQ(chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()),
   1529             browser2);
   1530 }
   1531 
   1532 // Do various drag and drop interaction tests between the application list and
   1533 // the launcher.
   1534 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragAndDrop) {
   1535   // Get a number of interfaces we need.
   1536   aura::test::EventGenerator generator(
   1537       ash::Shell::GetPrimaryRootWindow(), gfx::Point());
   1538   ash::test::ShelfViewTestAPI test(
   1539       ash::test::LauncherTestAPI(launcher_).shelf_view());
   1540   AppListService* service = AppListService::Get(chrome::GetActiveDesktop());
   1541 
   1542   // There should be two items in our launcher by this time.
   1543   EXPECT_EQ(2, model_->item_count());
   1544   EXPECT_FALSE(service->IsAppListVisible());
   1545 
   1546   // Open the app list menu and check that the drag and drop host was set.
   1547   gfx::Rect app_list_bounds =
   1548       test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen();
   1549   generator.MoveMouseTo(app_list_bounds.CenterPoint().x(),
   1550                         app_list_bounds.CenterPoint().y());
   1551   base::MessageLoop::current()->RunUntilIdle();
   1552   generator.ClickLeftButton();
   1553 
   1554   EXPECT_TRUE(service->IsAppListVisible());
   1555   app_list::AppsGridView* grid_view =
   1556       ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).
   1557           GetRootGridView();
   1558   ASSERT_TRUE(grid_view);
   1559   ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test());
   1560 
   1561   // There should be 2 items in our application list.
   1562   const views::ViewModel* vm_grid = grid_view->view_model_for_test();
   1563   EXPECT_EQ(2, vm_grid->view_size());
   1564 
   1565   // Test #1: Drag an app list which does not exist yet item into the
   1566   // launcher. Keeping it dragged, see that a new item gets created. Continuing
   1567   // to drag it out should remove it again.
   1568 
   1569   // Get over item #1 of the application list and press the mouse button.
   1570   views::View* item1 = vm_grid->view_at(1);
   1571   gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen();
   1572   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1573                         bounds_grid_1.CenterPoint().y());
   1574   base::MessageLoop::current()->RunUntilIdle();
   1575   generator.PressLeftButton();
   1576 
   1577   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1578 
   1579   // Drag the item into the launcher and check that a new item gets created.
   1580   const views::ViewModel* vm_launcher =
   1581       test.shelf_view()->view_model_for_test();
   1582   views::View* launcher1 = vm_launcher->view_at(1);
   1583   gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen();
   1584   generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
   1585                         bounds_launcher_1.CenterPoint().y());
   1586   base::MessageLoop::current()->RunUntilIdle();
   1587 
   1588   // Check that a new item got created.
   1589   EXPECT_EQ(3, model_->item_count());
   1590   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1591 
   1592   // Move it where the item originally was and check that it disappears again.
   1593   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1594                         bounds_grid_1.CenterPoint().y());
   1595   base::MessageLoop::current()->RunUntilIdle();
   1596   EXPECT_EQ(2, model_->item_count());
   1597   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1598 
   1599   // Dropping it should keep the launcher as it originally was.
   1600   generator.ReleaseLeftButton();
   1601   base::MessageLoop::current()->RunUntilIdle();
   1602   EXPECT_EQ(2, model_->item_count());
   1603   // There are a few animations which need finishing before we can continue.
   1604   test.RunMessageLoopUntilAnimationsDone();
   1605   // Move the mouse outside of the launcher.
   1606   generator.MoveMouseTo(0, 0);
   1607 
   1608   // Test #2: Check that the unknown item dropped into the launcher will
   1609   // create a new item.
   1610   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1611                         bounds_grid_1.CenterPoint().y());
   1612   generator.PressLeftButton();
   1613   generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
   1614                         bounds_launcher_1.CenterPoint().y());
   1615   base::MessageLoop::current()->RunUntilIdle();
   1616   EXPECT_EQ(3, model_->item_count());
   1617   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1618   generator.ReleaseLeftButton();
   1619   base::MessageLoop::current()->RunUntilIdle();
   1620   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1621   EXPECT_EQ(3, model_->item_count());  // It should be still there.
   1622   test.RunMessageLoopUntilAnimationsDone();
   1623 
   1624   // Test #3: Check that the now known item dropped into the launcher will
   1625   // not create a new item.
   1626   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1627                         bounds_grid_1.CenterPoint().y());
   1628   generator.PressLeftButton();
   1629   generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
   1630                         bounds_launcher_1.CenterPoint().y());
   1631   base::MessageLoop::current()->RunUntilIdle();
   1632   EXPECT_EQ(3, model_->item_count());  // No new item got added.
   1633   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1634   generator.ReleaseLeftButton();
   1635   base::MessageLoop::current()->RunUntilIdle();
   1636   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1637   EXPECT_EQ(3, model_->item_count());  // And it remains that way.
   1638 
   1639   // Test #4: Check that by pressing ESC the operation gets cancelled.
   1640   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1641                         bounds_grid_1.CenterPoint().y());
   1642   generator.PressLeftButton();
   1643   generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
   1644                         bounds_launcher_1.CenterPoint().y());
   1645   base::MessageLoop::current()->RunUntilIdle();
   1646   // Issue an ESC and see that the operation gets cancelled.
   1647   generator.PressKey(ui::VKEY_ESCAPE, 0);
   1648   generator.ReleaseKey(ui::VKEY_ESCAPE, 0);
   1649   EXPECT_FALSE(grid_view->dragging());
   1650   EXPECT_FALSE(grid_view->has_dragged_view());
   1651   generator.ReleaseLeftButton();
   1652 }
   1653 
   1654 #if !defined(OS_WIN)
   1655 // Used to test drag & drop an item between app list and shelf with multi
   1656 // display environment.
   1657 class LauncherAppBrowserTestWithMultiMonitor
   1658     : public LauncherAppBrowserTestNoDefaultBrowser {
   1659  protected:
   1660   LauncherAppBrowserTestWithMultiMonitor() {}
   1661   virtual ~LauncherAppBrowserTestWithMultiMonitor() {}
   1662 
   1663   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
   1664     LauncherAppBrowserTestNoDefaultBrowser::SetUpCommandLine(command_line);
   1665     command_line->AppendSwitchASCII("ash-host-window-bounds",
   1666                                     "800x600,801+0-800x600");
   1667   }
   1668 
   1669  private:
   1670 
   1671   DISALLOW_COPY_AND_ASSIGN(LauncherAppBrowserTestWithMultiMonitor);
   1672 };
   1673 
   1674 // Do basic drag and drop interaction tests between the application list and
   1675 // the launcher in the secondary monitor.
   1676 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestWithMultiMonitor,
   1677     BasicDragAndDrop) {
   1678   // Get a number of interfaces we need.
   1679   DCHECK_EQ(ash::Shell::GetAllRootWindows().size(), 2U);
   1680   aura::Window* secondary_root_window = ash::Shell::GetAllRootWindows()[1];
   1681   ash::Launcher* secondary_launcher =
   1682       ash::Launcher::ForWindow(secondary_root_window);
   1683 
   1684   aura::test::EventGenerator generator(secondary_root_window, gfx::Point());
   1685   ash::test::ShelfViewTestAPI test(
   1686       ash::test::LauncherTestAPI(secondary_launcher).shelf_view());
   1687   AppListService* service = AppListService::Get(chrome::GetActiveDesktop());
   1688 
   1689   // There should be two items in our launcher by this time.
   1690   EXPECT_EQ(2, model_->item_count());
   1691   EXPECT_FALSE(service->IsAppListVisible());
   1692 
   1693   // Open the app list menu and check that the drag and drop host was set.
   1694   gfx::Rect app_list_bounds =
   1695       test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen();
   1696   gfx::Display display =
   1697       ash::Shell::GetScreen()->GetDisplayNearestWindow(secondary_root_window);
   1698   const gfx::Point& origin = display.bounds().origin();
   1699   app_list_bounds.Offset(-origin.x(), -origin.y());
   1700 
   1701   generator.MoveMouseTo(app_list_bounds.CenterPoint().x(),
   1702                         app_list_bounds.CenterPoint().y());
   1703   base::MessageLoop::current()->RunUntilIdle();
   1704   generator.ClickLeftButton();
   1705 
   1706   EXPECT_TRUE(service->IsAppListVisible());
   1707   app_list::AppsGridView* grid_view =
   1708       ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).
   1709           GetRootGridView();
   1710   ASSERT_TRUE(grid_view);
   1711   ASSERT_TRUE(grid_view->has_drag_and_drop_host_for_test());
   1712 
   1713   // There should be 2 items in our application list.
   1714   const views::ViewModel* vm_grid = grid_view->view_model_for_test();
   1715   EXPECT_EQ(2, vm_grid->view_size());
   1716 
   1717   // Drag an app list item which does not exist yet in the launcher.
   1718   // Keeping it dragged, see that a new item gets created.
   1719   // Continuing to drag it out should remove it again.
   1720 
   1721   // Get over item #1 of the application list and press the mouse button.
   1722   views::View* item1 = vm_grid->view_at(1);
   1723   gfx::Rect bounds_grid_1 = item1->GetBoundsInScreen();
   1724   bounds_grid_1.Offset(-origin.x(), -origin.y());
   1725   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1726                         bounds_grid_1.CenterPoint().y());
   1727   base::MessageLoop::current()->RunUntilIdle();
   1728   generator.PressLeftButton();
   1729 
   1730   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1731 
   1732   // Drag the item into the launcher and check that a new item gets created.
   1733   const views::ViewModel* vm_launcher =
   1734       test.shelf_view()->view_model_for_test();
   1735   views::View* launcher1 = vm_launcher->view_at(1);
   1736   gfx::Rect bounds_launcher_1 = launcher1->GetBoundsInScreen();
   1737   bounds_launcher_1.Offset(-origin.x(), -origin.y());
   1738   generator.MoveMouseTo(bounds_launcher_1.CenterPoint().x(),
   1739                         bounds_launcher_1.CenterPoint().y());
   1740   base::MessageLoop::current()->RunUntilIdle();
   1741 
   1742   // Check that a new item got created.
   1743   EXPECT_EQ(3, model_->item_count());
   1744   EXPECT_TRUE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1745 
   1746   // Move it where the item originally was and check that it disappears again.
   1747   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1748                         bounds_grid_1.CenterPoint().y());
   1749   base::MessageLoop::current()->RunUntilIdle();
   1750   EXPECT_EQ(2, model_->item_count());
   1751   EXPECT_FALSE(grid_view->forward_events_to_drag_and_drop_host_for_test());
   1752 
   1753   // Dropping it should keep the launcher as it originally was.
   1754   generator.ReleaseLeftButton();
   1755   base::MessageLoop::current()->RunUntilIdle();
   1756   EXPECT_EQ(2, model_->item_count());
   1757 }
   1758 #endif
   1759 
   1760 // Do tests for removal of items from the shelf by dragging.
   1761 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, DragOffShelf) {
   1762   aura::test::EventGenerator generator(
   1763       ash::Shell::GetPrimaryRootWindow(), gfx::Point());
   1764   ash::test::ShelfViewTestAPI test(
   1765       ash::test::LauncherTestAPI(launcher_).shelf_view());
   1766   test.SetAnimationDuration(1);  // Speed up animations for test.
   1767   // Create a known application and check that we have 3 items in the launcher.
   1768   CreateShortcut("app1");
   1769   test.RunMessageLoopUntilAnimationsDone();
   1770   EXPECT_EQ(3, model_->item_count());
   1771 
   1772   // Test #1: Ripping out the browser item should not change anything.
   1773   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
   1774   EXPECT_LE(0, browser_index);
   1775   RipOffItemIndex(browser_index, &generator, &test, RIP_OFF_ITEM);
   1776   // => It should not have been removed and the location should be unchanged.
   1777   EXPECT_EQ(3, model_->item_count());
   1778   EXPECT_EQ(browser_index,
   1779             GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT));
   1780   // Make sure that the hide state has been unset after the snap back animation
   1781   // finished.
   1782   ash::internal::ShelfButton* button = test.GetButton(browser_index);
   1783   EXPECT_FALSE(button->state() & ash::internal::ShelfButton::STATE_HIDDEN);
   1784 
   1785   // Test #2: Ripping out the application and canceling the operation should
   1786   // not change anything.
   1787   int app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
   1788   EXPECT_LE(0, app_index);
   1789   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_CANCEL);
   1790   // => It should not have been removed and the location should be unchanged.
   1791   ASSERT_EQ(3, model_->item_count());
   1792   EXPECT_EQ(app_index, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
   1793 
   1794   // Test #3: Ripping out the application and moving it back in should not
   1795   // change anything.
   1796   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM_AND_RETURN);
   1797   // => It should not have been removed and the location should be unchanged.
   1798   ASSERT_EQ(3, model_->item_count());
   1799   // Through the operation the index might have changed.
   1800   app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
   1801 
   1802   // Test #4: Ripping out the application should remove the item.
   1803   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
   1804   // => It should not have been removed and the location should be unchanged.
   1805   EXPECT_EQ(2, model_->item_count());
   1806   EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
   1807 
   1808   // Test #5: Uninstalling an application while it is being ripped off should
   1809   // not crash.
   1810   ash::LauncherID app_id = CreateShortcut("app2");
   1811   test.RunMessageLoopUntilAnimationsDone();
   1812   int app2_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
   1813   EXPECT_EQ(3, model_->item_count());  // And it remains that way.
   1814   RipOffItemIndex(app2_index,
   1815                   &generator,
   1816                   &test,
   1817                   RIP_OFF_ITEM_AND_DONT_RELEASE_MOUSE);
   1818   RemoveShortcut(app_id);
   1819   test.RunMessageLoopUntilAnimationsDone();
   1820   EXPECT_EQ(2, model_->item_count());  // The item should now be gone.
   1821   generator.ReleaseLeftButton();
   1822   base::MessageLoop::current()->RunUntilIdle();
   1823   EXPECT_EQ(2, model_->item_count());  // And it remains that way.
   1824   EXPECT_EQ(-1, GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT));
   1825 
   1826   // Test #6: Ripping out the application when the overflow button exists.
   1827   // After ripping out, overflow button should be removed.
   1828   int items_added = 0;
   1829   EXPECT_FALSE(test.IsOverflowButtonVisible());
   1830 
   1831   // Create fake app shortcuts until overflow button is created.
   1832   while (!test.IsOverflowButtonVisible()) {
   1833     std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
   1834     PinFakeApp(fake_app_id);
   1835     test.RunMessageLoopUntilAnimationsDone();
   1836 
   1837     ++items_added;
   1838     ASSERT_LT(items_added, 10000);
   1839   }
   1840   // Make one more item after creating a overflow button.
   1841   std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
   1842   PinFakeApp(fake_app_id);
   1843   test.RunMessageLoopUntilAnimationsDone();
   1844 
   1845   int total_count = model_->item_count();
   1846   app_index = GetIndexOfShelfItemType(ash::TYPE_APP_SHORTCUT);
   1847   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
   1848   // When an item is ripped off from the launcher that has overflow button
   1849   // (see crbug.com/3050787), it was hidden accidentally and was then
   1850   // suppressing any further events. If handled correctly the operation will
   1851   // however correctly done and the item will get removed (as well as the
   1852   // overflow button).
   1853   EXPECT_EQ(total_count - 1, model_->item_count());
   1854   EXPECT_TRUE(test.IsOverflowButtonVisible());
   1855 
   1856   // Rip off again and the overflow button should has disappeared.
   1857   RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM);
   1858   EXPECT_EQ(total_count - 2, model_->item_count());
   1859   EXPECT_FALSE(test.IsOverflowButtonVisible());
   1860 }
   1861 
   1862 // Check that clicking on an app launcher item launches a new browser.
   1863 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, ClickItem) {
   1864   // Get a number of interfaces we need.
   1865   aura::test::EventGenerator generator(
   1866       ash::Shell::GetPrimaryRootWindow(), gfx::Point());
   1867   ash::test::ShelfViewTestAPI test(
   1868       ash::test::LauncherTestAPI(launcher_).shelf_view());
   1869   AppListService* service = AppListService::Get(chrome::GetActiveDesktop());
   1870   // There should be two items in our launcher by this time.
   1871   EXPECT_EQ(2, model_->item_count());
   1872   EXPECT_FALSE(service->IsAppListVisible());
   1873 
   1874   // Open the app list menu and check that the drag and drop host was set.
   1875   gfx::Rect app_list_bounds =
   1876       test.shelf_view()->GetAppListButtonView()->GetBoundsInScreen();
   1877   generator.MoveMouseTo(app_list_bounds.CenterPoint().x(),
   1878                         app_list_bounds.CenterPoint().y());
   1879   generator.ClickLeftButton();
   1880   base::MessageLoop::current()->RunUntilIdle();
   1881 
   1882   EXPECT_TRUE(service->IsAppListVisible());
   1883   app_list::AppsGridView* grid_view =
   1884       ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).
   1885           GetRootGridView();
   1886   ASSERT_TRUE(grid_view);
   1887   const views::ViewModel* vm_grid = grid_view->view_model_for_test();
   1888   EXPECT_EQ(2, vm_grid->view_size());
   1889   gfx::Rect bounds_grid_1 = vm_grid->view_at(1)->GetBoundsInScreen();
   1890   // Test now that a click does create a new application tab.
   1891   TabStripModel* tab_strip = browser()->tab_strip_model();
   1892   int tab_count = tab_strip->count();
   1893   generator.MoveMouseTo(bounds_grid_1.CenterPoint().x(),
   1894                         bounds_grid_1.CenterPoint().y());
   1895   generator.ClickLeftButton();
   1896   base::MessageLoop::current()->RunUntilIdle();
   1897   EXPECT_EQ(tab_count + 1, tab_strip->count());
   1898 }
   1899 
   1900 // Check LauncherItemController of Browser Shortcut functionality.
   1901 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTestNoDefaultBrowser,
   1902     BrowserShortcutLauncherItemController) {
   1903   LauncherItemController* item_controller =
   1904       controller_->GetBrowserShortcutLauncherItemController();
   1905 
   1906   // Get the number of browsers.
   1907   size_t running_browser = chrome::GetTotalBrowserCount();
   1908   EXPECT_EQ(0u, running_browser);
   1909   EXPECT_FALSE(item_controller->IsOpen());
   1910 
   1911   // Activate. This creates new browser
   1912   item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
   1913   // New Window is created.
   1914   running_browser = chrome::GetTotalBrowserCount();
   1915   EXPECT_EQ(1u, running_browser);
   1916   EXPECT_TRUE(item_controller->IsOpen());
   1917 
   1918   // Minimize Window.
   1919   ash::wm::WindowState* window_state = ash::wm::GetActiveWindowState();
   1920   window_state->Minimize();
   1921   EXPECT_TRUE(window_state->IsMinimized());
   1922 
   1923   // Activate again. This doesn't create new browser.
   1924   // It activates window.
   1925   item_controller->Activate(ash::LAUNCH_FROM_UNKNOWN);
   1926   running_browser = chrome::GetTotalBrowserCount();
   1927   EXPECT_EQ(1u, running_browser);
   1928   EXPECT_TRUE(item_controller->IsOpen());
   1929   EXPECT_FALSE(window_state->IsMinimized());
   1930 }
   1931 
   1932 // Check that GetLauncherIDForWindow() returns |LauncherID| of the active tab.
   1933 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, MatchingLauncherIDandActiveTab) {
   1934   EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
   1935   EXPECT_EQ(1, browser()->tab_strip_model()->count());
   1936   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
   1937   EXPECT_EQ(2, model_->item_count());
   1938 
   1939   aura::Window* window = browser()->window()->GetNativeWindow();
   1940 
   1941   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
   1942   ash::LauncherID browser_id = model_->items()[browser_index].id;
   1943   EXPECT_EQ(browser_id, ash::GetLauncherIDForWindow(window));
   1944 
   1945   ash::LauncherID app_id = CreateShortcut("app1");
   1946   EXPECT_EQ(3, model_->item_count());
   1947 
   1948   // Creates a new tab for "app1" and checks that GetLauncherIDForWindow()
   1949   // returns |LauncherID| of "app1".
   1950   ActivateLauncherItem(model_->ItemIndexByID(app_id));
   1951   EXPECT_EQ(2, browser()->tab_strip_model()->count());
   1952   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
   1953   EXPECT_EQ(app_id, ash::GetLauncherIDForWindow(window));
   1954 
   1955   // Makes tab at index 0(NTP) as an active tab and checks that
   1956   // GetLauncherIDForWindow() returns |LauncherID| of browser shortcut.
   1957   browser()->tab_strip_model()->ActivateTabAt(0, false);
   1958   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
   1959   EXPECT_EQ(browser_id, ash::GetLauncherIDForWindow(window));
   1960 }
   1961 
   1962 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, OverflowBubble) {
   1963   // Make sure to have a browser window
   1964   chrome::NewTab(browser());
   1965 
   1966   // No overflow yet.
   1967   EXPECT_FALSE(launcher_->IsShowingOverflowBubble());
   1968 
   1969   ash::test::ShelfViewTestAPI test(
   1970       ash::test::LauncherTestAPI(launcher_).shelf_view());
   1971 
   1972   int items_added = 0;
   1973   while (!test.IsOverflowButtonVisible()) {
   1974     std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added);
   1975     PinFakeApp(fake_app_id);
   1976 
   1977     ++items_added;
   1978     ASSERT_LT(items_added, 10000);
   1979   }
   1980 
   1981   // Now show overflow bubble.
   1982   test.ShowOverflowBubble();
   1983   EXPECT_TRUE(launcher_->IsShowingOverflowBubble());
   1984 
   1985   // Unpin first pinned app and there should be no crash.
   1986   controller_->UnpinAppWithID(std::string("fake_app_0"));
   1987 
   1988   test.RunMessageLoopUntilAnimationsDone();
   1989   EXPECT_FALSE(launcher_->IsShowingOverflowBubble());
   1990 }
   1991 
   1992 // Check that a windowed V1 application can navigate away from its domain, but
   1993 // still gets detected properly.
   1994 IN_PROC_BROWSER_TEST_F(LauncherAppBrowserTest, V1AppNavigation) {
   1995   // We assume that the web store is always there (which it apparently is).
   1996   controller_->PinAppWithID(extension_misc::kWebStoreAppId);
   1997   ash::LauncherID id = controller_->GetLauncherIDForAppID(
   1998       extension_misc::kWebStoreAppId);
   1999   ASSERT_NE(0, id);
   2000   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status);
   2001 
   2002   // Create a windowed application.
   2003   AppLaunchParams params(
   2004       profile(),
   2005       controller_->GetExtensionForAppID(extension_misc::kWebStoreAppId),
   2006       0,
   2007       chrome::HOST_DESKTOP_TYPE_ASH);
   2008   params.container = extensions::LAUNCH_CONTAINER_WINDOW;
   2009   OpenApplication(params);
   2010   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status);
   2011 
   2012   // Find the browser which holds our app.
   2013   Browser* app_browser = NULL;
   2014   const BrowserList* ash_browser_list =
   2015       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
   2016   for (BrowserList::const_reverse_iterator it =
   2017            ash_browser_list->begin_last_active();
   2018        it != ash_browser_list->end_last_active() && !app_browser; ++it) {
   2019     if ((*it)->is_app()) {
   2020       app_browser = *it;
   2021       break;
   2022     }
   2023   }
   2024   ASSERT_TRUE(app_browser);
   2025 
   2026   // After navigating away in the app, we should still be active.
   2027   ui_test_utils::NavigateToURL(app_browser,
   2028                                GURL("http://www.foo.com/bar.html"));
   2029   // Make sure the navigation was entirely performed.
   2030   base::MessageLoop::current()->RunUntilIdle();
   2031   EXPECT_EQ(ash::STATUS_ACTIVE, model_->ItemByID(id)->status);
   2032   app_browser->tab_strip_model()->CloseWebContentsAt(0,
   2033                                                      TabStripModel::CLOSE_NONE);
   2034   // Make sure that the app is really gone.
   2035   base::MessageLoop::current()->RunUntilIdle();
   2036   EXPECT_EQ(ash::STATUS_CLOSED, model_->ItemByID(id)->status);
   2037 }
   2038