Index: components/autofill/core/common/save_password_progress_logger.cc |
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc |
index cdb8dd7a177e97f1542db30a714749683b3094f1..5f051ccf96dd8b821064d72f05e133e5aab1073b 100644 |
--- a/components/autofill/core/common/save_password_progress_logger.cc |
+++ b/components/autofill/core/common/save_password_progress_logger.cc |
@@ -4,9 +4,14 @@ |
#include "components/autofill/core/common/save_password_progress_logger.h" |
+#include <algorithm> |
+ |
#include "base/json/json_writer.h" |
#include "base/logging.h" |
#include "base/numerics/safe_conversions.h" |
+#include "base/strings/string16.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/utf_string_conversions.h" |
#include "base/values.h" |
#include "components/autofill/core/common/password_form.h" |
@@ -20,6 +25,76 @@ namespace autofill { |
namespace { |
+// Note 1: Caching the ID->string map in an array would be probably faster, but |
+// the switch statement is (a) robust against re-ordering, and (b) checks in |
+// compile-time, that all IDs get a string assigned. The expected frequency of |
+// calls is low enough (in particular, zero if password manager internals page |
+// is not open), that optimizing for code robustness is preferred against speed. |
+// Note 2: The messages can be used as dictionary keys. Do not use '.' in them. |
+std::string GetStringFromID(SavePasswordProgressLogger::StringID id) { |
+ switch (id) { |
+ case SavePasswordProgressLogger::STRING_DECISION_ASK: |
+ return "Decision: ASK the user"; |
+ case SavePasswordProgressLogger::STRING_DECISION_DROP: |
+ return "Decision: DROP the password"; |
+ case SavePasswordProgressLogger::STRING_DECISION_SAVE: |
+ return "Decision: SAVE the password"; |
+ case SavePasswordProgressLogger::STRING_METHOD: |
+ return "Form method"; |
+ case SavePasswordProgressLogger::STRING_METHOD_GET: |
+ return "GET"; |
+ case SavePasswordProgressLogger::STRING_METHOD_POST: |
+ return "POST"; |
+ case SavePasswordProgressLogger::STRING_METHOD_EMPTY: |
+ return "(empty)"; |
+ case SavePasswordProgressLogger::STRING_OTHER: |
+ return "(other)"; |
+ case SavePasswordProgressLogger::STRING_SCHEME_HTML: |
+ return "HTML"; |
+ case SavePasswordProgressLogger::STRING_SCHEME_BASIC: |
+ return "Basic"; |
+ case SavePasswordProgressLogger::STRING_SCHEME_DIGEST: |
+ return "Digest"; |
+ case SavePasswordProgressLogger::STRING_SCHEME_MESSAGE: |
+ return "Scheme"; |
+ case SavePasswordProgressLogger::STRING_SIGNON_REALM: |
+ return "Signon realm"; |
+ case SavePasswordProgressLogger::STRING_ORIGINAL_SIGNON_REALM: |
+ return "Original signon realm"; |
+ case SavePasswordProgressLogger::STRING_ORIGIN: |
+ return "Origin"; |
+ case SavePasswordProgressLogger::STRING_ACTION: |
+ return "Action"; |
+ case SavePasswordProgressLogger::STRING_USERNAME_ELEMENT: |
+ return "Username element"; |
+ case SavePasswordProgressLogger::STRING_PASSWORD_ELEMENT: |
+ return "Password element"; |
+ case SavePasswordProgressLogger::STRING_PASSWORD_AUTOCOMPLETE_SET: |
+ return "Password autocomplete set"; |
+ case SavePasswordProgressLogger::STRING_OLD_PASSWORD_ELEMENT: |
+ return "Old password element"; |
+ case SavePasswordProgressLogger::STRING_SSL_VALID: |
+ return "SSL valid"; |
+ case SavePasswordProgressLogger::STRING_PASSWORD_GENERATED: |
+ return "Password generated"; |
+ case SavePasswordProgressLogger::STRING_TIMES_USED: |
+ return "Times used"; |
+ case SavePasswordProgressLogger::STRING_USE_ADDITIONAL_AUTHENTICATION: |
+ return "Use additional authentication"; |
+ case SavePasswordProgressLogger::STRING_PSL_MATCH: |
+ return "PSL match"; |
+ case SavePasswordProgressLogger::STRING_NAME_OR_ID: |
+ return "Form name or ID"; |
+ case SavePasswordProgressLogger::STRING_MESSAGE: |
+ return "Message"; |
+ case SavePasswordProgressLogger::STRING_INVALID: |
+ return "INVALID"; |
+ // Intentionally no default: clause here -- all IDs need to get covered. |
+ } |
+ NOTREACHED(); // Win compilers don't believe this is unreachable. |
+ return std::string(); |
+}; |
+ |
// Removes privacy sensitive parts of |url| (currently all but host and scheme). |
std::string ScrubURL(const GURL& url) { |
if (url.is_valid()) |
@@ -27,112 +102,150 @@ std::string ScrubURL(const GURL& url) { |
return std::string(); |
} |
+// Returns true for all characters which we don't want to see in the logged IDs |
+// or names of HTML elements. |
+bool IsUnwantedInElementID(char c) { |
+ return !(c == '_' || c == '-' || IsAsciiAlpha(c) || IsAsciiDigit(c)); |
+} |
+ |
+// Replaces all characters satisfying IsUnwantedInElementID by a ' ', and turns |
+// all characters to lowercase. This damages some valid HTML element IDs or |
+// names, but it is likely that it will be still possible to match the scrubbed |
+// string to the original ID or name in the HTML doc. That's good enough for the |
+// logging purposes, and provides some security benefits. |
+std::string ScrubElementID(std::string element_id) { |
+ std::replace_if( |
+ element_id.begin(), element_id.end(), IsUnwantedInElementID, ' '); |
+ return StringToLowerASCII(element_id); |
+} |
+ |
+std::string ScrubElementID(const base::string16& element_id) { |
+ return ScrubElementID(base::UTF16ToUTF8(element_id)); |
+} |
+ |
std::string FormSchemeToString(PasswordForm::Scheme scheme) { |
+ SavePasswordProgressLogger::StringID result_id = |
+ SavePasswordProgressLogger::STRING_INVALID; |
switch (scheme) { |
case PasswordForm::SCHEME_HTML: |
- return "HTML"; |
+ result_id = SavePasswordProgressLogger::STRING_SCHEME_HTML; |
+ break; |
case PasswordForm::SCHEME_BASIC: |
- return "BASIC"; |
+ result_id = SavePasswordProgressLogger::STRING_SCHEME_BASIC; |
+ break; |
case PasswordForm::SCHEME_DIGEST: |
- return "DIGEST"; |
+ result_id = SavePasswordProgressLogger::STRING_SCHEME_DIGEST; |
+ break; |
case PasswordForm::SCHEME_OTHER: |
- return "OTHER"; |
+ result_id = SavePasswordProgressLogger::STRING_OTHER; |
+ break; |
} |
- NOTREACHED(); // Win compilers don't believe this is unreachable. |
- return std::string(); |
+ return GetStringFromID(result_id); |
} |
-StringValue DecisionToStringValue( |
- SavePasswordProgressLogger::Decision decision) { |
- switch (decision) { |
- case SavePasswordProgressLogger::DECISION_SAVE: |
- return StringValue("SAVE the password"); |
- case SavePasswordProgressLogger::DECISION_ASK: |
- return StringValue("ASK the user whether to save the password"); |
- case SavePasswordProgressLogger::DECISION_DROP: |
- return StringValue("DROP the password"); |
- } |
- NOTREACHED(); // Win compilers don't believe this is unreachable. |
- return StringValue(std::string()); |
+std::string FormMethodToString(const std::string& method) { |
+ std::string method_processed; |
+ base::TrimWhitespaceASCII( |
+ StringToLowerASCII(method), base::TRIM_ALL, &method_processed); |
+ SavePasswordProgressLogger::StringID result_id = |
+ SavePasswordProgressLogger::STRING_OTHER; |
+ if (method_processed.empty()) |
+ result_id = SavePasswordProgressLogger::STRING_METHOD_EMPTY; |
+ else if (method_processed == "get") |
+ result_id = SavePasswordProgressLogger::STRING_METHOD_GET; |
+ else if (method_processed == "post") |
+ result_id = SavePasswordProgressLogger::STRING_METHOD_POST; |
+ return GetStringFromID(result_id); |
} |
} // namespace |
-SavePasswordProgressLogger::SavePasswordProgressLogger() {} |
+SavePasswordProgressLogger::SavePasswordProgressLogger() { |
+} |
-SavePasswordProgressLogger::~SavePasswordProgressLogger() {} |
+SavePasswordProgressLogger::~SavePasswordProgressLogger() { |
+} |
-void SavePasswordProgressLogger::LogPasswordForm(const std::string& message, |
- const PasswordForm& form) { |
+void SavePasswordProgressLogger::LogPasswordForm( |
+ SavePasswordProgressLogger::StringID label, |
+ const PasswordForm& form) { |
DictionaryValue log; |
- // Do not use the "<<" operator for PasswordForms, because it also prints |
- // passwords. Also, that operator is only for testing. |
- log.SetString("scheme", FormSchemeToString(form.scheme)); |
- log.SetString("signon realm", ScrubURL(GURL(form.signon_realm))); |
- log.SetString("original signon realm", |
+ log.SetString(GetStringFromID(STRING_SCHEME_MESSAGE), |
+ FormSchemeToString(form.scheme)); |
+ log.SetString(GetStringFromID(STRING_SCHEME_MESSAGE), |
+ FormSchemeToString(form.scheme)); |
+ log.SetString(GetStringFromID(STRING_SIGNON_REALM), |
+ ScrubURL(GURL(form.signon_realm))); |
+ log.SetString(GetStringFromID(STRING_ORIGINAL_SIGNON_REALM), |
ScrubURL(GURL(form.original_signon_realm))); |
- log.SetString("origin", ScrubURL(form.origin)); |
- log.SetString("action", ScrubURL(form.action)); |
- log.SetString("username element", form.username_element); |
- log.SetString("password element", form.password_element); |
- log.SetBoolean("password autocomplete set", form.password_autocomplete_set); |
- log.SetString("old password element", form.old_password_element); |
- log.SetBoolean("ssl valid", form.ssl_valid); |
- log.SetBoolean("password generated", |
+ log.SetString(GetStringFromID(STRING_ORIGIN), ScrubURL(form.origin)); |
+ log.SetString(GetStringFromID(STRING_ACTION), ScrubURL(form.action)); |
+ log.SetString(GetStringFromID(STRING_USERNAME_ELEMENT), |
+ ScrubElementID(form.username_element)); |
+ log.SetString(GetStringFromID(STRING_PASSWORD_ELEMENT), |
+ ScrubElementID(form.password_element)); |
+ log.SetBoolean(GetStringFromID(STRING_PASSWORD_AUTOCOMPLETE_SET), |
+ form.password_autocomplete_set); |
+ log.SetString(GetStringFromID(STRING_OLD_PASSWORD_ELEMENT), |
+ ScrubElementID(form.old_password_element)); |
+ log.SetBoolean(GetStringFromID(STRING_SSL_VALID), form.ssl_valid); |
+ log.SetBoolean(GetStringFromID(STRING_PASSWORD_GENERATED), |
form.type == PasswordForm::TYPE_GENERATED); |
- log.SetInteger("times used", form.times_used); |
- log.SetBoolean("use additional authentication", |
+ log.SetInteger(GetStringFromID(STRING_TIMES_USED), form.times_used); |
+ log.SetBoolean(GetStringFromID(STRING_USE_ADDITIONAL_AUTHENTICATION), |
form.use_additional_authentication); |
- log.SetBoolean("is PSL match", form.IsPublicSuffixMatch()); |
- LogValue(message, log); |
+ log.SetBoolean(GetStringFromID(STRING_PSL_MATCH), form.IsPublicSuffixMatch()); |
+ LogValue(label, log); |
} |
-void SavePasswordProgressLogger::LogHTMLForm(const std::string& message, |
- const std::string& name_or_id, |
- const std::string& method, |
- const GURL& action) { |
+void SavePasswordProgressLogger::LogHTMLForm( |
+ SavePasswordProgressLogger::StringID label, |
+ const std::string& name_or_id, |
+ const std::string& method, |
+ const GURL& action) { |
DictionaryValue log; |
- log.SetString("name_or_id", name_or_id); |
- log.SetString("method", method); |
- log.SetString("action", ScrubURL(action)); |
- LogValue(message, log); |
-} |
- |
-void SavePasswordProgressLogger::LogURL(const std::string& message, |
- const GURL& url) { |
- LogValue(message, StringValue(ScrubURL(url))); |
+ log.SetString(GetStringFromID(STRING_NAME_OR_ID), ScrubElementID(name_or_id)); |
+ log.SetString(GetStringFromID(STRING_METHOD), FormMethodToString(method)); |
+ log.SetString(GetStringFromID(STRING_ACTION), ScrubURL(action)); |
+ LogValue(label, log); |
} |
-void SavePasswordProgressLogger::LogBoolean(const std::string& message, |
- bool value) { |
- LogValue(message, FundamentalValue(value)); |
+void SavePasswordProgressLogger::LogURL( |
+ SavePasswordProgressLogger::StringID label, |
+ const GURL& url) { |
+ LogValue(label, StringValue(ScrubURL(url))); |
} |
-void SavePasswordProgressLogger::LogNumber(const std::string& message, |
- int value) { |
- LogValue(message, FundamentalValue(value)); |
+void SavePasswordProgressLogger::LogBoolean( |
+ SavePasswordProgressLogger::StringID label, |
+ bool truth_value) { |
+ LogValue(label, FundamentalValue(truth_value)); |
} |
-void SavePasswordProgressLogger::LogNumber(const std::string& message, |
- size_t value) { |
- LogValue(message, FundamentalValue(checked_cast<int, size_t>(value))); |
+void SavePasswordProgressLogger::LogNumber( |
+ SavePasswordProgressLogger::StringID label, |
+ int signed_number) { |
+ LogValue(label, FundamentalValue(signed_number)); |
} |
-void SavePasswordProgressLogger::LogFinalDecision(Decision decision) { |
- LogValue("Final decision taken", DecisionToStringValue(decision)); |
+void SavePasswordProgressLogger::LogNumber( |
+ SavePasswordProgressLogger::StringID label, |
+ size_t unsigned_number) { |
+ int signed_number = checked_cast<int, size_t>(unsigned_number); |
+ LogNumber(label, signed_number); |
} |
-void SavePasswordProgressLogger::LogMessage(const std::string& message) { |
- LogValue("Message", StringValue(message)); |
+void SavePasswordProgressLogger::LogMessage( |
+ SavePasswordProgressLogger::StringID message) { |
+ LogValue(STRING_MESSAGE, StringValue(GetStringFromID(message))); |
} |
-void SavePasswordProgressLogger::LogValue(const std::string& name, |
- const Value& log) { |
+void SavePasswordProgressLogger::LogValue(StringID label, const Value& log) { |
std::string log_string; |
bool conversion_to_string_successful = base::JSONWriter::WriteWithOptions( |
&log, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string); |
DCHECK(conversion_to_string_successful); |
- SendLog(name + ": " + log_string); |
+ SendLog(GetStringFromID(label) + ": " + log_string); |
} |
} // namespace autofill |