[Launcher per display] Removed Shell::status_area_widget(), system_tray()
 HasPrimaryStatusArea/GetPrimarySystemTray for login screen
 which will have only one tray/status area on primary

BUG=145978
TEST=none

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172169 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 5a67366..66864e9 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -633,10 +633,15 @@
         return true;
       }
       break;
-    case SHOW_SYSTEM_TRAY_BUBBLE:
-      if (!shell->system_tray()->HasSystemBubble())
-        shell->system_tray()->ShowDefaultView(BUBBLE_CREATE_NEW);
+    case SHOW_SYSTEM_TRAY_BUBBLE: {
+      internal::RootWindowController* controller =
+          Shell::IsLauncherPerDisplayEnabled() ?
+          internal::RootWindowController::ForActiveRootWindow() :
+          Shell::GetPrimaryRootWindowController();
+      if (!controller->GetSystemTray()->HasSystemBubble())
+        controller->GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
       break;
+    }
     case SHOW_TASK_MANAGER:
       Shell::GetInstance()->delegate()->ShowTaskManager();
       return true;
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index c153a601..716b9f26 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -577,7 +577,7 @@
 
 TEST_F(ExtendedDesktopTest, OpenSystemTray) {
   UpdateDisplay("500x600,600x400");
-  SystemTray* tray = ash::Shell::GetInstance()->system_tray();
+  SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
   ASSERT_FALSE(tray->HasSystemBubble());
 
   // Opens the tray by a dummy click event and makes sure that adding/removing
diff --git a/ash/launcher/overflow_bubble.cc b/ash/launcher/overflow_bubble.cc
index 7c14f8e..d2f889e 100644
--- a/ash/launcher/overflow_bubble.cc
+++ b/ash/launcher/overflow_bubble.cc
@@ -8,9 +8,11 @@
 
 #include "ash/launcher/launcher_types.h"
 #include "ash/launcher/launcher_view.h"
+#include "ash/root_window_controller.h"
 #include "ash/system/tray/system_tray.h"
 #include "ash/shell.h"
 #include "ash/wm/shelf_layout_manager.h"
+#include "ui/aura/root_window.h"
 #include "ui/gfx/insets.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/bubble/bubble_delegate.h"
@@ -258,8 +260,8 @@
                                   overflow_start_index);
 
   bubble_ = bubble_view;
-  ash::Shell::GetInstance()->system_tray()->InitializeBubbleAnimations(
-      bubble_->GetWidget());
+  RootWindowController::ForWindow(anchor->GetWidget()->GetNativeView())->
+      GetSystemTray()->InitializeBubbleAnimations(bubble_->GetWidget());
   bubble_->GetWidget()->AddObserver(this);
   bubble_->GetWidget()->Show();
 }
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 8ccdd12..e3ca185 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -176,14 +176,23 @@
 }
 
 // static
-internal::RootWindowController*
-RootWindowController::ForLauncher(aura::Window* window) {
+RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
   if (Shell::IsLauncherPerDisplayEnabled())
     return GetRootWindowController(window->GetRootWindow());
   else
     return Shell::GetPrimaryRootWindowController();
 }
 
+// static
+RootWindowController* RootWindowController::ForWindow(aura::Window* window) {
+  return GetRootWindowController(window->GetRootWindow());
+}
+
+// static
+RootWindowController* RootWindowController::ForActiveRootWindow() {
+  return GetRootWindowController(Shell::GetActiveRootWindow());
+}
+
 void RootWindowController::Shutdown() {
   CloseChildWindows();
   if (Shell::GetActiveRootWindow() == root_window_.get()) {
@@ -221,7 +230,7 @@
       container = GetContainer(kShellWindowId_SystemModalContainer);
     }
   } else {
-    user::LoginStatus login = Shell::GetInstance()->status_area_widget() ?
+    user::LoginStatus login = Shell::GetInstance()->tray_delegate() ?
         Shell::GetInstance()->tray_delegate()->GetUserLoginStatus() :
         user::LOGGED_IN_NONE;
     int modal_window_id = (login == user::LOGGED_IN_LOCKED ||
@@ -442,6 +451,14 @@
   }
 }
 
