- Show app list on 2nd launcher
- Share the launcher mode/delegate in multiple launchers.
 This CL moves the launcher mode/delegate to Shell
- Initialize Display objects before creating RootWindow
 for 2nd as it'll be used during creation.

I'll add tests in next CL, as it crashes without https://codereview.chromium.org/11515004/.

BUG=145978
TEST=none

Review URL: https://chromiumcodereview.appspot.com/11465037

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172310 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 66864e9..70aa3ac 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -566,7 +566,7 @@
       DCHECK_EQ(ui::VKEY_LWIN, accelerator.key_code());
       if (Shell::GetInstance()->delegate()->IsSpokenFeedbackEnabled())
         return false;
-      ash::Shell::GetInstance()->ToggleAppList();
+      ash::Shell::GetInstance()->ToggleAppList(NULL);
       return true;
     case DISABLE_CAPS_LOCK:
       if (previous_event_type == ui::ET_KEY_RELEASED ||
@@ -834,8 +834,9 @@
 
 void AcceleratorController::SwitchToWindow(int window) {
   Launcher* launcher = Launcher::ForPrimaryDisplay();
-  const LauncherItems& items = launcher->model()->items();
-  int item_count = launcher->model()->item_count();
+  LauncherModel* launcher_model = Shell::GetInstance()->launcher_model();
+  const LauncherItems& items = launcher_model->items();
+  int item_count = launcher_model->item_count();
   int indexes_left = window >= 0 ? window : item_count;
   int found_index = -1;
 
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index 16328fc..2fce25a 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -470,11 +470,11 @@
   DCHECK(!root_windows_.empty());
   NotifyDisplayConfigurationChanging();
   aura::RootWindow* root = AddRootWindowForDisplay(display);
-  Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
   UpdateDisplayBoundsForLayout();
-
   if (desired_primary_display_id_ == display.id())
     SetPrimaryDisplay(display);
+
+  Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
 }
 
 void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index e14d39a..572f91a 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -447,8 +447,14 @@
   std::vector<gfx::Display> new_displays;
   new_displays.push_back(DisplayController::GetPrimaryDisplay());
   // Add if there is only one display.
-  if (displays_.size() == 1)
-    new_displays.push_back(aura::CreateDisplayFromSpec("100+200-500x400"));
+  if (displays_.size() == 1) {
+    // Layout the 2nd display below the primary as with the real device.
+    aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
+    gfx::Rect host_bounds =
+        gfx::Rect(primary->GetHostOrigin(),  primary->GetHostSize());
+    new_displays.push_back(aura::CreateDisplayFromSpec(
+        StringPrintf("%d+%d-500x400", host_bounds.x(), host_bounds.bottom())));
+  }
   OnNativeDisplaysChanged(new_displays);
 }
 
diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc
index ca3fb39..d9b1a3f 100644
--- a/ash/launcher/launcher.cc
+++ b/ash/launcher/launcher.cc
@@ -206,11 +206,8 @@
       delegate_view_(new DelegateView(this)),
       launcher_view_(NULL),
       alignment_(SHELF_ALIGNMENT_BOTTOM),
+      delegate_(Shell::GetInstance()->GetLauncherDelegate()),
       background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha) {
-  model_.reset(new LauncherModel);
-  delegate_.reset(
-      Shell::GetInstance()->delegate()->CreateLauncherDelegate(model_.get()));
-
   widget_.reset(new views::Widget);
   views::Widget::InitParams params(
       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
@@ -220,7 +217,7 @@
       window_container_->GetRootWindow(),
       ash::internal::kShellWindowId_LauncherContainer);
   launcher_view_ = new internal::LauncherView(
-      model_.get(), delegate_.get(), shelf_layout_manager);
+      Shell::GetInstance()->launcher_model(), delegate_, shelf_layout_manager);
   launcher_view_->Init();
   delegate_view_->AddChildView(launcher_view_);
   params.delegate = delegate_view_;
