Remove Shell::shelf|status_area_widget|launcher and
updated all clients to use one on RootWindowController and/or
Launcher::ForPrimaryDisplay/ForWindow.

BUG=145978

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162664 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index f4e8f26a..08232a2b 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -88,7 +88,7 @@
 }
 
 void HandleCycleWindowLinear(CycleDirection direction) {
-  Shell::GetInstance()->launcher()->CycleWindowLinear(direction);
+  Launcher::ForPrimaryDisplay()->CycleWindowLinear(direction);
 }
 
 #if defined(OS_CHROMEOS)
@@ -602,8 +602,8 @@
           HandleVolumeUp(accelerator);
       break;
     case FOCUS_LAUNCHER:
-      if (shell->launcher())
-        return shell->focus_cycler()->FocusWidget(shell->launcher()->widget());
+      return shell->focus_cycler()->FocusWidget(
+          Launcher::ForPrimaryDisplay()->widget());
       break;
     case FOCUS_NEXT_PANE:
       return HandleRotatePaneFocus(Shell::FORWARD);
@@ -851,10 +851,9 @@
 }
 
 void AcceleratorController::SwitchToWindow(int window) {
-  const LauncherItems& items =
-      Shell::GetInstance()->launcher()->model()->items();
-  int item_count =
-      Shell::GetInstance()->launcher()->model()->item_count();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
+  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;
 
@@ -875,7 +874,7 @@
       (items[found_index].status == ash::STATUS_RUNNING ||
        items[found_index].status == ash::STATUS_CLOSED)) {
     // Then set this one as active.
-    Shell::GetInstance()->launcher()->ActivateLauncherItem(found_index);
+    launcher->ActivateLauncherItem(found_index);
   }
 }
 
diff --git a/ash/dip_unittest.cc b/ash/dip_unittest.cc
index 2a311d54..8ac0adb 100644
--- a/ash/dip_unittest.cc
+++ b/ash/dip_unittest.cc
@@ -63,7 +63,7 @@
 
   // Sanity check if the workarea's inset hight is same as
   // the launcher's height.
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   EXPECT_EQ(
       display_2x.bounds().InsetsFrom(work_area).height(),
       launcher->widget()->GetNativeView()->layer()->bounds().height());
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index 28d7ad8..5d98027b 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -205,7 +205,7 @@
       display_controller->GetRootWindowForDisplayId(secondary_display.id());
   EXPECT_NE(primary_root, secondary_root);
   aura::Window* launcher_window =
-      Shell::GetInstance()->launcher()->widget()->GetNativeView();
+      Launcher::ForPrimaryDisplay()->widget()->GetNativeView();
   EXPECT_TRUE(primary_root->Contains(launcher_window));
   EXPECT_FALSE(secondary_root->Contains(launcher_window));
   EXPECT_EQ(primary_display.id(),
@@ -277,7 +277,7 @@
   aura::RootWindow* secondary_root =
       display_controller->GetRootWindowForDisplayId(secondary_display.id());
   aura::Window* launcher_window =
-      Shell::GetInstance()->launcher()->widget()->GetNativeView();
+      Launcher::ForPrimaryDisplay()->widget()->GetNativeView();
   EXPECT_TRUE(primary_root->Contains(launcher_window));
   EXPECT_FALSE(secondary_root->Contains(launcher_window));
   EXPECT_NE(primary_root, secondary_root);
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc
index 19166a0..f694f45 100644
--- a/ash/focus_cycler_unittest.cc
+++ b/ash/focus_cycler_unittest.cc
@@ -68,7 +68,7 @@
       focus_cycler.get());
 
   // Add the launcher
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
@@ -103,7 +103,7 @@
       focus_cycler.get());
 
   // Add the launcher
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
@@ -138,7 +138,7 @@
       focus_cycler.get());
 
   // Add the launcher
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
@@ -185,7 +185,7 @@
       focus_cycler.get());
 
   // Add the launcher and focus it
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
@@ -222,7 +222,7 @@
     AshTestBase::SetUp();
 
     // Hide the launcher
-    Launcher* launcher = Shell::GetInstance()->launcher();
+    Launcher* launcher = Launcher::ForPrimaryDisplay();
     ASSERT_TRUE(launcher);
     views::Widget* launcher_widget = launcher->widget();
     ASSERT_TRUE(launcher_widget);
@@ -231,7 +231,7 @@
 
   virtual void TearDown() OVERRIDE {
     // Show the launcher
-    Launcher* launcher = Shell::GetInstance()->launcher();
+    Launcher* launcher = Launcher::ForPrimaryDisplay();
     ASSERT_TRUE(launcher);
     views::Widget* launcher_widget = launcher->widget();
     ASSERT_TRUE(launcher_widget);
@@ -255,7 +255,7 @@
       focus_cycler.get());
 
   // Add the launcher
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
@@ -286,7 +286,7 @@
       focus_cycler.get());
 
   // Add the launcher
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   views::Widget* launcher_widget = launcher->widget();
   ASSERT_TRUE(launcher_widget);
diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc
index 338819a8..da951599 100644
--- a/ash/launcher/launcher.cc
+++ b/ash/launcher/launcher.cc
@@ -12,12 +12,14 @@
 #include "ash/launcher/launcher_model.h"
 #include "ash/launcher/launcher_navigator.h"
 #include "ash/launcher/launcher_view.h"
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/shell_window_ids.h"
 #include "ash/wm/shelf_layout_manager.h"
 #include "ash/wm/window_properties.h"
 #include "grit/ash_resources.h"
+#include "ui/aura/root_window.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -238,6 +240,17 @@
 Launcher::~Launcher() {
 }
 
+// static
+Launcher* Launcher::ForPrimaryDisplay() {
+  return internal::RootWindowController::ForLauncher(
+      Shell::GetPrimaryRootWindow())->launcher();
+}
+
+// static
+Launcher* Launcher::ForWindow(aura::Window* window) {
+  return internal::RootWindowController::ForLauncher(window)->launcher();
+}
+
 void Launcher::SetFocusCycler(internal::FocusCycler* focus_cycler) {
   delegate_view_->set_focus_cycler(focus_cycler);
   focus_cycler->AddWidget(widget_.get());
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index 452730f3..64a6a47 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -44,6 +44,15 @@
            internal::ShelfLayoutManager* shelf_layout_manager);
   virtual ~Launcher();
 
+  // Return the launcher for the primary display. NULL if no user is
+  // logged in yet.
+  static Launcher* ForPrimaryDisplay();
+
+  // Return the launcher for the display that |window| is currently on,
+  // or a launcher on primary display if the launcher per display feature
+  // is disabled. NULL if no user is logged in yet.
+  static Launcher* ForWindow(aura::Window* window);
+
   // Sets the focus cycler.  Also adds the launcher to the cycle.
   void SetFocusCycler(internal::FocusCycler* focus_cycler);
   internal::FocusCycler* GetFocusCycler();
diff --git a/ash/launcher/launcher_tooltip_manager_unittest.cc b/ash/launcher/launcher_tooltip_manager_unittest.cc
index 17f72da..8d63320 100644
--- a/ash/launcher/launcher_tooltip_manager_unittest.cc
+++ b/ash/launcher/launcher_tooltip_manager_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "ash/launcher/launcher_tooltip_manager.h"
 
+#include "ash/root_window_controller.h"
+#include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/shelf_layout_manager.h"
 #include "ash/wm/window_util.h"
