Chromium Code Reviews| Index: chrome/browser/password_manager/native_backend_kwallet_x.cc |
| =================================================================== |
| --- chrome/browser/password_manager/native_backend_kwallet_x.cc (revision 99666) |
| +++ chrome/browser/password_manager/native_backend_kwallet_x.cc (working copy) |
| @@ -4,18 +4,20 @@ |
| #include "chrome/browser/password_manager/native_backend_kwallet_x.h" |
| -#include <sstream> |
| +#include <vector> |
| #include "base/logging.h" |
| #include "base/pickle.h" |
| #include "base/stl_util.h" |
| #include "base/stringprintf.h" |
| +#include "base/synchronization/waitable_event.h" |
| #include "content/browser/browser_thread.h" |
| +#include "dbus/bus.h" |
| +#include "dbus/message.h" |
| +#include "dbus/object_proxy.h" |
| #include "grit/chromium_strings.h" |
| #include "ui/base/l10n/l10n_util.h" |
| -using std::string; |
| -using std::vector; |
| using webkit_glue::PasswordForm; |
| // We could localize this string, but then changing your locale would cause |
| @@ -32,7 +34,6 @@ |
| NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id, |
| PrefService* prefs) |
| : profile_id_(id), prefs_(prefs), |
| - error_(NULL), connection_(NULL), proxy_(NULL), |
| app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) { |
| if (PasswordStoreX::PasswordsUseLocalProfileId(prefs)) { |
| folder_name_ = GetProfileSpecificFolderName(); |
| @@ -45,87 +46,143 @@ |
| } |
| NativeBackendKWallet::~NativeBackendKWallet() { |
| - if (proxy_) |
| - g_object_unref(proxy_); |
| + if (session_bus_) |
| + session_bus_->ShutdownAndBlock(); |
|
satorux1
2011/09/06 20:42:40
This would crash with DCHECK() if D-Bus thread is
Mike Mammarella
2011/09/07 01:01:27
Ah, one of the perils of code you have never actua
|
| } |
| bool NativeBackendKWallet::Init() { |
| // Get a connection to the session bus. |
| - connection_ = dbus_g_bus_get(DBUS_BUS_SESSION, &error_); |
| - if (CheckError()) |
| - return false; |
| + dbus::Bus::Options options; |
| + options.bus_type = dbus::Bus::SESSION; |
| + options.connection_type = dbus::Bus::PRIVATE; |
| + options.dbus_thread_message_loop_proxy = |
| + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB); |
|
satorux1
2011/09/06 20:42:40
Why do we use the DB thread? Could you add a comme
Mike Mammarella
2011/09/07 01:01:27
Hmm. Now that I think about it more, I think I can
|
| + return InitWithBus(new dbus::Bus(options)); |
| +} |
| +// NativeBackendKWallet isn't reference counted, but the one place we post a |
| +// message to it (in InitWithBus below) waits for the task to run. So we can |
| +// disable needing reference counting safely here. |
| +template<> |
| +struct RunnableMethodTraits<NativeBackendKWallet> { |
| + void RetainCallee(NativeBackendKWallet*) {} |
| + void ReleaseCallee(NativeBackendKWallet*) {} |
| +}; |
| + |
| +bool NativeBackendKWallet::InitWithBus(dbus::Bus* bus) { |
| + DCHECK(!session_bus_); |
| + session_bus_ = bus; |
| + kwallet_proxy_ = bus->GetObjectProxy(kKWalletServiceName, kKWalletPath); |
| + |
| + // We must synchronously do a few DBus calls to figure out if initialization |
| + // succeeds, but later, we'll want to do most work on the DB thread. So we |
| + // have to do the initialization on the DB thread here too, and wait for it. |
| + bool success = false; |
| + base::WaitableEvent event(false, false); |
| + BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| + NewRunnableMethod( |
| + this, &NativeBackendKWallet::InitOnDBThread, |
| + &event, &success)); |
| + event.Wait(); |
| + return success; |
| +} |
| + |
| +void NativeBackendKWallet::InitOnDBThread(base::WaitableEvent* event, |
| + bool* success) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| if (!InitWallet()) { |
| // kwalletd may not be running. Try to start it and try again. |
| if (!StartKWalletd() || !InitWallet()) |
| - return false; |
| + return; // *success starts out false |
| } |
| - |
| - return true; |
| + *success = true; |
| } |
| bool NativeBackendKWallet::StartKWalletd() { |
| - // Sadly kwalletd doesn't use DBUS activation, so we have to make a call to |
| + // Sadly kwalletd doesn't use DBus activation, so we have to make a call to |
| // klauncher to start it. |
| - DBusGProxy* klauncher_proxy = |
| - dbus_g_proxy_new_for_name(connection_, kKLauncherServiceName, |
| - kKLauncherPath, kKLauncherInterface); |
| + dbus::ObjectProxy* klauncher = |
| + session_bus_->GetObjectProxy(kKLauncherServiceName, kKLauncherPath); |
| - char* empty_string_list = NULL; |
| - int ret = 1; |
| - char* error = NULL; |
| - dbus_g_proxy_call(klauncher_proxy, "start_service_by_desktop_name", &error_, |
| - G_TYPE_STRING, "kwalletd", // serviceName |
| - G_TYPE_STRV, &empty_string_list, // urls |
| - G_TYPE_STRV, &empty_string_list, // envs |
| - G_TYPE_STRING, "", // startup_id |
| - G_TYPE_BOOLEAN, (gboolean) false, // blind |
| - G_TYPE_INVALID, |
| - G_TYPE_INT, &ret, // result |
| - G_TYPE_STRING, NULL, // dubsName |
| - G_TYPE_STRING, &error, // error |
| - G_TYPE_INT, NULL, // pid |
| - G_TYPE_INVALID); |
| - |
| - if (error && *error) { |
| + dbus::MethodCall method_call(kKLauncherInterface, |
| + "start_service_by_desktop_name"); |
| + dbus::MessageWriter builder(&method_call); |
| + dbus::MessageWriter empty(&method_call); |
| + builder.AppendString("kwalletd"); // serviceName |
| + builder.OpenArray("s", &empty); // urls |
| + builder.CloseContainer(&empty); |
| + builder.OpenArray("s", &empty); // envs |
| + builder.CloseContainer(&empty); |
| + builder.AppendString(""); // startup_id |
| + builder.AppendBool(false); // blind |
| + scoped_ptr<dbus::Response> response( |
| + klauncher->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting klauncher to start kwalletd"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + int32_t ret = -1; |
| + std::string dbusName; |
|
satorux1
2011/09/06 20:42:40
dbus_name
Mike Mammarella
2011/09/07 01:01:27
Done. Huh. I wonder where this came from. I'm pret
|
| + std::string error; |
| + int32_t pid = -1; |
| + if (!reader.PopInt32(&ret) || !reader.PopString(&dbusName) || |
| + !reader.PopString(&error) || !reader.PopInt32(&pid)) { |
| + LOG(ERROR) << "Error reading response from klauncher to start kwalletd"; |
|
satorux1
2011/09/06 20:42:40
You could add << response->ToString(). It'll make
Mike Mammarella
2011/09/07 01:01:27
Done.
|
| + return false; |
| + } |
| + if (!error.empty()) { |
| LOG(ERROR) << "Error launching kwalletd: " << error; |
| - ret = 1; // Make sure we return false after freeing. |
| + return false; |
| } |
| + if (ret) { |
| + LOG(ERROR) << "Error launching kwalletd: " << ret; |
| + return false; |
| + } |
|
satorux1
2011/09/06 20:42:40
Maybe you could merge the two conditionals, by usi
Mike Mammarella
2011/09/07 01:01:27
Done.
|
| - g_free(error); |
| - g_object_unref(klauncher_proxy); |
| - |
| - if (CheckError() || ret != 0) |
| - return false; |
| return true; |
| } |
| bool NativeBackendKWallet::InitWallet() { |
| - // Make a proxy to KWallet. |
| - proxy_ = dbus_g_proxy_new_for_name(connection_, kKWalletServiceName, |
| - kKWalletPath, kKWalletInterface); |
| + { |
| + // Check that KWallet is enabled. |
| + dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (isEnabled)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + bool enabled = false; |
| + if (!reader.PopBool(&enabled)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (isEnabled)"; |
|
satorux1
2011/09/06 20:42:40
Likewise, I'd recommend including response->ToStri
Mike Mammarella
2011/09/07 01:01:27
Done.
|
| + return false; |
| + } |
| + // Not enabled? Don't use KWallet. But also don't warn here. |
| + if (!enabled) |
| + return false; |
| + } |
| - // Check KWallet is enabled. |
| - gboolean is_enabled = false; |
| - dbus_g_proxy_call(proxy_, "isEnabled", &error_, |
| - G_TYPE_INVALID, |
| - G_TYPE_BOOLEAN, &is_enabled, |
| - G_TYPE_INVALID); |
| - if (CheckError() || !is_enabled) |
| - return false; |
| + { |
| + // Get the wallet name. |
| + dbus::MethodCall method_call(kKWalletInterface, "networkWallet"); |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (networkWallet)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + if (!reader.PopString(&wallet_name_)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (networkWallet)"; |
| + return false; |
| + } |
| + } |
| - // Get the wallet name. |
| - char* wallet_name = NULL; |
| - dbus_g_proxy_call(proxy_, "networkWallet", &error_, |
| - G_TYPE_INVALID, |
| - G_TYPE_STRING, &wallet_name, |
| - G_TYPE_INVALID); |
| - if (CheckError() || !wallet_name) |
| - return false; |
| - |
| - wallet_name_.assign(wallet_name); |
| - g_free(wallet_name); |
| - |
| return true; |
| } |
| @@ -209,39 +266,66 @@ |
| return false; |
| // We could probably also use readEntryList here. |
|
satorux1
2011/09/06 20:42:40
What's readEntryList? Is this comment still valid?
Mike Mammarella
2011/09/07 01:01:27
It's another possible method call in the KWallet i
|
| - char** realm_list = NULL; |
| - dbus_g_proxy_call(proxy_, "entryList", &error_, |
| - G_TYPE_INT, wallet_handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_STRV, &realm_list, |
| - G_TYPE_INVALID); |
| - if (CheckError()) |
| - return false; |
| + std::vector<std::string> realm_list; |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (entryList)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + dbus::MessageReader array(response.get()); |
| + if (!reader.PopArray(&array)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (entryList)"; |
| + return false; |
| + } |
| + while (array.HasMoreData()) { |
| + std::string realm; |
| + if (!array.PopString(&realm)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (entryList)"; |
| + return false; |
| + } |
| + realm_list.push_back(realm); |
| + } |
| + } |
| bool ok = true; |
| - 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, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, *realm, // key |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, |
| - G_TYPE_INVALID); |
| - |
| - if (CheckError() || !byte_array || |
| - !CheckSerializedValue(byte_array, *realm)) { |
| + for (size_t i = 0; i < realm_list.size(); ++i) { |
| + const std::string& signon_realm = realm_list[i]; |
| + dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| continue; |
| } |
| + dbus::MessageReader reader(response.get()); |
| + uint8_t* bytes = NULL; |
| + size_t length = 0; |
| + if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (readEntry)"; |
| + continue; |
| + } |
| + if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| + continue; |
| - string signon_realm(*realm); |
| - Pickle pickle(byte_array->data, byte_array->len); |
| + // Can't we all just agree on whether bytes are signed or not? Please? |
| + Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| PasswordFormList all_forms; |
| DeserializeValue(signon_realm, pickle, &all_forms); |
| - g_array_free(byte_array, true); |
| PasswordFormList kept_forms; |
| kept_forms.reserve(all_forms.size()); |
| @@ -258,7 +342,6 @@ |
| ok = false; |
| STLDeleteElements(&kept_forms); |
| } |
| - g_strfreev(realm_list); |
| return ok; |
| } |
| @@ -294,51 +377,72 @@ |
| } |
| bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, |
| - const string& signon_realm, |
| + const std::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, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, signon_realm.c_str(), // key |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_BOOLEAN, &has_entry, |
| - G_TYPE_INVALID); |
| - |
| - if (CheckError()) |
| - return false; |
| - if (!has_entry) { |
| - // This is not an error. There just isn't a matching entry. |
| - return true; |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (hasEntry)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + bool has_entry = false; |
| + if (!reader.PopBool(&has_entry)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (hasEntry)"; |
| + return false; |
| + } |
| + if (!has_entry) { |
| + // This is not an error. There just isn't a matching entry. |
| + return true; |
| + } |
| } |
| - GArray* byte_array = NULL; |
| - dbus_g_proxy_call(proxy_, "readEntry", &error_, |
| - G_TYPE_INT, wallet_handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, signon_realm.c_str(), // key |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, |
| - G_TYPE_INVALID); |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + uint8_t* bytes = NULL; |
| + size_t length = 0; |
| + if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (readEntry)"; |
| + return false; |
| + } |
| + if (!bytes) |
| + return false; |
| + if (!CheckSerializedValue(bytes, length, signon_realm)) { |
| + // This is weird, but we choose not to call it an error. There is an |
| + // invalid entry somehow, but by just ignoring it, we make it easier to |
| + // repair without having to delete it using kwalletmanager (that is, by |
| + // just saving a new password within this realm to overwrite it). |
| + return true; |
| + } |
| - if (CheckError() || !byte_array) |
| - return false; |
| - if (!CheckSerializedValue(byte_array, signon_realm.c_str())) { |
| - // This is weird, but we choose not to call it an error. There's an invalid |
| - // entry somehow, but by pretending it just doesn't exist, we make it easier |
| - // to repair without having to delete it using kwalletmanager (that is, by |
| - // just saving a new password within this realm to overwrite it). |
| - g_array_free(byte_array, true); |
| - return true; |
| + // Can't we all just agree on whether bytes are signed or not? Please? |
| + Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| + PasswordFormList all_forms; |
| + DeserializeValue(signon_realm, pickle, forms); |
| } |
| - Pickle pickle(byte_array->data, byte_array->len); |
| - DeserializeValue(signon_realm, pickle, forms); |
| - g_array_free(byte_array, true); |
| - |
| return true; |
| } |
| @@ -386,57 +490,93 @@ |
| bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, |
| int wallet_handle) { |
| // 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, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_STRV, &realm_list, |
| - G_TYPE_INVALID); |
| - if (CheckError()) |
| - return false; |
| + std::vector<std::string> realm_list; |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (entryList)"; |
| + return false; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + dbus::MessageReader array(response.get()); |
| + if (!reader.PopArray(&array)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (entryList)"; |
| + return false; |
| + } |
| + while (array.HasMoreData()) { |
| + std::string realm; |
| + if (!array.PopString(&realm)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (entryList)"; |
| + return false; |
| + } |
| + realm_list.push_back(realm); |
| + } |
| + } |
| - 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, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, *realm, // key |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, |
| - G_TYPE_INVALID); |
| - |
| - if (CheckError() || !byte_array || |
| - !CheckSerializedValue(byte_array, *realm)) { |
| + for (size_t i = 0; i < realm_list.size(); ++i) { |
| + const std::string& signon_realm = realm_list[i]; |
| + dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| continue; |
| } |
| + dbus::MessageReader reader(response.get()); |
| + uint8_t* bytes = NULL; |
| + size_t length = 0; |
| + if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (readEntry)"; |
| + continue; |
| + } |
| + if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| + continue; |
| - Pickle pickle(byte_array->data, byte_array->len); |
| - DeserializeValue(*realm, pickle, forms); |
| - g_array_free(byte_array, true); |
| + // Can't we all just agree on whether bytes are signed or not? Please? |
| + Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| + PasswordFormList all_forms; |
| + DeserializeValue(signon_realm, pickle, forms); |
| } |
| - g_strfreev(realm_list); |
| return true; |
| } |
| bool NativeBackendKWallet::SetLoginsList(const PasswordFormList& forms, |
| - const string& signon_realm, |
| + const std::string& signon_realm, |
| int wallet_handle) { |
| if (forms.empty()) { |
| // No items left? Remove the entry from the wallet. |
| + dbus::MethodCall method_call(kKWalletInterface, "removeEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (removeEntry)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| int ret = 0; |
| - dbus_g_proxy_call(proxy_, "removeEntry", &error_, |
| - G_TYPE_INT, wallet_handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, signon_realm.c_str(), // key |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_INT, &ret, |
| - G_TYPE_INVALID); |
| - if (CheckError()) |
| + if (!reader.PopInt32(&ret)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (removeEntry)"; |
| return false; |
| + } |
| if (ret != 0) |
| LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; |
| return ret == 0; |
| @@ -445,26 +585,27 @@ |
| Pickle value; |
| SerializeValue(forms, &value); |
| - // Convert the pickled bytes to a GByteArray. |
| - GArray* byte_array = g_array_sized_new(false, false, sizeof(char), |
| - value.size()); |
| - g_array_append_vals(byte_array, value.data(), value.size()); |
| - |
| - // Make the call. |
| + dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(wallet_handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(signon_realm); // key |
| + builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()), |
| + value.size()); // value |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (writeEntry)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| int ret = 0; |
| - dbus_g_proxy_call(proxy_, "writeEntry", &error_, |
| - G_TYPE_INT, wallet_handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, signon_realm.c_str(), // key |
| - DBUS_TYPE_G_UCHAR_ARRAY, byte_array, // value |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_INT, &ret, |
| - G_TYPE_INVALID); |
| - g_array_free(byte_array, true); |
| - |
| - if (CheckError()) |
| + if (!reader.PopInt32(&ret)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (writeEntry)"; |
| return false; |
| + } |
| if (ret != 0) |
| LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; |
| return ret == 0; |
| @@ -505,19 +646,20 @@ |
| } |
| } |
| -bool NativeBackendKWallet::CheckSerializedValue(const GArray* byte_array, |
| - const char* realm) { |
| +bool NativeBackendKWallet::CheckSerializedValue(const uint8_t* byte_array, |
| + size_t length, |
| + const std::string& realm) { |
| const Pickle::Header* header = |
| - reinterpret_cast<const Pickle::Header*>(byte_array->data); |
| - if (byte_array->len < sizeof(*header) || |
| - header->payload_size > byte_array->len - sizeof(*header)) { |
| + reinterpret_cast<const Pickle::Header*>(byte_array); |
| + if (length < sizeof(*header) || |
| + header->payload_size > length - sizeof(*header)) { |
| LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; |
| return false; |
| } |
| return true; |
| } |
| -void NativeBackendKWallet::DeserializeValue(const string& signon_realm, |
| +void NativeBackendKWallet::DeserializeValue(const std::string& signon_realm, |
| const Pickle& pickle, |
| PasswordFormList* forms) { |
| void* iter = NULL; |
| @@ -579,7 +721,7 @@ |
| bool NativeBackendKWallet::ReadGURL(const Pickle& pickle, void** iter, |
| GURL* url) { |
| - string url_string; |
| + std::string url_string; |
| if (!pickle.ReadString(iter, &url_string)) { |
| LOG(ERROR) << "Failed to deserialize URL"; |
| *url = GURL(); |
| @@ -589,55 +731,82 @@ |
| return true; |
| } |
| -bool NativeBackendKWallet::CheckError() { |
| - if (error_) { |
| - LOG(ERROR) << "Failed to complete KWallet call: " << error_->message; |
| - g_error_free(error_); |
| - error_ = NULL; |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| int NativeBackendKWallet::WalletHandle() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| + |
| // Open the wallet. |
| // TODO(mdm): Are we leaking these handles? Find out. |
| - int handle = kInvalidKWalletHandle; |
| - dbus_g_proxy_call(proxy_, "open", &error_, |
| - G_TYPE_STRING, wallet_name_.c_str(), // wallet |
| - G_TYPE_INT64, 0LL, // wid |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_INT, &handle, |
| - G_TYPE_INVALID); |
| - if (CheckError() || handle == kInvalidKWalletHandle) |
| - return kInvalidKWalletHandle; |
| + int32_t handle = kInvalidKWalletHandle; |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "open"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendString(wallet_name_); // wallet |
| + builder.AppendInt64(0); // wid |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (open)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + if (!reader.PopInt32(&handle)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (open)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + if (handle == kInvalidKWalletHandle) { |
| + LOG(ERROR) << "Error obtaining KWallet handle"; |
| + return kInvalidKWalletHandle; |
| + } |
| + } |
| // Check if our folder exists. |
| - gboolean has_folder = false; |
| - dbus_g_proxy_call(proxy_, "hasFolder", &error_, |
| - G_TYPE_INT, handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_BOOLEAN, &has_folder, |
| - G_TYPE_INVALID); |
| - if (CheckError()) |
| - return kInvalidKWalletHandle; |
| + bool has_folder = false; |
| + { |
| + dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (hasFolder)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + if (!reader.PopBool(&has_folder)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (hasFolder)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + } |
| // Create it if it didn't. |
| if (!has_folder) { |
| - gboolean success = false; |
| - dbus_g_proxy_call(proxy_, "createFolder", &error_, |
| - G_TYPE_INT, handle, // handle |
| - G_TYPE_STRING, folder_name_.c_str(), // folder |
| - G_TYPE_STRING, app_name_.c_str(), // appid |
| - G_TYPE_INVALID, |
| - G_TYPE_BOOLEAN, &success, |
| - G_TYPE_INVALID); |
| - if (CheckError() || !success) |
| + dbus::MethodCall method_call(kKWalletInterface, "createFolder"); |
| + dbus::MessageWriter builder(&method_call); |
| + builder.AppendInt32(handle); // handle |
| + builder.AppendString(folder_name_); // folder |
| + builder.AppendString(app_name_); // appid |
| + scoped_ptr<dbus::Response> response( |
| + kwallet_proxy_->CallMethodAndBlock( |
| + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| + if (!response.get()) { |
| + LOG(ERROR) << "Error contacting kwalletd (createFolder)"; |
| return kInvalidKWalletHandle; |
| + } |
| + dbus::MessageReader reader(response.get()); |
| + bool success = false; |
| + if (!reader.PopBool(&success)) { |
| + LOG(ERROR) << "Error reading response from kwalletd (createFolder)"; |
| + return kInvalidKWalletHandle; |
| + } |
| + if (!success) { |
| + LOG(ERROR) << "Error creating KWallet folder"; |
| + return kInvalidKWalletHandle; |
| + } |
| } |
| // Successful initialization. Try migration if necessary. |