@@ -333,13 +330,14 @@
 }
 
 void Launcher::ActivateLauncherItem(int index) {
-  DCHECK(delegate_.get());
-  const ash::LauncherItems& items = model_->items();
+  const ash::LauncherItems& items =
+      Shell::GetInstance()->launcher_model()->items();
   delegate_->ItemClicked(items[index], ui::EF_NONE);
 }
 
 void Launcher::CycleWindowLinear(CycleDirection direction) {
-  int item_index = GetNextActivatedItemIndex(*model(), direction);
+  int item_index = GetNextActivatedItemIndex(
+      *(Shell::GetInstance()->launcher_model()), direction);
   if (item_index >= 0)
     ActivateLauncherItem(item_index);
 }
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index 7db8f50..758482a 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -110,9 +110,8 @@
   // TODO(sky): remove this!
   internal::LauncherView* GetLauncherViewForTest();
 
-  LauncherDelegate* delegate() { return delegate_.get(); }
+  LauncherDelegate* delegate() { return delegate_; }
 
-  LauncherModel* model() { return model_.get(); }
   views::Widget* widget() { return widget_.get(); }
 
   views::Widget* GetDimmerWidgetForTest() { return dimmer_.get(); }
@@ -122,8 +121,6 @@
  private:
   class DelegateView;
 
-  scoped_ptr<LauncherModel> model_;
-
   // Widget hosting the view.
   scoped_ptr<views::Widget> widget_;
   scoped_ptr<views::Widget> dimmer_;
@@ -138,7 +135,7 @@
 
   ShelfAlignment alignment_;
 
-  scoped_ptr<LauncherDelegate> delegate_;
+  LauncherDelegate* delegate_;
 
   // Size reserved for the status area.
   gfx::Size status_size_;
diff --git a/ash/launcher/launcher_unittest.cc b/ash/launcher/launcher_unittest.cc
index cbf8229..2c6dd58 100644
--- a/ash/launcher/launcher_unittest.cc
+++ b/ash/launcher/launcher_unittest.cc
@@ -58,7 +58,7 @@
   ASSERT_TRUE(launcher);
   LauncherView* launcher_view = launcher->GetLauncherViewForTest();
   test::LauncherViewTestAPI test(launcher_view);
-  LauncherModel* model = launcher->model();
+  LauncherModel* model = Shell::GetInstance()->launcher_model();
 
   // Initially we have the app list and chrome icon.
   int button_count = test.GetButtonCount();
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index a81a1c539..4620500 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -1042,7 +1042,7 @@
     case TYPE_APP_LIST:
       Shell::GetInstance()->delegate()->RecordUserMetricsAction(
           UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON);
-      Shell::GetInstance()->ToggleAppList();
+      Shell::GetInstance()->ToggleAppList(GetWidget()->GetNativeView());
       break;
 
     case TYPE_BROWSER_SHORTCUT:
diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc
index 727d0ff..8c0823ed 100644
--- a/ash/launcher/launcher_view_unittest.cc
+++ b/ash/launcher/launcher_view_unittest.cc
@@ -675,7 +675,7 @@
 }
 
 TEST_F(LauncherViewTest, ShouldHideTooltipWithAppListWindowTest) {
-  Shell::GetInstance()->ToggleAppList();
+  Shell::GetInstance()->ToggleAppList(NULL);
   ASSERT_TRUE(Shell::GetInstance()->GetAppListWindow());
 
   // The tooltip shouldn't hide if the mouse is on normal buttons.
diff --git a/ash/shell.cc b/ash/shell.cc
index dbf94c24..de1721d 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -20,6 +20,8 @@
 #include "ash/drag_drop/drag_drop_controller.h"
 #include "ash/focus_cycler.h"
 #include "ash/high_contrast/high_contrast_controller.h"
+#include "ash/launcher/launcher_delegate.h"
+#include "ash/launcher/launcher_model.h"
 #include "ash/magnifier/magnification_controller.h"
 #include "ash/magnifier/partial_magnification_controller.h"
 #include "ash/root_window_controller.h"
@@ -267,7 +269,7 @@
 
   // These need a valid Shell instance to clean up properly, so explicitly
   // delete them before invalidating the instance.
-  // Alphabetical.
+  // Alphabetical. TODO(oshima): sort.
   drag_drop_controller_.reset();
   magnification_controller_.reset();
   partial_magnification_controller_.reset();
@@ -280,6 +282,8 @@
   nested_dispatcher_controller_.reset();
   user_action_client_.reset();
   visibility_controller_.reset();
+  launcher_delegate_.reset();
+  launcher_model_.reset();
 
   power_button_controller_.reset();
   session_state_controller_.reset();
@@ -578,10 +582,13 @@
   GetRootWindowController(root)->ShowContextMenu(location_in_screen);
 }
 