@@ -26,11 +28,12 @@
 
   virtual void SetUp() OVERRIDE {
     AshTestBase::SetUp();
-
+    internal::RootWindowController* controller =
+        Shell::GetPrimaryRootWindowController();
     tooltip_manager_.reset(new internal::LauncherTooltipManager(
         SHELF_ALIGNMENT_BOTTOM,
-        Shell::GetInstance()->shelf(),
-        Shell::GetInstance()->launcher()->GetLauncherViewForTest()));
+        controller->shelf(),
+        controller->launcher()->GetLauncherViewForTest()));
   }
 
   virtual void TearDown() OVERRIDE {
@@ -96,8 +99,9 @@
   widget->Show();
 
   // Once the shelf is hidden, the tooltip should be invisible.
-  ASSERT_EQ(internal::ShelfLayoutManager::HIDDEN,
-            Shell::GetInstance()->shelf()->visibility_state());
+  ASSERT_EQ(
+      internal::ShelfLayoutManager::HIDDEN,
+      Shell::GetPrimaryRootWindowController()->shelf()->visibility_state());
   EXPECT_FALSE(TooltipIsVisible());
 
   // Do not show the view if the shelf is hidden.
@@ -113,7 +117,8 @@
   ShowImmediately();
   ASSERT_TRUE(TooltipIsVisible());
 
-  internal::ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  internal::ShelfLayoutManager* shelf =
+      Shell::GetPrimaryRootWindowController()->shelf();
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   shelf->UpdateAutoHideState();
   ASSERT_EQ(internal::ShelfLayoutManager::AUTO_HIDE_HIDDEN,
diff --git a/ash/launcher/launcher_unittest.cc b/ash/launcher/launcher_unittest.cc
index 3e21807..cbf8229 100644
--- a/ash/launcher/launcher_unittest.cc
+++ b/ash/launcher/launcher_unittest.cc
@@ -22,7 +22,7 @@
 // Makes sure invoking SetStatusSize on the launcher changes the size of the
 // LauncherView.
 TEST_F(LauncherTest, SetStatusSize) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   LauncherView* launcher_view = launcher->GetLauncherViewForTest();
 
   gfx::Size launcher_size =
@@ -35,7 +35,7 @@
 
 // Tests that the dimmer widget resizes itself as appropriate.
 TEST_F(LauncherTest, DimmerSize) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   launcher->SetDimsShelf(true);
 
   gfx::Size launcher_size =
@@ -54,7 +54,7 @@
 // Confirm that launching a browser gets the appropriate state reflected in
 // its button.
 TEST_F(LauncherTest, OpenBrowser) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   LauncherView* launcher_view = launcher->GetLauncherViewForTest();
   test::LauncherViewTestAPI test(launcher_view);
diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc
index 27623b5..5296d8d9 100644
--- a/ash/launcher/launcher_view_unittest.cc
+++ b/ash/launcher/launcher_view_unittest.cc
@@ -74,8 +74,7 @@
 
   virtual void SetUp() OVERRIDE {
     AshTestBase::SetUp();
-
-    Launcher* launcher = Shell::GetInstance()->launcher();
+    Launcher* launcher = Launcher::ForPrimaryDisplay();
     observer_.reset(new TestLauncherIconObserver(launcher));
 
     launcher_view_test_.reset(new LauncherViewTestAPI(
@@ -125,7 +124,7 @@
 }
 
 TEST_F(LauncherViewIconObserverTest, BoundsChanged) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   gfx::Size launcher_size =
       launcher->widget()->GetWindowBoundsInScreen().size();
   int total_width = launcher_size.width() / 2;
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 8640429..800db1dd 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -161,6 +161,15 @@
   root_window_.reset();
 }
 
+// static
+internal::RootWindowController*
+RootWindowController::ForLauncher(aura::Window* window) {
+  if (Shell::IsLauncherPerDisplayEnabled())
+    return GetRootWindowController(window->GetRootWindow());
+  else
+    return Shell::GetPrimaryRootWindowController();
+}
+
 void RootWindowController::Shutdown() {
   CloseChildWindows();
   if (Shell::GetActiveRootWindow() == root_window_.get()) {
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 07f08b4..27132ac 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -48,6 +48,12 @@
   explicit RootWindowController(aura::RootWindow* root_window);
   ~RootWindowController();
 
+  // Returns a RootWindowController that has a launcher for given
+  // |window|. This returns the RootWindowController for the |window|'s
+  // root window when multiple launcher mode is enabled, or the primary
+  // RootWindowController otherwise.
+  static RootWindowController* ForLauncher(aura::Window* window);
+
   aura::RootWindow* root_window() { return root_window_.get(); }
 
   RootWindowLayoutManager* root_window_layout() { return root_window_layout_; }
@@ -60,10 +66,9 @@
 
   Launcher* launcher() { return launcher_.get(); }
 
-  // TODO(sky): don't expose this!
-  internal::ShelfLayoutManager* shelf() const { return shelf_; }
+  ShelfLayoutManager* shelf() const { return shelf_; }
 
-  internal::StatusAreaWidget* status_area_widget() const {
+  StatusAreaWidget* status_area_widget() const {
     return status_area_widget_;
   }
 
@@ -131,15 +136,15 @@
   RootWindowLayoutManager* root_window_layout_;
 
   // Widget containing system tray.
-  internal::StatusAreaWidget* status_area_widget_;
+  StatusAreaWidget* status_area_widget_;
 
   // The shelf for managing the launcher and the status widget.
   // RootWindowController does not own the shelf. Instead, it is owned
   // by container of the status area.
-  internal::ShelfLayoutManager* shelf_;
+  ShelfLayoutManager* shelf_;
 
   // Manages layout of panels. Owned by PanelContainer.
-  internal::PanelLayoutManager* panel_layout_manager_;
+  PanelLayoutManager* panel_layout_manager_;
 
   scoped_ptr<Launcher> launcher_;
 
diff --git a/ash/screen_ash.cc b/ash/screen_ash.cc
index 4c7e1db..41053bd 100644
--- a/ash/screen_ash.cc
+++ b/ash/screen_ash.cc
@@ -6,7 +6,9 @@
 
 #include "ash/display/display_controller.h"
 #include "ash/display/multi_display_manager.h"
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
+#include "ash/wm/property_util.h"
 #include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/shelf_layout_manager.h"
 #include "base/logging.h"
@@ -39,7 +41,7 @@
 
 // static
 gfx::Rect ScreenAsh::GetMaximizedWindowBoundsInParent(aura::Window* window) {
-  if (window->GetRootWindow() == Shell::GetPrimaryRootWindow())
+  if (GetRootWindowController(window->GetRootWindow())->launcher())
     return GetDisplayWorkAreaBoundsInParent(window);
   else
     return GetDisplayBoundsInParent(window);
diff --git a/ash/shell.cc b/ash/shell.cc
index 90036a98..836861e 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -35,6 +35,7 @@
 #include "ash/wm/app_list_controller.h"
 #include "ash/wm/base_layout_manager.h"
 #include "ash/wm/capture_controller.h"
+#include "ash/wm/coordinate_conversion.h"
 #include "ash/wm/custom_frame_view_ash.h"
 #include "ash/wm/dialog_frame_view.h"
 #include "ash/wm/event_client_impl.h"
@@ -513,8 +514,9 @@
   // No context menus when screen is locked.
   if (IsScreenLocked())
     return;
-  if (launcher())
-    launcher()->ShowContextMenu(location);
+  aura::RootWindow* root =
+      wm::GetRootWindowMatching(gfx::Rect(location, gfx::Size()));
+  Launcher::ForWindow(root)->ShowContextMenu(location);
 }
 
 void Shell::ToggleAppList() {
@@ -580,6 +582,11 @@
   ash::Shell::GetInstance()->UpdateShelfVisibility();
 }
 
+void Shell::UpdateAfterLoginStatusChange(user::LoginStatus status) {
+  GetPrimaryRootWindowController()->status_area_widget()->
+      UpdateAfterLoginStatusChange(status);
+}
+
 void Shell::OnAppTerminating() {
   FOR_EACH_OBSERVER(ShellObserver, observers_, OnAppTerminating());
 }
@@ -604,11 +611,8 @@
   observers_.RemoveObserver(observer);
 }
 
-Launcher* Shell::launcher() {
-  return GetPrimaryRootWindowController()->launcher();
-}
-
 void Shell::UpdateShelfVisibility() {
+  // TODO(oshima): Update all root windows.
   GetPrimaryRootWindowController()->UpdateShelfVisibility();
 }
 
@@ -665,22 +669,22 @@
   }
 }
 
-internal::ShelfLayoutManager* Shell::shelf() const {
-  return GetPrimaryRootWindowController()->shelf();
-}
-
-internal::StatusAreaWidget* Shell::status_area_widget() const {
-  return GetPrimaryRootWindowController()->status_area_widget();
+WebNotificationTray* Shell::GetWebNotificationTray() {
+  return GetPrimaryRootWindowController()->status_area_widget()->
+      web_notification_tray();
 }
 
 SystemTrayDelegate* Shell::tray_delegate() {
-  return status_area_widget() ? status_area_widget()->system_tray_delegate() :
-                                NULL;
+  // TODO(oshima): Decouple system tray and its delegate.
+  internal::StatusAreaWidget* status_area_widget =
+      GetPrimaryRootWindowController()->status_area_widget();
+  return status_area_widget ? status_area_widget->system_tray_delegate() : NULL;
 }
 
 SystemTray* Shell::system_tray() {
-  return status_area_widget() ? status_area_widget()->system_tray() :
-                                NULL;
+  internal::StatusAreaWidget* status_area_widget =
+      GetPrimaryRootWindowController()->status_area_widget();
+  return status_area_widget ? status_area_widget->system_tray() : NULL;
 }
 
 void Shell::InitRootWindowForSecondaryDisplay(aura::RootWindow* root) {
diff --git a/ash/shell.h b/ash/shell.h
index dbcc2fd70..4f4586a 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -75,6 +75,7 @@
 class UserActivityDetector;
 class UserWallpaperDelegate;
 class VideoDetector;
+class WebNotificationTray;
 class WindowCycleController;
 
 namespace internal {
@@ -237,6 +238,10 @@
   // Called when the user logs in.
   void OnLoginStateChanged(user::LoginStatus status);
 
+  // Called when the login status changes.
+  // TODO(oshima): Investigate if we can merge this and |OnLoginStateChanged|.
+  void UpdateAfterLoginStatusChange(user::LoginStatus status);
+
   // Called when the application is exiting.
   void OnAppTerminating();
 
@@ -316,9 +321,6 @@
     return magnification_controller_.get();
   }
 
-  // TODO(oshima): Remove methods that are moved to RootWindowController.
-  Launcher* launcher();
-
   const ScreenAsh* screen() { return screen_.get(); }
 
   // Force the shelf to query for it's current visibility state.
@@ -343,10 +345,8 @@
   // on all displays.
   void OnModalWindowRemoved(aura::Window* removed);
 
-  // TODO(sky): don't expose this!
-  internal::ShelfLayoutManager* shelf() const;
-
-  internal::StatusAreaWidget* status_area_widget() const;
+  // Returns WebNotificationTray on the primary root window.
+  WebNotificationTray* GetWebNotificationTray();
 
   // Convenience accessor for members of StatusAreaWidget.
   SystemTrayDelegate* tray_delegate();
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc
index fa9a7e49..df45d89 100644
--- a/ash/shell/window_type_launcher.cc
+++ b/ash/shell/window_type_launcher.cc
@@ -4,6 +4,7 @@
 
 #include "ash/shell/window_type_launcher.h"
 
+#include "ash/root_window_controller.h"
 #include "ash/screensaver/screensaver_view.h"
 #include "ash/shell.h"
 #include "ash/shell/example_factory.h"
@@ -327,7 +328,7 @@
                                             base::TimeDelta::FromSeconds(5));
 
   } else if (sender == show_web_notification_) {
-    ash::Shell::GetInstance()->status_area_widget()->
+    ash::Shell::GetPrimaryRootWindowController()->status_area_widget()->
         web_notification_tray()->AddNotification(
             "id0",
             ASCIIToUTF16("Test Shell Web Notification"),
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc
index a85d8f6c..97fee7d7 100644
--- a/ash/shell/window_watcher.cc
+++ b/ash/shell/window_watcher.cc
@@ -8,6 +8,7 @@
 #include "ash/launcher/launcher_model.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
+#include "ui/aura/root_window.h"
 #include "ui/aura/window.h"
 
 namespace ash {
@@ -43,9 +44,9 @@
 };
 
 WindowWatcher::WindowWatcher()
-    : window_(ash::Shell::GetInstance()->launcher()->window_container()),
+    : window_(Launcher::ForPrimaryDisplay()->window_container()),
       panel_container_(ash::Shell::GetContainer(
-          Shell::GetPrimaryRootWindow(),
+          window_->GetRootWindow(),
           internal::kShellWindowId_PanelContainer)) {
   workspace_window_watcher_.reset(new WorkspaceWindowWatcher(this));
   panel_container_->AddObserver(this);
@@ -76,7 +77,7 @@
     return;
 
   static int image_count = 0;
-  ash::LauncherModel* model = ash::Shell::GetInstance()->launcher()->model();
+  ash::LauncherModel* model = Launcher::ForPrimaryDisplay()->model();
   ash::LauncherItem item;
   item.type = ash::TYPE_TABBED;
   id_to_window_[model->next_id()] = new_window;
@@ -99,8 +100,7 @@
   for (IDToWindow::iterator i = id_to_window_.begin();
        i != id_to_window_.end(); ++i) {
     if (i->second == window) {
-      ash::LauncherModel* model =
-          ash::Shell::GetInstance()->launcher()->model();
+      ash::LauncherModel* model = Launcher::ForPrimaryDisplay()->model();
       int index = model->ItemIndexByID(i->first);
       DCHECK_NE(-1, index);
       model->RemoveItemAt(index);
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc
index 131d500..d939cdb 100644
--- a/ash/shell_unittest.cc
+++ b/ash/shell_unittest.cc
@@ -10,6 +10,7 @@
 #include "ash/ash_switches.h"
 #include "ash/desktop_background/desktop_background_widget_controller.h"
 #include "ash/launcher/launcher.h"
+#include "ash/root_window_controller.h"
 #include "ash/shell_delegate.h"
 #include "ash/shell_window_ids.h"
 #include "ash/test/ash_test_base.h"
@@ -277,7 +278,7 @@
   // We start with the usual window containers.
   ExpectAllContainers();
   // Launcher is visible.
-  views::Widget* launcher_widget = shell->launcher()->widget();
+  views::Widget* launcher_widget = Launcher::ForPrimaryDisplay()->widget();
   EXPECT_TRUE(launcher_widget->IsVisible());
   // Launcher is at bottom-left of screen.
   EXPECT_EQ(0, launcher_widget->GetWindowBoundsInScreen().x());
@@ -316,18 +317,21 @@
   EXPECT_FALSE(widget->IsMaximized());
 
   // Shelf defaults to visible.
-  EXPECT_EQ(internal::ShelfLayoutManager::VISIBLE,
-            Shell::GetInstance()->shelf()->visibility_state());
+  EXPECT_EQ(
+      internal::ShelfLayoutManager::VISIBLE,
+      Shell::GetPrimaryRootWindowController()->shelf()->visibility_state());
 
   // Fullscreen window hides it.
   widget->SetFullscreen(true);
-  EXPECT_EQ(internal::ShelfLayoutManager::HIDDEN,
-            Shell::GetInstance()->shelf()->visibility_state());
+  EXPECT_EQ(
+      internal::ShelfLayoutManager::HIDDEN,
+      Shell::GetPrimaryRootWindowController()->shelf()->visibility_state());
 
   // Restoring the window restores it.
   widget->Restore();
-  EXPECT_EQ(internal::ShelfLayoutManager::VISIBLE,
-            Shell::GetInstance()->shelf()->visibility_state());
+  EXPECT_EQ(
+      internal::ShelfLayoutManager::VISIBLE,
+      Shell::GetPrimaryRootWindowController()->shelf()->visibility_state());
 
   // Clean up.
   widget->Close();
diff --git a/ash/system/ime/tray_ime.cc b/ash/system/ime/tray_ime.cc
index 6abcd81..34682a2 100644
--- a/ash/system/ime/tray_ime.cc
+++ b/ash/system/ime/tray_ime.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/system/tray/system_tray_delegate.h"
@@ -335,7 +336,8 @@
     // refreshed.
     if (notification_) {
       notification_->UpdateLabel();
-    } else if (!Shell::GetInstance()->shelf()->IsVisible() || !message_shown_) {
+    } else if (!Shell::GetPrimaryRootWindowController()->shelf()->IsVisible() ||
+               !message_shown_) {
       ShowNotificationView();
       message_shown_ = true;
     }
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc
index 59f91a7a..afb086a 100644
--- a/ash/system/status_area_widget.cc
+++ b/ash/system/status_area_widget.cc
@@ -351,7 +351,7 @@
        web_notification_tray_->IsMessageCenterBubbleVisible()))
     return true;
 
-  if (!Shell::GetInstance()->shelf()->IsVisible())
+  if (!RootWindowController::ForLauncher(GetNativeView())->shelf()->IsVisible())
     return false;
 
   // If the launcher is currently visible, don't hide the launcher if the mouse
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index 56b7e9c5..ecae854 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -345,7 +345,7 @@
 
   UpdateNotificationBubble();  // State changed, re-create notifications.
   status_area_widget()->SetHideWebNotifications(true);
-  Shell::GetInstance()->shelf()->UpdateAutoHideState();
+  GetShelfLayoutManager()->UpdateAutoHideState();
 }
 
 void SystemTray::UpdateNotificationBubble() {
@@ -444,7 +444,7 @@
   if (bubble_.get() && bubble_view == bubble_->bubble_view()) {
     DestroyBubble();
     UpdateNotificationBubble();  // State changed, re-create notifications.
-    Shell::GetInstance()->shelf()->UpdateAutoHideState();
+    GetShelfLayoutManager()->UpdateAutoHideState();
   } else if (notification_bubble_.get() &&
              bubble_view == notification_bubble_->bubble_view()) {
     DestroyNotificationBubble();
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc
index b03c548..54f34b8 100644
--- a/ash/system/tray/system_tray_unittest.cc
+++ b/ash/system/tray/system_tray_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/root_window_controller.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/system_tray_item.h"
 #include "ash/test/ash_test_base.h"
@@ -21,7 +22,8 @@
 namespace {
 
 SystemTray* GetSystemTray() {
-  return Shell::GetInstance()->status_area_widget()->system_tray();
+  return Shell::GetPrimaryRootWindowController()->status_area_widget()->
+      system_tray();
 }
 
 // Trivial item implementation that tracks its views for testing.
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index ef360c7..3a4ef7a 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -5,6 +5,7 @@
 #include "ash/system/tray/tray_background_view.h"
 
 #include "ash/launcher/background_animator.h"
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
 #include "ash/system/status_area_widget.h"
@@ -254,6 +255,11 @@
   hide_background_animator_.SetPaintsBackground(value, change_type);
 }
 
+ShelfLayoutManager* TrayBackgroundView::GetShelfLayoutManager() {
+  return
+      RootWindowController::ForLauncher(GetWidget()->GetNativeView())->shelf();
+}
+
 void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) {
   shelf_alignment_ = alignment;
   SetBorder();
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h
index 2d496a55..416393a 100644
--- a/ash/system/tray/tray_background_view.h
+++ b/ash/system/tray/tray_background_view.h
@@ -14,6 +14,7 @@
 namespace ash {
 namespace internal {
 
+class ShelfLayoutManager;
 class StatusAreaWidget;
 class TrayBackground;
 class TrayLayerAnimationObserver;
@@ -130,6 +131,8 @@
   TrayContainer* tray_container() const { return tray_container_; }
   ShelfAlignment shelf_alignment() const { return shelf_alignment_; }
 
+  ShelfLayoutManager* GetShelfLayoutManager();
+
  private:
   friend class TrayLayerAnimationObserver;
 
diff --git a/ash/system/tray_update.cc b/ash/system/tray_update.cc
index cc39e475..7530a8b 100644
--- a/ash/system/tray_update.cc
+++ b/ash/system/tray_update.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/tray_update.h"
 
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/system/tray/system_tray_delegate.h"
@@ -125,7 +126,9 @@
   // Overridden from ui::LayerAnimationObserver.
   virtual void OnLayerAnimationEnded(
       ui::LayerAnimationSequence* sequence) OVERRIDE {
-    if (Shell::GetInstance()->shelf()->IsVisible())
+    // TODO(oshima): Find out if the updator will be shown on non
+    // primary display.
+    if (Shell::GetPrimaryRootWindowController()->shelf()->IsVisible())
       timer_.Stop();
     else if (!timer_.IsRunning())
       RestartTimer();
@@ -180,7 +183,8 @@
   severity_ = severity;
   SetImageFromResourceId(DecideResource(severity_, false));
   tray_view()->SetVisible(true);
-  if (!Shell::GetInstance()->shelf()->IsVisible() && !nagger_.get()) {
+  if (!Shell::GetPrimaryRootWindowController()->shelf()->IsVisible() &&
+      !nagger_.get()) {
     // The shelf is not visible, and there is no nagger scheduled.
     nagger_.reset(new tray::UpdateNagger(this));
   }
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index b904c33..baf9f01 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -138,7 +138,7 @@
   HidePopupBubble();
   message_center_bubble_.reset(new MessageCenterBubble(this));
   status_area_widget()->SetHideSystemNotifications(true);
-  Shell::GetInstance()->shelf()->UpdateAutoHideState();
+  GetShelfLayoutManager()->UpdateAutoHideState();
 }
 
 void WebNotificationTray::HideMessageCenterBubble() {
@@ -149,7 +149,7 @@
   notification_list_->SetMessageCenterVisible(false);
   UpdateTray();
   status_area_widget()->SetHideSystemNotifications(false);
-  Shell::GetInstance()->shelf()->UpdateAutoHideState();
+  GetShelfLayoutManager()->UpdateAutoHideState();
 }
 
 void WebNotificationTray::SetHidePopupBubble(bool hide) {
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc
index 3ac88a80..0de2575 100644
--- a/ash/system/web_notification/web_notification_tray_unittest.cc
+++ b/ash/system/web_notification/web_notification_tray_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/root_window_controller.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/system_tray_item.h"
 #include "ash/test/ash_test_base.h"
@@ -21,7 +22,8 @@
 namespace {
 
 WebNotificationTray* GetWebNotificationTray() {
-  return Shell::GetInstance()->status_area_widget()->web_notification_tray();
+  return Shell::GetPrimaryRootWindowController()->status_area_widget()->
+      web_notification_tray();
 }
 
 class TestDelegate : public WebNotificationTray::Delegate {
diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc
index c3d1840e..f7f7390 100644
--- a/ash/wm/app_list_controller.cc
+++ b/ash/wm/app_list_controller.cc
@@ -115,7 +115,7 @@
 
   // App list needs to know the new shelf layout in order to calculate its
   // UI layout when AppListView visibility changes.
-  Shell::GetInstance()->shelf()->UpdateAutoHideState();
+  Shell::GetPrimaryRootWindowController()->shelf()->UpdateAutoHideState();
 
   if (view_) {
     ScheduleAnimation();
@@ -128,7 +128,7 @@
         Shell::GetPrimaryRootWindowController()->GetContainer(
             kShellWindowId_AppListContainer),
         pagination_model_.get(),
-        Shell::GetInstance()->launcher()->GetAppListButtonView(),
+        Launcher::ForWindow(GetWindow())->GetAppListButtonView(),
         gfx::Point(),
         GetBubbleArrowLocation());
     SetView(view);
@@ -154,7 +154,7 @@
     views::Widget* widget = view_->GetWidget();
     widget->AddObserver(this);
     Shell::GetInstance()->AddEnvEventFilter(this);
-    Shell::GetInstance()->launcher()->AddIconObserver(this);
+    Launcher::ForWindow(GetWindow())->AddIconObserver(this);
     widget->GetNativeView()->GetRootWindow()->AddRootWindowObserver(this);
     widget->GetNativeView()->GetFocusManager()->AddObserver(this);
     widget->SetOpacity(0);
@@ -174,7 +174,7 @@
   widget->RemoveObserver(this);
   GetLayer(widget)->GetAnimator()->RemoveObserver(this);
   Shell::GetInstance()->RemoveEnvEventFilter(this);
-  Shell::GetInstance()->launcher()->RemoveIconObserver(this);
+  Launcher::ForWindow(GetWindow())->RemoveIconObserver(this);
   widget->GetNativeView()->GetRootWindow()->RemoveRootWindowObserver(this);
   widget->GetNativeView()->GetFocusManager()->RemoveObserver(this);
   view_ = NULL;
diff --git a/ash/wm/gestures/shelf_gesture_handler.cc b/ash/wm/gestures/shelf_gesture_handler.cc
index 9ac8f93..4bf4a39b 100644
--- a/ash/wm/gestures/shelf_gesture_handler.cc
+++ b/ash/wm/gestures/shelf_gesture_handler.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/gestures/shelf_gesture_handler.h"
 
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/system/status_area_widget.h"
@@ -40,7 +41,8 @@
   if (active && wm::IsWindowFullscreen(active))
     return false;
 
-  ShelfLayoutManager* shelf = shell->shelf();
+  // TODO(oshima): Find the root window controller from event's location.
+  ShelfLayoutManager* shelf = Shell::GetPrimaryRootWindowController()->shelf();
   if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) {
     drag_in_progress_ = true;
     shelf->StartGestureDrag(event);
diff --git a/ash/wm/gestures/system_pinch_handler.cc b/ash/wm/gestures/system_pinch_handler.cc
index d974add..2f519b0 100644
--- a/ash/wm/gestures/system_pinch_handler.cc
+++ b/ash/wm/gestures/system_pinch_handler.cc
@@ -136,7 +136,7 @@
       return window->bounds();
     }
 
-    Launcher* launcher = Shell::GetInstance()->launcher();
+    Launcher* launcher = Launcher::ForWindow(window);
     gfx::Rect rect = launcher->GetScreenBoundsOfItemIconForWindow(target_);
     if (rect.IsEmpty())
       rect = launcher->widget()->GetWindowBoundsInScreen();
diff --git a/ash/wm/panel_layout_manager_unittest.cc b/ash/wm/panel_layout_manager_unittest.cc
index f38ed9f4f..bcd9601f 100644
--- a/ash/wm/panel_layout_manager_unittest.cc
+++ b/ash/wm/panel_layout_manager_unittest.cc
@@ -33,9 +33,8 @@
     ash::test::AshTestBase::SetUp();
     ASSERT_TRUE(ash::test::TestLauncherDelegate::instance());
 
-    Launcher* launcher = Shell::GetInstance()->launcher();
     launcher_view_test_.reset(new test::LauncherViewTestAPI(
-        launcher->GetLauncherViewForTest()));
+        Launcher::ForPrimaryDisplay()->GetLauncherViewForTest()));
     launcher_view_test_->SetAnimationDuration(1);
   }
 
@@ -79,7 +78,7 @@
     // Waits until all launcher view animations are done.
     launcher_view_test()->RunMessageLoopUntilAnimationsDone();
 
-    Launcher* launcher = Shell::GetInstance()->launcher();
+    Launcher* launcher = Launcher::ForPrimaryDisplay();
     gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel);
     ASSERT_FALSE(icon_bounds.IsEmpty());
 
diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc
index 31eb4ba..8aff1ae 100644
--- a/ash/wm/shelf_layout_manager.cc
+++ b/ash/wm/shelf_layout_manager.cc
@@ -9,6 +9,7 @@
 
 #include "ash/ash_switches.h"
 #include "ash/launcher/launcher.h"
+#include "ash/root_window_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
@@ -172,13 +173,13 @@
 
 // ShelfLayoutManager ----------------------------------------------------------
 
-ShelfLayoutManager::ShelfLayoutManager(views::Widget* status)
-    : root_window_(Shell::GetPrimaryRootWindow()),
+ShelfLayoutManager::ShelfLayoutManager(StatusAreaWidget* status_area_widget)
+    : root_window_(status_area_widget->GetNativeView()->GetRootWindow()),
       in_layout_(false),
       auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER),
       alignment_(SHELF_ALIGNMENT_BOTTOM),
       launcher_(NULL),
-      status_(status),
+      status_area_widget_(status_area_widget),
       workspace_controller_(NULL),
       window_overlaps_shelf_(false),
       gesture_drag_status_(GESTURE_DRAG_NONE),
@@ -208,9 +209,10 @@
 }
 
 bool ShelfLayoutManager::IsVisible() const {
-  return status_->IsVisible() && (state_.visibility_state == VISIBLE ||
-      (state_.visibility_state == AUTO_HIDE &&
-       state_.auto_hide_state == AUTO_HIDE_SHOWN));
+  return status_area_widget_->IsVisible() &&
+      (state_.visibility_state == VISIBLE ||
+       (state_.visibility_state == AUTO_HIDE &&
+        state_.auto_hide_state == AUTO_HIDE_SHOWN));
 }
 
 void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
@@ -230,10 +232,7 @@
   alignment_ = alignment;
   if (launcher_)
     launcher_->SetAlignment(alignment);
-  StatusAreaWidget* status_area_widget =
-      Shell::GetInstance()->status_area_widget();
-  if (status_area_widget)
-    Shell::GetInstance()->status_area_widget()->SetShelfAlignment(alignment);
+  status_area_widget_->SetShelfAlignment(alignment);
   LayoutShelf();
   return true;
 }
@@ -242,7 +241,7 @@
   // TODO(oshima): this is wrong. Figure out what display shelf is on
   // and everything should be based on it.
   gfx::Rect bounds(ScreenAsh::GetDisplayBoundsInParent(
-      status_->GetNativeView()));
+      status_area_widget_->GetNativeView()));
   int width = 0, height = 0;
   GetShelfSize(&width, &height);
   switch (alignment_) {
@@ -272,10 +271,10 @@
             target_bounds.launcher_bounds_in_root));
     launcher_->SetStatusSize(target_bounds.status_bounds_in_root.size());
   }
-  GetLayer(status_)->SetOpacity(target_bounds.opacity);
-  status_->SetBounds(
+  GetLayer(status_area_widget_)->SetOpacity(target_bounds.opacity);
+  status_area_widget_->SetBounds(
       ScreenAsh::ConvertRectToScreen(
-          status_->GetNativeView()->parent(),
+          status_area_widget_->GetNativeView()->parent(),
           target_bounds.status_bounds_in_root));
   Shell::GetInstance()->SetDisplayWorkAreaInsets(
       Shell::GetPrimaryRootWindow(),
@@ -376,7 +375,8 @@
           GetPreferredSize().height();
 
     if (min_height < launcher_widget()->GetWindowBoundsInScreen().height() &&
-        gesture.root_location().x() >= status_->GetWindowBoundsInScreen().x() &&
+        gesture.root_location().x() >=
+        status_area_widget_->GetWindowBoundsInScreen().x() &&
         IsDraggingTrayEnabled())
       return DRAG_TRAY;
   }
@@ -423,7 +423,7 @@
                                                          AUTO_HIDE_SHOWN;
   if (launcher_widget())
     launcher_widget()->Deactivate();
-  status_->Deactivate();
+  status_area_widget_->Deactivate();
   if (gesture_drag_auto_hide_state_ == AUTO_HIDE_HIDDEN &&
       auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
     gesture_drag_status_ = GESTURE_DRAG_NONE;
@@ -443,7 +443,7 @@
   gesture_drag_status_ = GESTURE_DRAG_NONE;
   ui::ScopedLayerAnimationSettings
       launcher_settings(GetLayer(launcher_widget())->GetAnimator()),
-      status_settings(GetLayer(status_)->GetAnimator());
+      status_settings(GetLayer(status_area_widget_)->GetAnimator());
   LayoutShelf();
   UpdateVisibilityState();
   UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
@@ -476,7 +476,7 @@
   // effect the layout in anyway.
   if (!in_layout_ &&
       ((launcher_widget() && launcher_widget()->GetNativeView() == child) ||
-       (status_->GetNativeView() == child))) {
+       (status_area_widget_->GetNativeView() == child))) {
     LayoutShelf();
   }
 }
@@ -553,7 +553,7 @@
     GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
   }
   ui::ScopedLayerAnimationSettings status_animation_setter(
-      GetLayer(status_)->GetAnimator());
+      GetLayer(status_area_widget_)->GetAnimator());
   status_animation_setter.SetTransitionDuration(
       base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS));
   status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
