| 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_generation_agent.h" | 5 #include "components/autofill/content/renderer/password_generation_agent.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "components/autofill/content/common/autofill_messages.h" | 11 #include "components/autofill/content/common/autofill_messages.h" |
| 12 #include "components/autofill/content/renderer/form_autofill_util.h" | 12 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 13 #include "components/autofill/content/renderer/form_classifier.h" | 13 #include "components/autofill/content/renderer/form_classifier.h" |
| 14 #include "components/autofill/content/renderer/password_autofill_agent.h" | 14 #include "components/autofill/content/renderer/password_autofill_agent.h" |
| 15 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 15 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 16 #include "components/autofill/core/common/autofill_switches.h" | 16 #include "components/autofill/core/common/autofill_switches.h" |
| 17 #include "components/autofill/core/common/form_data.h" | 17 #include "components/autofill/core/common/form_data.h" |
| 18 #include "components/autofill/core/common/password_form.h" | 18 #include "components/autofill/core/common/password_form.h" |
| 19 #include "components/autofill/core/common/password_form_generation_data.h" | 19 #include "components/autofill/core/common/password_form_generation_data.h" |
| 20 #include "components/autofill/core/common/password_generation_util.h" | 20 #include "components/autofill/core/common/password_generation_util.h" |
| 21 #include "components/autofill/core/common/signatures_util.h" |
| 21 #include "content/public/renderer/render_frame.h" | 22 #include "content/public/renderer/render_frame.h" |
| 22 #include "content/public/renderer/render_view.h" | 23 #include "content/public/renderer/render_view.h" |
| 23 #include "google_apis/gaia/gaia_urls.h" | 24 #include "google_apis/gaia/gaia_urls.h" |
| 24 #include "services/shell/public/cpp/interface_registry.h" | 25 #include "services/shell/public/cpp/interface_registry.h" |
| 25 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" | 26 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" |
| 26 #include "third_party/WebKit/public/platform/WebVector.h" | 27 #include "third_party/WebKit/public/platform/WebVector.h" |
| 27 #include "third_party/WebKit/public/web/WebDocument.h" | 28 #include "third_party/WebKit/public/web/WebDocument.h" |
| 28 #include "third_party/WebKit/public/web/WebFormElement.h" | 29 #include "third_party/WebKit/public/web/WebFormElement.h" |
| 29 #include "third_party/WebKit/public/web/WebInputElement.h" | 30 #include "third_party/WebKit/public/web/WebInputElement.h" |
| 30 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 31 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 50 passwords->push_back(*input_element); | 51 passwords->push_back(*input_element); |
| 51 } | 52 } |
| 52 } | 53 } |
| 53 return !passwords->empty(); | 54 return !passwords->empty(); |
| 54 } | 55 } |
| 55 | 56 |
| 56 bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) { | 57 bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) { |
| 57 return std::find(urls.begin(), urls.end(), url) != urls.end(); | 58 return std::find(urls.begin(), urls.end(), url) != urls.end(); |
| 58 } | 59 } |
| 59 | 60 |
| 60 // Finds a form in |forms| that has the same action and name as |form|. | 61 // Calculates the signature of |form| and searches it in |forms|. |
| 61 // If the action of a form in |forms| is empty, it uses |base_url| as action. It | |
| 62 // also strips parameters of the action. | |
| 63 const PasswordFormGenerationData* FindFormGenerationData( | 62 const PasswordFormGenerationData* FindFormGenerationData( |
| 64 const std::vector<PasswordFormGenerationData>& forms, | 63 const std::vector<PasswordFormGenerationData>& forms, |
| 65 const PasswordForm& form, | 64 const PasswordForm& form) { |
| 66 const GURL& base_url) { | 65 FormSignature form_signature = CalculateFormSignature(form.form_data); |
| 67 for (const auto& form_it : forms) { | 66 for (const auto& form_it : forms) { |
| 68 GURL action = form_it.action; | 67 if (form_it.form_signature == form_signature) |
| 69 if (action.is_empty()) | |
| 70 action = base_url; | |
| 71 action = form_util::StripAuthAndParams(action); | |
| 72 if (form_it.name == form.form_data.name && action == form.action) | |
| 73 return &form_it; | 68 return &form_it; |
| 74 } | 69 } |
| 75 return nullptr; | 70 return nullptr; |
| 76 } | 71 } |
| 77 | 72 |
| 78 // This function returns a vector of password fields into which Chrome should | 73 // This function returns a vector of password fields into which Chrome should |
| 79 // fill the generated password. It assumes that |field_data| describes the field | 74 // fill the generated password. It assumes that |field_signature| describes the |
| 80 // where Chrome shows the password generation prompt. It returns no more | 75 // field where Chrome shows the password generation prompt. It returns no more |
| 81 // than 2 elements. | 76 // than 2 elements. |
| 82 std::vector<blink::WebInputElement> FindPasswordElementsForGeneration( | 77 std::vector<blink::WebInputElement> FindPasswordElementsForGeneration( |
| 83 const std::vector<blink::WebInputElement>& all_password_elements, | 78 const std::vector<blink::WebInputElement>& all_password_elements, |
| 84 const base::string16& field_name) { | 79 const FieldSignature field_signature) { |
| 85 auto iter = | 80 auto iter = std::find_if( |
| 86 std::find_if(all_password_elements.begin(), all_password_elements.end(), | 81 all_password_elements.begin(), all_password_elements.end(), |
| 87 [&field_name](const blink::WebInputElement& input) { | 82 [&field_signature](const blink::WebInputElement& input) { |
| 88 // Make explicit conversion before comparing with string16. | 83 FieldSignature signature = CalculateFieldSignatureByNameAndType( |
| 89 base::string16 input_name = input.nameForAutofill(); | 84 input.nameForAutofill(), input.formControlType().utf8()); |
| 90 return input_name == field_name; | 85 return signature == field_signature; |
| 91 }); | 86 }); |
| 92 std::vector<blink::WebInputElement> passwords; | 87 std::vector<blink::WebInputElement> passwords; |
| 93 | 88 |
| 94 // We copy not more than 2 fields because occasionally there are forms where | 89 // We copy not more than 2 fields because occasionally there are forms where |
| 95 // the security question answers are put in password fields and we don't want | 90 // the security question answers are put in password fields and we don't want |
| 96 // to fill those. | 91 // to fill those. |
| 97 for (; iter != all_password_elements.end() && passwords.size() < 2; ++iter) { | 92 for (; iter != all_password_elements.end() && passwords.size() < 2; ++iter) |
| 98 passwords.push_back(*iter); | 93 passwords.push_back(*iter); |
| 99 } | |
| 100 return passwords; | 94 return passwords; |
| 101 } | 95 } |
| 102 | 96 |
| 103 void CopyElementValueToOtherInputElements( | 97 void CopyElementValueToOtherInputElements( |
| 104 const blink::WebInputElement* element, | 98 const blink::WebInputElement* element, |
| 105 std::vector<blink::WebInputElement>* elements) { | 99 std::vector<blink::WebInputElement>* elements) { |
| 106 for (blink::WebInputElement& it : *elements) { | 100 for (blink::WebInputElement& it : *elements) { |
| 107 if (*element != it) { | 101 if (*element != it) { |
| 108 it.setValue(element->value(), true /* sendEvents */); | 102 it.setValue(element->value(), true /* sendEvents */); |
| 109 } | 103 } |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 378 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 385 switches::kLocalHeuristicsOnlyForPasswordGeneration)) { | 379 switches::kLocalHeuristicsOnlyForPasswordGeneration)) { |
| 386 VLOG(2) << "Bypassing additional checks."; | 380 VLOG(2) << "Bypassing additional checks."; |
| 387 } else if (!ContainsURL(not_blacklisted_password_form_origins_, | 381 } else if (!ContainsURL(not_blacklisted_password_form_origins_, |
| 388 possible_password_form->origin)) { | 382 possible_password_form->origin)) { |
| 389 VLOG(2) << "Have not received confirmation that password form isn't " | 383 VLOG(2) << "Have not received confirmation that password form isn't " |
| 390 << "blacklisted"; | 384 << "blacklisted"; |
| 391 continue; | 385 continue; |
| 392 } else { | 386 } else { |
| 393 generation_data = FindFormGenerationData( | 387 generation_data = FindFormGenerationData( |
| 394 generation_enabled_forms_, *possible_password_form, | 388 generation_enabled_forms_, *possible_password_form); |
| 395 render_frame()->GetWebFrame()->document().baseURL()); | |
| 396 if (!generation_data) { | 389 if (!generation_data) { |
| 397 if (AutocompleteAttributesSetForGeneration(*possible_password_form)) { | 390 if (AutocompleteAttributesSetForGeneration(*possible_password_form)) { |
| 398 VLOG(2) << "Ignoring lack of Autofill signal due to Autocomplete " | 391 VLOG(2) << "Ignoring lack of Autofill signal due to Autocomplete " |
| 399 << "attributes"; | 392 << "attributes"; |
| 400 password_generation::LogPasswordGenerationEvent( | 393 password_generation::LogPasswordGenerationEvent( |
| 401 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION); | 394 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION); |
| 402 } else { | 395 } else { |
| 403 VLOG(2) | 396 VLOG(2) |
| 404 << "Have not received confirmation from Autofill that form is " | 397 << "Have not received confirmation from Autofill that form is " |
| 405 << "used for account creation"; | 398 << "used for account creation"; |
| 406 continue; | 399 continue; |
| 407 } | 400 } |
| 408 } | 401 } |
| 409 } | 402 } |
| 410 | 403 |
| 411 VLOG(2) << "Password generation eligible form found"; | 404 VLOG(2) << "Password generation eligible form found"; |
| 412 std::vector<blink::WebInputElement> password_elements = | 405 std::vector<blink::WebInputElement> password_elements = |
| 413 generation_data ? FindPasswordElementsForGeneration( | 406 generation_data ? FindPasswordElementsForGeneration( |
| 414 possible_form_data.password_elements, | 407 possible_form_data.password_elements, |
| 415 generation_data->generation_field.name) | 408 generation_data->field_signature) |
| 416 : possible_form_data.password_elements; | 409 : possible_form_data.password_elements; |
| 417 if (password_elements.empty()) { | 410 if (password_elements.empty()) { |
| 418 // It might be if JavaScript changes field names. | 411 // It might be if JavaScript changes field names. |
| 419 VLOG(2) << "Fields for generation are not found"; | 412 VLOG(2) << "Fields for generation are not found"; |
| 420 return; | 413 return; |
| 421 } | 414 } |
| 422 generation_form_data_.reset(new AccountCreationFormData( | 415 generation_form_data_.reset(new AccountCreationFormData( |
| 423 possible_form_data.form, std::move(password_elements))); | 416 possible_form_data.form, std::move(password_elements))); |
| 424 generation_element_ = generation_form_data_->password_elements[0]; | 417 generation_element_ = generation_form_data_->password_elements[0]; |
| 425 generation_element_.setAttribute("aria-autocomplete", "list"); | 418 generation_element_.setAttribute("aria-autocomplete", "list"); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 form_util::GetUnownedFormFieldElements(doc.all(), nullptr); | 560 form_util::GetUnownedFormFieldElements(doc.all(), nullptr); |
| 568 } | 561 } |
| 569 | 562 |
| 570 if (!password_form) | 563 if (!password_form) |
| 571 return; | 564 return; |
| 572 | 565 |
| 573 generation_element_ = last_focused_password_element_; | 566 generation_element_ = last_focused_password_element_; |
| 574 std::vector<blink::WebInputElement> password_elements; | 567 std::vector<blink::WebInputElement> password_elements; |
| 575 GetAccountCreationPasswordFields(control_elements, &password_elements); | 568 GetAccountCreationPasswordFields(control_elements, &password_elements); |
| 576 password_elements = FindPasswordElementsForGeneration( | 569 password_elements = FindPasswordElementsForGeneration( |
| 577 password_elements, last_focused_password_element_.nameForAutofill()); | 570 password_elements, |
| 571 CalculateFieldSignatureByNameAndType( |
| 572 last_focused_password_element_.nameForAutofill(), |
| 573 last_focused_password_element_.formControlType().utf8())); |
| 578 generation_form_data_.reset(new AccountCreationFormData( | 574 generation_form_data_.reset(new AccountCreationFormData( |
| 579 make_linked_ptr(password_form.release()), password_elements)); | 575 make_linked_ptr(password_form.release()), password_elements)); |
| 580 is_manually_triggered_ = true; | 576 is_manually_triggered_ = true; |
| 581 ShowGenerationPopup(); | 577 ShowGenerationPopup(); |
| 582 } | 578 } |
| 583 | 579 |
| 584 const mojom::PasswordManagerDriverPtr& | 580 const mojom::PasswordManagerDriverPtr& |
| 585 PasswordGenerationAgent::GetPasswordManagerDriver() { | 581 PasswordGenerationAgent::GetPasswordManagerDriver() { |
| 586 DCHECK(password_agent_); | 582 DCHECK(password_agent_); |
| 587 return password_agent_->GetPasswordManagerDriver(); | 583 return password_agent_->GetPasswordManagerDriver(); |
| 588 } | 584 } |
| 589 | 585 |
| 590 } // namespace autofill | 586 } // namespace autofill |
| OLD | NEW |