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

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 30 matching lines...) Expand all
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/WebLocalFrame.h" 47 #include "third_party/WebKit/public/web/WebLocalFrame.h"
48 #include "third_party/WebKit/public/web/WebNode.h" 48 #include "third_party/WebKit/public/web/WebNode.h"
49 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 49 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
50 #include "third_party/WebKit/public/web/WebView.h" 50 #include "third_party/WebKit/public/web/WebView.h"
51 #include "third_party/WebKit/public/web/modules/password_manager/WebFormElementO bserver.h"
52 #include "third_party/WebKit/public/web/modules/password_manager/WebFormElementO bserverCallback.h"
51 #include "ui/base/page_transition_types.h" 53 #include "ui/base/page_transition_types.h"
52 #include "ui/events/keycodes/keyboard_codes.h" 54 #include "ui/events/keycodes/keyboard_codes.h"
53 #include "url/gurl.h" 55 #include "url/gurl.h"
54 56
55 namespace autofill { 57 namespace autofill {
56 namespace { 58 namespace {
57 59
58 // The size above which we stop triggering autocomplete. 60 // The size above which we stop triggering autocomplete.
59 static const size_t kMaximumTextSizeForAutocomplete = 1000; 61 static const size_t kMaximumTextSizeForAutocomplete = 1000;
60 62
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 element.To<blink::WebFormControlElement>(); 613 element.To<blink::WebFormControlElement>();
612 if (control.FormControlType() == kPassword) 614 if (control.FormControlType() == kPassword)
613 return true; 615 return true;
614 } 616 }
615 } 617 }
616 return false; 618 return false;
617 } 619 }
618 620
619 } // namespace 621 } // namespace
620 622
623 class PasswordAutofillAgent::FormElementObserverCallback
624 : public blink::WebFormElementObserverCallback {
625 public:
626 explicit FormElementObserverCallback(PasswordAutofillAgent* agent)
627 : agent_(agent) {}
628 ~FormElementObserverCallback() override = default;
629
630 void ElementWasHiddenOrRemoved() override {
631 agent_->OnSameDocumentNavigationCompleted(
632 PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
633 }
634
635 private:
636 PasswordAutofillAgent* agent_;
637
638 DISALLOW_COPY_AND_ASSIGN(FormElementObserverCallback);
639 };
640
621 //////////////////////////////////////////////////////////////////////////////// 641 ////////////////////////////////////////////////////////////////////////////////
622 // PasswordAutofillAgent, public: 642 // PasswordAutofillAgent, public:
623 643
624 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame) 644 PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame)
625 : content::RenderFrameObserver(render_frame), 645 : content::RenderFrameObserver(render_frame),
626 logging_state_active_(false), 646 logging_state_active_(false),
627 was_username_autofilled_(false), 647 was_username_autofilled_(false),
628 was_password_autofilled_(false), 648 was_password_autofilled_(false),
629 sent_request_to_store_(false), 649 sent_request_to_store_(false),
630 checked_safe_browsing_reputation_(false), 650 checked_safe_browsing_reputation_(false),
631 binding_(this) { 651 binding_(this),
652 form_element_observer_(nullptr) {
632 // PasswordAutofillAgent is guaranteed to outlive |render_frame|. 653 // PasswordAutofillAgent is guaranteed to outlive |render_frame|.
633 render_frame->GetInterfaceRegistry()->AddInterface( 654 render_frame->GetInterfaceRegistry()->AddInterface(
634 base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this))); 655 base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
635 } 656 }
636 657
637 PasswordAutofillAgent::~PasswordAutofillAgent() { 658 PasswordAutofillAgent::~PasswordAutofillAgent() {
659 if (form_element_observer_) {
660 form_element_observer_->Disconnect();
661 form_element_observer_ = nullptr;
662 }
638 } 663 }
639 664
640 void PasswordAutofillAgent::BindRequest( 665 void PasswordAutofillAgent::BindRequest(
641 const service_manager::BindSourceInfo& source_info, 666 const service_manager::BindSourceInfo& source_info,
642 mojom::PasswordAutofillAgentRequest request) { 667 mojom::PasswordAutofillAgentRequest request) {
643 binding_.Bind(std::move(request)); 668 binding_.Bind(std::move(request));
644 } 669 }
645 670
646 void PasswordAutofillAgent::SetAutofillAgent(AutofillAgent* autofill_agent) { 671 void PasswordAutofillAgent::SetAutofillAgent(AutofillAgent* autofill_agent) {
647 autofill_agent_ = autofill_agent; 672 autofill_agent_ = autofill_agent;
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 bool PasswordAutofillAgent::OriginCanAccessPasswordManager( 1050 bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
1026 const blink::WebSecurityOrigin& origin) { 1051 const blink::WebSecurityOrigin& origin) {
1027 return origin.CanAccessPasswordManager(); 1052 return origin.CanAccessPasswordManager();
1028 } 1053 }
1029 1054
1030 void PasswordAutofillAgent::OnDynamicFormsSeen() { 1055 void PasswordAutofillAgent::OnDynamicFormsSeen() {
1031 SendPasswordForms(false /* only_visible */); 1056 SendPasswordForms(false /* only_visible */);
1032 } 1057 }
1033 1058
1034 void PasswordAutofillAgent::AJAXSucceeded() { 1059 void PasswordAutofillAgent::AJAXSucceeded() {
1035 OnSameDocumentNavigationCompleted(false); 1060 OnSameDocumentNavigationCompleted(
1061 PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
1036 } 1062 }
1037 1063
1038 void PasswordAutofillAgent::OnSameDocumentNavigationCompleted( 1064 void PasswordAutofillAgent::OnSameDocumentNavigationCompleted(
1039 bool is_inpage_navigation) { 1065 PasswordForm::SubmissionIndicatorEvent event) {
1040 if (!provisionally_saved_form_.IsPasswordValid()) 1066 if (!provisionally_saved_form_.IsPasswordValid())
1041 return; 1067 return;
1042 1068
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 1069 // Prompt to save only if the form is now gone, either invisible or
1049 // removed from the DOM. 1070 // removed from the DOM.
1050 blink::WebFrame* frame = render_frame()->GetWebFrame(); 1071 blink::WebFrame* frame = render_frame()->GetWebFrame();
1051 const auto& password_form = provisionally_saved_form_.password_form(); 1072 const auto& password_form = provisionally_saved_form_.password_form();
1052 // TODO(crbug.com/720347): This method could be called often and checking form 1073 // TODO(crbug.com/720347): This method could be called often and checking form
1053 // visibility could be expesive. Add performance metrics for this. 1074 // visibility could be expesive. Add performance metrics for this.
1054 if (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(), 1075 if (event != PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR &&
1055 password_form.action, password_form.origin, 1076 (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(),
1056 password_form.form_data) || 1077 password_form.action, password_form.origin,
1057 (provisionally_saved_form_.form_element().IsNull() && 1078 password_form.form_data) ||
1058 IsUnownedPasswordFormVisible( 1079 (provisionally_saved_form_.form_element().IsNull() &&
1059 frame, provisionally_saved_form_.input_element(), 1080 IsUnownedPasswordFormVisible(
1060 password_form.action, password_form.origin, password_form.form_data, 1081 frame, provisionally_saved_form_.input_element(),
1061 form_predictions_))) { 1082 password_form.action, password_form.origin, password_form.form_data,
1083 form_predictions_)))) {
1084 if (!form_element_observer_) {
1085 std::unique_ptr<FormElementObserverCallback> callback(
1086 new FormElementObserverCallback(this));
1087 if (provisionally_saved_form_.form_element().IsNull()) {
1088 form_element_observer_ = blink::WebFormElementObserver::Create(
1089 provisionally_saved_form_.input_element(), std::move(callback));
1090 } else {
1091 form_element_observer_ = blink::WebFormElementObserver::Create(
1092 provisionally_saved_form_.form_element(), std::move(callback));
1093 }
1094 }
1062 return; 1095 return;
1063 } 1096 }
1064 1097
1098 provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
1065 GetPasswordManagerDriver()->InPageNavigation(password_form); 1099 GetPasswordManagerDriver()->InPageNavigation(password_form);
1100 if (form_element_observer_) {
1101 form_element_observer_->Disconnect();
1102 form_element_observer_ = nullptr;
1103 }
1066 provisionally_saved_form_.Reset(); 1104 provisionally_saved_form_.Reset();
1067 } 1105 }
1068 1106
1069 void PasswordAutofillAgent::UserGestureObserved() { 1107 void PasswordAutofillAgent::UserGestureObserved() {
1070 gatekeeper_.OnUserGesture(); 1108 gatekeeper_.OnUserGesture();
1071 } 1109 }
1072 1110
1073 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) { 1111 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
1074 std::unique_ptr<RendererSavePasswordProgressLogger> logger; 1112 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1075 if (logging_state_active_) { 1113 if (logging_state_active_) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 } 1248 }
1211 1249
1212 void PasswordAutofillAgent::WillCommitProvisionalLoad() { 1250 void PasswordAutofillAgent::WillCommitProvisionalLoad() {
1213 FrameClosing(); 1251 FrameClosing();
1214 } 1252 }
1215 1253
1216 void PasswordAutofillAgent::DidCommitProvisionalLoad( 1254 void PasswordAutofillAgent::DidCommitProvisionalLoad(
1217 bool is_new_navigation, 1255 bool is_new_navigation,
1218 bool is_same_document_navigation) { 1256 bool is_same_document_navigation) {
1219 if (is_same_document_navigation) { 1257 if (is_same_document_navigation) {
1220 OnSameDocumentNavigationCompleted(true); 1258 OnSameDocumentNavigationCompleted(
1259 PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION);
1221 } else { 1260 } else {
1222 checked_safe_browsing_reputation_ = false; 1261 checked_safe_browsing_reputation_ = false;
1223 } 1262 }
1224 } 1263 }
1225 1264
1226 void PasswordAutofillAgent::FrameDetached() { 1265 void PasswordAutofillAgent::FrameDetached() {
1227 // If a sub frame has been destroyed while the user was entering information 1266 // 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 1267 // 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. 1268 // for examples of sites that perform login using this technique.
1230 if (render_frame()->GetWebFrame()->Parent() && 1269 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; 1331 submitted_form->username_value = saved_form.username_value;
1293 submitted_form->submission_event = 1332 submitted_form->submission_event =
1294 PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION; 1333 PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION;
1295 } 1334 }
1296 1335
1297 // Some observers depend on sending this information now instead of when 1336 // Some observers depend on sending this information now instead of when
1298 // the frame starts loading. If there are redirects that cause a new 1337 // the frame starts loading. If there are redirects that cause a new
1299 // RenderView to be instantiated (such as redirects to the WebStore) 1338 // RenderView to be instantiated (such as redirects to the WebStore)
1300 // we will never get to finish the load. 1339 // we will never get to finish the load.
1301 GetPasswordManagerDriver()->PasswordFormSubmitted(*submitted_form); 1340 GetPasswordManagerDriver()->PasswordFormSubmitted(*submitted_form);
1341 if (form_element_observer_) {
1342 form_element_observer_->Disconnect();
1343 form_element_observer_ = nullptr;
1344 }
1302 provisionally_saved_form_.Reset(); 1345 provisionally_saved_form_.Reset();
1303 } else if (logger) { 1346 } else if (logger) {
1304 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD); 1347 logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
1305 } 1348 }
1306 } 1349 }
1307 1350
1308 void PasswordAutofillAgent::OnDestruct() { 1351 void PasswordAutofillAgent::OnDestruct() {
1309 binding_.Close(); 1352 binding_.Close();
1310 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); 1353 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
1311 } 1354 }
(...skipping 27 matching lines...) Expand all
1339 !blink::WebUserGestureIndicator::IsProcessingUserGesture()) { 1382 !blink::WebUserGestureIndicator::IsProcessingUserGesture()) {
1340 // If onsubmit has been called, try and save that form. 1383 // If onsubmit has been called, try and save that form.
1341 if (provisionally_saved_form_.IsSet()) { 1384 if (provisionally_saved_form_.IsSet()) {
1342 if (logger) { 1385 if (logger) {
1343 logger->LogPasswordForm( 1386 logger->LogPasswordForm(
1344 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME, 1387 Logger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
1345 provisionally_saved_form_.password_form()); 1388 provisionally_saved_form_.password_form());
1346 } 1389 }
1347 GetPasswordManagerDriver()->PasswordFormSubmitted( 1390 GetPasswordManagerDriver()->PasswordFormSubmitted(
1348 provisionally_saved_form_.password_form()); 1391 provisionally_saved_form_.password_form());
1392 if (form_element_observer_) {
1393 form_element_observer_->Disconnect();
1394 form_element_observer_ = nullptr;
1395 }
1349 provisionally_saved_form_.Reset(); 1396 provisionally_saved_form_.Reset();
1350 } else { 1397 } else {
1351 std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms; 1398 std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms;
1352 // Loop through the forms on the page looking for one that has been 1399 // Loop through the forms on the page looking for one that has been
1353 // filled out. If one exists, try and save the credentials. 1400 // filled out. If one exists, try and save the credentials.
1354 blink::WebVector<blink::WebFormElement> forms; 1401 blink::WebVector<blink::WebFormElement> forms;
1355 render_frame()->GetWebFrame()->GetDocument().Forms(forms); 1402 render_frame()->GetWebFrame()->GetDocument().Forms(forms);
1356 1403
1357 bool password_forms_found = false; 1404 bool password_forms_found = false;
1358 for (size_t i = 0; i < forms.size(); ++i) { 1405 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)); 1669 render_frame()->GetRenderView()->ElementBoundsInWindow(user_input));
1623 username_query_prefix_ = username_string; 1670 username_query_prefix_ = username_string;
1624 return CanShowSuggestion(password_info.fill_data, username_string, show_all); 1671 return CanShowSuggestion(password_info.fill_data, username_string, show_all);
1625 } 1672 }
1626 1673
1627 void PasswordAutofillAgent::FrameClosing() { 1674 void PasswordAutofillAgent::FrameClosing() {
1628 for (auto const& iter : web_input_to_password_info_) { 1675 for (auto const& iter : web_input_to_password_info_) {
1629 password_to_username_.erase(iter.second.password_field); 1676 password_to_username_.erase(iter.second.password_field);
1630 } 1677 }
1631 web_input_to_password_info_.clear(); 1678 web_input_to_password_info_.clear();
1679 if (form_element_observer_) {
1680 form_element_observer_->Disconnect();
1681 form_element_observer_ = nullptr;
1682 }
1632 provisionally_saved_form_.Reset(); 1683 provisionally_saved_form_.Reset();
1633 field_value_and_properties_map_.clear(); 1684 field_value_and_properties_map_.clear();
1634 sent_request_to_store_ = false; 1685 sent_request_to_store_ = false;
1635 checked_safe_browsing_reputation_ = false; 1686 checked_safe_browsing_reputation_ = false;
1636 } 1687 }
1637 1688
1638 void PasswordAutofillAgent::ClearPreview( 1689 void PasswordAutofillAgent::ClearPreview(
1639 blink::WebInputElement* username, 1690 blink::WebInputElement* username,
1640 blink::WebInputElement* password) { 1691 blink::WebInputElement* password) {
1641 if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) { 1692 if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 PasswordAutofillAgent::GetPasswordManagerDriver() { 1724 PasswordAutofillAgent::GetPasswordManagerDriver() {
1674 if (!password_manager_driver_) { 1725 if (!password_manager_driver_) {
1675 render_frame()->GetRemoteInterfaces()->GetInterface( 1726 render_frame()->GetRemoteInterfaces()->GetInterface(
1676 mojo::MakeRequest(&password_manager_driver_)); 1727 mojo::MakeRequest(&password_manager_driver_));
1677 } 1728 }
1678 1729
1679 return password_manager_driver_; 1730 return password_manager_driver_;
1680 } 1731 }
1681 1732
1682 } // namespace autofill 1733 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698