OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/content/renderer/password_autofill_agent.h" | 5 #include "components/autofill/content/renderer/password_autofill_agent.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 // necessary form elements. To avoid having to look these up again when we want | 54 // necessary form elements. To avoid having to look these up again when we want |
55 // to fill the form, the FindFormElements function stores the pointers | 55 // to fill the form, the FindFormElements function stores the pointers |
56 // in a FormElements* result, referenced to ensure they are safe to use. | 56 // in a FormElements* result, referenced to ensure they are safe to use. |
57 struct FormElements { | 57 struct FormElements { |
58 blink::WebFormElement form_element; | 58 blink::WebFormElement form_element; |
59 FormInputElementMap input_elements; | 59 FormInputElementMap input_elements; |
60 }; | 60 }; |
61 | 61 |
62 typedef std::vector<FormElements*> FormElementsList; | 62 typedef std::vector<FormElements*> FormElementsList; |
63 | 63 |
| 64 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { |
| 65 return !fill_data.username_field.name.empty(); |
| 66 } |
| 67 |
64 // Utility function to find the unique entry of the |form_element| for the | 68 // Utility function to find the unique entry of the |form_element| for the |
65 // specified input |field|. On successful find, adds it to |result| and returns | 69 // specified input |field|. On successful find, adds it to |result| and returns |
66 // |true|. Otherwise clears the references from each |HTMLInputElement| from | 70 // |true|. Otherwise clears the references from each |HTMLInputElement| from |
67 // |result| and returns |false|. | 71 // |result| and returns |false|. |
68 bool FindFormInputElement(blink::WebFormElement* form_element, | 72 bool FindFormInputElement(blink::WebFormElement* form_element, |
69 const FormFieldData& field, | 73 const FormFieldData& field, |
70 FormElements* result) { | 74 FormElements* result) { |
71 blink::WebVector<blink::WebNode> temp_elements; | 75 blink::WebVector<blink::WebNode> temp_elements; |
72 form_element->getNamedElements(field.name, temp_elements); | 76 form_element->getNamedElements(field.name, temp_elements); |
73 | 77 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 result->input_elements.clear(); | 115 result->input_elements.clear(); |
112 return false; | 116 return false; |
113 } | 117 } |
114 | 118 |
115 return true; | 119 return true; |
116 } | 120 } |
117 | 121 |
118 // Helper to search the given form element for the specified input elements in | 122 // Helper to search the given form element for the specified input elements in |
119 // |data|, and add results to |result|. | 123 // |data|, and add results to |result|. |
120 bool FindFormInputElements(blink::WebFormElement* form_element, | 124 bool FindFormInputElements(blink::WebFormElement* form_element, |
121 const FormData& data, | 125 const PasswordFormFillData& data, |
122 FormElements* result) { | 126 FormElements* result) { |
123 const bool username_is_present = !data.fields[0].name.empty(); | 127 return FindFormInputElement(form_element, data.password_field, result) && |
124 | 128 (!FillDataContainsUsername(data) || |
125 // Loop through the list of elements we need to find on the form in order to | 129 FindFormInputElement(form_element, data.username_field, result)); |
126 // autofill it. If we don't find any one of them, abort processing this | |
127 // form; it can't be the right one. | |
128 // First field is the username, skip it if not present. | |
129 for (size_t j = (username_is_present ? 0 : 1); j < data.fields.size(); ++j) { | |
130 if (!FindFormInputElement(form_element, data.fields[j], result)) | |
131 return false; | |
132 } | |
133 | |
134 return true; | |
135 } | 130 } |
136 | 131 |
137 // Helper to locate form elements identified by |data|. | 132 // Helper to locate form elements identified by |data|. |
138 void FindFormElements(blink::WebView* view, | 133 void FindFormElements(blink::WebView* view, |
139 const FormData& data, | 134 const PasswordFormFillData& data, |
140 FormElementsList* results) { | 135 FormElementsList* results) { |
141 DCHECK(view); | 136 DCHECK(view); |
142 DCHECK(results); | 137 DCHECK(results); |
143 blink::WebFrame* main_frame = view->mainFrame(); | 138 blink::WebFrame* main_frame = view->mainFrame(); |
144 if (!main_frame) | 139 if (!main_frame) |
145 return; | 140 return; |
146 | 141 |
147 GURL::Replacements rep; | 142 GURL::Replacements rep; |
148 rep.ClearQuery(); | 143 rep.ClearQuery(); |
149 rep.ClearRef(); | 144 rep.ClearRef(); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 | 232 |
238 // Log a message including the name, method and action of |form|. | 233 // Log a message including the name, method and action of |form|. |
239 void LogHTMLForm(SavePasswordProgressLogger* logger, | 234 void LogHTMLForm(SavePasswordProgressLogger* logger, |
240 SavePasswordProgressLogger::StringID message_id, | 235 SavePasswordProgressLogger::StringID message_id, |
241 const blink::WebFormElement& form) { | 236 const blink::WebFormElement& form) { |
242 logger->LogHTMLForm(message_id, | 237 logger->LogHTMLForm(message_id, |
243 form.name().utf8(), | 238 form.name().utf8(), |
244 GURL(form.action().utf8())); | 239 GURL(form.action().utf8())); |
245 } | 240 } |
246 | 241 |
247 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { | |
248 return !fill_data.basic_data.fields[0].name.empty(); | |
249 } | |
250 | |
251 // Sets |suggestions_present| to true if there are any suggestions to be derived | 242 // Sets |suggestions_present| to true if there are any suggestions to be derived |
252 // from |fill_data|. Unless |show_all| is true, only considers suggestions with | 243 // from |fill_data|. Unless |show_all| is true, only considers suggestions with |
253 // usernames having |current_username| as a prefix. Returns true if a username | 244 // usernames having |current_username| as a prefix. Returns true if a username |
254 // from the |fill_data.other_possible_usernames| would be included in the | 245 // from the |fill_data.other_possible_usernames| would be included in the |
255 // suggestions. | 246 // suggestions. |
256 bool GetSuggestionsStats(const PasswordFormFillData& fill_data, | 247 bool GetSuggestionsStats(const PasswordFormFillData& fill_data, |
257 const base::string16& current_username, | 248 const base::string16& current_username, |
258 bool show_all, | 249 bool show_all, |
259 bool* suggestions_present) { | 250 bool* suggestions_present) { |
260 *suggestions_present = false; | 251 *suggestions_present = false; |
261 | 252 |
262 for (const auto& usernames : fill_data.other_possible_usernames) { | 253 for (const auto& usernames : fill_data.other_possible_usernames) { |
263 for (size_t i = 0; i < usernames.second.size(); ++i) { | 254 for (size_t i = 0; i < usernames.second.size(); ++i) { |
264 if (show_all || | 255 if (show_all || |
265 StartsWith(usernames.second[i], current_username, false)) { | 256 StartsWith(usernames.second[i], current_username, false)) { |
266 *suggestions_present = true; | 257 *suggestions_present = true; |
267 return true; | 258 return true; |
268 } | 259 } |
269 } | 260 } |
270 } | 261 } |
271 | 262 |
272 if (show_all || StartsWith(fill_data.basic_data.fields[0].value, | 263 if (show_all || |
273 current_username, false)) { | 264 StartsWith(fill_data.username_field.value, current_username, false)) { |
274 *suggestions_present = true; | 265 *suggestions_present = true; |
275 return false; | 266 return false; |
276 } | 267 } |
277 | 268 |
278 for (const auto& login : fill_data.additional_logins) { | 269 for (const auto& login : fill_data.additional_logins) { |
279 if (show_all || StartsWith(login.first, current_username, false)) { | 270 if (show_all || StartsWith(login.first, current_username, false)) { |
280 *suggestions_present = true; | 271 *suggestions_present = true; |
281 return false; | 272 return false; |
282 } | 273 } |
283 } | 274 } |
(...skipping 21 matching lines...) Expand all Loading... |
305 base::string16 current_username; | 296 base::string16 current_username; |
306 if (!username_element->isNull()) { | 297 if (!username_element->isNull()) { |
307 current_username = username_element->value(); | 298 current_username = username_element->value(); |
308 } | 299 } |
309 | 300 |
310 // username and password will contain the match found if any. | 301 // username and password will contain the match found if any. |
311 base::string16 username; | 302 base::string16 username; |
312 base::string16 password; | 303 base::string16 password; |
313 | 304 |
314 // Look for any suitable matches to current field text. | 305 // Look for any suitable matches to current field text. |
315 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | 306 if (DoUsernamesMatch(fill_data.username_field.value, current_username, |
316 current_username, | |
317 exact_username_match)) { | 307 exact_username_match)) { |
318 username = fill_data.basic_data.fields[0].value; | 308 username = fill_data.username_field.value; |
319 password = fill_data.basic_data.fields[1].value; | 309 password = fill_data.password_field.value; |
320 } else { | 310 } else { |
321 // Scan additional logins for a match. | 311 // Scan additional logins for a match. |
322 PasswordFormFillData::LoginCollection::const_iterator iter; | 312 PasswordFormFillData::LoginCollection::const_iterator iter; |
323 for (iter = fill_data.additional_logins.begin(); | 313 for (iter = fill_data.additional_logins.begin(); |
324 iter != fill_data.additional_logins.end(); | 314 iter != fill_data.additional_logins.end(); |
325 ++iter) { | 315 ++iter) { |
326 if (DoUsernamesMatch( | 316 if (DoUsernamesMatch( |
327 iter->first, current_username, exact_username_match)) { | 317 iter->first, current_username, exact_username_match)) { |
328 username = iter->first; | 318 username = iter->first; |
329 password = iter->second.password; | 319 password = iter->second.password; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 if (!IsElementAutocompletable(password_element)) | 395 if (!IsElementAutocompletable(password_element)) |
406 return false; | 396 return false; |
407 | 397 |
408 bool form_contains_username_field = FillDataContainsUsername(fill_data); | 398 bool form_contains_username_field = FillDataContainsUsername(fill_data); |
409 // Try to set the username to the preferred name, but only if the field | 399 // Try to set the username to the preferred name, but only if the field |
410 // can be set and isn't prefilled. | 400 // can be set and isn't prefilled. |
411 if (form_contains_username_field && | 401 if (form_contains_username_field && |
412 IsElementAutocompletable(username_element) && | 402 IsElementAutocompletable(username_element) && |
413 username_element.value().isEmpty()) { | 403 username_element.value().isEmpty()) { |
414 // TODO(tkent): Check maxlength and pattern. | 404 // TODO(tkent): Check maxlength and pattern. |
415 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 405 username_element.setValue(fill_data.username_field.value, true); |
416 } | 406 } |
417 | 407 |
418 // Fill if we have an exact match for the username. Note that this sets | 408 // Fill if we have an exact match for the username. Note that this sets |
419 // username to autofilled. | 409 // username to autofilled. |
420 return FillUserNameAndPassword(&username_element, | 410 return FillUserNameAndPassword(&username_element, |
421 &password_element, | 411 &password_element, |
422 fill_data, | 412 fill_data, |
423 true /* exact_username_match */, | 413 true /* exact_username_match */, |
424 false /* set_selection */, | 414 false /* set_selection */, |
425 registration_callback); | 415 registration_callback); |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 const PasswordFormFillData& form_data) { | 1010 const PasswordFormFillData& form_data) { |
1021 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { | 1011 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { |
1022 if (form_data.other_possible_usernames.size()) | 1012 if (form_data.other_possible_usernames.size()) |
1023 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; | 1013 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; |
1024 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) | 1014 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) |
1025 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; | 1015 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; |
1026 } | 1016 } |
1027 | 1017 |
1028 FormElementsList forms; | 1018 FormElementsList forms; |
1029 // We own the FormElements* in forms. | 1019 // We own the FormElements* in forms. |
1030 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); | 1020 FindFormElements(render_view()->GetWebView(), form_data, &forms); |
1031 FormElementsList::iterator iter; | 1021 FormElementsList::iterator iter; |
1032 for (iter = forms.begin(); iter != forms.end(); ++iter) { | 1022 for (iter = forms.begin(); iter != forms.end(); ++iter) { |
1033 scoped_ptr<FormElements> form_elements(*iter); | 1023 scoped_ptr<FormElements> form_elements(*iter); |
1034 | 1024 |
1035 // Attach autocomplete listener to enable selecting alternate logins. | 1025 // Attach autocomplete listener to enable selecting alternate logins. |
1036 blink::WebInputElement username_element, password_element; | 1026 blink::WebInputElement username_element, password_element; |
1037 | 1027 |
1038 // Check whether the password form has a username input field. | 1028 // Check whether the password form has a username input field. |
1039 bool form_contains_username_field = FillDataContainsUsername(form_data); | 1029 bool form_contains_username_field = FillDataContainsUsername(form_data); |
1040 if (form_contains_username_field) { | 1030 if (form_contains_username_field) { |
1041 username_element = | 1031 username_element = |
1042 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 1032 form_elements->input_elements[form_data.username_field.name]; |
1043 } | 1033 } |
1044 | 1034 |
1045 // No password field, bail out. | 1035 // No password field, bail out. |
1046 if (form_data.basic_data.fields[1].name.empty()) | 1036 if (form_data.password_field.name.empty()) |
1047 break; | 1037 break; |
1048 | 1038 |
1049 // Get pointer to password element. (We currently only support single | 1039 // Get pointer to password element. (We currently only support single |
1050 // password forms). | 1040 // password forms). |
1051 password_element = | 1041 password_element = |
1052 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 1042 form_elements->input_elements[form_data.password_field.name]; |
1053 | 1043 |
1054 // If wait_for_username is true, we don't want to initially fill the form | 1044 // If wait_for_username is true, we don't want to initially fill the form |
1055 // until the user types in a valid username. | 1045 // until the user types in a valid username. |
1056 if (!form_data.wait_for_username && | 1046 if (!form_data.wait_for_username && |
1057 FillFormOnPasswordRecieved( | 1047 FillFormOnPasswordRecieved( |
1058 form_data, | 1048 form_data, |
1059 username_element, | 1049 username_element, |
1060 password_element, | 1050 password_element, |
1061 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1051 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
1062 base::Unretained(&gatekeeper_)))) { | 1052 base::Unretained(&gatekeeper_)))) { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1238 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1228 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1239 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1229 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1240 password_form->password_value.empty() && | 1230 password_form->password_value.empty() && |
1241 password_form->new_password_value.empty())) { | 1231 password_form->new_password_value.empty())) { |
1242 return; | 1232 return; |
1243 } | 1233 } |
1244 provisionally_saved_forms_[frame].reset(password_form.release()); | 1234 provisionally_saved_forms_[frame].reset(password_form.release()); |
1245 } | 1235 } |
1246 | 1236 |
1247 } // namespace autofill | 1237 } // namespace autofill |
OLD | NEW |