| 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> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
| 18 #include "chrome/browser/chrome_notification_types.h" | 18 #include "chrome/browser/chrome_notification_types.h" |
| 19 #include "chrome/browser/metrics/metrics_reporting_state.h" | 19 #include "chrome/browser/metrics/metrics_reporting_state.h" |
| 20 #include "chrome/browser/prefs/session_startup_pref.h" |
| 20 #include "chrome/browser/sessions/session_restore.h" | 21 #include "chrome/browser/sessions/session_restore.h" |
| 21 #include "chrome/browser/ui/browser_list.h" | 22 #include "chrome/browser/ui/browser_list.h" |
| 22 #include "chrome/browser/ui/browser_list_observer.h" | 23 #include "chrome/browser/ui/browser_list_observer.h" |
| 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 24 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 24 #include "chrome/browser/ui/views/frame/browser_view.h" | 25 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 25 #include "chrome/browser/ui/views/toolbar/app_menu_button.h" | 26 #include "chrome/browser/ui/views/toolbar/app_menu_button.h" |
| 26 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" | 27 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" |
| 27 #include "chrome/common/url_constants.h" | 28 #include "chrome/common/url_constants.h" |
| 28 #include "chrome/grit/chromium_strings.h" | 29 #include "chrome/grit/chromium_strings.h" |
| 29 #include "chrome/grit/generated_resources.h" | 30 #include "chrome/grit/generated_resources.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 62 |
| 62 enum SessionCrashedBubbleHistogramValue { | 63 enum SessionCrashedBubbleHistogramValue { |
| 63 SESSION_CRASHED_BUBBLE_SHOWN, | 64 SESSION_CRASHED_BUBBLE_SHOWN, |
| 64 SESSION_CRASHED_BUBBLE_ERROR, | 65 SESSION_CRASHED_BUBBLE_ERROR, |
| 65 SESSION_CRASHED_BUBBLE_RESTORED, | 66 SESSION_CRASHED_BUBBLE_RESTORED, |
| 66 SESSION_CRASHED_BUBBLE_ALREADY_UMA_OPTIN, | 67 SESSION_CRASHED_BUBBLE_ALREADY_UMA_OPTIN, |
| 67 SESSION_CRASHED_BUBBLE_UMA_OPTIN, | 68 SESSION_CRASHED_BUBBLE_UMA_OPTIN, |
| 68 SESSION_CRASHED_BUBBLE_HELP, | 69 SESSION_CRASHED_BUBBLE_HELP, |
| 69 SESSION_CRASHED_BUBBLE_IGNORED, | 70 SESSION_CRASHED_BUBBLE_IGNORED, |
| 70 SESSION_CRASHED_BUBBLE_OPTIN_BAR_SHOWN, | 71 SESSION_CRASHED_BUBBLE_OPTIN_BAR_SHOWN, |
| 72 SESSION_CRASHED_BUBBLE_STARTUP_PAGES, |
| 71 SESSION_CRASHED_BUBBLE_MAX, | 73 SESSION_CRASHED_BUBBLE_MAX, |
| 72 }; | 74 }; |
| 73 | 75 |
| 74 void RecordBubbleHistogramValue(SessionCrashedBubbleHistogramValue value) { | 76 void RecordBubbleHistogramValue(SessionCrashedBubbleHistogramValue value) { |
| 75 UMA_HISTOGRAM_ENUMERATION( | 77 UMA_HISTOGRAM_ENUMERATION( |
| 76 "SessionCrashed.Bubble", value, SESSION_CRASHED_BUBBLE_MAX); | 78 "SessionCrashed.Bubble", value, SESSION_CRASHED_BUBBLE_MAX); |
| 77 } | 79 } |
| 78 | 80 |
| 79 // Whether or not the bubble UI should be used. | 81 // Whether or not the bubble UI should be used. |
| 80 // TODO(crbug.com/653966): Enable this on all desktop platforms. | 82 // TODO(crbug.com/653966): Enable this on all desktop platforms. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 Browser* browser, | 197 Browser* browser, |
| 196 content::WebContents* web_contents, | 198 content::WebContents* web_contents, |
| 197 bool offer_uma_optin) | 199 bool offer_uma_optin) |
| 198 : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), | 200 : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), |
| 199 content::WebContentsObserver(web_contents), | 201 content::WebContentsObserver(web_contents), |
| 200 browser_(browser), | 202 browser_(browser), |
| 201 web_contents_(web_contents), | 203 web_contents_(web_contents), |
| 202 uma_option_(NULL), | 204 uma_option_(NULL), |
| 203 offer_uma_optin_(offer_uma_optin), | 205 offer_uma_optin_(offer_uma_optin), |
| 204 first_navigation_ignored_(false), | 206 first_navigation_ignored_(false), |
| 205 restored_(false) { | 207 ignored_(true) { |
| 206 set_close_on_deactivate(false); | 208 set_close_on_deactivate(false); |
| 207 registrar_.Add( | 209 registrar_.Add( |
| 208 this, | 210 this, |
| 209 chrome::NOTIFICATION_TAB_CLOSING, | 211 chrome::NOTIFICATION_TAB_CLOSING, |
| 210 content::Source<content::NavigationController>(&( | 212 content::Source<content::NavigationController>(&( |
| 211 web_contents->GetController()))); | 213 web_contents->GetController()))); |
| 212 browser->tab_strip_model()->AddObserver(this); | 214 browser->tab_strip_model()->AddObserver(this); |
| 213 } | 215 } |
| 214 | 216 |
| 215 SessionCrashedBubbleView::~SessionCrashedBubbleView() { | 217 SessionCrashedBubbleView::~SessionCrashedBubbleView() { |
| 216 browser_->tab_strip_model()->RemoveObserver(this); | 218 browser_->tab_strip_model()->RemoveObserver(this); |
| 217 } | 219 } |
| 218 | 220 |
| 219 base::string16 SessionCrashedBubbleView::GetWindowTitle() const { | 221 base::string16 SessionCrashedBubbleView::GetWindowTitle() const { |
| 220 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE); | 222 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE); |
| 221 } | 223 } |
| 222 | 224 |
| 223 bool SessionCrashedBubbleView::ShouldShowWindowTitle() const { | 225 bool SessionCrashedBubbleView::ShouldShowWindowTitle() const { |
| 224 return true; | 226 return true; |
| 225 } | 227 } |
| 226 | 228 |
| 227 bool SessionCrashedBubbleView::ShouldShowCloseButton() const { | 229 bool SessionCrashedBubbleView::ShouldShowCloseButton() const { |
| 228 return true; | 230 return true; |
| 229 } | 231 } |
| 230 | 232 |
| 231 void SessionCrashedBubbleView::OnWidgetDestroying(views::Widget* widget) { | 233 void SessionCrashedBubbleView::OnWidgetDestroying(views::Widget* widget) { |
| 232 if (!restored_) | 234 if (ignored_) |
| 233 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED); | 235 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED); |
| 234 BubbleDialogDelegateView::OnWidgetDestroying(widget); | 236 BubbleDialogDelegateView::OnWidgetDestroying(widget); |
| 235 } | 237 } |
| 236 | 238 |
| 237 void SessionCrashedBubbleView::Init() { | 239 void SessionCrashedBubbleView::Init() { |
| 238 SetLayoutManager(new views::FillLayout()); | 240 SetLayoutManager(new views::FillLayout()); |
| 239 | 241 |
| 240 // Description text label. | 242 // Description text label. |
| 241 views::Label* text_label = new views::Label( | 243 views::Label* text_label = new views::Label( |
| 242 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE)); | 244 l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 uma_layout->AddView(uma_label); | 305 uma_layout->AddView(uma_label); |
| 304 | 306 |
| 305 return uma_view; | 307 return uma_view; |
| 306 } | 308 } |
| 307 | 309 |
| 308 bool SessionCrashedBubbleView::Accept() { | 310 bool SessionCrashedBubbleView::Accept() { |
| 309 RestorePreviousSession(); | 311 RestorePreviousSession(); |
| 310 return true; | 312 return true; |
| 311 } | 313 } |
| 312 | 314 |
| 315 // The cancel button is used as an option to open the startup pages instead of |
| 316 // restoring the previous session. |
| 317 bool SessionCrashedBubbleView::Cancel() { |
| 318 OpenStartupPages(); |
| 319 return true; |
| 320 } |
| 321 |
| 313 bool SessionCrashedBubbleView::Close() { | 322 bool SessionCrashedBubbleView::Close() { |
| 314 // Don't default to Accept() just because that's the only choice. Instead, do | 323 // Don't default to Accept() just because that's the only choice. Instead, do |
| 315 // nothing. | 324 // nothing. |
| 316 return true; | 325 return true; |
| 317 } | 326 } |
| 318 | 327 |
| 319 int SessionCrashedBubbleView::GetDialogButtons() const { | 328 int SessionCrashedBubbleView::GetDialogButtons() const { |
| 320 return ui::DIALOG_BUTTON_OK; | 329 int buttons = ui::DIALOG_BUTTON_OK; |
| 330 // Offer the option to open the startup pages using the cancel button, but |
| 331 // only when the user has selected the URLS option, and set at least one url. |
| 332 SessionStartupPref session_startup_pref = |
| 333 SessionStartupPref::GetStartupPref(browser_->profile()); |
| 334 if (session_startup_pref.type == SessionStartupPref::URLS && |
| 335 !session_startup_pref.urls.empty()) { |
| 336 buttons |= ui::DIALOG_BUTTON_CANCEL; |
| 337 } |
| 338 return buttons; |
| 321 } | 339 } |
| 322 | 340 |
| 323 base::string16 SessionCrashedBubbleView::GetDialogButtonLabel( | 341 base::string16 SessionCrashedBubbleView::GetDialogButtonLabel( |
| 324 ui::DialogButton button) const { | 342 ui::DialogButton button) const { |
| 325 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON); | 343 if (button == ui::DIALOG_BUTTON_OK) |
| 344 return l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON); |
| 345 DCHECK_EQ(ui::DIALOG_BUTTON_CANCEL, button); |
| 346 return l10n_util::GetStringUTF16( |
| 347 IDS_SESSION_CRASHED_VIEW_STARTUP_PAGES_BUTTON); |
| 326 } | 348 } |
| 327 | 349 |
| 328 void SessionCrashedBubbleView::StyledLabelLinkClicked(views::StyledLabel* label, | 350 void SessionCrashedBubbleView::StyledLabelLinkClicked(views::StyledLabel* label, |
| 329 const gfx::Range& range, | 351 const gfx::Range& range, |
| 330 int event_flags) { | 352 int event_flags) { |
| 331 browser_->OpenURL(content::OpenURLParams( | 353 browser_->OpenURL(content::OpenURLParams( |
| 332 GURL("https://support.google.com/chrome/answer/96817"), | 354 GURL("https://support.google.com/chrome/answer/96817"), |
| 333 content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, | 355 content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, |
| 334 ui::PAGE_TRANSITION_LINK, false)); | 356 ui::PAGE_TRANSITION_LINK, false)); |
| 335 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_HELP); | 357 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_HELP); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 CloseBubble(); | 390 CloseBubble(); |
| 369 } | 391 } |
| 370 | 392 |
| 371 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents, | 393 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents, |
| 372 int index) { | 394 int index) { |
| 373 if (web_contents_ == contents) | 395 if (web_contents_ == contents) |
| 374 CloseBubble(); | 396 CloseBubble(); |
| 375 } | 397 } |
| 376 | 398 |
| 377 void SessionCrashedBubbleView::RestorePreviousSession() { | 399 void SessionCrashedBubbleView::RestorePreviousSession() { |
| 400 ignored_ = false; |
| 401 MaybeEnableUMA(); |
| 402 CloseBubble(); |
| 403 |
| 404 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_RESTORED); |
| 405 // Restoring tabs has side effects, so it's preferable to do it after the |
| 406 // bubble was closed. |
| 378 SessionRestore::RestoreSessionAfterCrash(browser_); | 407 SessionRestore::RestoreSessionAfterCrash(browser_); |
| 379 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_RESTORED); | 408 } |
| 380 restored_ = true; | |
| 381 | 409 |
| 410 void SessionCrashedBubbleView::OpenStartupPages() { |
| 411 ignored_ = false; |
| 412 MaybeEnableUMA(); |
| 413 CloseBubble(); |
| 414 |
| 415 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_STARTUP_PAGES); |
| 416 // Opening tabs has side effects, so it's preferable to do it after the bubble |
| 417 // was closed. |
| 418 SessionRestore::OpenStartupPagesAfterCrash(browser_); |
| 419 } |
| 420 |
| 421 void SessionCrashedBubbleView::MaybeEnableUMA() { |
| 382 // Record user's choice for opt-in in to UMA. | 422 // Record user's choice for opt-in in to UMA. |
| 383 // There's no opt-out choice in the crash restore bubble. | 423 // There's no opt-out choice in the crash restore bubble. |
| 384 if (uma_option_ && uma_option_->checked()) { | 424 if (uma_option_ && uma_option_->checked()) { |
| 385 ChangeMetricsReportingState(true); | 425 ChangeMetricsReportingState(true); |
| 386 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_UMA_OPTIN); | 426 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_UMA_OPTIN); |
| 387 } | 427 } |
| 388 CloseBubble(); | |
| 389 } | 428 } |
| 390 | 429 |
| 391 void SessionCrashedBubbleView::CloseBubble() { | 430 void SessionCrashedBubbleView::CloseBubble() { |
| 392 GetWidget()->Close(); | 431 GetWidget()->Close(); |
| 393 } | 432 } |
| OLD | NEW |