| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/renderer/autofill_helper.h" | 5 #include "chrome/renderer/autofill_helper.h" |
| 6 | 6 |
| 7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/common/chrome_constants.h" | 9 #include "chrome/common/chrome_constants.h" |
| 10 #include "chrome/renderer/form_manager.h" | 10 #include "chrome/renderer/form_manager.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 AutoFillHelper::AutoFillHelper(RenderView* render_view) | 49 AutoFillHelper::AutoFillHelper(RenderView* render_view) |
| 50 : render_view_(render_view), | 50 : render_view_(render_view), |
| 51 autofill_query_id_(0), | 51 autofill_query_id_(0), |
| 52 autofill_action_(AUTOFILL_NONE), | 52 autofill_action_(AUTOFILL_NONE), |
| 53 suggestions_clear_index_(-1), | 53 suggestions_clear_index_(-1), |
| 54 suggestions_options_index_(-1) { | 54 suggestions_options_index_(-1) { |
| 55 } | 55 } |
| 56 | 56 |
| 57 void AutoFillHelper::QueryAutoFillSuggestions(const WebNode& node) { | 57 void AutoFillHelper::QueryAutoFillSuggestions(const WebNode& node, |
| 58 bool autofill_disabled) { |
| 58 static int query_counter = 0; | 59 static int query_counter = 0; |
| 59 autofill_query_id_ = query_counter++; | 60 autofill_query_id_ = query_counter++; |
| 60 autofill_query_node_ = node; | 61 autofill_query_node_ = node; |
| 62 autofill_disabled_ = autofill_disabled; |
| 61 | 63 |
| 62 const WebFormControlElement& element = node.toConst<WebFormControlElement>(); | 64 const WebFormControlElement& element = node.toConst<WebFormControlElement>(); |
| 63 webkit_glue::FormField field; | 65 webkit_glue::FormField field; |
| 64 FormManager::WebFormControlElementToFormField( | 66 FormManager::WebFormControlElementToFormField( |
| 65 element, FormManager::EXTRACT_VALUE, &field); | 67 element, FormManager::EXTRACT_VALUE, &field); |
| 66 | 68 |
| 67 // WebFormControlElementToFormField does not scrape the DOM for the field | 69 // WebFormControlElementToFormField does not scrape the DOM for the field |
| 68 // label, so find the label here. | 70 // label, so find the label here. |
| 69 // TODO(jhawkins): Add form and field identities so we can use the cached form | 71 // TODO(jhawkins): Add form and field identities so we can use the cached form |
| 70 // data in FormManager. | 72 // data in FormManager. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 101 web_view->hidePopups(); | 103 web_view->hidePopups(); |
| 102 return; | 104 return; |
| 103 } | 105 } |
| 104 | 106 |
| 105 std::vector<string16> v(values); | 107 std::vector<string16> v(values); |
| 106 std::vector<string16> l(labels); | 108 std::vector<string16> l(labels); |
| 107 std::vector<string16> i(icons); | 109 std::vector<string16> i(icons); |
| 108 std::vector<int> ids(unique_ids); | 110 std::vector<int> ids(unique_ids); |
| 109 int separator_index = -1; | 111 int separator_index = -1; |
| 110 | 112 |
| 113 if (autofill_disabled_) { |
| 114 // If autofill is disabled and we had suggestions, show a warning instead. |
| 115 v.assign(1, |
| 116 l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_FORM_DISABLED)); |
| 117 l.assign(1, string16()); |
| 118 i.assign(1, string16()); |
| 119 ids.assign(1, -1); |
| 120 } else if (ids[0] < 0 && ids.size() > 1) { |
| 121 // If we received a warning instead of suggestions from autofill but regular |
| 122 // suggestions from autocomplete, don't show the autofill warning. |
| 123 v.erase(v.begin()); |
| 124 l.erase(l.begin()); |
| 125 i.erase(i.begin()); |
| 126 ids.erase(ids.begin()); |
| 127 } |
| 128 |
| 111 // The form has been auto-filled, so give the user the chance to clear the | 129 // The form has been auto-filled, so give the user the chance to clear the |
| 112 // form. Append the 'Clear form' menu item. | 130 // form. Append the 'Clear form' menu item. |
| 113 if (form_manager_.FormWithNodeIsAutoFilled(autofill_query_node_)) { | 131 if (form_manager_.FormWithNodeIsAutoFilled(autofill_query_node_)) { |
| 114 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); | 132 v.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_CLEAR_FORM_MENU_ITEM)); |
| 115 l.push_back(string16()); | 133 l.push_back(string16()); |
| 116 i.push_back(string16()); | 134 i.push_back(string16()); |
| 117 ids.push_back(0); | 135 ids.push_back(0); |
| 118 suggestions_clear_index_ = v.size() - 1; | 136 suggestions_clear_index_ = v.size() - 1; |
| 119 separator_index = values.size(); | 137 separator_index = v.size() - 1; |
| 120 } | 138 } |
| 121 | 139 |
| 122 // Only include "AutoFill Options" special menu item if we have AutoFill | 140 // Only include "AutoFill Options" special menu item if we have AutoFill |
| 123 // items, identified by |unique_ids| having at least one valid value. | 141 // items, identified by |unique_ids| having at least one valid value. |
| 124 bool show_options = false; | 142 bool show_options = false; |
| 125 for (size_t i = 0; i < ids.size(); ++i) { | 143 for (size_t i = 0; i < ids.size(); ++i) { |
| 126 if (ids[i] != 0) { | 144 if (ids[i] > 0) { |
| 127 show_options = true; | 145 show_options = true; |
| 128 break; | 146 break; |
| 129 } | 147 } |
| 130 } | 148 } |
| 131 if (show_options) { | 149 if (show_options) { |
| 132 // Append the 'Chrome Autofill options' menu item; | 150 // Append the 'Chrome Autofill options' menu item; |
| 133 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, | 151 v.push_back(l10n_util::GetStringFUTF16(IDS_AUTOFILL_OPTIONS_POPUP, |
| 134 WideToUTF16(chrome::kBrowserAppName))); | 152 WideToUTF16(chrome::kBrowserAppName))); |
| 135 l.push_back(string16()); | 153 l.push_back(string16()); |
| 136 i.push_back(string16()); | 154 i.push_back(string16()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 237 |
| 220 void AutoFillHelper::FrameWillClose(WebFrame* frame) { | 238 void AutoFillHelper::FrameWillClose(WebFrame* frame) { |
| 221 form_manager_.ResetFrame(frame); | 239 form_manager_.ResetFrame(frame); |
| 222 } | 240 } |
| 223 | 241 |
| 224 void AutoFillHelper::FrameDetached(WebFrame* frame) { | 242 void AutoFillHelper::FrameDetached(WebFrame* frame) { |
| 225 form_manager_.ResetFrame(frame); | 243 form_manager_.ResetFrame(frame); |
| 226 } | 244 } |
| 227 | 245 |
| 228 void AutoFillHelper::TextDidChangeInTextField(const WebInputElement& element) { | 246 void AutoFillHelper::TextDidChangeInTextField(const WebInputElement& element) { |
| 229 ShowSuggestions(element, false, true); | 247 ShowSuggestions(element, false, true, false); |
| 230 } | 248 } |
| 231 | 249 |
| 232 bool AutoFillHelper::InputElementClicked(const WebInputElement& element, | 250 bool AutoFillHelper::InputElementClicked(const WebInputElement& element, |
| 233 bool was_focused, | 251 bool was_focused, |
| 234 bool is_focused) { | 252 bool is_focused) { |
| 235 if (was_focused) | 253 if (was_focused) |
| 236 ShowSuggestions(element, true, false); | 254 ShowSuggestions(element, true, false, true); |
| 237 return false; | 255 return false; |
| 238 } | 256 } |
| 239 | 257 |
| 258 void AutoFillHelper::ShowSuggestions(const WebInputElement& element, |
| 259 bool autofill_on_empty_values, |
| 260 bool requires_caret_at_end, |
| 261 bool display_warning_if_disabled) { |
| 262 bool autofill_disabled = !element.isEnabledFormControl() || |
| 263 !element.isText() || element.isPasswordField() || |
| 264 !element.autoComplete() || element.isReadOnly(); |
| 265 if (autofill_disabled && !display_warning_if_disabled) |
| 266 return; |
| 240 | 267 |
| 241 void AutoFillHelper::ShowSuggestions( | 268 // If the field has no name, then we won't have values. |
| 242 const WebInputElement& const_element, | 269 if (element.nameForAutofill().isEmpty()) |
| 243 bool autofill_on_empty_values, | |
| 244 bool requires_caret_at_end) { | |
| 245 // We need to call non-const methods. | |
| 246 WebInputElement element(const_element); | |
| 247 if (!element.isEnabledFormControl() || | |
| 248 !element.isText() || | |
| 249 element.isPasswordField() || | |
| 250 !element.autoComplete() || element.isReadOnly()) { | |
| 251 return; | |
| 252 } | |
| 253 | |
| 254 WebString name = element.nameForAutofill(); | |
| 255 if (name.isEmpty()) // If the field has no name, then we won't have values. | |
| 256 return; | 270 return; |
| 257 | 271 |
| 258 // Don't attempt to autofill with values that are too large. | 272 // Don't attempt to autofill with values that are too large. |
| 259 WebString value = element.value(); | 273 WebString value = element.value(); |
| 260 if (value.length() > kMaximumTextSizeForAutoFill) | 274 if (value.length() > kMaximumTextSizeForAutoFill) |
| 261 return; | 275 return; |
| 262 | 276 |
| 263 if (!autofill_on_empty_values && value.isEmpty()) | 277 if (!autofill_on_empty_values && value.isEmpty()) |
| 264 return; | 278 return; |
| 265 | 279 |
| 266 if (requires_caret_at_end && | 280 if (requires_caret_at_end && |
| 267 (element.selectionStart() != element.selectionEnd() || | 281 (element.selectionStart() != element.selectionEnd() || |
| 268 element.selectionEnd() != static_cast<int>(value.length()))) { | 282 element.selectionEnd() != static_cast<int>(value.length()))) |
| 269 return; | 283 return; |
| 270 } | |
| 271 | 284 |
| 272 QueryAutoFillSuggestions(element); | 285 QueryAutoFillSuggestions(element, autofill_disabled); |
| 273 } | 286 } |
| 274 | 287 |
| 275 void AutoFillHelper::QueryAutoFillFormData(const WebNode& node, | 288 void AutoFillHelper::QueryAutoFillFormData(const WebNode& node, |
| 276 int unique_id, | 289 int unique_id, |
| 277 AutoFillAction action) { | 290 AutoFillAction action) { |
| 278 static int query_counter = 0; | 291 static int query_counter = 0; |
| 279 autofill_query_id_ = query_counter++; | 292 autofill_query_id_ = query_counter++; |
| 280 | 293 |
| 281 webkit_glue::FormData form; | 294 webkit_glue::FormData form; |
| 282 const WebInputElement element = node.toConst<WebInputElement>(); | 295 const WebInputElement element = node.toConst<WebInputElement>(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 305 FormManager::EXTRACT_NONE, &form)) { | 318 FormManager::EXTRACT_NONE, &form)) { |
| 306 forms.push_back(form); | 319 forms.push_back(form); |
| 307 } | 320 } |
| 308 } | 321 } |
| 309 | 322 |
| 310 if (!forms.empty()) { | 323 if (!forms.empty()) { |
| 311 render_view_->Send(new ViewHostMsg_FormsSeen(render_view_->routing_id(), | 324 render_view_->Send(new ViewHostMsg_FormsSeen(render_view_->routing_id(), |
| 312 forms)); | 325 forms)); |
| 313 } | 326 } |
| 314 } | 327 } |
| OLD | NEW |