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" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "components/autofill/content/common/autofill_messages.h" | 12 #include "components/autofill/content/common/autofill_messages.h" |
13 #include "components/autofill/content/renderer/form_autofill_util.h" | 13 #include "components/autofill/content/renderer/form_autofill_util.h" |
14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 14 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
15 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h" | 15 #include "components/autofill/content/renderer/renderer_save_password_progress_l ogger.h" |
16 #include "components/autofill/core/common/form_field_data.h" | 16 #include "components/autofill/core/common/form_field_data.h" |
17 #include "components/autofill/core/common/password_form.h" | 17 #include "components/autofill/core/common/password_form.h" |
18 #include "components/autofill/core/common/password_form_fill_data.h" | 18 #include "components/autofill/core/common/password_form_fill_data.h" |
19 #include "content/public/renderer/document_state.h" | 19 #include "content/public/renderer/document_state.h" |
20 #include "content/public/renderer/navigation_state.h" | 20 #include "content/public/renderer/navigation_state.h" |
21 #include "content/public/renderer/render_frame.h" | |
21 #include "content/public/renderer/render_view.h" | 22 #include "content/public/renderer/render_view.h" |
22 #include "third_party/WebKit/public/platform/WebVector.h" | 23 #include "third_party/WebKit/public/platform/WebVector.h" |
23 #include "third_party/WebKit/public/web/WebAutofillClient.h" | 24 #include "third_party/WebKit/public/web/WebAutofillClient.h" |
24 #include "third_party/WebKit/public/web/WebDocument.h" | 25 #include "third_party/WebKit/public/web/WebDocument.h" |
25 #include "third_party/WebKit/public/web/WebElement.h" | 26 #include "third_party/WebKit/public/web/WebElement.h" |
26 #include "third_party/WebKit/public/web/WebFormElement.h" | 27 #include "third_party/WebKit/public/web/WebFormElement.h" |
27 #include "third_party/WebKit/public/web/WebInputEvent.h" | 28 #include "third_party/WebKit/public/web/WebInputEvent.h" |
28 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 29 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
29 #include "third_party/WebKit/public/web/WebNode.h" | 30 #include "third_party/WebKit/public/web/WebNode.h" |
30 #include "third_party/WebKit/public/web/WebNodeList.h" | 31 #include "third_party/WebKit/public/web/WebNodeList.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 // Note: clear will remove a reference from each InputElement. | 115 // Note: clear will remove a reference from each InputElement. |
115 if (!found_input) { | 116 if (!found_input) { |
116 result->input_elements.clear(); | 117 result->input_elements.clear(); |
117 return false; | 118 return false; |
118 } | 119 } |
119 } | 120 } |
120 return true; | 121 return true; |
121 } | 122 } |
122 | 123 |
123 // Helper to locate form elements identified by |data|. | 124 // Helper to locate form elements identified by |data|. |
124 void FindFormElements(blink::WebView* view, | 125 void FindFormElements(content::RenderFrame* render_frame, |
125 const FormData& data, | 126 const FormData& data, |
126 FormElementsList* results) { | 127 FormElementsList* results) { |
127 DCHECK(view); | |
128 DCHECK(results); | 128 DCHECK(results); |
129 blink::WebFrame* main_frame = view->mainFrame(); | |
130 if (!main_frame) | |
131 return; | |
132 | 129 |
133 GURL::Replacements rep; | 130 GURL::Replacements rep; |
134 rep.ClearQuery(); | 131 rep.ClearQuery(); |
135 rep.ClearRef(); | 132 rep.ClearRef(); |
136 | 133 |
137 // Loop through each frame. | 134 blink::WebDocument doc = render_frame->GetWebFrame()->document(); |
138 for (blink::WebFrame* f = main_frame; f; f = f->traverseNext(false)) { | 135 if (!doc.isHTMLDocument()) |
139 blink::WebDocument doc = f->document(); | 136 return; |
140 if (!doc.isHTMLDocument()) | 137 |
138 GURL full_origin(doc.url()); | |
139 if (data.origin != full_origin.ReplaceComponents(rep)) | |
140 return; | |
141 | |
142 blink::WebVector<blink::WebFormElement> forms; | |
143 doc.forms(forms); | |
144 | |
145 for (size_t i = 0; i < forms.size(); ++i) { | |
146 blink::WebFormElement fe = forms[i]; | |
147 | |
148 GURL full_action(doc.completeURL(fe.action())); | |
149 if (full_action.is_empty()) { | |
150 // The default action URL is the form's origin. | |
151 full_action = full_origin; | |
152 } | |
153 | |
154 // Action URL must match. | |
155 if (data.action != full_action.ReplaceComponents(rep)) | |
141 continue; | 156 continue; |
142 | 157 |
143 GURL full_origin(doc.url()); | 158 scoped_ptr<FormElements> curr_elements(new FormElements); |
144 if (data.origin != full_origin.ReplaceComponents(rep)) | 159 if (!FindFormInputElements(&fe, data, curr_elements.get())) |
145 continue; | 160 continue; |
146 | 161 |
147 blink::WebVector<blink::WebFormElement> forms; | 162 // We found the right element. |
148 doc.forms(forms); | 163 // Note: this assignment adds a reference to |fe|. |
149 | 164 curr_elements->form_element = fe; |
150 for (size_t i = 0; i < forms.size(); ++i) { | 165 results->push_back(curr_elements.release()); |
151 blink::WebFormElement fe = forms[i]; | |
152 | |
153 GURL full_action(f->document().completeURL(fe.action())); | |
154 if (full_action.is_empty()) { | |
155 // The default action URL is the form's origin. | |
156 full_action = full_origin; | |
157 } | |
158 | |
159 // Action URL must match. | |
160 if (data.action != full_action.ReplaceComponents(rep)) | |
161 continue; | |
162 | |
163 scoped_ptr<FormElements> curr_elements(new FormElements); | |
164 if (!FindFormInputElements(&fe, data, curr_elements.get())) | |
165 continue; | |
166 | |
167 // We found the right element. | |
168 // Note: this assignment adds a reference to |fe|. | |
169 curr_elements->form_element = fe; | |
170 results->push_back(curr_elements.release()); | |
171 } | |
172 } | 166 } |
173 } | 167 } |
174 | 168 |
175 bool IsElementEditable(const blink::WebInputElement& element) { | 169 bool IsElementEditable(const blink::WebInputElement& element) { |
176 return element.isEnabled() && !element.isReadOnly(); | 170 return element.isEnabled() && !element.isReadOnly(); |
177 } | 171 } |
178 | 172 |
179 bool DoUsernamesMatch(const base::string16& username1, | 173 bool DoUsernamesMatch(const base::string16& username1, |
180 const base::string16& username2, | 174 const base::string16& username2, |
181 bool exact_match) { | 175 bool exact_match) { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 return false; | 416 return false; |
423 auto it = map.find(key); | 417 auto it = map.find(key); |
424 return it != map.end() && it->second.get(); | 418 return it != map.end() && it->second.get(); |
425 } | 419 } |
426 | 420 |
427 } // namespace | 421 } // namespace |
428 | 422 |
429 //////////////////////////////////////////////////////////////////////////////// | 423 //////////////////////////////////////////////////////////////////////////////// |
430 // PasswordAutofillAgent, public: | 424 // PasswordAutofillAgent, public: |
431 | 425 |
432 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderView* render_view) | 426 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame) |
433 : content::RenderViewObserver(render_view), | 427 : content::RenderFrameObserver(render_frame), |
428 legacy_(render_frame->GetRenderView(), this), | |
434 usernames_usage_(NOTHING_TO_AUTOFILL), | 429 usernames_usage_(NOTHING_TO_AUTOFILL), |
435 web_view_(render_view->GetWebView()), | |
436 logging_state_active_(false), | 430 logging_state_active_(false), |
437 was_username_autofilled_(false), | 431 was_username_autofilled_(false), |
438 was_password_autofilled_(false), | 432 was_password_autofilled_(false), |
439 username_selection_start_(0), | 433 username_selection_start_(0), |
440 did_stop_loading_(false), | 434 did_stop_loading_(false), |
441 weak_ptr_factory_(this) { | 435 weak_ptr_factory_(this) { |
442 Send(new AutofillHostMsg_PasswordAutofillAgentConstructed(routing_id())); | 436 Send(new AutofillHostMsg_PasswordAutofillAgentConstructed(routing_id())); |
443 } | 437 } |
444 | 438 |
445 PasswordAutofillAgent::~PasswordAutofillAgent() { | 439 PasswordAutofillAgent::~PasswordAutofillAgent() { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 514 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
521 } | 515 } |
522 return true; | 516 return true; |
523 } | 517 } |
524 | 518 |
525 bool PasswordAutofillAgent::TextDidChangeInTextField( | 519 bool PasswordAutofillAgent::TextDidChangeInTextField( |
526 const blink::WebInputElement& element) { | 520 const blink::WebInputElement& element) { |
527 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 | 521 // TODO(vabr): Get a mutable argument instead. http://crbug.com/397083 |
528 blink::WebInputElement mutable_element = element; // We need a non-const. | 522 blink::WebInputElement mutable_element = element; // We need a non-const. |
529 | 523 |
524 DCHECK_EQ(element.document().frame(), render_frame()->GetWebFrame()); | |
525 | |
530 if (element.isPasswordField()) { | 526 if (element.isPasswordField()) { |
531 // Some login forms have event handlers that put a hash of the password into | 527 // Some login forms have event handlers that put a hash of the password into |
532 // a hidden field and then clear the password (http://crbug.com/28910, | 528 // a hidden field and then clear the password (http://crbug.com/28910, |
533 // http://crbug.com/391693). This method gets called before any of those | 529 // http://crbug.com/391693). This method gets called before any of those |
534 // handlers run, so save away a copy of the password in case it gets lost. | 530 // handlers run, so save away a copy of the password in case it gets lost. |
535 // To honor the user having explicitly cleared the password, even an empty | 531 // To honor the user having explicitly cleared the password, even an empty |
536 // password will be saved here. | 532 // password will be saved here. |
537 if (blink::WebLocalFrame* element_frame = element.document().frame()) { | 533 ProvisionallySavePassword(element.form(), RESTRICTION_NONE); |
538 ProvisionallySavePassword( | |
539 element_frame, element.form(), RESTRICTION_NONE); | |
540 } | |
541 | 534 |
542 PasswordToLoginMap::iterator iter = password_to_username_.find(element); | 535 PasswordToLoginMap::iterator iter = password_to_username_.find(element); |
543 if (iter != password_to_username_.end()) { | 536 if (iter != password_to_username_.end()) { |
544 login_to_password_info_[iter->second].password_was_edited_last = true; | 537 login_to_password_info_[iter->second].password_was_edited_last = true; |
545 // Note that the suggested value of |mutable_element| was reset when its | 538 // Note that the suggested value of |mutable_element| was reset when its |
546 // value changed. | 539 // value changed. |
547 mutable_element.setAutofilled(false); | 540 mutable_element.setAutofilled(false); |
548 } | 541 } |
549 return false; | 542 return false; |
550 } | 543 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 return true; | 684 return true; |
692 | 685 |
693 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); | 686 return ShowSuggestionPopup(iter->second.fill_data, element, show_all); |
694 } | 687 } |
695 | 688 |
696 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( | 689 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( |
697 const blink::WebSecurityOrigin& origin) { | 690 const blink::WebSecurityOrigin& origin) { |
698 return origin.canAccessPasswordManager(); | 691 return origin.canAccessPasswordManager(); |
699 } | 692 } |
700 | 693 |
701 void PasswordAutofillAgent::OnDynamicFormsSeen(blink::WebFrame* frame) { | 694 void PasswordAutofillAgent::OnDynamicFormsSeen() { |
702 SendPasswordForms(frame, false /* only_visible */); | 695 SendPasswordForms(false /* only_visible */); |
703 } | 696 } |
704 | 697 |
705 void PasswordAutofillAgent::FirstUserGestureObserved() { | 698 void PasswordAutofillAgent::FirstUserGestureObserved() { |
706 gatekeeper_.OnUserGesture(); | 699 gatekeeper_.OnUserGesture(); |
707 } | 700 } |
708 | 701 |
709 void PasswordAutofillAgent::SendPasswordForms(blink::WebFrame* frame, | 702 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) { |
710 bool only_visible) { | |
711 scoped_ptr<RendererSavePasswordProgressLogger> logger; | 703 scoped_ptr<RendererSavePasswordProgressLogger> logger; |
712 if (logging_state_active_) { | 704 if (logging_state_active_) { |
713 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); | 705 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); |
714 logger->LogMessage(Logger::STRING_SEND_PASSWORD_FORMS_METHOD); | 706 logger->LogMessage(Logger::STRING_SEND_PASSWORD_FORMS_METHOD); |
715 logger->LogBoolean(Logger::STRING_ONLY_VISIBLE, only_visible); | 707 logger->LogBoolean(Logger::STRING_ONLY_VISIBLE, only_visible); |
716 } | 708 } |
717 | 709 |
710 blink::WebFrame* frame = render_frame()->GetWebFrame(); | |
718 // Make sure that this security origin is allowed to use password manager. | 711 // Make sure that this security origin is allowed to use password manager. |
719 blink::WebSecurityOrigin origin = frame->document().securityOrigin(); | 712 blink::WebSecurityOrigin origin = frame->document().securityOrigin(); |
720 if (logger) { | 713 if (logger) { |
721 logger->LogURL(Logger::STRING_SECURITY_ORIGIN, | 714 logger->LogURL(Logger::STRING_SECURITY_ORIGIN, |
722 GURL(origin.toString().utf8())); | 715 GURL(origin.toString().utf8())); |
723 } | 716 } |
724 if (!OriginCanAccessPasswordManager(origin)) { | 717 if (!OriginCanAccessPasswordManager(origin)) { |
725 if (logger) { | 718 if (logger) { |
726 logger->LogMessage(Logger::STRING_SECURITY_ORIGIN_FAILURE); | 719 logger->LogMessage(Logger::STRING_SECURITY_ORIGIN_FAILURE); |
727 logger->LogMessage(Logger::STRING_DECISION_DROP); | 720 logger->LogMessage(Logger::STRING_DECISION_DROP); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
786 bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) { | 779 bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) { |
787 bool handled = true; | 780 bool handled = true; |
788 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message) | 781 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message) |
789 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm) | 782 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm) |
790 IPC_MESSAGE_HANDLER(AutofillMsg_SetLoggingState, OnSetLoggingState) | 783 IPC_MESSAGE_HANDLER(AutofillMsg_SetLoggingState, OnSetLoggingState) |
791 IPC_MESSAGE_UNHANDLED(handled = false) | 784 IPC_MESSAGE_UNHANDLED(handled = false) |
792 IPC_END_MESSAGE_MAP() | 785 IPC_END_MESSAGE_MAP() |
793 return handled; | 786 return handled; |
794 } | 787 } |
795 | 788 |
789 void PasswordAutofillAgent::DidFinishDocumentLoad() { | |
790 // The |frame| contents have been parsed, but not yet rendered. Let the | |
791 // PasswordManager know that forms are loaded, even though we can't yet tell | |
792 // whether they're visible. | |
793 SendPasswordForms(false); | |
794 } | |
795 | |
796 void PasswordAutofillAgent::DidFinishLoad() { | |
797 // The |frame| contents have been rendered. Let the PasswordManager know | |
798 // which of the loaded frames are actually visible to the user. This also | |
799 // triggers the "Save password?" infobar if the user just submitted a password | |
800 // form. | |
801 SendPasswordForms(true); | |
802 } | |
803 | |
804 void PasswordAutofillAgent::FrameWillClose() { | |
805 FrameClosing(); | |
806 } | |
807 | |
796 void PasswordAutofillAgent::DidStartLoading() { | 808 void PasswordAutofillAgent::DidStartLoading() { |
797 did_stop_loading_ = false; | 809 did_stop_loading_ = false; |
798 if (usernames_usage_ != NOTHING_TO_AUTOFILL) { | 810 if (usernames_usage_ != NOTHING_TO_AUTOFILL) { |
799 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage", | 811 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage", |
800 usernames_usage_, | 812 usernames_usage_, OTHER_POSSIBLE_USERNAMES_MAX); |
801 OTHER_POSSIBLE_USERNAMES_MAX); | |
802 usernames_usage_ = NOTHING_TO_AUTOFILL; | 813 usernames_usage_ = NOTHING_TO_AUTOFILL; |
803 } | 814 } |
804 } | 815 } |
805 | 816 |
806 void PasswordAutofillAgent::DidFinishDocumentLoad(blink::WebLocalFrame* frame) { | |
807 // The |frame| contents have been parsed, but not yet rendered. Let the | |
808 // PasswordManager know that forms are loaded, even though we can't yet tell | |
809 // whether they're visible. | |
810 SendPasswordForms(frame, false); | |
811 } | |
812 | |
813 void PasswordAutofillAgent::DidFinishLoad(blink::WebLocalFrame* frame) { | |
814 // The |frame| contents have been rendered. Let the PasswordManager know | |
815 // which of the loaded frames are actually visible to the user. This also | |
816 // triggers the "Save password?" infobar if the user just submitted a password | |
817 // form. | |
818 SendPasswordForms(frame, true); | |
819 } | |
820 | |
821 void PasswordAutofillAgent::DidStopLoading() { | 817 void PasswordAutofillAgent::DidStopLoading() { |
822 did_stop_loading_ = true; | 818 did_stop_loading_ = true; |
823 } | 819 } |
824 | 820 |
825 void PasswordAutofillAgent::FrameDetached(blink::WebFrame* frame) { | 821 void PasswordAutofillAgent::FrameDetached(blink::WebFrame* frame) { |
826 FrameClosing(frame); | 822 if (frame == render_frame()->GetWebFrame()) |
827 } | 823 FrameClosing(); |
828 | |
829 void PasswordAutofillAgent::FrameWillClose(blink::WebFrame* frame) { | |
830 FrameClosing(frame); | |
831 } | 824 } |
832 | 825 |
833 void PasswordAutofillAgent::WillSendSubmitEvent( | 826 void PasswordAutofillAgent::WillSendSubmitEvent( |
834 blink::WebLocalFrame* frame, | 827 blink::WebLocalFrame* frame, |
835 const blink::WebFormElement& form) { | 828 const blink::WebFormElement& form) { |
829 if (frame != render_frame()->GetWebFrame()) | |
830 return; | |
836 // Forms submitted via XHR are not seen by WillSubmitForm if the default | 831 // Forms submitted via XHR are not seen by WillSubmitForm if the default |
837 // onsubmit handler is overridden. Such submission first gets detected in | 832 // onsubmit handler is overridden. Such submission first gets detected in |
838 // DidStartProvisionalLoad, which no longer knows about the particular form, | 833 // DidStartProvisionalLoad, which no longer knows about the particular form, |
839 // and uses the candidate stored in |provisionally_saved_forms_|. | 834 // and uses the candidate stored in |provisionally_saved_form_|. |
840 // | 835 // |
841 // User-typed password will get stored to |provisionally_saved_forms_| in | 836 // User-typed password will get stored to |provisionally_saved_form_| in |
842 // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to | 837 // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to |
843 // be saved here. | 838 // be saved here. |
844 // | 839 // |
845 // Only non-empty passwords are saved here. Empty passwords were likely | 840 // Only non-empty passwords are saved here. Empty passwords were likely |
846 // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693). | 841 // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693). |
847 // Had the user cleared the password, |provisionally_saved_forms_| would | 842 // Had the user cleared the password, |provisionally_saved_form_| would |
848 // already have been updated in TextDidChangeInTextField. | 843 // already have been updated in TextDidChangeInTextField. |
849 ProvisionallySavePassword(frame, form, RESTRICTION_NON_EMPTY_PASSWORD); | 844 ProvisionallySavePassword(form, RESTRICTION_NON_EMPTY_PASSWORD); |
850 } | 845 } |
851 | 846 |
852 void PasswordAutofillAgent::WillSubmitForm(blink::WebLocalFrame* frame, | 847 void PasswordAutofillAgent::WillSubmitForm(blink::WebLocalFrame* frame, |
853 const blink::WebFormElement& form) { | 848 const blink::WebFormElement& form) { |
854 DCHECK(frame); | 849 if (frame != render_frame()->GetWebFrame()) |
850 return; | |
851 | |
855 scoped_ptr<RendererSavePasswordProgressLogger> logger; | 852 scoped_ptr<RendererSavePasswordProgressLogger> logger; |
856 if (logging_state_active_) { | 853 if (logging_state_active_) { |
857 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); | 854 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); |
858 logger->LogMessage(Logger::STRING_WILL_SUBMIT_FORM_METHOD); | 855 logger->LogMessage(Logger::STRING_WILL_SUBMIT_FORM_METHOD); |
859 LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form); | 856 LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form); |
860 } | 857 } |
861 | 858 |
862 scoped_ptr<PasswordForm> submitted_form = CreatePasswordForm(form); | 859 scoped_ptr<PasswordForm> submitted_form = CreatePasswordForm(form); |
863 | 860 |
864 // If there is a provisionally saved password, copy over the previous | 861 // If there is a provisionally saved password, copy over the previous |
865 // password value so we get the user's typed password, not the value that | 862 // password value so we get the user's typed password, not the value that |
866 // may have been transformed for submit. | 863 // may have been transformed for submit. |
867 // TODO(gcasto): Do we need to have this action equality check? Is it trying | 864 // TODO(gcasto): Do we need to have this action equality check? Is it trying |
868 // to prevent accidentally copying over passwords from a different form? | 865 // to prevent accidentally copying over passwords from a different form? |
869 if (submitted_form) { | 866 if (submitted_form) { |
870 if (logger) { | 867 if (logger) { |
871 logger->LogPasswordForm(Logger::STRING_CREATED_PASSWORD_FORM, | 868 logger->LogPasswordForm(Logger::STRING_CREATED_PASSWORD_FORM, |
872 *submitted_form); | 869 *submitted_form); |
873 } | 870 } |
874 if (ContainsNonNullEntryForNonNullKey( | 871 if (provisionally_saved_form_.get() && |
875 provisionally_saved_forms_, static_cast<blink::WebFrame*>(frame)) && | 872 submitted_form->action == provisionally_saved_form_->action) { |
876 submitted_form->action == provisionally_saved_forms_[frame]->action) { | |
877 if (logger) | 873 if (logger) |
878 logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED); | 874 logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED); |
879 submitted_form->password_value = | 875 submitted_form->password_value = |
880 provisionally_saved_forms_[frame]->password_value; | 876 provisionally_saved_form_->password_value; |
881 submitted_form->new_password_value = | 877 submitted_form->new_password_value = |
882 provisionally_saved_forms_[frame]->new_password_value; | 878 provisionally_saved_form_->new_password_value; |
883 } | 879 } |
884 | 880 |
885 // Some observers depend on sending this information now instead of when | 881 // Some observers depend on sending this information now instead of when |
886 // the frame starts loading. If there are redirects that cause a new | 882 // the frame starts loading. If there are redirects that cause a new |
887 // RenderView to be instantiated (such as redirects to the WebStore) | 883 // RenderView to be instantiated (such as redirects to the WebStore) |
888 // we will never get to finish the load. | 884 // we will never get to finish the load. |
889 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(), | 885 Send(new AutofillHostMsg_PasswordFormSubmitted( |
890 *submitted_form)); | 886 routing_id(), *provisionally_saved_form_.release())); |
891 // Remove reference since we have already submitted this form. | |
892 provisionally_saved_forms_.erase(frame); | |
893 } else if (logger) { | 887 } else if (logger) { |
894 logger->LogMessage(Logger::STRING_DECISION_DROP); | 888 logger->LogMessage(Logger::STRING_DECISION_DROP); |
895 } | 889 } |
896 } | 890 } |
897 | 891 |
898 blink::WebFrame* PasswordAutofillAgent::CurrentOrChildFrameWithSavedForms( | 892 void PasswordAutofillAgent::DidStartProvisionalLoad() { |
899 const blink::WebFrame* current_frame) { | |
900 for (FrameToPasswordFormMap::const_iterator it = | |
901 provisionally_saved_forms_.begin(); | |
902 it != provisionally_saved_forms_.end(); | |
903 ++it) { | |
904 blink::WebFrame* form_frame = it->first; | |
905 // The check that the returned frame is related to |current_frame| is mainly | |
906 // for double-checking. There should not be any unrelated frames in | |
907 // |provisionally_saved_forms_|, because the map is cleared after | |
908 // navigation. If there are reasons to remove this check in the future and | |
909 // keep just the first frame found, it might be a good idea to add a UMA | |
910 // statistic or a similar check on how many frames are here to choose from. | |
911 if (current_frame == form_frame || | |
912 current_frame->findChildByName(form_frame->assignedName())) { | |
913 return form_frame; | |
914 } | |
915 } | |
916 return NULL; | |
917 } | |
918 | |
919 void PasswordAutofillAgent::DidStartProvisionalLoad( | |
920 blink::WebLocalFrame* frame) { | |
921 scoped_ptr<RendererSavePasswordProgressLogger> logger; | 893 scoped_ptr<RendererSavePasswordProgressLogger> logger; |
922 if (logging_state_active_) { | 894 if (logging_state_active_) { |
923 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); | 895 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); |
924 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD); | 896 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD); |
925 } | 897 } |
926 | 898 |
927 if (!frame->parent()) { | 899 blink::WebFrame* frame = render_frame()->GetWebFrame(); |
vabr (Chromium)
2014/11/10 14:34:40
So here the behaviour seems changed -- we try to s
Evan Stade
2014/11/14 23:25:49
reverted.
| |
928 // If the navigation is not triggered by a user gesture, e.g. by some ajax | 900 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when |
929 // callback, then inherit the submitted password form from the previous | 901 // the user is performing actions outside the page (e.g. typed url, |
930 // state. This fixes the no password save issue for ajax login, tracked in | 902 // history navigation). We don't want to trigger saving in these cases. |
931 // [http://crbug/43219]. Note that this still fails for sites that use | 903 content::DocumentState* document_state = |
932 // synchonous XHR as isProcessingUserGesture() will return true. | 904 content::DocumentState::FromDataSource(frame->provisionalDataSource()); |
933 blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame); | 905 content::NavigationState* navigation_state = |
934 if (logger) { | 906 document_state->navigation_state(); |
935 logger->LogBoolean(Logger::STRING_FORM_FRAME_EQ_FRAME, | 907 if (ui::PageTransitionIsWebTriggerable(navigation_state->transition_type()) && |
936 form_frame == frame); | 908 !blink::WebUserGestureIndicator::isProcessingUserGesture()) { |
937 } | 909 // If onsubmit has been called, try and save that form. |
938 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when | 910 if (provisionally_saved_form_.get()) { |
939 // the user is performing actions outside the page (e.g. typed url, | 911 if (logger) { |
940 // history navigation). We don't want to trigger saving in these cases. | 912 logger->LogPasswordForm( |
941 content::DocumentState* document_state = | 913 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME, |
942 content::DocumentState::FromDataSource( | 914 *provisionally_saved_form_); |
943 frame->provisionalDataSource()); | 915 } |
944 content::NavigationState* navigation_state = | 916 Send(new AutofillHostMsg_PasswordFormSubmitted( |
945 document_state->navigation_state(); | 917 routing_id(), *provisionally_saved_form_.release())); |
946 if (ui::PageTransitionIsWebTriggerable( | 918 } else { |
947 navigation_state->transition_type()) && | 919 // Loop through the forms on the page looking for one that has been |
948 !blink::WebUserGestureIndicator::isProcessingUserGesture()) { | 920 // filled out. If one exists, try and save the credentials. |
949 // If onsubmit has been called, try and save that form. | 921 blink::WebVector<blink::WebFormElement> forms; |
950 if (ContainsNonNullEntryForNonNullKey(provisionally_saved_forms_, | 922 frame->document().forms(forms); |
951 form_frame)) { | 923 |
924 bool password_forms_found = false; | |
925 for (size_t i = 0; i < forms.size(); ++i) { | |
926 blink::WebFormElement form_element = forms[i]; | |
952 if (logger) { | 927 if (logger) { |
953 logger->LogPasswordForm( | 928 LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, |
954 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME, | 929 form_element); |
955 *provisionally_saved_forms_[form_frame]); | |
956 } | 930 } |
957 Send(new AutofillHostMsg_PasswordFormSubmitted( | 931 scoped_ptr<PasswordForm> password_form( |
958 routing_id(), *provisionally_saved_forms_[form_frame])); | 932 CreatePasswordForm(form_element)); |
959 provisionally_saved_forms_.erase(form_frame); | 933 if (password_form.get() && !password_form->username_value.empty() && |
960 } else { | 934 FormContainsNonDefaultPasswordValue(*password_form, form_element)) { |
961 // Loop through the forms on the page looking for one that has been | 935 password_forms_found = true; |
962 // filled out. If one exists, try and save the credentials. | |
963 blink::WebVector<blink::WebFormElement> forms; | |
964 frame->document().forms(forms); | |
965 | |
966 bool password_forms_found = false; | |
967 for (size_t i = 0; i < forms.size(); ++i) { | |
968 blink::WebFormElement form_element = forms[i]; | |
969 if (logger) { | 936 if (logger) { |
970 LogHTMLForm( | 937 logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_FOUND_ON_PAGE, |
971 logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form_element); | 938 *password_form); |
972 } | 939 } |
973 scoped_ptr<PasswordForm> password_form( | 940 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(), |
974 CreatePasswordForm(form_element)); | 941 *password_form)); |
975 if (password_form.get() && !password_form->username_value.empty() && | |
976 FormContainsNonDefaultPasswordValue( | |
977 *password_form, form_element)) { | |
978 password_forms_found = true; | |
979 if (logger) { | |
980 logger->LogPasswordForm( | |
981 Logger::STRING_PASSWORD_FORM_FOUND_ON_PAGE, *password_form); | |
982 } | |
983 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(), | |
984 *password_form)); | |
985 } | |
986 } | |
987 if (!password_forms_found && logger) { | |
988 logger->LogMessage(Logger::STRING_DECISION_DROP); | |
989 } | 942 } |
990 } | 943 } |
944 if (!password_forms_found && logger) { | |
945 logger->LogMessage(Logger::STRING_DECISION_DROP); | |
946 } | |
991 } | 947 } |
992 // Clear the whole map during main frame navigation. | |
993 provisionally_saved_forms_.clear(); | |
994 | 948 |
995 // This is a new navigation, so require a new user gesture before filling in | 949 // This is a new navigation, so require a new user gesture before filling in |
996 // passwords. | 950 // passwords. |
997 gatekeeper_.Reset(); | 951 gatekeeper_.Reset(); |
998 } else { | |
999 if (logger) | |
1000 logger->LogMessage(Logger::STRING_DECISION_DROP); | |
1001 } | 952 } |
1002 } | 953 } |
1003 | 954 |
1004 void PasswordAutofillAgent::OnFillPasswordForm( | 955 void PasswordAutofillAgent::OnFillPasswordForm( |
1005 int key, | 956 int key, |
1006 const PasswordFormFillData& form_data) { | 957 const PasswordFormFillData& form_data) { |
1007 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { | 958 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { |
1008 if (form_data.other_possible_usernames.size()) | 959 if (form_data.other_possible_usernames.size()) |
1009 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; | 960 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; |
1010 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) | 961 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) |
1011 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; | 962 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; |
1012 } | 963 } |
1013 | 964 |
1014 FormElementsList forms; | 965 FormElementsList forms; |
1015 // We own the FormElements* in forms. | 966 // We own the FormElements* in forms. |
1016 FindFormElements(render_view()->GetWebView(), form_data.basic_data, &forms); | 967 FindFormElements(render_frame(), form_data.basic_data, &forms); |
1017 FormElementsList::iterator iter; | 968 FormElementsList::iterator iter; |
1018 for (iter = forms.begin(); iter != forms.end(); ++iter) { | 969 for (iter = forms.begin(); iter != forms.end(); ++iter) { |
1019 scoped_ptr<FormElements> form_elements(*iter); | 970 scoped_ptr<FormElements> form_elements(*iter); |
1020 | 971 |
1021 // Attach autocomplete listener to enable selecting alternate logins. | 972 // Attach autocomplete listener to enable selecting alternate logins. |
1022 blink::WebInputElement username_element, password_element; | 973 blink::WebInputElement username_element, password_element; |
1023 | 974 |
1024 // Check whether the password form has a username input field. | 975 // Check whether the password form has a username input field. |
1025 bool form_contains_username_field = FillDataContainsUsername(form_data); | 976 bool form_contains_username_field = FillDataContainsUsername(form_data); |
1026 if (form_contains_username_field) { | 977 if (form_contains_username_field) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1091 FindFormAndFieldForFormControlElement( | 1042 FindFormAndFieldForFormControlElement( |
1092 user_input, &form, &field, REQUIRE_NONE); | 1043 user_input, &form, &field, REQUIRE_NONE); |
1093 | 1044 |
1094 blink::WebInputElement selected_element = user_input; | 1045 blink::WebInputElement selected_element = user_input; |
1095 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); | 1046 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); |
1096 | 1047 |
1097 LoginToPasswordInfoKeyMap::const_iterator key_it = | 1048 LoginToPasswordInfoKeyMap::const_iterator key_it = |
1098 login_to_password_info_key_.find(user_input); | 1049 login_to_password_info_key_.find(user_input); |
1099 DCHECK(key_it != login_to_password_info_key_.end()); | 1050 DCHECK(key_it != login_to_password_info_key_.end()); |
1100 | 1051 |
1101 float scale = web_view_->pageScaleFactor(); | 1052 float scale = |
1053 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor(); | |
1102 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, | 1054 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, |
1103 bounding_box.y() * scale, | 1055 bounding_box.y() * scale, |
1104 bounding_box.width() * scale, | 1056 bounding_box.width() * scale, |
1105 bounding_box.height() * scale); | 1057 bounding_box.height() * scale); |
1106 Send(new AutofillHostMsg_ShowPasswordSuggestions( | 1058 Send(new AutofillHostMsg_ShowPasswordSuggestions( |
1107 routing_id(), key_it->second, field.text_direction, user_input.value(), | 1059 routing_id(), key_it->second, field.text_direction, user_input.value(), |
1108 show_all, bounding_box_scaled)); | 1060 show_all, bounding_box_scaled)); |
1109 | 1061 |
1110 bool suggestions_present = false; | 1062 bool suggestions_present = false; |
1111 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, | 1063 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1144 fill_data, | 1096 fill_data, |
1145 false /* exact_username_match */, | 1097 false /* exact_username_match */, |
1146 true /* set_selection */, | 1098 true /* set_selection */, |
1147 base::Bind(&PasswordValueGatekeeper::RegisterElement, | 1099 base::Bind(&PasswordValueGatekeeper::RegisterElement, |
1148 base::Unretained(&gatekeeper_)))) { | 1100 base::Unretained(&gatekeeper_)))) { |
1149 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; | 1101 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; |
1150 } | 1102 } |
1151 #endif | 1103 #endif |
1152 } | 1104 } |
1153 | 1105 |
1154 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { | 1106 void PasswordAutofillAgent::FrameClosing() { |
1155 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); | 1107 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); |
1156 iter != login_to_password_info_.end();) { | 1108 iter != login_to_password_info_.end();) { |
1157 // There may not be a username field, so get the frame from the password | 1109 // There may not be a username field, so get the frame from the password |
1158 // field. | 1110 // field. |
1159 if (iter->second.password_field.document().frame() == frame) { | 1111 DCHECK_EQ(iter->second.password_field.document().frame(), |
1160 login_to_password_info_key_.erase(iter->first); | 1112 render_frame()->GetWebFrame()); |
1161 password_to_username_.erase(iter->second.password_field); | 1113 login_to_password_info_key_.erase(iter->first); |
1162 login_to_password_info_.erase(iter++); | 1114 password_to_username_.erase(iter->second.password_field); |
1163 } else { | 1115 login_to_password_info_.erase(iter++); |
1164 ++iter; | |
1165 } | |
1166 } | 1116 } |
1167 for (FrameToPasswordFormMap::iterator iter = | 1117 provisionally_saved_form_.reset(); |
1168 provisionally_saved_forms_.begin(); | |
1169 iter != provisionally_saved_forms_.end();) { | |
1170 if (iter->first == frame) | |
1171 provisionally_saved_forms_.erase(iter++); | |
1172 else | |
1173 ++iter; | |
1174 } | |
1175 } | 1118 } |
1176 | 1119 |
1177 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, | 1120 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, |
1178 blink::WebInputElement* found_input, | 1121 blink::WebInputElement* found_input, |
1179 PasswordInfo** found_password) { | 1122 PasswordInfo** found_password) { |
1180 if (!node.isElementNode()) | 1123 if (!node.isElementNode()) |
1181 return false; | 1124 return false; |
1182 | 1125 |
1183 blink::WebElement element = node.toConst<blink::WebElement>(); | 1126 blink::WebElement element = node.toConst<blink::WebElement>(); |
1184 if (!element.hasHTMLTagName("input")) | 1127 if (!element.hasHTMLTagName("input")) |
(...skipping 18 matching lines...) Expand all Loading... | |
1203 username->setSelectionRange(username_selection_start_, | 1146 username->setSelectionRange(username_selection_start_, |
1204 username->value().length()); | 1147 username->value().length()); |
1205 } | 1148 } |
1206 if (!password->suggestedValue().isEmpty()) { | 1149 if (!password->suggestedValue().isEmpty()) { |
1207 password->setSuggestedValue(blink::WebString()); | 1150 password->setSuggestedValue(blink::WebString()); |
1208 password->setAutofilled(was_password_autofilled_); | 1151 password->setAutofilled(was_password_autofilled_); |
1209 } | 1152 } |
1210 } | 1153 } |
1211 | 1154 |
1212 void PasswordAutofillAgent::ProvisionallySavePassword( | 1155 void PasswordAutofillAgent::ProvisionallySavePassword( |
1213 blink::WebLocalFrame* frame, | |
1214 const blink::WebFormElement& form, | 1156 const blink::WebFormElement& form, |
1215 ProvisionallySaveRestriction restriction) { | 1157 ProvisionallySaveRestriction restriction) { |
1216 // TODO(vabr): This is just to stop getting a NULL frame in | |
1217 // |provisionally_saved_forms_|. Cases where we try to save password for a | |
1218 // form in a NULL frame should not happen, and it's currently unclear how they | |
1219 // happen (http://crbug.com/420519). This thing will be hopefully solved by | |
1220 // migrating the PasswordAutofillAgent to observe frames directly | |
1221 // (http://crbug.com/400186). | |
1222 if (!frame) | |
1223 return; | |
1224 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); | 1158 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); |
1225 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && | 1159 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && |
1226 password_form->password_value.empty() && | 1160 password_form->password_value.empty() && |
1227 password_form->new_password_value.empty())) { | 1161 password_form->new_password_value.empty())) { |
1228 return; | 1162 return; |
1229 } | 1163 } |
1230 provisionally_saved_forms_[frame].reset(password_form.release()); | 1164 provisionally_saved_form_.reset(password_form.release()); |
1165 } | |
1166 | |
1167 // LegacyPasswordAutofillAgent ------------------------------------------------- | |
1168 | |
1169 PasswordAutofillAgent::LegacyPasswordAutofillAgent::LegacyPasswordAutofillAgent( | |
1170 content::RenderView* render_view, | |
1171 PasswordAutofillAgent* agent) | |
1172 : content::RenderViewObserver(render_view), agent_(agent) { | |
1173 } | |
1174 | |
1175 PasswordAutofillAgent::LegacyPasswordAutofillAgent:: | |
1176 ~LegacyPasswordAutofillAgent() { | |
1177 } | |
1178 | |
1179 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::OnDestruct() { | |
1180 // No op. Do not delete |this|. | |
1181 } | |
1182 | |
1183 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStartLoading() { | |
1184 agent_->DidStartLoading(); | |
1185 } | |
1186 | |
1187 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() { | |
1188 agent_->DidStopLoading(); | |
1189 } | |
1190 | |
1191 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::FrameDetached( | |
1192 blink::WebFrame* frame) { | |
1193 agent_->FrameDetached(frame); | |
1194 } | |
1195 | |
1196 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSendSubmitEvent( | |
1197 blink::WebLocalFrame* frame, | |
1198 const blink::WebFormElement& form) { | |
1199 agent_->WillSendSubmitEvent(frame, form); | |
1200 } | |
1201 | |
1202 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm( | |
1203 blink::WebLocalFrame* frame, | |
1204 const blink::WebFormElement& form) { | |
1205 agent_->WillSubmitForm(frame, form); | |
1231 } | 1206 } |
1232 | 1207 |
1233 } // namespace autofill | 1208 } // namespace autofill |
OLD | NEW |