Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/ui/views/critical_notification_bubble_view.cc

Issue 8142028: When critical updates have been installed and the user has been idle for quite some time, show a ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "chrome/browser/ui/views/critical_notification_bubble_view.h"
6
7 #include "base/string_number_conversions.h"
8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/ui/browser_list.h"
10 #include "chrome/browser/upgrade_detector.h"
11 #include "content/browser/user_metrics.h"
12 #include "grit/chromium_strings.h"
13 #include "grit/generated_resources.h"
14 #include "grit/locale_settings.h"
15 #include "grit/theme_resources.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h"
18 #include "views/controls/button/text_button.h"
19 #include "views/controls/image_view.h"
20 #include "views/controls/label.h"
21
22 namespace {
23
24 // Layout constants.
25 const int kPaddingAfterImage = 5;
26 const int kPaddingAboveButtonRow = 4;
27 const int kPaddingBetweenButtons = 7;
28
29 // How long to give the user until auto-restart if no action is taken. The code
30 // assumes this to be less than a minute.
31 const int kCountdownDuration = 30; // Seconds.
32
33 // How often to refresh the bubble UI to update the counter. As long as the
34 // countdown is in seconds, this should be 1000 or lower.
35 const int kRefreshBubbleEvery = 1000; // Millisecond.
36
37 } // namespace
38
39 ////////////////////////////////////////////////////////////////////////////////
40 // CriticalNotificationBubbleView
41
42 Bubble* CriticalNotificationBubbleView::bubble_ = NULL;
43
44 CriticalNotificationBubbleView::CriticalNotificationBubbleView() {
45 bubble_created_ = base::Time::Now();
46
47 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
48
49 image_ = new views::ImageView();
50 image_->SetImage(ResourceBundle::GetSharedInstance().
51 GetBitmapNamed(IDR_UPDATE_MENU3));
52 AddChildView(image_);
53
54 headline_ = new views::Label();
55 headline_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
56 UpdateBubbleHeadline(GetRemainingTime());
57 AddChildView(headline_);
58
59 message_ = new views::Label();
60 message_->SetMultiLine(true);
61 message_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
62 message_->SetText(UTF16ToWide(
63 l10n_util::GetStringFUTF16(IDS_CRITICAL_NOTIFICATION_TEXT,
64 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))));
65 AddChildView(message_);
66
67 restart_button_ = new views::NativeTextButton(this,
68 UTF16ToWide(l10n_util::GetStringUTF16(
69 IDS_CRITICAL_NOTIFICATION_RESTART)));
70 restart_button_->SetIsDefault(true);
71 AddChildView(restart_button_);
72 dismiss_button_ = new views::NativeTextButton(this, UTF16ToWide(
73 l10n_util::GetStringUTF16(IDS_CRITICAL_NOTIFICATION_DISMISS)));
74 AddChildView(dismiss_button_);
75
76 if (bubble_)
77 bubble_->Close();
78
79 refresh_timer_.Start(FROM_HERE,
80 base::TimeDelta::FromMilliseconds(kRefreshBubbleEvery),
81 this, &CriticalNotificationBubbleView::OnCountdown);
82
83 UserMetrics::RecordAction(UserMetricsAction("CriticalNotificationShown"));
84 }
85
86 CriticalNotificationBubbleView::~CriticalNotificationBubbleView() {
87 }
88
89 int CriticalNotificationBubbleView::GetRemainingTime() {
90 base::TimeDelta time_lapsed = base::Time::Now() - bubble_created_;
91 return kCountdownDuration - time_lapsed.InSeconds();
92 }
93
94 void CriticalNotificationBubbleView::UpdateBubbleHeadline(int seconds) {
95 headline_->SetText(UTF16ToWide(
96 l10n_util::GetStringFUTF16(IDS_CRITICAL_NOTIFICATION_HEADLINE,
97 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
98 base::IntToString16(seconds))));
99 }
100
101 void CriticalNotificationBubbleView::OnCountdown() {
102 int seconds = GetRemainingTime();
103 if (seconds <= 0) {
104 // Time's up!
105 UserMetrics::RecordAction(
106 UserMetricsAction("CriticalNotification_AutoRestart"));
107 refresh_timer_.Stop();
108 BrowserList::AttemptRestart();
Ben Goodger (Google) 2011/10/12 15:10:45 btw, what happens if a tab stops shutdown (with an
Finnur 2011/10/13 14:34:10 What happens? Good question. The "Leave-this-page?
109 } else {
110 // Update the counter.
111 UpdateBubbleHeadline(seconds);
112 bubble_->ScheduleDraw();
113 }
114 }
115
116 gfx::Size CriticalNotificationBubbleView::GetPreferredSize() {
117 int width = views::Widget::GetLocalizedContentsWidth(
118 IDS_CRUCIAL_NOTIFICATION_BUBBLE_WIDTH_CHARS);
119 gfx::Size size(width, 0);
120
121 gfx::Size headline = headline_->GetPreferredSize();
122 int height = message_->GetHeightForWidth(size.width());
123 gfx::Size button_row = dismiss_button_->GetPreferredSize();
124
125 size.set_height(headline.height() +
126 height +
127 kPaddingAboveButtonRow +
128 button_row.height());
129 return size;
130 }
131
132 void CriticalNotificationBubbleView::Layout() {
133 gfx::Size bubble_size = GetPreferredSize();
134
135 gfx::Size sz = image_->GetPreferredSize();
136 image_->SetBounds(0, 0, sz.width(), sz.height());
137
138 sz = headline_->GetPreferredSize();
139 headline_->SetBounds(image_->width() + kPaddingAfterImage,
140 (image_->height() - sz.height()) / 2,
141 sz.width(), sz.height());
142
143 sz = message_->GetPreferredSize();
144 int height = message_->GetHeightForWidth(bubble_size.width());
145 message_->SetBounds(0, headline_->height(), bubble_size.width(), height);
146
147 sz = dismiss_button_->GetPreferredSize();
148 dismiss_button_->SetBounds(bubble_size.width() - sz.width(),
149 message_->y() + message_->height() +
150 kPaddingAboveButtonRow,
151 sz.width(),
152 sz.height());
153
154 sz = restart_button_->GetPreferredSize();
155 restart_button_->SetBounds(dismiss_button_->x() - sz.width() -
156 kPaddingBetweenButtons,
157 dismiss_button_->y(),
158 sz.width(),
159 sz.height());
160 }
161
162 void CriticalNotificationBubbleView::ButtonPressed(
163 views::Button* sender, const views::Event& event) {
164 UpgradeDetector::GetInstance()->acknowledge_critical_update();
165
166 if (sender == restart_button_) {
167 UserMetrics::RecordAction(
168 UserMetricsAction("CriticalNotification_Restart"));
169 BrowserList::AttemptRestart();
170 } else if (sender == dismiss_button_) {
171 UserMetrics::RecordAction(UserMetricsAction("CriticalNotification_Ignore"));
172 bubble_->Close();
173 } else {
174 NOTREACHED();
175 }
176 }
177
178 void CriticalNotificationBubbleView::BubbleClosing(Bubble* bubble,
179 bool closed_by_escape) {
180 bubble_ = NULL;
181
182 refresh_timer_.Stop();
183
184 if (closed_by_escape)
185 UpgradeDetector::GetInstance()->acknowledge_critical_update();
186 }
187
188 bool CriticalNotificationBubbleView::CloseOnEscape() {
Ben Goodger (Google) 2011/10/12 15:10:45 general bubble design notes for future reference:
189 return true;
190 }
191
192 bool CriticalNotificationBubbleView::FadeInOnShow() {
193 return true;
194 }
195
196 string16 CriticalNotificationBubbleView::accessible_name() {
197 return ASCIIToWide("CriticalNotification");
198 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698