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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 const blink::WebFormElement& form) { | 218 const blink::WebFormElement& form) { |
219 logger->LogHTMLForm(message_id, | 219 logger->LogHTMLForm(message_id, |
220 form.name().utf8(), | 220 form.name().utf8(), |
221 GURL(form.action().utf8())); | 221 GURL(form.action().utf8())); |
222 } | 222 } |
223 | 223 |
224 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { | 224 bool FillDataContainsUsername(const PasswordFormFillData& fill_data) { |
225 return !fill_data.basic_data.fields[0].name.empty(); | 225 return !fill_data.basic_data.fields[0].name.empty(); |
226 } | 226 } |
227 | 227 |
228 // This function attempts to fill |suggestions| and |realms| form |fill_data| | |
229 // based on |input| that is current_username. Returns true when |suggestions| | |
vabr (Chromium)
2014/09/30 13:54:53
I don't think you addressed the issue with |curren
Deepak
2014/09/30 14:19:48
Done.
| |
230 // gets filled from |fill_data.other_possible_usernames|, else returns false. | |
231 bool GetSuggestions(const PasswordFormFillData& fill_data, | |
232 const base::string16& input, | |
233 std::vector<base::string16>* suggestions, | |
234 std::vector<base::string16>* realms, | |
235 bool show_all) { | |
236 bool usernames_shown = false; | |
237 if (show_all || | |
238 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | |
239 suggestions->push_back(fill_data.basic_data.fields[0].value); | |
240 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | |
241 } | |
242 | |
243 for (PasswordFormFillData::LoginCollection::const_iterator iter = | |
244 fill_data.additional_logins.begin(); | |
245 iter != fill_data.additional_logins.end(); | |
246 ++iter) { | |
247 if (show_all || StartsWith(iter->first, input, false)) { | |
248 suggestions->push_back(iter->first); | |
249 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | |
250 } | |
251 } | |
252 | |
253 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
254 fill_data.other_possible_usernames.begin(); | |
255 iter != fill_data.other_possible_usernames.end(); | |
256 ++iter) { | |
257 for (size_t i = 0; i < iter->second.size(); ++i) { | |
258 if (show_all || StartsWith(iter->second[i], input, false)) { | |
259 usernames_shown = true; | |
260 suggestions->push_back(iter->second[i]); | |
261 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | |
262 } | |
263 } | |
264 } | |
265 return usernames_shown; | |
266 } | |
267 | |
268 // This function attempts to fill |username_element| and |password_element| | |
269 // with values from |fill_data|. The |password_element| will only have the | |
270 // |suggestedValue| set, and will be registered for copying that to the real | |
271 // value through |registration_callback|. The function returns true when | |
272 // selected username comes from |fill_data.other_possible_usernames|. | |
273 bool FillUserNameAndPassword( | |
274 blink::WebInputElement* username_element, | |
275 blink::WebInputElement* password_element, | |
276 const PasswordFormFillData& fill_data, | |
277 bool exact_username_match, | |
278 bool set_selection, | |
279 base::Callback<void(blink::WebInputElement*)> registration_callback) { | |
280 bool possible_username_selected = false; | |
281 // Don't fill username if password can't be set. | |
282 if (!IsElementAutocompletable(*password_element)) | |
283 return false; | |
284 | |
285 base::string16 current_username; | |
286 if (!username_element->isNull()) { | |
287 current_username = username_element->value(); | |
288 } | |
289 | |
290 // username and password will contain the match found if any. | |
291 base::string16 username; | |
292 base::string16 password; | |
293 | |
294 // Look for any suitable matches to current field text. | |
295 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | |
296 current_username, | |
297 exact_username_match)) { | |
298 username = fill_data.basic_data.fields[0].value; | |
299 password = fill_data.basic_data.fields[1].value; | |
300 } else { | |
301 // Scan additional logins for a match. | |
302 PasswordFormFillData::LoginCollection::const_iterator iter; | |
303 for (iter = fill_data.additional_logins.begin(); | |
304 iter != fill_data.additional_logins.end(); | |
305 ++iter) { | |
306 if (DoUsernamesMatch( | |
307 iter->first, current_username, exact_username_match)) { | |
308 username = iter->first; | |
309 password = iter->second.password; | |
310 break; | |
311 } | |
312 } | |
313 | |
314 // Check possible usernames. | |
315 if (username.empty() && password.empty()) { | |
316 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
317 fill_data.other_possible_usernames.begin(); | |
318 iter != fill_data.other_possible_usernames.end(); | |
319 ++iter) { | |
320 for (size_t i = 0; i < iter->second.size(); ++i) { | |
321 if (DoUsernamesMatch( | |
322 iter->second[i], current_username, exact_username_match)) { | |
323 possible_username_selected = true; | |
324 username = iter->second[i]; | |
325 password = iter->first.password; | |
326 break; | |
327 } | |
328 } | |
329 if (!username.empty() && !password.empty()) | |
330 break; | |
331 } | |
332 } | |
333 } | |
334 if (password.empty()) | |
335 return possible_username_selected; // No match was found. | |
336 | |
337 // TODO(tkent): Check maxlength and pattern for both username and password | |
338 // fields. | |
339 | |
340 // Input matches the username, fill in required values. | |
341 if (!username_element->isNull() && | |
342 IsElementAutocompletable(*username_element)) { | |
343 username_element->setValue(username, true); | |
344 username_element->setAutofilled(true); | |
345 | |
346 if (set_selection) { | |
347 username_element->setSelectionRange(current_username.length(), | |
348 username.length()); | |
349 } | |
350 } else if (current_username != username) { | |
351 // If the username can't be filled and it doesn't match a saved password | |
352 // as is, don't autofill a password. | |
353 return possible_username_selected; | |
354 } | |
355 | |
356 // Wait to fill in the password until a user gesture occurs. This is to make | |
357 // sure that we do not fill in the DOM with a password until we believe the | |
358 // user is intentionally interacting with the page. | |
359 password_element->setSuggestedValue(password); | |
360 registration_callback.Run(password_element); | |
361 | |
362 password_element->setAutofilled(true); | |
363 return possible_username_selected; | |
364 } | |
365 | |
366 // Attempts to fill |username_element| and |password_element| with the | |
367 // |fill_data|. Will use the data corresponding to the preferred username, | |
368 // unless the |username_element| already has a value set. In that case, | |
369 // attempts to fill the password matching the already filled username, if | |
370 // such a password exists. The |password_element| will have the | |
371 // |suggestedValue| set, and |suggestedValue| will be registered for copying to | |
372 // the real value through |registration_callback|. Returns true when the | |
373 // username gets selected from |other_possible_usernames|, else returns false. | |
374 bool FillFormOnPasswordRecieved( | |
375 const PasswordFormFillData& fill_data, | |
376 blink::WebInputElement username_element, | |
377 blink::WebInputElement password_element, | |
378 base::Callback<void(blink::WebInputElement*)> registration_callback) { | |
379 // Do not fill if the password field is in an iframe. | |
380 DCHECK(password_element.document().frame()); | |
381 if (password_element.document().frame()->parent()) | |
382 return false; | |
383 | |
384 bool form_contains_username_field = FillDataContainsUsername(fill_data); | |
385 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
386 form_contains_username_field && !username_element.form().autoComplete()) | |
387 return false; | |
388 | |
389 // If we can't modify the password, don't try to set the username | |
390 if (!IsElementAutocompletable(password_element)) | |
391 return false; | |
392 | |
393 // Try to set the username to the preferred name, but only if the field | |
394 // can be set and isn't prefilled. | |
395 if (form_contains_username_field && | |
396 IsElementAutocompletable(username_element) && | |
397 username_element.value().isEmpty()) { | |
398 // TODO(tkent): Check maxlength and pattern. | |
399 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
400 } | |
401 | |
402 // Fill if we have an exact match for the username. Note that this sets | |
403 // username to autofilled. | |
404 return FillUserNameAndPassword(&username_element, | |
405 &password_element, | |
406 fill_data, | |
407 true /* exact_username_match */, | |
408 false /* set_selection */, | |
409 registration_callback); | |
410 } | |
411 | |
228 } // namespace | 412 } // namespace |
229 | 413 |
230 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
231 // PasswordAutofillAgent, public: | 415 // PasswordAutofillAgent, public: |
232 | 416 |
233 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 417 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
234 : content::RenderViewObserver(render_view), | 418 : content::RenderViewObserver(render_view), |
235 usernames_usage_(NOTHING_TO_AUTOFILL), | 419 usernames_usage_(NOTHING_TO_AUTOFILL), |
236 web_view_(render_view->GetWebView()), | 420 web_view_(render_view->GetWebView()), |
237 logging_state_active_(false), | 421 logging_state_active_(false), |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 return false; | 487 return false; |
304 | 488 |
305 blink::WebInputElement password = password_info.password_field; | 489 blink::WebInputElement password = password_info.password_field; |
306 if (!IsElementEditable(password)) | 490 if (!IsElementEditable(password)) |
307 return false; | 491 return false; |
308 | 492 |
309 blink::WebInputElement username = element; // We need a non-const. | 493 blink::WebInputElement username = element; // We need a non-const. |
310 | 494 |
311 // Do not set selection when ending an editing session, otherwise it can | 495 // Do not set selection when ending an editing session, otherwise it can |
312 // mess with focus. | 496 // mess with focus. |
313 FillUserNameAndPassword(&username, | 497 if (FillUserNameAndPassword( |
314 &password, | 498 &username, |
315 fill_data, | 499 &password, |
316 true /* exact_username_match */, | 500 fill_data, |
317 false /* set_selection */); | 501 true /* exact_username_match */, |
502 false /* set_selection */, | |
503 base::Bind(&PasswordValueGatekeeper::RegisterElement, | |
504 base::Unretained(&gatekeeper_)))) { | |
505 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
506 } | |
318 return true; | 507 return true; |
319 } | 508 } |
320 | 509 |
321 bool PasswordAutofillAgent::TextDidChangeInTextField( | 510 bool PasswordAutofillAgent::TextDidChangeInTextField( |
322 const blink::WebInputElement& element) { | 511 const blink::WebInputElement& element) { |
323 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 512 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
324 blink::WebInputElement mutable_element = element; // We need a non-const. | 513 blink::WebInputElement mutable_element = element; // We need a non-const. |
325 | 514 |
326 if (element.isPasswordField()) { | 515 if (element.isPasswordField()) { |
327 // Some login forms have event handlers that put a hash of the password into | 516 // Some login forms have event handlers that put a hash of the password into |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
822 if (form_data.basic_data.fields[1].name.empty()) | 1011 if (form_data.basic_data.fields[1].name.empty()) |
823 break; | 1012 break; |
824 | 1013 |
825 // Get pointer to password element. (We currently only support single | 1014 // Get pointer to password element. (We currently only support single |
826 // password forms). | 1015 // password forms). |
827 password_element = | 1016 password_element = |
828 form_elements->input_elements[form_data.basic_data.fields[1].name]; | 1017 form_elements->input_elements[form_data.basic_data.fields[1].name]; |
829 | 1018 |
830 // If wait_for_username is true, we don't want to initially fill the form | 1019 // If wait_for_username is true, we don't want to initially fill the form |
831 // until the user types in a valid username. | 1020 // until the user types in a valid username. |
832 if (!form_data.wait_for_username) | 1021 if (!form_data.wait_for_username && |
833 FillFormOnPasswordRecieved(form_data, username_element, password_element); | 1022 FillFormOnPasswordRecieved( |
834 | 1023 form_data, |
1024 username_element, | |
1025 password_element, | |
1026 base::Bind(&PasswordValueGatekeeper::RegisterElement, | |
1027 base::Unretained(&gatekeeper_)))) { | |
1028 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
1029 } | |
835 // We might have already filled this form if there are two <form> elements | 1030 // We might have already filled this form if there are two <form> elements |
836 // with identical markup. | 1031 // with identical markup. |
837 if (login_to_password_info_.find(username_element) != | 1032 if (login_to_password_info_.find(username_element) != |
838 login_to_password_info_.end()) | 1033 login_to_password_info_.end()) |
839 continue; | 1034 continue; |
840 | 1035 |
841 PasswordInfo password_info; | 1036 PasswordInfo password_info; |
842 password_info.fill_data = form_data; | 1037 password_info.fill_data = form_data; |
843 password_info.password_field = password_element; | 1038 password_info.password_field = password_element; |
844 login_to_password_info_[username_element] = password_info; | 1039 login_to_password_info_[username_element] = password_info; |
(...skipping 15 matching lines...) Expand all Loading... | |
860 logging_state_active_ = active; | 1055 logging_state_active_ = active; |
861 } | 1056 } |
862 | 1057 |
863 //////////////////////////////////////////////////////////////////////////////// | 1058 //////////////////////////////////////////////////////////////////////////////// |
864 // PasswordAutofillAgent, private: | 1059 // PasswordAutofillAgent, private: |
865 | 1060 |
866 PasswordAutofillAgent::PasswordInfo::PasswordInfo() | 1061 PasswordAutofillAgent::PasswordInfo::PasswordInfo() |
867 : backspace_pressed_last(false), password_was_edited_last(false) { | 1062 : backspace_pressed_last(false), password_was_edited_last(false) { |
868 } | 1063 } |
869 | 1064 |
870 void PasswordAutofillAgent::GetSuggestions( | |
871 const PasswordFormFillData& fill_data, | |
872 const base::string16& input, | |
873 std::vector<base::string16>* suggestions, | |
874 std::vector<base::string16>* realms, | |
875 bool show_all) { | |
876 if (show_all || | |
877 StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | |
878 suggestions->push_back(fill_data.basic_data.fields[0].value); | |
879 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | |
880 } | |
881 | |
882 for (PasswordFormFillData::LoginCollection::const_iterator iter = | |
883 fill_data.additional_logins.begin(); | |
884 iter != fill_data.additional_logins.end(); | |
885 ++iter) { | |
886 if (show_all || StartsWith(iter->first, input, false)) { | |
887 suggestions->push_back(iter->first); | |
888 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | |
889 } | |
890 } | |
891 | |
892 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
893 fill_data.other_possible_usernames.begin(); | |
894 iter != fill_data.other_possible_usernames.end(); | |
895 ++iter) { | |
896 for (size_t i = 0; i < iter->second.size(); ++i) { | |
897 if (show_all || StartsWith(iter->second[i], input, false)) { | |
898 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | |
899 suggestions->push_back(iter->second[i]); | |
900 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | |
901 } | |
902 } | |
903 } | |
904 } | |
905 | |
906 bool PasswordAutofillAgent::ShowSuggestionPopup( | 1065 bool PasswordAutofillAgent::ShowSuggestionPopup( |
907 const PasswordFormFillData& fill_data, | 1066 const PasswordFormFillData& fill_data, |
908 const blink::WebInputElement& user_input, | 1067 const blink::WebInputElement& user_input, |
909 bool show_all) { | 1068 bool show_all) { |
910 blink::WebFrame* frame = user_input.document().frame(); | 1069 blink::WebFrame* frame = user_input.document().frame(); |
911 if (!frame) | 1070 if (!frame) |
912 return false; | 1071 return false; |
913 | 1072 |
914 blink::WebView* webview = frame->view(); | 1073 blink::WebView* webview = frame->view(); |
915 if (!webview) | 1074 if (!webview) |
916 return false; | 1075 return false; |
917 | 1076 |
918 std::vector<base::string16> suggestions; | 1077 std::vector<base::string16> suggestions; |
919 std::vector<base::string16> realms; | 1078 std::vector<base::string16> realms; |
920 GetSuggestions( | 1079 if (GetSuggestions( |
921 fill_data, user_input.value(), &suggestions, &realms, show_all); | 1080 fill_data, user_input.value(), &suggestions, &realms, show_all)) { |
1081 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | |
1082 } | |
1083 | |
922 DCHECK_EQ(suggestions.size(), realms.size()); | 1084 DCHECK_EQ(suggestions.size(), realms.size()); |
923 | 1085 |
924 FormData form; | 1086 FormData form; |
925 FormFieldData field; | 1087 FormFieldData field; |
926 FindFormAndFieldForFormControlElement( | 1088 FindFormAndFieldForFormControlElement( |
927 user_input, &form, &field, REQUIRE_NONE); | 1089 user_input, &form, &field, REQUIRE_NONE); |
928 | 1090 |
929 blink::WebInputElement selected_element = user_input; | 1091 blink::WebInputElement selected_element = user_input; |
930 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1092 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
931 | 1093 |
932 float scale = web_view_->pageScaleFactor(); | 1094 float scale = web_view_->pageScaleFactor(); |
933 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1095 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
934 bounding_box.y() * scale, | 1096 bounding_box.y() * scale, |
935 bounding_box.width() * scale, | 1097 bounding_box.width() * scale, |
936 bounding_box.height() * scale); | 1098 bounding_box.height() * scale); |
937 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1099 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
938 routing_id(), field, bounding_box_scaled, suggestions, realms)); | 1100 routing_id(), field, bounding_box_scaled, suggestions, realms)); |
939 return !suggestions.empty(); | 1101 return !suggestions.empty(); |
940 } | 1102 } |
941 | 1103 |
942 void PasswordAutofillAgent::FillFormOnPasswordRecieved( | |
943 const PasswordFormFillData& fill_data, | |
944 blink::WebInputElement username_element, | |
945 blink::WebInputElement password_element) { | |
946 // Do not fill if the password field is in an iframe. | |
947 DCHECK(password_element.document().frame()); | |
948 if (password_element.document().frame()->parent()) | |
949 return; | |
950 | |
951 bool form_contains_username_field = FillDataContainsUsername(fill_data); | |
952 if (!ShouldIgnoreAutocompleteOffForPasswordFields() && | |
953 form_contains_username_field && !username_element.form().autoComplete()) | |
954 return; | |
955 | |
956 // If we can't modify the password, don't try to set the username | |
957 if (!IsElementAutocompletable(password_element)) | |
958 return; | |
959 | |
960 // Try to set the username to the preferred name, but only if the field | |
961 // can be set and isn't prefilled. | |
962 if (form_contains_username_field && | |
963 IsElementAutocompletable(username_element) && | |
964 username_element.value().isEmpty()) { | |
965 // TODO(tkent): Check maxlength and pattern. | |
966 username_element.setValue(fill_data.basic_data.fields[0].value, true); | |
967 } | |
968 | |
969 // Fill if we have an exact match for the username. Note that this sets | |
970 // username to autofilled. | |
971 FillUserNameAndPassword(&username_element, | |
972 &password_element, | |
973 fill_data, | |
974 true /* exact_username_match */, | |
975 false /* set_selection */); | |
976 } | |
977 | |
978 bool PasswordAutofillAgent::FillUserNameAndPassword( | |
979 blink::WebInputElement* username_element, | |
980 blink::WebInputElement* password_element, | |
981 const PasswordFormFillData& fill_data, | |
982 bool exact_username_match, | |
983 bool set_selection) { | |
984 // Don't fill username if password can't be set. | |
985 if (!IsElementAutocompletable(*password_element)) | |
986 return false; | |
987 | |
988 base::string16 current_username; | |
989 if (!username_element->isNull()) { | |
990 current_username = username_element->value(); | |
991 } | |
992 | |
993 // username and password will contain the match found if any. | |
994 base::string16 username; | |
995 base::string16 password; | |
996 | |
997 // Look for any suitable matches to current field text. | |
998 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, | |
999 current_username, | |
1000 exact_username_match)) { | |
1001 username = fill_data.basic_data.fields[0].value; | |
1002 password = fill_data.basic_data.fields[1].value; | |
1003 } else { | |
1004 // Scan additional logins for a match. | |
1005 PasswordFormFillData::LoginCollection::const_iterator iter; | |
1006 for (iter = fill_data.additional_logins.begin(); | |
1007 iter != fill_data.additional_logins.end(); | |
1008 ++iter) { | |
1009 if (DoUsernamesMatch( | |
1010 iter->first, current_username, exact_username_match)) { | |
1011 username = iter->first; | |
1012 password = iter->second.password; | |
1013 break; | |
1014 } | |
1015 } | |
1016 | |
1017 // Check possible usernames. | |
1018 if (username.empty() && password.empty()) { | |
1019 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | |
1020 fill_data.other_possible_usernames.begin(); | |
1021 iter != fill_data.other_possible_usernames.end(); | |
1022 ++iter) { | |
1023 for (size_t i = 0; i < iter->second.size(); ++i) { | |
1024 if (DoUsernamesMatch( | |
1025 iter->second[i], current_username, exact_username_match)) { | |
1026 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
1027 username = iter->second[i]; | |
1028 password = iter->first.password; | |
1029 break; | |
1030 } | |
1031 } | |
1032 if (!username.empty() && !password.empty()) | |
1033 break; | |
1034 } | |
1035 } | |
1036 } | |
1037 if (password.empty()) | |
1038 return false; // No match was found. | |
1039 | |
1040 // TODO(tkent): Check maxlength and pattern for both username and password | |
1041 // fields. | |
1042 | |
1043 // Input matches the username, fill in required values. | |
1044 if (!username_element->isNull() && | |
1045 IsElementAutocompletable(*username_element)) { | |
1046 username_element->setValue(username, true); | |
1047 username_element->setAutofilled(true); | |
1048 | |
1049 if (set_selection) { | |
1050 username_element->setSelectionRange(current_username.length(), | |
1051 username.length()); | |
1052 } | |
1053 } else if (current_username != username) { | |
1054 // If the username can't be filled and it doesn't match a saved password | |
1055 // as is, don't autofill a password. | |
1056 return false; | |
1057 } | |
1058 | |
1059 // Wait to fill in the password until a user gesture occurs. This is to make | |
1060 // sure that we do not fill in the DOM with a password until we believe the | |
1061 // user is intentionally interacting with the page. | |
1062 password_element->setSuggestedValue(password); | |
1063 gatekeeper_.RegisterElement(password_element); | |
1064 | |
1065 password_element->setAutofilled(true); | |
1066 return true; | |
1067 } | |
1068 | |
1069 void PasswordAutofillAgent::PerformInlineAutocomplete( | 1104 void PasswordAutofillAgent::PerformInlineAutocomplete( |
1070 const blink::WebInputElement& username_input, | 1105 const blink::WebInputElement& username_input, |
1071 const blink::WebInputElement& password_input, | 1106 const blink::WebInputElement& password_input, |
1072 const PasswordFormFillData& fill_data) { | 1107 const PasswordFormFillData& fill_data) { |
1073 DCHECK(!fill_data.wait_for_username); | 1108 DCHECK(!fill_data.wait_for_username); |
1074 | 1109 |
1075 // We need non-const versions of the username and password inputs. | 1110 // We need non-const versions of the username and password inputs. |
1076 blink::WebInputElement username = username_input; | 1111 blink::WebInputElement username = username_input; |
1077 blink::WebInputElement password = password_input; | 1112 blink::WebInputElement password = password_input; |
1078 | 1113 |
1079 // Don't inline autocomplete if the caret is not at the end. | 1114 // Don't inline autocomplete if the caret is not at the end. |
1080 // TODO(jcivelli): is there a better way to test the caret location? | 1115 // TODO(jcivelli): is there a better way to test the caret location? |
1081 if (username.selectionStart() != username.selectionEnd() || | 1116 if (username.selectionStart() != username.selectionEnd() || |
1082 username.selectionEnd() != static_cast<int>(username.value().length())) { | 1117 username.selectionEnd() != static_cast<int>(username.value().length())) { |
1083 return; | 1118 return; |
1084 } | 1119 } |
1085 | 1120 |
1086 // Show the popup with the list of available usernames. | 1121 // Show the popup with the list of available usernames. |
1087 ShowSuggestionPopup(fill_data, username, false); | 1122 ShowSuggestionPopup(fill_data, username, false); |
1088 | 1123 |
1089 #if !defined(OS_ANDROID) | 1124 #if !defined(OS_ANDROID) |
1090 // Fill the user and password field with the most relevant match. Android | 1125 // Fill the user and password field with the most relevant match. Android |
1091 // only fills in the fields after the user clicks on the suggestion popup. | 1126 // only fills in the fields after the user clicks on the suggestion popup. |
1092 FillUserNameAndPassword(&username, | 1127 if (FillUserNameAndPassword( |
1093 &password, | 1128 &username, |
1094 fill_data, | 1129 &password, |
1095 false /* exact_username_match */, | 1130 fill_data, |
1096 true /* set_selection */); | 1131 false /* exact_username_match */, |
1132 true /* set_selection */, | |
1133 base::Bind(&PasswordValueGatekeeper::RegisterElement, | |
1134 base::Unretained(&gatekeeper_)))) { | |
1135 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | |
1136 } | |
1097 #endif | 1137 #endif |
1098 } | 1138 } |
1099 | 1139 |
1100 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1140 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
1101 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1141 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
1102 iter != login_to_password_info_.end();) { | 1142 iter != login_to_password_info_.end();) { |
1103 // There may not be a username field, so get the frame from the password | 1143 // There may not be a username field, so get the frame from the password |
1104 // field. | 1144 // field. |
1105 if (iter->second.password_field.document().frame() == frame) { | 1145 if (iter->second.password_field.document().frame() == frame) { |
1106 password_to_username_.erase(iter->second.password_field); | 1146 password_to_username_.erase(iter->second.password_field); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1162 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1202 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1163 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1203 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1164 password_form->password_value.empty() && | 1204 password_form->password_value.empty() && |
1165 password_form->new_password_value.empty())) { | 1205 password_form->new_password_value.empty())) { |
1166 return; | 1206 return; |
1167 } | 1207 } |
1168 provisionally_saved_forms_[frame].reset(password_form.release()); | 1208 provisionally_saved_forms_[frame].reset(password_form.release()); |
1169 } | 1209 } |
1170 | 1210 |
1171 } // namespace autofill | 1211 } // namespace autofill |
OLD | NEW |