summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorskuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-18 09:09:41 +0000
committerskuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-18 09:09:41 +0000
commitc8d19f8b527b6e731cc88d89574dc9127e9a62ac (patch)
tree03f18eeb52be5315dea606cb5756ad3e32429170 /ash
parente519c435d39e453f532b1ba352ad2944c75895d8 (diff)
downloadchromium_src-c8d19f8b527b6e731cc88d89574dc9127e9a62ac.zip
chromium_src-c8d19f8b527b6e731cc88d89574dc9127e9a62ac.tar.gz
chromium_src-c8d19f8b527b6e731cc88d89574dc9127e9a62ac.tar.bz2
Adding new user menu section to the SystemTrayMenu & refactoring of user access
It is still not fully finished - but it is functional and might be useful for what you are doing (and already quite big as it is). Note that the functionality is controlled by the flag. What is missing? - There are no unit tests yet - The visual Drop down box to add a new user is missing. - The error message box which shows the error if there are already 3 users signed in is missing. - At the moment I have ~7 lines of test code in there which I will remove before I check in. (I need them since the multi login still does not work for me) I am not sure if you want to wait until I finish the issue - or if you'd rather want to have this to be able to rather merge early then later. I leave this up to you. If you are for the latter one, you can have at least a look at my changes and if they conflict with yours. BUG=239201 TEST=visual Review URL: https://chromiumcodereview.appspot.com/14756019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200978 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash_strings.grd12
-rw-r--r--ash/desktop_background/desktop_background_view.cc2
-rw-r--r--ash/root_window_controller.cc2
-rw-r--r--ash/root_window_controller_unittest.cc4
-rw-r--r--ash/session_state_delegate.h42
-rw-r--r--ash/session_state_delegate_stub.cc32
-rw-r--r--ash/session_state_delegate_stub.h15
-rw-r--r--ash/shell.cc2
-rw-r--r--ash/system/tray/system_tray.cc12
-rw-r--r--ash/system/tray/system_tray_delegate.h11
-rw-r--r--ash/system/tray/system_tray_item.h2
-rw-r--r--ash/system/tray/test_system_tray_delegate.cc20
-rw-r--r--ash/system/tray/test_system_tray_delegate.h6
-rw-r--r--ash/system/user/login_status.cc9
-rw-r--r--ash/system/user/tray_user.cc393
-rw-r--r--ash/system/user/tray_user.h10
-rw-r--r--ash/test/test_session_state_delegate.cc34
-rw-r--r--ash/test/test_session_state_delegate.h15
-rw-r--r--ash/wm/gestures/shelf_gesture_handler.cc2
19 files changed, 473 insertions, 152 deletions
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 2ea0cf8..5da716d 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -218,6 +218,9 @@ Press Ctrl+Alt+Z to disable.
<message name="IDS_ASH_STATUS_TRAY_SIGN_OUT" desc="The label used for the button in the status tray to sign out of the system.">
Sign out
</message>
+ <message name="IDS_ASH_STATUS_TRAY_SIGN_OUT_ALL" desc="The label used for the button in the status tray to sign out all users of the system.">
+ Sign out all
+ </message>
<message name="IDS_ASH_STATUS_TRAY_GUEST_LABEL" desc="The label used in the system tray's user card to indicate that the current session is a guest session.">
Guest
</message>
@@ -248,6 +251,15 @@ Press Ctrl+Alt+Z to disable.
<message name="IDS_ASH_STATUS_TRAY_SMS_NUMBER" desc="Sender for SMS messagees in the system tray.">
SMS from <ph name="PHONE_NUMBER">$1<ex>08700 776655</ex></ph>
</message>
+ <message name="IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT" desc="The string for the button which lets the user add another account to the current session.">
+ Sign in another account...
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER" desc="The caption for the error message when the user has reached the limit of multi profile users.">
+ Can't sign into another account.
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER" desc="The error message when the user has reached the limit of multi profile users.">
+ You can only have up to three accounts in multiple sign-in.
+ </message>
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH" desc="The label used as the header in the bluetooth popup.">
Bluetooth
diff --git a/ash/desktop_background/desktop_background_view.cc b/ash/desktop_background/desktop_background_view.cc
index 6d6e487..f851789 100644
--- a/ash/desktop_background/desktop_background_view.cc
+++ b/ash/desktop_background/desktop_background_view.cc
@@ -201,7 +201,7 @@ views::Widget* CreateDesktopBackground(aura::RootWindow* root_window,
// 4. From an empty background, guest user logged in.
if (wallpaper_delegate->ShouldShowInitialAnimation() ||
root_window->GetProperty(kAnimatingDesktopController) ||
- Shell::GetInstance()->session_state_delegate()->HasActiveUser()) {
+ Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers()) {
views::corewm::SetWindowVisibilityAnimationTransition(
desktop_widget->GetNativeView(), views::corewm::ANIMATE_SHOW);
} else {
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 6d0355e..2dc3756 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -281,7 +281,7 @@ void RootWindowController::InitForPrimaryDisplay() {
new ToplevelWindowEventHandler(panel_container));
panel_container->SetLayoutManager(panel_layout_manager_);
- if (Shell::GetInstance()->session_state_delegate()->HasActiveUser())
+ if (Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers())
shelf_->CreateLauncher();
InitKeyboard();
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc
index b33e012..4a3351e 100644
--- a/ash/root_window_controller_unittest.cc
+++ b/ash/root_window_controller_unittest.cc
@@ -327,7 +327,7 @@ TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
SetUserLoggedIn(false);
EXPECT_EQ(user::LOGGED_IN_NONE,
shell->system_tray_delegate()->GetUserLoginStatus());
- EXPECT_FALSE(shell->session_state_delegate()->HasActiveUser());
+ EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers());
EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted());
internal::RootWindowController* controller =
@@ -352,7 +352,7 @@ TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) {
SetSessionStarted(true);
EXPECT_EQ(user::LOGGED_IN_USER,
shell->system_tray_delegate()->GetUserLoginStatus());
- EXPECT_TRUE(shell->session_state_delegate()->HasActiveUser());
+ EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers());
EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted());
EXPECT_EQ(Shell::GetContainer(controller->root_window(),
internal::kShellWindowId_SystemModalContainer)->layout_manager(),
diff --git a/ash/session_state_delegate.h b/ash/session_state_delegate.h
index f5ee359..f5451cf 100644
--- a/ash/session_state_delegate.h
+++ b/ash/session_state_delegate.h
@@ -5,17 +5,36 @@
#ifndef ASH_SESSION_STATE_DELEGATE_H_
#define ASH_SESSION_STATE_DELEGATE_H_
+#include <string>
+#include <vector>
+
#include "ash/ash_export.h"
+#include "base/string16.h"
+
+namespace gfx {
+class ImageSkia;
+} // namespace gfx
namespace ash {
+// The index for the multi-profile item to use. The list is always LRU sorted
+// So that the index #0 is the currently active user.
+typedef int MultiProfileIndex;
+
+// A list of email addresses.
+typedef std::vector<std::string> UserEmailList;
+
// Delegate for checking and modifying the session state.
class ASH_EXPORT SessionStateDelegate {
public:
virtual ~SessionStateDelegate() {};
- // Returns |true| if a session is in progress and there is an active user.
- virtual bool HasActiveUser() const = 0;
+ // Returns the maximum possible number of logged in users.
+ virtual int GetMaximumNumberOfLoggedInUsers() const = 0;
+
+ // Returns the number of signed in users. If 0 is returned, there is either
+ // no session in progress or no active user.
+ virtual int NumberOfLoggedInUsers() const = 0;
// Returns |true| if the session has been fully started for the active user.
// When a user becomes active, the profile and browser UI are not immediately
@@ -34,6 +53,25 @@ class ASH_EXPORT SessionStateDelegate {
// Unlocks the screen.
virtual void UnlockScreen() = 0;
+
+ // Gets the displayed name for the user with the given |index|.
+ // Note that |index| can at maximum be |NumberOfLoggedInUsers() - 1|.
+ virtual const base::string16 GetUserDisplayName(
+ MultiProfileIndex index) const = 0;
+
+ // Gets the email address for the user with the given |index|.
+ // Note that |index| can at maximum be |NumberOfLoggedInUsers() - 1|.
+ virtual const std::string GetUserEmail(MultiProfileIndex index) const = 0;
+
+ // Gets the avatar image for the user with the given |index|.
+ // Note that |index| can at maximum be |NumberOfLoggedInUsers() - 1|.
+ virtual const gfx::ImageSkia& GetUserImage(MultiProfileIndex index) const = 0;
+
+ // Returns a list of all logged in users.
+ virtual void GetLoggedInUsers(UserEmailList* users) = 0;
+
+ // Switches to another active user (if that user has already signed in).
+ virtual void SwitchActiveUser(const std::string& email) = 0;
};
} // namespace ash
diff --git a/ash/session_state_delegate_stub.cc b/ash/session_state_delegate_stub.cc
index b913b5f..86ce366 100644
--- a/ash/session_state_delegate_stub.cc
+++ b/ash/session_state_delegate_stub.cc
@@ -6,6 +6,8 @@
#include "ash/shell.h"
#include "ash/shell/example_factory.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
namespace ash {
@@ -15,8 +17,12 @@ SessionStateDelegateStub::SessionStateDelegateStub() : screen_locked_(false) {
SessionStateDelegateStub::~SessionStateDelegateStub() {
}
-bool SessionStateDelegateStub::HasActiveUser() const {
- return true;
+int SessionStateDelegateStub::GetMaximumNumberOfLoggedInUsers() const {
+ return 3;
+}
+
+int SessionStateDelegateStub::NumberOfLoggedInUsers() const {
+ return 1;
}
bool SessionStateDelegateStub::IsActiveUserSessionStarted() const {
@@ -42,4 +48,26 @@ void SessionStateDelegateStub::UnlockScreen() {
Shell::GetInstance()->UpdateShelfVisibility();
}
+const base::string16 SessionStateDelegateStub::GetUserDisplayName(
+ MultiProfileIndex index) const {
+ return UTF8ToUTF16("stub-user");
+}
+
+const std::string SessionStateDelegateStub::GetUserEmail(
+ MultiProfileIndex index) const {
+ return "stub-user@domain.com";
+}
+
+const gfx::ImageSkia& SessionStateDelegateStub::GetUserImage(
+ MultiProfileIndex index) const {
+ return null_image_;
+}
+
+void SessionStateDelegateStub::GetLoggedInUsers(
+ UserEmailList* users) {
+}
+
+void SessionStateDelegateStub::SwitchActiveUser(const std::string& email) {
+}
+
} // namespace ash
diff --git a/ash/session_state_delegate_stub.h b/ash/session_state_delegate_stub.h
index db9b711..707c53e 100644
--- a/ash/session_state_delegate_stub.h
+++ b/ash/session_state_delegate_stub.h
@@ -8,6 +8,7 @@
#include "ash/session_state_delegate.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "ui/gfx/image/image_skia.h"
namespace ash {
@@ -18,16 +19,28 @@ class SessionStateDelegateStub : public SessionStateDelegate {
virtual ~SessionStateDelegateStub();
// SessionStateDelegate:
- virtual bool HasActiveUser() const OVERRIDE;
+ virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
+ virtual int NumberOfLoggedInUsers() const OVERRIDE;
virtual bool IsActiveUserSessionStarted() const OVERRIDE;
virtual bool CanLockScreen() const OVERRIDE;
virtual bool IsScreenLocked() const OVERRIDE;
virtual void LockScreen() OVERRIDE;
virtual void UnlockScreen() OVERRIDE;
+ virtual const base::string16 GetUserDisplayName(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual const std::string GetUserEmail(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual const gfx::ImageSkia& GetUserImage(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual void GetLoggedInUsers(UserEmailList* users) OVERRIDE;
+ virtual void SwitchActiveUser(const std::string& email) OVERRIDE;
private:
bool screen_locked_;
+ // A pseudo user image.
+ gfx::ImageSkia null_image_;
+
DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub);
};
diff --git a/ash/shell.cc b/ash/shell.cc
index 9112130..1e75bab 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -616,7 +616,7 @@ void Shell::Init() {
void Shell::ShowContextMenu(const gfx::Point& location_in_screen) {
// No context menus if there is no session with an active user.
- if (!session_state_delegate_->HasActiveUser())
+ if (!session_state_delegate_->NumberOfLoggedInUsers())
return;
// No context menus when screen is locked.
if (session_state_delegate_->IsScreenLocked())
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index 8dc0fa4..4602271 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -138,7 +138,17 @@ void SystemTray::CreateItems(SystemTrayDelegate* delegate) {
#if !defined(OS_WIN)
AddTrayItem(new internal::TraySessionLengthLimit(this));
AddTrayItem(new internal::TrayLogoutButton(this));
- AddTrayItem(new internal::TrayUser(this));
+ // In multi-profile user mode we can have multiple user tiles.
+ ash::Shell* shell = ash::Shell::GetInstance();
+ int maximum_user_profiles =
+ shell->delegate()->IsMultiProfilesEnabled() ?
+ shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers() :
+ 0;
+ // Note: We purposely use one more item then logged in users to account for
+ // the additional separator.
+ for (int i = 0; i <= maximum_user_profiles; i++)
+ AddTrayItem(new internal::TrayUser(this, i));
+
#endif
#if defined(OS_CHROMEOS)
AddTrayItem(new internal::TrayEnterprise(this));
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h
index 32c5830..2e84617 100644
--- a/ash/system/tray/system_tray_delegate.h
+++ b/ash/system/tray/system_tray_delegate.h
@@ -110,8 +110,6 @@ typedef std::vector<IMEInfo> IMEInfoList;
class VolumeControlDelegate;
-typedef std::vector<std::string> UserEmailList;
-
class SystemTrayDelegate {
public:
virtual ~SystemTrayDelegate() {}
@@ -126,18 +124,9 @@ class SystemTrayDelegate {
virtual bool GetTrayVisibilityOnStartup() = 0;
// Gets information about the active user.
- virtual const base::string16 GetUserDisplayName() const = 0;
- virtual const std::string GetUserEmail() const = 0;
- virtual const gfx::ImageSkia& GetUserImage() const = 0;
virtual user::LoginStatus GetUserLoginStatus() const = 0;
virtual bool IsOobeCompleted() const = 0;
- // Returns a list of all logged in users.
- virtual void GetLoggedInUsers(UserEmailList* users) = 0;
-
- // Switches to another active user (if that user has already signed in).
- virtual void SwitchActiveUser(const std::string& email) = 0;
-
// Shows UI for changing user's profile picture.
virtual void ChangeProfilePicture() = 0;
diff --git a/ash/system/tray/system_tray_item.h b/ash/system/tray/system_tray_item.h
index 29fdf8a..a0d7d1b 100644
--- a/ash/system/tray/system_tray_item.h
+++ b/ash/system/tray/system_tray_item.h
@@ -36,7 +36,7 @@ class ASH_EXPORT SystemTrayItem {
// NOTE: The returned view should almost always be a TrayItemView, which
// automatically resizes the widget when the size of the view changes, and
// adds animation when the visibility of the view changes. If a view wants to
- // avoid these behaviour, then it should not be a TrayItemView.
+ // avoid this behavior, then it should not be a TrayItemView.
virtual views::View* CreateTrayView(user::LoginStatus status);
// Returns a view for the item to be displayed in the list. This view can be
diff --git a/ash/system/tray/test_system_tray_delegate.cc b/ash/system/tray/test_system_tray_delegate.cc
index 10dc85c..a833f18 100644
--- a/ash/system/tray/test_system_tray_delegate.cc
+++ b/ash/system/tray/test_system_tray_delegate.cc
@@ -9,9 +9,7 @@
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/volume_control_delegate.h"
-#include "base/utf_string_conversions.h"
#include "base/message_loop.h"
-#include "base/string16.h"
#include "base/time.h"
namespace ash {
@@ -74,18 +72,6 @@ bool TestSystemTrayDelegate::GetTrayVisibilityOnStartup() {
}
// Overridden from SystemTrayDelegate:
-const base::string16 TestSystemTrayDelegate::GetUserDisplayName() const {
- return UTF8ToUTF16("Über tray Über tray Über tray Über tray");
-}
-
-const std::string TestSystemTrayDelegate::GetUserEmail() const {
- return "über@tray";
-}
-
-const gfx::ImageSkia& TestSystemTrayDelegate::GetUserImage() const {
- return null_image_;
-}
-
user::LoginStatus TestSystemTrayDelegate::GetUserLoginStatus() const {
// At new user image screen manager->IsUserLoggedIn() would return true
// but there's no browser session available yet so use SessionStarted().
@@ -105,12 +91,6 @@ bool TestSystemTrayDelegate::IsOobeCompleted() const {
return true;
}
-void TestSystemTrayDelegate::GetLoggedInUsers(UserEmailList* users) {
-}
-
-void TestSystemTrayDelegate::SwitchActiveUser(const std::string& email) {
-}
-
void TestSystemTrayDelegate::ChangeProfilePicture() {
}
diff --git a/ash/system/tray/test_system_tray_delegate.h b/ash/system/tray/test_system_tray_delegate.h
index 8dd1d34..4e44680 100644
--- a/ash/system/tray/test_system_tray_delegate.h
+++ b/ash/system/tray/test_system_tray_delegate.h
@@ -26,13 +26,8 @@ class TestSystemTrayDelegate : public SystemTrayDelegate {
virtual bool GetTrayVisibilityOnStartup() OVERRIDE;
// Overridden from SystemTrayDelegate:
- virtual const base::string16 GetUserDisplayName() const OVERRIDE;
- virtual const std::string GetUserEmail() const OVERRIDE;
- virtual const gfx::ImageSkia& GetUserImage() const OVERRIDE;
virtual user::LoginStatus GetUserLoginStatus() const OVERRIDE;
virtual bool IsOobeCompleted() const OVERRIDE;
- virtual void GetLoggedInUsers(UserEmailList* users) OVERRIDE;
- virtual void SwitchActiveUser(const std::string& email) OVERRIDE;
virtual void ChangeProfilePicture() OVERRIDE;
virtual const std::string GetEnterpriseDomain() const OVERRIDE;
virtual const base::string16 GetEnterpriseMessage() const OVERRIDE;
@@ -124,7 +119,6 @@ class TestSystemTrayDelegate : public SystemTrayDelegate {
bool cellular_enabled_;
bool bluetooth_enabled_;
bool caps_lock_enabled_;
- gfx::ImageSkia null_image_;
scoped_ptr<VolumeControlDelegate> volume_control_delegate_;
DISALLOW_COPY_AND_ASSIGN(TestSystemTrayDelegate);
diff --git a/ash/system/user/login_status.cc b/ash/system/user/login_status.cc
index 77fc04a..acaaf08 100644
--- a/ash/system/user/login_status.cc
+++ b/ash/system/user/login_status.cc
@@ -4,6 +4,8 @@
#include "ash/system/user/login_status.h"
+#include "ash/session_state_delegate.h"
+#include "ash/shell.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "grit/ash_strings.h"
@@ -26,7 +28,12 @@ base::string16 GetLocalizedSignOutStringForStatus(LoginStatus status,
message_id = IDS_ASH_STATUS_TRAY_EXIT_PUBLIC;
break;
default:
- message_id = IDS_ASH_STATUS_TRAY_SIGN_OUT;
+ if (ash::Shell::GetInstance()->session_state_delegate()->
+ NumberOfLoggedInUsers() > 1) {
+ message_id = IDS_ASH_STATUS_TRAY_SIGN_OUT_ALL;
+ } else {
+ message_id = IDS_ASH_STATUS_TRAY_SIGN_OUT;
+ }
break;
}
base::string16 message =
diff --git a/ash/system/user/tray_user.cc b/ash/system/user/tray_user.cc
index 3b4c877..1fb419d 100644
--- a/ash/system/user/tray_user.cc
+++ b/ash/system/user/tray_user.cc
@@ -8,6 +8,7 @@
#include <climits>
#include <vector>
+#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/tray/system_tray.h"
@@ -61,10 +62,18 @@ namespace {
const int kUserDetailsVerticalPadding = 5;
const int kUserCardVerticalPadding = 10;
+const int kInactiveUserCardVerticalPadding = 4;
const int kProfileRoundedCornerRadius = 2;
const int kUserIconSize = 27;
const int kUserLabelToIconPadding = 5;
+// When a hover border is used, it is starting this many pixels before the icon
+// position.
+const int kTrayUserTileHoverBorderInset = 10;
+
+// The border color of the user button.
+const SkColor kBorderColor = 0xffdcdcdc;
+
// The invisible word joiner character, used as a marker to indicate the start
// and end of the user's display name in the public account user card's text.
const char16 kDisplayNameMark[] = { 0x2060, 0 };
@@ -104,8 +113,9 @@ namespace tray {
class RoundedImageView : public views::View {
public:
// Constructs a new rounded image view with rounded corners of radius
- // |corner_radius|.
- explicit RoundedImageView(int corner_radius);
+ // |corner_radius|. If |active_user| is set, the icon will be drawn in
+ // full colors - otherwise it will fade into the background.
+ RoundedImageView(int corner_radius, bool active_user);
virtual ~RoundedImageView();
// Set the image that should be displayed. The image contents is copied to the
@@ -122,17 +132,11 @@ class RoundedImageView : public views::View {
gfx::Size image_size_;
int corner_radius_;
- DISALLOW_COPY_AND_ASSIGN(RoundedImageView);
-};
-
-class ClickableAvatar : public views::CustomButton {
- public:
- ClickableAvatar(views::ButtonListener* listener,
- ash::user::LoginStatus login);
- virtual ~ClickableAvatar();
+ // True if the given user is the active user and the icon should get
+ // painted as active.
+ bool active_user_;
- private:
- DISALLOW_COPY_AND_ASSIGN(ClickableAvatar);
+ DISALLOW_COPY_AND_ASSIGN(RoundedImageView);
};
// The user details shown in public account mode. This is essentially a label
@@ -166,10 +170,31 @@ class PublicAccountUserDetails : public views::View,
DISALLOW_COPY_AND_ASSIGN(PublicAccountUserDetails);
};
+// The button which holds the user card in case of multi profile.
+class UserCard : public views::CustomButton {
+ public:
+ UserCard(views::ButtonListener* listener, bool active_user);
+ virtual ~UserCard();
+
+ // Overridden from views::View
+ virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
+
+ private:
+ // Change the hover/active state of the "button".
+ void ShowActive(bool active);
+
+ // True if this is the active user.
+ bool is_active_user_;
+ DISALLOW_COPY_AND_ASSIGN(UserCard);
+};
+
class UserView : public views::View,
public views::ButtonListener {
public:
- explicit UserView(SystemTrayItem* owner, ash::user::LoginStatus login);
+ UserView(SystemTrayItem* owner,
+ ash::user::LoginStatus login,
+ MultiProfileIndex index);
virtual ~UserView();
private:
@@ -185,15 +210,25 @@ class UserView : public views::View,
void AddLogoutButton(ash::user::LoginStatus login);
void AddUserCard(SystemTrayItem* owner, ash::user::LoginStatus login);
+ // Create a user icon representation for the user card.
+ views::View* CreateIconForUserCard(ash::user::LoginStatus login);
+
+ // Create the additional user card content for the retail logged in mode.
+ void AddLoggedInRetailModeUserCardContent();
+
+ // Create the additional user card content for the public mode.
+ void AddLoggedInPublicModeUserCardContent(SystemTrayItem* owner);
+
+ MultiProfileIndex multiprofile_index_;
views::View* user_card_;
views::View* logout_button_;
- ClickableAvatar* profile_picture_;
DISALLOW_COPY_AND_ASSIGN(UserView);
};
-RoundedImageView::RoundedImageView(int corner_radius)
- : corner_radius_(corner_radius) {}
+RoundedImageView::RoundedImageView(int corner_radius, bool active_user)
+ : corner_radius_(corner_radius),
+ active_user_(active_user) {}
RoundedImageView::~RoundedImageView() {}
@@ -226,31 +261,12 @@ void RoundedImageView::OnPaint(gfx::Canvas* canvas) {
path.addRoundRect(gfx::RectToSkRect(image_bounds), kRadius, kRadius);
SkPaint paint;
paint.setAntiAlias(true);
- paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ paint.setXfermodeMode(active_user_ ? SkXfermode::kSrcOver_Mode :
+ SkXfermode::kLuminosity_Mode);
canvas->DrawImageInPath(resized_, image_bounds.x(), image_bounds.y(),
path, paint);
}
-ClickableAvatar::ClickableAvatar(views::ButtonListener* listener,
- ash::user::LoginStatus login)
- : views::CustomButton(listener) {
- SetLayoutManager(new views::FillLayout());
- RoundedImageView* user_picture =
- new RoundedImageView(kProfileRoundedCornerRadius);
- if (login == ash::user::LOGGED_IN_GUEST) {
- user_picture->SetImage(*ui::ResourceBundle::GetSharedInstance().
- GetImageNamed(IDR_AURA_UBER_TRAY_GUEST_ICON).ToImageSkia(),
- gfx::Size(kUserIconSize, kUserIconSize));
- } else {
- user_picture->SetImage(
- ash::Shell::GetInstance()->system_tray_delegate()->GetUserImage(),
- gfx::Size(kUserIconSize, kUserIconSize));
- }
- AddChildView(user_picture);
-}
-
-ClickableAvatar::~ClickableAvatar() {}
-
PublicAccountUserDetails::PublicAccountUserDetails(SystemTrayItem* owner,
int used_width)
: learn_more_(NULL) {
@@ -261,14 +277,17 @@ PublicAccountUserDetails::PublicAccountUserDetails(SystemTrayItem* owner,
kUserDetailsVerticalPadding, rtl ? 0 : inner_padding,
kUserDetailsVerticalPadding, rtl ? inner_padding : 0));
- ash::SystemTrayDelegate* delegate =
- ash::Shell::GetInstance()->system_tray_delegate();
// Retrieve the user's display name and wrap it with markers.
- base::string16 display_name = delegate->GetUserDisplayName();
+ // Note that since this is a public account it always has to be the primary
+ // user.
+ base::string16 display_name =
+ ash::Shell::GetInstance()->session_state_delegate()->
+ GetUserDisplayName(0);
RemoveChars(display_name, kDisplayNameMark, &display_name);
display_name = kDisplayNameMark[0] + display_name + kDisplayNameMark[0];
// Retrieve the domain managing the device and wrap it with markers.
- base::string16 domain = UTF8ToUTF16(delegate->GetEnterpriseDomain());
+ base::string16 domain = UTF8ToUTF16(
+ ash::Shell::GetInstance()->system_tray_delegate()->GetEnterpriseDomain());
RemoveChars(domain, kDisplayNameMark, &domain);
base::i18n::WrapStringWithLTRFormatting(&domain);
// Retrieve the label text, inserting the display name and domain.
@@ -289,7 +308,7 @@ void PublicAccountUserDetails::Layout() {
lines_.clear();
const gfx::Rect contents_area = GetContentsBounds();
if (contents_area.IsEmpty())
- return;
+ return;
// Word-wrap the label text.
const gfx::Font font;
@@ -425,19 +444,60 @@ void PublicAccountUserDetails::CalculatePreferredSize(SystemTrayItem* owner,
bubble_view->SetWidth(preferred_size_.width() + used_width);
}
-UserView::UserView(SystemTrayItem* owner, ash::user::LoginStatus login)
- : user_card_(NULL),
- logout_button_(NULL),
- profile_picture_(NULL) {
+UserCard::UserCard(views::ButtonListener* listener, bool active_user)
+ : CustomButton(listener),
+ is_active_user_(active_user) {
+ if (is_active_user_) {
+ set_background(
+ views::Background::CreateSolidBackground(kBackgroundColor));
+ ShowActive(false);
+ }
+}
+
+UserCard::~UserCard() {}
+
+void UserCard::OnMouseEntered(const ui::MouseEvent& event) {
+ if (is_active_user_) {
+ background()->SetNativeControlColor(kHoverBackgroundColor);
+ ShowActive(true);
+ SchedulePaint();
+ }
+}
+
+void UserCard::OnMouseExited(const ui::MouseEvent& event) {
+ if (is_active_user_) {
+ background()->SetNativeControlColor(kBackgroundColor);
+ ShowActive(false);
+ SchedulePaint();
+ }
+}
+
+void UserCard::ShowActive(bool active) {
+ int width = active ? 1 : 0;
+ set_border(views::Border::CreateSolidSidedBorder(width, width, width, 1,
+ kBorderColor));
+}
+
+UserView::UserView(SystemTrayItem* owner,
+ ash::user::LoginStatus login,
+ MultiProfileIndex index)
+ : multiprofile_index_(index),
+ user_card_(NULL),
+ logout_button_(NULL) {
CHECK_NE(ash::user::LOGGED_IN_NONE, login);
- set_background(views::Background::CreateSolidBackground(
- login == ash::user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor :
- kBackgroundColor));
+ if (!index) {
+ // Only the logged in user will have a background. All other users will have
+ // to allow the TrayPopupContainer highlighting the menu line.
+ set_background(views::Background::CreateSolidBackground(
+ login == ash::user::LOGGED_IN_PUBLIC ? kPublicAccountBackgroundColor :
+ kBackgroundColor));
+ }
SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
kTrayPopupPaddingBetweenItems));
// The logout button must be added before the user card so that the user card
// can correctly calculate the remaining available width.
- AddLogoutButton(login);
+ // Note that only the current multiprofile user gets a button.
+ AddLogoutButton(!multiprofile_index_ ? login : ash::user::LOGGED_IN_LOCKED);
AddUserCard(owner, login);
}
@@ -445,10 +505,11 @@ UserView::~UserView() {}
gfx::Size UserView::GetPreferredSize() {
gfx::Size size = views::View::GetPreferredSize();
- // Make sure the default user view item is at least as tall as the other
- // items.
- size.set_height(std::max(size.height(),
- kTrayPopupItemHeight + GetInsets().height()));
+ // Only the active user panel will be forced to a certain height.
+ if (!multiprofile_index_) {
+ size.set_height(std::max(size.height(),
+ kTrayPopupItemHeight + GetInsets().height()));
+ }
return size;
}
@@ -463,14 +524,36 @@ void UserView::Layout() {
gfx::Rect logout_area = contents_area;
logout_area.ClampToCenteredSize(logout_button_->GetPreferredSize());
logout_area.set_x(contents_area.right() - logout_area.width());
- logout_button_->SetBoundsRect(logout_area);
// Give the remaining space to the user card.
gfx::Rect user_card_area = contents_area;
- int remaining_width = contents_area.width() -
- (logout_area.width() + kTrayPopupPaddingBetweenItems);
- user_card_area.set_width(std::max(0, remaining_width));
+ int remaining_width = contents_area.width() - logout_area.width();
+ if (ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled()) {
+ // In multiprofile case |user_card_| and |logout_button_| have to have the
+ // same height.
+ int y = std::min(user_card_area.y(), logout_area.y());
+ int height = std::max(user_card_area.height(), logout_area.height());
+ logout_area.set_y(y);
+ logout_area.set_height(height);
+ user_card_area.set_y(y);
+ user_card_area.set_height(height);
+
+ // In multiprofile mode we have also to increase the size of the card by
+ // the size of the border to make it overlap with the logout button.
+ user_card_area.set_width(std::max(0, remaining_width + 1));
+
+ // To make the logout button symmetrical with the user card we also make
+ // the button longer by the same size the hover area in front of the icon
+ // got inset.
+ logout_area.set_width(logout_area.width() +
+ kTrayUserTileHoverBorderInset);
+ } else {
+ // In all other modes we have to make sure that there is enough spacing
+ // between the two.
+ remaining_width -= kTrayPopupPaddingBetweenItems;
+ }
user_card_->SetBoundsRect(user_card_area);
+ logout_button_->SetBoundsRect(logout_area);
} else if (user_card_) {
user_card_->SetBoundsRect(contents_area);
} else if (logout_button_) {
@@ -481,11 +564,29 @@ void UserView::Layout() {
void UserView::ButtonPressed(views::Button* sender, const ui::Event& event) {
if (sender == logout_button_) {
ash::Shell::GetInstance()->system_tray_delegate()->SignOut();
- } else if (sender == profile_picture_) {
- if (ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled())
- ash::Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
- else
- ash::Shell::GetInstance()->system_tray_delegate()->ChangeProfilePicture();
+ } else if (sender == user_card_ &&
+ ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled()) {
+ if (!multiprofile_index_) {
+ // TODO(skuhne): Need to add the images & adding logic here.
+ // TODO(skuhne): Make sure that we do not offer an add when this mode is
+ // active.
+ // TODO(skuhne): Use IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT as
+ // string.
+ const SessionStateDelegate* session_state_delegate =
+ ash::Shell::GetInstance()->session_state_delegate();
+ if (session_state_delegate->NumberOfLoggedInUsers() >=
+ session_state_delegate->GetMaximumNumberOfLoggedInUsers()) {
+ // TODO(skuhne): Use IDS_ASH_STATUS_TRAY_CAPTION_CANNOT_ADD_USER and
+ // IDS_ASH_STATUS_TRAY_MESSAGE_CANNOT_ADD_USER when showing the error
+ // message that no more users can be added.
+ } else {
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowUserLogin();
+ }
+ } else {
+ ash::SessionStateDelegate* delegate =
+ ash::Shell::GetInstance()->session_state_delegate();
+ delegate->SwitchActiveUser(delegate->GetUserEmail(multiprofile_index_));
+ }
} else {
NOTREACHED();
}
@@ -521,53 +622,74 @@ void UserView::AddLogoutButton(ash::user::LoginStatus login) {
void UserView::AddUserCard(SystemTrayItem* owner,
ash::user::LoginStatus login) {
- set_border(views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal,
- 0, kTrayPopupPaddingHorizontal));
+ // Add padding around the panel.
+ set_border(views::Border::CreateEmptyBorder(
+ kUserCardVerticalPadding, kTrayPopupPaddingHorizontal,
+ kUserCardVerticalPadding, kTrayPopupPaddingHorizontal));
+
+ if (ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled() &&
+ login != ash::user::LOGGED_IN_RETAIL_MODE) {
+ user_card_ = new UserCard(this, multiprofile_index_ == 0);
+ } else {
+ user_card_ = new views::View();
+ }
- user_card_ = new views::View();
user_card_->SetLayoutManager(new views::BoxLayout(
- views::BoxLayout::kHorizontal, 0, kUserCardVerticalPadding,
- kTrayPopupPaddingBetweenItems));
+ views::BoxLayout::kHorizontal, 0, 0 , kTrayPopupPaddingBetweenItems));
AddChildViewAt(user_card_, 0);
if (login == ash::user::LOGGED_IN_RETAIL_MODE) {
- views::Label* details = new views::Label;
- ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
- details->SetText(
- bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL));
- details->set_border(views::Border::CreateEmptyBorder(0, 4, 0, 1));
- details->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- user_card_->AddChildView(details);
+ AddLoggedInRetailModeUserCardContent();
return;
}
- profile_picture_ = new ClickableAvatar(this, login);
- user_card_->AddChildView(profile_picture_);
+
+ // The entire user card should trigger hover (the inner items get disabled).
+ user_card_->SetEnabled(true);
if (login == ash::user::LOGGED_IN_PUBLIC) {
- user_card_->AddChildView(new PublicAccountUserDetails(
- owner, GetPreferredSize().width() + kTrayPopupPaddingBetweenItems));
+ AddLoggedInPublicModeUserCardContent(owner);
return;
}
- ash::SystemTrayDelegate* delegate =
- ash::Shell::GetInstance()->system_tray_delegate();
+ views::View* icon = CreateIconForUserCard(login);
+ user_card_->AddChildView(icon);
+
+ // To allow the border to start before the icon, reduce the size before and
+ // add an inset to the icon to get the spacing.
+ if (multiprofile_index_ == 0 &&
+ ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled()) {
+ icon->set_border(views::Border::CreateEmptyBorder(
+ 0, kTrayUserTileHoverBorderInset, 0, 0));
+ set_border(views::Border::CreateEmptyBorder(
+ kUserCardVerticalPadding,
+ kTrayPopupPaddingHorizontal - kTrayUserTileHoverBorderInset,
+ kUserCardVerticalPadding,
+ kTrayPopupPaddingHorizontal));
+ }
+ ash::SessionStateDelegate* delegate =
+ ash::Shell::GetInstance()->session_state_delegate();
views::View* details = new views::View;
+ details->SetEnabled(false);
details->SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kVertical, 0, kUserDetailsVerticalPadding, 0));
-
+ views::Label* username = NULL;
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
- views::Label* username = new views::Label(
- login == ash::user::LOGGED_IN_GUEST ?
- bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_GUEST_LABEL) :
- delegate->GetUserDisplayName());
- username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- details->AddChildView(username);
+ if (!multiprofile_index_) {
+ views::Label* username = new views::Label(
+ login == ash::user::LOGGED_IN_GUEST ?
+ bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_GUEST_LABEL) :
+ delegate->GetUserDisplayName(multiprofile_index_));
+ username->SetEnabled(false);
+ username->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ details->AddChildView(username);
+ }
+ views::Label* additional = NULL;
if (login != ash::user::LOGGED_IN_GUEST) {
- views::Label* additional = new views::Label();
+ additional = new views::Label();
additional->SetText(login == ash::user::LOGGED_IN_LOCALLY_MANAGED ?
bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL) :
- UTF8ToUTF16(delegate->GetUserEmail()));
+ UTF8ToUTF16(delegate->GetUserEmail(multiprofile_index_)));
additional->SetFont(bundle.GetFont(ui::ResourceBundle::SmallFont));
additional->SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -575,13 +697,62 @@ void UserView::AddUserCard(SystemTrayItem* owner,
details->AddChildView(additional);
}
+ // Adjust text properties dependent on if it is an active or inactive user.
+ if (multiprofile_index_) {
+ // Fade the text of non active users to 50%.
+ SkColor text_color = additional->enabled_color();
+ text_color = SkColorSetA(text_color, SkColorGetA(text_color) / 2);
+ if (additional)
+ additional->SetDisabledColor(text_color);
+ if (username)
+ username->SetDisabledColor(text_color);
+ }
+
+ // Use a small font for email address if username exists as well.
+ if (username)
+ additional->SetFont(bundle.GetFont(ui::ResourceBundle::SmallFont));
+
user_card_->AddChildView(details);
}
+views::View* UserView::CreateIconForUserCard(ash::user::LoginStatus login) {
+ RoundedImageView* icon = new RoundedImageView(kProfileRoundedCornerRadius,
+ multiprofile_index_ == 0);
+ icon->SetEnabled(false);
+ if (login == ash::user::LOGGED_IN_GUEST) {
+ icon->SetImage(*ui::ResourceBundle::GetSharedInstance().
+ GetImageNamed(IDR_AURA_UBER_TRAY_GUEST_ICON).ToImageSkia(),
+ gfx::Size(kUserIconSize, kUserIconSize));
+ } else {
+ icon->SetImage(
+ ash::Shell::GetInstance()->session_state_delegate()->
+ GetUserImage(multiprofile_index_),
+ gfx::Size(kUserIconSize, kUserIconSize));
+ }
+ return icon;
+}
+
+void UserView::AddLoggedInRetailModeUserCardContent() {
+ views::Label* details = new views::Label;
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ details->SetText(
+ bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_KIOSK_LABEL));
+ details->set_border(views::Border::CreateEmptyBorder(0, 4, 0, 1));
+ details->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ user_card_->AddChildView(details);
+}
+
+void UserView::AddLoggedInPublicModeUserCardContent(SystemTrayItem* owner) {
+ user_card_->AddChildView(CreateIconForUserCard(ash::user::LOGGED_IN_PUBLIC));
+ user_card_->AddChildView(new PublicAccountUserDetails(
+ owner, GetPreferredSize().width() + kTrayPopupPaddingBetweenItems));
+}
+
} // namespace tray
-TrayUser::TrayUser(SystemTray* system_tray)
+TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index)
: SystemTrayItem(system_tray),
+ multiprofile_index_(index),
user_(NULL),
layout_view_(NULL),
avatar_(NULL),
@@ -595,6 +766,11 @@ TrayUser::~TrayUser() {
views::View* TrayUser::CreateTrayView(user::LoginStatus status) {
CHECK(layout_view_ == NULL);
+ // Only the current user gets an icon. All other users will only be
+ // represented in the tray menu.
+ if (multiprofile_index_)
+ return NULL;
+
layout_view_ = new views::View();
layout_view_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal,
@@ -608,7 +784,24 @@ views::View* TrayUser::CreateDefaultView(user::LoginStatus status) {
return NULL;
CHECK(user_ == NULL);
- user_ = new tray::UserView(this, status);
+
+ const SessionStateDelegate* session_state_delegate =
+ ash::Shell::GetInstance()->session_state_delegate();
+ int logged_in_users = session_state_delegate->NumberOfLoggedInUsers();
+
+ // If there are multiple users logged in, the users will be separated from the
+ // rest of the menu by a separator.
+ if (multiprofile_index_ ==
+ session_state_delegate->GetMaximumNumberOfLoggedInUsers() &&
+ logged_in_users > 1) {
+ return new views::View();
+ }
+
+ // Do not show more UserView's then there are logged in users.
+ if (multiprofile_index_ >= logged_in_users)
+ return NULL;;
+
+ user_ = new tray::UserView(this, status, multiprofile_index_);
return user_;
}
@@ -630,7 +823,9 @@ void TrayUser::DestroyDetailedView() {
}
void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
- CHECK(layout_view_);
+ // Only the active user is represented in the tray.
+ if (!layout_view_)
+ return;
bool need_label = false;
bool need_avatar = false;
switch (status) {
@@ -664,7 +859,7 @@ void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
label_ = NULL;
}
if (need_avatar) {
- avatar_ = new tray::RoundedImageView(kProfileRoundedCornerRadius);
+ avatar_ = new tray::RoundedImageView(kProfileRoundedCornerRadius, true);
layout_view_->AddChildView(avatar_);
} else {
avatar_ = NULL;
@@ -684,14 +879,17 @@ void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
gfx::Size(kUserIconSize, kUserIconSize));
} else {
avatar_->SetImage(
- ash::Shell::GetInstance()->system_tray_delegate()->GetUserImage(),
+ ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
+ multiprofile_index_),
gfx::Size(kUserIconSize, kUserIconSize));
}
}
}
void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
- CHECK(layout_view_);
+ // Inactive users won't have a layout.
+ if (!layout_view_)
+ return;
if (alignment == SHELF_ALIGNMENT_BOTTOM ||
alignment == SHELF_ALIGNMENT_TOP) {
if (avatar_) {
@@ -728,7 +926,8 @@ void TrayUser::OnUserUpdate() {
// Check for null to avoid crbug.com/150944.
if (avatar_) {
avatar_->SetImage(
- ash::Shell::GetInstance()->system_tray_delegate()->GetUserImage(),
+ ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
+ multiprofile_index_),
gfx::Size(kUserIconSize, kUserIconSize));
}
}
diff --git a/ash/system/user/tray_user.h b/ash/system/user/tray_user.h
index 340ab2d..69ad224 100644
--- a/ash/system/user/tray_user.h
+++ b/ash/system/user/tray_user.h
@@ -5,6 +5,7 @@
#ifndef ASH_SYSTEM_USER_TRAY_USER_H_
#define ASH_SYSTEM_USER_TRAY_USER_H_
+#include "ash/session_state_delegate.h"
#include "ash/system/tray/system_tray_item.h"
#include "ash/system/user/user_observer.h"
#include "base/compiler_specific.h"
@@ -25,7 +26,11 @@ class RoundedImageView;
class TrayUser : public SystemTrayItem,
public UserObserver {
public:
- explicit TrayUser(SystemTray* system_tray);
+ // The given |multiprofile_index| is the number of the user in a multi profile
+ // scenario. Index #0 is the running user, the other indices are other
+ // logged in users (if there are any). Only index #0 will add an icon to
+ // the system tray.
+ TrayUser(SystemTray* system_tray, MultiProfileIndex index);
virtual ~TrayUser();
private:
@@ -43,6 +48,9 @@ class TrayUser : public SystemTrayItem,
// Overridden from UserObserver.
virtual void OnUserUpdate() OVERRIDE;
+ // The user index to use.
+ MultiProfileIndex multiprofile_index_;
+
tray::UserView* user_;
// View that contains label and/or avatar.
diff --git a/ash/test/test_session_state_delegate.cc b/ash/test/test_session_state_delegate.cc
index 881f4982..2cff17e 100644
--- a/ash/test/test_session_state_delegate.cc
+++ b/ash/test/test_session_state_delegate.cc
@@ -4,6 +4,9 @@
#include "ash/test/test_session_state_delegate.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+
namespace ash {
namespace test {
@@ -17,8 +20,13 @@ TestSessionStateDelegate::TestSessionStateDelegate()
TestSessionStateDelegate::~TestSessionStateDelegate() {
}
-bool TestSessionStateDelegate::HasActiveUser() const {
- return has_active_user_;
+int TestSessionStateDelegate::GetMaximumNumberOfLoggedInUsers() const {
+ return 3;
+}
+
+int TestSessionStateDelegate::NumberOfLoggedInUsers() const {
+ // TODO(skuhne): Add better test framework to test multiple profiles.
+ return has_active_user_ ? 1 : 0;
}
bool TestSessionStateDelegate::IsActiveUserSessionStarted() const {
@@ -59,5 +67,27 @@ void TestSessionStateDelegate::SetCanLockScreen(bool can_lock_screen) {
can_lock_screen_ = can_lock_screen;
}
+const base::string16 TestSessionStateDelegate::GetUserDisplayName(
+ ash::MultiProfileIndex index) const {
+ return UTF8ToUTF16("Über tray Über tray Über tray Über tray");
+}
+
+const std::string TestSessionStateDelegate::GetUserEmail(
+ ash::MultiProfileIndex index) const {
+ return "über@tray";
+}
+
+const gfx::ImageSkia& TestSessionStateDelegate::GetUserImage(
+ ash::MultiProfileIndex index) const {
+ return null_image_;
+}
+
+void TestSessionStateDelegate::GetLoggedInUsers(UserEmailList* users) {
+}
+
+void TestSessionStateDelegate::SwitchActiveUser(const std::string& email) {
+}
+
+
} // namespace test
} // namespace ash
diff --git a/ash/test/test_session_state_delegate.h b/ash/test/test_session_state_delegate.h
index 807e335..d91bd94 100644
--- a/ash/test/test_session_state_delegate.h
+++ b/ash/test/test_session_state_delegate.h
@@ -8,6 +8,7 @@
#include "ash/session_state_delegate.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "ui/gfx/image/image_skia.h"
namespace ash {
namespace test {
@@ -18,12 +19,21 @@ class TestSessionStateDelegate : public SessionStateDelegate {
virtual ~TestSessionStateDelegate();
// SessionStateDelegate:
- virtual bool HasActiveUser() const OVERRIDE;
+ virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
+ virtual int NumberOfLoggedInUsers() const OVERRIDE;
virtual bool IsActiveUserSessionStarted() const OVERRIDE;
virtual bool CanLockScreen() const OVERRIDE;
virtual bool IsScreenLocked() const OVERRIDE;
virtual void LockScreen() OVERRIDE;
virtual void UnlockScreen() OVERRIDE;
+ virtual const base::string16 GetUserDisplayName(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual const std::string GetUserEmail(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual const gfx::ImageSkia& GetUserImage(
+ ash::MultiProfileIndex index) const OVERRIDE;
+ virtual void GetLoggedInUsers(UserEmailList* users) OVERRIDE;
+ virtual void SwitchActiveUser(const std::string& email) OVERRIDE;
// Updates the internal state that indicates whether a session is in progress
// and there is an active user. If |has_active_user| is |false|,
@@ -58,6 +68,9 @@ class TestSessionStateDelegate : public SessionStateDelegate {
// Whether the screen is currently locked.
bool screen_locked_;
+ // A test user image.
+ gfx::ImageSkia null_image_;
+
DISALLOW_COPY_AND_ASSIGN(TestSessionStateDelegate);
};
diff --git a/ash/wm/gestures/shelf_gesture_handler.cc b/ash/wm/gestures/shelf_gesture_handler.cc
index 847820d..aba69fd 100644
--- a/ash/wm/gestures/shelf_gesture_handler.cc
+++ b/ash/wm/gestures/shelf_gesture_handler.cc
@@ -31,7 +31,7 @@ ShelfGestureHandler::~ShelfGestureHandler() {
bool ShelfGestureHandler::ProcessGestureEvent(const ui::GestureEvent& event) {
Shell* shell = Shell::GetInstance();
- if (!shell->session_state_delegate()->HasActiveUser() ||
+ if (!shell->session_state_delegate()->NumberOfLoggedInUsers() ||
shell->session_state_delegate()->IsScreenLocked()) {
// The gestures are disabled in the lock/login screen.
return false;