@@ -580,8 +580,9 @@
     update_shelf_observer_ = new UpdateShelfObserver(this);
     status_animation_setter.AddObserver(update_shelf_observer_);
   }
-  GetLayer(status_)->SetBounds(target_bounds.status_bounds_in_root);
-  GetLayer(status_)->SetOpacity(target_bounds.opacity);
+  ui::Layer* layer = GetLayer(status_area_widget_);
+  layer->SetBounds(target_bounds.status_bounds_in_root);
+  layer->SetOpacity(target_bounds.opacity);
   Shell::GetInstance()->SetDisplayWorkAreaInsets(
       Shell::GetPrimaryRootWindow(),
       target_bounds.work_area_insets);
@@ -591,14 +592,15 @@
 }
 
 void ShelfLayoutManager::StopAnimating() {
+  ui::Layer* layer = GetLayer(status_area_widget_);
   if (launcher_widget())
-    GetLayer(launcher_widget())->GetAnimator()->StopAnimating();
-  GetLayer(status_)->GetAnimator()->StopAnimating();
+    layer->GetAnimator()->StopAnimating();
+  layer->GetAnimator()->StopAnimating();
 }
 
 void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
   *width = *height = 0;
-  gfx::Size status_size(status_->GetWindowBoundsInScreen().size());
+  gfx::Size status_size(status_area_widget_->GetWindowBoundsInScreen().size());
   gfx::Size launcher_size = launcher_ ?
       launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
   if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
