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

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

Powered by Google App Engine
This is Rietveld 408576698