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

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: mem leak Created 6 years 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 submitted_form->username_value = 881 submitted_form->username_value =
886 provisionally_saved_forms_[frame]->username_value; 882 provisionally_saved_form_->username_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 *submitted_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_FORM_IS_NOT_PASSWORD); 893 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
899 } 894 }
900 } 895 }
901 896
902 blink::WebFrame* PasswordAutofillAgent::CurrentOrChildFrameWithSavedForms( 897 void PasswordAutofillAgent::LegacyDidStartProvisionalLoad(
903 const blink::WebFrame* current_frame) { 898 blink::WebLocalFrame* navigated_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; 899 scoped_ptr<RendererSavePasswordProgressLogger> logger;
926 if (logging_state_active_) { 900 if (logging_state_active_) {
927 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id())); 901 logger.reset(new RendererSavePasswordProgressLogger(this, routing_id()));
928 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD); 902 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
929 } 903 }
930 904
931 if (!frame->parent()) { 905 if (navigated_frame->parent()) {
932 // If the navigation is not triggered by a user gesture, e.g. by some ajax 906 if (logger)
933 // callback, then inherit the submitted password form from the previous 907 logger->LogMessage(Logger::STRING_FRAME_NOT_MAIN_FRAME);
934 // state. This fixes the no password save issue for ajax login, tracked in 908 return;
935 // [http://crbug/43219]. Note that this still fails for sites that use 909 }
936 // synchonous XHR as isProcessingUserGesture() will return true. 910
937 blink::WebFrame* form_frame = CurrentOrChildFrameWithSavedForms(frame); 911 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when
938 if (logger) { 912 // the user is performing actions outside the page (e.g. typed url,
939 logger->LogBoolean(Logger::STRING_FORM_FRAME_EQ_FRAME, 913 // history navigation). We don't want to trigger saving in these cases.
940 form_frame == frame); 914 content::DocumentState* document_state =
941 } 915 content::DocumentState::FromDataSource(
942 // Bug fix for crbug.com/368690. isProcessingUserGesture() is false when 916 navigated_frame->provisionalDataSource());
943 // the user is performing actions outside the page (e.g. typed url, 917 content::NavigationState* navigation_state =
944 // history navigation). We don't want to trigger saving in these cases. 918 document_state->navigation_state();
945 content::DocumentState* document_state = 919 if (ui::PageTransitionIsWebTriggerable(navigation_state->transition_type()) &&
946 content::DocumentState::FromDataSource( 920 !blink::WebUserGestureIndicator::isProcessingUserGesture()) {
947 frame->provisionalDataSource()); 921 // If onsubmit has been called, try and save that form.
948 content::NavigationState* navigation_state = 922 if (provisionally_saved_form_) {
949 document_state->navigation_state(); 923 if (logger) {
950 if (ui::PageTransitionIsWebTriggerable( 924 logger->LogPasswordForm(
951 navigation_state->transition_type()) && 925 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
952 !blink::WebUserGestureIndicator::isProcessingUserGesture()) { 926 *provisionally_saved_form_);
953 // If onsubmit has been called, try and save that form. 927 }
954 if (ContainsNonNullEntryForNonNullKey(provisionally_saved_forms_, 928 Send(new AutofillHostMsg_PasswordFormSubmitted(
955 form_frame)) { 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 render_frame()->GetWebFrame()->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_PASSWORD_FORM_NOT_FOUND_ON_PAGE);
993 } 955 }
994 } 956 }
957 if (!password_forms_found && logger)
958 logger->LogMessage(Logger::STRING_PASSWORD_FORM_NOT_FOUND_ON_PAGE);
995 } 959 }
996 // Clear the whole map during main frame navigation. 960 }
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_FRAME_NOT_MAIN_FRAME);
1005 }
1006 } 965 }
1007 966
1008 void PasswordAutofillAgent::OnFillPasswordForm( 967 void PasswordAutofillAgent::OnFillPasswordForm(
1009 int key, 968 int key,
1010 const PasswordFormFillData& form_data) { 969 const PasswordFormFillData& form_data) {
1011 if (usernames_usage_ == NOTHING_TO_AUTOFILL) { 970 if (usernames_usage_ == NOTHING_TO_AUTOFILL) {
1012 if (form_data.other_possible_usernames.size()) 971 if (form_data.other_possible_usernames.size())
1013 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT; 972 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_PRESENT;
1014 else if (usernames_usage_ == NOTHING_TO_AUTOFILL) 973 else if (usernames_usage_ == NOTHING_TO_AUTOFILL)
1015 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT; 974 usernames_usage_ = OTHER_POSSIBLE_USERNAMES_ABSENT;
1016 } 975 }
1017 976
1018 FormElementsList forms; 977 FormElementsList forms;
1019 // We own the FormElements* in forms. 978 // We own the FormElements* in forms.
1020 FindFormElements(render_view()->GetWebView(), form_data, &forms); 979 FindFormElements(render_frame(), form_data, &forms);
1021 FormElementsList::iterator iter; 980 FormElementsList::iterator iter;
1022 for (iter = forms.begin(); iter != forms.end(); ++iter) { 981 for (iter = forms.begin(); iter != forms.end(); ++iter) {
1023 scoped_ptr<FormElements> form_elements(*iter); 982 scoped_ptr<FormElements> form_elements(*iter);
1024 983
1025 // Attach autocomplete listener to enable selecting alternate logins. 984 // Attach autocomplete listener to enable selecting alternate logins.
1026 blink::WebInputElement username_element, password_element; 985 blink::WebInputElement username_element, password_element;
1027 986
1028 // Check whether the password form has a username input field. 987 // Check whether the password form has a username input field.
1029 bool form_contains_username_field = FillDataContainsUsername(form_data); 988 bool form_contains_username_field = FillDataContainsUsername(form_data);
1030 if (form_contains_username_field) { 989 if (form_contains_username_field) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 FindFormAndFieldForFormControlElement( 1054 FindFormAndFieldForFormControlElement(
1096 user_input, &form, &field, REQUIRE_NONE); 1055 user_input, &form, &field, REQUIRE_NONE);
1097 1056
1098 blink::WebInputElement selected_element = user_input; 1057 blink::WebInputElement selected_element = user_input;
1099 gfx::Rect bounding_box(selected_element.boundsInViewportSpace()); 1058 gfx::Rect bounding_box(selected_element.boundsInViewportSpace());
1100 1059
1101 LoginToPasswordInfoKeyMap::const_iterator key_it = 1060 LoginToPasswordInfoKeyMap::const_iterator key_it =
1102 login_to_password_info_key_.find(user_input); 1061 login_to_password_info_key_.find(user_input);
1103 DCHECK(key_it != login_to_password_info_key_.end()); 1062 DCHECK(key_it != login_to_password_info_key_.end());
1104 1063
1105 float scale = web_view_->pageScaleFactor(); 1064 float scale =
1065 render_frame()->GetRenderView()->GetWebView()->pageScaleFactor();
1106 gfx::RectF bounding_box_scaled(bounding_box.x() * scale, 1066 gfx::RectF bounding_box_scaled(bounding_box.x() * scale,
1107 bounding_box.y() * scale, 1067 bounding_box.y() * scale,
1108 bounding_box.width() * scale, 1068 bounding_box.width() * scale,
1109 bounding_box.height() * scale); 1069 bounding_box.height() * scale);
1110 Send(new AutofillHostMsg_ShowPasswordSuggestions( 1070 Send(new AutofillHostMsg_ShowPasswordSuggestions(
1111 routing_id(), key_it->second, field.text_direction, user_input.value(), 1071 routing_id(), key_it->second, field.text_direction, user_input.value(),
1112 show_all, bounding_box_scaled)); 1072 show_all, bounding_box_scaled));
1113 1073
1114 bool suggestions_present = false; 1074 bool suggestions_present = false;
1115 if (GetSuggestionsStats(fill_data, user_input.value(), show_all, 1075 if (GetSuggestionsStats(fill_data, user_input.value(), show_all,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1148 fill_data, 1108 fill_data,
1149 false /* exact_username_match */, 1109 false /* exact_username_match */,
1150 true /* set_selection */, 1110 true /* set_selection */,
1151 base::Bind(&PasswordValueGatekeeper::RegisterElement, 1111 base::Bind(&PasswordValueGatekeeper::RegisterElement,
1152 base::Unretained(&gatekeeper_)))) { 1112 base::Unretained(&gatekeeper_)))) {
1153 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED; 1113 usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
1154 } 1114 }
1155 #endif 1115 #endif
1156 } 1116 }
1157 1117
1158 void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) { 1118 void PasswordAutofillAgent::FrameClosing() {
1159 for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin(); 1119 for (auto const& iter : login_to_password_info_) {
1160 iter != login_to_password_info_.end();) { 1120 login_to_password_info_key_.erase(iter.first);
1161 // There may not be a username field, so get the frame from the password 1121 password_to_username_.erase(iter.second.password_field);
1162 // field.
1163 if (iter->second.password_field.document().frame() == frame) {
1164 login_to_password_info_key_.erase(iter->first);
1165 password_to_username_.erase(iter->second.password_field);
1166 login_to_password_info_.erase(iter++);
1167 } else {
1168 ++iter;
1169 }
1170 } 1122 }
1171 for (FrameToPasswordFormMap::iterator iter = 1123 login_to_password_info_.clear();
1172 provisionally_saved_forms_.begin(); 1124 provisionally_saved_form_.reset();
1173 iter != provisionally_saved_forms_.end();) {
1174 if (iter->first == frame)
1175 provisionally_saved_forms_.erase(iter++);
1176 else
1177 ++iter;
1178 }
1179 } 1125 }
1180 1126
1181 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node, 1127 bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node,
1182 blink::WebInputElement* found_input, 1128 blink::WebInputElement* found_input,
1183 PasswordInfo** found_password) { 1129 PasswordInfo** found_password) {
1184 if (!node.isElementNode()) 1130 if (!node.isElementNode())
1185 return false; 1131 return false;
1186 1132
1187 blink::WebElement element = node.toConst<blink::WebElement>(); 1133 blink::WebElement element = node.toConst<blink::WebElement>();
1188 if (!element.hasHTMLTagName("input")) 1134 if (!element.hasHTMLTagName("input"))
(...skipping 18 matching lines...) Expand all
1207 username->setSelectionRange(username_selection_start_, 1153 username->setSelectionRange(username_selection_start_,
1208 username->value().length()); 1154 username->value().length());
1209 } 1155 }
1210 if (!password->suggestedValue().isEmpty()) { 1156 if (!password->suggestedValue().isEmpty()) {
1211 password->setSuggestedValue(blink::WebString()); 1157 password->setSuggestedValue(blink::WebString());
1212 password->setAutofilled(was_password_autofilled_); 1158 password->setAutofilled(was_password_autofilled_);
1213 } 1159 }
1214 } 1160 }
1215 1161
1216 void PasswordAutofillAgent::ProvisionallySavePassword( 1162 void PasswordAutofillAgent::ProvisionallySavePassword(
1217 blink::WebLocalFrame* frame,
1218 const blink::WebFormElement& form, 1163 const blink::WebFormElement& form,
1219 ProvisionallySaveRestriction restriction) { 1164 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)); 1165 scoped_ptr<PasswordForm> password_form(CreatePasswordForm(form));
1229 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD && 1166 if (!password_form || (restriction == RESTRICTION_NON_EMPTY_PASSWORD &&
1230 password_form->password_value.empty() && 1167 password_form->password_value.empty() &&
1231 password_form->new_password_value.empty())) { 1168 password_form->new_password_value.empty())) {
1232 return; 1169 return;
1233 } 1170 }
1234 provisionally_saved_forms_[frame].reset(password_form.release()); 1171 provisionally_saved_form_ = password_form.Pass();
1172 }
1173
1174 // LegacyPasswordAutofillAgent -------------------------------------------------
1175
1176 PasswordAutofillAgent::LegacyPasswordAutofillAgent::LegacyPasswordAutofillAgent(
1177 content::RenderView* render_view,
1178 PasswordAutofillAgent* agent)
1179 : content::RenderViewObserver(render_view), agent_(agent) {
1180 }
1181
1182 PasswordAutofillAgent::LegacyPasswordAutofillAgent::
1183 ~LegacyPasswordAutofillAgent() {
1184 }
1185
1186 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::OnDestruct() {
1187 // No op. Do not delete |this|.
1188 }
1189
1190 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStartLoading() {
1191 agent_->DidStartLoading();
1192 }
1193
1194 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::DidStopLoading() {
1195 agent_->DidStopLoading();
1196 }
1197
1198 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::
1199 DidStartProvisionalLoad(blink::WebLocalFrame* navigated_frame) {
1200 agent_->LegacyDidStartProvisionalLoad(navigated_frame);
1201 }
1202
1203 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::FrameDetached(
1204 blink::WebFrame* frame) {
1205 agent_->FrameDetached(frame);
1206 }
1207
1208 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSendSubmitEvent(
1209 blink::WebLocalFrame* frame,
1210 const blink::WebFormElement& form) {
1211 agent_->WillSendSubmitEvent(frame, form);
1212 }
1213
1214 void PasswordAutofillAgent::LegacyPasswordAutofillAgent::WillSubmitForm(
1215 blink::WebLocalFrame* frame,
1216 const blink::WebFormElement& form) {
1217 agent_->WillSubmitForm(frame, form);
1235 } 1218 }
1236 1219
1237 } // namespace autofill 1220 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698