-void Shell::ToggleAppList() {
+void Shell::ToggleAppList(aura::Window* window) {
+  // If the context window is not given, show it on the active root window.
+  if (!window)
+    window = GetActiveRootWindow();
   if (!app_list_controller_.get())
     app_list_controller_.reset(new internal::AppListController);
-  app_list_controller_->SetVisible(!app_list_controller_->IsVisible());
+  app_list_controller_->SetVisible(!app_list_controller_->IsVisible(), window);
 }
 
 bool Shell::GetAppListTargetVisibility() const {
@@ -767,6 +774,15 @@
   return GetPrimaryRootWindowController()->GetSystemTray();
 }
 
+LauncherDelegate* Shell::GetLauncherDelegate() {
+  if (!launcher_delegate_.get()) {
+    launcher_model_.reset(new LauncherModel);
+    launcher_delegate_.reset(
+        delegate_->CreateLauncherDelegate(launcher_model_.get()));
+  }
+  return launcher_delegate_.get();
+}
+
 void Shell::InitRootWindowForSecondaryDisplay(aura::RootWindow* root) {
   aura::client::SetFocusClient(root, focus_client_.get());
   internal::RootWindowController* controller =
diff --git a/ash/shell.h b/ash/shell.h
index 3a21dfd6..0a1fe5f 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -71,6 +71,8 @@
 class DisplayController;
 class HighContrastController;
 class Launcher;
+class LauncherDelegate;
+class LauncherModel;
 class MagnificationController;
 class NestedDispatcherController;
 class PartialMagnificationController;
@@ -191,8 +193,10 @@
   // |location_in_screen| (in screen coordinates).
   void ShowContextMenu(const gfx::Point& location_in_screen);
 
-  // Toggles app list.
-  void ToggleAppList();
+  // Toggles the app list. |window| specifies in which display the app
+  // list should be shown. If this is NULL, the active root window
+  // will be used.
+  void ToggleAppList(aura::Window* anchor);
 
   // Returns app list target visibility.
   bool GetAppListTargetVisibility() const;
@@ -366,6 +370,9 @@
   // Returns the system tray on primary display.
   SystemTray* GetPrimarySystemTray();
 
+  // Returns the launcher delegate, creating if necesary.
+  LauncherDelegate* GetLauncherDelegate();
+
   // TODO(stevenjb): Rename to system_tray_delegate().
   SystemTrayDelegate* tray_delegate() {
     return system_tray_delegate_.get();
@@ -375,6 +382,10 @@
     return system_tray_notifier_.get();
   }
 
+  LauncherModel* launcher_model() {
+    return launcher_model_.get();
+  }
+
   static void set_initially_hide_cursor(bool hide) {
     initially_hide_cursor_ = hide;
   }
@@ -468,6 +479,9 @@
   scoped_ptr<SystemTrayNotifier> system_tray_notifier_;
   scoped_ptr<UserWallpaperDelegate> user_wallpaper_delegate_;
   scoped_ptr<CapsLockDelegate> caps_lock_delegate_;
+  scoped_ptr<LauncherDelegate> launcher_delegate_;
+
+  scoped_ptr<LauncherModel> launcher_model_;
 
   scoped_ptr<internal::AppListController> app_list_controller_;
 
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc
index 0e7e103e..268a472 100644
--- a/ash/shell/app_list.cc
+++ b/ash/shell/app_list.cc
@@ -275,7 +275,7 @@
   virtual void Dismiss() OVERRIDE {
     DCHECK(ash::Shell::HasInstance());
     if (Shell::GetInstance()->GetAppListTargetVisibility())
-      Shell::GetInstance()->ToggleAppList();
+      Shell::GetInstance()->ToggleAppList(NULL);
   }
 
   virtual void ViewClosing() OVERRIDE {
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc
index 157a598..9f30bff7 100644
--- a/ash/shell/window_watcher.cc
+++ b/ash/shell/window_watcher.cc
@@ -77,7 +77,7 @@
     return;
 
   static int image_count = 0;
-  ash::LauncherModel* model = Launcher::ForPrimaryDisplay()->model();
+  ash::LauncherModel* model = Shell::GetInstance()->launcher_model();
   ash::LauncherItem item;
   item.type = ash::TYPE_TABBED;
   id_to_window_[model->next_id()] = new_window;
@@ -100,7 +100,7 @@
   for (IDToWindow::iterator i = id_to_window_.begin();
        i != id_to_window_.end(); ++i) {
     if (i->second == window) {
-      ash::LauncherModel* model = Launcher::ForPrimaryDisplay()->model();
+      ash::LauncherModel* model = Shell::GetInstance()->launcher_model();
       int index = model->ItemIndexByID(i->first);
       DCHECK_NE(-1, index);
       model->RemoveItemAt(index);
diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc
index 3c52d770..d21e19f 100644
--- a/ash/wm/app_list_controller.cc
+++ b/ash/wm/app_list_controller.cc
@@ -101,7 +101,7 @@
   pagination_model_->RemoveObserver(this);
 }
 
-void AppListController::SetVisible(bool visible) {
+void AppListController::SetVisible(bool visible, aura::Window* window) {
   if (visible == is_visible_)
     return;
 
@@ -118,14 +118,12 @@
     // will be released with AppListView on close.
     app_list::AppListView* view = new app_list::AppListView(
         Shell::GetInstance()->delegate()->CreateAppListViewDelegate());
-    // TODO(oshima): support multiple displays.
-    aura::Window* container = Shell::GetPrimaryRootWindowController()->
+    aura::Window* container = GetRootWindowController(window->GetRootWindow())->
         GetContainer(kShellWindowId_AppListContainer);
     view->InitAsBubble(
-        Shell::GetPrimaryRootWindowController()->GetContainer(
-            kShellWindowId_AppListContainer),
+        container,
         pagination_model_.get(),
-        Launcher::ForWindow(GetWindow())->GetAppListButtonView(),
+        Launcher::ForWindow(container)->GetAppListButtonView(),
         gfx::Point(),
         GetBubbleArrowLocation(container));
     SetView(view);
@@ -151,7 +149,7 @@
   views::Widget* widget = view_->GetWidget();
   widget->AddObserver(this);
   Shell::GetInstance()->AddPreTargetHandler(this);
-  Launcher::ForWindow(GetWindow())->AddIconObserver(this);
+  Launcher::ForWindow(widget->GetNativeWindow())->AddIconObserver(this);
   widget->GetNativeView()->GetRootWindow()->AddRootWindowObserver(this);
   aura::client::GetFocusClient(widget->GetNativeView())->AddObserver(this);
 
@@ -166,7 +164,7 @@
   widget->RemoveObserver(this);
   GetLayer(widget)->GetAnimator()->RemoveObserver(this);
   Shell::GetInstance()->RemovePreTargetHandler(this);
-  Launcher::ForWindow(GetWindow())->RemoveIconObserver(this);
+  Launcher::ForWindow(widget->GetNativeWindow())->RemoveIconObserver(this);
   widget->GetNativeView()->GetRootWindow()->RemoveRootWindowObserver(this);
   aura::client::GetFocusClient(widget->GetNativeView())->RemoveObserver(this);
   view_ = NULL;
@@ -222,7 +220,7 @@
                                        &window_local_point);
     // Use HitTest to respect the hit test mask of the bubble.
     if (!window->HitTest(window_local_point))
-      SetVisible(false);
+      SetVisible(false, window);
   }
 }
 
@@ -251,11 +249,11 @@
 void AppListController::OnWindowFocused(aura::Window* gained_focus,
                                         aura::Window* lost_focus) {
   if (gained_focus && view_ && is_visible_) {
-    aura::Window* applist_container = Shell::GetContainer(
-        Shell::GetPrimaryRootWindow(),
-        kShellWindowId_AppListContainer);
+    aura::Window* applist_container =
+        GetRootWindowController(gained_focus->GetRootWindow())->GetContainer(
+            kShellWindowId_AppListContainer);
     if (gained_focus->parent() != applist_container)
-      SetVisible(false);
+      SetVisible(false, gained_focus);
   }
 }
 
@@ -282,7 +280,7 @@
 void AppListController::OnWidgetClosing(views::Widget* widget) {
   DCHECK(view_->GetWidget() == widget);
   if (is_visible_)
-    SetVisible(false);
+    SetVisible(false, widget->GetNativeView());
   ResetView();
 }
 
diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h
index b45efaa2..07314aa7 100644
--- a/ash/wm/app_list_controller.h
+++ b/ash/wm/app_list_controller.h
@@ -45,8 +45,10 @@
   AppListController();
   virtual ~AppListController();
 
-  // Show/hide app list window.
-  void SetVisible(bool visible);
+  // Show/hide app list window. The |window| is used to deterime in
+  // which display (in which the |window| exists) the app list should
+  // be shown.
+  void SetVisible(bool visible, aura::Window* window);
 
   // Whether app list window is visible (shown or being shown).
   bool IsVisible() const;
diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc
index 1937a7e..e37e486 100644
--- a/ash/wm/shelf_layout_manager.cc
+++ b/ash/wm/shelf_layout_manager.cc
@@ -249,8 +249,7 @@
           status_area_widget_->GetNativeView()->parent(),
           target_bounds.status_bounds_in_root));
   Shell::GetInstance()->SetDisplayWorkAreaInsets(
-      Shell::GetPrimaryRootWindow(),
-      target_bounds.work_area_insets);
+      root_window_, target_bounds.work_area_insets);
   UpdateHitTestBounds();
 }
 
