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); |
-} |