Index: chrome/browser/password_manager/native_backend_gnome_x.cc |
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc |
index 788858d95365d6aacaeb5bdb1cde25a3b4e3bd17..c974b0a569c5aa6e8315ed410bc982a74ca8b579 100644 |
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc |
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc |
@@ -13,6 +13,8 @@ |
#include "base/basictypes.h" |
#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/metrics/histogram.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_piece.h" |
#include "base/strings/string_util.h" |
@@ -20,6 +22,7 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/time/time.h" |
+#include "chrome/browser/password_manager/psl_matching_helper.h" |
#include "components/autofill/core/common/password_form.h" |
#include "content/public/browser/browser_thread.h" |
@@ -98,7 +101,7 @@ const char kGnomeKeyringAppString[] = "chrome"; |
// Convert the attributes of a given keyring entry into a new PasswordForm. |
// Note: does *not* get the actual password, as that is not a key attribute! |
// Returns NULL if the attributes are for the wrong application. |
-PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
+scoped_ptr<PasswordForm> FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
// Read the string and int attributes into the appropriate map. |
std::map<std::string, std::string> string_attr_map; |
std::map<std::string, uint32_t> uint_attr_map; |
@@ -112,9 +115,9 @@ PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
// Check to make sure this is a password we care about. |
const std::string& app_value = string_attr_map["application"]; |
if (!base::StringPiece(app_value).starts_with(kGnomeKeyringAppString)) |
- return NULL; |
+ return scoped_ptr<PasswordForm>(); |
- PasswordForm* form = new PasswordForm(); |
+ scoped_ptr<PasswordForm> form(new PasswordForm()); |
form->origin = GURL(string_attr_map["origin_url"]); |
form->action = GURL(string_attr_map["action_url"]); |
form->username_element = UTF8ToUTF16(string_attr_map["username_element"]); |
@@ -132,31 +135,55 @@ PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
form->blacklisted_by_user = uint_attr_map["blacklisted_by_user"]; |
form->scheme = static_cast<PasswordForm::Scheme>(uint_attr_map["scheme"]); |
- return form; |
+ return form.Pass(); |
} |
// Parse all the results from the given GList into a PasswordFormList, and free |
// the GList. PasswordForms are allocated on the heap, and should be deleted by |
-// the consumer. |
+// the consumer. If not empty, |filter_by_signon_realm| is used to filter out |
+// results -- only credentials with signon realms passing the PSL matching |
+// (done by |helper|) against |filter_by_signon_realm| will be kept. |
void ConvertFormList(GList* found, |
+ const std::string& filter_by_signon_realm, |
+ const PSLMatchingHelper& helper, |
NativeBackendGnome::PasswordFormList* forms) { |
+ PSLMatchingHelper::PSLDomainMatchMetric psl_domain_match_metric = |
+ PSLMatchingHelper::PSL_DOMAIN_MATCH_NONE; |
for (GList* element = g_list_first(found); element != NULL; |
element = g_list_next(element)) { |
GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
GnomeKeyringAttributeList* attrs = data->attributes; |
- PasswordForm* form = FormFromAttributes(attrs); |
+ scoped_ptr<PasswordForm> form(FormFromAttributes(attrs)); |
if (form) { |
+ if (!filter_by_signon_realm.empty() && |
+ form->signon_realm != filter_by_signon_realm) { |
+ // This is not an exact match, we try PSL matching. |
+ if (!(PSLMatchingHelper::IsPublicSuffixDomainMatch( |
+ filter_by_signon_realm, form->signon_realm))) { |
+ continue; |
+ } |
+ psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_FOUND; |
+ form->original_signon_realm = form->signon_realm; |
+ } |
if (data->secret) { |
form->password_value = UTF8ToUTF16(data->secret); |
} else { |
LOG(WARNING) << "Unable to access password from list element!"; |
} |
- forms->push_back(form); |
+ forms->push_back(form.release()); |
} else { |
LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; |
} |
} |
+ if (!filter_by_signon_realm.empty()) { |
+ UMA_HISTOGRAM_ENUMERATION( |
+ "PasswordManager.PslDomainMatchTriggering", |
+ helper.IsMatchingEnabled() |
+ ? psl_domain_match_metric |
+ : PSLMatchingHelper::PSL_DOMAIN_MATCH_DISABLED, |
+ PSLMatchingHelper::PSL_DOMAIN_MATCH_COUNT); |
+ } |
} |
// Schema is analagous to the fields in PasswordForm. |
@@ -250,6 +277,12 @@ class GKRMethod : public GnomeKeyringLoader { |
base::WaitableEvent event_; |
GnomeKeyringResult result_; |
NativeBackendGnome::PasswordFormList forms_; |
+ // Two additional arguments to OnOperationGetList: |
+ // If the credential search is related to a particular form, |
+ // |original_signon_realm_| contains the signon realm of that form. It is used |
+ // to filter the relevant results out of all the found ones. |
+ std::string original_signon_realm_; |
+ const PSLMatchingHelper helper_; |
}; |
void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { |
@@ -286,6 +319,7 @@ void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { |
void GKRMethod::AddLoginSearch(const PasswordForm& form, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ original_signon_realm_ = form.signon_realm; |
// Search GNOME Keyring for matching passwords to update. |
ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
AppendString(&attrs, "origin_url", form.origin.spec()); |
@@ -305,6 +339,7 @@ void GKRMethod::AddLoginSearch(const PasswordForm& form, |
void GKRMethod::UpdateLoginSearch(const PasswordForm& form, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ original_signon_realm_ = form.signon_realm; |
// Search GNOME Keyring for matching passwords to update. |
ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
AppendString(&attrs, "origin_url", form.origin.spec()); |
@@ -341,9 +376,14 @@ void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) { |
void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ original_signon_realm_ = form.signon_realm; |
// Search GNOME Keyring for matching passwords. |
ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
- AppendString(&attrs, "signon_realm", form.signon_realm); |
+ if (!helper_.ShouldPSLDomainMatchingApply( |
+ PSLMatchingHelper::GetRegistryControlledDomain( |
+ GURL(form.signon_realm)))) { |
+ AppendString(&attrs, "signon_realm", form.signon_realm); |
+ } |
AppendString(&attrs, "application", app_string); |
gnome_keyring_find_items(GNOME_KEYRING_ITEM_GENERIC_SECRET, |
attrs.get(), |
@@ -355,6 +395,7 @@ void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { |
void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ original_signon_realm_.clear(); |
// Search GNOME Keyring for matching passwords. |
ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
AppendUint32(&attrs, "blacklisted_by_user", blacklisted_by_user); |
@@ -368,6 +409,7 @@ void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user, |
void GKRMethod::GetAllLogins(const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ original_signon_realm_.clear(); |
// We need to search for something, otherwise we get no results - so |
// we search for the fixed application string. |
ScopedAttributeList attrs(gnome_keyring_attribute_list_new()); |
@@ -434,7 +476,9 @@ void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list, |
method->result_ = result; |
method->forms_.clear(); |
// |list| will be freed after this callback returns, so convert it now. |
- ConvertFormList(list, &method->forms_); |
+ ConvertFormList( |
+ list, method->original_signon_realm_, method->helper_, &method->forms_); |
+ method->original_signon_realm_.clear(); |
method->event_.Signal(); |
} |