@@ -578,8 +577,7 @@
   layer->SetBounds(target_bounds.status_bounds_in_root);
   layer->SetOpacity(target_bounds.opacity);
   Shell::GetInstance()->SetDisplayWorkAreaInsets(
-      Shell::GetPrimaryRootWindow(),
-      target_bounds.work_area_insets);
+      root_window_, target_bounds.work_area_insets);
   UpdateHitTestBounds();
   if (!delay_shelf_update)
     UpdateShelfBackground(change_type);
diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc
index 76c78684..382a477 100644
--- a/ash/wm/shelf_layout_manager_unittest.cc
+++ b/ash/wm/shelf_layout_manager_unittest.cc
@@ -519,12 +519,12 @@
   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
 
   // Toggle app list to show, and the shelf stays visible.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   EXPECT_TRUE(shell->GetAppListTargetVisibility());
   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
 
   // Toggle app list to hide, and the shelf stays visible.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
 }
@@ -551,7 +551,7 @@
   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
 
   // Toggle app list to show.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   // The shelf's auto hide state won't be changed until the timer fires, so
   // calling shell->UpdateShelfVisibility() is kind of manually helping it to
   // update the state.
@@ -561,7 +561,7 @@
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
 
   // Toggle app list to hide.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
 }
@@ -586,12 +586,12 @@
   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
 
   // Toggle app list to show.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   EXPECT_TRUE(shell->GetAppListTargetVisibility());
   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
 
   // Toggle app list to hide.
