Commit 9205af99 authored by vabr@chromium.org's avatar vabr@chromium.org

Password manager: introduce logging for the internals page

Follow-up CL of https://codereview.chromium.org/228263004/

This CL adds instances of SavePasswordProgressLogger into crucial parts of the password manager code. After this CL, the logging should already work, i.e., when the command line flag is enabled, the internals page should show debugging info about saving a password on a website.

More context in the design doc: https://docs.google.com/document/d/1ArDhTo0w-8tOPiTwqM1gG6ZGqODo8UTpXlJjjnCNK4s/edit?usp=sharing

BUG=347927

Review URL: https://codereview.chromium.org/231283003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266481 0039d316-1c4b-4281-b951-d872f2087c98
parent 4b06d9be
......@@ -25,6 +25,7 @@
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_logger.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ipc/ipc_message_macros.h"
......@@ -194,6 +195,10 @@ void ChromePasswordManagerClient::SetLogger(
// instances to 1 in normal profiles, and 0 in incognito.
DCHECK(!logger || !logger_);
logger_ = logger;
// Also inform the renderer process to start or stop logging.
web_contents()->GetRenderViewHost()->Send(new AutofillMsg_ChangeLoggingState(
web_contents()->GetRenderViewHost()->GetRoutingID(), logger != NULL));
}
void ChromePasswordManagerClient::LogSavePasswordProgress(
......
......@@ -5,9 +5,11 @@
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/autofill/content/common/autofill_messages.h"
#include "components/password_manager/core/browser/password_manager_logger.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_render_process_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -35,7 +37,12 @@ class ChromePasswordManagerClientTest : public ChromeRenderViewHostTestHarness {
protected:
ChromePasswordManagerClient* GetClient();
testing::StrictMock<MockPasswordManagerLogger> logger;
// If the test IPC sink contains an AutofillMsg_ChangeLoggingState message,
// then copies its argument into |activation_flag| and returns true. Otherwise
// returns false.
bool WasLoggingActivationMessageSent(bool* activation_flag);
testing::StrictMock<MockPasswordManagerLogger> logger_;
};
void ChromePasswordManagerClientTest::SetUp() {
......@@ -48,10 +55,24 @@ ChromePasswordManagerClient* ChromePasswordManagerClientTest::GetClient() {
return ChromePasswordManagerClient::FromWebContents(web_contents());
}
bool ChromePasswordManagerClientTest::WasLoggingActivationMessageSent(
bool* activation_flag) {
const uint32 kMsgID = AutofillMsg_ChangeLoggingState::ID;
const IPC::Message* message =
process()->sink().GetFirstMessageMatching(kMsgID);
if (!message)
return false;
Tuple1<bool> param;
AutofillMsg_ChangeLoggingState::Read(message, &param);
*activation_flag = param.a;
process()->sink().ClearMessages();
return true;
}
TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressNoLogger) {
ChromePasswordManagerClient* client = GetClient();
EXPECT_CALL(logger, LogSavePasswordProgress(kTestText)).Times(0);
EXPECT_CALL(logger_, LogSavePasswordProgress(kTestText)).Times(0);
// Before attaching the logger, no text should be passed.
client->LogSavePasswordProgress(kTestText);
EXPECT_FALSE(client->IsLoggingActive());
......@@ -61,8 +82,8 @@ TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressAttachLogger) {
ChromePasswordManagerClient* client = GetClient();
// After attaching the logger, text should be passed.
client->SetLogger(&logger);
EXPECT_CALL(logger, LogSavePasswordProgress(kTestText)).Times(1);
client->SetLogger(&logger_);
EXPECT_CALL(logger_, LogSavePasswordProgress(kTestText)).Times(1);
client->LogSavePasswordProgress(kTestText);
EXPECT_TRUE(client->IsLoggingActive());
}
......@@ -70,10 +91,26 @@ TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressAttachLogger) {
TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressDetachLogger) {
ChromePasswordManagerClient* client = GetClient();
client->SetLogger(&logger);
client->SetLogger(&logger_);
// After detaching the logger, no text should be passed.
client->SetLogger(NULL);
EXPECT_CALL(logger, LogSavePasswordProgress(kTestText)).Times(0);
EXPECT_CALL(logger_, LogSavePasswordProgress(kTestText)).Times(0);
client->LogSavePasswordProgress(kTestText);
EXPECT_FALSE(client->IsLoggingActive());
}
TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressNotifyRenderer) {
ChromePasswordManagerClient* client = GetClient();
bool logging_active = false;
// Initially, the logging should be off, so no IPC messages.
EXPECT_FALSE(WasLoggingActivationMessageSent(&logging_active));
client->SetLogger(&logger_);
EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
EXPECT_TRUE(logging_active);
client->SetLogger(NULL);
EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
EXPECT_FALSE(logging_active);
}
......@@ -14,6 +14,7 @@
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_registrar.h"
......@@ -135,7 +136,21 @@ void LoginHandler::SetAuth(const base::string16& username,
const base::string16& password) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (TestAndSetAuthHandled())
scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger;
if (password_manager_ && password_manager_->client()->IsLoggingActive()) {
logger.reset(new password_manager::BrowserSavePasswordProgressLogger(
password_manager_->client()));
logger->LogMessage(
autofill::SavePasswordProgressLogger::STRING_SET_AUTH_METHOD);
}
bool already_handled = TestAndSetAuthHandled();
if (logger) {
logger->LogBoolean(
autofill::SavePasswordProgressLogger::STRING_AUTHENTICATION_HANDLED,
already_handled);
}
if (already_handled)
return;
// Tell the password manager the credentials were submitted / accepted.
......@@ -143,6 +158,11 @@ void LoginHandler::SetAuth(const base::string16& username,
password_form_.username_value = username;
password_form_.password_value = password;
password_manager_->ProvisionallySavePassword(password_form_);
if (logger) {
logger->LogPasswordForm(
autofill::SavePasswordProgressLogger::STRING_LOGINHANDLER_FORM,
password_form_);
}
}
// Calling NotifyAuthSupplied() directly instead of posting a task
......
......@@ -113,6 +113,10 @@ IPC_MESSAGE_ROUTED2(AutofillMsg_PreviewForm,
IPC_MESSAGE_ROUTED1(AutofillMsg_FillPasswordForm,
autofill::PasswordFormFillData /* the fill form data*/)
// Notification to start (|active| == true) or stop (|active| == false) logging
// the decisions made about saving the password.
IPC_MESSAGE_ROUTED1(AutofillMsg_ChangeLoggingState, bool /* active */)
// Send the heuristic and server field type predictions to the renderer.
IPC_MESSAGE_ROUTED1(
AutofillMsg_FieldTypePredictionsAvailable,
......
......@@ -130,6 +130,7 @@ class PasswordAutofillAgent : public content::RenderViewObserver {
// RenderView IPC handlers:
void OnFillPasswordForm(const PasswordFormFillData& form_data);
void OnChangeLoggingState(bool active);
// Scans the given frame for password forms and sends them up to the browser.
// If |only_visible| is true, only forms visible in the layout are sent.
......@@ -195,6 +196,9 @@ class PasswordAutofillAgent : public content::RenderViewObserver {
PasswordValueGatekeeper gatekeeper_;
// True indicates that user debug information should be logged.
bool logging_state_active_;
base::WeakPtrFactory<PasswordAutofillAgent> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgent);
......
......@@ -87,6 +87,80 @@ std::string GetStringFromID(SavePasswordProgressLogger::StringID id) {
return "Form name or ID";
case SavePasswordProgressLogger::STRING_MESSAGE:
return "Message";
case SavePasswordProgressLogger::STRING_SET_AUTH_METHOD:
return "LoginHandler::SetAuth";
case SavePasswordProgressLogger::STRING_AUTHENTICATION_HANDLED:
return "Authentication already handled";
case SavePasswordProgressLogger::STRING_LOGINHANDLER_FORM:
return "LoginHandler reports this form";
case SavePasswordProgressLogger::STRING_SEND_PASSWORD_FORMS_METHOD:
return "PasswordAutofillAgent::SendPasswordForms";
case SavePasswordProgressLogger::STRING_SECURITY_ORIGIN:
return "Security origin";
case SavePasswordProgressLogger::STRING_SECURITY_ORIGIN_FAILURE:
return "Security origin cannot access password manager.";
case SavePasswordProgressLogger::STRING_WEBPAGE_EMPTY:
return "Webpage is empty.";
case SavePasswordProgressLogger::STRING_NUMBER_OF_ALL_FORMS:
return "Number of all forms";
case SavePasswordProgressLogger::STRING_FORM_FOUND_ON_PAGE:
return "Form found on page";
case SavePasswordProgressLogger::STRING_FORM_IS_VISIBLE:
return "Form is visible";
case SavePasswordProgressLogger::STRING_FORM_IS_PASSWORD:
return "Form is a password form";
case SavePasswordProgressLogger::STRING_WILL_SUBMIT_FORM_METHOD:
return "PasswordAutofillAgent::WillSubmitForm";
case SavePasswordProgressLogger::STRING_HTML_FORM_FOR_SUBMIT:
return "HTML form for submit";
case SavePasswordProgressLogger::STRING_CREATED_PASSWORD_FORM:
return "Created PasswordForm";
case SavePasswordProgressLogger::STRING_SUBMITTED_PASSWORD_REPLACED:
return "Submitted password replaced with the provisionally saved one.";
case SavePasswordProgressLogger::STRING_DID_START_PROVISIONAL_LOAD_METHOD:
return "PasswordAutofillAgent::DidStartProvisionalLoad";
case SavePasswordProgressLogger::STRING_FORM_FRAME_EQ_FRAME:
return "form_frame == frame";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME:
return "provisionally_saved_forms_[form_frame]";
case SavePasswordProgressLogger::STRING_PASSWORD_FORM_FOUND_ON_PAGE:
return "PasswordForm found on the page";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD:
return "PasswordManager::ProvisionallySavePassword";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM:
return "ProvisionallySavePassword form";
case SavePasswordProgressLogger::STRING_IS_SAVING_ENABLED:
return "IsSavingEnabled";
case SavePasswordProgressLogger::STRING_EMPTY_PASSWORD:
return "Empty password";
case SavePasswordProgressLogger::STRING_EXACT_MATCH:
return "Form manager found, exact match.";
case SavePasswordProgressLogger::STRING_MATCH_WITHOUT_ACTION:
return "Form manager found, match except for action.";
case SavePasswordProgressLogger::STRING_NO_FORM_MANAGER:
return "No form manager found.";
case SavePasswordProgressLogger::STRING_FORM_BLACKLISTED:
return "Form blacklisted.";
case SavePasswordProgressLogger::STRING_INVALID_FORM:
return "Invalid form.";
case SavePasswordProgressLogger::STRING_AUTOCOMPLETE_OFF:
return "Autocomplete=off.";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVED_FORM:
return "provisionally_saved_form";
case SavePasswordProgressLogger::STRING_IGNORE_POSSIBLE_USERNAMES:
return "Ignore other possible usernames";
case SavePasswordProgressLogger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD:
return "PasswordManager::OnPasswordFormsRendered";
case SavePasswordProgressLogger::STRING_NO_PROVISIONAL_SAVE_MANAGER:
return "No provisional save manager";
case SavePasswordProgressLogger::STRING_NUMBER_OF_VISIBLE_FORMS:
return "Number of visible forms";
case SavePasswordProgressLogger::STRING_PASSWORD_FORM_REAPPEARED:
return "Password form re-appeared";
case SavePasswordProgressLogger::STRING_SAVING_DISABLED:
return "Saving disabled";
case SavePasswordProgressLogger::STRING_NO_MATCHING_FORM:
return "No matching form";
case SavePasswordProgressLogger::STRING_INVALID:
return "INVALID";
// Intentionally no default: clause here -- all IDs need to get covered.
......
......@@ -62,6 +62,43 @@ class SavePasswordProgressLogger {
STRING_PSL_MATCH,
STRING_NAME_OR_ID,
STRING_MESSAGE,
STRING_SET_AUTH_METHOD,
STRING_AUTHENTICATION_HANDLED,
STRING_LOGINHANDLER_FORM,
STRING_SEND_PASSWORD_FORMS_METHOD,
STRING_SECURITY_ORIGIN,
STRING_SECURITY_ORIGIN_FAILURE,
STRING_WEBPAGE_EMPTY,
STRING_NUMBER_OF_ALL_FORMS,
STRING_FORM_FOUND_ON_PAGE,
STRING_FORM_IS_VISIBLE,
STRING_FORM_IS_PASSWORD,
STRING_WILL_SUBMIT_FORM_METHOD,
STRING_HTML_FORM_FOR_SUBMIT,
STRING_CREATED_PASSWORD_FORM,
STRING_SUBMITTED_PASSWORD_REPLACED,
STRING_DID_START_PROVISIONAL_LOAD_METHOD,
STRING_FORM_FRAME_EQ_FRAME,
STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
STRING_PASSWORD_FORM_FOUND_ON_PAGE,
STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD,
STRING_PROVISIONALLY_SAVE_PASSWORD_FORM,
STRING_IS_SAVING_ENABLED,
STRING_EMPTY_PASSWORD,
STRING_EXACT_MATCH,
STRING_MATCH_WITHOUT_ACTION,
STRING_NO_FORM_MANAGER,
STRING_FORM_BLACKLISTED,
STRING_INVALID_FORM,
STRING_AUTOCOMPLETE_OFF,
STRING_PROVISIONALLY_SAVED_FORM,
STRING_IGNORE_POSSIBLE_USERNAMES,
STRING_ON_PASSWORD_FORMS_RENDERED_METHOD,
STRING_NO_PROVISIONAL_SAVE_MANAGER,
STRING_NUMBER_OF_VISIBLE_FORMS,
STRING_PASSWORD_FORM_REAPPEARED,
STRING_SAVING_DISABLED,
STRING_NO_MATCHING_FORM,
STRING_INVALID, // Represents a string returned in a case of an error.
STRING_MAX = STRING_INVALID
};
......
......@@ -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();
}
......
......@@ -30,6 +30,7 @@ class PrefRegistrySyncable;
namespace password_manager {
class BrowserSavePasswordProgressLogger;
class PasswordManagerClient;
class PasswordManagerDriver;
class PasswordManagerTest;
......@@ -114,9 +115,12 @@ class PasswordManager : public LoginModel {
};
// Log failure for UMA. Logs additional metrics if the |form_origin|
// corresponds to one of the top, explicitly monitored websites.
// corresponds to one of the top, explicitly monitored websites. For some
// values of |failure| also sends logs to the internals page through |logger|,
// it |logger| is not NULL.
void RecordFailure(ProvisionalSaveFailure failure,
const std::string& form_origin);
const std::string& form_origin,
BrowserSavePasswordProgressLogger* logger);
// Possibly set up FieldTrial for testing other possible usernames. This only
// happens if there are other_possible_usernames to be shown and the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment