| 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 <algorithm> |
| 7 #include <memory> | 8 #include <memory> |
| 9 #include <utility> |
| 8 | 10 |
| 9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" | 13 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "components/autofill/content/renderer/form_autofill_util.h" | 14 #include "components/autofill/content/renderer/form_autofill_util.h" |
| 13 #include "components/autofill/content/renderer/form_classifier.h" | 15 #include "components/autofill/content/renderer/form_classifier.h" |
| 14 #include "components/autofill/content/renderer/password_autofill_agent.h" | 16 #include "components/autofill/content/renderer/password_autofill_agent.h" |
| 15 #include "components/autofill/content/renderer/password_form_conversion_utils.h" | 17 #include "components/autofill/content/renderer/password_form_conversion_utils.h" |
| 16 #include "components/autofill/core/common/autofill_switches.h" | 18 #include "components/autofill/core/common/autofill_switches.h" |
| 17 #include "components/autofill/core/common/form_data.h" | 19 #include "components/autofill/core/common/form_data.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 32 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 34 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 33 #include "third_party/WebKit/public/web/WebView.h" | 35 #include "third_party/WebKit/public/web/WebView.h" |
| 34 #include "ui/gfx/geometry/rect.h" | 36 #include "ui/gfx/geometry/rect.h" |
| 35 | 37 |
| 36 namespace autofill { | 38 namespace autofill { |
| 37 | 39 |
| 38 namespace { | 40 namespace { |
| 39 | 41 |
| 40 using Logger = autofill::SavePasswordProgressLogger; | 42 using Logger = autofill::SavePasswordProgressLogger; |
| 41 | 43 |
| 42 // Returns true if we think that this form is for account creation. |passwords| | 44 // Returns true if we think that this form is for account creation. Password |
| 43 // is filled with the password field(s) in the form. | 45 // field(s) of the form are pushed back to |passwords|. |
| 44 bool GetAccountCreationPasswordFields( | 46 bool GetAccountCreationPasswordFields( |
| 45 const std::vector<blink::WebFormControlElement>& control_elements, | 47 const std::vector<blink::WebFormControlElement>& control_elements, |
| 46 std::vector<blink::WebInputElement>* passwords) { | 48 std::vector<blink::WebInputElement>* passwords) { |
| 47 for (size_t i = 0; i < control_elements.size(); i++) { | 49 for (const auto& control_element : control_elements) { |
| 48 const blink::WebInputElement* input_element = | 50 const blink::WebInputElement* input_element = |
| 49 ToWebInputElement(&control_elements[i]); | 51 ToWebInputElement(&control_element); |
| 50 if (input_element && input_element->IsTextField()) { | 52 if (input_element && input_element->IsTextField() && |
| 51 if (input_element->IsPasswordField()) | 53 input_element->IsPasswordField()) { |
| 52 passwords->push_back(*input_element); | 54 passwords->push_back(*input_element); |
| 53 } | 55 } |
| 54 } | 56 } |
| 55 return !passwords->empty(); | 57 return !passwords->empty(); |
| 56 } | 58 } |
| 57 | 59 |
| 58 bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) { | 60 bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) { |
| 59 return std::find(urls.begin(), urls.end(), url) != urls.end(); | 61 return std::find(urls.begin(), urls.end(), url) != urls.end(); |
| 60 } | 62 } |
| 61 | 63 |
| 62 // Calculates the signature of |form| and searches it in |forms|. | 64 // Calculates the signature of |form| and searches it in |forms|. |
| 63 const PasswordFormGenerationData* FindFormGenerationData( | 65 const PasswordFormGenerationData* FindFormGenerationData( |
| 64 const std::vector<PasswordFormGenerationData>& forms, | 66 const std::vector<PasswordFormGenerationData>& forms, |
| 65 const PasswordForm& form) { | 67 const PasswordForm& form) { |
| 66 FormSignature form_signature = CalculateFormSignature(form.form_data); | 68 FormSignature form_signature = CalculateFormSignature(form.form_data); |
| 67 for (const auto& form_it : forms) { | 69 for (const auto& form_it : forms) { |
| 68 if (form_it.form_signature == form_signature) | 70 if (form_it.form_signature == form_signature) |
| 69 return &form_it; | 71 return &form_it; |
| 70 } | 72 } |
| 71 return nullptr; | 73 return nullptr; |
| 72 } | 74 } |
| 73 | 75 |
| 74 // This function returns a vector of password fields into which Chrome should | 76 // Returns a vector of up to 2 password fields with autocomplete attribute set |
| 75 // fill the generated password. It assumes that |field_signature| describes the | 77 // to "new-password". These will be filled with the generated password. |
| 76 // field where Chrome shows the password generation prompt. It returns no more | 78 std::vector<blink::WebInputElement> FindNewPasswordElementsMarkedBySite( |
| 77 // than 2 elements. | 79 const std::vector<blink::WebInputElement>& all_password_elements) { |
| 80 std::vector<blink::WebInputElement> passwords; |
| 81 |
| 82 auto is_new_password_field = [](const blink::WebInputElement& element) { |
| 83 return HasAutocompleteAttributeValue(element, "new-password"); |
| 84 }; |
| 85 |
| 86 auto field_iter = |
| 87 std::find_if(all_password_elements.begin(), all_password_elements.end(), |
| 88 is_new_password_field); |
| 89 if (field_iter != all_password_elements.end()) { |
| 90 passwords.push_back(*field_iter++); |
| 91 field_iter = std::find_if(field_iter, all_password_elements.end(), |
| 92 is_new_password_field); |
| 93 if (field_iter != all_password_elements.end()) |
| 94 passwords.push_back(*field_iter); |
| 95 } |
| 96 |
| 97 return passwords; |
| 98 } |
| 99 |
| 100 // Returns a vector of up to 2 password fields into which Chrome should fill the |
| 101 // generated password. It assumes that |field_signature| describes the field |
| 102 // where Chrome shows the password generation prompt. |
| 78 std::vector<blink::WebInputElement> FindPasswordElementsForGeneration( | 103 std::vector<blink::WebInputElement> FindPasswordElementsForGeneration( |
| 79 const std::vector<blink::WebInputElement>& all_password_elements, | 104 const std::vector<blink::WebInputElement>& all_password_elements, |
| 80 const PasswordFormGenerationData& generation_data) { | 105 const PasswordFormGenerationData& generation_data) { |
| 81 auto generation_field_iter = all_password_elements.end(); | 106 auto generation_field_iter = all_password_elements.end(); |
| 82 auto confirmation_field_iter = all_password_elements.end(); | 107 auto confirmation_field_iter = all_password_elements.end(); |
| 83 for (auto iter = all_password_elements.begin(); | 108 for (auto iter = all_password_elements.begin(); |
| 84 iter != all_password_elements.end(); ++iter) { | 109 iter != all_password_elements.end(); ++iter) { |
| 85 const blink::WebInputElement& input = *iter; | 110 const blink::WebInputElement& input = *iter; |
| 86 FieldSignature signature = CalculateFieldSignatureByNameAndType( | 111 FieldSignature signature = CalculateFieldSignatureByNameAndType( |
| 87 input.NameForAutofill().Utf16(), input.FormControlType().Utf8()); | 112 input.NameForAutofill().Utf16(), input.FormControlType().Utf8()); |
| 88 if (signature == generation_data.field_signature) | 113 if (signature == generation_data.field_signature) { |
| 89 generation_field_iter = iter; | 114 generation_field_iter = iter; |
| 90 else if (generation_data.confirmation_field_signature && | 115 } else if (generation_data.confirmation_field_signature && |
| 91 signature == *generation_data.confirmation_field_signature) | 116 signature == *generation_data.confirmation_field_signature) { |
| 92 confirmation_field_iter = iter; | 117 confirmation_field_iter = iter; |
| 118 } |
| 93 } | 119 } |
| 94 | 120 |
| 95 std::vector<blink::WebInputElement> passwords; | 121 std::vector<blink::WebInputElement> passwords; |
| 96 if (generation_field_iter != all_password_elements.end()) { | 122 if (generation_field_iter != all_password_elements.end()) { |
| 97 passwords.push_back(*generation_field_iter); | 123 passwords.push_back(*generation_field_iter); |
| 98 | 124 |
| 99 if (confirmation_field_iter == all_password_elements.end()) | 125 if (confirmation_field_iter == all_password_elements.end()) |
| 100 confirmation_field_iter = generation_field_iter + 1; | 126 confirmation_field_iter = generation_field_iter + 1; |
| 101 if (confirmation_field_iter != all_password_elements.end()) | 127 if (confirmation_field_iter != all_password_elements.end()) |
| 102 passwords.push_back(*confirmation_field_iter); | 128 passwords.push_back(*confirmation_field_iter); |
| 103 } | 129 } |
| 104 return passwords; | 130 return passwords; |
| 105 } | 131 } |
| 106 | 132 |
| 107 void CopyElementValueToOtherInputElements( | 133 void CopyElementValueToOtherInputElements( |
| 108 const blink::WebInputElement* element, | 134 const blink::WebInputElement* element, |
| 109 std::vector<blink::WebInputElement>* elements) { | 135 std::vector<blink::WebInputElement>* elements) { |
| 110 for (blink::WebInputElement& it : *elements) { | 136 for (blink::WebInputElement& it : *elements) { |
| 111 if (*element != it) { | 137 if (*element != it) { |
| 112 it.SetAutofillValue(element->Value()); | 138 it.SetAutofillValue(element->Value()); |
| 113 } | 139 } |
| 114 } | 140 } |
| 115 } | 141 } |
| 116 | 142 |
| 117 bool AutocompleteAttributesSetForGeneration(const PasswordForm& form) { | |
| 118 return form.username_marked_by_site && form.new_password_marked_by_site; | |
| 119 } | |
| 120 | |
| 121 } // namespace | 143 } // namespace |
| 122 | 144 |
| 123 PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData( | 145 PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData( |
| 124 linked_ptr<PasswordForm> password_form, | 146 linked_ptr<PasswordForm> password_form, |
| 125 std::vector<blink::WebInputElement> passwords) | 147 std::vector<blink::WebInputElement> passwords) |
| 126 : form(password_form), | 148 : form(password_form), password_elements(std::move(passwords)) {} |
| 127 password_elements(passwords) {} | |
| 128 | 149 |
| 129 PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData( | 150 PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData( |
| 130 const AccountCreationFormData& other) = default; | 151 const AccountCreationFormData& other) = default; |
| 131 | 152 |
| 132 PasswordGenerationAgent::AccountCreationFormData::~AccountCreationFormData() {} | 153 PasswordGenerationAgent::AccountCreationFormData::~AccountCreationFormData() {} |
| 133 | 154 |
| 134 PasswordGenerationAgent::PasswordGenerationAgent( | 155 PasswordGenerationAgent::PasswordGenerationAgent( |
| 135 content::RenderFrame* render_frame, | 156 content::RenderFrame* render_frame, |
| 136 PasswordAutofillAgent* password_agent) | 157 PasswordAutofillAgent* password_agent) |
| 137 : content::RenderFrameObserver(render_frame), | 158 : content::RenderFrameObserver(render_frame), |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 GURL realm(password_form->signon_realm); | 291 GURL realm(password_form->signon_realm); |
| 271 if (realm == GaiaUrls::GetInstance()->gaia_login_form_realm()) | 292 if (realm == GaiaUrls::GetInstance()->gaia_login_form_realm()) |
| 272 continue; | 293 continue; |
| 273 | 294 |
| 274 std::vector<blink::WebInputElement> passwords; | 295 std::vector<blink::WebInputElement> passwords; |
| 275 if (GetAccountCreationPasswordFields( | 296 if (GetAccountCreationPasswordFields( |
| 276 form_util::ExtractAutofillableElementsInForm(forms[i]), | 297 form_util::ExtractAutofillableElementsInForm(forms[i]), |
| 277 &passwords)) { | 298 &passwords)) { |
| 278 if (form_classifier_enabled_) | 299 if (form_classifier_enabled_) |
| 279 RunFormClassifierAndSaveVote(forms[i], *password_form); | 300 RunFormClassifierAndSaveVote(forms[i], *password_form); |
| 280 AccountCreationFormData ac_form_data( | 301 possible_account_creation_forms_.emplace_back( |
| 281 make_linked_ptr(password_form.release()), passwords); | 302 make_linked_ptr(password_form.release()), std::move(passwords)); |
| 282 possible_account_creation_forms_.push_back(ac_form_data); | |
| 283 } | 303 } |
| 284 } | 304 } |
| 285 | 305 |
| 286 if (!possible_account_creation_forms_.empty()) { | 306 if (!possible_account_creation_forms_.empty()) { |
| 287 LogNumber( | 307 LogNumber( |
| 288 Logger::STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS, | 308 Logger::STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS, |
| 289 possible_account_creation_forms_.size()); | 309 possible_account_creation_forms_.size()); |
| 290 DetermineGenerationElement(); | 310 DetermineGenerationElement(); |
| 291 } | 311 } |
| 292 } | 312 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 if (possible_account_creation_forms_.empty()) { | 402 if (possible_account_creation_forms_.empty()) { |
| 383 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_POSSIBLE_CREATION_FORMS); | 403 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_POSSIBLE_CREATION_FORMS); |
| 384 return; | 404 return; |
| 385 } | 405 } |
| 386 | 406 |
| 387 // Note that no messages will be sent if this feature is disabled | 407 // Note that no messages will be sent if this feature is disabled |
| 388 // (e.g. password saving is disabled). | 408 // (e.g. password saving is disabled). |
| 389 for (auto& possible_form_data : possible_account_creation_forms_) { | 409 for (auto& possible_form_data : possible_account_creation_forms_) { |
| 390 PasswordForm* possible_password_form = possible_form_data.form.get(); | 410 PasswordForm* possible_password_form = possible_form_data.form.get(); |
| 391 const PasswordFormGenerationData* generation_data = nullptr; | 411 const PasswordFormGenerationData* generation_data = nullptr; |
| 412 |
| 413 std::vector<blink::WebInputElement> password_elements; |
| 392 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 414 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 393 switches::kLocalHeuristicsOnlyForPasswordGeneration)) { | 415 switches::kLocalHeuristicsOnlyForPasswordGeneration)) { |
| 416 password_elements = possible_form_data.password_elements; |
| 394 VLOG(2) << "Bypassing additional checks."; | 417 VLOG(2) << "Bypassing additional checks."; |
| 395 } else if (!ContainsURL(not_blacklisted_password_form_origins_, | 418 } else if (!ContainsURL(not_blacklisted_password_form_origins_, |
| 396 possible_password_form->origin)) { | 419 possible_password_form->origin)) { |
| 397 LogMessage(Logger::STRING_GENERATION_RENDERER_NOT_BLACKLISTED); | 420 LogMessage(Logger::STRING_GENERATION_RENDERER_NOT_BLACKLISTED); |
| 398 continue; | 421 continue; |
| 399 } else { | 422 } else { |
| 400 generation_data = FindFormGenerationData(generation_enabled_forms_, | 423 generation_data = FindFormGenerationData(generation_enabled_forms_, |
| 401 *possible_password_form); | 424 *possible_password_form); |
| 402 if (!generation_data) { | 425 if (generation_data) { |
| 403 if (AutocompleteAttributesSetForGeneration(*possible_password_form)) { | 426 password_elements = FindPasswordElementsForGeneration( |
| 404 LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE); | 427 possible_form_data.password_elements, *generation_data); |
| 405 password_generation::LogPasswordGenerationEvent( | 428 } else { |
| 406 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION); | 429 if (!possible_password_form->new_password_marked_by_site) { |
| 407 } else { | |
| 408 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL); | 430 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL); |
| 409 continue; | 431 continue; |
| 410 } | 432 } |
| 433 |
| 434 LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE); |
| 435 password_generation::LogPasswordGenerationEvent( |
| 436 password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION); |
| 437 |
| 438 password_elements = FindNewPasswordElementsMarkedBySite( |
| 439 possible_form_data.password_elements); |
| 411 } | 440 } |
| 412 } | 441 } |
| 442 |
| 413 LogMessage(Logger::STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND); | 443 LogMessage(Logger::STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND); |
| 414 std::vector<blink::WebInputElement> password_elements = | |
| 415 generation_data | |
| 416 ? FindPasswordElementsForGeneration( | |
| 417 possible_form_data.password_elements, *generation_data) | |
| 418 : possible_form_data.password_elements; | |
| 419 if (password_elements.empty()) { | 444 if (password_elements.empty()) { |
| 420 // It might be if JavaScript changes field names. | 445 // It might be if JavaScript changes field names. |
| 421 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_FIELD_FOUND); | 446 LogMessage(Logger::STRING_GENERATION_RENDERER_NO_FIELD_FOUND); |
| 422 return; | 447 return; |
| 423 } | 448 } |
| 449 |
| 424 generation_form_data_.reset(new AccountCreationFormData( | 450 generation_form_data_.reset(new AccountCreationFormData( |
| 425 possible_form_data.form, std::move(password_elements))); | 451 possible_form_data.form, std::move(password_elements))); |
| 426 generation_element_ = generation_form_data_->password_elements[0]; | 452 generation_element_ = generation_form_data_->password_elements[0]; |
| 427 generation_element_.SetAttribute("aria-autocomplete", "list"); | 453 generation_element_.SetAttribute("aria-autocomplete", "list"); |
| 428 password_generation::LogPasswordGenerationEvent( | 454 password_generation::LogPasswordGenerationEvent( |
| 429 password_generation::GENERATION_AVAILABLE); | 455 password_generation::GENERATION_AVAILABLE); |
| 430 possible_account_creation_forms_.clear(); | 456 possible_account_creation_forms_.clear(); |
| 431 GetPasswordManagerClient()->GenerationAvailableForForm( | 457 GetPasswordManagerClient()->GenerationAvailableForForm( |
| 432 *generation_form_data_->form); | 458 *generation_form_data_->form); |
| 433 return; | 459 return; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 | 651 |
| 626 void PasswordGenerationAgent::LogNumber(Logger::StringID message_id, | 652 void PasswordGenerationAgent::LogNumber(Logger::StringID message_id, |
| 627 int number) { | 653 int number) { |
| 628 if (!password_agent_->logging_state_active()) | 654 if (!password_agent_->logging_state_active()) |
| 629 return; | 655 return; |
| 630 RendererSavePasswordProgressLogger logger(GetPasswordManagerDriver().get()); | 656 RendererSavePasswordProgressLogger logger(GetPasswordManagerDriver().get()); |
| 631 logger.LogNumber(message_id, number); | 657 logger.LogNumber(message_id, number); |
| 632 } | 658 } |
| 633 | 659 |
| 634 } // namespace autofill | 660 } // namespace autofill |
| OLD | NEW |