| 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 |