@@ -625,9 +627,8 @@
 void ShelfLayoutManager::CalculateTargetBounds(
     const State& state,
     TargetBounds* target_bounds) {
-  const gfx::Rect& available_bounds(
-      status_->GetNativeView()->GetRootWindow()->bounds());
-  gfx::Rect status_size(status_->GetWindowBoundsInScreen().size());
+  const gfx::Rect& available_bounds(root_window_->bounds());
+  gfx::Rect status_size(status_area_widget_->GetWindowBoundsInScreen().size());
   gfx::Size launcher_size = launcher_ ?
       launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
   int shelf_size = 0;
@@ -787,15 +788,11 @@
     launcher_->SetPaintsBackground(launcher_paints, type);
   // The status area normally draws a background, but we don't want it to draw a
   // background when the launcher does or when we're at login/lock screen.
-  StatusAreaWidget* status_area_widget =
-      Shell::GetInstance()->status_area_widget();
-  if (status_area_widget) {
-    ShellDelegate* delegate = Shell::GetInstance()->delegate();
-    bool delegate_allows_tray_bg = !delegate ||
-        (delegate->IsUserLoggedIn() && !delegate->IsScreenLocked());
-    bool status_area_paints = !launcher_paints && delegate_allows_tray_bg;
-    status_area_widget->SetPaintsBackground(status_area_paints, type);
-  }
+  ShellDelegate* delegate = Shell::GetInstance()->delegate();
+  bool delegate_allows_tray_bg = !delegate ||
+      (delegate->IsUserLoggedIn() && !delegate->IsScreenLocked());
+  bool status_area_paints = !launcher_paints && delegate_allows_tray_bg;
+  status_area_widget_->SetPaintsBackground(status_area_paints, type);
 }
 
 bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
