| Index: components/password_manager/core/browser/password_manager.cc
|
| diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
|
| index 0e018826b2be4afe1868a7c780cdd65df9d9d714..55df537ecfb6cb697ca29f84e82869f2502c1f54 100644
|
| --- a/components/password_manager/core/browser/password_manager.cc
|
| +++ b/components/password_manager/core/browser/password_manager.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/threading/platform_thread.h"
|
| #include "components/autofill/core/common/password_autofill_util.h"
|
| +#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
|
| #include "components/password_manager/core/browser/password_autofill_manager.h"
|
| #include "components/password_manager/core/browser/password_form_manager.h"
|
| #include "components/password_manager/core/browser/password_manager_client.h"
|
| @@ -29,6 +30,10 @@ namespace {
|
|
|
| const char kSpdyProxyRealm[] = "/SpdyProxy";
|
|
|
| +// Shorten the name to spare line breaks. The code provides enough context
|
| +// already.
|
| +typedef autofill::SavePasswordProgressLogger Logger;
|
| +
|
| // This routine is called when PasswordManagers are constructed.
|
| //
|
| // Currently we report metrics only once at startup. We require
|
| @@ -109,14 +114,25 @@ bool PasswordManager::IsSavingEnabled() const {
|
| }
|
|
|
| void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| - if (!IsSavingEnabled()) {
|
| - RecordFailure(SAVING_DISABLED, form.origin.host());
|
| + bool is_saving_enabled = IsSavingEnabled();
|
| +
|
| + scoped_ptr<BrowserSavePasswordProgressLogger> logger;
|
| + if (client_->IsLoggingActive()) {
|
| + logger.reset(new BrowserSavePasswordProgressLogger(client_));
|
| + logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD);
|
| + logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM,
|
| + form);
|
| + logger->LogBoolean(Logger::STRING_IS_SAVING_ENABLED, is_saving_enabled);
|
| + }
|
| +
|
| + if (!is_saving_enabled) {
|
| + RecordFailure(SAVING_DISABLED, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| // No password to save? Then don't.
|
| if (form.password_value.empty()) {
|
| - RecordFailure(EMPTY_PASSWORD, form.origin.host());
|
| + RecordFailure(EMPTY_PASSWORD, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| @@ -130,6 +146,8 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| if ((*iter)->DoesManage(form, PasswordFormManager::ACTION_MATCH_REQUIRED)) {
|
| // If we find a manager that exactly matches the submitted form including
|
| // the action URL, exit the loop.
|
| + if (logger)
|
| + logger->LogMessage(Logger::STRING_EXACT_MATCH);
|
| matched_manager_it = iter;
|
| break;
|
| } else if ((*iter)->DoesManage(
|
| @@ -137,6 +155,8 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| // If the current manager matches the submitted form excluding the action
|
| // URL, remember it as a candidate and continue searching for an exact
|
| // match.
|
| + if (logger)
|
| + logger->LogMessage(Logger::STRING_MATCH_WITHOUT_ACTION);
|
| matched_manager_it = iter;
|
| }
|
| }
|
| @@ -149,7 +169,7 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| manager.reset(*matched_manager_it);
|
| pending_login_managers_.weak_erase(matched_manager_it);
|
| } else {
|
| - RecordFailure(NO_MATCHING_FORM, form.origin.host());
|
| + RecordFailure(NO_MATCHING_FORM, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| @@ -158,20 +178,20 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| // results for the given form and autofill. If this is the case, we just
|
| // give up.
|
| if (!manager->HasCompletedMatching()) {
|
| - RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host());
|
| + RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| // Also get out of here if the user told us to 'never remember' passwords for
|
| // this form.
|
| if (manager->IsBlacklisted()) {
|
| - RecordFailure(FORM_BLACKLISTED, form.origin.host());
|
| + RecordFailure(FORM_BLACKLISTED, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| // Bail if we're missing any of the necessary form components.
|
| if (!manager->HasValidPasswordForm()) {
|
| - RecordFailure(INVALID_FORM, form.origin.host());
|
| + RecordFailure(INVALID_FORM, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| @@ -180,7 +200,7 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| // autocomplete attribute if autocomplete='off' is not ignored.
|
| if (!autofill::ShouldIgnoreAutocompleteOffForPasswordFields() &&
|
| !manager->HasGeneratedPassword() && !form.password_autocomplete_set) {
|
| - RecordFailure(AUTOCOMPLETE_OFF, form.origin.host());
|
| + RecordFailure(AUTOCOMPLETE_OFF, form.origin.host(), logger.get());
|
| return;
|
| }
|
|
|
| @@ -189,16 +209,26 @@ void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
|
| form.origin.SchemeIsSecure() &&
|
| !driver_->DidLastPageLoadEncounterSSLErrors();
|
| provisionally_saved_form.preferred = true;
|
| + if (logger) {
|
| + logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM,
|
| + provisionally_saved_form);
|
| + }
|
| PasswordFormManager::OtherPossibleUsernamesAction action =
|
| PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES;
|
| if (OtherPossibleUsernamesEnabled())
|
| action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES;
|
| + if (logger) {
|
| + logger->LogBoolean(
|
| + Logger::STRING_IGNORE_POSSIBLE_USERNAMES,
|
| + action == PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
|
| + }
|
| manager->ProvisionallySave(provisionally_saved_form, action);
|
| provisional_save_manager_.swap(manager);
|
| }
|
|
|
| void PasswordManager::RecordFailure(ProvisionalSaveFailure failure,
|
| - const std::string& form_origin) {
|
| + const std::string& form_origin,
|
| + BrowserSavePasswordProgressLogger* logger) {
|
| UMA_HISTOGRAM_ENUMERATION(
|
| "PasswordManager.ProvisionalSaveFailure", failure, MAX_FAILURE_VALUE);
|
|
|
| @@ -210,6 +240,36 @@ void PasswordManager::RecordFailure(ProvisionalSaveFailure failure,
|
| failure,
|
| MAX_FAILURE_VALUE);
|
| }
|
| +
|
| + if (logger) {
|
| + switch (failure) {
|
| + case SAVING_DISABLED:
|
| + logger->LogMessage(Logger::STRING_SAVING_DISABLED);
|
| + break;
|
| + case EMPTY_PASSWORD:
|
| + logger->LogMessage(Logger::STRING_EMPTY_PASSWORD);
|
| + break;
|
| + case MATCHING_NOT_COMPLETE:
|
| + logger->LogMessage(Logger::STRING_NO_FORM_MANAGER);
|
| + break;
|
| + case NO_MATCHING_FORM:
|
| + logger->LogMessage(Logger::STRING_NO_MATCHING_FORM);
|
| + break;
|
| + case FORM_BLACKLISTED:
|
| + logger->LogMessage(Logger::STRING_FORM_BLACKLISTED);
|
| + break;
|
| + case INVALID_FORM:
|
| + logger->LogMessage(Logger::STRING_INVALID_FORM);
|
| + break;
|
| + case AUTOCOMPLETE_OFF:
|
| + logger->LogMessage(Logger::STRING_AUTOCOMPLETE_OFF);
|
| + break;
|
| + case MAX_FAILURE_VALUE:
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + logger->LogMessage(Logger::STRING_DECISION_DROP);
|
| + }
|
| }
|
|
|
| void PasswordManager::AddSubmissionCallback(
|
| @@ -280,11 +340,27 @@ bool PasswordManager::ShouldPromptUserToSavePassword() const {
|
|
|
| void PasswordManager::OnPasswordFormsRendered(
|
| const std::vector<PasswordForm>& visible_forms) {
|
| - if (!provisional_save_manager_.get())
|
| + scoped_ptr<BrowserSavePasswordProgressLogger> logger;
|
| + if (client_->IsLoggingActive()) {
|
| + logger.reset(new BrowserSavePasswordProgressLogger(client_));
|
| + logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD);
|
| + }
|
| +
|
| + if (!provisional_save_manager_.get()) {
|
| + if (logger) {
|
| + logger->LogMessage(Logger::STRING_NO_PROVISIONAL_SAVE_MANAGER);
|
| + logger->LogMessage(Logger::STRING_DECISION_DROP);
|
| + }
|
| return;
|
| + }
|
|
|
| DCHECK(IsSavingEnabled());
|
|
|
| + if (logger) {
|
| + logger->LogNumber(Logger::STRING_NUMBER_OF_VISIBLE_FORMS,
|
| + visible_forms.size());
|
| + }
|
| +
|
| // If we see the login form again, then the login failed.
|
| for (size_t i = 0; i < visible_forms.size(); ++i) {
|
| // TODO(vabr): The similarity check is just action equality for now. If it
|
| @@ -293,6 +369,11 @@ void PasswordManager::OnPasswordFormsRendered(
|
| if (visible_forms[i].action.is_valid() &&
|
| provisional_save_manager_->pending_credentials().action ==
|
| visible_forms[i].action) {
|
| + if (logger) {
|
| + logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED,
|
| + visible_forms[i]);
|
| + logger->LogMessage(Logger::STRING_DECISION_DROP);
|
| + }
|
| provisional_save_manager_->SubmitFailed();
|
| provisional_save_manager_.reset();
|
| return;
|
| @@ -306,8 +387,12 @@ void PasswordManager::OnPasswordFormsRendered(
|
| provisional_save_manager_->SubmitPassed();
|
|
|
| if (ShouldPromptUserToSavePassword()) {
|
| + if (logger)
|
| + logger->LogMessage(Logger::STRING_DECISION_ASK);
|
| client_->PromptUserToSavePassword(provisional_save_manager_.release());
|
| } else {
|
| + if (logger)
|
| + logger->LogMessage(Logger::STRING_DECISION_SAVE);
|
| provisional_save_manager_->Save();
|
| provisional_save_manager_.reset();
|
| }
|
|
|