-  shell->ToggleAppList();
+  shell->ToggleAppList(NULL);
   EXPECT_FALSE(shell->GetAppListTargetVisibility());
   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
 }
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
index a2e6b20e..8bb13ba 100644
--- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
@@ -14,7 +14,7 @@
 void AppListControllerDelegateAsh::DismissView() {
   DCHECK(ash::Shell::HasInstance());
   if (ash::Shell::GetInstance()->GetAppListTargetVisibility())
-    ash::Shell::GetInstance()->ToggleAppList();
+    ash::Shell::GetInstance()->ToggleAppList(NULL);
 }
 
 bool AppListControllerDelegateAsh::IsAppPinned(
@@ -63,7 +63,7 @@
 
 #if defined(OS_CHROMEOS)
 void ShowAppList() {
-  ash::Shell::GetInstance()->ToggleAppList();
+  ash::Shell::GetInstance()->ToggleAppList(NULL);
 }
 #endif
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index c4cb1a27..de6435ca 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "ash/launcher/launcher.h"
 #include "ash/launcher/launcher_model.h"
+#include "ash/shell.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "base/utf_string_conversions.h"
@@ -48,6 +49,10 @@
 
   virtual ~LauncherPlatformAppBrowserTest() {}
 
+  ash::LauncherModel* launcher_model() {
+    return ash::Shell::GetInstance()->launcher_model();
+  }
+
   virtual void RunTestOnMainThreadLoop() {
     launcher_ = ash::Launcher::ForPrimaryDisplay();
     controller_ = static_cast<ChromeLauncherController*>(launcher_->delegate());
@@ -74,7 +79,7 @@
 
   virtual void RunTestOnMainThreadLoop() {
     launcher_ = ash::Launcher::ForPrimaryDisplay();
-    model_ = launcher_->model();
+    model_ = ash::Shell::GetInstance()->launcher_model();
     return ExtensionBrowserTest::RunTestOnMainThreadLoop();
   }
 
@@ -124,24 +129,23 @@
 
 // Test that we can launch a platform app and get a running item.
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchUnpinned) {
-  ash::Launcher* launcher = ash::Launcher::ForPrimaryDisplay();
-  int item_count = launcher->model()->item_count();
+  int item_count = launcher_model()->item_count();
   const Extension* extension = LoadAndLaunchPlatformApp("launch");
   ShellWindow* window = CreateShellWindow(extension);
   ++item_count;
-  ASSERT_EQ(item_count, launcher->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item =
-      launcher->model()->items()[launcher->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   CloseShellWindow(window);
   --item_count;
-  EXPECT_EQ(item_count, launcher->model()->item_count());
+  EXPECT_EQ(item_count, launcher_model()->item_count());
 }
 
 // Test that we can launch a platform app that already has a shortcut.
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, LaunchPinned) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First get app_id.
   const Extension* extension = LoadAndLaunchPlatformApp("launch");
@@ -150,36 +154,36 @@
   // Then create a shortcut.
   ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  ash::LauncherItem item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
 
   // Open a window. Confirm the item is now running.
   ShellWindow* window = CreateShellWindow(extension);
   ash::wm::ActivateWindow(window->GetNativeWindow());
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // Then close it, make sure there's still an item.
   CloseShellWindow(window);
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
 }
 
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, PinRunning) {
   // Run.
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
   const Extension* extension = LoadAndLaunchPlatformApp("launch");
   ShellWindow* window = CreateShellWindow(extension);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID id = item.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
@@ -187,31 +191,31 @@
   // Create a shortcut. The app item should be after it.
   ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  EXPECT_LT(launcher_->model()->ItemIndexByID(foo_id),
-            launcher_->model()->ItemIndexByID(id));
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  EXPECT_LT(launcher_model()->ItemIndexByID(foo_id),
+            launcher_model()->ItemIndexByID(id));
 
   // Pin the app. The item should remain.
   controller_->Pin(id);
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // New shortcuts should come after the item.
   ash::LauncherID bar_id = CreateAppShortcutLauncherItem("bar");
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  EXPECT_LT(launcher_->model()->ItemIndexByID(id),
-            launcher_->model()->ItemIndexByID(bar_id));
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  EXPECT_LT(launcher_model()->ItemIndexByID(id),
+            launcher_model()->ItemIndexByID(bar_id));
 
   // Then close it, make sure the item remains.
   CloseShellWindow(window);
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
 }
 
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, UnpinRunning) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First get app_id.
   const Extension* extension = LoadAndLaunchPlatformApp("launch");
