Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / ui / views / session_crashed_bubble_view.cc
blob0e39368136c5d030c657098a18e87aadbf1a4317
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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/session_crashed_bubble_view.h"
7 #include <vector>
9 #include "base/prefs/pref_service.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/sessions/session_restore.h"
13 #include "chrome/browser/ui/options/options_util.h"
14 #include "chrome/browser/ui/startup/session_crashed_bubble.h"
15 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/browser/ui/views/frame/browser_view.h"
18 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/installer/util/google_update_settings.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/notification_source.h"
24 #include "content/public/browser/web_contents.h"
25 #include "grit/chromium_strings.h"
26 #include "grit/generated_resources.h"
27 #include "grit/ui_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/views/controls/button/checkbox.h"
31 #include "ui/views/controls/button/label_button.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/link.h"
34 #include "ui/views/controls/separator.h"
35 #include "ui/views/layout/grid_layout.h"
36 #include "ui/views/layout/layout_constants.h"
37 #include "ui/views/widget/widget.h"
39 using views::GridLayout;
41 namespace {
43 // Fixed width of the column holding the description label of the bubble.
44 const int kWidthOfDescriptionText = 320;
46 // Margins width for the top rows to compensate for the bottom panel for which
47 // we don't want any margin.
48 const int kMarginWidth = 12;
49 const int kMarginHeight = kMarginWidth;
51 // The color of the background of the sub panel to offer UMA optin.
52 const SkColor kLightGrayBackgroundColor = 0xFFF0F0F0;
53 const SkColor kWhiteBackgroundColor = 0xFFFFFFFF;
55 bool ShouldOfferMetricsReporting() {
56 // Stats collection only applies to Google Chrome builds.
57 #if defined(GOOGLE_CHROME_BUILD)
58 // Only show metrics reporting option if user didn't already consent to it.
59 if (GoogleUpdateSettings::GetCollectStatsConsent())
60 return false;
61 return g_browser_process->local_state()->FindPreference(
62 prefs::kMetricsReportingEnabled)->IsUserModifiable();
63 #else
64 return false;
65 #endif // defined(GOOGLE_CHROME_BUILD)
68 } // namespace
70 // static
71 void SessionCrashedBubbleView::Show(Browser* browser) {
72 if (browser->profile()->IsOffTheRecord())
73 return;
75 views::View* anchor_view =
76 BrowserView::GetBrowserViewForBrowser(browser)->toolbar()->app_menu();
77 content::WebContents* web_contents =
78 browser->tab_strip_model()->GetActiveWebContents();
79 SessionCrashedBubbleView* crash_bubble =
80 new SessionCrashedBubbleView(anchor_view, browser, web_contents);
81 views::BubbleDelegateView::CreateBubble(crash_bubble)->Show();
84 SessionCrashedBubbleView::SessionCrashedBubbleView(
85 views::View* anchor_view,
86 Browser* browser,
87 content::WebContents* web_contents)
88 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
89 content::WebContentsObserver(web_contents),
90 browser_(browser),
91 web_contents_(web_contents),
92 restore_button_(NULL),
93 close_(NULL),
94 uma_option_(NULL),
95 started_navigation_(false) {
96 set_close_on_deactivate(false);
97 registrar_.Add(
98 this,
99 chrome::NOTIFICATION_TAB_CLOSING,
100 content::Source<content::NavigationController>(&(
101 web_contents->GetController())));
102 browser->tab_strip_model()->AddObserver(this);
105 SessionCrashedBubbleView::~SessionCrashedBubbleView() {
106 browser_->tab_strip_model()->RemoveObserver(this);
109 views::View* SessionCrashedBubbleView::GetInitiallyFocusedView() {
110 return restore_button_;
113 void SessionCrashedBubbleView::Init() {
114 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
116 // Close button.
117 close_ = new views::LabelButton(this, base::string16());
118 close_->SetImage(views::CustomButton::STATE_NORMAL,
119 *rb->GetImageNamed(IDR_CLOSE_2).ToImageSkia());
120 close_->SetImage(views::CustomButton::STATE_HOVERED,
121 *rb->GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
122 close_->SetImage(views::CustomButton::STATE_PRESSED,
123 *rb->GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
124 close_->SetSize(close_->GetPreferredSize());
125 close_->SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
127 // Bubble title label.
128 views::Label* title_label = new views::Label(
129 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE));
130 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
131 title_label->SetFontList(rb->GetFontList(ui::ResourceBundle::BoldFont));
133 // Description text label.
134 views::Label* text_label = new views::Label(
135 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE));
136 text_label->SetMultiLine(true);
137 text_label->SetLineHeight(20);
138 text_label->SetEnabledColor(SK_ColorDKGRAY);
139 text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
141 // Learn more link
142 views::Link* learn_more_link = NULL;
143 if (ShouldOfferMetricsReporting()) {
144 learn_more_link = new views::Link(
145 l10n_util::GetStringUTF16(IDS_LEARN_MORE));
146 learn_more_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
147 learn_more_link->set_listener(this);
148 learn_more_link->SetUnderline(false);
151 // Restore button.
152 restore_button_ = new views::LabelButton(
153 this, l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON));
154 restore_button_->SetStyle(views::Button::STYLE_BUTTON);
155 restore_button_->SetIsDefault(true);
156 restore_button_->SetFontList(rb->GetFontList(ui::ResourceBundle::BoldFont));
158 GridLayout* layout = new GridLayout(this);
159 SetLayoutManager(layout);
161 // Title and close button row.
162 const int kTitleColumnSetId = 0;
163 views::ColumnSet* cs = layout->AddColumnSet(kTitleColumnSetId);
164 cs->AddPaddingColumn(0, kMarginWidth);
165 cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
166 GridLayout::USE_PREF, 0, 0);
167 cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
168 cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
169 GridLayout::USE_PREF, 0, 0);
171 // Text row.
172 const int kTextColumnSetId = 1;
173 cs = layout->AddColumnSet(kTextColumnSetId);
174 cs->AddPaddingColumn(0, kMarginWidth);
175 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
176 GridLayout::FIXED, kWidthOfDescriptionText, 0);
178 // Learn more link and restore button row
179 const int kLinkAndButtonColumnSetId = 2;
180 cs = layout->AddColumnSet(kLinkAndButtonColumnSetId);
181 cs->AddPaddingColumn(0, kMarginWidth);
182 if (learn_more_link) {
183 cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
184 GridLayout::USE_PREF, 0, 0);
186 cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
187 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
188 GridLayout::USE_PREF, 0, 0);
189 cs->AddPaddingColumn(0, kMarginWidth);
191 layout->AddPaddingRow(0, kMarginHeight);
192 layout->StartRow(0, kTitleColumnSetId);
193 layout->AddView(title_label);
194 layout->AddView(close_);
195 layout->AddPaddingRow(0, kMarginHeight);
197 layout->StartRow(0, kTextColumnSetId);
198 layout->AddView(text_label);
199 layout->AddPaddingRow(0, kMarginHeight);
201 layout->StartRow(0, kLinkAndButtonColumnSetId);
202 if (learn_more_link)
203 layout->AddView(learn_more_link);
204 layout->AddView(restore_button_);
205 layout->AddPaddingRow(0, kMarginHeight);
207 // Metrics reporting option.
208 if (learn_more_link)
209 CreateUmaOptinView(layout);
211 set_color(kWhiteBackgroundColor);
212 set_margins(gfx::Insets());
213 Layout();
216 void SessionCrashedBubbleView::CreateUmaOptinView(GridLayout* layout) {
217 // Checkbox for metric reporting setting.
218 uma_option_ = new views::Checkbox(
219 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_UMA_OPTIN));
220 uma_option_->SetTextColor(views::Button::STATE_NORMAL, SK_ColorGRAY);
221 uma_option_->SetChecked(false);
222 uma_option_->SetTextMultiLine(true);
223 uma_option_->set_background(
224 views::Background::CreateSolidBackground(kLightGrayBackgroundColor));
225 uma_option_->set_listener(this);
226 // We use a border instead of padding so that the background color reach
227 // the edges of the bubble.
228 uma_option_->SetBorder(
229 views::Border::CreateSolidSidedBorder(
230 kMarginHeight, kMarginWidth, kMarginHeight, kMarginWidth,
231 kLightGrayBackgroundColor));
233 // Separator.
234 const int kSeparatorColumnSetId = 3;
235 views::ColumnSet* cs = layout->AddColumnSet(kSeparatorColumnSetId);
236 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
237 GridLayout::FIXED, kWidthOfDescriptionText + kMarginWidth, 0);
239 // Reporting row.
240 const int kReportColumnSetId = 4;
241 cs = layout->AddColumnSet(kReportColumnSetId);
242 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
243 GridLayout::FIXED, kWidthOfDescriptionText + kMarginWidth, 0);
245 layout->StartRow(0, kSeparatorColumnSetId);
246 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
247 layout->StartRow(0, kReportColumnSetId);
248 layout->AddView(uma_option_);
251 void SessionCrashedBubbleView::ButtonPressed(views::Button* sender,
252 const ui::Event& event) {
253 DCHECK(sender);
254 if (sender == restore_button_)
255 RestorePreviousSession(sender);
256 else if (sender == close_)
257 CloseBubble();
260 void SessionCrashedBubbleView::LinkClicked(views::Link* source,
261 int event_flags) {
262 browser_->OpenURL(content::OpenURLParams(
263 GURL("https://support.google.com/chrome/answer/96817"),
264 content::Referrer(),
265 NEW_FOREGROUND_TAB,
266 content::PAGE_TRANSITION_LINK,
267 false));
270 void SessionCrashedBubbleView::DidStartNavigationToPendingEntry(
271 const GURL& url,
272 content::NavigationController::ReloadType reload_type) {
273 started_navigation_ = true;
276 void SessionCrashedBubbleView::DidFinishLoad(
277 int64 frame_id,
278 const GURL& validated_url,
279 bool is_main_frame,
280 content::RenderViewHost* render_view_host) {
281 if (started_navigation_)
282 CloseBubble();
285 void SessionCrashedBubbleView::WasShown() {
286 GetWidget()->Show();
289 void SessionCrashedBubbleView::WasHidden() {
290 GetWidget()->Hide();
293 void SessionCrashedBubbleView::Observe(
294 int type,
295 const content::NotificationSource& source,
296 const content::NotificationDetails& details) {
297 if (type == chrome::NOTIFICATION_TAB_CLOSING)
298 CloseBubble();
301 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents,
302 int index) {
303 if (web_contents_ == contents)
304 CloseBubble();
307 void SessionCrashedBubbleView::RestorePreviousSession(views::Button* sender) {
308 SessionRestore::RestoreSessionAfterCrash(browser_);
310 // Record user's choice for opting in to UMA.
311 // There's no opting-out choice in the crash restore bubble.
312 if (uma_option_ && uma_option_->checked())
313 OptionsUtil::ResolveMetricsReportingEnabled(true);
314 CloseBubble();
317 void SessionCrashedBubbleView::CloseBubble() {
318 GetWidget()->Close();
321 bool ShowSessionCrashedBubble(Browser* browser) {
322 SessionCrashedBubbleView::Show(browser);
323 return true;