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

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

Issue 2865233003: Use an MutationObserver to check when a password form disappears after XHR (Closed)
Patch Set: updates Created 3 years, 7 months 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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <string> 10 #include <string>
(...skipping 26 matching lines...) Expand all
37 #include "content/public/renderer/render_view.h" 37 #include "content/public/renderer/render_view.h"
38 #include "services/service_manager/public/cpp/binder_registry.h" 38 #include "services/service_manager/public/cpp/binder_registry.h"
39 #include "services/service_manager/public/cpp/interface_provider.h" 39 #include "services/service_manager/public/cpp/interface_provider.h"
40 #include "third_party/WebKit/public/platform/WebInputEvent.h" 40 #include "third_party/WebKit/public/platform/WebInputEvent.h"
41 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" 41 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
42 #include "third_party/WebKit/public/platform/WebVector.h" 42 #include "third_party/WebKit/public/platform/WebVector.h"
43 #include "third_party/WebKit/public/web/WebAutofillClient.h" 43 #include "third_party/WebKit/public/web/WebAutofillClient.h"
44 #include "third_party/WebKit/public/web/WebDocument.h" 44 #include "third_party/WebKit/public/web/WebDocument.h"
45 #include "third_party/WebKit/public/web/WebElement.h" 45 #include "third_party/WebKit/public/web/WebElement.h"
46 #include "third_party/WebKit/public/web/WebFormElement.h" 46 #include "third_party/WebKit/public/web/WebFormElement.h"
47 #include "third_party/WebKit/public/web/WebFormElementObserverCallback.h"
47 #include "third_party/WebKit/public/web/WebLocalFrame.h" 48 #include "third_party/WebKit/public/web/WebLocalFrame.h"
48 #include "third_party/WebKit/public/web/WebNode.h" 49 #include "third_party/WebKit/public/web/WebNode.h"
49 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 50 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
50 #include "third_party/WebKit/public/web/WebView.h" 51 #include "third_party/WebKit/public/web/WebView.h"
51 #include "ui/base/page_transition_types.h" 52 #include "ui/base/page_transition_types.h"
52 #include "ui/events/keycodes/keyboard_codes.h" 53 #include "ui/events/keycodes/keyboard_codes.h"
53 #include "url/gurl.h" 54 #include "url/gurl.h"
54 55
55 namespace autofill { 56 namespace autofill {
56 namespace { 57 namespace {
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 element.To<blink::WebFormControlElement>(); 612 element.To<blink::WebFormControlElement>();
612 if (control.FormControlType() == kPassword) 613 if (control.FormControlType() == kPassword)
613 return true; 614 return true;
614 } 615 }
615 } 616 }
616 return false; 617 return false;
617 } 618 }
618 619
619 } // namespace 620 } // namespace
620 621
622 class PasswordAutofillAgent::FormElementObserver
623 : public blink::WebFormElementObserverCallback {
624 public:
625 explicit FormElementObserver(PasswordAutofillAgent* agent) : agent_(agent) {}
626 ~FormElementObserver() override { Detach(); }
627
628 void Detach() {
629 if (agent_) {
630 DCHECK_EQ(agent_->form_element_observer_, this);
631 agent_->form_element_observer_ = nullptr;
632 }
633 agent_ = nullptr;
634 }
635
636 void ElementWasHiddenOrRemoved() override {
637 if (!agent_)
638 return;
639 agent_->OnSameDocumentNavigationCompleted(
640 PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
641 // The above call will delete "this".
642 }
643
644 private:
645 PasswordAutofillAgent* agent_;
646
647 DISALLOW_COPY_AND_ASSIGN(FormElementObserver);
648 };
649
621 //////////////////////////////////////////////////////////////////////////////// 650 ////////////////////////////////////////////////////////////////////////////////
622 // PasswordAutofillAgent, public: 651 // PasswordAutofillAgent, public:
623 652
624 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame) 653 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame)
625 : content::RenderFrameObserver(render_frame), 654 : content::RenderFrameObserver(render_frame),
626 logging_state_active_(false), 655 logging_state_active_(false),
627 was_username_autofilled_(false), 656 was_username_autofilled_(false),
628 was_password_autofilled_(false), 657 was_password_autofilled_(false),
629 sent_request_to_store_(false), 658 sent_request_to_store_(false),
630 checked_safe_browsing_reputation_(false), 659 checked_safe_browsing_reputation_(false),
631 binding_(this) { 660 binding_(this),
661 form_element_observer_(nullptr) {
632 // PasswordAutofillAgent is guaranteed to outlive |render_frame|. 662 // PasswordAutofillAgent is guaranteed to outlive |render_frame|.
633 render_frame->GetInterfaceRegistry()->AddInterface( 663 render_frame->GetInterfaceRegistry()->AddInterface(
634 base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this))); 664 base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
635 } 665 }
636 666
637 PasswordAutofillAgent::~PasswordAutofillAgent() { 667 PasswordAutofillAgent::~PasswordAutofillAgent() {
668 if (form_element_observer_)
669 form_element_observer_->Detach();
638 } 670 }
639 671
640 void PasswordAutofillAgent::BindRequest( 672 void PasswordAutofillAgent::BindRequest(
641 const service_manager::BindSourceInfo& source_info, 673 const service_manager::BindSourceInfo& source_info,
642 mojom::PasswordAutofillAgentRequest request) { 674 mojom::PasswordAutofillAgentRequest request) {
643 binding_.Bind(std::move(request)); 675 binding_.Bind(std::move(request));
644 } 676 }
645 677
646 void PasswordAutofillAgent::SetAutofillAgent(AutofillAgent* autofill_agent) { 678 void PasswordAutofillAgent::SetAutofillAgent(AutofillAgent* autofill_agent) {
647 autofill_agent_ = autofill_agent; 679 autofill_agent_ = autofill_agent;
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( 1057 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
1026 const blink::WebSecurityOrigin& origin) { 1058 const blink::WebSecurityOrigin& origin) {
1027 return origin.CanAccessPasswordManager(); 1059 return origin.CanAccessPasswordManager();
1028 } 1060 }
1029 1061
1030 void PasswordAutofillAgent::OnDynamicFormsSeen() { 1062 void PasswordAutofillAgent::OnDynamicFormsSeen() {
1031 SendPasswordForms(false /* only_visible */); 1063 SendPasswordForms(false /* only_visible */);
1032 } 1064 }
1033 1065
1034 void PasswordAutofillAgent::AJAXSucceeded() { 1066 void PasswordAutofillAgent::AJAXSucceeded() {
1035 OnSameDocumentNavigationCompleted(false); 1067 OnSameDocumentNavigationCompleted(
1068 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
1036 } 1069 }
1037 1070
1038 void PasswordAutofillAgent::OnSameDocumentNavigationCompleted( 1071 void PasswordAutofillAgent::OnSameDocumentNavigationCompleted(
1039 bool is_inpage_navigation) { 1072 PasswordForm::SubmissionIndicatorEvent event) {
1040 if (!provisionally_saved_form_.IsPasswordValid()) 1073 if (!provisionally_saved_form_.IsPasswordValid())
1041 return; 1074 return;
1042 1075
1043 provisionally_saved_form_.SetSubmissionIndicatorEvent(
1044 is_inpage_navigation
1045 ? PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION
1046 : PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
1047
1048 // Prompt to save only if the form is now gone, either invisible or 1076 // Prompt to save only if the form is now gone, either invisible or
1049 // removed from the DOM. 1077 // removed from the DOM.
1050 blink::WebFrame* frame = render_frame()->GetWebFrame(); 1078 blink::WebFrame* frame = render_frame()->GetWebFrame();
1051 const auto& password_form = provisionally_saved_form_.password_form(); 1079 const auto& password_form = provisionally_saved_form_.password_form();
1052 // TODO(crbug.com/720347): This method could be called often and checking form 1080 // TODO(crbug.com/720347): This method could be called often and checking form
1053 // visibility could be expesive. Add performance metrics for this. 1081 // visibility could be expesive. Add performance metrics for this.
1054 if (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(), 1082 if (event != PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR &&
1055 password_form.action, password_form.origin, 1083 (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(),
1056 password_form.form_data) || 1084 password_form.action, password_form.origin,
1057 (provisionally_saved_form_.form_element().IsNull() && 1085 password_form.form_data) ||
1058 IsUnownedPasswordFormVisible( 1086 (provisionally_saved_form_.form_element().IsNull() &&
1059 frame, provisionally_saved_form_.input_element(), 1087 IsUnownedPasswordFormVisible(
1060 password_form.action, password_form.origin, password_form.form_data, 1088 frame, provisionally_saved_form_.input_element(),
1061 form_predictions_))) { 1089 password_form.action, password_form.origin, password_form.form_data,
1090 form_predictions_)))) {
1091 if (!form_element_observer_) {
1092 std::unique_ptr<FormElementObserver> observer(
1093 new FormElementObserver(this));
1094 form_element_observer_ = observer.get();
1095 if (provisionally_saved_form_.form_element().IsNull()) {
1096 provisionally_saved_form_.input_element()
1097 .GetDocument()
1098 .ObserveFormElement(provisionally_saved_form_.input_element(),
1099 std::move(observer));
1100 } else {
1101 provisionally_saved_form_.form_element()
1102 .GetDocument()
1103 .ObserveFormElement(provisionally_saved_form_.form_element(),
1104 std::move(observer));
1105 }
1106 }
1062 return; 1107 return;
1063 } 1108 }
1064 1109
1110 provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
1065 GetPasswordManagerDriver()->InPageNavigation(password_form); 1111 GetPasswordManagerDriver()->InPageNavigation(password_form);
1112 if (form_element_observer_)
1113 form_element_observer_->Detach();
1066 provisionally_saved_form_.Reset(); 1114 provisionally_saved_form_.Reset();
1067 } 1115 }
1068 1116
1069 void PasswordAutofillAgent::UserGestureObserved() { 1117 void PasswordAutofillAgent::UserGestureObserved() {
1070 gatekeeper_.OnUserGesture(); 1118 gatekeeper_.OnUserGesture();
1071 } 1119 }
1072 1120
1073 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) { 1121 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
1074 std::unique_ptr<RendererSavePasswordProgressLogger> logger; 1122 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1075 if (logging_state_active_) { 1123 if (logging_state_active_) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 } 1258 }
1211 1259
1212 void PasswordAutofillAgent::WillCommitProvisionalLoad() { 1260 void PasswordAutofillAgent::WillCommitProvisionalLoad() {
1213 FrameClosing(); 1261 FrameClosing();
1214 } 1262 }
1215 1263
1216 void PasswordAutofillAgent::DidCommitProvisionalLoad( 1264 void PasswordAutofillAgent::DidCommitProvisionalLoad(
1217 bool is_new_navigation, 1265 bool is_new_navigation,
1218 bool is_same_document_navigation) { 1266 bool is_same_document_navigation) {
1219 if (is_same_document_navigation) { 1267 if (is_same_document_navigation) {
1220 OnSameDocumentNavigationCompleted(true); 1268 OnSameDocumentNavigationCompleted(
1269 PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION);
1221 } else { 1270 } else {
1222 checked_safe_browsing_reputation_ = false; 1271 checked_safe_browsing_reputation_ = false;
1223 } 1272 }
1224 } 1273 }
1225 1274
1226 void PasswordAutofillAgent::FrameDetached() { 1275 void PasswordAutofillAgent::FrameDetached() {
1227 // If a sub frame has been destroyed while the user was entering information 1276 // If a sub frame has been destroyed while the user was entering information
1228 // into a password form, try to save the data. See https://crbug.com/450806 1277 // into a password form, try to save the data. See https://crbug.com/450806
1229 // for examples of sites that perform login using this technique. 1278 // for examples of sites that perform login using this technique.
1230 if (render_frame()->GetWebFrame()->Parent() && 1279 if (render_frame()->GetWebFrame()->Parent() &&
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 submitted_form->username_value = saved_form.username_value; 1341 submitted_form->username_value = saved_form.username_value;
1293 submitted_form->submission_event = 1342 submitted_form->submission_event =
1294 PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; 1343 PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION;
1295 } 1344 }
1296 1345
1297 // Some observers depend on sending this information now instead of when 1346 // Some observers depend on sending this information now instead of when
1298 // the frame starts loading. If there are redirects that cause a new 1347 // the frame starts loading. If there are redirects that cause a new
1299 // RenderView to be instantiated (such as redirects to the WebStore) 1348 // RenderView to be instantiated (such as redirects to the WebStore)
1300 // we will never get to finish the load. 1349 // we will never get to finish the load.
1301 GetPasswordManagerDriver()->PasswordFormSubmitted(*submitted_form); 1350 GetPasswordManagerDriver()->PasswordFormSubmitted(*submitted_form);
1351 if (form_element_observer_)
1352 form_element_observer_->Detach();
1302 provisionally_saved_form_.Reset(); 1353 provisionally_saved_form_.Reset();
1303 } else if (logger) { 1354 } else if (logger) {
1304 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD); 1355 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
1305 } 1356 }
1306 } 1357 }
1307 1358
1308 void PasswordAutofillAgent::OnDestruct() { 1359 void PasswordAutofillAgent::OnDestruct() {
1309 binding_.Close(); 1360 binding_.Close();
1310 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); 1361 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
1311 } 1362 }
(...skipping 27 matching lines...) Expand all
1339 !blink::WebUserGestureIndicator::IsProcessingUserGesture()) { 1390 !blink::WebUserGestureIndicator::IsProcessingUserGesture()) {
1340 // If onsubmit has been called, try and save that form. 1391 // If onsubmit has been called, try and save that form.
1341 if (provisionally_saved_form_.IsSet()) { 1392 if (provisionally_saved_form_.IsSet()) {
1342 if (logger) { 1393 if (logger) {
1343 logger->LogPasswordForm( 1394 logger->LogPasswordForm(
1344 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME, 1395 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
1345 provisionally_saved_form_.password_form()); 1396 provisionally_saved_form_.password_form());
1346 } 1397 }
1347 GetPasswordManagerDriver()->PasswordFormSubmitted( 1398 GetPasswordManagerDriver()->PasswordFormSubmitted(
1348 provisionally_saved_form_.password_form()); 1399 provisionally_saved_form_.password_form());
1400 if (form_element_observer_)
1401 form_element_observer_->Detach();
1349 provisionally_saved_form_.Reset(); 1402 provisionally_saved_form_.Reset();
1350 } else { 1403 } else {
1351 std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms; 1404 std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms;
1352 // Loop through the forms on the page looking for one that has been 1405 // Loop through the forms on the page looking for one that has been
1353 // filled out. If one exists, try and save the credentials. 1406 // filled out. If one exists, try and save the credentials.
1354 blink::WebVector<blink::WebFormElement> forms; 1407 blink::WebVector<blink::WebFormElement> forms;
1355 render_frame()->GetWebFrame()->GetDocument().Forms(forms); 1408 render_frame()->GetWebFrame()->GetDocument().Forms(forms);
1356 1409
1357 bool password_forms_found = false; 1410 bool password_forms_found = false;
1358 for (size_t i = 0; i < forms.size(); ++i) { 1411 for (size_t i = 0; i < forms.size(); ++i) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 render_frame()->GetRenderView()->ElementBoundsInWindow(user_input)); 1675 render_frame()->GetRenderView()->ElementBoundsInWindow(user_input));
1623 username_query_prefix_ = username_string; 1676 username_query_prefix_ = username_string;
1624 return CanShowSuggestion(password_info.fill_data, username_string, show_all); 1677 return CanShowSuggestion(password_info.fill_data, username_string, show_all);
1625 } 1678 }
1626 1679
1627 void PasswordAutofillAgent::FrameClosing() { 1680 void PasswordAutofillAgent::FrameClosing() {
1628 for (auto const& iter : web_input_to_password_info_) { 1681 for (auto const& iter : web_input_to_password_info_) {
1629 password_to_username_.erase(iter.second.password_field); 1682 password_to_username_.erase(iter.second.password_field);
1630 } 1683 }
1631 web_input_to_password_info_.clear(); 1684 web_input_to_password_info_.clear();
1685 if (form_element_observer_)
1686 form_element_observer_->Detach();
1632 provisionally_saved_form_.Reset(); 1687 provisionally_saved_form_.Reset();
1633 field_value_and_properties_map_.clear(); 1688 field_value_and_properties_map_.clear();
1634 sent_request_to_store_ = false; 1689 sent_request_to_store_ = false;
1635 checked_safe_browsing_reputation_ = false; 1690 checked_safe_browsing_reputation_ = false;
1636 } 1691 }
1637 1692
1638 void PasswordAutofillAgent::ClearPreview( 1693 void PasswordAutofillAgent::ClearPreview(
1639 blink::WebInputElement* username, 1694 blink::WebInputElement* username,
1640 blink::WebInputElement* password) { 1695 blink::WebInputElement* password) {
1641 if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) { 1696 if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 PasswordAutofillAgent::GetPasswordManagerDriver() { 1728 PasswordAutofillAgent::GetPasswordManagerDriver() {
1674 if (!password_manager_driver_) { 1729 if (!password_manager_driver_) {
1675 render_frame()->GetRemoteInterfaces()->GetInterface( 1730 render_frame()->GetRemoteInterfaces()->GetInterface(
1676 mojo::MakeRequest(&password_manager_driver_)); 1731 mojo::MakeRequest(&password_manager_driver_));
1677 } 1732 }
1678 1733
1679 return password_manager_driver_; 1734 return password_manager_driver_;
1680 } 1735 }
1681 1736
1682 } // namespace autofill 1737 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698