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 |