@@ -220,8 +224,8 @@
   // Then create a shortcut.
   ash::LauncherID shortcut_id = CreateAppShortcutLauncherItem(app_id);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  ash::LauncherItem item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  ash::LauncherItem item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_CLOSED, item.status);
 
@@ -229,45 +233,45 @@
   // move once it gets unpinned.
   ash::LauncherID foo_id = CreateAppShortcutLauncherItem("foo");
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  EXPECT_LT(launcher_->model()->ItemIndexByID(shortcut_id),
-            launcher_->model()->ItemIndexByID(foo_id));
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  EXPECT_LT(launcher_model()->ItemIndexByID(shortcut_id),
+            launcher_model()->ItemIndexByID(foo_id));
 
   // Open a window. Confirm the item is now running.
   ShellWindow* window = CreateShellWindow(extension);
   ash::wm::ActivateWindow(window->GetNativeWindow());
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_APP_SHORTCUT, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // Unpin the app. The item should remain.
   controller_->Unpin(shortcut_id);
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(shortcut_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(shortcut_id);
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
   // The item should have moved after the other shortcuts.
-  EXPECT_GT(launcher_->model()->ItemIndexByID(shortcut_id),
-            launcher_->model()->ItemIndexByID(foo_id));
+  EXPECT_GT(launcher_model()->ItemIndexByID(shortcut_id),
+            launcher_model()->ItemIndexByID(foo_id));
 
   // Then close it, make sure the item's gone.
   CloseShellWindow(window);
   --item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
 }
 
 // Test that we can launch a platform app with more than one window.
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MultipleWindows) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First run app.
   const Extension* extension = LoadAndLaunchPlatformApp("launch");
   ShellWindow* window1 = CreateShellWindow(extension);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id = item.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