@@ -820,8 +817,7 @@
   if (shell->GetAppListTargetVisibility())
     return AUTO_HIDE_SHOWN;
 
-  if (shell->status_area_widget() &&
-      shell->status_area_widget()->ShouldShowLauncher())
+  if (status_area_widget_ && status_area_widget_->ShouldShowLauncher())
     return AUTO_HIDE_SHOWN;
 
   if (launcher_ && launcher_->IsShowingMenu())
@@ -830,7 +826,7 @@
   if (launcher_ && launcher_->IsShowingOverflowBubble())
     return AUTO_HIDE_SHOWN;
 
-  if (launcher_widget()->IsActive() || status_->IsActive())
+  if (launcher_widget()->IsActive() || status_area_widget_->IsActive())
     return AUTO_HIDE_SHOWN;
 
   // Don't show if the user is dragging the mouse.
@@ -838,8 +834,8 @@
     return AUTO_HIDE_HIDDEN;
 
   gfx::Rect shelf_region = launcher_widget()->GetWindowBoundsInScreen();
-  if (shell->status_area_widget() &&
-      shell->status_area_widget()->IsMessageBubbleShown() &&
+  if (status_area_widget_ &&
+      status_area_widget_->IsMessageBubbleShown() &&
       IsVisible()) {
     // Increase the the hit test area to prevent the shelf from disappearing
     // when the mouse is over the bubble gap.
@@ -878,7 +874,8 @@
     launcher_widget()->GetNativeWindow()->SetHitTestBoundsOverrideOuter(
         insets, 1);
   }
-  status_->GetNativeWindow()->SetHitTestBoundsOverrideOuter( insets, 1);
+  status_area_widget_->GetNativeWindow()->
+      SetHitTestBoundsOverrideOuter(insets, 1);
 }
 
 bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