+SystemTray* RootWindowController::GetSystemTray() {
+  // We assume in throughout the code that this will not return NULL. If code
+  // triggers this for valid reasons, it should test status_area_widget first.
+  internal::StatusAreaWidget* status_area = status_area_widget();
+  CHECK(status_area);
+  return status_area->system_tray();
+}
+
 void RootWindowController::ShowContextMenu(
     const gfx::Point& location_in_screen) {
   aura::RootWindow* target = Shell::IsLauncherPerDisplayEnabled() ?
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index a8cb82f..92185a6a 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -32,6 +32,7 @@
 
 namespace ash {
 class Launcher;
+class SystemTray;
 class ToplevelWindowEventHandler;
 
 namespace internal {
@@ -62,6 +63,12 @@
   // RootWindowController otherwise.
   static RootWindowController* ForLauncher(aura::Window* window);
 
+  // Returns a RootWindowController of the window's root window.
+  static RootWindowController* ForWindow(aura::Window* window);
+
+  // Returns the RootWindowController of the active root window.
+  static internal::RootWindowController* ForActiveRootWindow();
+
   aura::RootWindow* root_window() { return root_window_.get(); }
 
   RootWindowLayoutManager* root_window_layout() { return root_window_layout_; }
@@ -76,10 +83,15 @@
 
   ShelfLayoutManager* shelf() const { return shelf_; }
 
-  StatusAreaWidget* status_area_widget() const {
+  StatusAreaWidget* status_area_widget() {
     return status_area_widget_;
   }
 
+  // Returns the system tray on this root window. Note that
+  // calling this on the root window that doesn't have a launcher will
+  // lead to a crash.
+  SystemTray* GetSystemTray();
+
   // Shows context menu at the |location_in_screen|. This uses
   // |ShellDelegate::CreateContextMenu| to define the content of the menu.
   void ShowContextMenu(const gfx::Point& location_in_screen);
diff --git a/ash/shell.cc b/ash/shell.cc
index ba58f5d..a6e4ee0 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -670,7 +670,14 @@
 }
 
 void Shell::CreateLauncher() {
-  GetPrimaryRootWindowController()->CreateLauncher();
+  if (IsLauncherPerDisplayEnabled()) {
+    RootWindowControllerList controllers = GetAllRootWindowControllers();
+    for (RootWindowControllerList::iterator iter = controllers.begin();
+         iter != controllers.end(); ++iter)
+      (*iter)->CreateLauncher();
+  } else {
+    GetPrimaryRootWindowController()->CreateLauncher();
+  }
 }
 
 void Shell::ShowLauncher() {
@@ -753,16 +760,12 @@
       web_notification_tray();
 }
 
-internal::StatusAreaWidget* Shell::status_area_widget() {
-  return GetPrimaryRootWindowController()->status_area_widget();
+bool Shell::HasPrimaryStatusArea() {
+  return !!GetPrimaryRootWindowController()->status_area_widget();
 }
 
-SystemTray* Shell::system_tray() {
-  // We assume in throughout the code that this will not return NULL. If code
-  // triggers this for valid reasons, it should test status_area_widget first.
-  internal::StatusAreaWidget* status_area = status_area_widget();
-  CHECK(status_area);
-  return status_area->system_tray();
+SystemTray* Shell::GetPrimarySystemTray() {
+  return GetPrimaryRootWindowController()->GetSystemTray();
 }
 
 void Shell::InitRootWindowForSecondaryDisplay(aura::RootWindow* root) {
diff --git a/ash/shell.h b/ash/shell.h
index 346c977..3a21dfd6 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -148,9 +148,11 @@
   static void DeleteInstance();
 
   // Returns the root window controller for the primary root window.
+  // TODO(oshima): move this to |RootWindowController|
   static internal::RootWindowController* GetPrimaryRootWindowController();
 
   // Returns all root window controllers.
+  // TODO(oshima): move this to |RootWindowController|
   static RootWindowControllerList GetAllRootWindowControllers();
 
   // Returns the primary RootWindow. The primary RootWindow is the one
@@ -358,13 +360,11 @@
   // Returns WebNotificationTray on the primary root window.
   WebNotificationTray* GetWebNotificationTray();
 
-  // Convenience accessor for members of StatusAreaWidget.
-  // NOTE: status_area_widget() may return NULL during shutdown;
-  // tray_delegate() and system_tray() will crash if called after
-  // status_area_widget() has been destroyed; check status_area_widget()
-  // before calling these in destructors.
-  internal::StatusAreaWidget* status_area_widget();
-  SystemTray* system_tray();
+  // Does the primary display have status area?
+  bool HasPrimaryStatusArea();
+
+  // Returns the system tray on primary display.
+  SystemTray* GetPrimarySystemTray();
 
   // TODO(stevenjb): Rename to system_tray_delegate().
   SystemTrayDelegate* tray_delegate() {
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc
index b28bd65..b28f72e6 100644
--- a/ash/system/chromeos/network/network_state_list_detailed_view.cc
+++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/chromeos/network/network_state_list_detailed_view.h"
 
+#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
 #include "ash/system/chromeos/network/network_icon.h"
@@ -218,7 +219,8 @@
   ResetInfoBubble();
 
   if (sender == footer()->content()) {
-    Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+    RootWindowController::ForWindow(GetWidget()->GetNativeView())->
+        GetSystemTray()->ShowDefaultView(BUBBLE_USE_EXISTING);
     return;
   }
 
diff --git a/ash/system/tray_update.cc b/ash/system/tray_update.cc
index ef352eb..67aa2b3 100644
--- a/ash/system/tray_update.cc
+++ b/ash/system/tray_update.cc
@@ -108,7 +108,7 @@
 
   virtual ~UpdateNagger() {
     internal::StatusAreaWidget* status_area =
-        ash::Shell::GetInstance()->status_area_widget();
+        Shell::GetPrimaryRootWindowController()->status_area_widget();
     if (status_area) {
       status_area->system_tray()->GetWidget()->GetNativeView()->layer()->
           GetAnimator()->RemoveObserver(this);
diff --git a/ash/wm/gestures/tray_gesture_handler.cc b/ash/wm/gestures/tray_gesture_handler.cc
index 1a8f2ea..5eabccb9f 100644
--- a/ash/wm/gestures/tray_gesture_handler.cc
+++ b/ash/wm/gestures/tray_gesture_handler.cc
@@ -21,7 +21,8 @@
 TrayGestureHandler::TrayGestureHandler()
     : widget_(NULL),
       gesture_drag_amount_(0) {
-  SystemTray* tray = Shell::GetInstance()->system_tray();
+  // TODO(oshima): Support multiple display case.
+  SystemTray* tray = Shell::GetInstance()->GetPrimarySystemTray();
   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
   SystemTrayBubble* bubble = tray->GetSystemBubble();
   if (!bubble)
@@ -93,7 +94,7 @@
     widget_->Close();
   } else {
     SystemTrayBubble* bubble =
-        Shell::GetInstance()->system_tray()->GetSystemBubble();
+        Shell::GetInstance()->GetPrimarySystemTray()->GetSystemBubble();
     if (bubble)
       bubble->bubble_view()->set_gesture_dragging(false);
   }
diff --git a/ash/wm/shelf_layout_manager_unittest.cc b/ash/wm/shelf_layout_manager_unittest.cc
index 6a3dad7..76c78684 100644
--- a/ash/wm/shelf_layout_manager_unittest.cc
+++ b/ash/wm/shelf_layout_manager_unittest.cc
@@ -49,10 +49,11 @@
 }
 
 ShelfLayoutManager* GetShelfLayoutManager() {
-  aura::Window* window = Shell::GetContainer(
-      Shell::GetPrimaryRootWindow(),
-      internal::kShellWindowId_LauncherContainer);
-  return static_cast<ShelfLayoutManager*>(window->layout_manager());
+  return Shell::GetPrimaryRootWindowController()->shelf();
+}
+
+SystemTray* GetSystemTray() {
+  return Shell::GetPrimaryRootWindowController()->GetSystemTray();
 }
 
 class ShelfLayoutObserverTest : public ShelfLayoutManager::Observer {
@@ -80,7 +81,7 @@
 class TestItem : public SystemTrayItem {
  public:
   TestItem()
-      : SystemTrayItem(Shell::GetInstance()->system_tray()),
+      : SystemTrayItem(GetSystemTray()),
         tray_view_(NULL),
         default_view_(NULL),
         detailed_view_(NULL),
@@ -153,10 +154,6 @@
  public:
   ShelfLayoutManagerTest() {}
 
-  ShelfLayoutManager* shelf_layout_manager() {
-    return Shell::GetPrimaryRootWindowController()->shelf();
-  }
-
   void SetState(ShelfLayoutManager* shelf,
                 ShelfVisibilityState state) {
     shelf->SetState(state);
@@ -510,7 +507,7 @@
   Shell* shell = Shell::GetInstance();
   internal::RootWindowController* controller =
       Shell::GetPrimaryRootWindowController();
-  ShelfLayoutManager* shelf = shelf_layout_manager();
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
   shelf->LayoutShelf();
   controller->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
 
@@ -537,7 +534,7 @@
 // toggling app list won't change shelf visibility state.
 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
   Shell* shell = Shell::GetInstance();
-  ShelfLayoutManager* shelf = shelf_layout_manager();
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
   internal::RootWindowController* controller =
       Shell::GetPrimaryRootWindowController();
   shelf->LayoutShelf();
@@ -573,7 +570,7 @@
 // state, and toggling app list won't change shelf visibility state.
 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
   Shell* shell = Shell::GetInstance();
-  ShelfLayoutManager* shelf = shelf_layout_manager();
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
   // For shelf to be visible, app list is not open in initial state.
   shelf->LayoutShelf();
 
@@ -601,7 +598,7 @@
 
 // Tests SHELF_ALIGNMENT_LEFT and SHELF_ALIGNMENT_RIGHT.
 TEST_F(ShelfLayoutManagerTest, SetAlignment) {
-  ShelfLayoutManager* shelf = shelf_layout_manager();
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
   // Force an initial layout.
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   shelf->LayoutShelf();
@@ -620,8 +617,7 @@
   EXPECT_GE(
       launcher_bounds.width(),
       shelf->launcher_widget()->GetContentsView()->GetPreferredSize().width());
-  EXPECT_EQ(SHELF_ALIGNMENT_LEFT,
-            Shell::GetInstance()->system_tray()->shelf_alignment());
+  EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment());
   StatusAreaWidget* status_area_widget = shelf->status_area_widget();
   gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
   EXPECT_GE(status_bounds.width(),
@@ -650,8 +646,7 @@
             display.GetWorkAreaInsets().right());
   EXPECT_GE(launcher_bounds.width(),
       shelf->launcher_widget()->GetContentsView()->GetPreferredSize().width());
-  EXPECT_EQ(SHELF_ALIGNMENT_RIGHT,
-            Shell::GetInstance()->system_tray()->shelf_alignment());
+  EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, GetSystemTray()->shelf_alignment());
   status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
   EXPECT_GE(status_bounds.width(),
             status_area_widget->GetContentsView()->GetPreferredSize().width());
@@ -777,7 +772,7 @@
   shelf->LayoutShelf();
 
   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
-  SystemTray* tray = Shell::GetInstance()->system_tray();
+  SystemTray* tray = GetSystemTray();
 
   // First, make sure the shelf is visible.
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
@@ -827,7 +822,7 @@
       SHOW_SYSTEM_TRAY_BUBBLE, ui::Accelerator());
   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
-  EXPECT_TRUE(Shell::GetInstance()->system_tray()->HasSystemBubble());
+  EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
 
   // Now activate the tray (using the keyboard, instead of using the mouse to
   // make sure the mouse does not alter the auto-hide state in the shelf).
@@ -838,7 +833,7 @@
   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   generator.PressKey(ui::VKEY_SPACE, 0);
   generator.ReleaseKey(ui::VKEY_SPACE, 0);
-  EXPECT_TRUE(Shell::GetInstance()->system_tray()->HasSystemBubble());
+  EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
   EXPECT_FALSE(observer.changed_auto_hide_state());
@@ -901,7 +896,7 @@
 // Confirm that the shelf is dimmed only when content is maximized and
 // shelf is not autohidden.
 TEST_F(ShelfLayoutManagerTest, Dimming) {
-  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+  GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   scoped_ptr<aura::Window> w1(CreateTestWindow());
   w1->Show();
   wm::ActivateWindow(w1.get());
@@ -924,7 +919,7 @@
   EXPECT_TRUE(launcher->GetDimsShelf());
 
   // Changing shelf to autohide stops dimming.
-  shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   EXPECT_FALSE(launcher->GetDimsShelf());
 }
 
@@ -934,7 +929,7 @@
   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   StatusAreaWidget* status_area_widget =
       Shell::GetPrimaryRootWindowController()->status_area_widget();
-  SystemTray* tray = Shell::GetInstance()->system_tray();
+  SystemTray* tray = GetSystemTray();
 
   shelf->LayoutShelf();
   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
diff --git a/chrome/browser/chromeos/login/webui_login_view.cc b/chrome/browser/chromeos/login/webui_login_view.cc
index 4bf813d..f24af0a 100644
--- a/chrome/browser/chromeos/login/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/webui_login_view.cc
@@ -142,8 +142,10 @@
 }
 
 WebUILoginView::~WebUILoginView() {
-  if (ash::Shell::GetInstance()->status_area_widget())
-    ash::Shell::GetInstance()->system_tray()->SetNextFocusableView(NULL);
+  if (ash::Shell::GetInstance()->HasPrimaryStatusArea()) {
+    ash::Shell::GetInstance()->GetPrimarySystemTray()->
+        SetNextFocusableView(NULL);
+  }
 }
 
 void WebUILoginView::Init(views::Widget* login_window) {
@@ -242,8 +244,8 @@
 }
 
 void WebUILoginView::SetStatusAreaVisible(bool visible) {
-  if (ash::Shell::GetInstance()->status_area_widget()) {
-    ash::SystemTray* tray = ash::Shell::GetInstance()->system_tray();
+  if (ash::Shell::GetInstance()->HasPrimaryStatusArea()) {
+    ash::SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
     if (visible) {
       // Tray may have been initialized being hidden.
       tray->SetVisible(visible);
@@ -256,7 +258,7 @@
 
 void WebUILoginView::SetUIEnabled(bool enabled) {
   forward_keyboard_event_ = enabled;
-  ash::Shell::GetInstance()->system_tray()->SetEnabled(enabled);
+  ash::Shell::GetInstance()->GetPrimarySystemTray()->SetEnabled(enabled);
 }
 
 // WebUILoginView protected: ---------------------------------------------------
@@ -334,7 +336,7 @@
 }
 
 bool WebUILoginView::TakeFocus(content::WebContents* source, bool reverse) {
-  ash::SystemTray* tray = ash::Shell::GetInstance()->system_tray();
+  ash::SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
   if (tray && tray->GetWidget()->IsVisible()) {
     tray->SetNextFocusableView(this);
     ash::Shell::GetInstance()->RotateFocus(reverse ? ash::Shell::BACKWARD :
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index cfd87ab..0b19b42 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -775,8 +775,8 @@
   }
 
  private:
-  ash::SystemTray* GetSystemTray() {
-    return ash::Shell::GetInstance()->system_tray();
+  ash::SystemTray* GetPrimarySystemTray() {
+    return ash::Shell::GetInstance()->GetPrimarySystemTray();
   }
 
   ash::SystemTrayNotifier* GetSystemTrayNotifier() {
@@ -1004,7 +1004,7 @@
     RefreshNetworkObserver(crosnet);
     RefreshNetworkDeviceObserver(crosnet);
     data_promo_notification_->ShowOptionalMobileDataPromoNotification(
-        crosnet, GetSystemTray(), this);
+        crosnet, GetPrimarySystemTray(), this);
 
     NotifyRefreshNetwork();
   }