@@ -275,22 +279,22 @@
   // Add second window.
   ShellWindow* window2 = CreateShellWindow(extension);
   // Confirm item stays.
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(item_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(item_id);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // Close second window.
   CloseShellWindow(window2);
   // Confirm item stays.
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
-  item = *launcher_->model()->ItemByID(item_id);
+  ASSERT_EQ(item_count, launcher_model()->item_count());
+  item = *launcher_model()->ItemByID(item_id);
   EXPECT_EQ(ash::STATUS_ACTIVE, item.status);
 
   // Close first window.
   CloseShellWindow(window1);
   // Confirm item is removed.
   --item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
 }
 
 // Times out on ChromeOS: http://crbug.com/159394
@@ -300,15 +304,15 @@
 #define MAYBE_MultipleApps MultipleApps
 #endif
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MAYBE_MultipleApps) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First run app.
   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
   ShellWindow* window1 = CreateShellWindow(extension1);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item1 =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id1 = item1.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
@@ -317,29 +321,29 @@
   const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
   ShellWindow* window2 = CreateShellWindow(extension2);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item2 =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id2 = item2.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
 
   EXPECT_NE(item_id1, item_id2);
   EXPECT_EQ(ash::STATUS_RUNNING,
-            launcher_->model()->ItemByID(item_id1)->status);
+            launcher_model()->ItemByID(item_id1)->status);
 
   // Close second app.
   CloseShellWindow(window2);
   --item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   // First app should be active again.
   EXPECT_EQ(ash::STATUS_ACTIVE,
-            launcher_->model()->ItemByID(item_id1)->status);
+            launcher_model()->ItemByID(item_id1)->status);
 
   // Close first app.
   CloseShellWindow(window1);
   --item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
 
 }
 
