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 "chrome/browser/ui/views/session_crashed_bubble_view.h" | 5 #include "chrome/browser/ui/views/session_crashed_bubble_view.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 28 matching lines...) Expand all Loading... |
39 #include "components/strings/grit/components_chromium_strings.h" | 39 #include "components/strings/grit/components_chromium_strings.h" |
40 #include "components/strings/grit/components_google_chrome_strings.h" | 40 #include "components/strings/grit/components_google_chrome_strings.h" |
41 #include "components/strings/grit/components_strings.h" | 41 #include "components/strings/grit/components_strings.h" |
42 #include "content/public/browser/browser_context.h" | 42 #include "content/public/browser/browser_context.h" |
43 #include "content/public/browser/browser_thread.h" | 43 #include "content/public/browser/browser_thread.h" |
44 #include "content/public/browser/notification_source.h" | 44 #include "content/public/browser/notification_source.h" |
45 #include "content/public/browser/web_contents.h" | 45 #include "content/public/browser/web_contents.h" |
46 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
47 #include "ui/views/bubble/bubble_frame_view.h" | 47 #include "ui/views/bubble/bubble_frame_view.h" |
48 #include "ui/views/controls/button/checkbox.h" | 48 #include "ui/views/controls/button/checkbox.h" |
49 #include "ui/views/controls/button/label_button.h" | |
50 #include "ui/views/controls/label.h" | 49 #include "ui/views/controls/label.h" |
51 #include "ui/views/controls/separator.h" | 50 #include "ui/views/controls/separator.h" |
52 #include "ui/views/controls/styled_label.h" | 51 #include "ui/views/controls/styled_label.h" |
| 52 #include "ui/views/layout/fill_layout.h" |
53 #include "ui/views/layout/grid_layout.h" | 53 #include "ui/views/layout/grid_layout.h" |
54 #include "ui/views/layout/layout_constants.h" | 54 #include "ui/views/layout/layout_constants.h" |
55 #include "ui/views/widget/widget.h" | 55 #include "ui/views/widget/widget.h" |
56 | 56 |
57 using views::GridLayout; | 57 using views::GridLayout; |
58 | 58 |
59 namespace { | 59 namespace { |
60 | 60 |
61 // Fixed width of the column holding the description label of the bubble. | 61 // Fixed width of the column holding the description label of the bubble. |
62 const int kWidthOfDescriptionText = 320; | 62 const int kWidthOfDescriptionText = 320; |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 browser->tab_strip_model()->GetActiveWebContents(); | 206 browser->tab_strip_model()->GetActiveWebContents(); |
207 | 207 |
208 if (!web_contents) { | 208 if (!web_contents) { |
209 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ERROR); | 209 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ERROR); |
210 return; | 210 return; |
211 } | 211 } |
212 | 212 |
213 SessionCrashedBubbleView* crash_bubble = | 213 SessionCrashedBubbleView* crash_bubble = |
214 new SessionCrashedBubbleView(anchor_view, browser, web_contents, | 214 new SessionCrashedBubbleView(anchor_view, browser, web_contents, |
215 offer_uma_optin); | 215 offer_uma_optin); |
216 views::BubbleDelegateView::CreateBubble(crash_bubble)->Show(); | 216 views::BubbleDialogDelegateView::CreateBubble(crash_bubble)->Show(); |
217 | 217 |
218 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_SHOWN); | 218 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_SHOWN); |
219 if (uma_opted_in_already) | 219 if (uma_opted_in_already) |
220 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ALREADY_UMA_OPTIN); | 220 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ALREADY_UMA_OPTIN); |
221 } | 221 } |
222 | 222 |
223 SessionCrashedBubbleView::SessionCrashedBubbleView( | 223 SessionCrashedBubbleView::SessionCrashedBubbleView( |
224 views::View* anchor_view, | 224 views::View* anchor_view, |
225 Browser* browser, | 225 Browser* browser, |
226 content::WebContents* web_contents, | 226 content::WebContents* web_contents, |
227 bool offer_uma_optin) | 227 bool offer_uma_optin) |
228 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), | 228 : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), |
229 content::WebContentsObserver(web_contents), | 229 content::WebContentsObserver(web_contents), |
230 browser_(browser), | 230 browser_(browser), |
231 web_contents_(web_contents), | 231 web_contents_(web_contents), |
232 restore_button_(NULL), | |
233 uma_option_(NULL), | 232 uma_option_(NULL), |
234 offer_uma_optin_(offer_uma_optin), | 233 offer_uma_optin_(offer_uma_optin), |
235 started_navigation_(false), | 234 started_navigation_(false), |
236 restored_(false) { | 235 restored_(false) { |
237 set_close_on_deactivate(false); | 236 set_close_on_deactivate(false); |
238 registrar_.Add( | 237 registrar_.Add( |
239 this, | 238 this, |
240 chrome::NOTIFICATION_TAB_CLOSING, | 239 chrome::NOTIFICATION_TAB_CLOSING, |
241 content::Source<content::NavigationController>(&( | 240 content::Source<content::NavigationController>(&( |
242 web_contents->GetController()))); | 241 web_contents->GetController()))); |
243 browser->tab_strip_model()->AddObserver(this); | 242 browser->tab_strip_model()->AddObserver(this); |
244 } | 243 } |
245 | 244 |
246 SessionCrashedBubbleView::~SessionCrashedBubbleView() { | 245 SessionCrashedBubbleView::~SessionCrashedBubbleView() { |
247 browser_->tab_strip_model()->RemoveObserver(this); | 246 browser_->tab_strip_model()->RemoveObserver(this); |
248 } | 247 } |
249 | 248 |
250 views::View* SessionCrashedBubbleView::GetInitiallyFocusedView() { | |
251 return restore_button_; | |
252 } | |
253 | |
254 base::string16 SessionCrashedBubbleView::GetWindowTitle() const { | 249 base::string16 SessionCrashedBubbleView::GetWindowTitle() const { |
255 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE); | 250 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE); |
256 } | 251 } |
257 | 252 |
258 bool SessionCrashedBubbleView::ShouldShowWindowTitle() const { | 253 bool SessionCrashedBubbleView::ShouldShowWindowTitle() const { |
259 return true; | 254 return true; |
260 } | 255 } |
261 | 256 |
262 bool SessionCrashedBubbleView::ShouldShowCloseButton() const { | 257 bool SessionCrashedBubbleView::ShouldShowCloseButton() const { |
263 return true; | 258 return true; |
264 } | 259 } |
265 | 260 |
266 void SessionCrashedBubbleView::OnWidgetDestroying(views::Widget* widget) { | 261 void SessionCrashedBubbleView::OnWidgetDestroying(views::Widget* widget) { |
267 if (!restored_) | 262 if (!restored_) |
268 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED); | 263 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED); |
269 BubbleDelegateView::OnWidgetDestroying(widget); | 264 BubbleDialogDelegateView::OnWidgetDestroying(widget); |
270 } | 265 } |
271 | 266 |
272 void SessionCrashedBubbleView::Init() { | 267 void SessionCrashedBubbleView::Init() { |
| 268 SetLayoutManager(new views::FillLayout()); |
| 269 |
273 // Description text label. | 270 // Description text label. |
274 views::Label* text_label = new views::Label( | 271 views::Label* text_label = new views::Label( |
275 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE)); | 272 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE)); |
276 text_label->SetMultiLine(true); | 273 text_label->SetMultiLine(true); |
277 text_label->SetLineHeight(20); | 274 text_label->SetLineHeight(20); |
278 text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 275 text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
279 text_label->SizeToFit(kWidthOfDescriptionText); | 276 text_label->SizeToFit(kWidthOfDescriptionText); |
280 | 277 AddChildView(text_label); |
281 // Restore button. | |
282 restore_button_ = new views::LabelButton( | |
283 this, l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON)); | |
284 restore_button_->SetStyle(views::Button::STYLE_BUTTON); | |
285 restore_button_->SetIsDefault(true); | |
286 | |
287 GridLayout* layout = new GridLayout(this); | |
288 SetLayoutManager(layout); | |
289 | |
290 // Text row. | |
291 const int kTextColumnSetId = 0; | |
292 views::ColumnSet* cs = layout->AddColumnSet(kTextColumnSetId); | |
293 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, | |
294 GridLayout::FIXED, kWidthOfDescriptionText, 0); | |
295 | |
296 // Restore button row. | |
297 const int kButtonColumnSetId = 1; | |
298 cs = layout->AddColumnSet(kButtonColumnSetId); | |
299 cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 1, | |
300 GridLayout::USE_PREF, 0, 0); | |
301 | |
302 layout->StartRow(0, kTextColumnSetId); | |
303 layout->AddView(text_label); | |
304 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
305 | |
306 layout->StartRow(0, kButtonColumnSetId); | |
307 layout->AddView(restore_button_); | |
308 } | 278 } |
309 | 279 |
310 scoped_ptr<views::View> SessionCrashedBubbleView::CreateFootnoteView() { | 280 views::View* SessionCrashedBubbleView::CreateFootnoteView() { |
311 if (!offer_uma_optin_) | 281 if (!offer_uma_optin_) |
312 return nullptr; | 282 return nullptr; |
313 | 283 |
314 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_OPTIN_BAR_SHOWN); | 284 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_OPTIN_BAR_SHOWN); |
315 | 285 |
316 // Checkbox for metric reporting setting. | 286 // Checkbox for metric reporting setting. |
317 // Since the text to the right of the checkbox can't be a simple string (needs | 287 // Since the text to the right of the checkbox can't be a simple string (needs |
318 // a hyperlink in it), this checkbox contains an empty string as its label, | 288 // a hyperlink in it), this checkbox contains an empty string as its label, |
319 // and the real text will be added as a separate view. | 289 // and the real text will be added as a separate view. |
320 uma_option_ = new views::Checkbox(base::string16()); | 290 uma_option_ = new views::Checkbox(base::string16()); |
(...skipping 18 matching lines...) Expand all Loading... |
339 gfx::Range before_link_range(0, offset); | 309 gfx::Range before_link_range(0, offset); |
340 if (!before_link_range.is_empty()) | 310 if (!before_link_range.is_empty()) |
341 uma_label->AddStyleRange(before_link_range, uma_style); | 311 uma_label->AddStyleRange(before_link_range, uma_style); |
342 gfx::Range after_link_range(offset + link_text.length(), uma_text.length()); | 312 gfx::Range after_link_range(offset + link_text.length(), uma_text.length()); |
343 if (!after_link_range.is_empty()) | 313 if (!after_link_range.is_empty()) |
344 uma_label->AddStyleRange(after_link_range, uma_style); | 314 uma_label->AddStyleRange(after_link_range, uma_style); |
345 // Shift the text down by 1px to align with the checkbox. | 315 // Shift the text down by 1px to align with the checkbox. |
346 uma_label->SetBorder(views::Border::CreateEmptyBorder(1, 0, 0, 0)); | 316 uma_label->SetBorder(views::Border::CreateEmptyBorder(1, 0, 0, 0)); |
347 | 317 |
348 // Create a view to hold the checkbox and the text. | 318 // Create a view to hold the checkbox and the text. |
349 scoped_ptr<views::View> uma_view(new views::View()); | 319 views::View* uma_view = new views::View(); |
350 GridLayout* uma_layout = new GridLayout(uma_view.get()); | 320 GridLayout* uma_layout = new GridLayout(uma_view); |
351 uma_view->SetLayoutManager(uma_layout); | 321 uma_view->SetLayoutManager(uma_layout); |
352 | 322 |
353 const int kReportColumnSetId = 0; | 323 const int kReportColumnSetId = 0; |
354 views::ColumnSet* cs = uma_layout->AddColumnSet(kReportColumnSetId); | 324 views::ColumnSet* cs = uma_layout->AddColumnSet(kReportColumnSetId); |
355 cs->AddColumn(GridLayout::CENTER, GridLayout::LEADING, 0, | 325 cs->AddColumn(GridLayout::CENTER, GridLayout::LEADING, 0, |
356 GridLayout::USE_PREF, 0, 0); | 326 GridLayout::USE_PREF, 0, 0); |
357 cs->AddPaddingColumn(0, kCheckboxTextDistance); | 327 cs->AddPaddingColumn(0, kCheckboxTextDistance); |
358 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, | 328 cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, |
359 0); | 329 0); |
360 | 330 |
361 uma_layout->StartRow(0, kReportColumnSetId); | 331 uma_layout->StartRow(0, kReportColumnSetId); |
362 uma_layout->AddView(uma_option_); | 332 uma_layout->AddView(uma_option_); |
363 uma_layout->AddView(uma_label); | 333 uma_layout->AddView(uma_label); |
364 | 334 |
365 return uma_view; | 335 return uma_view; |
366 } | 336 } |
367 | 337 |
368 void SessionCrashedBubbleView::ButtonPressed(views::Button* sender, | 338 bool SessionCrashedBubbleView::Accept() { |
369 const ui::Event& event) { | 339 RestorePreviousSession(); |
370 DCHECK_EQ(sender, restore_button_); | 340 return true; |
371 RestorePreviousSession(sender); | 341 } |
| 342 |
| 343 bool SessionCrashedBubbleView::Close() { |
| 344 // Don't default to Accept() just because that's the only choice. Instead, do |
| 345 // nothing. |
| 346 return true; |
| 347 } |
| 348 |
| 349 int SessionCrashedBubbleView::GetDialogButtons() const { |
| 350 return ui::DIALOG_BUTTON_OK; |
| 351 } |
| 352 |
| 353 base::string16 SessionCrashedBubbleView::GetDialogButtonLabel( |
| 354 ui::DialogButton button) const { |
| 355 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON); |
372 } | 356 } |
373 | 357 |
374 void SessionCrashedBubbleView::StyledLabelLinkClicked(views::StyledLabel* label, | 358 void SessionCrashedBubbleView::StyledLabelLinkClicked(views::StyledLabel* label, |
375 const gfx::Range& range, | 359 const gfx::Range& range, |
376 int event_flags) { | 360 int event_flags) { |
377 browser_->OpenURL(content::OpenURLParams( | 361 browser_->OpenURL(content::OpenURLParams( |
378 GURL("https://support.google.com/chrome/answer/96817"), | 362 GURL("https://support.google.com/chrome/answer/96817"), |
379 content::Referrer(), | 363 content::Referrer(), |
380 NEW_FOREGROUND_TAB, | 364 NEW_FOREGROUND_TAB, |
381 ui::PAGE_TRANSITION_LINK, | 365 ui::PAGE_TRANSITION_LINK, |
(...skipping 29 matching lines...) Expand all Loading... |
411 if (type == chrome::NOTIFICATION_TAB_CLOSING) | 395 if (type == chrome::NOTIFICATION_TAB_CLOSING) |
412 CloseBubble(); | 396 CloseBubble(); |
413 } | 397 } |
414 | 398 |
415 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents, | 399 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents, |
416 int index) { | 400 int index) { |
417 if (web_contents_ == contents) | 401 if (web_contents_ == contents) |
418 CloseBubble(); | 402 CloseBubble(); |
419 } | 403 } |
420 | 404 |
421 void SessionCrashedBubbleView::RestorePreviousSession(views::Button* sender) { | 405 void SessionCrashedBubbleView::RestorePreviousSession() { |
422 SessionRestore::RestoreSessionAfterCrash(browser_); | 406 SessionRestore::RestoreSessionAfterCrash(browser_); |
423 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_RESTORED); | 407 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_RESTORED); |
424 restored_ = true; | 408 restored_ = true; |
425 | 409 |
426 // Record user's choice for opt-in in to UMA. | 410 // Record user's choice for opt-in in to UMA. |
427 // There's no opt-out choice in the crash restore bubble. | 411 // There's no opt-out choice in the crash restore bubble. |
428 if (uma_option_ && uma_option_->checked()) { | 412 if (uma_option_ && uma_option_->checked()) { |
429 InitiateMetricsReportingChange(true, OnMetricsReportingCallbackType()); | 413 InitiateMetricsReportingChange(true, OnMetricsReportingCallbackType()); |
430 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_UMA_OPTIN); | 414 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_UMA_OPTIN); |
431 } | 415 } |
432 CloseBubble(); | 416 CloseBubble(); |
433 } | 417 } |
434 | 418 |
435 void SessionCrashedBubbleView::CloseBubble() { | 419 void SessionCrashedBubbleView::CloseBubble() { |
436 GetWidget()->Close(); | 420 GetWidget()->Close(); |
437 } | 421 } |
OLD | NEW |