OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/system/chromeos/session/tray_session_length_limit.h" | 5 #include "ash/system/chromeos/session/tray_session_length_limit.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/shelf/shelf_types.h" | |
10 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ash/system/chromeos/label_tray_view.h" | |
11 #include "ash/system/system_notifier.h" | 11 #include "ash/system/system_notifier.h" |
12 #include "ash/system/tray/system_tray.h" | 12 #include "ash/system/tray/system_tray.h" |
13 #include "ash/system/tray/system_tray_delegate.h" | 13 #include "ash/system/tray/system_tray_delegate.h" |
14 #include "ash/system/tray/system_tray_notifier.h" | 14 #include "ash/system/tray/system_tray_notifier.h" |
15 #include "ash/system/tray/tray_constants.h" | |
16 #include "ash/system/tray/tray_utils.h" | |
17 #include "base/location.h" | |
18 #include "base/logging.h" | 15 #include "base/logging.h" |
19 #include "base/strings/string16.h" | |
20 #include "base/strings/string_number_conversions.h" | |
21 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
22 #include "grit/ash_resources.h" | 17 #include "grit/ash_resources.h" |
23 #include "grit/ash_strings.h" | 18 #include "grit/ash_strings.h" |
24 #include "third_party/skia/include/core/SkColor.h" | |
25 #include "ui/base/l10n/l10n_util.h" | 19 #include "ui/base/l10n/l10n_util.h" |
26 #include "ui/base/l10n/time_format.h" | 20 #include "ui/base/l10n/time_format.h" |
27 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
28 #include "ui/gfx/font_list.h" | |
29 #include "ui/message_center/message_center.h" | 22 #include "ui/message_center/message_center.h" |
30 #include "ui/message_center/notification.h" | 23 #include "ui/message_center/notification.h" |
31 #include "ui/views/border.h" | |
32 #include "ui/views/controls/label.h" | |
33 #include "ui/views/layout/box_layout.h" | |
34 #include "ui/views/layout/grid_layout.h" | |
35 #include "ui/views/view.h" | 24 #include "ui/views/view.h" |
36 | 25 |
37 using message_center::Notification; | |
38 | |
39 namespace ash { | 26 namespace ash { |
40 namespace { | 27 namespace { |
41 | 28 |
42 // If the remaining session time falls below this threshold, the user should be | 29 // If the remaining session time falls below this threshold, the user should be |
43 // informed that the session is about to expire. | 30 // informed that the session is about to expire. |
44 const int kExpiringSoonThresholdInSeconds = 5 * 60; // 5 minutes. | 31 const int kExpiringSoonThresholdInMinutes = 5; |
45 | 32 |
46 // Color in which the remaining session time is normally shown. | 33 // Use 500ms interval for updates to notification and tray bubble to reduce the |
47 const SkColor kRemainingTimeColor = SK_ColorWHITE; | 34 // likelihood of a user-visible skip in high load situations (as might happen |
48 // Color in which the remaining session time is shown when it is expiring soon. | 35 // with 1000ms). |
49 const SkColor kRemainingTimeExpiringSoonColor = SK_ColorRED; | 36 const int kTimerIntervalInMilliseconds = 500; |
50 | |
51 views::Label* CreateAndSetupLabel() { | |
52 views::Label* label = new views::Label; | |
53 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
54 SetupLabelForTray(label); | |
55 label->SetFontList(label->font_list().DeriveWithStyle( | |
56 label->font_list().GetFontStyle() & ~gfx::Font::BOLD)); | |
57 return label; | |
58 } | |
59 | |
60 base::string16 IntToTwoDigitString(int value) { | |
61 DCHECK_GE(value, 0); | |
62 DCHECK_LE(value, 99); | |
63 if (value < 10) | |
64 return base::ASCIIToUTF16("0") + base::IntToString16(value); | |
65 return base::IntToString16(value); | |
66 } | |
67 | |
68 base::string16 FormatRemainingSessionTimeNotification( | |
69 const base::TimeDelta& remaining_session_time) { | |
70 return l10n_util::GetStringFUTF16( | |
71 IDS_ASH_STATUS_TRAY_REMAINING_SESSION_TIME_NOTIFICATION, | |
72 ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, | |
73 ui::TimeFormat::LENGTH_LONG, | |
74 10, | |
75 remaining_session_time)); | |
76 } | |
77 | |
78 // Creates, or updates the notification for session length timeout with | |
79 // |remaining_time|. |state_changed| is true when its internal state has been | |
80 // changed from another. | |
81 void CreateOrUpdateNotification(const std::string& notification_id, | |
82 const base::TimeDelta& remaining_time, | |
83 bool state_changed) { | |
84 message_center::MessageCenter* message_center = | |
85 message_center::MessageCenter::Get(); | |
86 | |
87 // Do not create a new notification if no state has changed. It may happen | |
88 // when the notification is already closed by the user, see crbug.com/285941. | |
89 if (!state_changed && !message_center->HasNotification(notification_id)) | |
90 return; | |
91 | |
92 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
93 message_center::RichNotificationData data; | |
94 // Makes the spoken feedback only when the state has been changed. | |
95 data.should_make_spoken_feedback_for_popup_updates = state_changed; | |
96 scoped_ptr<Notification> notification(new Notification( | |
97 message_center::NOTIFICATION_TYPE_SIMPLE, | |
98 notification_id, | |
99 FormatRemainingSessionTimeNotification(remaining_time), | |
100 base::string16() /* message */, | |
101 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_SESSION_LENGTH_LIMIT_TIMER), | |
102 base::string16() /* display_source */, | |
103 message_center::NotifierId( | |
104 message_center::NotifierId::SYSTEM_COMPONENT, | |
105 system_notifier::kNotifierSessionLengthTimeout), | |
106 data, | |
107 NULL /* delegate */)); | |
108 notification->SetSystemPriority(); | |
109 message_center::MessageCenter::Get()->AddNotification(notification.Pass()); | |
110 } | |
111 | 37 |
112 } // namespace | 38 } // namespace |
113 | 39 |
114 namespace tray { | |
115 | |
116 class RemainingSessionTimeTrayView : public views::View { | |
117 public: | |
118 RemainingSessionTimeTrayView(const TraySessionLengthLimit* owner, | |
119 ShelfAlignment shelf_alignment); | |
120 virtual ~RemainingSessionTimeTrayView(); | |
121 | |
122 void UpdateClockLayout(ShelfAlignment shelf_alignment); | |
123 void Update(); | |
124 | |
125 private: | |
126 void SetBorderFromAlignment(ShelfAlignment shelf_alignment); | |
127 | |
128 const TraySessionLengthLimit* owner_; | |
129 | |
130 views::Label* horizontal_layout_label_; | |
131 views::Label* vertical_layout_label_hours_left_; | |
132 views::Label* vertical_layout_label_hours_right_; | |
133 views::Label* vertical_layout_label_minutes_left_; | |
134 views::Label* vertical_layout_label_minutes_right_; | |
135 views::Label* vertical_layout_label_seconds_left_; | |
136 views::Label* vertical_layout_label_seconds_right_; | |
137 | |
138 DISALLOW_COPY_AND_ASSIGN(RemainingSessionTimeTrayView); | |
139 }; | |
140 | |
141 RemainingSessionTimeTrayView::RemainingSessionTimeTrayView( | |
142 const TraySessionLengthLimit* owner, | |
143 ShelfAlignment shelf_alignment) | |
144 : owner_(owner), | |
145 horizontal_layout_label_(NULL), | |
146 vertical_layout_label_hours_left_(NULL), | |
147 vertical_layout_label_hours_right_(NULL), | |
148 vertical_layout_label_minutes_left_(NULL), | |
149 vertical_layout_label_minutes_right_(NULL), | |
150 vertical_layout_label_seconds_left_(NULL), | |
151 vertical_layout_label_seconds_right_(NULL) { | |
152 UpdateClockLayout(shelf_alignment); | |
153 } | |
154 | |
155 RemainingSessionTimeTrayView::~RemainingSessionTimeTrayView() { | |
156 } | |
157 | |
158 void RemainingSessionTimeTrayView::UpdateClockLayout( | |
159 ShelfAlignment shelf_alignment) { | |
160 SetBorderFromAlignment(shelf_alignment); | |
161 const bool horizontal_layout = (shelf_alignment == SHELF_ALIGNMENT_BOTTOM || | |
162 shelf_alignment == SHELF_ALIGNMENT_TOP); | |
163 if (horizontal_layout && !horizontal_layout_label_) { | |
164 // Remove labels used for vertical layout. | |
165 RemoveAllChildViews(true); | |
166 vertical_layout_label_hours_left_ = NULL; | |
167 vertical_layout_label_hours_right_ = NULL; | |
168 vertical_layout_label_minutes_left_ = NULL; | |
169 vertical_layout_label_minutes_right_ = NULL; | |
170 vertical_layout_label_seconds_left_ = NULL; | |
171 vertical_layout_label_seconds_right_ = NULL; | |
172 | |
173 // Create label used for horizontal layout. | |
174 horizontal_layout_label_ = CreateAndSetupLabel(); | |
175 | |
176 // Construct layout. | |
177 SetLayoutManager( | |
178 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); | |
179 AddChildView(horizontal_layout_label_); | |
180 | |
181 } else if (!horizontal_layout && horizontal_layout_label_) { | |
182 // Remove label used for horizontal layout. | |
183 RemoveAllChildViews(true); | |
184 horizontal_layout_label_ = NULL; | |
185 | |
186 // Create labels used for vertical layout. | |
187 vertical_layout_label_hours_left_ = CreateAndSetupLabel(); | |
188 vertical_layout_label_hours_right_ = CreateAndSetupLabel(); | |
189 vertical_layout_label_minutes_left_ = CreateAndSetupLabel(); | |
190 vertical_layout_label_minutes_right_ = CreateAndSetupLabel(); | |
191 vertical_layout_label_seconds_left_ = CreateAndSetupLabel(); | |
192 vertical_layout_label_seconds_right_ = CreateAndSetupLabel(); | |
193 | |
194 // Construct layout. | |
195 views::GridLayout* layout = new views::GridLayout(this); | |
196 SetLayoutManager(layout); | |
197 views::ColumnSet* columns = layout->AddColumnSet(0); | |
198 columns->AddPaddingColumn(0, 6); | |
199 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, | |
200 0, views::GridLayout::USE_PREF, 0, 0); | |
201 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, | |
202 0, views::GridLayout::USE_PREF, 0, 0); | |
203 layout->AddPaddingRow(0, kTrayLabelItemVerticalPaddingVerticalAlignment); | |
204 layout->StartRow(0, 0); | |
205 layout->AddView(vertical_layout_label_hours_left_); | |
206 layout->AddView(vertical_layout_label_hours_right_); | |
207 layout->StartRow(0, 0); | |
208 layout->AddView(vertical_layout_label_minutes_left_); | |
209 layout->AddView(vertical_layout_label_minutes_right_); | |
210 layout->StartRow(0, 0); | |
211 layout->AddView(vertical_layout_label_seconds_left_); | |
212 layout->AddView(vertical_layout_label_seconds_right_); | |
213 layout->AddPaddingRow(0, kTrayLabelItemVerticalPaddingVerticalAlignment); | |
214 } | |
215 Update(); | |
216 } | |
217 | |
218 void RemainingSessionTimeTrayView::Update() { | |
219 const TraySessionLengthLimit::LimitState limit_state = | |
220 owner_->GetLimitState(); | |
221 | |
222 if (limit_state == TraySessionLengthLimit::LIMIT_NONE) { | |
223 SetVisible(false); | |
224 return; | |
225 } | |
226 | |
227 int seconds = owner_->GetRemainingSessionTime().InSeconds(); | |
228 // If the remaining session time is 100 hours or more, show 99:59:59 instead. | |
229 seconds = std::min(seconds, 100 * 60 * 60 - 1); // 100 hours - 1 second. | |
230 int minutes = seconds / 60; | |
231 seconds %= 60; | |
232 const int hours = minutes / 60; | |
233 minutes %= 60; | |
234 | |
235 const base::string16 hours_str = IntToTwoDigitString(hours); | |
236 const base::string16 minutes_str = IntToTwoDigitString(minutes); | |
237 const base::string16 seconds_str = IntToTwoDigitString(seconds); | |
238 const SkColor color = | |
239 limit_state == TraySessionLengthLimit::LIMIT_EXPIRING_SOON ? | |
240 kRemainingTimeExpiringSoonColor : kRemainingTimeColor; | |
241 | |
242 if (horizontal_layout_label_) { | |
243 horizontal_layout_label_->SetText(l10n_util::GetStringFUTF16( | |
244 IDS_ASH_STATUS_TRAY_REMAINING_SESSION_TIME, | |
245 hours_str, minutes_str, seconds_str)); | |
246 horizontal_layout_label_->SetEnabledColor(color); | |
247 } else if (vertical_layout_label_hours_left_) { | |
248 vertical_layout_label_hours_left_->SetText(hours_str.substr(0, 1)); | |
249 vertical_layout_label_hours_right_->SetText(hours_str.substr(1, 1)); | |
250 vertical_layout_label_minutes_left_->SetText(minutes_str.substr(0, 1)); | |
251 vertical_layout_label_minutes_right_->SetText(minutes_str.substr(1, 1)); | |
252 vertical_layout_label_seconds_left_->SetText(seconds_str.substr(0, 1)); | |
253 vertical_layout_label_seconds_right_->SetText(seconds_str.substr(1, 1)); | |
254 vertical_layout_label_hours_left_->SetEnabledColor(color); | |
255 vertical_layout_label_hours_right_->SetEnabledColor(color); | |
256 vertical_layout_label_minutes_left_->SetEnabledColor(color); | |
257 vertical_layout_label_minutes_right_->SetEnabledColor(color); | |
258 vertical_layout_label_seconds_left_->SetEnabledColor(color); | |
259 vertical_layout_label_seconds_right_->SetEnabledColor(color); | |
260 } | |
261 | |
262 Layout(); | |
263 SetVisible(true); | |
264 } | |
265 | |
266 void RemainingSessionTimeTrayView::SetBorderFromAlignment( | |
267 ShelfAlignment shelf_alignment) { | |
268 if (shelf_alignment == SHELF_ALIGNMENT_BOTTOM || | |
269 shelf_alignment == SHELF_ALIGNMENT_TOP) { | |
270 SetBorder(views::Border::CreateEmptyBorder( | |
271 0, | |
272 kTrayLabelItemHorizontalPaddingBottomAlignment, | |
273 0, | |
274 kTrayLabelItemHorizontalPaddingBottomAlignment)); | |
275 } else { | |
276 SetBorder(views::Border::NullBorder()); | |
277 } | |
278 } | |
279 | |
280 } // namespace tray | |
281 | |
282 // static | 40 // static |
283 const char TraySessionLengthLimit::kNotificationId[] = | 41 const char TraySessionLengthLimit::kNotificationId[] = |
284 "chrome://session/timeout"; | 42 "chrome://session/timeout"; |
285 | 43 |
286 TraySessionLengthLimit::TraySessionLengthLimit(SystemTray* system_tray) | 44 TraySessionLengthLimit::TraySessionLengthLimit(SystemTray* system_tray) |
287 : SystemTrayItem(system_tray), | 45 : SystemTrayItem(system_tray), |
288 tray_view_(NULL), | 46 limit_state_(LIMIT_NONE), |
289 limit_state_(LIMIT_NONE) { | 47 last_limit_state_(LIMIT_NONE), |
48 tray_bubble_view_(NULL) { | |
290 Shell::GetInstance()->system_tray_notifier()-> | 49 Shell::GetInstance()->system_tray_notifier()-> |
291 AddSessionLengthLimitObserver(this); | 50 AddSessionLengthLimitObserver(this); |
292 Update(); | 51 Update(); |
293 } | 52 } |
294 | 53 |
295 TraySessionLengthLimit::~TraySessionLengthLimit() { | 54 TraySessionLengthLimit::~TraySessionLengthLimit() { |
296 Shell::GetInstance()->system_tray_notifier()-> | 55 Shell::GetInstance()->system_tray_notifier()-> |
297 RemoveSessionLengthLimitObserver(this); | 56 RemoveSessionLengthLimitObserver(this); |
298 } | 57 } |
299 | 58 |
300 views::View* TraySessionLengthLimit::CreateTrayView(user::LoginStatus status) { | 59 base::string16 TraySessionLengthLimit::ComposeNotificationMessage() const { |
bartfab (slow)
2014/05/06 17:57:00
Nit 1: Re-arrange methods so that their implementa
Thiemo Nagel
2014/05/06 18:49:06
Done.
| |
301 CHECK(tray_view_ == NULL); | 60 return l10n_util::GetStringFUTF16( |
302 tray_view_ = new tray::RemainingSessionTimeTrayView( | 61 IDS_ASH_STATUS_TRAY_NOTIFICATION_SESSION_LENGTH_LIMIT, |
303 this, system_tray()->shelf_alignment()); | 62 ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, |
304 return tray_view_; | 63 ui::TimeFormat::LENGTH_LONG, |
64 10, | |
65 remaining_session_time_)); | |
305 } | 66 } |
306 | 67 |
307 void TraySessionLengthLimit::DestroyTrayView() { | 68 base::string16 TraySessionLengthLimit::ComposeTrayBubbleMessage() const { |
308 tray_view_ = NULL; | 69 return l10n_util::GetStringFUTF16( |
70 IDS_ASH_STATUS_TRAY_BUBBLE_SESSION_LENGTH_LIMIT, | |
71 ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, | |
72 ui::TimeFormat::LENGTH_LONG, | |
73 10, | |
74 remaining_session_time_)); | |
309 } | 75 } |
310 | 76 |
311 void TraySessionLengthLimit::UpdateAfterShelfAlignmentChange( | 77 // Add view to tray bubble. |
312 ShelfAlignment alignment) { | 78 views::View* TraySessionLengthLimit::CreateDefaultView( |
313 if (tray_view_) | 79 user::LoginStatus status) { |
314 tray_view_->UpdateClockLayout(alignment); | 80 CHECK(!tray_bubble_view_); |
81 UpdateState(); | |
82 if (limit_state_ == LIMIT_NONE) | |
83 return NULL; | |
84 tray_bubble_view_ = new LabelTrayView( | |
85 this, IDR_AURA_UBER_TRAY_BUBBLE_SESSION_LENGTH_LIMIT); | |
86 tray_bubble_view_->SetMessage(ComposeTrayBubbleMessage()); | |
87 return tray_bubble_view_; | |
88 } | |
89 | |
90 // View has been removed from tray bubble. | |
91 void TraySessionLengthLimit::DestroyDefaultView() { | |
92 tray_bubble_view_ = NULL; | |
315 } | 93 } |
316 | 94 |
317 void TraySessionLengthLimit::OnSessionStartTimeChanged() { | 95 void TraySessionLengthLimit::OnSessionStartTimeChanged() { |
318 Update(); | 96 Update(); |
319 } | 97 } |
320 | 98 |
321 void TraySessionLengthLimit::OnSessionLengthLimitChanged() { | 99 void TraySessionLengthLimit::OnSessionLengthLimitChanged() { |
322 Update(); | 100 Update(); |
323 } | 101 } |
324 | 102 |
325 TraySessionLengthLimit::LimitState | 103 void TraySessionLengthLimit::OnViewClicked(views::View* sender) { |
bartfab (slow)
2014/05/06 17:57:00
What is the point of being a ViewClickListener if
Thiemo Nagel
2014/05/06 18:49:06
Mindless cut&paste. Fixed.
| |
326 TraySessionLengthLimit::GetLimitState() const { | |
327 return limit_state_; | |
328 } | |
329 | |
330 base::TimeDelta TraySessionLengthLimit::GetRemainingSessionTime() const { | |
331 return remaining_session_time_; | |
332 } | 104 } |
333 | 105 |
334 void TraySessionLengthLimit::Update() { | 106 void TraySessionLengthLimit::Update() { |
107 UpdateState(); | |
108 UpdateNotification(); | |
109 UpdateTrayBubbleView(); | |
110 } | |
111 | |
112 void TraySessionLengthLimit::UpdateState() { | |
335 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); | 113 SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate(); |
336 const LimitState previous_limit_state = limit_state_; | 114 if (delegate->GetSessionStartTime(&session_start_time_) && |
337 if (!delegate->GetSessionStartTime(&session_start_time_) || | 115 delegate->GetSessionLengthLimit(&time_limit_)) { |
338 !delegate->GetSessionLengthLimit(&limit_)) { | 116 const base::TimeDelta expiring_soon_threshold( |
117 base::TimeDelta::FromMinutes(kExpiringSoonThresholdInMinutes)); | |
118 remaining_session_time_ = std::max( | |
119 time_limit_ - (base::TimeTicks::Now() - session_start_time_), | |
120 base::TimeDelta()); | |
121 limit_state_ = remaining_session_time_ <= expiring_soon_threshold ? | |
122 LIMIT_EXPIRING_SOON : LIMIT_SET; | |
123 if (!timer_) | |
124 timer_.reset(new base::RepeatingTimer<TraySessionLengthLimit>); | |
125 if (!timer_->IsRunning()) { | |
126 timer_->Start(FROM_HERE, | |
127 base::TimeDelta::FromMilliseconds( | |
128 kTimerIntervalInMilliseconds), | |
129 this, | |
130 &TraySessionLengthLimit::Update); | |
131 } | |
132 } else { | |
339 remaining_session_time_ = base::TimeDelta(); | 133 remaining_session_time_ = base::TimeDelta(); |
340 limit_state_ = LIMIT_NONE; | 134 limit_state_ = LIMIT_NONE; |
bartfab (slow)
2014/05/06 17:57:00
Nit: Reset last_limit_state_.
Thiemo Nagel
2014/05/06 18:49:06
This must happen in UpdateNotification(), otherwis
| |
341 timer_.reset(); | 135 timer_.reset(); |
342 } else { | 136 } |
343 remaining_session_time_ = std::max( | 137 } |
344 limit_ - (base::TimeTicks::Now() - session_start_time_), | 138 |
345 base::TimeDelta()); | 139 void TraySessionLengthLimit::UpdateNotification() { |
346 limit_state_ = remaining_session_time_.InSeconds() <= | 140 message_center::MessageCenter* message_center = |
347 kExpiringSoonThresholdInSeconds ? LIMIT_EXPIRING_SOON : LIMIT_SET; | 141 message_center::MessageCenter::Get(); |
348 if (!timer_) | 142 |
349 timer_.reset(new base::RepeatingTimer<TraySessionLengthLimit>); | 143 // If state hasn't changed and the notification has already been acknowledged, |
350 if (!timer_->IsRunning()) { | 144 // we won't re-create it. |
351 // Start a timer that will update the remaining session time every second. | 145 if (limit_state_ == last_limit_state_ && |
352 timer_->Start(FROM_HERE, | 146 !message_center->HasNotification(kNotificationId)) { |
353 base::TimeDelta::FromSeconds(1), | 147 return; |
354 this, | |
355 &TraySessionLengthLimit::Update); | |
356 } | |
357 } | 148 } |
358 | 149 |
359 switch (limit_state_) { | 150 // After state change, any possibly existing notification is removed to make |
360 case LIMIT_NONE: | 151 // sure it is re-shown even if it had been acknowledged by the user before |
361 message_center::MessageCenter::Get()->RemoveNotification( | 152 // (and in the rare case of state change towards LIMIT_NONE to make the |
362 kNotificationId, false /* by_user */); | 153 // notification disappear). |
363 break; | 154 if (limit_state_ != last_limit_state_ && |
364 case LIMIT_SET: | 155 message_center->HasNotification(kNotificationId)) { |
365 CreateOrUpdateNotification( | 156 message_center::MessageCenter::Get()->RemoveNotification( |
366 kNotificationId, | 157 kNotificationId, false /* by_user */); |
367 remaining_session_time_, | |
368 previous_limit_state == LIMIT_NONE); | |
369 break; | |
370 case LIMIT_EXPIRING_SOON: | |
371 CreateOrUpdateNotification( | |
372 kNotificationId, | |
373 remaining_session_time_, | |
374 previous_limit_state == LIMIT_NONE || | |
375 previous_limit_state == LIMIT_SET); | |
376 break; | |
377 } | 158 } |
378 | 159 |
379 // Update the tray view last so that it can check whether the notification | 160 // For LIMIT_NONE, there's nothing more to do. |
380 // view is currently visible or not. | 161 if (limit_state_ == LIMIT_NONE) { |
381 if (tray_view_) | 162 last_limit_state_ = limit_state_; |
382 tray_view_->Update(); | 163 return; |
164 } | |
165 | |
166 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | |
167 message_center::RichNotificationData data; | |
168 data.should_make_spoken_feedback_for_popup_updates = | |
169 (limit_state_ != last_limit_state_); | |
170 scoped_ptr<message_center::Notification> notification( | |
171 new message_center::Notification( | |
172 message_center::NOTIFICATION_TYPE_SIMPLE, | |
173 kNotificationId, | |
174 base::string16() /* title */, | |
175 ComposeNotificationMessage() /* message */, | |
176 bundle.GetImageNamed( | |
177 IDR_AURA_UBER_TRAY_NOTIFICATION_SESSION_LENGTH_LIMIT), | |
178 base::string16() /* display_source */, | |
179 message_center::NotifierId( | |
180 message_center::NotifierId::SYSTEM_COMPONENT, | |
181 system_notifier::kNotifierSessionLengthTimeout), | |
182 data, | |
183 NULL /* delegate */)); | |
184 notification->SetSystemPriority(); | |
185 if (message_center->HasNotification(kNotificationId)) | |
186 message_center->UpdateNotification(kNotificationId, notification.Pass()); | |
187 else | |
188 message_center->AddNotification(notification.Pass()); | |
189 last_limit_state_ = limit_state_; | |
383 } | 190 } |
384 | 191 |
385 bool TraySessionLengthLimit::IsTrayViewVisibleForTest() { | 192 void TraySessionLengthLimit::UpdateTrayBubbleView() const { |
386 return tray_view_ && tray_view_->visible(); | 193 if (!tray_bubble_view_) |
194 return; | |
195 if (limit_state_ == LIMIT_NONE) | |
196 tray_bubble_view_->SetMessage(base::string16()); | |
197 else | |
198 tray_bubble_view_->SetMessage(ComposeTrayBubbleMessage()); | |
199 tray_bubble_view_->Layout(); | |
387 } | 200 } |
388 | 201 |
389 } // namespace ash | 202 } // namespace ash |
OLD | NEW |