@@ -352,15 +356,15 @@
 #define MAYBE_WindowActivation WindowActivation
 #endif
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, MAYBE_WindowActivation) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First run app.
   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
   ShellWindow* window1 = CreateShellWindow(extension1);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item1 =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id1 = item1.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
@@ -369,30 +373,30 @@
   const Extension* extension2 = LoadAndLaunchPlatformApp("launch_2");
   ShellWindow* window2 = CreateShellWindow(extension2);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item2 =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id2 = item2.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item2.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item2.status);
 
   EXPECT_NE(item_id1, item_id2);
   EXPECT_EQ(ash::STATUS_RUNNING,
-            launcher_->model()->ItemByID(item_id1)->status);
+            launcher_model()->ItemByID(item_id1)->status);
 
   // Activate first one.
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id1));
-  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_->model()->ItemByID(item_id1)->status);
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
+  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status);
   EXPECT_EQ(ash::STATUS_RUNNING,
-            launcher_->model()->ItemByID(item_id2)->status);
+            launcher_model()->ItemByID(item_id2)->status);
   EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
 
   // Activate second one.
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id2));
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
   EXPECT_EQ(ash::STATUS_RUNNING,
-            launcher_->model()->ItemByID(item_id1)->status);
-  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_->model()->ItemByID(item_id2)->status);
+            launcher_model()->ItemByID(item_id1)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id2)->status);
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
   EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
 
@@ -404,21 +408,21 @@
   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
 
   // Activate launcher item for app1, this will cycle the active window.
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id1));
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
   EXPECT_TRUE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id1));
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
 
   // Activate the second app again
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id2));
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id2));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
   EXPECT_TRUE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
 
   // Activate the first app again
-  launcher_->ActivateLauncherItem(launcher_->model()->ItemIndexByID(item_id1));
+  launcher_->ActivateLauncherItem(launcher_model()->ItemIndexByID(item_id1));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window1->GetNativeWindow()));
   EXPECT_FALSE(ash::wm::IsActiveWindow(window2->GetNativeWindow()));
   EXPECT_TRUE(ash::wm::IsActiveWindow(window1b->GetNativeWindow()));
@@ -426,34 +430,34 @@
   // Close second app.
   CloseShellWindow(window2);
   --item_count;
-  EXPECT_EQ(item_count, launcher_->model()->item_count());
+  EXPECT_EQ(item_count, launcher_model()->item_count());
   // First app should be active again.
-  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_->model()->ItemByID(item_id1)->status);
+  EXPECT_EQ(ash::STATUS_ACTIVE, launcher_model()->ItemByID(item_id1)->status);
 
   // Close first app.
   CloseShellWindow(window1b);
   CloseShellWindow(window1);
   --item_count;
-  EXPECT_EQ(item_count, launcher_->model()->item_count());
+  EXPECT_EQ(item_count, launcher_model()->item_count());
 }
 
 IN_PROC_BROWSER_TEST_F(LauncherPlatformAppBrowserTest, BrowserActivation) {
-  int item_count = launcher_->model()->item_count();
+  int item_count = launcher_model()->item_count();
 
   // First run app.
   const Extension* extension1 = LoadAndLaunchPlatformApp("launch");
   CreateShellWindow(extension1);
   ++item_count;
-  ASSERT_EQ(item_count, launcher_->model()->item_count());
+  ASSERT_EQ(item_count, launcher_model()->item_count());
   ash::LauncherItem item1 =
-      launcher_->model()->items()[launcher_->model()->item_count() - 2];
+      launcher_model()->items()[launcher_model()->item_count() - 2];
   ash::LauncherID item_id1 = item1.id;
   EXPECT_EQ(ash::TYPE_PLATFORM_APP, item1.type);
   EXPECT_EQ(ash::STATUS_ACTIVE, item1.status);
 
   ash::wm::ActivateWindow(browser()->window()->GetNativeWindow());
   EXPECT_EQ(ash::STATUS_RUNNING,
-            launcher_->model()->ItemByID(item_id1)->status);
+            launcher_model()->ItemByID(item_id1)->status);
 }
 
 // Test that we can launch an app with a shortcut.