Chromium Code Reviews| 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 |