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

Side by Side Diff: chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc

Issue 2535043002: Add UMA metrics to measure the dismissal cause of dialogs. (Closed)
Patch Set: nits Created 4 years 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/javascript_dialogs/javascript_dialog_tab_helper.h" 5 #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/feature_list.h" 9 #include "base/feature_list.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 // That will clear the callback inside of JavaScriptDialog, and start the 49 // That will clear the callback inside of JavaScriptDialog, and start the
50 // JavaScriptDialog on its own path of destruction. CloseDialog() then calls 50 // JavaScriptDialog on its own path of destruction. CloseDialog() then calls
51 // ClearDialogInfo() which removes observers. 51 // ClearDialogInfo() which removes observers.
52 // 52 //
53 // If closing is initiated by the JavaScriptDialog, which is a self-deleting 53 // If closing is initiated by the JavaScriptDialog, which is a self-deleting
54 // object, then it will make its callback. The callback will have been wrapped 54 // object, then it will make its callback. The callback will have been wrapped
55 // within JavaScriptDialogTabHelper::RunJavaScriptDialog() to be a call to 55 // within JavaScriptDialogTabHelper::RunJavaScriptDialog() to be a call to
56 // JavaScriptDialogTabHelper::OnDialogClosed(), which, after doing the callback, 56 // JavaScriptDialogTabHelper::OnDialogClosed(), which, after doing the callback,
57 // again calls ClearDialogInfo() to remove observers. 57 // again calls ClearDialogInfo() to remove observers.
58 58
59 enum class JavaScriptDialogTabHelper::DismissalCause {
60 // This is used for a UMA histogram. Please never alter existing values, only
61 // append new ones.
62 TAB_HELPER_DESTROYED = 0,
63 SUBSEQUENT_DIALOG_SHOWN = 1,
64 HANDLE_DIALOG_CALLED = 2,
65 CANCEL_DIALOGS_CALLED = 3,
66 TAB_HIDDEN = 4,
67 BROWSER_SWITCHED = 5,
68 DIALOG_BUTTON_CLICKED = 6,
69 MAX,
70 };
71
59 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper( 72 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper(
60 content::WebContents* web_contents) 73 content::WebContents* web_contents)
61 : content::WebContentsObserver(web_contents) { 74 : content::WebContentsObserver(web_contents) {
62 } 75 }
63 76
64 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() { 77 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() {
65 if (dialog_) 78 if (dialog_) {
66 CloseDialog(true /*suppress_callback*/, false, base::string16()); 79 CloseDialog(true /*suppress_callback*/, false, base::string16(),
80 DismissalCause::TAB_HELPER_DESTROYED);
81 }
67 } 82 }
68 83
69 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting( 84 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting(
70 base::Closure callback) { 85 base::Closure callback) {
71 dialog_shown_ = callback; 86 dialog_shown_ = callback;
72 } 87 }
73 88
74 void JavaScriptDialogTabHelper::RunJavaScriptDialog( 89 void JavaScriptDialogTabHelper::RunJavaScriptDialog(
75 content::WebContents* alerting_web_contents, 90 content::WebContents* alerting_web_contents,
76 const GURL& origin_url, 91 const GURL& origin_url,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 "A window.prompt() dialog generated by this page was suppressed " 139 "A window.prompt() dialog generated by this page was suppressed "
125 "because this page is not the active tab of the front window. " 140 "because this page is not the active tab of the front window. "
126 "Please make sure your dialogs are triggered by user interactions " 141 "Please make sure your dialogs are triggered by user interactions "
127 "to avoid this situation. " 142 "to avoid this situation. "
128 "https://www.chromestatus.com/feature/5637107137642496"); 143 "https://www.chromestatus.com/feature/5637107137642496");
129 return; 144 return;
130 } 145 }
131 146
132 if (dialog_) { 147 if (dialog_) {
133 // There's already a dialog up; clear it out. 148 // There's already a dialog up; clear it out.
134 CloseDialog(false, false, base::string16()); 149 CloseDialog(false, false, base::string16(),
150 DismissalCause::SUBSEQUENT_DIALOG_SHOWN);
135 } 151 }
136 152
137 base::string16 title = 153 base::string16 title =
138 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url); 154 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url);
139 dialog_callback_ = callback; 155 dialog_callback_ = callback;
156 message_type_ = message_type;
140 dialog_ = JavaScriptDialog::Create( 157 dialog_ = JavaScriptDialog::Create(
141 parent_web_contents, alerting_web_contents, title, message_type, 158 parent_web_contents, alerting_web_contents, title, message_type,
142 message_text, default_prompt_text, 159 message_text, default_prompt_text,
143 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed, 160 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed,
144 base::Unretained(this), callback)); 161 base::Unretained(this), callback));
145 162
146 BrowserList::AddObserver(this); 163 BrowserList::AddObserver(this);
147 164
148 // Message suppression is something that we don't give the user a checkbox 165 // Message suppression is something that we don't give the user a checkbox
149 // for any more. It was useful back in the day when dialogs were app-modal 166 // for any more. It was useful back in the day when dialogs were app-modal
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 web_contents, is_reload, 223 web_contents, is_reload,
207 base::Bind(&SaveUnloadUmaStats, engagement_score, callback)); 224 base::Bind(&SaveUnloadUmaStats, engagement_score, callback));
208 } 225 }
209 226
210 bool JavaScriptDialogTabHelper::HandleJavaScriptDialog( 227 bool JavaScriptDialogTabHelper::HandleJavaScriptDialog(
211 content::WebContents* web_contents, 228 content::WebContents* web_contents,
212 bool accept, 229 bool accept,
213 const base::string16* prompt_override) { 230 const base::string16* prompt_override) {
214 if (dialog_) { 231 if (dialog_) {
215 CloseDialog(false /*suppress_callback*/, accept, 232 CloseDialog(false /*suppress_callback*/, accept,
216 prompt_override ? *prompt_override : base::string16()); 233 prompt_override ? *prompt_override : base::string16(),
234 DismissalCause::HANDLE_DIALOG_CALLED);
217 return true; 235 return true;
218 } 236 }
219 237
220 // Handle any app-modal dialogs being run by the app-modal dialog system. 238 // Handle any app-modal dialogs being run by the app-modal dialog system.
221 return AppModalDialogManager()->HandleJavaScriptDialog(web_contents, accept, 239 return AppModalDialogManager()->HandleJavaScriptDialog(web_contents, accept,
222 prompt_override); 240 prompt_override);
223 } 241 }
224 242
225 void JavaScriptDialogTabHelper::CancelDialogs( 243 void JavaScriptDialogTabHelper::CancelDialogs(
226 content::WebContents* web_contents, 244 content::WebContents* web_contents,
227 bool suppress_callbacks, 245 bool suppress_callbacks,
228 bool reset_state) { 246 bool reset_state) {
229 if (dialog_) 247 if (dialog_)
230 CloseDialog(suppress_callbacks, false, base::string16()); 248 CloseDialog(suppress_callbacks, false, base::string16(),
249 DismissalCause::CANCEL_DIALOGS_CALLED);
231 250
232 // Cancel any app-modal dialogs being run by the app-modal dialog system. 251 // Cancel any app-modal dialogs being run by the app-modal dialog system.
233 return AppModalDialogManager()->CancelDialogs( 252 return AppModalDialogManager()->CancelDialogs(
234 web_contents, suppress_callbacks, reset_state); 253 web_contents, suppress_callbacks, reset_state);
235 } 254 }
236 255
237 void JavaScriptDialogTabHelper::WasHidden() { 256 void JavaScriptDialogTabHelper::WasHidden() {
238 if (dialog_) 257 if (dialog_) {
239 CloseDialog(false, false, base::string16()); 258 CloseDialog(false, false, base::string16(), DismissalCause::TAB_HIDDEN);
259 }
240 } 260 }
241 261
242 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) { 262 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) {
243 if (dialog_ && !IsWebContentsForemost(web_contents())) 263 if (dialog_ && !IsWebContentsForemost(web_contents())) {
244 CloseDialog(false, false, base::string16()); 264 CloseDialog(false, false, base::string16(),
265 DismissalCause::BROWSER_SWITCHED);
266 }
267 }
268
269 void JavaScriptDialogTabHelper::LogDialogDismissalCause(
270 JavaScriptDialogTabHelper::DismissalCause cause) {
271 switch (message_type_) {
272 case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
273 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Alert",
274 static_cast<int>(cause),
275 static_cast<int>(DismissalCause::MAX));
276 break;
277 case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
278 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Confirm",
279 static_cast<int>(cause),
280 static_cast<int>(DismissalCause::MAX));
281 break;
282 case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT:
283 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Prompt",
284 static_cast<int>(cause),
285 static_cast<int>(DismissalCause::MAX));
286 break;
287 }
245 } 288 }
246 289
247 void JavaScriptDialogTabHelper::OnDialogClosed( 290 void JavaScriptDialogTabHelper::OnDialogClosed(
248 DialogClosedCallback callback, 291 DialogClosedCallback callback,
249 bool success, 292 bool success,
250 const base::string16& user_input) { 293 const base::string16& user_input) {
294 LogDialogDismissalCause(DismissalCause::DIALOG_BUTTON_CLICKED);
251 callback.Run(success, user_input); 295 callback.Run(success, user_input);
252 296
253 ClearDialogInfo(); 297 ClearDialogInfo();
254 } 298 }
255 299
256 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback, 300 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback,
257 bool success, 301 bool success,
258 const base::string16& user_input) { 302 const base::string16& user_input,
303 DismissalCause cause) {
259 DCHECK(dialog_); 304 DCHECK(dialog_);
305 LogDialogDismissalCause(cause);
260 306
261 dialog_->CloseDialogWithoutCallback(); 307 dialog_->CloseDialogWithoutCallback();
262 if (!suppress_callback) 308 if (!suppress_callback)
263 dialog_callback_.Run(success, user_input); 309 dialog_callback_.Run(success, user_input);
264 310
265 ClearDialogInfo(); 311 ClearDialogInfo();
266 } 312 }
267 313
268 void JavaScriptDialogTabHelper::ClearDialogInfo() { 314 void JavaScriptDialogTabHelper::ClearDialogInfo() {
269 dialog_.reset(); 315 dialog_.reset();
270 dialog_callback_.Reset(); 316 dialog_callback_.Reset();
271 BrowserList::RemoveObserver(this); 317 BrowserList::RemoveObserver(this);
272 } 318 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698