OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |