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

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

Issue 341823005: Collects stats on how user interacts with the bubble. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix comment. Created 6 years, 5 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
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/metrics/field_trial.h" 12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 14 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/sessions/session_restore.h" 17 #include "chrome/browser/sessions/session_restore.h"
17 #include "chrome/browser/ui/browser_list.h" 18 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/browser/ui/browser_list_observer.h" 19 #include "chrome/browser/ui/browser_list_observer.h"
19 #include "chrome/browser/ui/options/options_util.h" 20 #include "chrome/browser/ui/options/options_util.h"
20 #include "chrome/browser/ui/startup/session_crashed_bubble.h" 21 #include "chrome/browser/ui/startup/session_crashed_bubble.h"
21 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" 22 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h" 23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 59
59 // The color of the text and background of the sub panel to offer UMA optin. 60 // The color of the text and background of the sub panel to offer UMA optin.
60 // These values match the BookmarkSyncPromoView colors. 61 // These values match the BookmarkSyncPromoView colors.
61 const SkColor kBackgroundColor = SkColorSetRGB(245, 245, 245); 62 const SkColor kBackgroundColor = SkColorSetRGB(245, 245, 245);
62 const SkColor kTextColor = SkColorSetRGB(102, 102, 102); 63 const SkColor kTextColor = SkColorSetRGB(102, 102, 102);
63 64
64 // The Finch study name and group name that enables session crashed bubble UI. 65 // The Finch study name and group name that enables session crashed bubble UI.
65 const char kEnableBubbleUIFinchName[] = "EnableSessionCrashedBubbleUI"; 66 const char kEnableBubbleUIFinchName[] = "EnableSessionCrashedBubbleUI";
66 const char kEnableBubbleUIGroupEnabled[] = "Enabled"; 67 const char kEnableBubbleUIGroupEnabled[] = "Enabled";
67 68
69 enum SessionCrashedBubbleHistogramValue {
70 SESSION_CRASHED_BUBBLE_SHOWN,
71 SESSION_CRASHED_BUBBLE_ERROR,
72 SESSION_CRASHED_BUBBLE_RESTORED,
73 SESSION_CRASHED_BUBBLE_ALREADY_UMA_OPTIN,
jwd 2014/07/09 15:37:52 Is this being used anywhere anymore?
yao 2014/07/09 15:47:03 Done.
74 SESSION_CRASHED_BUBBLE_UMA_OPTIN,
75 SESSION_CRASHED_BUBBLE_HELP,
76 SESSION_CRASHED_BUBBLE_IGNORED,
77 SESSION_CRASHED_BUBBLE_MAX,
78 };
79
80 void RecordBubbleHistogramValue(SessionCrashedBubbleHistogramValue value) {
81 UMA_HISTOGRAM_ENUMERATION(
82 "SessionCrashed.Bubble", value, SESSION_CRASHED_BUBBLE_MAX);
83 }
84
68 // Whether or not the bubble UI should be used. 85 // Whether or not the bubble UI should be used.
69 bool IsBubbleUIEnabled() { 86 bool IsBubbleUIEnabled() {
70 const base::CommandLine& command_line = *CommandLine::ForCurrentProcess(); 87 const base::CommandLine& command_line = *CommandLine::ForCurrentProcess();
71 if (command_line.HasSwitch(switches::kDisableSessionCrashedBubble)) 88 if (command_line.HasSwitch(switches::kDisableSessionCrashedBubble))
72 return false; 89 return false;
73 if (command_line.HasSwitch(switches::kEnableSessionCrashedBubble)) 90 if (command_line.HasSwitch(switches::kEnableSessionCrashedBubble))
74 return true; 91 return true;
75 const std::string group_name = base::FieldTrialList::FindFullName( 92 const std::string group_name = base::FieldTrialList::FindFullName(
76 kEnableBubbleUIFinchName); 93 kEnableBubbleUIFinchName);
77 return group_name == kEnableBubbleUIGroupEnabled; 94 return group_name == kEnableBubbleUIGroupEnabled;
78 } 95 }
79 96
97 // Will be passed in as a callback function to BubbleFrameView. Before the
98 // bubble is closed (by the close button), collect the usage stats.
99 void BubbleToBeClosed() {
100 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED);
101 }
102
80 } // namespace 103 } // namespace
81 104
82 // A helper class that listens to browser removal event. 105 // A helper class that listens to browser removal event.
83 class SessionCrashedBubbleView::BrowserRemovalObserver 106 class SessionCrashedBubbleView::BrowserRemovalObserver
84 : public chrome::BrowserListObserver { 107 : public chrome::BrowserListObserver {
85 public: 108 public:
86 explicit BrowserRemovalObserver(Browser* browser) : browser_(browser) { 109 explicit BrowserRemovalObserver(Browser* browser) : browser_(browser) {
87 DCHECK(browser_); 110 DCHECK(browser_);
88 BrowserList::AddObserver(this); 111 BrowserList::AddObserver(this);
89 } 112 }
(...skipping 21 matching lines...) Expand all
111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 134 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
112 if (browser->profile()->IsOffTheRecord()) 135 if (browser->profile()->IsOffTheRecord())
113 return; 136 return;
114 137
115 // Observes browser removal event and will be deallocated in ShowForReal. 138 // Observes browser removal event and will be deallocated in ShowForReal.
116 scoped_ptr<BrowserRemovalObserver> browser_observer( 139 scoped_ptr<BrowserRemovalObserver> browser_observer(
117 new BrowserRemovalObserver(browser)); 140 new BrowserRemovalObserver(browser));
118 141
119 // Stats collection only applies to Google Chrome builds. 142 // Stats collection only applies to Google Chrome builds.
120 #if defined(GOOGLE_CHROME_BUILD) 143 #if defined(GOOGLE_CHROME_BUILD)
121 // Schedule a task to run ShouldOfferMetricsReporting() on FILE thread, since 144 // Schedule a task to run GoogleUpdateSettings::GetCollectStatsConsent() on
122 // GoogleUpdateSettings::GetCollectStatsConsent() does IO. Then, call 145 // FILE thread, since it does IO. Then, call
123 // SessionCrashedBubbleView::ShowForReal with the result. 146 // SessionCrashedBubbleView::ShowForReal with the result.
124 content::BrowserThread::PostTaskAndReplyWithResult( 147 content::BrowserThread::PostTaskAndReplyWithResult(
125 content::BrowserThread::FILE, 148 content::BrowserThread::FILE,
126 FROM_HERE, 149 FROM_HERE,
127 base::Bind(&GoogleUpdateSettings::GetCollectStatsConsent), 150 base::Bind(&GoogleUpdateSettings::GetCollectStatsConsent),
128 base::Bind(&SessionCrashedBubbleView::ShowForReal, 151 base::Bind(&SessionCrashedBubbleView::ShowForReal,
129 base::Passed(&browser_observer))); 152 base::Passed(&browser_observer)));
130 #else 153 #else
131 SessionCrashedBubbleView::ShowForReal(browser_observer.Pass(), false); 154 SessionCrashedBubbleView::ShowForReal(browser_observer.Pass(), false);
132 #endif // defined(GOOGLE_CHROME_BUILD) 155 #endif // defined(GOOGLE_CHROME_BUILD)
133 } 156 }
134 157
135 // static 158 // static
136 void SessionCrashedBubbleView::ShowForReal( 159 void SessionCrashedBubbleView::ShowForReal(
137 scoped_ptr<BrowserRemovalObserver> browser_observer, 160 scoped_ptr<BrowserRemovalObserver> browser_observer,
138 bool uma_opted_in_already) { 161 bool uma_opted_in_already) {
139 // Determine whether or not the uma opt-in option should be offered. It is 162 // Determine whether or not the uma opt-in option should be offered. It is
140 // offered only when it is a Google chrome build, user hasn't opted in yet, 163 // offered only when it is a Google chrome build, user hasn't opted in yet,
141 // and the preference is modifiable by the user. 164 // and the preference is modifiable by the user.
142 bool offer_uma_optin = false; 165 bool offer_uma_optin = false;
143 166
144 #if defined(GOOGLE_CHROME_BUILD) 167 #if defined(GOOGLE_CHROME_BUILD)
145 if (!uma_opted_in_already) 168 if (!uma_opted_in_already)
146 offer_uma_optin = g_browser_process->local_state()->FindPreference( 169 offer_uma_optin = g_browser_process->local_state()->FindPreference(
147 prefs::kMetricsReportingEnabled)->IsUserModifiable(); 170 prefs::kMetricsReportingEnabled)->IsUserModifiable();
148 #endif // defined(GOOGLE_CHROME_BUILD) 171 #endif // defined(GOOGLE_CHROME_BUILD)
149 172
150 Browser* browser = browser_observer->browser(); 173 Browser* browser = browser_observer->browser();
151 174
152 if (!browser) 175 if (!browser) {
176 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ERROR);
153 return; 177 return;
178 }
154 179
155 views::View* anchor_view = 180 views::View* anchor_view =
156 BrowserView::GetBrowserViewForBrowser(browser)->toolbar()->app_menu(); 181 BrowserView::GetBrowserViewForBrowser(browser)->toolbar()->app_menu();
157 content::WebContents* web_contents = 182 content::WebContents* web_contents =
158 browser->tab_strip_model()->GetActiveWebContents(); 183 browser->tab_strip_model()->GetActiveWebContents();
159 184
160 if (!web_contents) 185 if (!web_contents) {
186 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_ERROR);
161 return; 187 return;
188 }
162 189
163 SessionCrashedBubbleView* crash_bubble = 190 SessionCrashedBubbleView* crash_bubble =
164 new SessionCrashedBubbleView(anchor_view, browser, web_contents, 191 new SessionCrashedBubbleView(anchor_view, browser, web_contents,
165 offer_uma_optin); 192 offer_uma_optin);
166 views::BubbleDelegateView::CreateBubble(crash_bubble)->Show(); 193 views::BubbleDelegateView::CreateBubble(crash_bubble)->Show();
194 views::BubbleFrameView* frame_view = crash_bubble->GetBubbleFrameView();
195 if (frame_view) {
196 frame_view->set_before_close_callback(base::Bind(&BubbleToBeClosed));
197 }
198 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_SHOWN);
167 } 199 }
168 200
169 SessionCrashedBubbleView::SessionCrashedBubbleView( 201 SessionCrashedBubbleView::SessionCrashedBubbleView(
170 views::View* anchor_view, 202 views::View* anchor_view,
171 Browser* browser, 203 Browser* browser,
172 content::WebContents* web_contents, 204 content::WebContents* web_contents,
173 bool offer_uma_optin) 205 bool offer_uma_optin)
174 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), 206 : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
175 content::WebContentsObserver(web_contents), 207 content::WebContentsObserver(web_contents),
176 browser_(browser), 208 browser_(browser),
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 layout->AddView(new views::Separator(views::Separator::HORIZONTAL)); 352 layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
321 layout->StartRow(0, kReportColumnSetId); 353 layout->StartRow(0, kReportColumnSetId);
322 layout->AddView(uma_option_); 354 layout->AddView(uma_option_);
323 layout->AddView(uma_label); 355 layout->AddView(uma_label);
324 } 356 }
325 357
326 void SessionCrashedBubbleView::ButtonPressed(views::Button* sender, 358 void SessionCrashedBubbleView::ButtonPressed(views::Button* sender,
327 const ui::Event& event) { 359 const ui::Event& event) {
328 DCHECK_EQ(sender, restore_button_); 360 DCHECK_EQ(sender, restore_button_);
329 RestorePreviousSession(sender); 361 RestorePreviousSession(sender);
362 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_RESTORED);
330 } 363 }
331 364
332 void SessionCrashedBubbleView::StyledLabelLinkClicked(const gfx::Range& range, 365 void SessionCrashedBubbleView::StyledLabelLinkClicked(const gfx::Range& range,
333 int event_flags) { 366 int event_flags) {
334 browser_->OpenURL(content::OpenURLParams( 367 browser_->OpenURL(content::OpenURLParams(
335 GURL("https://support.google.com/chrome/answer/96817"), 368 GURL("https://support.google.com/chrome/answer/96817"),
336 content::Referrer(), 369 content::Referrer(),
337 NEW_FOREGROUND_TAB, 370 NEW_FOREGROUND_TAB,
338 content::PAGE_TRANSITION_LINK, 371 content::PAGE_TRANSITION_LINK,
339 false)); 372 false));
373 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_HELP);
340 } 374 }
341 375
342 void SessionCrashedBubbleView::DidStartNavigationToPendingEntry( 376 void SessionCrashedBubbleView::DidStartNavigationToPendingEntry(
343 const GURL& url, 377 const GURL& url,
344 content::NavigationController::ReloadType reload_type) { 378 content::NavigationController::ReloadType reload_type) {
345 started_navigation_ = true; 379 started_navigation_ = true;
346 } 380 }
347 381
348 void SessionCrashedBubbleView::DidFinishLoad( 382 void SessionCrashedBubbleView::DidFinishLoad(
349 int64 frame_id, 383 int64 frame_id,
350 const GURL& validated_url, 384 const GURL& validated_url,
351 bool is_main_frame, 385 bool is_main_frame,
352 content::RenderViewHost* render_view_host) { 386 content::RenderViewHost* render_view_host) {
353 if (started_navigation_) 387 if (started_navigation_) {
388 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED);
354 CloseBubble(); 389 CloseBubble();
390 }
355 } 391 }
356 392
357 void SessionCrashedBubbleView::WasShown() { 393 void SessionCrashedBubbleView::WasShown() {
358 GetWidget()->Show(); 394 GetWidget()->Show();
359 } 395 }
360 396
361 void SessionCrashedBubbleView::WasHidden() { 397 void SessionCrashedBubbleView::WasHidden() {
362 GetWidget()->Hide(); 398 GetWidget()->Hide();
363 } 399 }
364 400
365 void SessionCrashedBubbleView::Observe( 401 void SessionCrashedBubbleView::Observe(
366 int type, 402 int type,
367 const content::NotificationSource& source, 403 const content::NotificationSource& source,
368 const content::NotificationDetails& details) { 404 const content::NotificationDetails& details) {
369 if (type == chrome::NOTIFICATION_TAB_CLOSING) 405 if (type == chrome::NOTIFICATION_TAB_CLOSING) {
406 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED);
370 CloseBubble(); 407 CloseBubble();
408 }
371 } 409 }
372 410
373 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents, 411 void SessionCrashedBubbleView::TabDetachedAt(content::WebContents* contents,
374 int index) { 412 int index) {
375 if (web_contents_ == contents) 413 if (web_contents_ == contents) {
414 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_IGNORED);
376 CloseBubble(); 415 CloseBubble();
416 }
377 } 417 }
378 418
379 void SessionCrashedBubbleView::RestorePreviousSession(views::Button* sender) { 419 void SessionCrashedBubbleView::RestorePreviousSession(views::Button* sender) {
380 SessionRestore::RestoreSessionAfterCrash(browser_); 420 SessionRestore::RestoreSessionAfterCrash(browser_);
381 421
382 // Record user's choice for opting in to UMA. 422 // Record user's choice for opting in to UMA.
383 // There's no opting-out choice in the crash restore bubble. 423 // There's no opting-out choice in the crash restore bubble.
384 if (uma_option_ && uma_option_->checked()) { 424 if (uma_option_ && uma_option_->checked()) {
385 // TODO: Clean up function ResolveMetricsReportingEnabled so that user pref 425 // TODO: Clean up function ResolveMetricsReportingEnabled so that user pref
386 // is stored automatically. 426 // is stored automatically.
387 OptionsUtil::ResolveMetricsReportingEnabled(true); 427 OptionsUtil::ResolveMetricsReportingEnabled(true);
388 g_browser_process->local_state()->SetBoolean( 428 g_browser_process->local_state()->SetBoolean(
389 prefs::kMetricsReportingEnabled, true); 429 prefs::kMetricsReportingEnabled, true);
430 RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_UMA_OPTIN);
390 } 431 }
391 CloseBubble(); 432 CloseBubble();
392 } 433 }
393 434
394 void SessionCrashedBubbleView::CloseBubble() { 435 void SessionCrashedBubbleView::CloseBubble() {
395 GetWidget()->Close(); 436 GetWidget()->Close();
396 } 437 }
397 438
398 bool ShowSessionCrashedBubble(Browser* browser) { 439 bool ShowSessionCrashedBubble(Browser* browser) {
399 if (IsBubbleUIEnabled()) { 440 if (IsBubbleUIEnabled()) {
400 SessionCrashedBubbleView::Show(browser); 441 SessionCrashedBubbleView::Show(browser);
401 return true; 442 return true;
402 } 443 }
403 return false; 444 return false;
404 } 445 }
OLDNEW
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698