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_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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 | 211 |
| 212 // Log a message including the name, method and action of |form|. | 212 // Log a message including the name, method and action of |form|. |
| 213 void LogHTMLForm(SavePasswordProgressLogger* logger, | 213 void LogHTMLForm(SavePasswordProgressLogger* logger, |
| 214 SavePasswordProgressLogger::StringID message_id, | 214 SavePasswordProgressLogger::StringID message_id, |
| 215 const blink::WebFormElement& form) { | 215 const blink::WebFormElement& form) { |
| 216 logger->LogHTMLForm(message_id, | 216 logger->LogHTMLForm(message_id, |
| 217 form.name().utf8(), | 217 form.name().utf8(), |
| 218 GURL(form.action().utf8())); | 218 GURL(form.action().utf8())); |
| 219 } | 219 } |
| 220 | 220 |
| 221 bool FillUserNameAndPassword(struct ParametersNeedUpdate* param, | |
|
vabr (Chromium)
2014/09/25 10:25:49
Please just pass a OtherPossibleUsernamesUsage* us
vabr (Chromium)
2014/09/25 10:25:49
(Just for future: if you passed a struct argument
vabr (Chromium)
2014/09/25 10:25:49
nit: Please also document that the return value in
Deepak
2014/09/25 12:02:26
Acknowledged.
Deepak
2014/09/25 12:02:26
I have made OtherPossibleUsernamesUsage enum as pu
Deepak
2014/09/25 12:02:26
Acknowledged.
| |
| 222 blink::WebInputElement* username_element, | |
| 223 blink::WebInputElement* password_element, | |
| 224 const PasswordFormFillData& fill_data, | |
| 225 bool exact_username_match, | |
| 226 bool set_selection) { | |
| 227 base::string16 current_username = username_element->value(); | |
| 228 // username and password will contain the match found if any. | |
| 229 base::string16 username; | |
| 230 base::string16 password; | |
| 231 | |
| 232 // Don't fill username if password can't be set. | |
| 233 if (!IsElementAutocompletable(*password_element)) | |
| 234 return false; | |
| 235 | |
| 236 // Look for any suitable matches to current field text. | |
| 237 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | |
| 238 current_username, | |
| 239 exact_username_match)) { | |
| 240 username = fill_data.basic_data.fields[0].value; | |
| 241 password = fill_data.basic_data.fields[1].value; | |
| 242 } else { | |
| 243 // Scan additional logins for a match. | |
| 244 PasswordFormFillData::LoginCollection::const_iterator iter; | |
| 245 for (iter = fill_data.additional_logins.begin(); | |
| 246 iter != fill_data.additional_logins.end(); | |
| 247 ++iter) { | |
| 248 if (DoUsernamesMatch( | |
| 249 iter->first, current_username, exact_username_match)) { | |
| 250 username = iter->first; | |
| 251 password = iter->second.password; | |
| 252 break; | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 // Check possible usernames. | |
| 257 if (username.empty() && password.empty()) { | |
| 258 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 259 fill_data.other_possible_usernames.begin(); | |
| 260 iter != fill_data.other_possible_usernames.end(); | |
| 261 ++iter) { | |
| 262 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 263 if (DoUsernamesMatch( | |
| 264 iter->second[i], current_username, exact_username_match)) { | |
| 265 param->usernames_usage = true; | |
| 266 username = iter->second[i]; | |
| 267 password = iter->first.password; | |
| 268 break; | |
| 269 } | |
| 270 } | |
| 271 if (!username.empty() && !password.empty()) | |
| 272 break; | |
| 273 } | |
| 274 } | |
| 275 } | |
| 276 if (password.empty()) | |
| 277 return false; // No match was found. | |
| 278 | |
| 279 // Input matches the username, fill in required values. | |
|
vabr (Chromium)
2014/09/25 10:25:49
Why did you leave out the "TODO(kent)" present at
Deepak
2014/09/25 12:02:26
Acknowledged.
| |
| 280 if (IsElementAutocompletable(*username_element)) { | |
| 281 username_element->setValue(username, true); | |
| 282 username_element->setAutofilled(true); | |
| 283 | |
| 284 if (set_selection) { | |
| 285 username_element->setSelectionRange(current_username.length(), | |
| 286 username.length()); | |
| 287 } | |
| 288 } else if (current_username != username) { | |
| 289 // If the username can't be filled and it doesn't match a saved password | |
| 290 // as is, don't autofill a password. | |
| 291 return false; | |
| 292 } | |
| 293 | |
| 294 // Wait to fill in the password until a user gesture occurs. This is to make | |
| 295 // sure that we do not fill in the DOM with a password until we believe the | |
| 296 // user is intentionally interacting with the page. | |
| 297 password_element->setSuggestedValue(password); | |
| 298 param->gate_keeper = true; | |
|
vabr (Chromium)
2014/09/25 10:25:49
There is no need to signal this through |gate_keep
Deepak
2014/09/25 12:02:26
Acknowledged.
| |
| 299 | |
| 300 password_element->setAutofilled(true); | |
| 301 return true; | |
| 302 } | |
| 303 | |
| 304 void GetSuggestions(struct ParametersNeedUpdate* param, | |
|
vabr (Chromium)
2014/09/25 10:25:49
Please keep the order of the 3 functions as it was
Deepak
2014/09/25 12:02:26
We are calling FillUserNameAndPassword() from Fill
| |
| 305 const PasswordFormFillData& fill_data, | |
| 306 const base::string16& input, | |
| 307 std::vector<base::string16>* suggestions, | |
| 308 std::vector<base::string16>* realms, | |
| 309 bool show_all) { | |
| 310 if (show_all || | |
| 311 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | |
| 312 suggestions->push_back(fill_data.basic_data.fields[0].value); | |
| 313 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | |
| 314 } | |
| 315 | |
| 316 for (PasswordFormFillData::LoginCollection::const_iterator iter = | |
| 317 fill_data.additional_logins.begin(); | |
| 318 iter != fill_data.additional_logins.end(); | |
| 319 ++iter) { | |
| 320 if (show_all || StartsWith(iter->first, input, false)) { | |
| 321 suggestions->push_back(iter->first); | |
| 322 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | |
| 323 } | |
| 324 } | |
| 325 | |
| 326 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 327 fill_data.other_possible_usernames.begin(); | |
| 328 iter != fill_data.other_possible_usernames.end(); | |
| 329 ++iter) { | |
| 330 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 331 if (show_all || StartsWith(iter->second[i], input, false)) { | |
| 332 param->usernames_usage = true; | |
| 333 suggestions->push_back(iter->second[i]); | |
| 334 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | |
| 335 } | |
| 336 } | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 // Attempts to fill |username_element| and |password_element| with the | |
| 341 // |fill_data|. Will use the data corresponding to the preferred username, | |
| 342 // unless the |username_element| already has a value set. In that case, | |
| 343 // attempts to fill the password matching the already filled username, if | |
| 344 // such a password exists. | |
| 345 void FillFormOnPasswordRecieved(struct ParametersNeedUpdate* param, | |
| 346 const PasswordFormFillData& fill_data, | |
| 347 blink::WebInputElement username_element, | |
| 348 blink::WebInputElement password_element) { | |
| 349 // Do not fill if the password field is in an iframe. | |
| 350 DCHECK(password_element.document().frame()); | |
| 351 if (password_element.document().frame()->parent()) | |
| 352 return; | |
| 353 | |
| 354 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 355 !username_element.form().autoComplete()) | |
| 356 return; | |
| 357 | |
| 358 // If we can't modify the password, don't try to set the username | |
| 359 if (!IsElementAutocompletable(password_element)) | |
| 360 return; | |
| 361 | |
| 362 // Try to set the username to the preferred name, but only if the field | |
| 363 // can be set and isn't prefilled. | |
| 364 if (IsElementAutocompletable(username_element) && | |
| 365 username_element.value().isEmpty()) { | |
| 366 // TODO(tkent): Check maxlength and pattern. | |
| 367 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
| 368 } | |
| 369 | |
| 370 // Fill if we have an exact match for the username. Note that this sets | |
| 371 // username to autofilled. | |
| 372 FillUserNameAndPassword(param, | |
|
vabr (Chromium)
2014/09/25 10:25:49
Forward the return value here, to signal out if th
Deepak
2014/09/25 12:02:26
Acknowledged.
| |
| 373 &username_element, | |
| 374 &password_element, | |
| 375 fill_data, | |
| 376 true /* exact_username_match */, | |
| 377 false /* set_selection */); | |
| 378 } | |
| 379 | |
| 221 } // namespace | 380 } // namespace |
| 222 | 381 |
| 223 //////////////////////////////////////////////////////////////////////////////// | 382 //////////////////////////////////////////////////////////////////////////////// |
| 224 // PasswordAutofillAgent, public: | 383 // PasswordAutofillAgent, public: |
| 225 | 384 |
| 226 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 385 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
| 227 : content::RenderViewObserver(render_view), | 386 : content::RenderViewObserver(render_view), |
| 228 usernames_usage_(NOTHING_TO_AUTOFILL), | 387 usernames_usage_(NOTHING_TO_AUTOFILL), |
| 229 web_view_(render_view->GetWebView()), | 388 web_view_(render_view->GetWebView()), |
| 230 logging_state_active_(false), | 389 logging_state_active_(false), |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 return false; | 455 return false; |
| 297 | 456 |
| 298 blink::WebInputElement password = password_info.password_field; | 457 blink::WebInputElement password = password_info.password_field; |
| 299 if (!IsElementEditable(password)) | 458 if (!IsElementEditable(password)) |
| 300 return false; | 459 return false; |
| 301 | 460 |
| 302 blink::WebInputElement username = element; // We need a non-const. | 461 blink::WebInputElement username = element; // We need a non-const. |
| 303 | 462 |
| 304 // Do not set selection when ending an editing session, otherwise it can | 463 // Do not set selection when ending an editing session, otherwise it can |
| 305 // mess with focus. | 464 // mess with focus. |
| 306 FillUserNameAndPassword(&username, | 465 struct ParametersNeedUpdate param; |
| 466 FillUserNameAndPassword(¶m, | |
| 467 &username, | |
| 307 &password, | 468 &password, |
| 308 fill_data, | 469 fill_data, |
| 309 true /* exact_username_match */, | 470 true /* exact_username_match */, |
| 310 false /* set_selection */); | 471 false /* set_selection */); |
| 472 if (param.usernames_usage) | |
| 473 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
| 474 if (param.gate_keeper) | |
| 475 gatekeeper_.RegisterElement(&password); | |
| 476 | |
| 311 return true; | 477 return true; |
| 312 } | 478 } |
| 313 | 479 |
| 314 bool PasswordAutofillAgent::TextDidChangeInTextField( | 480 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 315 const blink::WebInputElement& element) { | 481 const blink::WebInputElement& element) { |
| 316 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 482 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
| 317 blink::WebInputElement mutable_element = element; // We need a non-const. | 483 blink::WebInputElement mutable_element = element; // We need a non-const. |
| 318 | 484 |
| 319 if (element.isPasswordField()) { | 485 if (element.isPasswordField()) { |
| 320 // Some login forms have event handlers that put a hash of the password into | 486 // Some login forms have event handlers that put a hash of the password into |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 blink::WebInputElement username_element = | 972 blink::WebInputElement username_element = |
| 807 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 973 form_elements->input_elements[form_data.basic_data.fields[0].name]; |
| 808 | 974 |
| 809 // Get pointer to password element. (We currently only support single | 975 // Get pointer to password element. (We currently only support single |
| 810 // password forms). | 976 // password forms). |
| 811 blink::WebInputElement password_element = | 977 blink::WebInputElement password_element = |
| 812 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 978 form_elements->input_elements[form_data.basic_data.fields[1].name]; |
| 813 | 979 |
| 814 // If wait_for_username is true, we don't want to initially fill the form | 980 // If wait_for_username is true, we don't want to initially fill the form |
| 815 // until the user types in a valid username. | 981 // until the user types in a valid username. |
| 816 if (!form_data.wait_for_username) | 982 if (!form_data.wait_for_username) { |
| 817 FillFormOnPasswordRecieved(form_data, username_element, password_element); | 983 struct ParametersNeedUpdate param; |
| 984 FillFormOnPasswordRecieved( | |
| 985 ¶m, form_data, username_element, password_element); | |
| 986 if (param.usernames_usage) | |
| 987 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
| 988 if (param.gate_keeper) | |
| 989 gatekeeper_.RegisterElement(&password_element); | |
| 990 } | |
| 818 | 991 |
| 819 // We might have already filled this form if there are two <form> elements | 992 // We might have already filled this form if there are two <form> elements |
| 820 // with identical markup. | 993 // with identical markup. |
| 821 if (login_to_password_info_.find(username_element) != | 994 if (login_to_password_info_.find(username_element) != |
| 822 login_to_password_info_.end()) | 995 login_to_password_info_.end()) |
| 823 continue; | 996 continue; |
| 824 | 997 |
| 825 PasswordInfo password_info; | 998 PasswordInfo password_info; |
| 826 password_info.fill_data = form_data; | 999 password_info.fill_data = form_data; |
| 827 password_info.password_field = password_element; | 1000 password_info.password_field = password_element; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 841 logging_state_active_ = active; | 1014 logging_state_active_ = active; |
| 842 } | 1015 } |
| 843 | 1016 |
| 844 //////////////////////////////////////////////////////////////////////////////// | 1017 //////////////////////////////////////////////////////////////////////////////// |
| 845 // PasswordAutofillAgent, private: | 1018 // PasswordAutofillAgent, private: |
| 846 | 1019 |
| 847 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1020 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
| 848 : backspace_pressed_last(false), password_was_edited_last(false) { | 1021 : backspace_pressed_last(false), password_was_edited_last(false) { |
| 849 } | 1022 } |
| 850 | 1023 |
| 851 void PasswordAutofillAgent::GetSuggestions( | |
| 852 const PasswordFormFillData& fill_data, | |
| 853 const base::string16& input, | |
| 854 std::vector<base::string16>* suggestions, | |
| 855 std::vector<base::string16>* realms, | |
| 856 bool show_all) { | |
| 857 if (show_all || | |
| 858 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | |
| 859 suggestions->push_back(fill_data.basic_data.fields[0].value); | |
| 860 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | |
| 861 } | |
| 862 | |
| 863 for (PasswordFormFillData::LoginCollection::const_iterator iter = | |
| 864 fill_data.additional_logins.begin(); | |
| 865 iter != fill_data.additional_logins.end(); | |
| 866 ++iter) { | |
| 867 if (show_all || StartsWith(iter->first, input, false)) { | |
| 868 suggestions->push_back(iter->first); | |
| 869 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | |
| 870 } | |
| 871 } | |
| 872 | |
| 873 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 874 fill_data.other_possible_usernames.begin(); | |
| 875 iter != fill_data.other_possible_usernames.end(); | |
| 876 ++iter) { | |
| 877 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 878 if (show_all || StartsWith(iter->second[i], input, false)) { | |
| 879 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | |
| 880 suggestions->push_back(iter->second[i]); | |
| 881 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | |
| 882 } | |
| 883 } | |
| 884 } | |
| 885 } | |
| 886 | |
| 887 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1024 bool PasswordAutofillAgent::ShowSuggestionPopup( |
| 888 const PasswordFormFillData& fill_data, | 1025 const PasswordFormFillData& fill_data, |
| 889 const blink::WebInputElement& user_input, | 1026 const blink::WebInputElement& user_input, |
| 890 bool show_all) { | 1027 bool show_all) { |
| 891 blink::WebFrame* frame = user_input.document().frame(); | 1028 blink::WebFrame* frame = user_input.document().frame(); |
| 892 if (!frame) | 1029 if (!frame) |
| 893 return false; | 1030 return false; |
| 894 | 1031 |
| 895 blink::WebView* webview = frame->view(); | 1032 blink::WebView* webview = frame->view(); |
| 896 if (!webview) | 1033 if (!webview) |
| 897 return false; | 1034 return false; |
| 898 | 1035 |
| 899 std::vector<base::string16> suggestions; | 1036 std::vector<base::string16> suggestions; |
| 900 std::vector<base::string16> realms; | 1037 std::vector<base::string16> realms; |
| 1038 struct ParametersNeedUpdate param; | |
| 901 GetSuggestions( | 1039 GetSuggestions( |
| 902 fill_data, user_input.value(), &suggestions, &realms, show_all); | 1040 ¶m, fill_data, user_input.value(), &suggestions, &realms, show_all); |
| 1041 if (param.usernames_usage) | |
| 1042 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | |
| 903 DCHECK_EQ(suggestions.size(), realms.size()); | 1043 DCHECK_EQ(suggestions.size(), realms.size()); |
| 904 | 1044 |
| 905 FormData form; | 1045 FormData form; |
| 906 FormFieldData field; | 1046 FormFieldData field; |
| 907 FindFormAndFieldForFormControlElement( | 1047 FindFormAndFieldForFormControlElement( |
| 908 user_input, &form, &field, REQUIRE_NONE); | 1048 user_input, &form, &field, REQUIRE_NONE); |
| 909 | 1049 |
| 910 blink::WebInputElement selected_element = user_input; | 1050 blink::WebInputElement selected_element = user_input; |
| 911 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1051 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
| 912 | 1052 |
| 913 float scale = web_view_->pageScaleFactor(); | 1053 float scale = web_view_->pageScaleFactor(); |
| 914 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1054 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
| 915 bounding_box.y() * scale, | 1055 bounding_box.y() * scale, |
| 916 bounding_box.width() * scale, | 1056 bounding_box.width() * scale, |
| 917 bounding_box.height() * scale); | 1057 bounding_box.height() * scale); |
| 918 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1058 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
| 919 routing_id(), field, bounding_box_scaled, suggestions, realms)); | 1059 routing_id(), field, bounding_box_scaled, suggestions, realms)); |
| 920 return !suggestions.empty(); | 1060 return !suggestions.empty(); |
| 921 } | 1061 } |
| 922 | 1062 |
| 923 void PasswordAutofillAgent::FillFormOnPasswordRecieved( | |
| 924 const PasswordFormFillData& fill_data, | |
| 925 blink::WebInputElement username_element, | |
| 926 blink::WebInputElement password_element) { | |
| 927 // Do not fill if the password field is in an iframe. | |
| 928 DCHECK(password_element.document().frame()); | |
| 929 if (password_element.document().frame()->parent()) | |
| 930 return; | |
| 931 | |
| 932 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 933 !username_element.form().autoComplete()) | |
| 934 return; | |
| 935 | |
| 936 // If we can't modify the password, don't try to set the username | |
| 937 if (!IsElementAutocompletable(password_element)) | |
| 938 return; | |
| 939 | |
| 940 // Try to set the username to the preferred name, but only if the field | |
| 941 // can be set and isn't prefilled. | |
| 942 if (IsElementAutocompletable(username_element) && | |
| 943 username_element.value().isEmpty()) { | |
| 944 // TODO(tkent): Check maxlength and pattern. | |
| 945 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
| 946 } | |
| 947 | |
| 948 // Fill if we have an exact match for the username. Note that this sets | |
| 949 // username to autofilled. | |
| 950 FillUserNameAndPassword(&username_element, | |
| 951 &password_element, | |
| 952 fill_data, | |
| 953 true /* exact_username_match */, | |
| 954 false /* set_selection */); | |
| 955 } | |
| 956 | |
| 957 bool PasswordAutofillAgent::FillUserNameAndPassword( | |
| 958 blink::WebInputElement* username_element, | |
| 959 blink::WebInputElement* password_element, | |
| 960 const PasswordFormFillData& fill_data, | |
| 961 bool exact_username_match, | |
| 962 bool set_selection) { | |
| 963 base::string16 current_username = username_element->value(); | |
| 964 // username and password will contain the match found if any. | |
| 965 base::string16 username; | |
| 966 base::string16 password; | |
| 967 | |
| 968 // Don't fill username if password can't be set. | |
| 969 if (!IsElementAutocompletable(*password_element)) | |
| 970 return false; | |
| 971 | |
| 972 // Look for any suitable matches to current field text. | |
| 973 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | |
| 974 current_username, | |
| 975 exact_username_match)) { | |
| 976 username = fill_data.basic_data.fields[0].value; | |
| 977 password = fill_data.basic_data.fields[1].value; | |
| 978 } else { | |
| 979 // Scan additional logins for a match. | |
| 980 PasswordFormFillData::LoginCollection::const_iterator iter; | |
| 981 for (iter = fill_data.additional_logins.begin(); | |
| 982 iter != fill_data.additional_logins.end(); | |
| 983 ++iter) { | |
| 984 if (DoUsernamesMatch( | |
| 985 iter->first, current_username, exact_username_match)) { | |
| 986 username = iter->first; | |
| 987 password = iter->second.password; | |
| 988 break; | |
| 989 } | |
| 990 } | |
| 991 | |
| 992 // Check possible usernames. | |
| 993 if (username.empty() && password.empty()) { | |
| 994 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 995 fill_data.other_possible_usernames.begin(); | |
| 996 iter != fill_data.other_possible_usernames.end(); | |
| 997 ++iter) { | |
| 998 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 999 if (DoUsernamesMatch( | |
| 1000 iter->second[i], current_username, exact_username_match)) { | |
| 1001 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
| 1002 username = iter->second[i]; | |
| 1003 password = iter->first.password; | |
| 1004 break; | |
| 1005 } | |
| 1006 } | |
| 1007 if (!username.empty() && !password.empty()) | |
| 1008 break; | |
| 1009 } | |
| 1010 } | |
| 1011 } | |
| 1012 if (password.empty()) | |
| 1013 return false; // No match was found. | |
| 1014 | |
| 1015 // TODO(tkent): Check maxlength and pattern for both username and password | |
| 1016 // fields. | |
| 1017 | |
| 1018 // Input matches the username, fill in required values. | |
| 1019 if (IsElementAutocompletable(*username_element)) { | |
| 1020 username_element->setValue(username, true); | |
| 1021 username_element->setAutofilled(true); | |
| 1022 | |
| 1023 if (set_selection) { | |
| 1024 username_element->setSelectionRange(current_username.length(), | |
| 1025 username.length()); | |
| 1026 } | |
| 1027 } else if (current_username != username) { | |
| 1028 // If the username can't be filled and it doesn't match a saved password | |
| 1029 // as is, don't autofill a password. | |
| 1030 return false; | |
| 1031 } | |
| 1032 | |
| 1033 // Wait to fill in the password until a user gesture occurs. This is to make | |
| 1034 // sure that we do not fill in the DOM with a password until we believe the | |
| 1035 // user is intentionally interacting with the page. | |
| 1036 password_element->setSuggestedValue(password); | |
| 1037 gatekeeper_.RegisterElement(password_element); | |
| 1038 | |
| 1039 password_element->setAutofilled(true); | |
| 1040 return true; | |
| 1041 } | |
| 1042 | |
| 1043 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1063 void PasswordAutofillAgent::PerformInlineAutocomplete( |
| 1044 const blink::WebInputElement& username_input, | 1064 const blink::WebInputElement& username_input, |
| 1045 const blink::WebInputElement& password_input, | 1065 const blink::WebInputElement& password_input, |
| 1046 const PasswordFormFillData& fill_data) { | 1066 const PasswordFormFillData& fill_data) { |
| 1047 DCHECK(!fill_data.wait_for_username); | 1067 DCHECK(!fill_data.wait_for_username); |
| 1048 | 1068 |
| 1049 // We need non-const versions of the username and password inputs. | 1069 // We need non-const versions of the username and password inputs. |
| 1050 blink::WebInputElement username = username_input; | 1070 blink::WebInputElement username = username_input; |
| 1051 blink::WebInputElement password = password_input; | 1071 blink::WebInputElement password = password_input; |
| 1052 | 1072 |
| 1053 // Don't inline autocomplete if the caret is not at the end. | 1073 // Don't inline autocomplete if the caret is not at the end. |
| 1054 // TODO(jcivelli): is there a better way to test the caret location? | 1074 // TODO(jcivelli): is there a better way to test the caret location? |
| 1055 if (username.selectionStart() != username.selectionEnd() || | 1075 if (username.selectionStart() != username.selectionEnd() || |
| 1056 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1076 username.selectionEnd() != static_cast<int>(username.value().length())) { |
| 1057 return; | 1077 return; |
| 1058 } | 1078 } |
| 1059 | 1079 |
| 1060 // Show the popup with the list of available usernames. | 1080 // Show the popup with the list of available usernames. |
| 1061 ShowSuggestionPopup(fill_data, username, false); | 1081 ShowSuggestionPopup(fill_data, username, false); |
| 1062 | 1082 |
| 1063 #if !defined(OS_ANDROID) | 1083 #if !defined(OS_ANDROID) |
| 1064 // Fill the user and password field with the most relevant match. Android | 1084 // Fill the user and password field with the most relevant match. Android |
| 1065 // only fills in the fields after the user clicks on the suggestion popup. | 1085 // only fills in the fields after the user clicks on the suggestion popup. |
| 1066 FillUserNameAndPassword(&username, | 1086 struct ParametersNeedUpdate param; |
|
tfarina
2014/09/25 20:00:23
no 'struct' here as well. This is a C[ism].
| |
| 1087 FillUserNameAndPassword(¶m, | |
| 1088 &username, | |
| 1067 &password, | 1089 &password, |
| 1068 fill_data, | 1090 fill_data, |
| 1069 false /* exact_username_match */, | 1091 false /* exact_username_match */, |
| 1070 true /* set_selection */); | 1092 true /* set_selection */); |
| 1093 if (param.usernames_usage) | |
| 1094 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
| 1095 if (param.gate_keeper) | |
| 1096 gatekeeper_.RegisterElement(&password); | |
| 1097 | |
| 1071 #endif | 1098 #endif |
| 1072 } | 1099 } |
| 1073 | 1100 |
| 1074 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1101 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 1075 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1102 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 1076 iter != login_to_password_info_.end();) { | 1103 iter != login_to_password_info_.end();) { |
| 1077 if (iter->first.document().frame() == frame) { | 1104 if (iter->first.document().frame() == frame) { |
| 1078 password_to_username_.erase(iter->second.password_field); | 1105 password_to_username_.erase(iter->second.password_field); |
| 1079 login_to_password_info_.erase(iter++); | 1106 login_to_password_info_.erase(iter++); |
| 1080 } else { | 1107 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1161 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
| 1135 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1162 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
| 1136 password_form->password_value.empty() && | 1163 password_form->password_value.empty() && |
| 1137 password_form->new_password_value.empty())) { | 1164 password_form->new_password_value.empty())) { |
| 1138 return; | 1165 return; |
| 1139 } | 1166 } |
| 1140 provisionally_saved_forms_[frame].reset(password_form.release()); | 1167 provisionally_saved_forms_[frame].reset(password_form.release()); |
| 1141 } | 1168 } |
| 1142 | 1169 |
| 1143 } // namespace autofill | 1170 } // namespace autofill |
| OLD | NEW |