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

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

Issue 225823006: Rewrite functions from WebPasswordFormData and WebPasswordFormUtils in (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update code as per review comments. Created 6 years, 8 months 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_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"
10 #include "third_party/WebKit/public/web/WebDocument.h"
9 #include "third_party/WebKit/public/web/WebFormControlElement.h" 11 #include "third_party/WebKit/public/web/WebFormControlElement.h"
10 #include "third_party/WebKit/public/web/WebPasswordFormData.h" 12 #include "third_party/WebKit/public/web/WebInputElement.h"
11 13
14 using blink::WebDocument;
15 using blink::WebFormControlElement;
12 using blink::WebFormElement; 16 using blink::WebFormElement;
13 using blink::WebPasswordFormData; 17 using blink::WebInputElement;
18 using blink::WebString;
19 using blink::WebVector;
14 20
15 namespace autofill { 21 namespace autofill {
16 namespace { 22 namespace {
17 23
18 scoped_ptr<PasswordForm> InitPasswordFormFromWebPasswordForm( 24 // Maximum number of password fields we will observe before throwing our
19 const WebFormElement& web_form, 25 // hands in the air and giving up with a given form.
20 const blink::WebPasswordFormData& web_password_form) { 26 static const size_t kMaxPasswords = 3;
21 PasswordForm* password_form = new PasswordForm(); 27
22 password_form->signon_realm = web_password_form.signonRealm.utf8(); 28 // Helper to determine which password is the main one, and which is
23 password_form->origin = web_password_form.origin; 29 // an old password (e.g on a "make new password" form), if any.
24 password_form->action = web_password_form.action; 30 bool LocateSpecificPasswords(std::vector<WebInputElement> passwords,
25 password_form->submit_element = web_password_form.submitElement; 31 WebInputElement* password,
26 password_form->username_element = web_password_form.userNameElement; 32 WebInputElement* old_password) {
27 password_form->username_value = web_password_form.userNameValue; 33 switch (passwords.size()) {
28 password_form->other_possible_usernames.insert( 34 case 1:
29 password_form->other_possible_usernames.begin(), 35 // Single password, easy.
30 web_password_form.possibleUserNames.data(), 36 *password = passwords[0];
31 web_password_form.possibleUserNames.data() + 37 break;
32 web_password_form.possibleUserNames.size()); 38 case 2:
33 password_form->password_element = web_password_form.passwordElement; 39 if (passwords[0].value() == passwords[1].value()) {
34 password_form->password_value = web_password_form.passwordValue; 40 // Treat two identical passwords as a single password.
35 password_form->password_autocomplete_set = 41 *password = passwords[0];
36 web_password_form.passwordShouldAutocomplete; 42 } else {
37 password_form->old_password_element = web_password_form.oldPasswordElement; 43 // Assume first is old password, second is new (no choice but to guess).
38 password_form->old_password_value = web_password_form.oldPasswordValue; 44 *old_password = passwords[0];
45 *password = passwords[1];
46 }
47 break;
48 case 3:
49 if (passwords[0].value() == passwords[1].value() &&
50 passwords[0].value() == passwords[2].value()) {
51 // All three passwords the same? Just treat as one and hope.
52 *password = passwords[0];
53 } else if (passwords[0].value() == passwords[1].value()) {
54 // Two the same and one different -> old password is duplicated one.
55 *old_password = passwords[0];
56 *password = passwords[2];
57 } else if (passwords[1].value() == passwords[2].value()) {
58 *old_password = passwords[0];
59 *password = passwords[1];
60 } else {
61 // Three different passwords, or first and last match with middle
62 // different. No idea which is which, so no luck.
63 return false;
64 }
65 break;
66 default:
67 return false;
68 }
69 return true;
70 }
71
72 // Get information about a login form that encapsulated in the
73 // PasswordForm struct.
74 void GetPasswordForm(const WebFormElement& form, PasswordForm* password_form) {
75 WebInputElement latest_input_element;
76 std::vector<WebInputElement> passwords;
77 std::vector<base::string16> other_possible_usernames;
78
79 WebVector<WebFormControlElement> control_elements;
80 form.getFormControlElements(control_elements);
81
82 for (size_t i = 0; i < control_elements.size(); ++i) {
83 WebFormControlElement control_element = control_elements[i];
84 if (control_element.isActivatedSubmit())
85 password_form->submit_element = control_element.formControlName();
86
87 WebInputElement* input_element = toWebInputElement(&control_element);
88 if (!input_element || !input_element->isEnabled())
89 continue;
90
91 if ((passwords.size() < kMaxPasswords) &&
92 input_element->isPasswordField()) {
93 // We assume that the username element is the input element before the
94 // first password element.
95 if (passwords.empty() && !latest_input_element.isNull()) {
96 password_form->username_element =
97 latest_input_element.nameForAutofill();
98 password_form->username_value = latest_input_element.value();
99 // Remove the selected username from other_possible_usernames.
100 if (!other_possible_usernames.empty() &&
101 !latest_input_element.value().isEmpty())
102 other_possible_usernames.resize(other_possible_usernames.size() - 1);
103 }
104 passwords.push_back(*input_element);
105 }
106
107 // Various input types such as text, url, email can be a username field.
108 if (input_element->isTextField() && !input_element->isPasswordField()) {
109 latest_input_element = *input_element;
110 // We ignore elements that have no value. Unlike username_element,
111 // other_possible_usernames is used only for autofill, not for form
112 // identification, and blank autofill entries are not useful.
113 if (!input_element->value().isEmpty())
114 other_possible_usernames.push_back(input_element->value());
115 }
116 }
117
118 // Get the document URL
119 GURL full_origin(form.document().url());
120
121 // Calculate the canonical action URL
122 WebString action = form.action();
123 if (action.isNull())
124 action = WebString(""); // missing 'action' attribute implies current URL
125 GURL full_action(form.document().completeURL(action));
126 if (!full_action.is_valid())
127 return;
128
129 WebInputElement password;
130 WebInputElement old_password;
131 if (!LocateSpecificPasswords(passwords, &password, &old_password))
132 return;
133
134 // 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.
136 GURL::Replacements rep;
137 rep.ClearUsername();
138 rep.ClearPassword();
139 rep.ClearQuery();
140 rep.ClearRef();
141 password_form->action = full_action.ReplaceComponents(rep);
142 password_form->origin = full_origin.ReplaceComponents(rep);
143
144 rep.SetPathStr("");
145 password_form->signon_realm = full_origin.ReplaceComponents(rep).spec();
146
147 password_form->other_possible_usernames.swap(other_possible_usernames);
148
149 if (!password.isNull()) {
150 password_form->password_element = password.nameForAutofill();
151 password_form->password_value = password.value();
152 password_form->password_autocomplete_set = password.autoComplete();
153 }
154 if (!old_password.isNull()) {
155 password_form->old_password_element = old_password.nameForAutofill();
156 password_form->old_password_value = old_password.value();
157 }
158
39 password_form->scheme = PasswordForm::SCHEME_HTML; 159 password_form->scheme = PasswordForm::SCHEME_HTML;
40 password_form->ssl_valid = false; 160 password_form->ssl_valid = false;
41 password_form->preferred = false; 161 password_form->preferred = false;
42 password_form->blacklisted_by_user = false; 162 password_form->blacklisted_by_user = false;
43 password_form->type = PasswordForm::TYPE_MANUAL; 163 password_form->type = PasswordForm::TYPE_MANUAL;
44 password_form->use_additional_authentication = false; 164 password_form->use_additional_authentication = false;
165 }
166
167 scoped_ptr<PasswordForm> InitPasswordFormFromWebFormElement(
168 const WebFormElement& web_form,
169 PasswordForm* password_form) {
170 GetPasswordForm(web_form, password_form);
171
172 if (!password_form->action.is_valid())
173 return scoped_ptr<PasswordForm>();
174
45 WebFormElementToFormData(web_form, 175 WebFormElementToFormData(web_form,
46 blink::WebFormControlElement(), 176 blink::WebFormControlElement(),
47 REQUIRE_NONE, 177 REQUIRE_NONE,
48 EXTRACT_NONE, 178 EXTRACT_NONE,
49 &password_form->form_data, 179 &password_form->form_data,
50 NULL /* FormFieldData */); 180 NULL /* FormFieldData */);
51 return scoped_ptr<PasswordForm>(password_form); 181 return scoped_ptr<PasswordForm>(password_form);
52 } 182 }
53 183
54 } // namespace 184 } // namespace
55 185
56 scoped_ptr<PasswordForm> CreatePasswordForm(const WebFormElement& webform) { 186 scoped_ptr<PasswordForm> CreatePasswordForm(const WebFormElement& web_form) {
57 WebPasswordFormData web_password_form(webform); 187 if (web_form.isNull())
58 if (web_password_form.isValid()) 188 return scoped_ptr<PasswordForm>();
59 return InitPasswordFormFromWebPasswordForm(webform, web_password_form); 189
60 return scoped_ptr<PasswordForm>(); 190 PasswordForm* password_form = new PasswordForm();
191 return InitPasswordFormFromWebFormElement(web_form, password_form);
61 } 192 }
62 193
63 } // namespace autofill 194 } // namespace autofill
Garrett Casto 2014/04/17 18:20:22 Nit: Remove trailing whitespace.
ziran.sun 2014/04/22 15:20:01 Sorry, but I couldn't find whitespace here...
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698