OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |