Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ash / system / user / tray_user.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/system/user/tray_user.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/session/session_state_delegate.h"
10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shell_delegate.h"
12 #include "ash/system/tray/system_tray.h"
13 #include "ash/system/tray/system_tray_delegate.h"
14 #include "ash/system/tray/system_tray_notifier.h"
15 #include "ash/system/tray/tray_constants.h"
16 #include "ash/system/tray/tray_item_view.h"
17 #include "ash/system/tray/tray_utils.h"
18 #include "ash/system/user/accounts_detailed_view.h"
19 #include "ash/system/user/rounded_image_view.h"
20 #include "ash/system/user/user_view.h"
21 #include "base/logging.h"
22 #include "base/strings/string16.h"
23 #include "components/user_manager/user_info.h"
24 #include "grit/ash_strings.h"
25 #include "ui/aura/window.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/gfx/image/image.h"
28 #include "ui/views/border.h"
29 #include "ui/views/controls/label.h"
30 #include "ui/views/layout/box_layout.h"
31 #include "ui/views/view.h"
32 #include "ui/views/widget/widget.h"
33
34 namespace {
35
36 const int kUserLabelToIconPadding = 5;
37
38 }  // namespace
39
40 namespace ash {
41
42 TrayUser::TrayUser(SystemTray* system_tray, MultiProfileIndex index)
43     : SystemTrayItem(system_tray),
44       multiprofile_index_(index),
45       user_(NULL),
46       layout_view_(NULL),
47       avatar_(NULL),
48       label_(NULL) {
49   Shell::GetInstance()->system_tray_notifier()->AddUserObserver(this);
50 }
51
52 TrayUser::~TrayUser() {
53   Shell::GetInstance()->system_tray_notifier()->RemoveUserObserver(this);
54 }
55
56 TrayUser::TestState TrayUser::GetStateForTest() const {
57   if (!user_)
58     return HIDDEN;
59   return user_->GetStateForTest();
60 }
61
62 gfx::Size TrayUser::GetLayoutSizeForTest() const {
63   if (!layout_view_) {
64     return gfx::Size(0, 0);
65   } else {
66     return layout_view_->size();
67   }
68 }
69
70 gfx::Rect TrayUser::GetUserPanelBoundsInScreenForTest() const {
71   DCHECK(user_);
72   return user_->GetBoundsInScreenOfUserButtonForTest();
73 }
74
75 void TrayUser::UpdateAfterLoginStatusChangeForTest(user::LoginStatus status) {
76   UpdateAfterLoginStatusChange(status);
77 }
78
79 views::View* TrayUser::CreateTrayView(user::LoginStatus status) {
80   CHECK(layout_view_ == NULL);
81
82   layout_view_ = new views::View;
83   layout_view_->SetLayoutManager(
84       new views::BoxLayout(views::BoxLayout::kHorizontal,
85                            0, 0, kUserLabelToIconPadding));
86   UpdateAfterLoginStatusChange(status);
87   return layout_view_;
88 }
89
90 views::View* TrayUser::CreateDefaultView(user::LoginStatus status) {
91   if (status == user::LOGGED_IN_NONE)
92     return NULL;
93   const SessionStateDelegate* session_state_delegate =
94       Shell::GetInstance()->session_state_delegate();
95
96   // If the screen is locked or a system modal dialog box is shown, show only
97   // the currently active user.
98   if (multiprofile_index_ &&
99       (session_state_delegate->IsUserSessionBlocked() ||
100        Shell::GetInstance()->IsSystemModalWindowOpen()))
101     return NULL;
102
103   CHECK(user_ == NULL);
104
105   int logged_in_users = session_state_delegate->NumberOfLoggedInUsers();
106
107   // Do not show more UserView's then there are logged in users.
108   if (multiprofile_index_ >= logged_in_users)
109     return NULL;
110
111   user_ = new tray::UserView(this, status, multiprofile_index_, false);
112   return user_;
113 }
114
115 views::View* TrayUser::CreateDetailedView(user::LoginStatus status) {
116   return new tray::AccountsDetailedView(this, status);
117 }
118
119 void TrayUser::DestroyTrayView() {
120   layout_view_ = NULL;
121   avatar_ = NULL;
122   label_ = NULL;
123 }
124
125 void TrayUser::DestroyDefaultView() {
126   user_ = NULL;
127 }
128
129 void TrayUser::DestroyDetailedView() {
130 }
131
132 void TrayUser::UpdateAfterLoginStatusChange(user::LoginStatus status) {
133   // Only the active user is represented in the tray.
134   if (!layout_view_)
135     return;
136   if (GetTrayIndex() > 0)
137     return;
138   bool need_label = false;
139   bool need_avatar = false;
140   SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
141   if (delegate->IsUserSupervised())
142     need_label =  true;
143   switch (status) {
144     case user::LOGGED_IN_LOCKED:
145     case user::LOGGED_IN_USER:
146     case user::LOGGED_IN_OWNER:
147     case user::LOGGED_IN_PUBLIC:
148       need_avatar = true;
149       break;
150     case user::LOGGED_IN_SUPERVISED:
151       need_avatar = true;
152       need_label = true;
153       break;
154     case user::LOGGED_IN_GUEST:
155       need_label = true;
156       break;
157     case user::LOGGED_IN_RETAIL_MODE:
158     case user::LOGGED_IN_KIOSK_APP:
159     case user::LOGGED_IN_NONE:
160       break;
161   }
162
163   if ((need_avatar != (avatar_ != NULL)) ||
164       (need_label != (label_ != NULL))) {
165     layout_view_->RemoveAllChildViews(true);
166     if (need_label) {
167       label_ = new views::Label;
168       SetupLabelForTray(label_);
169       layout_view_->AddChildView(label_);
170     } else {
171       label_ = NULL;
172     }
173     if (need_avatar) {
174       avatar_ = new tray::RoundedImageView(kTrayAvatarCornerRadius, true);
175       layout_view_->AddChildView(avatar_);
176     } else {
177       avatar_ = NULL;
178     }
179   }
180
181   if (delegate->IsUserSupervised()) {
182     label_->SetText(
183         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SUPERVISED_LABEL));
184   } else if (status == user::LOGGED_IN_GUEST) {
185     label_->SetText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_GUEST_LABEL));
186   }
187
188   if (avatar_) {
189     avatar_->SetCornerRadii(
190         0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
191     avatar_->SetBorder(views::Border::NullBorder());
192   }
193   UpdateAvatarImage(status);
194
195   // Update layout after setting label_ and avatar_ with new login status.
196   UpdateLayoutOfItem();
197 }
198
199 void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
200   // Inactive users won't have a layout.
201   if (!layout_view_)
202     return;
203   if (alignment == SHELF_ALIGNMENT_BOTTOM ||
204       alignment == SHELF_ALIGNMENT_TOP) {
205     if (avatar_) {
206       avatar_->SetBorder(views::Border::NullBorder());
207       avatar_->SetCornerRadii(
208           0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius, 0);
209     }
210     if (label_) {
211       // If label_ hasn't figured out its size yet, do that first.
212       if (label_->GetContentsBounds().height() == 0)
213         label_->SizeToPreferredSize();
214       int height = label_->GetContentsBounds().height();
215       int vertical_pad = (kTrayItemSize - height) / 2;
216       int remainder = height % 2;
217       label_->SetBorder(views::Border::CreateEmptyBorder(
218           vertical_pad + remainder,
219           kTrayLabelItemHorizontalPaddingBottomAlignment,
220           vertical_pad,
221           kTrayLabelItemHorizontalPaddingBottomAlignment));
222     }
223     layout_view_->SetLayoutManager(
224         new views::BoxLayout(views::BoxLayout::kHorizontal,
225                              0, 0, kUserLabelToIconPadding));
226   } else {
227     if (avatar_) {
228       avatar_->SetBorder(views::Border::NullBorder());
229       avatar_->SetCornerRadii(
230           0, 0, kTrayAvatarCornerRadius, kTrayAvatarCornerRadius);
231     }
232     if (label_) {
233       label_->SetBorder(views::Border::CreateEmptyBorder(
234           kTrayLabelItemVerticalPaddingVerticalAlignment,
235           kTrayLabelItemHorizontalPaddingBottomAlignment,
236           kTrayLabelItemVerticalPaddingVerticalAlignment,
237           kTrayLabelItemHorizontalPaddingBottomAlignment));
238     }
239     layout_view_->SetLayoutManager(
240         new views::BoxLayout(views::BoxLayout::kVertical,
241                              0, 0, kUserLabelToIconPadding));
242   }
243 }
244
245 void TrayUser::OnUserUpdate() {
246   UpdateAvatarImage(Shell::GetInstance()->system_tray_delegate()->
247       GetUserLoginStatus());
248 }
249
250 void TrayUser::OnUserAddedToSession() {
251   SessionStateDelegate* session_state_delegate =
252       Shell::GetInstance()->session_state_delegate();
253   // Only create views for user items which are logged in.
254   if (GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
255     return;
256
257   // Enforce a layout change that newly added items become visible.
258   UpdateLayoutOfItem();
259
260   // Update the user item.
261   UpdateAvatarImage(
262       Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus());
263 }
264
265 void TrayUser::UpdateAvatarImage(user::LoginStatus status) {
266   SessionStateDelegate* session_state_delegate =
267       Shell::GetInstance()->session_state_delegate();
268   if (!avatar_ ||
269       GetTrayIndex() >= session_state_delegate->NumberOfLoggedInUsers())
270     return;
271
272   content::BrowserContext* context = session_state_delegate->
273       GetBrowserContextByIndex(GetTrayIndex());
274   avatar_->SetImage(session_state_delegate->GetUserInfo(context)->GetImage(),
275                     gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
276
277   // Unit tests might come here with no images for some users.
278   if (avatar_->size().IsEmpty())
279     avatar_->SetSize(gfx::Size(kTrayAvatarSize, kTrayAvatarSize));
280 }
281
282 MultiProfileIndex TrayUser::GetTrayIndex() {
283   Shell* shell = Shell::GetInstance();
284   // If multi profile is not enabled we can use the normal index.
285   if (!shell->delegate()->IsMultiProfilesEnabled())
286     return multiprofile_index_;
287   // In case of multi profile we need to mirror the indices since the system
288   // tray items are in the reverse order then the menu items.
289   return shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers() -
290              1 - multiprofile_index_;
291 }
292
293 void TrayUser::UpdateLayoutOfItem() {
294   RootWindowController* controller = GetRootWindowController(
295       system_tray()->GetWidget()->GetNativeWindow()->GetRootWindow());
296   if (controller && controller->shelf()) {
297     UpdateAfterShelfAlignmentChange(
298         controller->GetShelfLayoutManager()->GetAlignment());
299   }
300 }
301
302 }  // namespace ash