Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: components/autofill/content/renderer/password_autofill_agent.cc

Issue 707173004: Refactor Autofill for out of process iframes (OOPIF). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698