summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-04 22:21:13 +0000
committermdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-04 22:21:13 +0000
commite43cf994ac0b0840c6712346d8a8788c4a71574a (patch)
tree780031099e2da5b453a493a214ab0246908f08dc /chrome
parent66dc0bdb78955160e52004da17ebab021be64e0c (diff)
downloadchromium_src-e43cf994ac0b0840c6712346d8a8788c4a71574a.zip
chromium_src-e43cf994ac0b0840c6712346d8a8788c4a71574a.tar.gz
chromium_src-e43cf994ac0b0840c6712346d8a8788c4a71574a.tar.bz2
Linux: bring GNOME Keyring and KWallet integration back into a compilable state. Still disabled, however.
BUG=12351,25404 TEST=both now seem to work correctly when enabled (but this CL does not enable them) Review URL: http://codereview.chromium.org/2407001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48983 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/password_manager/password_store.h5
-rw-r--r--chrome/browser/password_manager/password_store_gnome.cc254
-rw-r--r--chrome/browser/password_manager/password_store_gnome.h48
-rw-r--r--chrome/browser/password_manager/password_store_kwallet.cc322
-rw-r--r--chrome/browser/password_manager/password_store_kwallet.h83
5 files changed, 532 insertions, 180 deletions
diff --git a/chrome/browser/password_manager/password_store.h b/chrome/browser/password_manager/password_store.h
index b2e6ef0..14203fd 100644
--- a/chrome/browser/password_manager/password_store.h
+++ b/chrome/browser/password_manager/password_store.h
@@ -110,11 +110,12 @@ class PasswordStore : public base::RefCountedThreadSafe<PasswordStore> {
virtual void UpdateLoginImpl(const webkit_glue::PasswordForm& form) = 0;
// Synchronous implementation to remove the given login.
virtual void RemoveLoginImpl(const webkit_glue::PasswordForm& form) = 0;
+ // Synchronous implementation to remove the given logins.
+ virtual void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
+ const base::Time& delete_end) = 0;
// Should find all PasswordForms with the same signon_realm. The results
// will then be scored by the PasswordFormManager. Once they are found
// (or not), the consumer should be notified.
- virtual void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
- const base::Time& delete_end) = 0;
virtual void GetLoginsImpl(GetLoginsRequest* request,
const webkit_glue::PasswordForm& form) = 0;
// Finds all non-blacklist PasswordForms, and notifies the consumer.
diff --git a/chrome/browser/password_manager/password_store_gnome.cc b/chrome/browser/password_manager/password_store_gnome.cc
index 93f3b6f..f57208d 100644
--- a/chrome/browser/password_manager/password_store_gnome.cc
+++ b/chrome/browser/password_manager/password_store_gnome.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,10 +10,14 @@
#include "base/string_util.h"
#include "base/task.h"
#include "base/time.h"
+#include "base/utf_string_conversions.h"
using std::map;
using std::string;
using std::vector;
+using webkit_glue::PasswordForm;
+
+#define GNOME_KEYRING_APPLICATION_CHROME "chrome"
// Schema is analagous to the fields in PasswordForm.
const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = {
@@ -30,11 +34,15 @@ const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = {
{ "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
{ "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
{ "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
+ // This field is always "chrome" so that we can search for it.
+ { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
{ NULL }
}
};
-PasswordStoreGnome::PasswordStoreGnome() {
+PasswordStoreGnome::PasswordStoreGnome(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service) {
}
PasswordStoreGnome::~PasswordStoreGnome() {
@@ -45,91 +53,222 @@ bool PasswordStoreGnome::Init() {
}
void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) {
- AutoLock l(gnome_keyring_lock_);
- GnomeKeyringResult result = gnome_keyring_store_password_sync(
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ AddLoginHelper(form, base::Time::Now());
+}
+
+void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) {
+ // Based on LoginDatabase::UpdateLogin(), we search for forms to update by
+ // origin_url, username_element, username_value, password_element, and
+ // signon_realm. We then compare the result to the updated form. If they
+ // differ in any of the action, password_value, ssl_valid, or preferred
+ // fields, then we add a new login with those fields updated and only delete
+ // the original on success.
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ GList* found = NULL;
+ // Search gnome keyring for matching passwords.
+ GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ &found,
+ "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ form.origin.spec().c_str(),
+ "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ UTF16ToUTF8(form.username_element).c_str(),
+ "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ UTF16ToUTF8(form.username_value).c_str(),
+ "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ UTF16ToUTF8(form.password_element).c_str(),
+ "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ form.signon_realm.c_str(),
+ "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ GNOME_KEYRING_APPLICATION_CHROME,
+ NULL);
+ vector<PasswordForm*> forms;
+ if (result == GNOME_KEYRING_RESULT_OK) {
+ FillFormVector(found, &forms);
+ for (size_t i = 0; i < forms.size(); ++i) {
+ if (forms[i]->action != form.action ||
+ forms[i]->password_value != form.password_value ||
+ forms[i]->ssl_valid != form.ssl_valid ||
+ forms[i]->preferred != form.preferred) {
+ PasswordForm updated = *forms[i];
+ updated.action = form.action;
+ updated.password_value = form.password_value;
+ updated.ssl_valid = form.ssl_valid;
+ updated.preferred = form.preferred;
+ if (AddLoginHelper(updated, updated.date_created))
+ RemoveLoginImpl(*forms[i]);
+ }
+ delete forms[i];
+ }
+ } else {
+ LOG(ERROR) << "Keyring find failed: "
+ << gnome_keyring_result_to_message(result);
+ }
+}
+
+void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ // We find forms using the same fields as LoginDatabase::RemoveLogin().
+ GnomeKeyringResult result = gnome_keyring_delete_password_sync(
&kGnomeSchema,
- NULL, // Default keyring.
- // TODO(johnmaguire@google.com): Localise this.
- "Form password stored by Chrome",
- WideToASCII(form.password_value).c_str(),
"origin_url", form.origin.spec().c_str(),
"action_url", form.action.spec().c_str(),
- "username_element", form.username_element.c_str(),
- "username_value", form.username_value.c_str(),
- "password_element", form.password_element.c_str(),
- "submit_element", form.submit_element.c_str(),
+ "username_element", UTF16ToUTF8(form.username_element).c_str(),
+ "username_value", UTF16ToUTF8(form.username_value).c_str(),
+ "password_element", UTF16ToUTF8(form.password_element).c_str(),
+ "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
"signon_realm", form.signon_realm.c_str(),
- "ssl_valid", form.ssl_valid,
- "preferred", form.preferred,
- "date_created", Int64ToString(base::Time::Now().ToTimeT()).c_str(),
- "blacklisted_by_user", form.blacklisted_by_user,
- "scheme", form.scheme,
NULL);
-
if (result != GNOME_KEYRING_RESULT_OK) {
- LOG(ERROR) << "Keyring save failed: "
+ LOG(ERROR) << "Keyring delete failed: "
<< gnome_keyring_result_to_message(result);
}
}
-void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) {
- AddLoginImpl(form); // Add & Update are the same in gnome keyring.
+void PasswordStoreGnome::RemoveLoginsCreatedBetweenImpl(
+ const base::Time& delete_begin,
+ const base::Time& delete_end) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ GList* found = NULL;
+ // Search GNOME keyring for all passwords, then delete the ones in the range.
+ // We need to search for something, otherwise we get no results - so we search
+ // for the fixed application string.
+ GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ &found,
+ "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ GNOME_KEYRING_APPLICATION_CHROME,
+ NULL);
+ if (result == GNOME_KEYRING_RESULT_OK) {
+ // We could walk the list and delete items as we find them, but it is much
+ // easier to build the vector and use RemoveLoginImpl() to delete them.
+ vector<PasswordForm*> forms;
+ FillFormVector(found, &forms);
+ for (size_t i = 0; i < forms.size(); ++i) {
+ if (delete_begin <= forms[i]->date_created &&
+ (delete_end.is_null() || forms[i]->date_created < delete_end)) {
+ RemoveLoginImpl(*forms[i]);
+ }
+ delete forms[i];
+ }
+ } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
+ LOG(ERROR) << "Keyring find failed: "
+ << gnome_keyring_result_to_message(result);
+ }
}
-void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) {
- AutoLock l(gnome_keyring_lock_);
- GnomeKeyringResult result = gnome_keyring_delete_password_sync(
+void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request,
+ const PasswordForm& form) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ GList* found = NULL;
+ // Search gnome keyring for matching passwords.
+ GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ &found,
+ "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ form.signon_realm.c_str(),
+ "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ GNOME_KEYRING_APPLICATION_CHROME,
+ NULL);
+ vector<PasswordForm*> forms;
+ if (result == GNOME_KEYRING_RESULT_OK) {
+ FillFormVector(found, &forms);
+ } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
+ LOG(ERROR) << "Keyring find failed: "
+ << gnome_keyring_result_to_message(result);
+ }
+ NotifyConsumer(request, forms);
+}
+
+void PasswordStoreGnome::GetAutofillableLoginsImpl(
+ GetLoginsRequest* request) {
+ std::vector<PasswordForm*> forms;
+ FillAutofillableLogins(&forms);
+ NotifyConsumer(request, forms);
+}
+
+void PasswordStoreGnome::GetBlacklistLoginsImpl(
+ GetLoginsRequest* request) {
+ std::vector<PasswordForm*> forms;
+ FillBlacklistLogins(&forms);
+ NotifyConsumer(request, forms);
+}
+
+bool PasswordStoreGnome::FillAutofillableLogins(
+ std::vector<PasswordForm*>* forms) {
+ return FillSomeLogins(true, forms);
+}
+
+bool PasswordStoreGnome::FillBlacklistLogins(
+ std::vector<PasswordForm*>* forms) {
+ return FillSomeLogins(false, forms);
+}
+
+bool PasswordStoreGnome::AddLoginHelper(const PasswordForm& form,
+ const base::Time& date_created) {
+ GnomeKeyringResult result = gnome_keyring_store_password_sync(
&kGnomeSchema,
+ NULL, // Default keyring.
+ form.origin.spec().c_str(), // Display name.
+ UTF16ToUTF8(form.password_value).c_str(),
"origin_url", form.origin.spec().c_str(),
"action_url", form.action.spec().c_str(),
- "username_element", form.username_element.c_str(),
- "username_value", form.username_value.c_str(),
- "password_element", form.password_element.c_str(),
- "submit_element", form.submit_element.c_str(),
+ "username_element", UTF16ToUTF8(form.username_element).c_str(),
+ "username_value", UTF16ToUTF8(form.username_value).c_str(),
+ "password_element", UTF16ToUTF8(form.password_element).c_str(),
+ "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
"signon_realm", form.signon_realm.c_str(),
"ssl_valid", form.ssl_valid,
"preferred", form.preferred,
- "date_created", Int64ToString(form.date_created.ToTimeT()).c_str(),
+ "date_created", Int64ToString(date_created.ToTimeT()).c_str(),
"blacklisted_by_user", form.blacklisted_by_user,
"scheme", form.scheme,
+ "application", GNOME_KEYRING_APPLICATION_CHROME,
NULL);
+
if (result != GNOME_KEYRING_RESULT_OK) {
- LOG(ERROR) << "Keyring delete failed: "
+ LOG(ERROR) << "Keyring save failed: "
<< gnome_keyring_result_to_message(result);
+ return false;
}
+ return true;
}
-void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request) {
- AutoLock l(gnome_keyring_lock_);
+bool PasswordStoreGnome::FillSomeLogins(
+ bool autofillable,
+ std::vector<PasswordForm*>* forms) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
GList* found = NULL;
+ uint32_t blacklisted_by_user = !autofillable;
// Search gnome keyring for matching passwords.
GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
GNOME_KEYRING_ITEM_GENERIC_SECRET,
&found,
- "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
- request->form.signon_realm.c_str(),
+ "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32,
+ blacklisted_by_user,
+ "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ GNOME_KEYRING_APPLICATION_CHROME,
NULL);
- vector<PasswordForm*> forms;
- if (result == GNOME_KEYRING_RESULT_NO_MATCH) {
- NotifyConsumer(request, forms);
- return;
- } else if (result != GNOME_KEYRING_RESULT_OK) {
+ if (result == GNOME_KEYRING_RESULT_OK) {
+ FillFormVector(found, forms);
+ } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
LOG(ERROR) << "Keyring find failed: "
<< gnome_keyring_result_to_message(result);
- NotifyConsumer(request, forms);
- return;
+ return false;
}
+ return true;
+}
- // Parse all the results from the returned GList into a
- // vector<PasswordForm*>. PasswordForms are allocated on the heap. These
- // will be deleted by the consumer.
+void PasswordStoreGnome::FillFormVector(GList* found,
+ std::vector<PasswordForm*>* forms) {
GList* element = g_list_first(found);
while (element != NULL) {
GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data);
char* password = data->secret;
GnomeKeyringAttributeList* attributes = data->attributes;
- // Read the string & int attributes into the appropriate map.
+ // Read the string and int attributes into the appropriate map.
map<string, string> string_attribute_map;
map<string, uint32> uint_attribute_map;
for (unsigned int i = 0; i < attributes->len; ++i) {
@@ -147,31 +286,30 @@ void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request) {
form->origin = GURL(string_attribute_map["origin_url"]);
form->action = GURL(string_attribute_map["action_url"]);
form->username_element =
- ASCIIToWide(string(string_attribute_map["username_element"]));
+ UTF8ToUTF16(string(string_attribute_map["username_element"]));
form->username_value =
- ASCIIToWide(string(string_attribute_map["username_value"]));
+ UTF8ToUTF16(string(string_attribute_map["username_value"]));
form->password_element =
- ASCIIToWide(string(string_attribute_map["password_element"]));
- form->password_value = ASCIIToWide(string(password));
+ UTF8ToUTF16(string(string_attribute_map["password_element"]));
+ form->password_value = UTF8ToUTF16(string(password));
form->submit_element =
- ASCIIToWide(string(string_attribute_map["submit_element"]));
- form->signon_realm = uint_attribute_map["signon_realm"];
+ UTF8ToUTF16(string(string_attribute_map["submit_element"]));
+ form->signon_realm = string_attribute_map["signon_realm"];
form->ssl_valid = uint_attribute_map["ssl_valid"];
form->preferred = uint_attribute_map["preferred"];
string date = string_attribute_map["date_created"];
int64 date_created = 0;
- DCHECK(StringToInt64(date, &date_created) && date_created != 0);
+ bool date_ok = StringToInt64(date, &date_created);
+ DCHECK(date_ok);
+ DCHECK(date_created != 0);
form->date_created = base::Time::FromTimeT(date_created);
form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"];
- form->scheme =
- static_cast<PasswordForm::Scheme>(uint_attribute_map["scheme"]);
+ form->scheme = static_cast<PasswordForm::Scheme>(
+ uint_attribute_map["scheme"]);
- forms.push_back(form);
+ forms->push_back(form);
element = g_list_next(element);
}
gnome_keyring_found_list_free(found);
- found = NULL;
-
- NotifyConsumer(request, forms);
}
diff --git a/chrome/browser/password_manager/password_store_gnome.h b/chrome/browser/password_manager/password_store_gnome.h
index f448ad1..8927ba3 100644
--- a/chrome/browser/password_manager/password_store_gnome.h
+++ b/chrome/browser/password_manager/password_store_gnome.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,31 +9,59 @@ extern "C" {
#include <gnome-keyring.h>
}
+#include <vector>
+
#include "base/lock.h"
+#include "chrome/browser/password_manager/login_database.h"
#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/webdata/web_data_service.h"
class Profile;
class Task;
-// PasswordStore implementation using Gnome Keyring.
+// PasswordStore implementation using GNOME Keyring.
class PasswordStoreGnome : public PasswordStore {
public:
- PasswordStoreGnome();
+ PasswordStoreGnome(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service);
virtual bool Init();
private:
virtual ~PasswordStoreGnome();
- void AddLoginImpl(const PasswordForm& form);
- void UpdateLoginImpl(const PasswordForm& form);
- void RemoveLoginImpl(const PasswordForm& form);
- void GetLoginsImpl(GetLoginsRequest* request);
+ // Implements PasswordStore interface.
+ virtual void AddLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void UpdateLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void RemoveLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
+ const base::Time& delete_end);
+ virtual void GetLoginsImpl(GetLoginsRequest* request,
+ const webkit_glue::PasswordForm& form);
+ virtual void GetAutofillableLoginsImpl(GetLoginsRequest* request);
+ virtual void GetBlacklistLoginsImpl(GetLoginsRequest* request);
+ virtual bool FillAutofillableLogins(
+ std::vector<webkit_glue::PasswordForm*>* forms);
+ virtual bool FillBlacklistLogins(
+ std::vector<webkit_glue::PasswordForm*>* forms);
- static const GnomeKeyringPasswordSchema kGnomeSchema;
+ // Helper for AddLoginImpl() and UpdateLoginImpl() with a success status.
+ bool AddLoginHelper(const webkit_glue::PasswordForm& form,
+ const base::Time& date_created);
+
+ // Helper for FillAutofillableLogins() and FillBlacklistLogins().
+ bool FillSomeLogins(bool autofillable,
+ std::vector<webkit_glue::PasswordForm*>* forms);
- // Mutex for all interactions with Gnome Keyring.
- Lock gnome_keyring_lock_;
+ // Parse all the results from the given GList into a
+ // vector<PasswordForm*>, and free the GList. PasswordForms are
+ // allocated on the heap, and should be deleted by the consumer.
+ void FillFormVector(GList* found,
+ std::vector<webkit_glue::PasswordForm*>* forms);
+
+ static const GnomeKeyringPasswordSchema kGnomeSchema;
DISALLOW_COPY_AND_ASSIGN(PasswordStoreGnome);
};
diff --git a/chrome/browser/password_manager/password_store_kwallet.cc b/chrome/browser/password_manager/password_store_kwallet.cc
index 1c50e3e..26f0ab9 100644
--- a/chrome/browser/password_manager/password_store_kwallet.cc
+++ b/chrome/browser/password_manager/password_store_kwallet.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,12 +9,16 @@
#include "base/logging.h"
#include "base/md5.h"
#include "base/pickle.h"
+#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/task.h"
using std::string;
using std::vector;
+using webkit_glue::PasswordForm;
+// We could localize these strings, but then changing your locale would cause
+// you to lose access to all your stored passwords. Maybe best not to do that.
const char* PasswordStoreKWallet::kAppId = "Chrome";
const char* PasswordStoreKWallet::kKWalletFolder = "Chrome Form Data";
@@ -25,7 +29,9 @@ const char* PasswordStoreKWallet::kKLauncherServiceName = "org.kde.klauncher";
const char* PasswordStoreKWallet::kKLauncherPath = "/KLauncher";
const char* PasswordStoreKWallet::kKLauncherInterface = "org.kde.KLauncher";
-PasswordStoreKWallet::PasswordStoreKWallet()
+PasswordStoreKWallet::PasswordStoreKWallet(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service)
: error_(NULL),
connection_(NULL),
proxy_(NULL) {
@@ -38,13 +44,6 @@ PasswordStoreKWallet::~PasswordStoreKWallet() {
}
bool PasswordStoreKWallet::Init() {
- thread_.reset(new base::Thread("Chrome_KeyringThread"));
-
- if (!thread_->Start()) {
- thread_.reset(NULL);
- return false;
- }
-
// Initialize threading in dbus-glib - it should be fine for
// dbus_g_thread_init to be called multiple times.
if (!g_thread_supported())
@@ -56,8 +55,11 @@ bool PasswordStoreKWallet::Init() {
if (CheckError())
return false;
- if (!StartKWalletd()) return false;
- if (!InitWallet()) return false;
+ if (!InitWallet()) {
+ // kwalletd may not be running. Try to start it and try again.
+ if (!StartKWalletd() || !InitWallet())
+ return false;
+ }
return true;
}
@@ -134,11 +136,12 @@ void PasswordStoreKWallet::AddLoginImpl(const PasswordForm& form) {
return;
PasswordFormList forms;
- GetLoginsList(&forms, form, wallet_handle);
+ GetLoginsList(&forms, form.signon_realm, wallet_handle);
- forms.push_back(const_cast<PasswordForm*>(&form));
+ forms.push_back(new PasswordForm(form));
+ SetLoginsList(forms, form.signon_realm, wallet_handle);
- SetLoginsList(forms, form, wallet_handle);
+ STLDeleteElements(&forms);
}
void PasswordStoreKWallet::UpdateLoginImpl(const PasswordForm& form) {
@@ -148,16 +151,16 @@ void PasswordStoreKWallet::UpdateLoginImpl(const PasswordForm& form) {
return;
PasswordFormList forms;
- GetLoginsList(&forms, form, wallet_handle);
+ GetLoginsList(&forms, form.signon_realm, wallet_handle);
- for (uint i = 0; i < forms.size(); ++i) {
- if (CompareForms(form, *forms[i])) {
- forms.erase(forms.begin() + i);
- forms.insert(forms.begin() + i, const_cast<PasswordForm*>(&form));
- }
+ for (size_t i = 0; i < forms.size(); ++i) {
+ if (CompareForms(form, *forms[i], true))
+ *forms[i] = form;
}
- SetLoginsList(forms, form, wallet_handle);
+ SetLoginsList(forms, form.signon_realm, wallet_handle);
+
+ STLDeleteElements(&forms);
}
void PasswordStoreKWallet::RemoveLoginImpl(const PasswordForm& form) {
@@ -166,57 +169,126 @@ void PasswordStoreKWallet::RemoveLoginImpl(const PasswordForm& form) {
if (wallet_handle == kInvalidKWalletHandle)
return;
- PasswordFormList forms;
- GetLoginsList(&forms, form, wallet_handle);
+ PasswordFormList all_forms;
+ GetLoginsList(&all_forms, form.signon_realm, wallet_handle);
- for (uint i = 0; i < forms.size(); ++i) {
- if (CompareForms(form, *forms[i])) {
- forms.erase(forms.begin() + i);
- --i;
- }
+ PasswordFormList kept_forms;
+ kept_forms.reserve(all_forms.size());
+ for (size_t i = 0; i < all_forms.size(); ++i) {
+ if (CompareForms(form, *all_forms[i], false))
+ delete all_forms[i];
+ else
+ kept_forms.push_back(all_forms[i]);
}
- if (forms.empty()) {
- // No items left? Remove the entry from the wallet.
- int ret = 0;
- dbus_g_proxy_call(proxy_, "removeEntry", &error_,
- G_TYPE_INT, wallet_handle, // handle
- G_TYPE_STRING, kKWalletFolder, // folder
- G_TYPE_STRING, form.signon_realm.c_str(), // key
- G_TYPE_STRING, kAppId, // appid
+ // Update the entry in the wallet.
+ SetLoginsList(kept_forms, form.signon_realm, wallet_handle);
+ STLDeleteElements(&kept_forms);
+}
+
+void PasswordStoreKWallet::RemoveLoginsCreatedBetweenImpl(
+ const base::Time& delete_begin,
+ const base::Time& delete_end) {
+ AutoLock l(kwallet_lock_);
+ int wallet_handle = WalletHandle();
+ if (wallet_handle == kInvalidKWalletHandle)
+ return;
+
+ // We could probably also use readEntryList here.
+ char** realm_list = NULL;
+ dbus_g_proxy_call(proxy_, "entryList", &error_,
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INVALID,
+ G_TYPE_STRV, &realm_list,
+ G_TYPE_INVALID);
+ if (CheckError())
+ return;
+
+ for (char** realm = realm_list; *realm; ++realm) {
+ GArray* byte_array = NULL;
+ dbus_g_proxy_call(proxy_, "readEntry", &error_,
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, *realm, // key
+ G_TYPE_STRING, kAppId, // appid
G_TYPE_INVALID,
- G_TYPE_INT, &ret,
+ DBUS_TYPE_G_UCHAR_ARRAY, &byte_array,
G_TYPE_INVALID);
- CheckError();
- if (ret)
- LOG(ERROR) << "Bad return code " << ret << " from kwallet removeEntry";
- } else {
- // Otherwise update the entry in the wallet.
- SetLoginsList(forms, form, wallet_handle);
+
+ if (CheckError() || !byte_array || !byte_array->len)
+ continue;
+
+ string signon_realm(*realm);
+ Pickle pickle(byte_array->data, byte_array->len);
+ PasswordFormList all_forms;
+ DeserializeValue(signon_realm, pickle, &all_forms);
+ g_array_free(byte_array, true);
+
+ PasswordFormList kept_forms;
+ kept_forms.reserve(all_forms.size());
+ for (size_t i = 0; i < all_forms.size(); ++i) {
+ if (delete_begin <= all_forms[i]->date_created &&
+ (delete_end.is_null() || all_forms[i]->date_created < delete_end)) {
+ delete all_forms[i];
+ } else {
+ kept_forms.push_back(all_forms[i]);
+ }
+ }
+
+ SetLoginsList(kept_forms, signon_realm, wallet_handle);
+ STLDeleteElements(&kept_forms);
}
+ g_strfreev(realm_list);
}
-void PasswordStoreKWallet::GetLoginsImpl(GetLoginsRequest* request) {
+void PasswordStoreKWallet::GetLoginsImpl(GetLoginsRequest* request,
+ const PasswordForm& form) {
PasswordFormList forms;
AutoLock l(kwallet_lock_);
int wallet_handle = WalletHandle();
if (wallet_handle != kInvalidKWalletHandle)
- GetLoginsList(&forms, request->form, wallet_handle);
+ GetLoginsList(&forms, form.signon_realm, wallet_handle);
NotifyConsumer(request, forms);
}
+void PasswordStoreKWallet::GetAutofillableLoginsImpl(
+ GetLoginsRequest* request) {
+ std::vector<PasswordForm*> forms;
+ FillAutofillableLogins(&forms);
+ NotifyConsumer(request, forms);
+}
+
+void PasswordStoreKWallet::GetBlacklistLoginsImpl(
+ GetLoginsRequest* request) {
+ std::vector<PasswordForm*> forms;
+ FillBlacklistLogins(&forms);
+ NotifyConsumer(request, forms);
+}
+
+bool PasswordStoreKWallet::FillAutofillableLogins(
+ std::vector<PasswordForm*>* forms) {
+ return FillSomeLogins(true, forms);
+}
+
+bool PasswordStoreKWallet::FillBlacklistLogins(
+ std::vector<PasswordForm*>* forms) {
+ return FillSomeLogins(false, forms);
+}
+
void PasswordStoreKWallet::GetLoginsList(PasswordFormList* forms,
- const PasswordForm& key,
+ const string& signon_realm,
int wallet_handle) {
// Is there an entry in the wallet?
gboolean has_entry = false;
dbus_g_proxy_call(proxy_, "hasEntry", &error_,
- G_TYPE_INT, wallet_handle, // handle
- G_TYPE_STRING, kKWalletFolder, // folder
- G_TYPE_STRING, key.signon_realm.c_str(), // key
- G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, signon_realm.c_str(), // key
+ G_TYPE_STRING, kAppId, // appid
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &has_entry,
G_TYPE_INVALID);
@@ -226,10 +298,10 @@ void PasswordStoreKWallet::GetLoginsList(PasswordFormList* forms,
GArray* byte_array = NULL;
dbus_g_proxy_call(proxy_, "readEntry", &error_,
- G_TYPE_INT, wallet_handle, // handle
- G_TYPE_STRING, kKWalletFolder, // folder
- G_TYPE_STRING, key.signon_realm.c_str(), // key
- G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, signon_realm.c_str(), // key
+ G_TYPE_STRING, kAppId, // appid
G_TYPE_INVALID,
DBUS_TYPE_G_UCHAR_ARRAY, &byte_array,
G_TYPE_INVALID);
@@ -238,12 +310,30 @@ void PasswordStoreKWallet::GetLoginsList(PasswordFormList* forms,
return;
Pickle pickle(byte_array->data, byte_array->len);
- DeserializeValue(key, pickle, forms);
+ DeserializeValue(signon_realm, pickle, forms);
+ g_array_free(byte_array, true);
}
void PasswordStoreKWallet::SetLoginsList(const PasswordFormList& forms,
- const PasswordForm& key,
+ const string& signon_realm,
int wallet_handle) {
+ if (forms.empty()) {
+ // No items left? Remove the entry from the wallet.
+ int ret = 0;
+ dbus_g_proxy_call(proxy_, "removeEntry", &error_,
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, signon_realm.c_str(), // key
+ G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INVALID,
+ G_TYPE_INT, &ret,
+ G_TYPE_INVALID);
+ CheckError();
+ if (ret != 0)
+ LOG(ERROR) << "Bad return code " << ret << " from kwallet removeEntry";
+ return;
+ }
+
Pickle value;
SerializeValue(forms, &value);
@@ -255,74 +345,144 @@ void PasswordStoreKWallet::SetLoginsList(const PasswordFormList& forms,
// Make the call.
int ret = 0;
dbus_g_proxy_call(proxy_, "writeEntry", &error_,
- G_TYPE_INT, wallet_handle, // handle
- G_TYPE_STRING, kKWalletFolder, // folder
- G_TYPE_STRING, key.signon_realm.c_str(), // key
- DBUS_TYPE_G_UCHAR_ARRAY, byte_array, // value
- G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, signon_realm.c_str(), // key
+ DBUS_TYPE_G_UCHAR_ARRAY, byte_array, // value
+ G_TYPE_STRING, kAppId, // appid
G_TYPE_INVALID,
G_TYPE_INT, &ret,
G_TYPE_INVALID);
g_array_free(byte_array, true);
CheckError();
- if (ret)
+ if (ret != 0)
LOG(ERROR) << "Bad return code " << ret << " from kwallet writeEntry";
}
+bool PasswordStoreKWallet::FillSomeLogins(bool autofillable,
+ PasswordFormList* forms) {
+ AutoLock l(kwallet_lock_);
+ int wallet_handle = WalletHandle();
+ if (wallet_handle == kInvalidKWalletHandle)
+ return false;
+
+ // We could probably also use readEntryList here.
+ char** realm_list = NULL;
+ dbus_g_proxy_call(proxy_, "entryList", &error_,
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INVALID,
+ G_TYPE_STRV, &realm_list,
+ G_TYPE_INVALID);
+ if (CheckError())
+ return false;
+
+ PasswordFormList all_forms;
+ for (char** realm = realm_list; *realm; ++realm) {
+ GArray* byte_array = NULL;
+ dbus_g_proxy_call(proxy_, "readEntry", &error_,
+ G_TYPE_INT, wallet_handle, // handle
+ G_TYPE_STRING, kKWalletFolder, // folder
+ G_TYPE_STRING, *realm, // key
+ G_TYPE_STRING, kAppId, // appid
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_UCHAR_ARRAY, &byte_array,
+ G_TYPE_INVALID);
+
+ if (CheckError() || !byte_array || !byte_array->len)
+ continue;
+
+ Pickle pickle(byte_array->data, byte_array->len);
+ DeserializeValue(*realm, pickle, &all_forms);
+ g_array_free(byte_array, true);
+ }
+ g_strfreev(realm_list);
+
+ // We have to read all the entries, and then filter them here.
+ forms->reserve(forms->size() + all_forms.size());
+ for (size_t i = 0; i < all_forms.size(); ++i) {
+ if (all_forms[i]->blacklisted_by_user == !autofillable)
+ forms->push_back(all_forms[i]);
+ else
+ delete all_forms[i];
+ }
+
+ return true;
+}
+
bool PasswordStoreKWallet::CompareForms(const PasswordForm& a,
- const PasswordForm& b) {
+ const PasswordForm& b,
+ bool update_check) {
+ // An update check doesn't care about the submit element.
+ if (!update_check && a.submit_element != b.submit_element)
+ return false;
return a.origin == b.origin &&
a.password_element == b.password_element &&
a.signon_realm == b.signon_realm &&
- a.submit_element == b.submit_element &&
a.username_element == b.username_element &&
a.username_value == b.username_value;
}
void PasswordStoreKWallet::SerializeValue(const PasswordFormList& forms,
Pickle* pickle) {
- pickle->WriteInt(forms.size());
+ pickle->WriteInt(kPickleVersion);
+ pickle->WriteSize(forms.size());
for (PasswordFormList::const_iterator it = forms.begin() ;
it != forms.end() ; ++it) {
const PasswordForm* form = *it;
pickle->WriteInt(form->scheme);
pickle->WriteString(form->origin.spec());
pickle->WriteString(form->action.spec());
- pickle->WriteWString(form->username_element);
- pickle->WriteWString(form->username_value);
- pickle->WriteWString(form->password_element);
- pickle->WriteWString(form->password_value);
- pickle->WriteWString(form->submit_element);
+ pickle->WriteString16(form->username_element);
+ pickle->WriteString16(form->username_value);
+ pickle->WriteString16(form->password_element);
+ pickle->WriteString16(form->password_value);
+ pickle->WriteString16(form->submit_element);
pickle->WriteBool(form->ssl_valid);
pickle->WriteBool(form->preferred);
pickle->WriteBool(form->blacklisted_by_user);
+ pickle->WriteInt64(form->date_created.ToTimeT());
}
}
-void PasswordStoreKWallet::DeserializeValue(const PasswordForm& key,
+void PasswordStoreKWallet::DeserializeValue(const string& signon_realm,
const Pickle& pickle,
PasswordFormList* forms) {
void* iter = NULL;
- int count = 0;
- pickle.ReadInt(&iter, &count);
+ int version = -1;
+ pickle.ReadInt(&iter, &version);
+ if (version != kPickleVersion) {
+ // This is the only version so far, so anything else is an error.
+ return;
+ }
+
+ size_t count = 0;
+ pickle.ReadSize(&iter, &count);
- for (int i = 0; i < count; ++i) {
+ forms->reserve(forms->size() + count);
+ for (size_t i = 0; i < count; ++i) {
PasswordForm* form = new PasswordForm();
- form->signon_realm.assign(key.signon_realm);
+ form->signon_realm.assign(signon_realm);
- pickle.ReadInt(&iter, reinterpret_cast<int*>(&form->scheme));
+ int scheme = 0;
+ pickle.ReadInt(&iter, &scheme);
+ form->scheme = static_cast<PasswordForm::Scheme>(scheme);
ReadGURL(pickle, &iter, &form->origin);
ReadGURL(pickle, &iter, &form->action);
- pickle.ReadWString(&iter, &form->username_element);
- pickle.ReadWString(&iter, &form->username_value);
- pickle.ReadWString(&iter, &form->password_element);
- pickle.ReadWString(&iter, &form->password_value);
- pickle.ReadWString(&iter, &form->submit_element);
+ pickle.ReadString16(&iter, &form->username_element);
+ pickle.ReadString16(&iter, &form->username_value);
+ pickle.ReadString16(&iter, &form->password_element);
+ pickle.ReadString16(&iter, &form->password_value);
+ pickle.ReadString16(&iter, &form->submit_element);
pickle.ReadBool(&iter, &form->ssl_valid);
pickle.ReadBool(&iter, &form->preferred);
pickle.ReadBool(&iter, &form->blacklisted_by_user);
+ int64 date_created = 0;
+ pickle.ReadInt64(&iter, &date_created);
+ form->date_created = base::Time::FromTimeT(date_created);
forms->push_back(form);
}
}
diff --git a/chrome/browser/password_manager/password_store_kwallet.h b/chrome/browser/password_manager/password_store_kwallet.h
index 317cbdb..f7835fe 100644
--- a/chrome/browser/password_manager/password_store_kwallet.h
+++ b/chrome/browser/password_manager/password_store_kwallet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -12,8 +12,9 @@
#include <vector>
#include "base/lock.h"
-#include "base/thread.h"
+#include "chrome/browser/password_manager/login_database.h"
#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/webdata/web_data_service.h"
#include "webkit/glue/password_form.h"
class Pickle;
@@ -22,38 +23,54 @@ class Task;
class PasswordStoreKWallet : public PasswordStore {
public:
- PasswordStoreKWallet();
+ PasswordStoreKWallet(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service);
bool Init();
private:
- typedef std::vector<PasswordForm*> PasswordFormList;
+ typedef std::vector<webkit_glue::PasswordForm*> PasswordFormList;
virtual ~PasswordStoreKWallet();
// Implements PasswordStore interface.
- void AddLoginImpl(const PasswordForm& form);
- void UpdateLoginImpl(const PasswordForm& form);
- void RemoveLoginImpl(const PasswordForm& form);
- void GetLoginsImpl(GetLoginsRequest* request);
-
- // Initialisation.
+ virtual void AddLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void UpdateLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void RemoveLoginImpl(const webkit_glue::PasswordForm& form);
+ virtual void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
+ const base::Time& delete_end);
+ virtual void GetLoginsImpl(GetLoginsRequest* request,
+ const webkit_glue::PasswordForm& form);
+ virtual void GetAutofillableLoginsImpl(GetLoginsRequest* request);
+ virtual void GetBlacklistLoginsImpl(GetLoginsRequest* request);
+ virtual bool FillAutofillableLogins(
+ std::vector<webkit_glue::PasswordForm*>* forms);
+ virtual bool FillBlacklistLogins(
+ std::vector<webkit_glue::PasswordForm*>* forms);
+
+ // Initialization.
bool StartKWalletd();
bool InitWallet();
- // Reads a list of PasswordForms from the wallet that match the signon_realm
- // of key.
- void GetLoginsList(PasswordFormList* forms, const PasswordForm& key,
+ // Reads a list of PasswordForms from the wallet that match the signon_realm.
+ void GetLoginsList(PasswordFormList* forms,
+ const std::string& signon_realm,
int wallet_handle);
- // Writes a list of PasswordForms to the wallet with the signon_realm from
- // key. Overwrites any existing list for this key.
- void SetLoginsList(const PasswordFormList& forms, const PasswordForm& key,
+ // Writes a list of PasswordForms to the wallet with the given signon_realm.
+ // Overwrites any existing list for this signon_realm. Removes the entry if
+ // |forms| is empty.
+ void SetLoginsList(const PasswordFormList& forms,
+ const std::string& signon_realm,
int wallet_handle);
- // Checks if the last dbus call returned an error. If it did, logs the error
+ // Helper for FillAutofillableLogins() and FillBlacklistLogins().
+ bool FillSomeLogins(bool autofillable, PasswordFormList* forms);
+
+ // Checks if the last DBus call returned an error. If it did, logs the error
// message, frees it and returns true.
- // This must be called after every dbus call.
+ // This must be called after every DBus call.
bool CheckError();
// Opens the wallet and ensures that the "Chrome Form Data" folder exists.
@@ -61,27 +78,35 @@ class PasswordStoreKWallet : public PasswordStore {
int WalletHandle();
// Compares two PasswordForms and returns true if they are the same.
- // Checks only the fields that we persist in KWallet, and ignores
- // password_value.
- static bool CompareForms(const PasswordForm& a, const PasswordForm& b);
+ // If |update_check| is false, we only check the fields that are checked by
+ // LoginDatabase::UpdateLogin() when updating logins; otherwise, we check the
+ // fields that are checked by LoginDatabase::RemoveLogin() for removing them.
+ static bool CompareForms(const webkit_glue::PasswordForm& a,
+ const webkit_glue::PasswordForm& b,
+ bool update_check);
// Serializes a list of PasswordForms to be stored in the wallet.
static void SerializeValue(const PasswordFormList& forms, Pickle* pickle);
// Deserializes a list of PasswordForms from the wallet.
- static void DeserializeValue(const PasswordForm& key, const Pickle& pickle,
+ static void DeserializeValue(const std::string& signon_realm,
+ const Pickle& pickle,
PasswordFormList* forms);
- // Convenience function to read a GURL from a Pickle. Assumes the URL has
+ // Convenience function to read a GURL from a Pickle. Assumes the URL has
// been written as a std::string.
static void ReadGURL(const Pickle& pickle, void** iter, GURL* url);
+ // In case the fields in the pickle ever change, version them so we can try to
+ // read old pickles. (Note: do not eat old pickles past the expiration date.)
+ static const int kPickleVersion = 0;
+
// Name of the application - will appear in kwallet's dialogs.
static const char* kAppId;
// Name of the folder to store passwords in.
static const char* kKWalletFolder;
- // DBUS stuff.
+ // DBus stuff.
static const char* kKWalletServiceName;
static const char* kKWalletPath;
static const char* kKWalletInterface;
@@ -92,18 +117,18 @@ class PasswordStoreKWallet : public PasswordStore {
// Invalid handle returned by WalletHandle().
static const int kInvalidKWalletHandle = -1;
- // Controls all access to kwallet dbus calls.
+ // Controls all access to kwallet DBus calls.
Lock kwallet_lock_;
- // Error from the last dbus call. NULL when there's no error. Freed and
+ // Error from the last DBus call. NULL when there's no error. Freed and
// cleared by CheckError().
GError* error_;
- // Connection to the dbus session bus.
+ // Connection to the DBus session bus.
DBusGConnection* connection_;
- // Proxy to the kwallet dbus service.
+ // Proxy to the kwallet DBus service.
DBusGProxy* proxy_;
- // The name of the wallet we've opened. Set during Init().
+ // The name of the wallet we've opened. Set during Init().
std::string wallet_name_;
DISALLOW_COPY_AND_ASSIGN(PasswordStoreKWallet);