summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/password_manager/password_store_mac.cc131
-rw-r--r--chrome/browser/password_manager/password_store_mac.h9
-rw-r--r--chrome/common/notification_type.h8
3 files changed, 113 insertions, 35 deletions
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index f35d5ba..de8e5d5 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -13,9 +13,11 @@
#include "base/mac_util.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
+#include "base/task.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/keychain_mac.h"
#include "chrome/browser/password_manager/login_database.h"
+#include "chrome/browser/password_manager/password_store_change.h"
using webkit_glue::PasswordForm;
@@ -716,6 +718,10 @@ PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain,
}
PasswordStoreMac::~PasswordStoreMac() {
+ if (thread_.get()) {
+ thread_->message_loop()->DeleteSoon(FROM_HERE,
+ notification_service_.release());
+ }
}
bool PasswordStoreMac::Init() {
@@ -725,6 +731,8 @@ bool PasswordStoreMac::Init() {
thread_.reset(NULL);
return false;
}
+ ScheduleTask(NewRunnableMethod(this,
+ &PasswordStoreMac::CreateNotificationService));
return PasswordStore::Init();
}
@@ -736,7 +744,14 @@ void PasswordStoreMac::ScheduleTask(Task* task) {
void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) {
if (AddToKeychainIfNecessary(form)) {
- login_metadata_db_->AddLogin(form);
+ if (login_metadata_db_->AddLogin(form)) {
+ PasswordStoreChangeList changes;
+ changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
+ NotificationService::current()->Notify(
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources(),
+ Details<PasswordStoreChangeList>(&changes));
+ }
}
}
@@ -745,51 +760,93 @@ void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) {
// isn't, which is the behavior we want, so there's no separate update call.
if (AddToKeychainIfNecessary(form)) {
int update_count = 0;
- login_metadata_db_->UpdateLogin(form, &update_count);
- // Update will catch any database entries that we already had, but we could
- // also be updating a keychain-only form, in which case we need to add.
- if (update_count == 0) {
- login_metadata_db_->AddLogin(form);
+ if (login_metadata_db_->UpdateLogin(form, &update_count)) {
+ // Update will catch any database entries that we already had, but we
+ // could also be updating a keychain-only form, in which case we need to
+ // add.
+ PasswordStoreChangeList changes;
+ if (update_count == 0) {
+ if (login_metadata_db_->AddLogin(form)) {
+ changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD,
+ form));
+ }
+ } else {
+ changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE,
+ form));
+ }
+ if (!changes.empty()) {
+ NotificationService::current()->Notify(
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources(),
+ Details<PasswordStoreChangeList>(&changes));
+ }
}
}
}
void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) {
- login_metadata_db_->RemoveLogin(form);
-
- // See if we own a Keychain item associated with this item. We can do an exact
- // search rather than messing around with trying to do fuzzy matching because
- // passwords that we created will always have an exact-match database entry.
- // (If a user does lose their profile but not their keychain we'll treat the
- // entries we find like other imported entries anyway, so it's reasonable to
- // handle deletes on them the way we would for an imported item.)
- MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get());
- owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
- PasswordForm* owned_password_form =
- owned_keychain_adapter.PasswordExactlyMatchingForm(form);
- if (owned_password_form) {
- // If we don't have other forms using it (i.e., a form differing only by
- // the names of the form elements), delete the keychain entry.
- if (!DatabaseHasFormMatchingKeychainForm(form)) {
- owned_keychain_adapter.RemovePassword(form);
+ if (login_metadata_db_->RemoveLogin(form)) {
+ // See if we own a Keychain item associated with this item. We can do an
+ // exact search rather than messing around with trying to do fuzzy matching
+ // because passwords that we created will always have an exact-match
+ // database entry.
+ // (If a user does lose their profile but not their keychain we'll treat the
+ // entries we find like other imported entries anyway, so it's reasonable to
+ // handle deletes on them the way we would for an imported item.)
+ MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get());
+ owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
+ PasswordForm* owned_password_form =
+ owned_keychain_adapter.PasswordExactlyMatchingForm(form);
+ if (owned_password_form) {
+ // If we don't have other forms using it (i.e., a form differing only by
+ // the names of the form elements), delete the keychain entry.
+ if (!DatabaseHasFormMatchingKeychainForm(form)) {
+ owned_keychain_adapter.RemovePassword(form);
+ }
}
+
+ PasswordStoreChangeList changes;
+ changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
+ NotificationService::current()->Notify(
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources(),
+ Details<PasswordStoreChangeList>(&changes));
}
}
void PasswordStoreMac::RemoveLoginsCreatedBetweenImpl(
const base::Time& delete_begin, const base::Time& delete_end) {
- login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, delete_end);
-
- // We can't delete from the Keychain by date because we may be sharing items
- // with database entries that weren't in the delete range. Instead, we find
- // all the Keychain items we own but aren't using any more and delete those.
- std::vector<PasswordForm*> orphan_keychain_forms = GetUnusedKeychainForms();
- // This is inefficient, since we have to re-look-up each keychain item one at
- // a time to delete it even though the search step already had a list of
- // Keychain item references. If this turns out to be noticeably slow we'll
- // need to rearchitect to allow the search and deletion steps to share.
- RemoveKeychainForms(orphan_keychain_forms);
- STLDeleteElements(&orphan_keychain_forms);
+ std::vector<PasswordForm*> forms;
+ if (login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end,
+ &forms)) {
+ if (login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin,
+ delete_end)) {
+ // We can't delete from the Keychain by date because we may be sharing
+ // items with database entries that weren't in the delete range. Instead,
+ // we find all the Keychain items we own but aren't using any more and
+ // delete those.
+ std::vector<PasswordForm*> orphan_keychain_forms =
+ GetUnusedKeychainForms();
+ // This is inefficient, since we have to re-look-up each keychain item
+ // one at a time to delete it even though the search step already had a
+ // list of Keychain item references. If this turns out to be noticeably
+ // slow we'll need to rearchitect to allow the search and deletion steps
+ // to share.
+ RemoveKeychainForms(orphan_keychain_forms);
+ STLDeleteElements(&orphan_keychain_forms);
+
+ PasswordStoreChangeList changes;
+ for (std::vector<PasswordForm*>::const_iterator it = forms.begin();
+ it != forms.end(); ++it) {
+ changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
+ **it));
+ }
+ NotificationService::current()->Notify(
+ NotificationType::LOGINS_CHANGED,
+ NotificationService::AllSources(),
+ Details<PasswordStoreChangeList>(&changes));
+ }
+ }
}
void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request,
@@ -906,3 +963,7 @@ void PasswordStoreMac::RemoveKeychainForms(
owned_keychain_adapter.RemovePassword(**i);
}
}
+
+void PasswordStoreMac::CreateNotificationService() {
+ notification_service_.reset(new NotificationService);
+}
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h
index b746c4b..36dc7b4 100644
--- a/chrome/browser/password_manager/password_store_mac.h
+++ b/chrome/browser/password_manager/password_store_mac.h
@@ -11,6 +11,7 @@
#include "base/thread.h"
#include "chrome/browser/password_manager/login_database.h"
#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/common/notification_service.h"
class MacKeychain;
@@ -68,12 +69,20 @@ class PasswordStoreMac : public PasswordStore {
void RemoveKeychainForms(
const std::vector<webkit_glue::PasswordForm*>& forms);
+ // Allows the creation of |notification_service_| to be scheduled on the right
+ // thread.
+ void CreateNotificationService();
+
scoped_ptr<MacKeychain> keychain_;
scoped_ptr<LoginDatabase> login_metadata_db_;
// Thread that the synchronous methods are run on.
scoped_ptr<base::Thread> thread_;
+ // Since we aren't running on a well-known thread but still want to send out
+ // notifications, we need to run our own service.
+ scoped_ptr<NotificationService> notification_service_;
+
DISALLOW_COPY_AND_ASSIGN(PasswordStoreMac);
};
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 0793b94..eb9c51aa 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -964,6 +964,14 @@ class NotificationType {
BOOKMARK_CONTEXT_MENU_SHOWN,
#endif
+ // Password Store ----------------------------------------------------------
+ // This notification is sent whenenever login entries stored in the password
+ // store are changed. The detail of this notification is a list of changes
+ // represented by a vector of PasswordStoreChange. Each change includes a
+ // change type (ADD, UPDATE, or REMOVE) as well as the
+ // |webkit_glue::PasswordForm|s that were affected.
+ LOGINS_CHANGED,
+
// Count (must be last) ----------------------------------------------------
// Used to determine the number of notification types. Not valid as
// a type parameter when registering for or posting notifications.