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

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: update tests some more 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 } 724 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) { 781 bool PasswordAutofillAgent::OnMessageReceived(const IPC::Message& message) {
789 bool handled = true; 782 bool handled = true;
790 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message) 783 IPC_BEGIN_MESSAGE_MAP(PasswordAutofillAgent, message)
791 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm) 784 IPC_MESSAGE_HANDLER(AutofillMsg_FillPasswordForm, OnFillPasswordForm)
792 IPC_MESSAGE_HANDLER(AutofillMsg_SetLoggingState, OnSetLoggingState) 785 IPC_MESSAGE_HANDLER(AutofillMsg_SetLoggingState, OnSetLoggingState)
793 IPC_MESSAGE_UNHANDLED(handled = false) 786 IPC_MESSAGE_UNHANDLED(handled = false)
794 IPC_END_MESSAGE_MAP() 787 IPC_END_MESSAGE_MAP()
795 return handled; 788 return handled;
796 } 789 }
797 790
791 void PasswordAutofillAgent::DidFinishDocumentLoad() {
792 // The |frame| contents have been parsed, but not yet rendered. Let the
793 // PasswordManager know that forms are loaded, even though we can't yet tell
794 // whether they're visible.
795 SendPasswordForms(false);
796 }
797
798 void PasswordAutofillAgent::DidFinishLoad() {
799 // The |frame| contents have been rendered. Let the PasswordManager know
800 // which of the loaded frames are actually visible to the user. This also
801 // triggers the "Save password?" infobar if the user just submitted a password
802 // form.
803 SendPasswordForms(true);
804 }
805
806 void PasswordAutofillAgent::FrameWillClose() {
807 FrameClosing();
808 }
809
798 void PasswordAutofillAgent::DidStartLoading() { 810 void PasswordAutofillAgent::DidStartLoading() {
799 did_stop_loading_ = false; 811 did_stop_loading_ = false;
800 if (usernames_usage_ != NOTHING_TO_AUTOFILL) { 812 if (usernames_usage_ != NOTHING_TO_AUTOFILL) {
801 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage", 813 UMA_HISTOGRAM_ENUMERATION("PasswordManager.OtherPossibleUsernamesUsage",
802 usernames_usage_, 814 usernames_usage_, OTHER_POSSIBLE_USERNAMES_MAX);
803 OTHER_POSSIBLE_USERNAMES_MAX);
804 usernames_usage_ = NOTHING_TO_AUTOFILL; 815 usernames_usage_ = NOTHING_TO_AUTOFILL;
805 } 816 }
806 } 817 }
807 818
808 void PasswordAutofillAgent::DidFinishDocumentLoad(blink::WebLocalFrame* frame) {
809 // The |frame| contents have been parsed, but not yet rendered. Let the
810 // PasswordManager know that forms are loaded, even though we can't yet tell
811 // whether they're visible.
812 SendPasswordForms(frame, false);
813 }
814
815 void PasswordAutofillAgent::DidFinishLoad(blink::WebLocalFrame* frame) {
816 // The |frame| contents have been rendered. Let the PasswordManager know
817 // which of the loaded frames are actually visible to the user. This also
818 // triggers the "Save password?" infobar if the user just submitted a password
819 // form.
820 SendPasswordForms(frame, true);
821 }
822
823 void PasswordAutofillAgent::DidStopLoading() { 819 void PasswordAutofillAgent::DidStopLoading() {
824 did_stop_loading_ = true; 820 did_stop_loading_ = true;
825 } 821 }
826 822
827 void PasswordAutofillAgent::FrameDetached(blink::WebFrame* frame) { 823 void PasswordAutofillAgent::FrameDetached(blink::WebFrame* frame) {
828 FrameClosing(frame); 824 if (frame == render_frame()->GetWebFrame())
829 } 825 FrameClosing();
830
831 void PasswordAutofillAgent::FrameWillClose(blink::WebFrame* frame) {
832 FrameClosing(frame);
833 } 826 }
834 827
835 void PasswordAutofillAgent::WillSendSubmitEvent( 828 void PasswordAutofillAgent::WillSendSubmitEvent(
836 blink::WebLocalFrame* frame, 829 blink::WebLocalFrame* frame,
837 const blink::WebFormElement& form) { 830 const blink::WebFormElement& form) {
831 if (frame != render_frame()->GetWebFrame())
832 return;
838 // Forms submitted via XHR are not seen by WillSubmitForm if the default 833 // Forms submitted via XHR are not seen by WillSubmitForm if the default
839 // onsubmit handler is overridden. Such submission first gets detected in 834 // onsubmit handler is overridden. Such submission first gets detected in
840 // DidStartProvisionalLoad, which no longer knows about the particular form, 835 // DidStartProvisionalLoad, which no longer knows about the particular form,
841 // and uses the candidate stored in |provisionally_saved_forms_|. 836 // and uses the candidate stored in |provisionally_saved_form_|.
842 // 837 //
843 // User-typed password will get stored to |provisionally_saved_forms_| in 838 // User-typed password will get stored to |provisionally_saved_form_| in
844 // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to 839 // TextDidChangeInTextField. Autofilled or JavaScript-copied passwords need to
845 // be saved here. 840 // be saved here.
846 // 841 //
847 // Only non-empty passwords are saved here. Empty passwords were likely 842 // Only non-empty passwords are saved here. Empty passwords were likely
848 // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693). 843 // cleared by some scripts (http://crbug.com/28910, http://crbug.com/391693).
849 // Had the user cleared the password, |provisionally_saved_forms_| would 844 // Had the user cleared the password, |provisionally_saved_form_| would
850 // already have been updated in TextDidChangeInTextField. 845 // already have been updated in TextDidChangeInTextField.
851 ProvisionallySavePassword(frame, form, RESTRICTION_NON_EMPTY_PASSWORD); 846 ProvisionallySavePassword(form, RESTRICTION_NON_EMPTY_PASSWORD);
852 } 847 }
853 848
854 void PasswordAutofillAgent::WillSubmitForm(blink::WebLocalFrame* frame, 849 void PasswordAutofillAgent::WillSubmitForm(blink::WebLocalFrame* frame,
855 const blink::WebFormElement& form) { 850 const blink::WebFormElement& form) {
856 DCHECK(frame); 851 if (frame != render_frame()->GetWebFrame())
852 return;
853
857 scoped_ptr<RendererSavePasswordProgressLogger> logger; 854 scoped_ptr<RendererSavePasswordProgressLogger> logger;
858 if (logging_state_active_) { 855 if (logging_state_active_) {
859 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); 856 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
860 logger->LogMessage(Logger::STRING_WILL_SUBMIT_FORM_METHOD); 857 logger->LogMessage(Logger::STRING_WILL_SUBMIT_FORM_METHOD);
861 LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form); 858 LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form);
862 } 859 }
863 860
864 scoped_ptr<PasswordForm> submitted_form = CreatePasswordForm(form); 861 scoped_ptr<PasswordForm> submitted_form = CreatePasswordForm(form);
865 862
866 // If there is a provisionally saved password, copy over the previous 863 // If there is a provisionally saved password, copy over the previous
867 // password value so we get the user's typed password, not the value that 864 // password value so we get the user's typed password, not the value that
868 // may have been transformed for submit. 865 // may have been transformed for submit.
869 // TODO(gcasto): Do we need to have this action equality check? Is it trying 866 // TODO(gcasto): Do we need to have this action equality check? Is it trying
870 // to prevent accidentally copying over passwords from a different form? 867 // to prevent accidentally copying over passwords from a different form?
871 if (submitted_form) { 868 if (submitted_form) {
872 if (logger) { 869 if (logger) {
873 logger->LogPasswordForm(Logger::STRING_CREATED_PASSWORD_FORM, 870 logger->LogPasswordForm(Logger::STRING_CREATED_PASSWORD_FORM,
874 *submitted_form); 871 *submitted_form);
875 } 872 }
876 if (ContainsNonNullEntryForNonNullKey( 873 if (provisionally_saved_form_ &&
877 provisionally_saved_forms_, static_cast<blink::WebFrame*>(frame)) && 874 submitted_form->action == provisionally_saved_form_->action) {
878 submitted_form->action == provisionally_saved_forms_[frame]->action) {
879 if (logger) 875 if (logger)
880 logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED); 876 logger->LogMessage(Logger::STRING_SUBMITTED_PASSWORD_REPLACED);
881 submitted_form->password_value = 877 submitted_form->password_value =
882 provisionally_saved_forms_[frame]->password_value; 878 provisionally_saved_form_->password_value;
883 submitted_form->new_password_value = 879 submitted_form->new_password_value =
884 provisionally_saved_forms_[frame]->new_password_value; 880 provisionally_saved_form_->new_password_value;
885 } 881 }
886 882
887 // Some observers depend on sending this information now instead of when 883 // Some observers depend on sending this information now instead of when
888 // the frame starts loading. If there are redirects that cause a new 884 // the frame starts loading. If there are redirects that cause a new
889 // RenderView to be instantiated (such as redirects to the WebStore) 885 // RenderView to be instantiated (such as redirects to the WebStore)
890 // we will never get to finish the load. 886 // we will never get to finish the load.
891 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(), 887 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(),
892 *submitted_form)); 888 *provisionally_saved_form_));
893 // Remove reference since we have already submitted this form. 889 provisionally_saved_form_.reset();
894 provisionally_saved_forms_.erase(frame);
895 } else if (logger) { 890 } else if (logger) {
896 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD); 891 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
897 } 892 }
898 } 893 }
899 894
900 blink::WebFrame* PasswordAutofillAgent::CurrentOrChildFrameWithSavedForms( 895 void PasswordAutofillAgent::DidStartProvisionalLoad() {
901 const blink::WebFrame* current_frame) {
902 for (FrameToPasswordFormMap::const_iterator it =
903 provisionally_saved_forms_.begin();
904 it != provisionally_saved_forms_.end();
905 ++it) {
906 blink::WebFrame* form_frame = it->first;
907 // The check that the returned frame is related to |current_frame| is mainly
908 // for double-checking. There should not be any unrelated frames in
909 // |provisionally_saved_forms_|, because the map is cleared after
910 // navigation. If there are reasons to remove this check in the future and
911 // keep just the first frame found, it might be a good idea to add a UMA
912 // statistic or a similar check on how many frames are here to choose from.
913 if (current_frame == form_frame ||
914 current_frame->findChildByName(form_frame->assignedName())) {
915 return form_frame;
916 }
917 }
918 return NULL;
919 }
920
921 void PasswordAutofillAgent::DidStartProvisionalLoad(
922 blink::WebLocalFrame* frame) {
923 scoped_ptr<RendererSavePasswordProgressLogger> logger; 896 scoped_ptr<RendererSavePasswordProgressLogger> logger;
924 if (logging_state_active_) { 897 if (logging_state_active_) {
925 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); 898 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
926 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD); 899 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
927 } 900 }
928 901
929 if (!frame->parent()) { 902 blink::WebFrame* frame = render_frame()->GetWebFrame();
930 // If the navigation is not triggered by a user gesture, e.g. by some ajax 903
931 // callback, then inherit the submitted password form from the previous 904 if (frame->parent()) {
932 // state. This fixes the no password save issue for ajax login, tracked in 905 if (logger)
933 // [http://crbug/43219]. Note that this still fails for sites that use 906 logger->LogMessage(Logger::STRING_FRAME_NOT_MAIN_FRAME);
934 // synchonous XHR as isProcessingUserGesture() will return true. 907 return;
935 blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame); 908 }
936 if (logger) { 909
937 logger->LogBoolean(Logger::STRING_FORM_FRAME_EQ_FRAME, 910 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when
vabr (Chromium) 2014/11/21 09:31:52 Please remove STRING_FORM_FRAME_EQ_FRAME also from
938 form_frame == frame); 911 // the user is performing actions outside the page (e.g. typed url,
939 } 912 // history navigation). We don't want to trigger saving in these cases.
940 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when 913 content::DocumentState* document_state =
941 // the user is performing actions outside the page (e.g. typed url, 914 content::DocumentState::FromDataSource(frame->provisionalDataSource());
942 // history navigation). We don't want to trigger saving in these cases. 915 content::NavigationState* navigation_state =
943 content::DocumentState* document_state = 916 document_state->navigation_state();
944 content::DocumentState::FromDataSource( 917 if (ui::PageTransitionIsWebTriggerable(navigation_state->transition_type()) &&
945 frame->provisionalDataSource()); 918 !blink::WebUserGestureIndicator::isProcessingUserGesture()) {
946 content::NavigationState* navigation_state = 919 // If onsubmit has been called, try and save that form.
947 document_state->navigation_state(); 920 if (provisionally_saved_form_) {
948 if (ui::PageTransitionIsWebTriggerable( 921 if (logger) {
949 navigation_state->transition_type()) && 922 logger->LogPasswordForm(
950 !blink::WebUserGestureIndicator::isProcessingUserGesture()) { 923 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
951 // If onsubmit has been called, try and save that form. 924 *provisionally_saved_form_);
952 if (ContainsNonNullEntryForNonNullKey(provisionally_saved_forms_, 925 }
953 form_frame)) { 926 Send(new AutofillHostMsg_PasswordFormSubmitted(
927 routing_id(), *provisionally_saved_form_));
928 provisionally_saved_form_.reset();
929 } else {
930 // Loop through the forms on the page looking for one that has been
931 // filled out. If one exists, try and save the credentials.
932 blink::WebVector<blink::WebFormElement> forms;
933 frame->document().forms(forms);
934
935 bool password_forms_found = false;
936 for (size_t i = 0; i < forms.size(); ++i) {
937 blink::WebFormElement form_element = forms[i];
954 if (logger) { 938 if (logger) {
955 logger->LogPasswordForm( 939 LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE,
956 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME, 940 form_element);
957 *provisionally_saved_forms_[form_frame]);
958 } 941 }
959 Send(new AutofillHostMsg_PasswordFormSubmitted( 942 scoped_ptr<PasswordForm> password_form(
960 routing_id(), *provisionally_saved_forms_[form_frame])); 943 CreatePasswordForm(form_element));
961 provisionally_saved_forms_.erase(form_frame); 944 if (password_form.get() && !password_form->username_value.empty() &&
962 } else { 945 FormContainsNonDefaultPasswordValue(
963 // Loop through the forms on the page looking for one that has been 946 *password_form, form_element)) {
964 // filled out. If one exists, try and save the credentials. 947 password_forms_found = true;
965 blink::WebVector<blink::WebFormElement> forms;
966 frame->document().forms(forms);
967
968 bool password_forms_found = false;
969 for (size_t i = 0; i < forms.size(); ++i) {
970 blink::WebFormElement form_element = forms[i];
971 if (logger) { 948 if (logger) {
972 LogHTMLForm( 949 logger->LogPasswordForm(
973 logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form_element); 950 Logger::STRING_PASSWORD_FORM_FOUND_ON_PAGE, *password_form);
974 } 951 }
975 scoped_ptr<PasswordForm> password_form( 952 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(),
976 CreatePasswordForm(form_element)); 953 *password_form));
977 if (password_form.get() && !password_form->username_value.empty() &&
978 FormContainsNonDefaultPasswordValue(
979 *password_form, form_element)) {
980 password_forms_found = true;
981 if (logger) {
982 logger->LogPasswordForm(
983 Logger::STRING_PASSWORD_FORM_FOUND_ON_PAGE, *password_form);
984 }
985 Send(new AutofillHostMsg_PasswordFormSubmitted(routing_id(),
986 *password_form));
987 }
988 }
989 if (!password_forms_found && logger) {
990 logger->LogMessage(Logger::STRING_PASSWORD_FORM_NOT_FOUND_ON_PAGE);
991 } 954 }
992 } 955 }
956 if (!password_forms_found && logger)
957 logger->LogMessage(Logger::STRING_PASSWORD_FORM_NOT_FOUND_ON_PAGE);
993 } 958 }
994 // Clear the whole map during main frame navigation. 959 }
995 provisionally_saved_forms_.clear();
996 960
997 // This is a new navigation, so require a new user gesture before filling in 961 // This is a new navigation, so require a new user gesture before filling in
998 // passwords. 962 // passwords.
999 gatekeeper_.Reset(); 963 gatekeeper_.Reset();
1000 } else {
1001 if (logger)
1002 logger->LogMessage(Logger::STRING_FRAME_NOT_MAIN_FRAME);
1003 }
1004 } 964 }
1005 965
1006 void PasswordAutofillAgent::OnFillPasswordForm( 966 void PasswordAutofillAgent::OnFillPasswordForm(
1007 int key, 967 int key,
1008 const PasswordFormFillData& form_data) { 968 const PasswordFormFillData& form_data) {
1009 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { 969 if (usernames_usage_ == NOTHING_TO_AUTOFILL) {
1010 if (form_data.other_possible_usernames.size()) 970 if (form_data.other_possible_usernames.size())
1011 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; 971 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT;
1012 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) 972 else if (usernames_usage_ == NOTHING_TO_AUTOFILL)
1013 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; 973 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT;
1014 } 974 }
1015 975
1016 FormElementsList forms; 976 FormElementsList forms;
1017 // We own the FormElements* in forms. 977 // We own the FormElements* in forms.
1018 FindFormElements(render_view()->GetWebView(), form_data, &forms); 978 FindFormElements(render_frame(), form_data, &forms);
1019 FormElementsList::iterator iter; 979 FormElementsList::iterator iter;
1020 for (iter = forms.begin(); iter != forms.end(); ++iter) { 980 for (iter = forms.begin(); iter != forms.end(); ++iter) {
1021 scoped_ptr<FormElements> form_elements(*iter); 981 scoped_ptr<FormElements> form_elements(*iter);
1022 982
1023 // Attach autocomplete listener to enable selecting alternate logins. 983 // Attach autocomplete listener to enable selecting alternate logins.
1024 blink::WebInputElement username_element, password_element; 984 blink::WebInputElement username_element, password_element;
1025 985
1026 // Check whether the password form has a username input field. 986 // Check whether the password form has a username input field.
1027 bool form_contains_username_field = FillDataContainsUsername(form_data); 987 bool form_contains_username_field = FillDataContainsUsername(form_data);
1028 if (form_contains_username_field) { 988 if (form_contains_username_field) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 FindFormAndFieldForFormControlElement( 1053 FindFormAndFieldForFormControlElement(
1094 user_input, &form, &field, REQUIRE_NONE); 1054 user_input, &form, &field, REQUIRE_NONE);
1095 1055
1096 blink::WebInputElement selected_element = user_input; 1056 blink::WebInputElement selected_element = user_input;
1097 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); 1057 gfx::Rect bounding_box(selected_element.boundsInViewportSpace());
1098 1058
1099 LoginToPasswordInfoKeyMap::const_iterator key_it = 1059 LoginToPasswordInfoKeyMap::const_iterator key_it =
1100 login_to_password_info_key_.find(user_input); 1060 login_to_password_info_key_.find(user_input);
1101 DCHECK(key_it != login_to_password_info_key_.end()); 1061 DCHECK(key_it != login_to_password_info_key_.end());
1102 1062
1103 float scale = web_view_->pageScaleFactor(); 1063 float scale =
1064 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor();
1104 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, 1065 gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
1105 bounding_box.y() * scale, 1066 bounding_box.y() * scale,
1106 bounding_box.width() * scale, 1067 bounding_box.width() * scale,
1107 bounding_box.height() * scale); 1068 bounding_box.height() * scale);
1108 Send(new AutofillHostMsg_ShowPasswordSuggestions( 1069 Send(new AutofillHostMsg_ShowPasswordSuggestions(
1109 routing_id(), key_it->second, field.text_direction, user_input.value(), 1070 routing_id(), key_it->second, field.text_direction, user_input.value(),
1110 show_all, bounding_box_scaled)); 1071 show_all, bounding_box_scaled));
1111 1072
1112 bool suggestions_present = false; 1073 bool suggestions_present = false;
1113 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, 1074 if (GetSuggestionsStats(fill_data, user_input.value(), show_all,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 fill_data, 1107 fill_data,
1147 false /* exact_username_match */, 1108 false /* exact_username_match */,
1148 true /* set_selection */, 1109 true /* set_selection */,
1149 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1110 base::Bind(&PasswordValueGatekeeper::RegisterElement,
1150 base::Unretained(&gatekeeper_)))) { 1111 base::Unretained(&gatekeeper_)))) {
1151 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; 1112 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
1152 } 1113 }
1153 #endif 1114 #endif
1154 } 1115 }
1155 1116
1156 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1117 void PasswordAutofillAgent::FrameClosing() {
1157 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1118 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
1158 iter != login_to_password_info_.end();) { 1119 iter != login_to_password_info_.end();) {
1159 // There may not be a username field, so get the frame from the password 1120 // There may not be a username field, so get the frame from the password
1160 // field. 1121 // field.
1161 if (iter->second.password_field.document().frame() == frame) { 1122 DCHECK_EQ(iter->second.password_field.document().frame(),
1162 login_to_password_info_key_.erase(iter->first); 1123 render_frame()->GetWebFrame());
1163 password_to_username_.erase(iter->second.password_field); 1124 login_to_password_info_key_.erase(iter->first);
1164 login_to_password_info_.erase(iter++); 1125 password_to_username_.erase(iter->second.password_field);
1165 } else { 1126 login_to_password_info_.erase(iter++);
1166 ++iter;
1167 }
1168 } 1127 }
1169 for (FrameToPasswordFormMap::iterator iter = 1128 provisionally_saved_form_.reset();
1170 provisionally_saved_forms_.begin();
1171 iter != provisionally_saved_forms_.end();) {
1172 if (iter->first == frame)
1173 provisionally_saved_forms_.erase(iter++);
1174 else
1175 ++iter;
1176 }
1177 } 1129 }
1178 1130
1179 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, 1131 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node,
1180 blink::WebInputElement* found_input, 1132 blink::WebInputElement* found_input,
1181 PasswordInfo** found_password) { 1133 PasswordInfo** found_password) {
1182 if (!node.isElementNode()) 1134 if (!node.isElementNode())
1183 return false; 1135 return false;
1184 1136
1185 blink::WebElement element = node.toConst<blink::WebElement>(); 1137 blink::WebElement element = node.toConst<blink::WebElement>();
1186 if (!element.hasHTMLTagName("input")) 1138 if (!element.hasHTMLTagName("input"))
(...skipping 18 matching lines...) Expand all
1205 username->setSelectionRange(username_selection_start_, 1157 username->setSelectionRange(username_selection_start_,
1206 username->value().length()); 1158 username->value().length());
1207 } 1159 }
1208 if (!password->suggestedValue().isEmpty()) { 1160 if (!password->suggestedValue().isEmpty()) {
1209 password->setSuggestedValue(blink::WebString()); 1161 password->setSuggestedValue(blink::WebString());
1210 password->setAutofilled(was_password_autofilled_); 1162 password->setAutofilled(was_password_autofilled_);
1211 } 1163 }
1212 } 1164 }
1213 1165
1214 void PasswordAutofillAgent::ProvisionallySavePassword( 1166 void PasswordAutofillAgent::ProvisionallySavePassword(
1215 blink::WebLocalFrame* frame,
1216 const blink::WebFormElement& form, 1167 const blink::WebFormElement& form,
1217 ProvisionallySaveRestriction restriction) { 1168 ProvisionallySaveRestriction restriction) {
1218 // TODO(vabr): This is just to stop getting a NULL frame in
1219 // |provisionally_saved_forms_|. Cases where we try to save password for a
1220 // form in a NULL frame should not happen, and it's currently unclear how they
1221 // happen (http://crbug.com/420519). This thing will be hopefully solved by
1222 // migrating the PasswordAutofillAgent to observe frames directly
1223 // (http://crbug.com/400186).
1224 if (!frame)
1225 return;
1226 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form)); 1169 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1227 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1170 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1228 password_form->password_value.empty() && 1171 password_form->password_value.empty() &&
1229 password_form->new_password_value.empty())) { 1172 password_form->new_password_value.empty())) {
1230 return; 1173 return;
1231 } 1174 }
1232 provisionally_saved_forms_[frame].reset(password_form.release()); 1175 provisionally_saved_form_ = password_form.Pass();
1176 }
1177
1178 // LegacyPasswordAutofillAgent -------------------------------------------------
1179
1180 PasswordAutofillAgent::LegacyPasswordAutofillAgent::LegacyPasswordAutofillAgent(
1181 content::RenderView* render_view,
1182 PasswordAutofillAgent* agent)
1183 : content::RenderViewObserver(render_view), agent_(agent) {
1184 }
1185
1186 PasswordAutofillAgent::LegacyPasswordAutofillAgent::
1187 ~LegacyPasswordAutofillAgent() {
1188 }
1189
1190 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::OnDestruct() {
1191 // No op. Do not delete |this|.
1192 }
1193
1194 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStartLoading() {
1195 agent_->DidStartLoading();
1196 }
1197
1198 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() {
1199 agent_->DidStopLoading();
1200 }
1201
1202 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::FrameDetached(
1203 blink::WebFrame* frame) {
1204 agent_->FrameDetached(frame);
1205 }
1206
1207 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSendSubmitEvent(
1208 blink::WebLocalFrame* frame,
1209 const blink::WebFormElement& form) {
1210 agent_->WillSendSubmitEvent(frame, form);
1211 }
1212
1213 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm(
1214 blink::WebLocalFrame* frame,
1215 const blink::WebFormElement& form) {
1216 agent_->WillSubmitForm(frame, form);
1233 } 1217 }
1234 1218
1235 } // namespace autofill 1219 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698