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 void GetSuggestions( | |
|
vabr (Chromium)
2014/09/26 10:06:48
nit: Please provide a short comment describing wha
vabr (Chromium)
2014/09/26 10:06:48
I suggest removing the |usernames_usage| and signa
| |
| 222 const PasswordFormFillData& fill_data, | |
| 223 const base::string16& input, | |
| 224 std::vector<base::string16>* suggestions, | |
| 225 std::vector<base::string16>* realms, | |
| 226 bool show_all, | |
| 227 PasswordAutofillAgent::OtherPossibleUsernamesUsage* usernames_usage) { | |
| 228 if (show_all || | |
| 229 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | |
| 230 suggestions->push_back(fill_data.basic_data.fields[0].value); | |
| 231 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | |
| 232 } | |
| 233 | |
| 234 for (PasswordFormFillData::LoginCollection::const_iterator iter = | |
| 235 fill_data.additional_logins.begin(); | |
| 236 iter != fill_data.additional_logins.end(); | |
| 237 ++iter) { | |
| 238 if (show_all || StartsWith(iter->first, input, false)) { | |
| 239 suggestions->push_back(iter->first); | |
| 240 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 245 fill_data.other_possible_usernames.begin(); | |
| 246 iter != fill_data.other_possible_usernames.end(); | |
| 247 ++iter) { | |
| 248 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 249 if (show_all || StartsWith(iter->second[i], input, false)) { | |
| 250 *usernames_usage = PasswordAutofillAgent::OtherPossibleUsernamesUsage:: | |
| 251 OTHER_POSSIBLE_USERNAME_SELECTED; | |
|
vabr (Chromium)
2014/09/26 10:06:48
Please keep the correct value. SHOWN, not SELECTED
| |
| 252 suggestions->push_back(iter->second[i]); | |
| 253 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | |
| 254 } | |
| 255 } | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 bool FillUserNameAndPassword( | |
|
vabr (Chromium)
2014/09/26 10:06:48
I suggest the following changes to the signature o
vabr (Chromium)
2014/09/26 10:06:48
nit: Please also here provide a short comment desc
| |
| 260 blink::WebInputElement* username_element, | |
| 261 blink::WebInputElement* password_element, | |
| 262 const PasswordFormFillData& fill_data, | |
| 263 bool exact_username_match, | |
| 264 bool set_selection, | |
| 265 PasswordAutofillAgent::OtherPossibleUsernamesUsage* usernames_usage) { | |
| 266 base::string16 current_username = username_element->value(); | |
| 267 // username and password will contain the match found if any. | |
| 268 base::string16 username; | |
| 269 base::string16 password; | |
| 270 | |
| 271 // Don't fill username if password can't be set. | |
| 272 if (!IsElementAutocompletable(*password_element)) | |
| 273 return false; | |
| 274 | |
| 275 // Look for any suitable matches to current field text. | |
| 276 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | |
| 277 current_username, | |
| 278 exact_username_match)) { | |
| 279 username = fill_data.basic_data.fields[0].value; | |
| 280 password = fill_data.basic_data.fields[1].value; | |
| 281 } else { | |
| 282 // Scan additional logins for a match. | |
| 283 PasswordFormFillData::LoginCollection::const_iterator iter; | |
| 284 for (iter = fill_data.additional_logins.begin(); | |
| 285 iter != fill_data.additional_logins.end(); | |
| 286 ++iter) { | |
| 287 if (DoUsernamesMatch( | |
| 288 iter->first, current_username, exact_username_match)) { | |
| 289 username = iter->first; | |
| 290 password = iter->second.password; | |
| 291 break; | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 // Check possible usernames. | |
| 296 if (username.empty() && password.empty()) { | |
| 297 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
| 298 fill_data.other_possible_usernames.begin(); | |
| 299 iter != fill_data.other_possible_usernames.end(); | |
| 300 ++iter) { | |
| 301 for (size_t i = 0; i < iter->second.size(); ++i) { | |
| 302 if (DoUsernamesMatch( | |
| 303 iter->second[i], current_username, exact_username_match)) { | |
| 304 *usernames_usage = PasswordAutofillAgent:: | |
| 305 OtherPossibleUsernamesUsage::OTHER_POSSIBLE_USERNAME_SELECTED; | |
| 306 username = iter->second[i]; | |
| 307 password = iter->first.password; | |
| 308 break; | |
| 309 } | |
| 310 } | |
| 311 if (!username.empty() && !password.empty()) | |
| 312 break; | |
| 313 } | |
| 314 } | |
| 315 } | |
| 316 if (password.empty()) | |
| 317 return false; // No match was found. | |
| 318 | |
| 319 // TODO(tkent): Check maxlength and pattern for both username and password | |
| 320 // fields. | |
| 321 | |
| 322 // Input matches the username, fill in required values. | |
| 323 if (IsElementAutocompletable(*username_element)) { | |
| 324 username_element->setValue(username, true); | |
| 325 username_element->setAutofilled(true); | |
| 326 | |
| 327 if (set_selection) { | |
| 328 username_element->setSelectionRange(current_username.length(), | |
| 329 username.length()); | |
| 330 } | |
| 331 } else if (current_username != username) { | |
| 332 // If the username can't be filled and it doesn't match a saved password | |
| 333 // as is, don't autofill a password. | |
| 334 return false; | |
| 335 } | |
| 336 | |
| 337 // Wait to fill in the password until a user gesture occurs. This is to make | |
| 338 // sure that we do not fill in the DOM with a password until we believe the | |
| 339 // user is intentionally interacting with the page. | |
| 340 password_element->setSuggestedValue(password); | |
| 341 password_element->setAutofilled(true); | |
| 342 return true; | |
| 343 } | |
| 344 | |
| 345 // Attempts to fill |username_element| and |password_element| with the | |
| 346 // |fill_data|. Will use the data corresponding to the preferred username, | |
| 347 // unless the |username_element| already has a value set. In that case, | |
| 348 // attempts to fill the password matching the already filled username, if | |
| 349 // such a password exists. | |
|
vabr (Chromium)
2014/09/26 10:06:48
nit: Please describe the meaning of the (new) retu
| |
| 350 bool FillFormOnPasswordRecieved( | |
| 351 const PasswordFormFillData& fill_data, | |
| 352 blink::WebInputElement username_element, | |
| 353 blink::WebInputElement password_element, | |
| 354 PasswordAutofillAgent::OtherPossibleUsernamesUsage* usernames_usage) { | |
| 355 // Do not fill if the password field is in an iframe. | |
| 356 DCHECK(password_element.document().frame()); | |
| 357 if (password_element.document().frame()->parent()) | |
| 358 return false; | |
| 359 | |
| 360 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
| 361 !username_element.form().autoComplete()) | |
| 362 return false; | |
| 363 | |
| 364 // If we can't modify the password, don't try to set the username | |
| 365 if (!IsElementAutocompletable(password_element)) | |
| 366 return false; | |
| 367 | |
| 368 // Try to set the username to the preferred name, but only if the field | |
| 369 // can be set and isn't prefilled. | |
| 370 if (IsElementAutocompletable(username_element) && | |
| 371 username_element.value().isEmpty()) { | |
| 372 // TODO(tkent): Check maxlength and pattern. | |
| 373 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
| 374 } | |
| 375 | |
| 376 // Fill if we have an exact match for the username. Note that this sets | |
| 377 // username to autofilled. | |
| 378 return FillUserNameAndPassword(&username_element, | |
| 379 &password_element, | |
| 380 fill_data, | |
| 381 true /* exact_username_match */, | |
| 382 false /* set_selection */, | |
| 383 usernames_usage); | |
| 384 } | |
| 385 | |
| 221 } // namespace | 386 } // namespace |
| 222 | 387 |
| 223 //////////////////////////////////////////////////////////////////////////////// | 388 //////////////////////////////////////////////////////////////////////////////// |
| 224 // PasswordAutofillAgent, public: | 389 // PasswordAutofillAgent, public: |
| 225 | 390 |
| 226 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 391 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
| 227 : content::RenderViewObserver(render_view), | 392 : content::RenderViewObserver(render_view), |
| 228 usernames_usage_(NOTHING_TO_AUTOFILL), | 393 usernames_usage_(NOTHING_TO_AUTOFILL), |
| 229 web_view_(render_view->GetWebView()), | 394 web_view_(render_view->GetWebView()), |
| 230 logging_state_active_(false), | 395 logging_state_active_(false), |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 return false; | 461 return false; |
| 297 | 462 |
| 298 blink::WebInputElement password = password_info.password_field; | 463 blink::WebInputElement password = password_info.password_field; |
| 299 if (!IsElementEditable(password)) | 464 if (!IsElementEditable(password)) |
| 300 return false; | 465 return false; |
| 301 | 466 |
| 302 blink::WebInputElement username = element; // We need a non-const. | 467 blink::WebInputElement username = element; // We need a non-const. |
| 303 | 468 |
| 304 // Do not set selection when ending an editing session, otherwise it can | 469 // Do not set selection when ending an editing session, otherwise it can |
| 305 // mess with focus. | 470 // mess with focus. |
| 306 FillUserNameAndPassword(&username, | 471 bool gate_keeper = FillUserNameAndPassword(&username, |
|
vabr (Chromium)
2014/09/26 10:06:48
(The following is made obsolete by my other commen
| |
| 307 &password, | 472 &password, |
| 308 fill_data, | 473 fill_data, |
| 309 true /* exact_username_match */, | 474 true /* exact_username_match */, |
| 310 false /* set_selection */); | 475 false /* set_selection */, |
| 476 &usernames_usage_); | |
| 477 if (gate_keeper) | |
| 478 gatekeeper_.RegisterElement(&password); | |
| 479 | |
| 311 return true; | 480 return true; |
| 312 } | 481 } |
| 313 | 482 |
| 314 bool PasswordAutofillAgent::TextDidChangeInTextField( | 483 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 315 const blink::WebInputElement& element) { | 484 const blink::WebInputElement& element) { |
| 316 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 485 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
| 317 blink::WebInputElement mutable_element = element; // We need a non-const. | 486 blink::WebInputElement mutable_element = element; // We need a non-const. |
| 318 | 487 |
| 319 if (element.isPasswordField()) { | 488 if (element.isPasswordField()) { |
| 320 // Some login forms have event handlers that put a hash of the password into | 489 // 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 = | 975 blink::WebInputElement username_element = |
| 807 form_elements->input_elements[form_data.basic_data.fields[0].name]; | 976 form_elements->input_elements[form_data.basic_data.fields[0].name]; |
| 808 | 977 |
| 809 // Get pointer to password element. (We currently only support single | 978 // Get pointer to password element. (We currently only support single |
| 810 // password forms). | 979 // password forms). |
| 811 blink::WebInputElement password_element = | 980 blink::WebInputElement password_element = |
| 812 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 981 form_elements->input_elements[form_data.basic_data.fields[1].name]; |
| 813 | 982 |
| 814 // If wait_for_username is true, we don't want to initially fill the form | 983 // If wait_for_username is true, we don't want to initially fill the form |
| 815 // until the user types in a valid username. | 984 // until the user types in a valid username. |
| 816 if (!form_data.wait_for_username) | 985 if (!form_data.wait_for_username) { |
| 817 FillFormOnPasswordRecieved(form_data, username_element, password_element); | 986 bool gate_keeper = FillFormOnPasswordRecieved( |
| 987 form_data, username_element, password_element, &usernames_usage_); | |
| 988 if (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; |
| 901 GetSuggestions( | 1038 GetSuggestions(fill_data, |
| 902 fill_data, user_input.value(), &suggestions, &realms, show_all); | 1039 user_input.value(), |
| 1040 &suggestions, | |
| 1041 &realms, | |
| 1042 show_all, | |
| 1043 &usernames_usage_); | |
| 903 DCHECK_EQ(suggestions.size(), realms.size()); | 1044 DCHECK_EQ(suggestions.size(), realms.size()); |
| 904 | 1045 |
| 905 FormData form; | 1046 FormData form; |
| 906 FormFieldData field; | 1047 FormFieldData field; |
| 907 FindFormAndFieldForFormControlElement( | 1048 FindFormAndFieldForFormControlElement( |
| 908 user_input, &form, &field, REQUIRE_NONE); | 1049 user_input, &form, &field, REQUIRE_NONE); |
| 909 | 1050 |
| 910 blink::WebInputElement selected_element = user_input; | 1051 blink::WebInputElement selected_element = user_input; |
| 911 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1052 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
| 912 | 1053 |
| 913 float scale = web_view_->pageScaleFactor(); | 1054 float scale = web_view_->pageScaleFactor(); |
| 914 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1055 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
| 915 bounding_box.y() * scale, | 1056 bounding_box.y() * scale, |
| 916 bounding_box.width() * scale, | 1057 bounding_box.width() * scale, |
| 917 bounding_box.height() * scale); | 1058 bounding_box.height() * scale); |
| 918 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1059 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
| 919 routing_id(), field, bounding_box_scaled, suggestions, realms)); | 1060 routing_id(), field, bounding_box_scaled, suggestions, realms)); |
| 920 return !suggestions.empty(); | 1061 return !suggestions.empty(); |
| 921 } | 1062 } |
| 922 | 1063 |
| 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( | 1064 void PasswordAutofillAgent::PerformInlineAutocomplete( |
| 1044 const blink::WebInputElement& username_input, | 1065 const blink::WebInputElement& username_input, |
| 1045 const blink::WebInputElement& password_input, | 1066 const blink::WebInputElement& password_input, |
| 1046 const PasswordFormFillData& fill_data) { | 1067 const PasswordFormFillData& fill_data) { |
| 1047 DCHECK(!fill_data.wait_for_username); | 1068 DCHECK(!fill_data.wait_for_username); |
| 1048 | 1069 |
| 1049 // We need non-const versions of the username and password inputs. | 1070 // We need non-const versions of the username and password inputs. |
| 1050 blink::WebInputElement username = username_input; | 1071 blink::WebInputElement username = username_input; |
| 1051 blink::WebInputElement password = password_input; | 1072 blink::WebInputElement password = password_input; |
| 1052 | 1073 |
| 1053 // Don't inline autocomplete if the caret is not at the end. | 1074 // 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? | 1075 // TODO(jcivelli): is there a better way to test the caret location? |
| 1055 if (username.selectionStart() != username.selectionEnd() || | 1076 if (username.selectionStart() != username.selectionEnd() || |
| 1056 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1077 username.selectionEnd() != static_cast<int>(username.value().length())) { |
| 1057 return; | 1078 return; |
| 1058 } | 1079 } |
| 1059 | 1080 |
| 1060 // Show the popup with the list of available usernames. | 1081 // Show the popup with the list of available usernames. |
| 1061 ShowSuggestionPopup(fill_data, username, false); | 1082 ShowSuggestionPopup(fill_data, username, false); |
| 1062 | 1083 |
| 1063 #if !defined(OS_ANDROID) | 1084 #if !defined(OS_ANDROID) |
| 1064 // Fill the user and password field with the most relevant match. Android | 1085 // 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. | 1086 // only fills in the fields after the user clicks on the suggestion popup. |
| 1066 FillUserNameAndPassword(&username, | 1087 bool gate_keeper = FillUserNameAndPassword(&username, |
| 1067 &password, | 1088 &password, |
| 1068 fill_data, | 1089 fill_data, |
| 1069 false /* exact_username_match */, | 1090 false /* exact_username_match */, |
| 1070 true /* set_selection */); | 1091 true /* set_selection */, |
| 1092 &usernames_usage_); | |
| 1093 if (gate_keeper) | |
| 1094 gatekeeper_.RegisterElement(&password); | |
| 1071 #endif | 1095 #endif |
| 1072 } | 1096 } |
| 1073 | 1097 |
| 1074 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1098 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 1075 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1099 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 1076 iter != login_to_password_info_.end();) { | 1100 iter != login_to_password_info_.end();) { |
| 1077 if (iter->first.document().frame() == frame) { | 1101 if (iter->first.document().frame() == frame) { |
| 1078 password_to_username_.erase(iter->second.password_field); | 1102 password_to_username_.erase(iter->second.password_field); |
| 1079 login_to_password_info_.erase(iter++); | 1103 login_to_password_info_.erase(iter++); |
| 1080 } else { | 1104 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1158 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
| 1135 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1159 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
| 1136 password_form->password_value.empty() && | 1160 password_form->password_value.empty() && |
| 1137 password_form->new_password_value.empty())) { | 1161 password_form->new_password_value.empty())) { |
| 1138 return; | 1162 return; |
| 1139 } | 1163 } |
| 1140 provisionally_saved_forms_[frame].reset(password_form.release()); | 1164 provisionally_saved_forms_[frame].reset(password_form.release()); |
| 1141 } | 1165 } |
| 1142 | 1166 |
| 1143 } // namespace autofill | 1167 } // namespace autofill |
| OLD | NEW |