Show bubble to prompt UMA opt-in on crash recovery
BUG=293702
Review URL: https://codereview.chromium.org/224033002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267223 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index e1e6d81..53d78fc 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1679,6 +1679,13 @@
SINGLE_VALUE_TYPE(switches::kEnablePermissionsBubbles)
},
{
+ "enable-session-crashed-bubble",
+ IDS_FLAGS_ENABLE_SESSION_CRASHED_BUBBLE_NAME,
+ IDS_FLAGS_ENABLE_SESSION_CRASHED_BUBBLE_DESCRIPTION,
+ kOsWin | kOsLinux,
+ SINGLE_VALUE_TYPE(switches::kEnableSessionCrashedBubble)
+ },
+ {
"out-of-process-pdf",
IDS_FLAGS_OUT_OF_PROCESS_PDF_NAME,
IDS_FLAGS_OUT_OF_PROCESS_PDF_DESCRIPTION,
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index fc6c0f2..cf069bb 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/performance_monitor/startup_timer.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/search.h"
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_types.h"
@@ -36,6 +37,7 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
+#include "chrome/common/url_constants.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/navigation_controller.h"
@@ -1202,6 +1204,24 @@
}
// static
+void SessionRestore::RestoreSessionAfterCrash(Browser* browser) {
+ uint32 behavior = 0;
+ if (browser->tab_strip_model()->count() == 1) {
+ const content::WebContents* active_tab =
+ browser->tab_strip_model()->GetWebContentsAt(0);
+ if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
+ chrome::IsInstantNTP(active_tab)) {
+ // There is only one tab and its the new tab page, make session restore
+ // clobber it.
+ behavior = SessionRestore::CLOBBER_CURRENT_TAB;
+ }
+ }
+ SessionRestore::RestoreSession(browser->profile(), browser,
+ browser->host_desktop_type(), behavior,
+ std::vector<GURL>());
+}
+
+// static
std::vector<Browser*> SessionRestore::RestoreForeignSessionWindows(
Profile* profile,
chrome::HostDesktopType host_desktop_type,
diff --git a/chrome/browser/sessions/session_restore.h b/chrome/browser/sessions/session_restore.h
index 7dc2f7b8..0072bf6 100644
--- a/chrome/browser/sessions/session_restore.h
+++ b/chrome/browser/sessions/session_restore.h
@@ -52,6 +52,10 @@
uint32 behavior,
const std::vector<GURL>& urls_to_open);
+ // Restores the last session when the last session crashed. It's a wrapper
+ // of function RestoreSession.
+ static void RestoreSessionAfterCrash(Browser* browser);
+
// Specifically used in the restoration of a foreign session. This function
// restores the given session windows to multiple browsers all of which
// will be created on the desktop specified by |host_desktop_type|. Returns
diff --git a/chrome/browser/ui/startup/session_crashed_bubble.cc b/chrome/browser/ui/startup/session_crashed_bubble.cc
new file mode 100644
index 0000000..f158e9b
--- /dev/null
+++ b/chrome/browser/ui/startup/session_crashed_bubble.cc
@@ -0,0 +1,9 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/startup/session_crashed_bubble.h"
+
+bool ShowSessionCrashedBubble(Browser* browser) {
+ return false;
+}
diff --git a/chrome/browser/ui/startup/session_crashed_bubble.h b/chrome/browser/ui/startup/session_crashed_bubble.h
new file mode 100644
index 0000000..f74436f
--- /dev/null
+++ b/chrome/browser/ui/startup/session_crashed_bubble.h
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_STARTUP_SESSION_CRASHED_BUBBLE_H_
+#define CHROME_BROWSER_UI_STARTUP_SESSION_CRASHED_BUBBLE_H_
+
+class Browser;
+
+// Create a session recovery bubble if the last session crashed. It also offers
+// the option to enable metrics reporting if it's not already enabled. Function
+// returns true if a bubble is created, returns false if nothing is created.
+bool ShowSessionCrashedBubble(Browser* browser);
+
+#endif // CHROME_BROWSER_UI_STARTUP_SESSION_CRASHED_BUBBLE_H_
diff --git a/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc b/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
index c51df57..bc6eb02 100644
--- a/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/session_crashed_infobar_delegate.cc
@@ -72,23 +72,9 @@
}
bool SessionCrashedInfoBarDelegate::Accept() {
- uint32 behavior = 0;
- content::WebContents* web_contents =
- InfoBarService::WebContentsFromInfoBar(infobar());
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
- if (browser->tab_strip_model()->count() == 1) {
- const content::WebContents* active_tab =
- browser->tab_strip_model()->GetWebContentsAt(0);
- if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
- chrome::IsInstantNTP(active_tab)) {
- // There is only one tab and its the new tab page, make session restore
- // clobber it.
- behavior = SessionRestore::CLOBBER_CURRENT_TAB;
- }
- }
- SessionRestore::RestoreSession(browser->profile(), browser,
- browser->host_desktop_type(), behavior,
- std::vector<GURL>());
+ Browser* browser = chrome::FindBrowserWithWebContents(
+ InfoBarService::WebContentsFromInfoBar(infobar()));
+ SessionRestore::RestoreSessionAfterCrash(browser);
accepted_ = true;
return true;
}
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 5d346aca..f281cc0 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -66,6 +66,7 @@
#include "chrome/browser/ui/startup/default_browser_prompt.h"
#include "chrome/browser/ui/startup/google_api_keys_infobar_delegate.h"
#include "chrome/browser/ui/startup/obsolete_system_infobar_delegate.h"
+#include "chrome/browser/ui/startup/session_crashed_bubble.h"
#include "chrome/browser/ui/startup/session_crashed_infobar_delegate.h"
#include "chrome/browser/ui/startup/startup_browser_creator.h"
#include "chrome/browser/ui/tabs/pinned_tab_codec.h"
@@ -844,8 +845,11 @@
if (!browser || !profile_ || browser->tab_strip_model()->count() == 0)
return;
- if (HasPendingUncleanExit(browser->profile()))
- SessionCrashedInfoBarDelegate::Create(browser);
+ if (HasPendingUncleanExit(browser->profile())) {
+ if (!command_line_.HasSwitch(switches::kEnableSessionCrashedBubble) ||
+ !ShowSessionCrashedBubble(browser))
+ SessionCrashedInfoBarDelegate::Create(browser);
+ }
// The below info bars are only added to the first profile which is launched.
// Other profiles might be restoring the browsing sessions asynchronously,
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc
new file mode 100644
index 0000000..61075487
--- /dev/null
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -0,0 +1,325 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/session_crashed_bubble_view.h"
+
+#include <vector>
+
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/sessions/session_restore.h"
+#include "chrome/browser/ui/options/options_util.h"
+#include "chrome/browser/ui/startup/session_crashed_bubble.h"
+#include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/ui_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/controls/separator.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+
+using views::GridLayout;
+
+namespace {
+
+// Fixed width of the column holding the description label of the bubble.
+const int kWidthOfDescriptionText = 320;
+
+// Margins width for the top rows to compensate for the bottom panel for which
+// we don't want any margin.
+const int kMarginWidth = 12;
+const int kMarginHeight = kMarginWidth;
+
+// The color of the background of the sub panel to offer UMA optin.
+const SkColor kLightGrayBackgroundColor = 0xFFF0F0F0;
+const SkColor kWhiteBackgroundColor = 0xFFFFFFFF;
+
+bool ShouldOfferMetricsReporting() {
+// Stats collection only applies to Google Chrome builds.
+#if defined(GOOGLE_CHROME_BUILD)
+ // Only show metrics reporting option if user didn't already consent to it.
+ if (GoogleUpdateSettings::GetCollectStatsConsent())
+ return false;
+ return g_browser_process->local_state()->FindPreference(
+ prefs::kMetricsReportingEnabled)->IsUserModifiable();
+#else
+ return false;
+#endif // defined(GOOGLE_CHROME_BUILD)
+}
+
+} // namespace
+
+// static
+void SessionCrashedBubbleView::Show(Browser* browser) {
+ if (browser->profile()->IsOffTheRecord())
+ return;
+
+ views::View* anchor_view =
+ BrowserView::GetBrowserViewForBrowser(browser)->toolbar()->app_menu();
+ content::WebContents* web_contents =
+ browser->tab_strip_model()->GetActiveWebContents();
+ SessionCrashedBubbleView* crash_bubble =
+ new SessionCrashedBubbleView(anchor_view, browser, web_contents);
+ views::BubbleDelegateView::CreateBubble(crash_bubble)->Show();
+}
+
+SessionCrashedBubbleView::SessionCrashedBubbleView(
+ views::View* anchor_view,
+ Browser* browser,
+ content::WebContents* web_contents)
+ : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
+ content::WebContentsObserver(web_contents),
+ browser_(browser),
+ web_contents_(web_contents),
+ restore_button_(NULL),
+ close_(NULL),
+ uma_option_(NULL),
+ started_navigation_(false) {
+ set_close_on_deactivate(false);
+ set_move_with_anchor(true);
+ registrar_.Add(
+ this,
+ chrome::NOTIFICATION_TAB_CLOSING,
+ content::Source<content::NavigationController>(&(
+ web_contents->GetController())));
+ browser->tab_strip_model()->AddObserver(this);
+}
+
+SessionCrashedBubbleView::~SessionCrashedBubbleView() {
+ browser_->tab_strip_model()->RemoveObserver(this);
+}
+
+views::View* SessionCrashedBubbleView::GetInitiallyFocusedView() {
+ return restore_button_;
+}
+
+void SessionCrashedBubbleView::Init() {
+ ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+
+ // Close button.
+ close_ = new views::LabelButton(this, base::string16());
+ close_->SetImage(views::CustomButton::STATE_NORMAL,
+ *rb->GetImageNamed(IDR_CLOSE_2).ToImageSkia());
+ close_->SetImage(views::CustomButton::STATE_HOVERED,
+ *rb->GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
+ close_->SetImage(views::CustomButton::STATE_PRESSED,
+ *rb->GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
+ close_->SetSize(close_->GetPreferredSize());
+ close_->SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
+
+ // Bubble title label.
+ views::Label* title_label = new views::Label(
+ l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_BUBBLE_TITLE));
+ title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ title_label->SetFontList(rb->GetFontList(ui::ResourceBundle::BoldFont));
+
+ // Description text label.
+ views::Label* text_label = new views::Label(
+ l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_MESSAGE));
+ text_label->SetMultiLine(true);
+ text_label->SetLineHeight(20);
+ text_label->SetEnabledColor(SK_ColorDKGRAY);
+ text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+
+ // Learn more link
+ views::Link* learn_more_link = NULL;
+ if (ShouldOfferMetricsReporting()) {
+ learn_more_link = new views::Link(
+ l10n_util::GetStringUTF16(IDS_LEARN_MORE));
+ learn_more_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ learn_more_link->set_listener(this);
+ learn_more_link->SetUnderline(false);
+ }
+
+ // Restore button.
+ restore_button_ = new views::LabelButton(
+ this, l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON));
+ restore_button_->SetStyle(views::Button::STYLE_BUTTON);
+ restore_button_->SetIsDefault(true);
+ restore_button_->SetFontList(rb->GetFontList(ui::ResourceBundle::BoldFont));
+
+ GridLayout* layout = new GridLayout(this);
+ SetLayoutManager(layout);
+
+ // Title and close button row.
+ const int kTitleColumnSetId = 0;
+ views::ColumnSet* cs = layout->AddColumnSet(kTitleColumnSetId);
+ cs->AddPaddingColumn(0, kMarginWidth);
+ cs->AddColumn(GridLayout::LEADING, GridLayout::TRAILING, 0,
+ GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
+ cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
+ GridLayout::USE_PREF, 0, 0);
+
+ // Text row.
+ const int kTextColumnSetId = 1;
+ cs = layout->AddColumnSet(kTextColumnSetId);
+ cs->AddPaddingColumn(0, kMarginWidth);
+ cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, kWidthOfDescriptionText, 0);
+
+ // Learn more link and restore button row
+ const int kLinkAndButtonColumnSetId = 2;
+ cs = layout->AddColumnSet(kLinkAndButtonColumnSetId);
+ cs->AddPaddingColumn(0, kMarginWidth);
+ if (learn_more_link) {
+ cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ }
+ cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
+ cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
+ GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, kMarginWidth);
+
+ layout->AddPaddingRow(0, kMarginHeight);
+ layout->StartRow(0, kTitleColumnSetId);
+ layout->AddView(title_label);
+ layout->AddView(close_);
+ layout->AddPaddingRow(0, kMarginHeight);
+
+ layout->StartRow(0, kTextColumnSetId);
+ layout->AddView(text_label);
+ layout->AddPaddingRow(0, kMarginHeight);
+
+ layout->StartRow(0, kLinkAndButtonColumnSetId);
+ if (learn_more_link)
+ layout->AddView(learn_more_link);
+ layout->AddView(restore_button_);
+ layout->AddPaddingRow(0, kMarginHeight);
+
+ // Metrics reporting option.
+ if (learn_more_link)
+ CreateUmaOptinView(layout);
+
+ set_color(kWhiteBackgroundColor);
+ set_margins(gfx::Insets());
+ Layout();
+}
+
+void SessionCrashedBubbleView::CreateUmaOptinView(GridLayout* layout) {
+ // Checkbox for metric reporting setting.
+ uma_option_ = new views::Checkbox(
+ l10n_util::GetStringUTF16(IDS_SESSION_CRASHED_VIEW_UMA_OPTIN));
+ uma_option_->SetTextColor(views::Button::STATE_NORMAL, SK_ColorGRAY);
+ uma_option_->SetChecked(false);
+ uma_option_->SetTextMultiLine(true);
+ uma_option_->set_background(
+ views::Background::CreateSolidBackground(kLightGrayBackgroundColor));
+ uma_option_->set_listener(this);
+ // We use a border instead of padding so that the background color reach
+ // the edges of the bubble.
+ uma_option_->SetBorder(
+ views::Border::CreateSolidSidedBorder(
+ kMarginHeight, kMarginWidth, kMarginHeight, kMarginWidth,
+ kLightGrayBackgroundColor));
+
+ // Separator.
+ const int kSeparatorColumnSetId = 3;
+ views::ColumnSet* cs = layout->AddColumnSet(kSeparatorColumnSetId);
+ cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, kWidthOfDescriptionText + kMarginWidth, 0);
+
+ // Reporting row.
+ const int kReportColumnSetId = 4;
+ cs = layout->AddColumnSet(kReportColumnSetId);
+ cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
+ GridLayout::FIXED, kWidthOfDescriptionText + kMarginWidth, 0);
+
+ layout->StartRow(0, kSeparatorColumnSetId);
+ layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
+ layout->StartRow(0, kReportColumnSetId);
+ layout->AddView(uma_option_);
+}
+
+void SessionCrashedBubbleView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ DCHECK(sender);
+ if (sender == restore_button_)
+ RestorePreviousSession(sender);
+ else if (sender == close_)
+ CloseBubble();
+}
+
+void SessionCrashedBubbleView::LinkClicked(views::Link* source,
+ int event_flags) {
+ browser_->OpenURL(content::OpenURLParams(
+ GURL("https://support.google.com/chrome/answer/96817"),
+ content::Referrer(),
+ NEW_FOREGROUND_TAB,
+ content::PAGE_TRANSITION_LINK,
+ false));
+}
+
+void SessionCrashedBubbleView::DidStartNavigationToPendingEntry(
+ const GURL& url,
+ content::NavigationController::ReloadType reload_type) {
+ started_navigation_ = true;
+}
+
+void SessionCrashedBubbleView::DidFinishLoad(
+ int64 frame_id,
+ const GURL& validated_url,
+ bool is_main_frame,
+ content::RenderViewHost* render_view_host) {
+ if (started_navigation_)
+ CloseBubble();
+}
+
+void SessionCrashedBubbleView::WasShown() {
+ GetWidget()->Show();
+}
+
+void SessionCrashedBubbleView::WasHidden() {
+ GetWidget()->Hide();
+}
+
+void SessionCrashedBubbleView::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_TAB_CLOSING)
+ CloseBubble();
+}
+
+void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents,
+ int index) {
+ if (web_contents_ == contents)
+ CloseBubble();
+}
+
+void SessionCrashedBubbleView::RestorePreviousSession(views::Button* sender) {
+ SessionRestore::RestoreSessionAfterCrash(browser_);
+
+ // Record user's choice for opting in to UMA.
+ // There's no opting-out choice in the crash restore bubble.
+ if (uma_option_ && uma_option_->checked())
+ OptionsUtil::ResolveMetricsReportingEnabled(true);
+ CloseBubble();
+}
+
+void SessionCrashedBubbleView::CloseBubble() {
+ GetWidget()->Close();
+}
+
+bool ShowSessionCrashedBubble(Browser* browser) {
+ SessionCrashedBubbleView::Show(browser);
+ return true;
+}
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.h b/chrome/browser/ui/views/session_crashed_bubble_view.h
new file mode 100644
index 0000000..4093e619
--- /dev/null
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.h
@@ -0,0 +1,120 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SESSION_CRASHED_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_SESSION_CRASHED_BUBBLE_VIEW_H_
+
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/link_listener.h"
+
+namespace views {
+class Checkbox;
+class GridLayout;
+class LabelButton;
+class Widget;
+}
+
+namespace content {
+class WebContents;
+class RenderViewHost;
+}
+
+class Browser;
+
+// It creates a session restore request bubble when the previous session has
+// crashed. It also presents an option to enable metrics reporting, if it not
+// enabled already.
+class SessionCrashedBubbleView
+ : public views::BubbleDelegateView,
+ public views::ButtonListener,
+ public views::LinkListener,
+ public content::WebContentsObserver,
+ public content::NotificationObserver,
+ public TabStripModelObserver {
+ public:
+ static void Show(Browser* browser);
+
+ private:
+ SessionCrashedBubbleView(views::View* anchor_view,
+ Browser* browser,
+ content::WebContents* web_contents);
+ virtual ~SessionCrashedBubbleView();
+
+ // WidgetDelegateView methods.
+ virtual views::View* GetInitiallyFocusedView() OVERRIDE;
+
+ // views::BubbleDelegateView methods.
+ virtual void Init() OVERRIDE;
+
+ // views::ButtonListener methods.
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
+
+ // views::LinkListener methods.
+ virtual void LinkClicked(views::Link* source, int event_floags) OVERRIDE;
+
+ // content::WebContentsObserver methods.
+ virtual void DidStartNavigationToPendingEntry(
+ const GURL& url,
+ content::NavigationController::ReloadType reload_type) OVERRIDE;
+ virtual void DidFinishLoad(
+ int64 frame_id,
+ const GURL& validated_url,
+ bool is_main_frame,
+ content::RenderViewHost* render_view_host) OVERRIDE;
+ virtual void WasShown() OVERRIDE;
+ virtual void WasHidden() OVERRIDE;
+
+ // content::NotificationObserver methods.
+ virtual void Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // TabStripModelObserver methods.
+ // When the tab with current bubble is being dragged and dropped to a new
+ // window or to another window, the bubble will be dismissed as if the user
+ // chose not to restore the previous session.
+ virtual void TabDetachedAt(
+ content::WebContents* contents,
+ int index) OVERRIDE;
+
+ // Create the view for user to opt in to Uma.
+ void CreateUmaOptinView(views::GridLayout* layout);
+
+ // Restore previous session after user selects so.
+ void RestorePreviousSession(views::Button* sender);
+
+ // Close and destroy the bubble.
+ void CloseBubble();
+
+ content::NotificationRegistrar registrar_;
+
+ // Used for opening the question mark link as well as access the tab strip.
+ Browser* browser_;
+
+ // The web content associated with current bubble.
+ content::WebContents* web_contents_;
+
+ // Button for the user to confirm a session restore.
+ views::LabelButton* restore_button_;
+
+ // Button for the user to close this bubble.
+ views::LabelButton* close_;
+
+ // Checkbox for the user to opt-in to UMA reporting.
+ views::Checkbox* uma_option_;
+
+ // Whether or not a navigation has started on current tab.
+ bool started_navigation_;
+
+ DISALLOW_COPY_AND_ASSIGN(SessionCrashedBubbleView);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_SESSION_CRASHED_BUBBLE_VIEW_H_