| 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" |
| 11 #include "chrome/browser/engagement/site_engagement_service.h" | 11 #include "chrome/browser/engagement/site_engagement_service.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
| 14 #include "chrome/browser/ui/browser_list.h" | 14 #include "chrome/browser/ui/browser_list.h" |
| 15 #include "chrome/browser/ui/tab_modal_confirm_dialog.h" | 15 #include "chrome/browser/ui/tab_modal_confirm_dialog.h" |
| 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 16 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 17 #include "chrome/common/chrome_features.h" | |
| 18 #include "components/app_modal/javascript_dialog_manager.h" | 17 #include "components/app_modal/javascript_dialog_manager.h" |
| 19 #include "content/public/browser/navigation_handle.h" | 18 #include "content/public/browser/navigation_handle.h" |
| 20 #include "content/public/browser/render_frame_host.h" | 19 #include "content/public/browser/render_frame_host.h" |
| 21 #include "ui/gfx/text_elider.h" | 20 #include "ui/gfx/text_elider.h" |
| 22 | 21 |
| 23 DEFINE_WEB_CONTENTS_USER_DATA_KEY(JavaScriptDialogTabHelper); | 22 DEFINE_WEB_CONTENTS_USER_DATA_KEY(JavaScriptDialogTabHelper); |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 bool IsEnabled() { | |
| 28 return base::FeatureList::IsEnabled(features::kAutoDismissingDialogs); | |
| 29 } | |
| 30 | |
| 31 app_modal::JavaScriptDialogManager* AppModalDialogManager() { | 26 app_modal::JavaScriptDialogManager* AppModalDialogManager() { |
| 32 return app_modal::JavaScriptDialogManager::GetInstance(); | 27 return app_modal::JavaScriptDialogManager::GetInstance(); |
| 33 } | 28 } |
| 34 | 29 |
| 35 bool IsWebContentsForemost(content::WebContents* web_contents) { | 30 bool IsWebContentsForemost(content::WebContents* web_contents) { |
| 36 Browser* browser = BrowserList::GetInstance()->GetLastActive(); | 31 Browser* browser = BrowserList::GetInstance()->GetLastActive(); |
| 37 DCHECK(browser); | 32 DCHECK(browser); |
| 38 return browser->tab_strip_model()->GetActiveWebContents() == web_contents; | 33 return browser->tab_strip_model()->GetActiveWebContents() == web_contents; |
| 39 } | 34 } |
| 40 | 35 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Alert", foremost); | 121 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Alert", foremost); |
| 127 break; | 122 break; |
| 128 case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: | 123 case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: |
| 129 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Confirm", foremost); | 124 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Confirm", foremost); |
| 130 break; | 125 break; |
| 131 case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: | 126 case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: |
| 132 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Prompt", foremost); | 127 UMA_HISTOGRAM_BOOLEAN("JSDialogs.IsForemost.Prompt", foremost); |
| 133 break; | 128 break; |
| 134 } | 129 } |
| 135 | 130 |
| 136 if (IsEnabled()) { | 131 if (!IsWebContentsForemost(parent_web_contents) && |
| 137 if (!IsWebContentsForemost(parent_web_contents) && | 132 dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT) { |
| 138 dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT) { | 133 // Don't allow "prompt" dialogs to steal the user's focus. TODO(avi): |
| 139 // Don't allow "prompt" dialogs to steal the user's focus. TODO(avi): | 134 // Eventually, for subsequent phases of http://bit.ly/project-oldspice, |
| 140 // Eventually, for subsequent phases of http://bit.ly/project-oldspice, | 135 // turn off focus stealing for other dialog types. |
| 141 // turn off focus stealing for other dialog types. | 136 *did_suppress_message = true; |
| 142 *did_suppress_message = true; | 137 alerting_web_contents->GetMainFrame()->AddMessageToConsole( |
| 143 alerting_web_contents->GetMainFrame()->AddMessageToConsole( | 138 content::CONSOLE_MESSAGE_LEVEL_WARNING, |
| 144 content::CONSOLE_MESSAGE_LEVEL_WARNING, | 139 "A window.prompt() dialog generated by this page was suppressed " |
| 145 "A window.prompt() dialog generated by this page was suppressed " | 140 "because this page is not the active tab of the front window. " |
| 146 "because this page is not the active tab of the front window. " | 141 "Please make sure your dialogs are triggered by user interactions " |
| 147 "Please make sure your dialogs are triggered by user interactions " | 142 "to avoid this situation. " |
| 148 "to avoid this situation. " | 143 "https://www.chromestatus.com/feature/5637107137642496"); |
| 149 "https://www.chromestatus.com/feature/5637107137642496"); | 144 return; |
| 150 return; | 145 } |
| 151 } | |
| 152 | 146 |
| 153 if (dialog_) { | 147 if (dialog_) { |
| 154 // There's already a dialog up; clear it out. | 148 // There's already a dialog up; clear it out. |
| 155 CloseDialog(false, base::string16(), | 149 CloseDialog(false, base::string16(), |
| 156 DismissalCause::SUBSEQUENT_DIALOG_SHOWN); | 150 DismissalCause::SUBSEQUENT_DIALOG_SHOWN); |
| 157 } | 151 } |
| 158 | 152 |
| 159 // Enforce sane sizes. ElideRectangleString breaks horizontally, which isn't | 153 // Enforce sane sizes. ElideRectangleString breaks horizontally, which isn't |
| 160 // strictly needed, but it restricts the vertical size, which is crucial. | 154 // strictly needed, but it restricts the vertical size, which is crucial. |
| 161 // This gives about 2000 characters, which is about the same as the | 155 // This gives about 2000 characters, which is about the same as the |
| 162 // AppModalDialogManager provides, but allows no more than 24 lines. | 156 // AppModalDialogManager provides, but allows no more than 24 lines. |
| 163 const int kMessageTextMaxRows = 24; | 157 const int kMessageTextMaxRows = 24; |
| 164 const int kMessageTextMaxCols = 80; | 158 const int kMessageTextMaxCols = 80; |
| 165 const size_t kDefaultPromptMaxSize = 2000; | 159 const size_t kDefaultPromptMaxSize = 2000; |
| 166 base::string16 truncated_message_text; | 160 base::string16 truncated_message_text; |
| 167 gfx::ElideRectangleString(message_text, kMessageTextMaxRows, | 161 gfx::ElideRectangleString(message_text, kMessageTextMaxRows, |
| 168 kMessageTextMaxCols, false, | 162 kMessageTextMaxCols, false, |
| 169 &truncated_message_text); | 163 &truncated_message_text); |
| 170 base::string16 truncated_default_prompt_text; | 164 base::string16 truncated_default_prompt_text; |
| 171 gfx::ElideString(default_prompt_text, kDefaultPromptMaxSize, | 165 gfx::ElideString(default_prompt_text, kDefaultPromptMaxSize, |
| 172 &truncated_default_prompt_text); | 166 &truncated_default_prompt_text); |
| 173 | 167 |
| 174 base::string16 title = | 168 base::string16 title = |
| 175 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url); | 169 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url); |
| 176 dialog_callback_ = callback; | 170 dialog_callback_ = callback; |
| 177 dialog_type_ = dialog_type; | 171 dialog_type_ = dialog_type; |
| 178 dialog_ = JavaScriptDialog::Create( | 172 dialog_ = JavaScriptDialog::Create( |
| 179 parent_web_contents, alerting_web_contents, title, dialog_type, | 173 parent_web_contents, alerting_web_contents, title, dialog_type, |
| 180 truncated_message_text, truncated_default_prompt_text, | 174 truncated_message_text, truncated_default_prompt_text, |
| 181 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed, | 175 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed, |
| 182 base::Unretained(this), callback)); | 176 base::Unretained(this), callback)); |
| 183 | 177 |
| 184 BrowserList::AddObserver(this); | 178 BrowserList::AddObserver(this); |
| 185 | 179 |
| 186 // Message suppression is something that we don't give the user a checkbox | 180 // Message suppression is something that we don't give the user a checkbox |
| 187 // for any more. It was useful back in the day when dialogs were app-modal | 181 // for any more. It was useful back in the day when dialogs were app-modal |
| 188 // and clicking the checkbox was the only way to escape a loop that the page | 182 // and clicking the checkbox was the only way to escape a loop that the page |
| 189 // was doing, but now the user can just close the page. | 183 // was doing, but now the user can just close the page. |
| 190 *did_suppress_message = false; | 184 *did_suppress_message = false; |
| 191 | 185 |
| 192 if (!dialog_shown_.is_null()) { | 186 if (!dialog_shown_.is_null()) { |
| 193 dialog_shown_.Run(); | 187 dialog_shown_.Run(); |
| 194 dialog_shown_.Reset(); | 188 dialog_shown_.Reset(); |
| 195 } | |
| 196 } else { | |
| 197 AppModalDialogManager()->RunJavaScriptDialog( | |
| 198 alerting_web_contents, origin_url, dialog_type, message_text, | |
| 199 default_prompt_text, callback, did_suppress_message); | |
| 200 } | 189 } |
| 201 | 190 |
| 202 if (did_suppress_message) { | 191 if (did_suppress_message) { |
| 203 UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCountUserSuppressed", | 192 UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCountUserSuppressed", |
| 204 message_length); | 193 message_length); |
| 205 } | 194 } |
| 206 } | 195 } |
| 207 | 196 |
| 208 namespace { | 197 namespace { |
| 209 | 198 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 dialog_callback_.Run(success, user_input); | 338 dialog_callback_.Run(success, user_input); |
| 350 | 339 |
| 351 ClearDialogInfo(); | 340 ClearDialogInfo(); |
| 352 } | 341 } |
| 353 | 342 |
| 354 void JavaScriptDialogTabHelper::ClearDialogInfo() { | 343 void JavaScriptDialogTabHelper::ClearDialogInfo() { |
| 355 dialog_.reset(); | 344 dialog_.reset(); |
| 356 dialog_callback_.Reset(); | 345 dialog_callback_.Reset(); |
| 357 BrowserList::RemoveObserver(this); | 346 BrowserList::RemoveObserver(this); |
| 358 } | 347 } |
| OLD | NEW |