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

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: 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 {
Ilya Sherman 2016/11/29 03:10:35 Please document that this enum is used to back an
Avi (use Gerrit) 2016/11/29 16:10:59 Done.
60 TAB_HELPER_DESTROYED = 0,
61 SUBSEQUENT_DIALOG_SHOWN = 1,
62 HANDLE_DIALOG_CALLED = 2,
63 CANCEL_DIALOGS_CALLED = 3,
64 TAB_HIDDEN = 4,
65 BROWSER_SWITCHED = 5,
66 DIALOG_BUTTON_CLICKED = 6,
67 MAX,
68 };
69
59 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper( 70 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper(
60 content::WebContents* web_contents) 71 content::WebContents* web_contents)
61 : content::WebContentsObserver(web_contents) { 72 : content::WebContentsObserver(web_contents) {
62 } 73 }
63 74
64 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() { 75 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() {
65 if (dialog_) 76 if (dialog_) {
66 CloseDialog(true /*suppress_callback*/, false, base::string16()); 77 CloseDialog(true /*suppress_callback*/, false, base::string16(),
78 DismissalCause::TAB_HELPER_DESTROYED);
79 }
67 } 80 }
68 81
69 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting( 82 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting(
70 base::Closure callback) { 83 base::Closure callback) {
71 dialog_shown_ = callback; 84 dialog_shown_ = callback;
72 } 85 }
73 86
74 void JavaScriptDialogTabHelper::RunJavaScriptDialog( 87 void JavaScriptDialogTabHelper::RunJavaScriptDialog(
75 content::WebContents* alerting_web_contents, 88 content::WebContents* alerting_web_contents,
76 const GURL& origin_url, 89 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 " 137 "A window.prompt() dialog generated by this page was suppressed "
125 "because this page is not the active tab of the front window. " 138 "because this page is not the active tab of the front window. "
126 "Please make sure your dialogs are triggered by user interactions " 139 "Please make sure your dialogs are triggered by user interactions "
127 "to avoid this situation. " 140 "to avoid this situation. "
128 "https://www.chromestatus.com/feature/5637107137642496"); 141 "https://www.chromestatus.com/feature/5637107137642496");
129 return; 142 return;
130 } 143 }
131 144
132 if (dialog_) { 145 if (dialog_) {
133 // There's already a dialog up; clear it out. 146 // There's already a dialog up; clear it out.
134 CloseDialog(false, false, base::string16()); 147 CloseDialog(false, false, base::string16(),
148 DismissalCause::SUBSEQUENT_DIALOG_SHOWN);
135 } 149 }
136 150
137 base::string16 title = 151 base::string16 title =
138 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url); 152 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url);
139 dialog_callback_ = callback; 153 dialog_callback_ = callback;
154 message_type_ = message_type;
140 dialog_ = JavaScriptDialog::Create( 155 dialog_ = JavaScriptDialog::Create(
141 parent_web_contents, alerting_web_contents, title, message_type, 156 parent_web_contents, alerting_web_contents, title, message_type,
142 message_text, default_prompt_text, 157 message_text, default_prompt_text,
143 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed, 158 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed,
144 base::Unretained(this), callback)); 159 base::Unretained(this), callback));
145 160
146 BrowserList::AddObserver(this); 161 BrowserList::AddObserver(this);
147 162
148 // Message suppression is something that we don't give the user a checkbox 163 // 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 164 // 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, 221 web_contents, is_reload,
207 base::Bind(&SaveUnloadUmaStats, engagement_score, callback)); 222 base::Bind(&SaveUnloadUmaStats, engagement_score, callback));
208 } 223 }
209 224
210 bool JavaScriptDialogTabHelper::HandleJavaScriptDialog( 225 bool JavaScriptDialogTabHelper::HandleJavaScriptDialog(
211 content::WebContents* web_contents, 226 content::WebContents* web_contents,
212 bool accept, 227 bool accept,
213 const base::string16* prompt_override) { 228 const base::string16* prompt_override) {
214 if (dialog_) { 229 if (dialog_) {
215 CloseDialog(false /*suppress_callback*/, accept, 230 CloseDialog(false /*suppress_callback*/, accept,
216 prompt_override ? *prompt_override : base::string16()); 231 prompt_override ? *prompt_override : base::string16(),
232 DismissalCause::HANDLE_DIALOG_CALLED);
217 return true; 233 return true;
218 } 234 }
219 235
220 // Handle any app-modal dialogs being run by the app-modal dialog system. 236 // Handle any app-modal dialogs being run by the app-modal dialog system.
221 return AppModalDialogManager()->HandleJavaScriptDialog(web_contents, accept, 237 return AppModalDialogManager()->HandleJavaScriptDialog(web_contents, accept,
222 prompt_override); 238 prompt_override);
223 } 239 }
224 240
225 void JavaScriptDialogTabHelper::CancelDialogs( 241 void JavaScriptDialogTabHelper::CancelDialogs(
226 content::WebContents* web_contents, 242 content::WebContents* web_contents,
227 bool suppress_callbacks, 243 bool suppress_callbacks,
228 bool reset_state) { 244 bool reset_state) {
229 if (dialog_) 245 if (dialog_)
230 CloseDialog(suppress_callbacks, false, base::string16()); 246 CloseDialog(suppress_callbacks, false, base::string16(),
247 DismissalCause::CANCEL_DIALOGS_CALLED);
231 248
232 // Cancel any app-modal dialogs being run by the app-modal dialog system. 249 // Cancel any app-modal dialogs being run by the app-modal dialog system.
233 return AppModalDialogManager()->CancelDialogs( 250 return AppModalDialogManager()->CancelDialogs(
234 web_contents, suppress_callbacks, reset_state); 251 web_contents, suppress_callbacks, reset_state);
235 } 252 }
236 253
237 void JavaScriptDialogTabHelper::WasHidden() { 254 void JavaScriptDialogTabHelper::WasHidden() {
238 if (dialog_) 255 if (dialog_) {
239 CloseDialog(false, false, base::string16()); 256 CloseDialog(false, false, base::string16(), DismissalCause::TAB_HIDDEN);
257 }
240 } 258 }
241 259
242 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) { 260 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) {
243 if (dialog_ && !IsWebContentsForemost(web_contents())) 261 if (dialog_ && !IsWebContentsForemost(web_contents())) {
244 CloseDialog(false, false, base::string16()); 262 CloseDialog(false, false, base::string16(),
263 DismissalCause::BROWSER_SWITCHED);
264 }
265 }
266
267 void JavaScriptDialogTabHelper::LogDialogDismissalCause(
268 JavaScriptDialogTabHelper::DismissalCause cause) {
269 switch (message_type_) {
270 case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
271 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Alert",
272 static_cast<int>(cause),
273 static_cast<int>(DismissalCause::MAX));
274 break;
275 case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
276 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Confirm",
277 static_cast<int>(cause),
278 static_cast<int>(DismissalCause::MAX));
279 break;
280 case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT:
281 UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Prompt",
282 static_cast<int>(cause),
283 static_cast<int>(DismissalCause::MAX));
284 break;
285 }
245 } 286 }
246 287
247 void JavaScriptDialogTabHelper::OnDialogClosed( 288 void JavaScriptDialogTabHelper::OnDialogClosed(
248 DialogClosedCallback callback, 289 DialogClosedCallback callback,
249 bool success, 290 bool success,
250 const base::string16& user_input) { 291 const base::string16& user_input) {
292 LogDialogDismissalCause(DismissalCause::DIALOG_BUTTON_CLICKED);
251 callback.Run(success, user_input); 293 callback.Run(success, user_input);
252 294
253 ClearDialogInfo(); 295 ClearDialogInfo();
254 } 296 }
255 297
256 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback, 298 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback,
257 bool success, 299 bool success,
258 const base::string16& user_input) { 300 const base::string16& user_input,
301 DismissalCause cause) {
259 DCHECK(dialog_); 302 DCHECK(dialog_);
303 LogDialogDismissalCause(cause);
260 304
261 dialog_->CloseDialogWithoutCallback(); 305 dialog_->CloseDialogWithoutCallback();
262 if (!suppress_callback) 306 if (!suppress_callback)
263 dialog_callback_.Run(success, user_input); 307 dialog_callback_.Run(success, user_input);
264 308
265 ClearDialogInfo(); 309 ClearDialogInfo();
266 } 310 }
267 311
268 void JavaScriptDialogTabHelper::ClearDialogInfo() { 312 void JavaScriptDialogTabHelper::ClearDialogInfo() {
269 dialog_.reset(); 313 dialog_.reset();
270 dialog_callback_.Reset(); 314 dialog_callback_.Reset();
271 BrowserList::RemoveObserver(this); 315 BrowserList::RemoveObserver(this);
272 } 316 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698