| 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 21 matching lines...) Expand all Loading... |
| 32 #include "third_party/WebKit/public/web/WebView.h" | 32 #include "third_party/WebKit/public/web/WebView.h" |
| 33 #include "ui/events/keycodes/keyboard_codes.h" | 33 #include "ui/events/keycodes/keyboard_codes.h" |
| 34 | 34 |
| 35 namespace autofill { | 35 namespace autofill { |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 // The size above which we stop triggering autocomplete. | 38 // The size above which we stop triggering autocomplete. |
| 39 static const size_t kMaximumTextSizeForAutocomplete = 1000; | 39 static const size_t kMaximumTextSizeForAutocomplete = 1000; |
| 40 | 40 |
| 41 // Maps element names to the actual elements to simplify form filling. | 41 // Maps element names to the actual elements to simplify form filling. |
| 42 typedef std::map<base::string16, blink::WebInputElement> | 42 typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap; |
| 43 FormInputElementMap; | |
| 44 | 43 |
| 45 // Utility struct for form lookup and autofill. When we parse the DOM to look up | 44 // Utility struct for form lookup and autofill. When we parse the DOM to look up |
| 46 // a form, in addition to action and origin URL's we have to compare all | 45 // a form, in addition to action and origin URL's we have to compare all |
| 47 // necessary form elements. To avoid having to look these up again when we want | 46 // necessary form elements. To avoid having to look these up again when we want |
| 48 // to fill the form, the FindFormElements function stores the pointers | 47 // to fill the form, the FindFormElements function stores the pointers |
| 49 // in a FormElements* result, referenced to ensure they are safe to use. | 48 // in a FormElements* result, referenced to ensure they are safe to use. |
| 50 struct FormElements { | 49 struct FormElements { |
| 51 blink::WebFormElement form_element; | 50 blink::WebFormElement form_element; |
| 52 FormInputElementMap input_elements; | 51 FormInputElementMap input_elements; |
| 53 }; | 52 }; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 //////////////////////////////////////////////////////////////////////////////// | 205 //////////////////////////////////////////////////////////////////////////////// |
| 207 // PasswordAutofillAgent, public: | 206 // PasswordAutofillAgent, public: |
| 208 | 207 |
| 209 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 208 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) |
| 210 : content::RenderViewObserver(render_view), | 209 : content::RenderViewObserver(render_view), |
| 211 usernames_usage_(NOTHING_TO_AUTOFILL), | 210 usernames_usage_(NOTHING_TO_AUTOFILL), |
| 212 web_view_(render_view->GetWebView()), | 211 web_view_(render_view->GetWebView()), |
| 213 weak_ptr_factory_(this) { | 212 weak_ptr_factory_(this) { |
| 214 } | 213 } |
| 215 | 214 |
| 216 PasswordAutofillAgent::~PasswordAutofillAgent() {} | 215 PasswordAutofillAgent::~PasswordAutofillAgent() { |
| 216 } |
| 217 | 217 |
| 218 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() | 218 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper() |
| 219 : was_user_gesture_seen_(false) {} | 219 : was_user_gesture_seen_(false) { |
| 220 } |
| 220 | 221 |
| 221 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {} | 222 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() { |
| 223 } |
| 222 | 224 |
| 223 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement( | 225 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement( |
| 224 blink::WebInputElement* element) { | 226 blink::WebInputElement* element) { |
| 225 if (was_user_gesture_seen_) | 227 if (was_user_gesture_seen_) |
| 226 ShowValue(element); | 228 ShowValue(element); |
| 227 else | 229 else |
| 228 elements_.push_back(*element); | 230 elements_.push_back(*element); |
| 229 } | 231 } |
| 230 | 232 |
| 231 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() { | 233 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 251 element->setValue(element->suggestedValue(), true); | 253 element->setValue(element->suggestedValue(), true); |
| 252 } | 254 } |
| 253 | 255 |
| 254 bool PasswordAutofillAgent::TextFieldDidEndEditing( | 256 bool PasswordAutofillAgent::TextFieldDidEndEditing( |
| 255 const blink::WebInputElement& element) { | 257 const blink::WebInputElement& element) { |
| 256 LoginToPasswordInfoMap::const_iterator iter = | 258 LoginToPasswordInfoMap::const_iterator iter = |
| 257 login_to_password_info_.find(element); | 259 login_to_password_info_.find(element); |
| 258 if (iter == login_to_password_info_.end()) | 260 if (iter == login_to_password_info_.end()) |
| 259 return false; | 261 return false; |
| 260 | 262 |
| 261 const PasswordFormFillData& fill_data = | 263 const PasswordFormFillData& fill_data = iter->second.fill_data; |
| 262 iter->second.fill_data; | |
| 263 | 264 |
| 264 // If wait_for_username is false, we should have filled when the text changed. | 265 // If wait_for_username is false, we should have filled when the text changed. |
| 265 if (!fill_data.wait_for_username) | 266 if (!fill_data.wait_for_username) |
| 266 return false; | 267 return false; |
| 267 | 268 |
| 268 blink::WebInputElement password = iter->second.password_field; | 269 blink::WebInputElement password = iter->second.password_field; |
| 269 if (!IsElementEditable(password)) | 270 if (!IsElementEditable(password)) |
| 270 return false; | 271 return false; |
| 271 | 272 |
| 272 blink::WebInputElement username = element; // We need a non-const. | 273 blink::WebInputElement username = element; // We need a non-const. |
| 273 | 274 |
| 274 // Do not set selection when ending an editing session, otherwise it can | 275 // Do not set selection when ending an editing session, otherwise it can |
| 275 // mess with focus. | 276 // mess with focus. |
| 276 FillUserNameAndPassword(&username, &password, fill_data, | 277 FillUserNameAndPassword(&username, |
| 278 &password, |
| 279 fill_data, |
| 277 true /* exact_username_match */, | 280 true /* exact_username_match */, |
| 278 false /* set_selection */); | 281 false /* set_selection */); |
| 279 return true; | 282 return true; |
| 280 } | 283 } |
| 281 | 284 |
| 282 bool PasswordAutofillAgent::TextDidChangeInTextField( | 285 bool PasswordAutofillAgent::TextDidChangeInTextField( |
| 283 const blink::WebInputElement& element) { | 286 const blink::WebInputElement& element) { |
| 284 LoginToPasswordInfoMap::const_iterator iter = | 287 LoginToPasswordInfoMap::const_iterator iter = |
| 285 login_to_password_info_.find(element); | 288 login_to_password_info_.find(element); |
| 286 if (iter == login_to_password_info_.end()) | 289 if (iter == login_to_password_info_.end()) |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message) | 458 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message) |
| 456 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm) | 459 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm) |
| 457 IPC_MESSAGE_UNHANDLED(handled = false) | 460 IPC_MESSAGE_UNHANDLED(handled = false) |
| 458 IPC_END_MESSAGE_MAP() | 461 IPC_END_MESSAGE_MAP() |
| 459 return handled; | 462 return handled; |
| 460 } | 463 } |
| 461 | 464 |
| 462 void PasswordAutofillAgent::DidStartLoading() { | 465 void PasswordAutofillAgent::DidStartLoading() { |
| 463 if (usernames_usage_ != NOTHING_TO_AUTOFILL) { | 466 if (usernames_usage_ != NOTHING_TO_AUTOFILL) { |
| 464 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage", | 467 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage", |
| 465 usernames_usage_, OTHER_POSSIBLE_USERNAMES_MAX); | 468 usernames_usage_, |
| 469 OTHER_POSSIBLE_USERNAMES_MAX); |
| 466 usernames_usage_ = NOTHING_TO_AUTOFILL; | 470 usernames_usage_ = NOTHING_TO_AUTOFILL; |
| 467 } | 471 } |
| 468 } | 472 } |
| 469 | 473 |
| 470 void PasswordAutofillAgent::DidFinishDocumentLoad(blink::WebLocalFrame* frame) { | 474 void PasswordAutofillAgent::DidFinishDocumentLoad(blink::WebLocalFrame* frame) { |
| 471 // The |frame| contents have been parsed, but not yet rendered. Let the | 475 // The |frame| contents have been parsed, but not yet rendered. Let the |
| 472 // PasswordManager know that forms are loaded, even though we can't yet tell | 476 // PasswordManager know that forms are loaded, even though we can't yet tell |
| 473 // whether they're visible. | 477 // whether they're visible. |
| 474 SendPasswordForms(frame, false); | 478 SendPasswordForms(frame, false); |
| 475 } | 479 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 // If the navigation is not triggered by a user gesture, e.g. by some ajax | 560 // If the navigation is not triggered by a user gesture, e.g. by some ajax |
| 557 // callback, then inherit the submitted password form from the previous | 561 // callback, then inherit the submitted password form from the previous |
| 558 // state. This fixes the no password save issue for ajax login, tracked in | 562 // state. This fixes the no password save issue for ajax login, tracked in |
| 559 // [http://crbug/43219]. Note that this still fails for sites that use | 563 // [http://crbug/43219]. Note that this still fails for sites that use |
| 560 // synchonous XHR as isProcessingUserGesture() will return true. | 564 // synchonous XHR as isProcessingUserGesture() will return true. |
| 561 blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame); | 565 blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame); |
| 562 if (!blink::WebUserGestureIndicator::isProcessingUserGesture()) { | 566 if (!blink::WebUserGestureIndicator::isProcessingUserGesture()) { |
| 563 // If onsubmit has been called, try and save that form. | 567 // If onsubmit has been called, try and save that form. |
| 564 if (provisionally_saved_forms_[form_frame].get()) { | 568 if (provisionally_saved_forms_[form_frame].get()) { |
| 565 Send(new AutofillHostMsg_PasswordFormSubmitted( | 569 Send(new AutofillHostMsg_PasswordFormSubmitted( |
| 566 routing_id(), | 570 routing_id(), *provisionally_saved_forms_[form_frame])); |
| 567 *provisionally_saved_forms_[form_frame])); | |
| 568 provisionally_saved_forms_.erase(form_frame); | 571 provisionally_saved_forms_.erase(form_frame); |
| 569 } else { | 572 } else { |
| 570 // Loop through the forms on the page looking for one that has been | 573 // Loop through the forms on the page looking for one that has been |
| 571 // filled out. If one exists, try and save the credentials. | 574 // filled out. If one exists, try and save the credentials. |
| 572 blink::WebVector<blink::WebFormElement> forms; | 575 blink::WebVector<blink::WebFormElement> forms; |
| 573 frame->document().forms(forms); | 576 frame->document().forms(forms); |
| 574 | 577 |
| 575 for (size_t i = 0; i < forms.size(); ++i) { | 578 for (size_t i = 0; i < forms.size(); ++i) { |
| 576 blink::WebFormElement form_element= forms[i]; | 579 blink::WebFormElement form_element = forms[i]; |
| 577 scoped_ptr<PasswordForm> password_form( | 580 scoped_ptr<PasswordForm> password_form( |
| 578 CreatePasswordForm(form_element)); | 581 CreatePasswordForm(form_element)); |
| 579 if (password_form.get() && | 582 if (password_form.get() && !password_form->username_value.empty() && |
| 580 !password_form->username_value.empty() && | |
| 581 !password_form->password_value.empty() && | 583 !password_form->password_value.empty() && |
| 582 !PasswordValueIsDefault(*password_form, form_element)) { | 584 !PasswordValueIsDefault(*password_form, form_element)) { |
| 583 Send(new AutofillHostMsg_PasswordFormSubmitted( | 585 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(), |
| 584 routing_id(), *password_form)); | 586 *password_form)); |
| 585 } | 587 } |
| 586 } | 588 } |
| 587 } | 589 } |
| 588 } | 590 } |
| 589 // Clear the whole map during main frame navigation. | 591 // Clear the whole map during main frame navigation. |
| 590 provisionally_saved_forms_.clear(); | 592 provisionally_saved_forms_.clear(); |
| 591 | 593 |
| 592 // This is a new navigation, so require a new user gesture before filling in | 594 // This is a new navigation, so require a new user gesture before filling in |
| 593 // passwords. | 595 // passwords. |
| 594 gatekeeper_.Reset(); | 596 gatekeeper_.Reset(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 PasswordInfo password_info; | 637 PasswordInfo password_info; |
| 636 password_info.fill_data = form_data; | 638 password_info.fill_data = form_data; |
| 637 password_info.password_field = password_element; | 639 password_info.password_field = password_element; |
| 638 login_to_password_info_[username_element] = password_info; | 640 login_to_password_info_[username_element] = password_info; |
| 639 | 641 |
| 640 FormData form; | 642 FormData form; |
| 641 FormFieldData field; | 643 FormFieldData field; |
| 642 FindFormAndFieldForFormControlElement( | 644 FindFormAndFieldForFormControlElement( |
| 643 username_element, &form, &field, REQUIRE_NONE); | 645 username_element, &form, &field, REQUIRE_NONE); |
| 644 Send(new AutofillHostMsg_AddPasswordFormMapping( | 646 Send(new AutofillHostMsg_AddPasswordFormMapping( |
| 645 routing_id(), | 647 routing_id(), field, form_data)); |
| 646 field, | |
| 647 form_data)); | |
| 648 } | 648 } |
| 649 } | 649 } |
| 650 | 650 |
| 651 //////////////////////////////////////////////////////////////////////////////// | 651 //////////////////////////////////////////////////////////////////////////////// |
| 652 // PasswordAutofillAgent, private: | 652 // PasswordAutofillAgent, private: |
| 653 | 653 |
| 654 void PasswordAutofillAgent::GetSuggestions( | 654 void PasswordAutofillAgent::GetSuggestions( |
| 655 const PasswordFormFillData& fill_data, | 655 const PasswordFormFillData& fill_data, |
| 656 const base::string16& input, | 656 const base::string16& input, |
| 657 std::vector<base::string16>* suggestions, | 657 std::vector<base::string16>* suggestions, |
| 658 std::vector<base::string16>* realms) { | 658 std::vector<base::string16>* realms) { |
| 659 if (StartsWith(fill_data.basic_data.fields[0].value, input, false)) { | 659 if (StartsWith(fill_data.basic_data.fields[0].value, input, false)) { |
| 660 suggestions->push_back(fill_data.basic_data.fields[0].value); | 660 suggestions->push_back(fill_data.basic_data.fields[0].value); |
| 661 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); | 661 realms->push_back(base::UTF8ToUTF16(fill_data.preferred_realm)); |
| 662 } | 662 } |
| 663 | 663 |
| 664 for (PasswordFormFillData::LoginCollection::const_iterator iter = | 664 for (PasswordFormFillData::LoginCollection::const_iterator iter = |
| 665 fill_data.additional_logins.begin(); | 665 fill_data.additional_logins.begin(); |
| 666 iter != fill_data.additional_logins.end(); ++iter) { | 666 iter != fill_data.additional_logins.end(); |
| 667 ++iter) { |
| 667 if (StartsWith(iter->first, input, false)) { | 668 if (StartsWith(iter->first, input, false)) { |
| 668 suggestions->push_back(iter->first); | 669 suggestions->push_back(iter->first); |
| 669 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); | 670 realms->push_back(base::UTF8ToUTF16(iter->second.realm)); |
| 670 } | 671 } |
| 671 } | 672 } |
| 672 | 673 |
| 673 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | 674 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = |
| 674 fill_data.other_possible_usernames.begin(); | 675 fill_data.other_possible_usernames.begin(); |
| 675 iter != fill_data.other_possible_usernames.end(); ++iter) { | 676 iter != fill_data.other_possible_usernames.end(); |
| 677 ++iter) { |
| 676 for (size_t i = 0; i < iter->second.size(); ++i) { | 678 for (size_t i = 0; i < iter->second.size(); ++i) { |
| 677 if (StartsWith(iter->second[i], input, false)) { | 679 if (StartsWith(iter->second[i], input, false)) { |
| 678 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; | 680 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SHOWN; |
| 679 suggestions->push_back(iter->second[i]); | 681 suggestions->push_back(iter->second[i]); |
| 680 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); | 682 realms->push_back(base::UTF8ToUTF16(iter->first.realm)); |
| 681 } | 683 } |
| 682 } | 684 } |
| 683 } | 685 } |
| 684 } | 686 } |
| 685 | 687 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 705 user_input, &form, &field, REQUIRE_NONE); | 707 user_input, &form, &field, REQUIRE_NONE); |
| 706 | 708 |
| 707 blink::WebInputElement selected_element = user_input; | 709 blink::WebInputElement selected_element = user_input; |
| 708 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 710 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
| 709 | 711 |
| 710 float scale = web_view_->pageScaleFactor(); | 712 float scale = web_view_->pageScaleFactor(); |
| 711 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 713 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
| 712 bounding_box.y() * scale, | 714 bounding_box.y() * scale, |
| 713 bounding_box.width() * scale, | 715 bounding_box.width() * scale, |
| 714 bounding_box.height() * scale); | 716 bounding_box.height() * scale); |
| 715 Send(new AutofillHostMsg_ShowPasswordSuggestions(routing_id(), | 717 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
| 716 field, | 718 routing_id(), field, bounding_box_scaled, suggestions, realms)); |
| 717 bounding_box_scaled, | |
| 718 suggestions, | |
| 719 realms)); | |
| 720 return !suggestions.empty(); | 719 return !suggestions.empty(); |
| 721 } | 720 } |
| 722 | 721 |
| 723 void PasswordAutofillAgent::FillFormOnPasswordRecieved( | 722 void PasswordAutofillAgent::FillFormOnPasswordRecieved( |
| 724 const PasswordFormFillData& fill_data, | 723 const PasswordFormFillData& fill_data, |
| 725 blink::WebInputElement username_element, | 724 blink::WebInputElement username_element, |
| 726 blink::WebInputElement password_element) { | 725 blink::WebInputElement password_element) { |
| 727 // Do not fill if the password field is in an iframe. | 726 // Do not fill if the password field is in an iframe. |
| 728 DCHECK(password_element.document().frame()); | 727 DCHECK(password_element.document().frame()); |
| 729 if (password_element.document().frame()->parent()) | 728 if (password_element.document().frame()->parent()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 740 // Try to set the username to the preferred name, but only if the field | 739 // Try to set the username to the preferred name, but only if the field |
| 741 // can be set and isn't prefilled. | 740 // can be set and isn't prefilled. |
| 742 if (IsElementAutocompletable(username_element) && | 741 if (IsElementAutocompletable(username_element) && |
| 743 username_element.value().isEmpty()) { | 742 username_element.value().isEmpty()) { |
| 744 // TODO(tkent): Check maxlength and pattern. | 743 // TODO(tkent): Check maxlength and pattern. |
| 745 username_element.setValue(fill_data.basic_data.fields[0].value, true); | 744 username_element.setValue(fill_data.basic_data.fields[0].value, true); |
| 746 } | 745 } |
| 747 | 746 |
| 748 // Fill if we have an exact match for the username. Note that this sets | 747 // Fill if we have an exact match for the username. Note that this sets |
| 749 // username to autofilled. | 748 // username to autofilled. |
| 750 FillUserNameAndPassword(&username_element, &password_element, fill_data, | 749 FillUserNameAndPassword(&username_element, |
| 750 &password_element, |
| 751 fill_data, |
| 751 true /* exact_username_match */, | 752 true /* exact_username_match */, |
| 752 false /* set_selection */); | 753 false /* set_selection */); |
| 753 } | 754 } |
| 754 | 755 |
| 755 bool PasswordAutofillAgent::FillUserNameAndPassword( | 756 bool PasswordAutofillAgent::FillUserNameAndPassword( |
| 756 blink::WebInputElement* username_element, | 757 blink::WebInputElement* username_element, |
| 757 blink::WebInputElement* password_element, | 758 blink::WebInputElement* password_element, |
| 758 const PasswordFormFillData& fill_data, | 759 const PasswordFormFillData& fill_data, |
| 759 bool exact_username_match, | 760 bool exact_username_match, |
| 760 bool set_selection) { | 761 bool set_selection) { |
| 761 base::string16 current_username = username_element->value(); | 762 base::string16 current_username = username_element->value(); |
| 762 // username and password will contain the match found if any. | 763 // username and password will contain the match found if any. |
| 763 base::string16 username; | 764 base::string16 username; |
| 764 base::string16 password; | 765 base::string16 password; |
| 765 | 766 |
| 766 // Look for any suitable matches to current field text. | 767 // Look for any suitable matches to current field text. |
| 767 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, current_username, | 768 if (DoUsernamesMatch(fill_data.basic_data.fields[0].value, |
| 769 current_username, |
| 768 exact_username_match)) { | 770 exact_username_match)) { |
| 769 username = fill_data.basic_data.fields[0].value; | 771 username = fill_data.basic_data.fields[0].value; |
| 770 password = fill_data.basic_data.fields[1].value; | 772 password = fill_data.basic_data.fields[1].value; |
| 771 } else { | 773 } else { |
| 772 // Scan additional logins for a match. | 774 // Scan additional logins for a match. |
| 773 PasswordFormFillData::LoginCollection::const_iterator iter; | 775 PasswordFormFillData::LoginCollection::const_iterator iter; |
| 774 for (iter = fill_data.additional_logins.begin(); | 776 for (iter = fill_data.additional_logins.begin(); |
| 775 iter != fill_data.additional_logins.end(); ++iter) { | 777 iter != fill_data.additional_logins.end(); |
| 776 if (DoUsernamesMatch(iter->first, current_username, | 778 ++iter) { |
| 777 exact_username_match)) { | 779 if (DoUsernamesMatch( |
| 780 iter->first, current_username, exact_username_match)) { |
| 778 username = iter->first; | 781 username = iter->first; |
| 779 password = iter->second.password; | 782 password = iter->second.password; |
| 780 break; | 783 break; |
| 781 } | 784 } |
| 782 } | 785 } |
| 783 | 786 |
| 784 // Check possible usernames. | 787 // Check possible usernames. |
| 785 if (username.empty() && password.empty()) { | 788 if (username.empty() && password.empty()) { |
| 786 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = | 789 for (PasswordFormFillData::UsernamesCollection::const_iterator iter = |
| 787 fill_data.other_possible_usernames.begin(); | 790 fill_data.other_possible_usernames.begin(); |
| 788 iter != fill_data.other_possible_usernames.end(); ++iter) { | 791 iter != fill_data.other_possible_usernames.end(); |
| 792 ++iter) { |
| 789 for (size_t i = 0; i < iter->second.size(); ++i) { | 793 for (size_t i = 0; i < iter->second.size(); ++i) { |
| 790 if (DoUsernamesMatch(iter->second[i], current_username, | 794 if (DoUsernamesMatch( |
| 791 exact_username_match)) { | 795 iter->second[i], current_username, exact_username_match)) { |
| 792 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 796 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
| 793 username = iter->second[i]; | 797 username = iter->second[i]; |
| 794 password = iter->first.password; | 798 password = iter->first.password; |
| 795 break; | 799 break; |
| 796 } | 800 } |
| 797 } | 801 } |
| 798 if (!username.empty() && !password.empty()) | 802 if (!username.empty() && !password.empty()) |
| 799 break; | 803 break; |
| 800 } | 804 } |
| 801 } | 805 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 // Don't inline autocomplete if the caret is not at the end. | 853 // Don't inline autocomplete if the caret is not at the end. |
| 850 // TODO(jcivelli): is there a better way to test the caret location? | 854 // TODO(jcivelli): is there a better way to test the caret location? |
| 851 if (username.selectionStart() != username.selectionEnd() || | 855 if (username.selectionStart() != username.selectionEnd() || |
| 852 username.selectionEnd() != static_cast<int>(username.value().length())) { | 856 username.selectionEnd() != static_cast<int>(username.value().length())) { |
| 853 return; | 857 return; |
| 854 } | 858 } |
| 855 | 859 |
| 856 // Show the popup with the list of available usernames. | 860 // Show the popup with the list of available usernames. |
| 857 ShowSuggestionPopup(fill_data, username); | 861 ShowSuggestionPopup(fill_data, username); |
| 858 | 862 |
| 859 | |
| 860 #if !defined(OS_ANDROID) | 863 #if !defined(OS_ANDROID) |
| 861 // Fill the user and password field with the most relevant match. Android | 864 // Fill the user and password field with the most relevant match. Android |
| 862 // only fills in the fields after the user clicks on the suggestion popup. | 865 // only fills in the fields after the user clicks on the suggestion popup. |
| 863 FillUserNameAndPassword(&username, &password, fill_data, | 866 FillUserNameAndPassword(&username, |
| 867 &password, |
| 868 fill_data, |
| 864 false /* exact_username_match */, | 869 false /* exact_username_match */, |
| 865 true /* set_selection */); | 870 true /* set_selection */); |
| 866 #endif | 871 #endif |
| 867 } | 872 } |
| 868 | 873 |
| 869 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 874 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { |
| 870 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 875 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
| 871 iter != login_to_password_info_.end();) { | 876 iter != login_to_password_info_.end();) { |
| 872 if (iter->first.document().frame() == frame) | 877 if (iter->first.document().frame() == frame) |
| 873 login_to_password_info_.erase(iter++); | 878 login_to_password_info_.erase(iter++); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 898 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); | 903 LoginToPasswordInfoMap::iterator iter = login_to_password_info_.find(input); |
| 899 if (iter == login_to_password_info_.end()) | 904 if (iter == login_to_password_info_.end()) |
| 900 return false; | 905 return false; |
| 901 | 906 |
| 902 *found_input = input; | 907 *found_input = input; |
| 903 *found_password = iter->second; | 908 *found_password = iter->second; |
| 904 return true; | 909 return true; |
| 905 } | 910 } |
| 906 | 911 |
| 907 } // namespace autofill | 912 } // namespace autofill |
| OLD | NEW |