Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: components/autofill/content/renderer/password_autofill_agent.cc

Issue 614023002: [Password manager] Relplace the FormFieldData vector from autofill::FormData with named fields… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated nit from Vaclav's review. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/autofill/content/common/autofill_messages.h ('k') | components/autofill/core/common/autofill_data_validation.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698