@@ -886,7 +883,7 @@
     return false;
   return (launcher_widget() &&
           launcher_widget()->GetNativeWindow()->Contains(window)) ||
-      (status_ && status_->GetNativeWindow()->Contains(window));
+      (status_area_widget_->GetNativeWindow()->Contains(window));
 }
 
 int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
diff --git a/ash/wm/shelf_layout_manager.h b/ash/wm/shelf_layout_manager.h
index c0b57f8..6b9eb08 100644
--- a/ash/wm/shelf_layout_manager.h
+++ b/ash/wm/shelf_layout_manager.h
@@ -27,15 +27,12 @@
 class GestureEvent;
 }
 
-namespace views {
-class Widget;
-}
-
 namespace ash {
 class ScreenAsh;
 namespace internal {
 
 class ShelfLayoutManagerTest;
+class StatusAreaWidget;
 class WorkspaceController;
 
 // ShelfLayoutManager is the layout manager responsible for the launcher and
@@ -88,7 +85,7 @@
   // Size of the shelf when auto-hidden.
   static const int kAutoHideSize;
 
-  explicit ShelfLayoutManager(views::Widget* status);
+  explicit ShelfLayoutManager(StatusAreaWidget* status);
   virtual ~ShelfLayoutManager();
 
   // Sets the ShelfAutoHideBehavior. See enum description for details.
@@ -112,7 +109,7 @@
   const views::Widget* launcher_widget() const {
     return launcher_ ? launcher_->widget() : NULL;
   }
-  views::Widget* status() { return status_; }
+  StatusAreaWidget* status_area_widget() { return status_area_widget_; }
 
   bool in_layout() const { return in_layout_; }
 
@@ -277,7 +274,7 @@
   State state_;
 
   Launcher* launcher_;
-  views::Widget* status_;
+  StatusAreaWidget* status_area_widget_;
 
   WorkspaceController* workspace_controller_;
 
diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc
index 54e1075..dff6dc59 100644
--- a/ash/wm/shelf_layout_manager_unittest.cc
+++ b/ash/wm/shelf_layout_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include "ash/ash_switches.h"
 #include "ash/focus_cycler.h"
 #include "ash/launcher/launcher.h"
+#include "ash/root_window_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
@@ -152,6 +153,10 @@
  public:
   ShelfLayoutManagerTest() {}
 
+  ShelfLayoutManager* shelf_layout_manager() {
+    return Shell::GetPrimaryRootWindowController()->shelf();
+  }
+
   void SetState(ShelfLayoutManager* shelf,
                 ShelfLayoutManager::VisibilityState state) {
     shelf->SetState(state);
@@ -193,7 +198,8 @@
   shelf->LayoutShelf();
   EXPECT_EQ(ShelfLayoutManager::VISIBLE, shelf->visibility_state());
 
-  gfx::Rect status_bounds(shelf->status()->GetWindowBoundsInScreen());
+  gfx::Rect status_bounds(
+      shelf->status_area_widget()->GetWindowBoundsInScreen());
   gfx::Rect launcher_bounds(
       shelf->launcher_widget()->GetWindowBoundsInScreen());
   int shelf_height = shelf->GetIdealBounds().height();
@@ -211,7 +217,7 @@
   SetState(shelf, ShelfLayoutManager::HIDDEN);
   // Run the animation to completion.
   StepWidgetLayerAnimatorToEnd(shelf->launcher_widget());
-  StepWidgetLayerAnimatorToEnd(shelf->status());
+  StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
   EXPECT_EQ(ShelfLayoutManager::HIDDEN, shelf->visibility_state());
   EXPECT_EQ(0,
             display.bounds().bottom() - display.work_area().bottom());
@@ -219,14 +225,14 @@
   // Make sure the bounds of the two widgets changed.
   EXPECT_GE(shelf->launcher_widget()->GetNativeView()->bounds().y(),
             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
-  EXPECT_GE(shelf->status()->GetNativeView()->bounds().y(),
+  EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
 
   // And show it again.
   SetState(shelf, ShelfLayoutManager::VISIBLE);
   // Run the animation to completion.
   StepWidgetLayerAnimatorToEnd(shelf->launcher_widget());
-  StepWidgetLayerAnimatorToEnd(shelf->status());
+  StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
   EXPECT_EQ(ShelfLayoutManager::VISIBLE, shelf->visibility_state());
   EXPECT_EQ(shelf_height,
             display.bounds().bottom() - display.work_area().bottom());
@@ -238,7 +244,7 @@
   EXPECT_EQ(launcher_bounds.y(),
             bottom + (shelf->GetIdealBounds().height() -
                       launcher_bounds.height()) / 2);
-  status_bounds = shelf->status()->GetNativeView()->bounds();
+  status_bounds = shelf->status_area_widget()->GetNativeView()->bounds();
   EXPECT_EQ(status_bounds.y(),
             bottom + shelf_height - status_bounds.height());
 }
@@ -264,19 +270,19 @@
   // Make sure the bounds of the two widgets changed.
   EXPECT_GE(shelf->launcher_widget()->GetNativeView()->bounds().y(),
             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
-  EXPECT_GE(shelf->status()->GetNativeView()->bounds().y(),
+  EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
 }
 
 // Makes sure the launcher is initially sized correctly.
 TEST_F(ShelfLayoutManagerTest, LauncherInitiallySized) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManager();
   ASSERT_TRUE(shelf_layout_manager);
-  ASSERT_TRUE(shelf_layout_manager->status());
-  int status_width =
-      shelf_layout_manager->status()->GetWindowBoundsInScreen().width();
+  ASSERT_TRUE(shelf_layout_manager->status_area_widget());
+  int status_width = shelf_layout_manager->status_area_widget()->
+      GetWindowBoundsInScreen().width();
   // Test only makes sense if the status is > 0, which is better be.
   EXPECT_GT(status_width, 0);
   EXPECT_EQ(status_width, launcher->status_size().width());
@@ -284,12 +290,13 @@
 
 // Makes sure the launcher is sized when the status area changes size.
 TEST_F(ShelfLayoutManagerTest, LauncherUpdatedWhenStatusAreaChangesSize) {
-  Launcher* launcher = Shell::GetInstance()->launcher();
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
   ASSERT_TRUE(launcher);
   ShelfLayoutManager* shelf_layout_manager = GetShelfLayoutManager();
   ASSERT_TRUE(shelf_layout_manager);
-  ASSERT_TRUE(shelf_layout_manager->status());
-  shelf_layout_manager->status()->SetBounds(gfx::Rect(0, 0, 200, 200));
+  ASSERT_TRUE(shelf_layout_manager->status_area_widget());
+  shelf_layout_manager->status_area_widget()->SetBounds(
+      gfx::Rect(0, 0, 200, 200));
   EXPECT_EQ(200, launcher->status_size().width());
 }
 
@@ -493,7 +500,7 @@
 
   // Trying to activate the status should fail, since we only allow activating
   // it when the user is using the keyboard (i.e. through FocusCycler).
-  shelf->status()->Activate();
+  shelf->status_area_widget()->Activate();
   EXPECT_EQ(ShelfLayoutManager::AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
 
   shelf->launcher()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
@@ -504,7 +511,7 @@
 // state,and toggling app list won't change shelf visibility state.
 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfVisibleState) {
   Shell* shell = Shell::GetInstance();
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   shelf->LayoutShelf();
   shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
 
@@ -531,7 +538,7 @@
 // visibility state.
 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
   Shell* shell = Shell::GetInstance();
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   shelf->LayoutShelf();
   shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
 
@@ -565,7 +572,7 @@
 // state, and toggling app list won't change shelf visibility state.
 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
   Shell* shell = Shell::GetInstance();
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   // For shelf to be visible, app list is not open in initial state.
   shelf->LayoutShelf();
 
@@ -593,7 +600,7 @@
 
 // Tests SHELF_ALIGNMENT_LEFT and SHELF_ALIGNMENT_RIGHT.
 TEST_F(ShelfLayoutManagerTest, SetAlignment) {
-  ShelfLayoutManager* shelf = GetShelfLayoutManager();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   // Force an initial layout.
   shelf->LayoutShelf();
   EXPECT_EQ(ShelfLayoutManager::VISIBLE, shelf->visibility_state());
@@ -614,9 +621,10 @@
       shelf->launcher_widget()->GetContentsView()->GetPreferredSize().width());
   EXPECT_EQ(SHELF_ALIGNMENT_LEFT,
             Shell::GetInstance()->system_tray()->shelf_alignment());
-  gfx::Rect status_bounds(shelf->status()->GetWindowBoundsInScreen());
+  StatusAreaWidget* status_area_widget = shelf->status_area_widget();
+  gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
   EXPECT_GE(status_bounds.width(),
-            shelf->status()->GetContentsView()->GetPreferredSize().width());
+            status_area_widget->GetContentsView()->GetPreferredSize().width());
   EXPECT_EQ(shelf->GetIdealBounds().width(),
             display.GetWorkAreaInsets().left());
   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
@@ -637,9 +645,9 @@
       shelf->launcher_widget()->GetContentsView()->GetPreferredSize().width());
   EXPECT_EQ(SHELF_ALIGNMENT_RIGHT,
             Shell::GetInstance()->system_tray()->shelf_alignment());
-  status_bounds = gfx::Rect(shelf->status()->GetWindowBoundsInScreen());
+  status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
   EXPECT_GE(status_bounds.width(),
-            shelf->status()->GetContentsView()->GetPreferredSize().width());
+            status_area_widget->GetContentsView()->GetPreferredSize().width());
   EXPECT_EQ(shelf->GetIdealBounds().width(),
             display.GetWorkAreaInsets().right());
   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
@@ -763,7 +771,8 @@
   EXPECT_FALSE(tray->HasSystemBubble());
 
   // Now, drag up on the tray to show the bubble.
-  gfx::Point start = shelf->status()->GetWindowBoundsInScreen().CenterPoint();
+  gfx::Point start =
+      shelf->status_area_widget()->GetWindowBoundsInScreen().CenterPoint();
   gfx::Point end(start.x(), start.y() - 100);
   generator.GestureScrollSequence(start, end,
       base::TimeDelta::FromMilliseconds(10), 1);
@@ -879,39 +888,39 @@
 // Confirm that the shelf is dimmed only when content is maximized and
 // shelf is not autohidden.
 TEST_F(ShelfLayoutManagerTest, Dimming) {
-  Shell::GetInstance()->shelf()->SetAutoHideBehavior(
-      SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   scoped_ptr<aura::Window> w1(CreateTestWindow());
   w1->Show();
   wm::ActivateWindow(w1.get());
 
   // Normal window doesn't dim shelf.
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
-  EXPECT_FALSE(Shell::GetInstance()->launcher()->GetDimsShelf());
+  Launcher* launcher = Launcher::ForPrimaryDisplay();
+  EXPECT_FALSE(launcher->GetDimsShelf());
 
   // Maximized window does.
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
-  EXPECT_TRUE(Shell::GetInstance()->launcher()->GetDimsShelf());
+  EXPECT_TRUE(launcher->GetDimsShelf());
 
   // Change back to normal stops dimming.
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
-  EXPECT_FALSE(Shell::GetInstance()->launcher()->GetDimsShelf());
+  EXPECT_FALSE(launcher->GetDimsShelf());
 
   // Changing back to maximized dims again.
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
-  EXPECT_TRUE(Shell::GetInstance()->launcher()->GetDimsShelf());
+  EXPECT_TRUE(launcher->GetDimsShelf());
 
   // Changing shelf to autohide stops dimming.
-  Shell::GetInstance()->shelf()->SetAutoHideBehavior(
-      SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
-  EXPECT_FALSE(Shell::GetInstance()->launcher()->GetDimsShelf());
+  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  EXPECT_FALSE(launcher->GetDimsShelf());
 }
 
 // Make sure that the shelf will not hide if the mouse is between a bubble and
 // the shelf.
 TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) {
   ShelfLayoutManager* shelf = GetShelfLayoutManager();
-  StatusAreaWidget* status_area = Shell::GetInstance()->status_area_widget();
+  StatusAreaWidget* status_area_widget =
+      Shell::GetPrimaryRootWindowController()->status_area_widget();
   SystemTray* tray = Shell::GetInstance()->system_tray();
 
   shelf->LayoutShelf();
@@ -924,33 +933,33 @@
     // Make sure the shelf is visible and position the mouse over it. Then
     // allow auto hide.
     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
-    EXPECT_FALSE(status_area->IsMessageBubbleShown());
+    EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
     gfx::Point center =
-        shelf->status()->GetWindowBoundsInScreen().CenterPoint();
+        status_area_widget->GetWindowBoundsInScreen().CenterPoint();
     generator.MoveMouseTo(center.x(), center.y());
     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
     EXPECT_TRUE(shelf->IsVisible());
     if (!i) {
       // In our first iteration we make sure there is no bubble.
       tray->CloseBubbleForTest();
-      EXPECT_FALSE(status_area->IsMessageBubbleShown());
+      EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
     } else {
       // In our second iteration we show a bubble.
       TestItem *item = new TestItem;
       tray->AddTrayItem(item);
       tray->ShowNotificationView(item);
-      EXPECT_TRUE(status_area->IsMessageBubbleShown());
+      EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
     }
     // Move the pointer over the edge of the shelf.
-    generator.MoveMouseTo(center.x(),
-                          shelf->status()->GetWindowBoundsInScreen().y() - 7);
+    generator.MoveMouseTo(
+        center.x(), status_area_widget->GetWindowBoundsInScreen().y() - 7);
     shelf->UpdateVisibilityState();
     if (i) {
       EXPECT_TRUE(shelf->IsVisible());
-      EXPECT_TRUE(status_area->IsMessageBubbleShown());
+      EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
     } else {
       EXPECT_FALSE(shelf->IsVisible());
-      EXPECT_FALSE(status_area->IsMessageBubbleShown());
+      EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
     }
   }
 }
diff --git a/ash/wm/status_area_layout_manager.cc b/ash/wm/status_area_layout_manager.cc
index 84b4aa38..b971d79 100644
--- a/ash/wm/status_area_layout_manager.cc
+++ b/ash/wm/status_area_layout_manager.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/status_area_layout_manager.h"
 
+#include "ash/system/status_area_widget.h"
 #include "ash/wm/shelf_layout_manager.h"
 #include "base/auto_reset.h"
 #include "ui/aura/window.h"
@@ -49,7 +50,7 @@
     const gfx::Rect& requested_bounds) {
   // Only need to have the shelf do a layout if the child changing is the status
   // area and the shelf isn't in the process of doing a layout.
-  if (child != shelf_->status()->GetNativeView() || in_layout_) {
+  if (child != shelf_->status_area_widget()->GetNativeView() || in_layout_) {
     SetChildBoundsDirect(child, requested_bounds);
     return;
   }
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc
index bd56fa0..133f095 100644
--- a/ash/wm/window_animations.cc
+++ b/ash/wm/window_animations.cc
@@ -319,7 +319,11 @@
 }
 
 gfx::Rect GetMinimizeRectForWindow(aura::Window* window) {
-  gfx::Rect target_bounds = Shell::GetInstance()->launcher()->
+  Launcher* launcher = Launcher::ForWindow(window);
+  // Launcher is created lazily and can be NULL.
+  if (!launcher)
+    return gfx::Rect();
+  gfx::Rect target_bounds = Launcher::ForWindow(window)->
       GetScreenBoundsOfItemIconForWindow(window);
   if (target_bounds.IsEmpty()) {
     // Assume the launcher is overflowed, zoom off to the bottom right of the
diff --git a/ash/wm/workspace/frame_maximize_button.cc b/ash/wm/workspace/frame_maximize_button.cc
index 76415d05..23192407 100644
--- a/ash/wm/workspace/frame_maximize_button.cc
+++ b/ash/wm/workspace/frame_maximize_button.cc
@@ -477,7 +477,10 @@
           window->parent(),
           ScreenAsh::GetMaximizedWindowBoundsInParent(window));
     case SNAP_MINIMIZE: {
-      Launcher* launcher = Shell::GetInstance()->launcher();
+      Launcher* launcher = Launcher::ForWindow(window);
+      // Launcher is created lazily and can be NULL.
+      if (!launcher)
+        return gfx::Rect();
       gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(
           window));
       if (!item_rect.IsEmpty()) {
diff --git a/ash/wm/workspace/workspace_layout_manager2_unittest.cc b/ash/wm/workspace/workspace_layout_manager2_unittest.cc
index b5b8abd..799e0133 100644
--- a/ash/wm/workspace/workspace_layout_manager2_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager2_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/wm/workspace/workspace_layout_manager2.h"
 
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/property_util.h"
@@ -65,7 +66,8 @@
       aura::Window* w = window_;
       window_ = NULL;
 
-      gfx::Rect shelf_bounds(Shell::GetInstance()->shelf()->GetIdealBounds());
+      gfx::Rect shelf_bounds(
+          Shell::GetPrimaryRootWindowController()->shelf()->GetIdealBounds());
       const gfx::Rect& window_bounds(w->bounds());
       w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1,
                              window_bounds.width(), window_bounds.height()));
diff --git a/ash/wm/workspace/workspace_manager2_unittest.cc b/ash/wm/workspace/workspace_manager2_unittest.cc
index 4956a7d2..70a39e6 100644
--- a/ash/wm/workspace/workspace_manager2_unittest.cc
+++ b/ash/wm/workspace/workspace_manager2_unittest.cc
@@ -5,9 +5,11 @@
 #include "ash/wm/workspace/workspace_manager2.h"
 
 #include "ash/ash_switches.h"
+#include "ash/root_window_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
+#include "ash/system/status_area_widget.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/activation_controller.h"
 #include "ash/wm/property_util.h"
@@ -34,14 +36,6 @@
 namespace ash {
 namespace internal {
 
-namespace {
-
-bool GetWindowOverlapsShelf() {
-  return Shell::GetInstance()->shelf()->window_overlaps_shelf();
-}
-
-}  // namespace
-
 class WorkspaceManager2Test : public test::AshTestBase {
  public:
   WorkspaceManager2Test() : manager_(NULL) {}
@@ -81,6 +75,14 @@
     return manager_->active_workspace_;
   }
 
+  ShelfLayoutManager* shelf_layout_manager() {
+    return Shell::GetPrimaryRootWindowController()->shelf();
+  }
+
+  bool GetWindowOverlapsShelf() {
+    return shelf_layout_manager()->window_overlaps_shelf();
+  }
+
   Workspace2* FindBy(aura::Window* window) const {
     return manager_->FindBy(window);
   }
@@ -460,7 +462,7 @@
 
   scoped_ptr<Window> w1(CreateTestWindow());
   const gfx::Rect w1_bounds(0, 1, 101, 102);
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   const gfx::Rect touches_shelf_bounds(
       0, shelf->GetIdealBounds().y() - 10, 101, 102);
@@ -675,7 +677,7 @@
 // Test that we report we're in the fullscreen state even if the fullscreen
 // window isn't being managed by us (http://crbug.com/123931).
 TEST_F(WorkspaceManager2Test, GetWindowStateWithUnmanagedFullscreenWindow) {
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
 
   // We need to create a regular window first so there's an active workspace.
   scoped_ptr<Window> w1(CreateTestWindow());
@@ -718,7 +720,7 @@
 // window rather than a normal window.
 TEST_F(WorkspaceManager2Test,
        GetWindowStateWithUnmanagedFullscreenWindowWithMaximized) {
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
 
   // Make the first window maximized.
@@ -783,8 +785,8 @@
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
   EXPECT_EQ(ShelfLayoutManager::VISIBLE,
-            Shell::GetInstance()->shelf()->visibility_state());
-  EXPECT_FALSE(Shell::GetInstance()->launcher()->paints_background());
+            shelf_layout_manager()->visibility_state());
+  EXPECT_FALSE(Launcher::ForPrimaryDisplay()->paints_background());
 }
 
 // Verifies transients are moved when maximizing.
@@ -884,7 +886,7 @@
   generator.MoveMouseTo(0, 0);
 
   scoped_ptr<Window> w1(CreateTestWindow());
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   const gfx::Rect touches_shelf_bounds(
       0, shelf->GetIdealBounds().y() - 10, 101, 102);
   // Move |w1| to overlap the shelf.
@@ -912,7 +914,7 @@
   generator.MoveMouseTo(0, 0);
 
   scoped_ptr<Window> w1(CreateTestWindow());
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   const gfx::Rect w1_bounds(0, shelf->GetIdealBounds().y(), 100, 200);
   // Move |w1| so that the top edge is the same as the top edge of the shelf.
   w1->SetBounds(w1_bounds);
@@ -929,9 +931,9 @@
 
   // Increase the size of the shelf. This would make |w1| fall completely out of
   // the display work area.
-  gfx::Size size = shelf->status()->GetWindowBoundsInScreen().size();
+  gfx::Size size(shelf->status_area_widget()->GetWindowBoundsInScreen().size());
   size.Enlarge(0, 30);
-  shelf->status()->SetSize(size);
+  shelf->status_area_widget()->SetSize(size);
 
   // Switch to w1. The window should have moved.
   wm::ActivateWindow(w1.get());
@@ -992,7 +994,7 @@
 // . show the window and during the bounds change activate it.
 TEST_F(WorkspaceManager2Test, DontCrashOnChangeAndActivate) {
   // Force the shelf
-  ShelfLayoutManager* shelf = Shell::GetInstance()->shelf();
+  ShelfLayoutManager* shelf = shelf_layout_manager();
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
 
   DontCrashOnChangeAndActivateDelegate delegate;
diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc
index f151f627..9affd2a 100644
--- a/ash/wm/workspace/workspace_window_resizer_unittest.cc
+++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "ash/display/display_controller.h"
 #include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/root_window_controller.h"
 #include "ash/screen_ash.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
@@ -126,6 +127,10 @@
     return std::vector<aura::Window*>();
   }
 
+  internal::ShelfLayoutManager* shelf_layout_manager() {
+    return Shell::GetPrimaryRootWindowController()->shelf();
+  }
+
   TestWindowDelegate delegate_;
   TestWindowDelegate delegate2_;
   TestWindowDelegate delegate3_;
@@ -485,7 +490,7 @@
   // The secondary display is logically on the right, but on the system (e.g. X)
   // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
   UpdateDisplay("800x600,800x600");
-  Shell::GetInstance()->shelf()->LayoutShelf();
+  shelf_layout_manager()->LayoutShelf();
   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
   ASSERT_EQ(2U, root_windows.size());
 
@@ -546,7 +551,7 @@
 TEST_F(WorkspaceWindowResizerTest,
        MAYBE_WindowDragWithMultiDisplaysRightToLeft) {
   UpdateDisplay("800x600,800x600");
-  Shell::GetInstance()->shelf()->LayoutShelf();
+  shelf_layout_manager()->LayoutShelf();
   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
   ASSERT_EQ(2U, root_windows.size());
 
@@ -1004,7 +1009,7 @@
   scoped_ptr<SnapSizer> resizer(new SnapSizer(
       window_.get(), gfx::Point(), SnapSizer::LEFT_EDGE));
   ASSERT_TRUE(resizer.get());
-  Shell::GetInstance()->shelf()->SetAutoHideBehavior(
+  shelf_layout_manager()->SetAutoHideBehavior(
       SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   gfx::Rect rect = resizer->GetTargetBoundsForSize(0);
   EXPECT_EQ("0,0 720x597", rect.ToString());
@@ -1014,7 +1019,7 @@
   EXPECT_EQ("0,0 720x597", rect.ToString());
   rect = resizer->GetTargetBoundsForSize(3);
   EXPECT_EQ("0,0 640x597", rect.ToString());
-  Shell::GetInstance()->shelf()->SetAutoHideBehavior(
+  shelf_layout_manager()->SetAutoHideBehavior(
       SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   rect = resizer->GetTargetBoundsForSize(0);
   EXPECT_EQ("0,0 720x552", rect.ToString());
@@ -1093,7 +1098,7 @@
   // The secondary display is logically on the right, but on the system (e.g. X)
   // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
   UpdateDisplay("400x400,800x800*2");
-  Shell::GetInstance()->shelf()->LayoutShelf();
+  shelf_layout_manager()->LayoutShelf();
   Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
   ASSERT_EQ(2U, root_windows.size());