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. |