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); |
dvadym
2016/09/07 17:29:35
I was wondering, whether we want to cache this sig
| |
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 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 const PasswordFormGenerationData* generation_data = nullptr; | 377 const PasswordFormGenerationData* generation_data = nullptr; |
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(generation_enabled_forms_, |
394 generation_enabled_forms_, *possible_password_form, | 388 *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 |