OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/password_manager/core/browser/password_manager.h" | 5 #include "components/password_manager/core/browser/password_manager.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 #if defined(OS_WIN) | 120 #if defined(OS_WIN) |
121 // static | 121 // static |
122 void PasswordManager::RegisterLocalPrefs(PrefRegistrySimple* registry) { | 122 void PasswordManager::RegisterLocalPrefs(PrefRegistrySimple* registry) { |
123 registry->RegisterInt64Pref(prefs::kOsPasswordLastChanged, 0); | 123 registry->RegisterInt64Pref(prefs::kOsPasswordLastChanged, 0); |
124 registry->RegisterBooleanPref(prefs::kOsPasswordBlank, false); | 124 registry->RegisterBooleanPref(prefs::kOsPasswordBlank, false); |
125 } | 125 } |
126 #endif | 126 #endif |
127 | 127 |
128 PasswordManager::PasswordManager(PasswordManagerClient* client) | 128 PasswordManager::PasswordManager(PasswordManagerClient* client) |
129 : client_(client), driver_(client->GetDriver()) { | 129 : client_(client) { |
130 DCHECK(client_); | 130 DCHECK(client_); |
131 DCHECK(driver_); | |
132 saving_passwords_enabled_.Init(prefs::kPasswordManagerSavingEnabled, | 131 saving_passwords_enabled_.Init(prefs::kPasswordManagerSavingEnabled, |
133 client_->GetPrefs()); | 132 client_->GetPrefs()); |
134 | 133 |
135 ReportMetrics(*saving_passwords_enabled_, client_); | 134 ReportMetrics(*saving_passwords_enabled_, client_); |
136 } | 135 } |
137 | 136 |
138 PasswordManager::~PasswordManager() { | 137 PasswordManager::~PasswordManager() { |
139 FOR_EACH_OBSERVER(LoginModelObserver, observers_, OnLoginModelDestroying()); | 138 FOR_EACH_OBSERVER(LoginModelObserver, observers_, OnLoginModelDestroying()); |
140 } | 139 } |
141 | 140 |
142 void PasswordManager::SetFormHasGeneratedPassword(const PasswordForm& form) { | 141 void PasswordManager::SetFormHasGeneratedPassword( |
| 142 password_manager::PasswordManagerDriver* driver, |
| 143 const PasswordForm& form) { |
143 DCHECK(IsSavingEnabledForCurrentPage()); | 144 DCHECK(IsSavingEnabledForCurrentPage()); |
144 | 145 |
145 for (ScopedVector<PasswordFormManager>::iterator iter = | 146 for (ScopedVector<PasswordFormManager>::iterator iter = |
146 pending_login_managers_.begin(); | 147 pending_login_managers_.begin(); |
147 iter != pending_login_managers_.end(); | 148 iter != pending_login_managers_.end(); |
148 ++iter) { | 149 ++iter) { |
149 if ((*iter)->DoesManage(form) == | 150 if ((*iter)->DoesManage(form) == |
150 PasswordFormManager::RESULT_COMPLETE_MATCH) { | 151 PasswordFormManager::RESULT_COMPLETE_MATCH) { |
151 (*iter)->SetHasGeneratedPassword(); | 152 (*iter)->SetHasGeneratedPassword(); |
152 return; | 153 return; |
153 } | 154 } |
154 } | 155 } |
155 // If there is no corresponding PasswordFormManager, we create one. This is | 156 // If there is no corresponding PasswordFormManager, we create one. This is |
156 // not the common case, and should only happen when there is a bug in our | 157 // not the common case, and should only happen when there is a bug in our |
157 // ability to detect forms. | 158 // ability to detect forms. |
158 bool ssl_valid = form.origin.SchemeIsSecure(); | 159 bool ssl_valid = form.origin.SchemeIsSecure(); |
159 PasswordFormManager* manager = | 160 PasswordFormManager* manager = |
160 new PasswordFormManager(this, client_, driver_, form, ssl_valid); | 161 new PasswordFormManager(this, client_, driver, form, ssl_valid); |
161 pending_login_managers_.push_back(manager); | 162 pending_login_managers_.push_back(manager); |
162 manager->SetHasGeneratedPassword(); | 163 manager->SetHasGeneratedPassword(); |
163 // TODO(gcasto): Add UMA stats to track this. | 164 // TODO(gcasto): Add UMA stats to track this. |
164 } | 165 } |
165 | 166 |
166 bool PasswordManager::IsEnabledForCurrentPage() const { | 167 bool PasswordManager::IsEnabledForCurrentPage() const { |
167 bool ssl_errors = driver_->DidLastPageLoadEncounterSSLErrors(); | 168 bool ssl_errors = client_->DidLastPageLoadEncounterSSLErrors(); |
168 bool client_check = client_->IsPasswordManagerEnabledForCurrentPage(); | 169 bool client_check = client_->IsPasswordManagerEnabledForCurrentPage(); |
169 | 170 |
170 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 171 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
171 if (client_->IsLoggingActive()) { | 172 if (client_->IsLoggingActive()) { |
172 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 173 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
173 logger->LogMessage(Logger::STRING_ENABLED_FOR_CURRENT_PAGE_METHOD); | 174 logger->LogMessage(Logger::STRING_ENABLED_FOR_CURRENT_PAGE_METHOD); |
174 logger->LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, ssl_errors); | 175 logger->LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, ssl_errors); |
175 logger->LogBoolean(Logger::STRING_CLIENT_CHECK_PRESENT, client_check); | 176 logger->LogBoolean(Logger::STRING_CLIENT_CHECK_PRESENT, client_check); |
176 } | 177 } |
177 | 178 |
178 return !ssl_errors && client_check; | 179 return !ssl_errors && client_check; |
179 } | 180 } |
180 | 181 |
181 bool PasswordManager::IsSavingEnabledForCurrentPage() const { | 182 bool PasswordManager::IsSavingEnabledForCurrentPage() const { |
182 return *saving_passwords_enabled_ && !driver_->IsOffTheRecord() && | 183 return *saving_passwords_enabled_ && !client_->IsOffTheRecord() && |
183 IsEnabledForCurrentPage(); | 184 IsEnabledForCurrentPage(); |
184 } | 185 } |
185 | 186 |
186 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { | 187 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { |
187 bool is_saving_enabled = IsSavingEnabledForCurrentPage(); | 188 bool is_saving_enabled = IsSavingEnabledForCurrentPage(); |
188 | 189 |
189 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 190 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
190 if (client_->IsLoggingActive()) { | 191 if (client_->IsLoggingActive()) { |
191 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 192 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
192 logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD); | 193 logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD); |
193 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM, | 194 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM, |
194 form); | 195 form); |
195 logger->LogBoolean(Logger::STRING_IS_SAVING_ENABLED, is_saving_enabled); | 196 logger->LogBoolean(Logger::STRING_IS_SAVING_ENABLED, is_saving_enabled); |
196 logger->LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, | 197 logger->LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, |
197 driver_->DidLastPageLoadEncounterSSLErrors()); | 198 client_->DidLastPageLoadEncounterSSLErrors()); |
198 } | 199 } |
199 | 200 |
200 if (!is_saving_enabled) { | 201 if (!is_saving_enabled) { |
201 RecordFailure(SAVING_DISABLED, form.origin.host(), logger.get()); | 202 RecordFailure(SAVING_DISABLED, form.origin.host(), logger.get()); |
202 return; | 203 return; |
203 } | 204 } |
204 | 205 |
205 // No password to save? Then don't. | 206 // No password to save? Then don't. |
206 if ((form.new_password_element.empty() && form.password_value.empty()) || | 207 if ((form.new_password_element.empty() && form.password_value.empty()) || |
207 (!form.new_password_element.empty() && form.new_password_value.empty())) { | 208 (!form.new_password_element.empty() && form.new_password_value.empty())) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 if (ShouldDropSyncCredential() && | 285 if (ShouldDropSyncCredential() && |
285 client_->IsSyncAccountCredential( | 286 client_->IsSyncAccountCredential( |
286 base::UTF16ToUTF8(form.username_value), form.signon_realm)) { | 287 base::UTF16ToUTF8(form.username_value), form.signon_realm)) { |
287 RecordFailure(SYNC_CREDENTIAL, form.origin.host(), logger.get()); | 288 RecordFailure(SYNC_CREDENTIAL, form.origin.host(), logger.get()); |
288 return; | 289 return; |
289 } | 290 } |
290 | 291 |
291 PasswordForm provisionally_saved_form(form); | 292 PasswordForm provisionally_saved_form(form); |
292 provisionally_saved_form.ssl_valid = | 293 provisionally_saved_form.ssl_valid = |
293 form.origin.SchemeIsSecure() && | 294 form.origin.SchemeIsSecure() && |
294 !driver_->DidLastPageLoadEncounterSSLErrors(); | 295 !client_->DidLastPageLoadEncounterSSLErrors(); |
295 provisionally_saved_form.preferred = true; | 296 provisionally_saved_form.preferred = true; |
296 if (logger) { | 297 if (logger) { |
297 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM, | 298 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM, |
298 provisionally_saved_form); | 299 provisionally_saved_form); |
299 } | 300 } |
300 PasswordFormManager::OtherPossibleUsernamesAction action = | 301 PasswordFormManager::OtherPossibleUsernamesAction action = |
301 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; | 302 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; |
302 if (OtherPossibleUsernamesEnabled()) | 303 if (OtherPossibleUsernamesEnabled()) |
303 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; | 304 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; |
304 if (logger) { | 305 if (logger) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 observers_.AddObserver(observer); | 369 observers_.AddObserver(observer); |
369 } | 370 } |
370 | 371 |
371 void PasswordManager::RemoveObserver(LoginModelObserver* observer) { | 372 void PasswordManager::RemoveObserver(LoginModelObserver* observer) { |
372 observers_.RemoveObserver(observer); | 373 observers_.RemoveObserver(observer); |
373 } | 374 } |
374 | 375 |
375 void PasswordManager::DidNavigateMainFrame(bool is_in_page) { | 376 void PasswordManager::DidNavigateMainFrame(bool is_in_page) { |
376 // Clear data after main frame navigation if the navigation was to a | 377 // Clear data after main frame navigation if the navigation was to a |
377 // different page. | 378 // different page. |
378 if (!is_in_page) { | 379 if (!is_in_page) |
379 pending_login_managers_.clear(); | 380 pending_login_managers_.clear(); |
380 // There is no PasswordAutofillManager on iOS. | |
381 if (driver_->GetPasswordAutofillManager()) | |
382 driver_->GetPasswordAutofillManager()->Reset(); | |
383 } | |
384 } | 381 } |
385 | 382 |
386 void PasswordManager::OnPasswordFormSubmitted( | 383 void PasswordManager::OnPasswordFormSubmitted( |
| 384 password_manager::PasswordManagerDriver* driver, |
387 const PasswordForm& password_form) { | 385 const PasswordForm& password_form) { |
388 ProvisionallySavePassword(password_form); | 386 ProvisionallySavePassword(password_form); |
389 for (size_t i = 0; i < submission_callbacks_.size(); ++i) { | 387 for (size_t i = 0; i < submission_callbacks_.size(); ++i) { |
390 submission_callbacks_[i].Run(password_form); | 388 submission_callbacks_[i].Run(password_form); |
391 } | 389 } |
392 | 390 |
393 pending_login_managers_.clear(); | 391 pending_login_managers_.clear(); |
394 } | 392 } |
395 | 393 |
396 void PasswordManager::OnPasswordFormsParsed( | 394 void PasswordManager::OnPasswordFormsParsed( |
| 395 password_manager::PasswordManagerDriver* driver, |
397 const std::vector<PasswordForm>& forms) { | 396 const std::vector<PasswordForm>& forms) { |
398 CreatePendingLoginManagers(forms); | 397 CreatePendingLoginManagers(driver, forms); |
399 } | 398 } |
400 | 399 |
401 void PasswordManager::CreatePendingLoginManagers( | 400 void PasswordManager::CreatePendingLoginManagers( |
| 401 password_manager::PasswordManagerDriver* driver, |
402 const std::vector<PasswordForm>& forms) { | 402 const std::vector<PasswordForm>& forms) { |
403 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 403 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
404 if (client_->IsLoggingActive()) { | 404 if (client_->IsLoggingActive()) { |
405 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 405 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
406 logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD); | 406 logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD); |
407 } | 407 } |
408 | 408 |
409 if (!IsEnabledForCurrentPage()) | 409 if (!IsEnabledForCurrentPage()) |
410 return; | 410 return; |
411 | 411 |
(...skipping 19 matching lines...) Expand all Loading... |
431 !old_manager_found && old_manager != old_login_managers.end(); | 431 !old_manager_found && old_manager != old_login_managers.end(); |
432 ++old_manager) { | 432 ++old_manager) { |
433 old_manager_found = (*old_manager)->DoesManage(*iter) == | 433 old_manager_found = (*old_manager)->DoesManage(*iter) == |
434 PasswordFormManager::RESULT_COMPLETE_MATCH; | 434 PasswordFormManager::RESULT_COMPLETE_MATCH; |
435 } | 435 } |
436 if (old_manager_found) | 436 if (old_manager_found) |
437 continue; // The current form is already managed. | 437 continue; // The current form is already managed. |
438 | 438 |
439 bool ssl_valid = iter->origin.SchemeIsSecure(); | 439 bool ssl_valid = iter->origin.SchemeIsSecure(); |
440 PasswordFormManager* manager = | 440 PasswordFormManager* manager = |
441 new PasswordFormManager(this, client_, driver_, *iter, ssl_valid); | 441 new PasswordFormManager(this, client_, driver, *iter, ssl_valid); |
442 pending_login_managers_.push_back(manager); | 442 pending_login_managers_.push_back(manager); |
443 | 443 |
444 PasswordStore::AuthorizationPromptPolicy prompt_policy = | 444 PasswordStore::AuthorizationPromptPolicy prompt_policy = |
445 client_->GetAuthorizationPromptPolicy(*iter); | 445 client_->GetAuthorizationPromptPolicy(*iter); |
446 | 446 |
447 manager->FetchMatchingLoginsFromPasswordStore(prompt_policy); | 447 manager->FetchMatchingLoginsFromPasswordStore(prompt_policy); |
448 } | 448 } |
449 | 449 |
450 if (logger) { | 450 if (logger) { |
451 logger->LogNumber(Logger::STRING_NEW_NUMBER_LOGIN_MANAGERS, | 451 logger->LogNumber(Logger::STRING_NEW_NUMBER_LOGIN_MANAGERS, |
452 pending_login_managers_.size()); | 452 pending_login_managers_.size()); |
453 } | 453 } |
454 } | 454 } |
455 | 455 |
456 bool PasswordManager::ShouldPromptUserToSavePassword() const { | 456 bool PasswordManager::ShouldPromptUserToSavePassword() const { |
457 return !client_->IsAutomaticPasswordSavingEnabled() && | 457 return !client_->IsAutomaticPasswordSavingEnabled() && |
458 provisional_save_manager_->IsNewLogin() && | 458 provisional_save_manager_->IsNewLogin() && |
459 !provisional_save_manager_->HasGeneratedPassword() && | 459 !provisional_save_manager_->HasGeneratedPassword() && |
460 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); | 460 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); |
461 } | 461 } |
462 | 462 |
463 void PasswordManager::OnPasswordFormsRendered( | 463 void PasswordManager::OnPasswordFormsRendered( |
| 464 password_manager::PasswordManagerDriver* driver, |
464 const std::vector<PasswordForm>& visible_forms, | 465 const std::vector<PasswordForm>& visible_forms, |
465 bool did_stop_loading) { | 466 bool did_stop_loading) { |
466 CreatePendingLoginManagers(visible_forms); | 467 CreatePendingLoginManagers(driver, visible_forms); |
467 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 468 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
468 if (client_->IsLoggingActive()) { | 469 if (client_->IsLoggingActive()) { |
469 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 470 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
470 logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD); | 471 logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD); |
471 } | 472 } |
472 | 473 |
473 if (!provisional_save_manager_.get()) { | 474 if (!provisional_save_manager_.get()) { |
474 if (logger) { | 475 if (logger) { |
475 logger->LogMessage(Logger::STRING_NO_PROVISIONAL_SAVE_MANAGER); | 476 logger->LogMessage(Logger::STRING_NO_PROVISIONAL_SAVE_MANAGER); |
476 } | 477 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 base::FieldTrial::Probability enabled_probability = | 590 base::FieldTrial::Probability enabled_probability = |
590 client_->GetProbabilityForExperiment(kOtherPossibleUsernamesExperiment); | 591 client_->GetProbabilityForExperiment(kOtherPossibleUsernamesExperiment); |
591 trial->AppendGroup("Enabled", enabled_probability); | 592 trial->AppendGroup("Enabled", enabled_probability); |
592 } | 593 } |
593 | 594 |
594 bool PasswordManager::OtherPossibleUsernamesEnabled() const { | 595 bool PasswordManager::OtherPossibleUsernamesEnabled() const { |
595 return base::FieldTrialList::FindFullName( | 596 return base::FieldTrialList::FindFullName( |
596 kOtherPossibleUsernamesExperiment) == "Enabled"; | 597 kOtherPossibleUsernamesExperiment) == "Enabled"; |
597 } | 598 } |
598 | 599 |
599 void PasswordManager::Autofill(const PasswordForm& form_for_autofill, | 600 void PasswordManager::Autofill(password_manager::PasswordManagerDriver* driver, |
| 601 const PasswordForm& form_for_autofill, |
600 const PasswordFormMap& best_matches, | 602 const PasswordFormMap& best_matches, |
601 const PasswordForm& preferred_match, | 603 const PasswordForm& preferred_match, |
602 bool wait_for_username) const { | 604 bool wait_for_username) const { |
603 PossiblyInitializeUsernamesExperiment(best_matches); | 605 PossiblyInitializeUsernamesExperiment(best_matches); |
604 | 606 |
605 scoped_ptr<BrowserSavePasswordProgressLogger> logger; | 607 scoped_ptr<BrowserSavePasswordProgressLogger> logger; |
606 if (client_->IsLoggingActive()) { | 608 if (client_->IsLoggingActive()) { |
607 logger.reset(new BrowserSavePasswordProgressLogger(client_)); | 609 logger.reset(new BrowserSavePasswordProgressLogger(client_)); |
608 logger->LogMessage(Logger::STRING_PASSWORDMANAGER_AUTOFILL); | 610 logger->LogMessage(Logger::STRING_PASSWORDMANAGER_AUTOFILL); |
609 } | 611 } |
610 switch (form_for_autofill.scheme) { | 612 switch (form_for_autofill.scheme) { |
611 case PasswordForm::SCHEME_HTML: { | 613 case PasswordForm::SCHEME_HTML: { |
612 // Note the check above is required because the observers_ for a non-HTML | 614 // Note the check above is required because the observers_ for a non-HTML |
613 // schemed password form may have been freed, so we need to distinguish. | 615 // schemed password form may have been freed, so we need to distinguish. |
614 autofill::PasswordFormFillData fill_data; | 616 autofill::PasswordFormFillData fill_data; |
615 InitPasswordFormFillData(form_for_autofill, | 617 InitPasswordFormFillData(form_for_autofill, |
616 best_matches, | 618 best_matches, |
617 &preferred_match, | 619 &preferred_match, |
618 wait_for_username, | 620 wait_for_username, |
619 OtherPossibleUsernamesEnabled(), | 621 OtherPossibleUsernamesEnabled(), |
620 &fill_data); | 622 &fill_data); |
621 if (logger) | 623 if (logger) |
622 logger->LogBoolean(Logger::STRING_WAIT_FOR_USERNAME, wait_for_username); | 624 logger->LogBoolean(Logger::STRING_WAIT_FOR_USERNAME, wait_for_username); |
623 driver_->FillPasswordForm(fill_data); | 625 driver->FillPasswordForm(fill_data); |
624 break; | 626 break; |
625 } | 627 } |
626 default: | 628 default: |
627 if (logger) { | 629 if (logger) { |
628 logger->LogBoolean(Logger::STRING_LOGINMODELOBSERVER_PRESENT, | 630 logger->LogBoolean(Logger::STRING_LOGINMODELOBSERVER_PRESENT, |
629 observers_.might_have_observers()); | 631 observers_.might_have_observers()); |
630 } | 632 } |
631 FOR_EACH_OBSERVER( | 633 FOR_EACH_OBSERVER( |
632 LoginModelObserver, | 634 LoginModelObserver, |
633 observers_, | 635 observers_, |
634 OnAutofillDataAvailable(preferred_match.username_value, | 636 OnAutofillDataAvailable(preferred_match.username_value, |
635 preferred_match.password_value)); | 637 preferred_match.password_value)); |
636 break; | 638 break; |
637 } | 639 } |
638 | 640 |
639 client_->PasswordWasAutofilled(best_matches); | 641 client_->PasswordWasAutofilled(best_matches); |
640 } | 642 } |
641 | 643 |
642 } // namespace password_manager | 644 } // namespace password_manager |
OLD | NEW |