Index: chrome/browser/password_manager/native_backend_kwallet_x.cc |
=================================================================== |
--- chrome/browser/password_manager/native_backend_kwallet_x.cc (revision 100563) |
+++ 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,152 @@ |
} |
NativeBackendKWallet::~NativeBackendKWallet() { |
- if (proxy_) |
- g_object_unref(proxy_); |
+ // This destructor is called on the thread that is destroying the Profile |
+ // containing the PasswordStore that owns this NativeBackend. Generally that |
+ // won't be the DB thread; it will be the UI thread. So we post a message to |
+ // shut it down on the DB thread, and it will be destructed afterward when the |
+ // scoped_refptr<dbus::Bus> goes out of scope. The NativeBackend will be |
+ // destroyed before that occurs, but that's OK. |
+ if (session_bus_.get()) { |
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
+ NewRunnableMethod( |
satorux1
2011/09/12 19:28:57
base::Bind is preferable.
Mike Mammarella
2011/09/12 21:26:13
I am inclined to stick with this for now since I k
satorux1
2011/09/12 22:28:21
That's fine, but it should be as easy as:
Browser
|
+ session_bus_.get(), |
+ &dbus::Bus::ShutdownAndBlock)); |
+ } |
} |
bool NativeBackendKWallet::Init() { |
- // Get a connection to the session bus. |
- connection_ = dbus_g_bus_get(DBUS_BUS_SESSION, &error_); |
- if (CheckError()) |
- return false; |
+ // 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. |
+ scoped_refptr<dbus::Bus> optional_bus; // Will construct its own. |
+ bool success = false; |
+ base::WaitableEvent event(false, false); |
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
+ NewRunnableMethod( |
satorux1
2011/09/12 19:28:57
ditto.
Mike Mammarella
2011/09/12 21:26:13
same
|
+ this, &NativeBackendKWallet::InitWithBus, |
+ optional_bus, &event, &success)); |
+ event.Wait(); |
+ return success; |
+} |
- if (!InitWallet()) { |
- // kwalletd may not be running. Try to start it and try again. |
- if (!StartKWalletd() || !InitWallet()) |
- return false; |
+// 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*) {} |
+}; |
+ |
+void NativeBackendKWallet::InitWithBus(scoped_refptr<dbus::Bus> optional_bus, |
+ base::WaitableEvent* event, |
+ bool* success) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ DCHECK(!session_bus_.get()); |
+ if (optional_bus.get()) { |
satorux1
2011/09/12 19:28:57
This is a bit tricky. You might want to add a comm
Mike Mammarella
2011/09/12 21:26:13
Done.
|
+ session_bus_ = optional_bus; |
+ } else { |
+ // Get a connection to the session bus. |
+ dbus::Bus::Options options; |
+ options.bus_type = dbus::Bus::SESSION; |
+ options.connection_type = dbus::Bus::PRIVATE; |
+ session_bus_ = new dbus::Bus(options); |
} |
- |
- return true; |
+ kwallet_proxy_ = |
+ session_bus_->GetObjectProxy(kKWalletServiceName, kKWalletPath); |
+ // kwalletd may not be running. If it fails to initialize, try to start it |
+ // and then try to initialize it again. (Note the short-circuit evaluation.) |
+ *success = InitWallet() || (StartKWalletd() && InitWallet()); |
satorux1
2011/09/12 19:28:57
I wasn't sure if || had higher precedence than =.
Mike Mammarella
2011/09/12 21:26:13
Some of the operators (the bitwise ones especially
|
+ if (event) |
+ event->Signal(); |
} |
bool NativeBackendKWallet::StartKWalletd() { |
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
Done.
|
- // 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) { |
- LOG(ERROR) << "Error launching kwalletd: " << error; |
- ret = 1; // Make sure we return false after freeing. |
+ 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 dbus_name; |
+ std::string error; |
+ int32_t pid = -1; |
+ if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) || |
+ !reader.PopString(&error) || !reader.PopInt32(&pid)) { |
+ LOG(ERROR) << "Error reading response from klauncher to start kwalletd: " |
+ << response->ToString(); |
+ return false; |
+ } |
+ if (!error.empty() || ret) { |
+ LOG(ERROR) << "Error launching kwalletd: error '" << error << "' " |
+ << " (code " << ret << ")"; |
+ return false; |
+ } |
- g_free(error); |
- g_object_unref(klauncher_proxy); |
- |
- if (CheckError() || ret != 0) |
- return false; |
return true; |
} |
bool NativeBackendKWallet::InitWallet() { |
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
Done.
|
- // 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): " |
+ << response->ToString(); |
+ return false; |
+ } |
+ // Not enabled? Don't use KWallet. But also don't warn here. |
+ if (!enabled) |
+ return false; |
satorux1
2011/09/12 19:28:57
VLOG(1) may be helpful for debugging?
Mike Mammarella
2011/09/12 21:26:13
Done.
|
+ } |
- // 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): " |
+ << response->ToString(); |
+ 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 +275,69 @@ |
return false; |
// We could probably also use readEntryList here. |
- char** realm_list = NULL; |
- dbus_g_proxy_call(proxy_, "entryList", &error_, |
- G_TYPE_INT, wallet_handle, // handle |
- G_TYPE_STRING, 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): " |
+ << response->ToString(); |
+ return false; |
+ } |
+ while (array.HasMoreData()) { |
+ std::string realm; |
+ if (!array.PopString(&realm)) { |
+ LOG(ERROR) << "Error reading response from kwalletd (entryList): " |
+ << response->ToString(); |
+ 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): " |
+ << response->ToString(); |
+ 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 +354,6 @@ |
ok = false; |
STLDeleteElements(&kept_forms); |
} |
- g_strfreev(realm_list); |
return ok; |
} |
@@ -294,51 +389,74 @@ |
} |
bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, |
- const string& signon_realm, |
+ const std::string& signon_realm, |
int wallet_handle) { |
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
Although this method doesn't actually call WalletH
|
// 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): " |
+ << response->ToString(); |
+ 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): " |
+ << response->ToString(); |
+ 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). |
satorux1
2011/09/12 19:28:57
Worth adding a LOG(WARNING) or something?
Mike Mammarella
2011/09/12 21:26:13
CheckSerializedValue() has one.
|
+ 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 +504,97 @@ |
bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, |
int wallet_handle) { |
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
Same reasoning about WalletHandle().
|
// 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): " |
+ << response->ToString(); |
+ return false; |
+ } |
+ while (array.HasMoreData()) { |
satorux1
2011/09/12 19:28:57
This is the second time I see this. I guess it's w
Mike Mammarella
2011/09/12 21:26:13
That would be useful. I'll consider adding one in
|
+ std::string realm; |
+ if (!array.PopString(&realm)) { |
+ LOG(ERROR) << "Error reading response from kwalletd (entryList): " |
+ << response->ToString(); |
+ 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): " |
+ << response->ToString(); |
+ 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) { |
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
Same.
|
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): " |
+ << response->ToString(); |
return false; |
+ } |
if (ret != 0) |
LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; |
return ret == 0; |
@@ -445,26 +603,28 @@ |
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): " |
+ << response->ToString(); |
return false; |
+ } |
if (ret != 0) |
LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; |
return ret == 0; |
@@ -505,19 +665,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 +740,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 +750,85 @@ |
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): " |
+ << response->ToString(); |
+ 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): " |
+ << response->ToString(); |
+ 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): " |
+ << response->ToString(); |
+ return kInvalidKWalletHandle; |
+ } |
+ if (!success) { |
+ LOG(ERROR) << "Error creating KWallet folder"; |
+ return kInvalidKWalletHandle; |
+ } |
} |
// Successful initialization. Try migration if necessary. |