Chromium Code Reviews| 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_form_conversion_utils.h" | 5 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 6 | 6 |
| 7 #include "components/autofill/content/renderer/form_autofill_util.h" | 7 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 8 #include "components/autofill/core/common/password_form.h" | 8 #include "components/autofill/core/common/password_form.h" |
| 9 #include "third_party/WebKit/public/platform/WebString.h" | 9 #include "third_party/WebKit/public/platform/WebString.h" |
| 10 #include "third_party/WebKit/public/web/WebDocument.h" | 10 #include "third_party/WebKit/public/web/WebDocument.h" |
| 11 #include "third_party/WebKit/public/web/WebFormControlElement.h" | 11 #include "third_party/WebKit/public/web/WebFormControlElement.h" |
| 12 #include "third_party/WebKit/public/web/WebInputElement.h" | 12 #include "third_party/WebKit/public/web/WebInputElement.h" |
| 13 | 13 |
| 14 using blink::WebDocument; | 14 using blink::WebDocument; |
| 15 using blink::WebFormControlElement; | 15 using blink::WebFormControlElement; |
| 16 using blink::WebFormElement; | 16 using blink::WebFormElement; |
| 17 using blink::WebInputElement; | 17 using blink::WebInputElement; |
| 18 using blink::WebString; | 18 using blink::WebString; |
| 19 using blink::WebVector; | 19 using blink::WebVector; |
| 20 | 20 |
| 21 namespace autofill { | 21 namespace autofill { |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // Maximum number of password fields we will observe before throwing our | 24 // Maximum number of password fields we will observe before throwing our |
| 25 // hands in the air and giving up with a given form. | 25 // hands in the air and giving up with a given form. |
| 26 static const size_t kMaxPasswords = 3; | 26 static const size_t kMaxPasswords = 3; |
| 27 | 27 |
| 28 // Helper to determine which password is the main one, and which is | 28 // Helper to determine which password is the main one, and which is the new |
|
Ilya Sherman
2014/07/01 03:08:47
Hmm, it's not entirely clear what a "main" passwor
engedy
2014/07/03 13:34:19
Done.
| |
| 29 // an old password (e.g on a "make new password" form), if any. | 29 // password (e.g., on a sign-up or change password form), if any. |
| 30 bool LocateSpecificPasswords(std::vector<WebInputElement> passwords, | 30 bool LocateSpecificPasswords(std::vector<WebInputElement> passwords, |
| 31 WebInputElement* password, | 31 WebInputElement* password, |
| 32 WebInputElement* old_password) { | 32 WebInputElement* new_password) { |
| 33 switch (passwords.size()) { | 33 switch (passwords.size()) { |
| 34 case 1: | 34 case 1: |
| 35 // Single password, easy. | 35 // Single password, easy. |
| 36 *password = passwords[0]; | 36 *password = passwords[0]; |
| 37 break; | 37 break; |
| 38 case 2: | 38 case 2: |
| 39 if (passwords[0].value() == passwords[1].value()) { | 39 if (passwords[0].value() == passwords[1].value()) { |
| 40 // Treat two identical passwords as a single password. | 40 // Two identical passwords: assume we are seeing a new password with a |
|
vabr (Chromium)
2014/06/30 10:07:20
Did you consider what happens when the values are
engedy
2014/07/03 13:34:19
We have discussed this with Vaclav to great length
vabr (Chromium)
2014/07/03 14:42:56
Thinking about (2) from a bigger distance, I think
engedy
2014/07/03 18:47:36
Done.
| |
| 41 *password = passwords[0]; | 41 // confirmation. This can be either a sign-up form or a password change |
| 42 // form that does not ask for the old password. | |
| 43 *new_password = passwords[0]; | |
| 42 } else { | 44 } else { |
| 43 // Assume first is old password, second is new (no choice but to guess). | 45 // Assume first is old password, second is new (no choice but to guess). |
| 44 *old_password = passwords[0]; | 46 *password = passwords[0]; |
| 45 *password = passwords[1]; | 47 *new_password = passwords[1]; |
| 46 } | 48 } |
| 47 break; | 49 break; |
| 48 case 3: | 50 case 3: |
| 49 if (passwords[0].value() == passwords[1].value() && | 51 if (passwords[0].value() == passwords[1].value() && |
| 50 passwords[0].value() == passwords[2].value()) { | 52 passwords[0].value() == passwords[2].value()) { |
| 51 // All three passwords the same? Just treat as one and hope. | 53 // All three passwords the same? Just treat as one and hope. |
| 52 *password = passwords[0]; | 54 *password = passwords[0]; |
| 53 } else if (passwords[0].value() == passwords[1].value()) { | 55 } else if (passwords[0].value() == passwords[1].value()) { |
| 54 // Two the same and one different -> old password is duplicated one. | 56 // Strange that the new password comes first, but trust more in that the |
| 55 *old_password = passwords[0]; | 57 // field is duplicated more rather than in the ordering of fields. |
|
vabr (Chromium)
2014/06/30 10:07:20
(typo?) second "more"
engedy
2014/07/03 13:34:19
Done.
| |
| 56 *password = passwords[2]; | 58 *password = passwords[2]; |
| 59 *new_password = passwords[0]; | |
| 57 } else if (passwords[1].value() == passwords[2].value()) { | 60 } else if (passwords[1].value() == passwords[2].value()) { |
| 58 *old_password = passwords[0]; | 61 // New password is the duplicated one, and comes second. Makes sense. |
| 59 *password = passwords[1]; | 62 *password = passwords[0]; |
| 63 *new_password = passwords[1]; | |
| 60 } else { | 64 } else { |
| 61 // Three different passwords, or first and last match with middle | 65 // Three different passwords, or first and last match with middle |
| 62 // different. No idea which is which, so no luck. | 66 // different. No idea which is which, so no luck. |
| 63 return false; | 67 return false; |
| 64 } | 68 } |
| 65 break; | 69 break; |
| 66 default: | 70 default: |
| 67 return false; | 71 return false; |
| 68 } | 72 } |
| 69 return true; | 73 return true; |
| 70 } | 74 } |
| 71 | 75 |
| 72 // Get information about a login form that encapsulated in the | 76 // Get information about a login form encapsulated in a PasswordForm struct. |
| 73 // PasswordForm struct. | |
| 74 void GetPasswordForm(const WebFormElement& form, PasswordForm* password_form) { | 77 void GetPasswordForm(const WebFormElement& form, PasswordForm* password_form) { |
| 75 WebInputElement latest_input_element; | 78 WebInputElement latest_input_element; |
| 76 std::vector<WebInputElement> passwords; | 79 std::vector<WebInputElement> passwords; |
| 77 std::vector<base::string16> other_possible_usernames; | 80 std::vector<base::string16> other_possible_usernames; |
| 78 | 81 |
| 79 WebVector<WebFormControlElement> control_elements; | 82 WebVector<WebFormControlElement> control_elements; |
| 80 form.getFormControlElements(control_elements); | 83 form.getFormControlElements(control_elements); |
| 81 | 84 |
| 82 for (size_t i = 0; i < control_elements.size(); ++i) { | 85 for (size_t i = 0; i < control_elements.size(); ++i) { |
| 83 WebFormControlElement control_element = control_elements[i]; | 86 WebFormControlElement control_element = control_elements[i]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 | 123 |
| 121 // Calculate the canonical action URL | 124 // Calculate the canonical action URL |
| 122 WebString action = form.action(); | 125 WebString action = form.action(); |
| 123 if (action.isNull()) | 126 if (action.isNull()) |
| 124 action = WebString(""); // missing 'action' attribute implies current URL | 127 action = WebString(""); // missing 'action' attribute implies current URL |
| 125 GURL full_action(form.document().completeURL(action)); | 128 GURL full_action(form.document().completeURL(action)); |
| 126 if (!full_action.is_valid()) | 129 if (!full_action.is_valid()) |
| 127 return; | 130 return; |
| 128 | 131 |
| 129 WebInputElement password; | 132 WebInputElement password; |
| 130 WebInputElement old_password; | 133 WebInputElement new_password; |
| 131 if (!LocateSpecificPasswords(passwords, &password, &old_password)) | 134 if (!LocateSpecificPasswords(passwords, &password, &new_password)) |
| 132 return; | 135 return; |
| 133 | 136 |
| 134 // We want to keep the path but strip any authentication data, as well as | 137 // We want to keep the path but strip any authentication data, as well as |
| 135 // query and ref portions of URL, for the form action and form origin. | 138 // query and ref portions of URL, for the form action and form origin. |
| 136 GURL::Replacements rep; | 139 GURL::Replacements rep; |
| 137 rep.ClearUsername(); | 140 rep.ClearUsername(); |
| 138 rep.ClearPassword(); | 141 rep.ClearPassword(); |
| 139 rep.ClearQuery(); | 142 rep.ClearQuery(); |
| 140 rep.ClearRef(); | 143 rep.ClearRef(); |
| 141 password_form->action = full_action.ReplaceComponents(rep); | 144 password_form->action = full_action.ReplaceComponents(rep); |
| 142 password_form->origin = full_origin.ReplaceComponents(rep); | 145 password_form->origin = full_origin.ReplaceComponents(rep); |
| 143 | 146 |
| 144 rep.SetPathStr(""); | 147 rep.SetPathStr(""); |
| 145 password_form->signon_realm = full_origin.ReplaceComponents(rep).spec(); | 148 password_form->signon_realm = full_origin.ReplaceComponents(rep).spec(); |
| 146 | 149 |
| 147 password_form->other_possible_usernames.swap(other_possible_usernames); | 150 password_form->other_possible_usernames.swap(other_possible_usernames); |
| 148 | 151 |
| 149 if (!password.isNull()) { | 152 if (!password.isNull()) { |
| 150 password_form->password_element = password.nameForAutofill(); | 153 password_form->password_element = password.nameForAutofill(); |
| 151 password_form->password_value = password.value(); | 154 password_form->password_value = password.value(); |
| 152 password_form->password_autocomplete_set = password.autoComplete(); | 155 password_form->password_autocomplete_set = password.autoComplete(); |
| 153 } | 156 } |
| 154 if (!old_password.isNull()) { | 157 if (!new_password.isNull()) { |
| 155 password_form->old_password_element = old_password.nameForAutofill(); | 158 password_form->new_password_element = new_password.nameForAutofill(); |
| 156 password_form->old_password_value = old_password.value(); | 159 password_form->new_password_value = new_password.value(); |
| 157 } | 160 } |
| 158 | 161 |
| 159 password_form->scheme = PasswordForm::SCHEME_HTML; | 162 password_form->scheme = PasswordForm::SCHEME_HTML; |
| 160 password_form->ssl_valid = false; | 163 password_form->ssl_valid = false; |
| 161 password_form->preferred = false; | 164 password_form->preferred = false; |
| 162 password_form->blacklisted_by_user = false; | 165 password_form->blacklisted_by_user = false; |
| 163 password_form->type = PasswordForm::TYPE_MANUAL; | 166 password_form->type = PasswordForm::TYPE_MANUAL; |
| 164 password_form->use_additional_authentication = false; | 167 password_form->use_additional_authentication = false; |
| 165 } | 168 } |
| 166 | 169 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 180 blink::WebFormControlElement(), | 183 blink::WebFormControlElement(), |
| 181 REQUIRE_NONE, | 184 REQUIRE_NONE, |
| 182 EXTRACT_NONE, | 185 EXTRACT_NONE, |
| 183 &password_form->form_data, | 186 &password_form->form_data, |
| 184 NULL /* FormFieldData */); | 187 NULL /* FormFieldData */); |
| 185 | 188 |
| 186 return password_form.Pass(); | 189 return password_form.Pass(); |
| 187 } | 190 } |
| 188 | 191 |
| 189 } // namespace autofill | 192 } // namespace autofill |
| OLD | NEW |