Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2698)

Unified Diff: chrome/browser/password_manager/password_store_gnome.cc

Issue 2806002: Linux: refactor GNOME Keyring and KWallet integration to allow migration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/password_manager/password_store_gnome.cc
===================================================================
--- chrome/browser/password_manager/password_store_gnome.cc (revision 49824)
+++ chrome/browser/password_manager/password_store_gnome.cc (working copy)
@@ -1,433 +0,0 @@
-// 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.
-
-#include "chrome/browser/password_manager/password_store_gnome.h"
-
-#if defined(DLOPEN_GNOME_KEYRING)
-#include <dlfcn.h>
-#endif
-
-#include <map>
-#include <string>
-
-#include "base/logging.h"
-#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;
-
-/* Many of the gnome_keyring_* functions use variable arguments, which makes
- * them difficult if not impossible to wrap in C. Therefore, we want the
- * actual uses below to either call the functions directly (if we are linking
- * against libgnome-keyring), or call them via appropriately-typed function
- * pointers (if we are dynamically loading libgnome-keyring).
- *
- * Thus, instead of making a wrapper class with two implementations, we use
- * the preprocessor to rename the calls below in the dynamic load case, and
- * provide a function to initialize a set of function pointers that have the
- * alternate names. We also make sure the types are correct, since otherwise
- * dynamic loading like this would leave us vulnerable to signature changes. */
-
-#if defined(DLOPEN_GNOME_KEYRING)
-
-namespace {
-
-gboolean (*wrap_gnome_keyring_is_available)();
-GnomeKeyringResult (*wrap_gnome_keyring_store_password_sync)( // NOLINT
- const GnomeKeyringPasswordSchema* schema, const gchar* keyring,
- const gchar* display_name, const gchar* password, ...);
-GnomeKeyringResult (*wrap_gnome_keyring_delete_password_sync)( // NOLINT
- const GnomeKeyringPasswordSchema* schema, ...);
-GnomeKeyringResult (*wrap_gnome_keyring_find_itemsv_sync)( // NOLINT
- GnomeKeyringItemType type, GList** found, ...);
-const gchar* (*wrap_gnome_keyring_result_to_message)(GnomeKeyringResult res);
-void (*wrap_gnome_keyring_found_list_free)(GList* found_list);
-
-/* Cause the compiler to complain if the types of the above function pointers
- * do not correspond to the types of the actual gnome_keyring_* functions. */
-#define GNOME_KEYRING_VERIFY_TYPE(name) \
- typeof(&gnome_keyring_##name) name = wrap_gnome_keyring_##name; name = name
-
-inline void VerifyGnomeKeyringTypes() {
- GNOME_KEYRING_VERIFY_TYPE(is_available);
- GNOME_KEYRING_VERIFY_TYPE(store_password_sync);
- GNOME_KEYRING_VERIFY_TYPE(delete_password_sync);
- GNOME_KEYRING_VERIFY_TYPE(find_itemsv_sync);
- GNOME_KEYRING_VERIFY_TYPE(result_to_message);
- GNOME_KEYRING_VERIFY_TYPE(found_list_free);
-}
-#undef GNOME_KEYRING_VERIFY_TYPE
-
-/* Make it easy to initialize the function pointers above with a loop below. */
-#define GNOME_KEYRING_FUNCTION(name) \
- {#name, reinterpret_cast<void**>(&wrap_##name)}
-const struct {
- const char* name;
- void** pointer;
-} gnome_keyring_functions[] = {
- GNOME_KEYRING_FUNCTION(gnome_keyring_is_available),
- GNOME_KEYRING_FUNCTION(gnome_keyring_store_password_sync),
- GNOME_KEYRING_FUNCTION(gnome_keyring_delete_password_sync),
- GNOME_KEYRING_FUNCTION(gnome_keyring_find_itemsv_sync),
- GNOME_KEYRING_FUNCTION(gnome_keyring_result_to_message),
- GNOME_KEYRING_FUNCTION(gnome_keyring_found_list_free),
- {NULL, NULL}
-};
-#undef GNOME_KEYRING_FUNCTION
-
-/* Allow application code below to use the normal function names, but actually
- * end up using the function pointers above instead. */
-#define gnome_keyring_is_available \
- wrap_gnome_keyring_is_available
-#define gnome_keyring_store_password_sync \
- wrap_gnome_keyring_store_password_sync
-#define gnome_keyring_delete_password_sync \
- wrap_gnome_keyring_delete_password_sync
-#define gnome_keyring_find_itemsv_sync \
- wrap_gnome_keyring_find_itemsv_sync
-#define gnome_keyring_result_to_message \
- wrap_gnome_keyring_result_to_message
-#define gnome_keyring_found_list_free \
- wrap_gnome_keyring_found_list_free
-
-/* Load the library and initialize the function pointers. */
-bool LoadGnomeKeyring() {
- void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL);
- if (!handle) {
- LOG(INFO) << "Could not find libgnome-keyring.so.0";
- return false;
- }
- for (size_t i = 0; gnome_keyring_functions[i].name; ++i) {
- dlerror();
- *gnome_keyring_functions[i].pointer =
- dlsym(handle, gnome_keyring_functions[i].name);
- const char* error = dlerror();
- if (error) {
- LOG(ERROR) << "Unable to load symbol " <<
- gnome_keyring_functions[i].name << ": " << error;
- dlclose(handle);
- return false;
- }
- }
- // We leak the library handle. That's OK: this function is called only once.
- return true;
-}
-
-} // namespace
-
-#else // DLOPEN_GNOME_KEYRING
-
-namespace {
-
-bool LoadGnomeKeyring() {
- return true;
-}
-
-} // namespace
-
-#endif // DLOPEN_GNOME_KEYRING
-
-#define GNOME_KEYRING_APPLICATION_CHROME "chrome"
-
-// Schema is analagous to the fields in PasswordForm.
-const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = {
- GNOME_KEYRING_ITEM_GENERIC_SECRET, {
- { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
- { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
- { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
- { "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(LoginDatabase* login_db,
- Profile* profile,
- WebDataService* web_data_service) {
-}
-
-PasswordStoreGnome::~PasswordStoreGnome() {
-}
-
-bool PasswordStoreGnome::Init() {
- return PasswordStore::Init() &&
- LoadGnomeKeyring() &&
- gnome_keyring_is_available();
-}
-
-void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) {
- 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,
- "origin_url", form.origin.spec().c_str(),
- "action_url", form.action.spec().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(),
- NULL);
- if (result != GNOME_KEYRING_RESULT_OK) {
- LOG(ERROR) << "Keyring delete failed: "
- << gnome_keyring_result_to_message(result);
- }
-}
-
-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::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", 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(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 save failed: "
- << gnome_keyring_result_to_message(result);
- return false;
- }
- return true;
-}
-
-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,
- "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32,
- blacklisted_by_user,
- "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
- GNOME_KEYRING_APPLICATION_CHROME,
- NULL);
- 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);
- return false;
- }
- return true;
-}
-
-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 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) {
- GnomeKeyringAttribute attribute =
- gnome_keyring_attribute_list_index(attributes, i);
- if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) {
- string_attribute_map[string(attribute.name)] =
- string(attribute.value.string);
- } else if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) {
- uint_attribute_map[string(attribute.name)] = attribute.value.integer;
- }
- }
-
- PasswordForm* form = new PasswordForm();
- form->origin = GURL(string_attribute_map["origin_url"]);
- form->action = GURL(string_attribute_map["action_url"]);
- form->username_element =
- UTF8ToUTF16(string(string_attribute_map["username_element"]));
- form->username_value =
- UTF8ToUTF16(string(string_attribute_map["username_value"]));
- form->password_element =
- UTF8ToUTF16(string(string_attribute_map["password_element"]));
- form->password_value = UTF8ToUTF16(string(password));
- form->submit_element =
- 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;
- bool date_ok = StringToInt64(date, &date_created);
- DCHECK(date_ok);
- DCHECK_NE(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"]);
-
- forms->push_back(form);
-
- element = g_list_next(element);
- }
- gnome_keyring_found_list_free(found);
-}
« no previous file with comments | « chrome/browser/password_manager/password_store_gnome.h ('k') | chrome/browser/password_manager/password_store_kwallet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698