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