Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/password_manager/native_backend_kwallet_x.h" | 5 #include "chrome/browser/password_manager/native_backend_kwallet_x.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/pickle.h" | 10 #include "base/pickle.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/stringprintf.h" | 12 #include "base/stringprintf.h" |
| 13 #include "base/synchronization/waitable_event.h" | |
| 13 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
| 15 #include "dbus/bus.h" | |
| 16 #include "dbus/message.h" | |
| 17 #include "dbus/object_proxy.h" | |
| 14 #include "grit/chromium_strings.h" | 18 #include "grit/chromium_strings.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 19 #include "ui/base/l10n/l10n_util.h" |
| 16 | 20 |
| 17 using std::string; | |
| 18 using std::vector; | |
| 19 using webkit_glue::PasswordForm; | 21 using webkit_glue::PasswordForm; |
| 20 | 22 |
| 21 // We could localize this string, but then changing your locale would cause | 23 // We could localize this string, but then changing your locale would cause |
| 22 // you to lose access to all your stored passwords. Maybe best not to do that. | 24 // you to lose access to all your stored passwords. Maybe best not to do that. |
| 23 const char NativeBackendKWallet::kKWalletFolder[] = "Chrome Form Data"; | 25 const char NativeBackendKWallet::kKWalletFolder[] = "Chrome Form Data"; |
| 24 | 26 |
| 25 const char NativeBackendKWallet::kKWalletServiceName[] = "org.kde.kwalletd"; | 27 const char NativeBackendKWallet::kKWalletServiceName[] = "org.kde.kwalletd"; |
| 26 const char NativeBackendKWallet::kKWalletPath[] = "/modules/kwalletd"; | 28 const char NativeBackendKWallet::kKWalletPath[] = "/modules/kwalletd"; |
| 27 const char NativeBackendKWallet::kKWalletInterface[] = "org.kde.KWallet"; | 29 const char NativeBackendKWallet::kKWalletInterface[] = "org.kde.KWallet"; |
| 28 const char NativeBackendKWallet::kKLauncherServiceName[] = "org.kde.klauncher"; | 30 const char NativeBackendKWallet::kKLauncherServiceName[] = "org.kde.klauncher"; |
| 29 const char NativeBackendKWallet::kKLauncherPath[] = "/KLauncher"; | 31 const char NativeBackendKWallet::kKLauncherPath[] = "/KLauncher"; |
| 30 const char NativeBackendKWallet::kKLauncherInterface[] = "org.kde.KLauncher"; | 32 const char NativeBackendKWallet::kKLauncherInterface[] = "org.kde.KLauncher"; |
| 31 | 33 |
| 32 NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id, | 34 NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id, |
| 33 PrefService* prefs) | 35 PrefService* prefs) |
| 34 : profile_id_(id), prefs_(prefs), | 36 : profile_id_(id), prefs_(prefs), |
| 35 error_(NULL), connection_(NULL), proxy_(NULL), | |
| 36 app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) { | 37 app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) { |
| 37 if (PasswordStoreX::PasswordsUseLocalProfileId(prefs)) { | 38 if (PasswordStoreX::PasswordsUseLocalProfileId(prefs)) { |
| 38 folder_name_ = GetProfileSpecificFolderName(); | 39 folder_name_ = GetProfileSpecificFolderName(); |
| 39 // We already did the migration previously. Don't try again. | 40 // We already did the migration previously. Don't try again. |
| 40 migrate_tried_ = true; | 41 migrate_tried_ = true; |
| 41 } else { | 42 } else { |
| 42 folder_name_ = kKWalletFolder; | 43 folder_name_ = kKWalletFolder; |
| 43 migrate_tried_ = false; | 44 migrate_tried_ = false; |
| 44 } | 45 } |
| 45 } | 46 } |
| 46 | 47 |
| 47 NativeBackendKWallet::~NativeBackendKWallet() { | 48 NativeBackendKWallet::~NativeBackendKWallet() { |
| 48 if (proxy_) | 49 // This destructor is called on the thread that is destroying the Profile |
| 49 g_object_unref(proxy_); | 50 // containing the PasswordStore that owns this NativeBackend. Generally that |
| 51 // won't be the DB thread; it will be the UI thread. So we post a message to | |
| 52 // shut it down on the DB thread, and it will be destructed afterward when the | |
| 53 // scoped_refptr<dbus::Bus> goes out of scope. The NativeBackend will be | |
| 54 // destroyed before that occurs, but that's OK. | |
| 55 if (session_bus_.get()) { | |
| 56 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 57 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
| |
| 58 session_bus_.get(), | |
| 59 &dbus::Bus::ShutdownAndBlock)); | |
| 60 } | |
| 50 } | 61 } |
| 51 | 62 |
| 52 bool NativeBackendKWallet::Init() { | 63 bool NativeBackendKWallet::Init() { |
| 53 // Get a connection to the session bus. | 64 // We must synchronously do a few DBus calls to figure out if initialization |
| 54 connection_ = dbus_g_bus_get(DBUS_BUS_SESSION, &error_); | 65 // succeeds, but later, we'll want to do most work on the DB thread. So we |
| 55 if (CheckError()) | 66 // have to do the initialization on the DB thread here too, and wait for it. |
| 67 scoped_refptr<dbus::Bus> optional_bus; // Will construct its own. | |
| 68 bool success = false; | |
| 69 base::WaitableEvent event(false, false); | |
| 70 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | |
| 71 NewRunnableMethod( | |
|
satorux1
2011/09/12 19:28:57
ditto.
Mike Mammarella
2011/09/12 21:26:13
same
| |
| 72 this, &NativeBackendKWallet::InitWithBus, | |
| 73 optional_bus, &event, &success)); | |
| 74 event.Wait(); | |
| 75 return success; | |
| 76 } | |
| 77 | |
| 78 // NativeBackendKWallet isn't reference counted, but the one place we post a | |
| 79 // message to it (in InitWithBus below) waits for the task to run. So we can | |
| 80 // disable needing reference counting safely here. | |
| 81 template<> | |
| 82 struct RunnableMethodTraits<NativeBackendKWallet> { | |
| 83 void RetainCallee(NativeBackendKWallet*) {} | |
| 84 void ReleaseCallee(NativeBackendKWallet*) {} | |
| 85 }; | |
| 86 | |
| 87 void NativeBackendKWallet::InitWithBus(scoped_refptr<dbus::Bus> optional_bus, | |
| 88 base::WaitableEvent* event, | |
| 89 bool* success) { | |
| 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 91 DCHECK(!session_bus_.get()); | |
| 92 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.
| |
| 93 session_bus_ = optional_bus; | |
| 94 } else { | |
| 95 // Get a connection to the session bus. | |
| 96 dbus::Bus::Options options; | |
| 97 options.bus_type = dbus::Bus::SESSION; | |
| 98 options.connection_type = dbus::Bus::PRIVATE; | |
| 99 session_bus_ = new dbus::Bus(options); | |
| 100 } | |
| 101 kwallet_proxy_ = | |
| 102 session_bus_->GetObjectProxy(kKWalletServiceName, kKWalletPath); | |
| 103 // kwalletd may not be running. If it fails to initialize, try to start it | |
| 104 // and then try to initialize it again. (Note the short-circuit evaluation.) | |
| 105 *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
| |
| 106 if (event) | |
| 107 event->Signal(); | |
| 108 } | |
| 109 | |
| 110 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.
| |
| 111 // Sadly kwalletd doesn't use DBus activation, so we have to make a call to | |
| 112 // klauncher to start it. | |
| 113 dbus::ObjectProxy* klauncher = | |
| 114 session_bus_->GetObjectProxy(kKLauncherServiceName, kKLauncherPath); | |
| 115 | |
| 116 dbus::MethodCall method_call(kKLauncherInterface, | |
| 117 "start_service_by_desktop_name"); | |
| 118 dbus::MessageWriter builder(&method_call); | |
| 119 dbus::MessageWriter empty(&method_call); | |
| 120 builder.AppendString("kwalletd"); // serviceName | |
| 121 builder.OpenArray("s", &empty); // urls | |
| 122 builder.CloseContainer(&empty); | |
| 123 builder.OpenArray("s", &empty); // envs | |
| 124 builder.CloseContainer(&empty); | |
| 125 builder.AppendString(""); // startup_id | |
| 126 builder.AppendBool(false); // blind | |
| 127 scoped_ptr<dbus::Response> response( | |
| 128 klauncher->CallMethodAndBlock( | |
| 129 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 130 if (!response.get()) { | |
| 131 LOG(ERROR) << "Error contacting klauncher to start kwalletd"; | |
| 56 return false; | 132 return false; |
| 57 | 133 } |
| 58 if (!InitWallet()) { | 134 dbus::MessageReader reader(response.get()); |
| 59 // kwalletd may not be running. Try to start it and try again. | 135 int32_t ret = -1; |
| 60 if (!StartKWalletd() || !InitWallet()) | 136 std::string dbus_name; |
| 61 return false; | 137 std::string error; |
| 138 int32_t pid = -1; | |
| 139 if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) || | |
| 140 !reader.PopString(&error) || !reader.PopInt32(&pid)) { | |
| 141 LOG(ERROR) << "Error reading response from klauncher to start kwalletd: " | |
| 142 << response->ToString(); | |
| 143 return false; | |
| 144 } | |
| 145 if (!error.empty() || ret) { | |
| 146 LOG(ERROR) << "Error launching kwalletd: error '" << error << "' " | |
| 147 << " (code " << ret << ")"; | |
| 148 return false; | |
| 62 } | 149 } |
| 63 | 150 |
| 64 return true; | 151 return true; |
| 65 } | 152 } |
| 66 | 153 |
| 67 bool NativeBackendKWallet::StartKWalletd() { | 154 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.
| |
| 68 // Sadly kwalletd doesn't use DBUS activation, so we have to make a call to | 155 { |
| 69 // klauncher to start it. | 156 // Check that KWallet is enabled. |
| 70 DBusGProxy* klauncher_proxy = | 157 dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); |
| 71 dbus_g_proxy_new_for_name(connection_, kKLauncherServiceName, | 158 scoped_ptr<dbus::Response> response( |
| 72 kKLauncherPath, kKLauncherInterface); | 159 kwallet_proxy_->CallMethodAndBlock( |
| 73 | 160 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 74 char* empty_string_list = NULL; | 161 if (!response.get()) { |
| 75 int ret = 1; | 162 LOG(ERROR) << "Error contacting kwalletd (isEnabled)"; |
| 76 char* error = NULL; | 163 return false; |
| 77 dbus_g_proxy_call(klauncher_proxy, "start_service_by_desktop_name", &error_, | 164 } |
| 78 G_TYPE_STRING, "kwalletd", // serviceName | 165 dbus::MessageReader reader(response.get()); |
| 79 G_TYPE_STRV, &empty_string_list, // urls | 166 bool enabled = false; |
| 80 G_TYPE_STRV, &empty_string_list, // envs | 167 if (!reader.PopBool(&enabled)) { |
| 81 G_TYPE_STRING, "", // startup_id | 168 LOG(ERROR) << "Error reading response from kwalletd (isEnabled): " |
| 82 G_TYPE_BOOLEAN, (gboolean) false, // blind | 169 << response->ToString(); |
| 83 G_TYPE_INVALID, | 170 return false; |
| 84 G_TYPE_INT, &ret, // result | 171 } |
| 85 G_TYPE_STRING, NULL, // dubsName | 172 // Not enabled? Don't use KWallet. But also don't warn here. |
| 86 G_TYPE_STRING, &error, // error | 173 if (!enabled) |
| 87 G_TYPE_INT, NULL, // pid | 174 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.
| |
| 88 G_TYPE_INVALID); | |
| 89 | |
| 90 if (error && *error) { | |
| 91 LOG(ERROR) << "Error launching kwalletd: " << error; | |
| 92 ret = 1; // Make sure we return false after freeing. | |
| 93 } | 175 } |
| 94 | 176 |
| 95 g_free(error); | 177 { |
| 96 g_object_unref(klauncher_proxy); | 178 // Get the wallet name. |
| 97 | 179 dbus::MethodCall method_call(kKWalletInterface, "networkWallet"); |
| 98 if (CheckError() || ret != 0) | 180 scoped_ptr<dbus::Response> response( |
| 99 return false; | 181 kwallet_proxy_->CallMethodAndBlock( |
| 100 return true; | 182 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 101 } | 183 if (!response.get()) { |
| 102 | 184 LOG(ERROR) << "Error contacting kwalletd (networkWallet)"; |
| 103 bool NativeBackendKWallet::InitWallet() { | 185 return false; |
| 104 // Make a proxy to KWallet. | 186 } |
| 105 proxy_ = dbus_g_proxy_new_for_name(connection_, kKWalletServiceName, | 187 dbus::MessageReader reader(response.get()); |
| 106 kKWalletPath, kKWalletInterface); | 188 if (!reader.PopString(&wallet_name_)) { |
| 107 | 189 LOG(ERROR) << "Error reading response from kwalletd (networkWallet): " |
| 108 // Check KWallet is enabled. | 190 << response->ToString(); |
| 109 gboolean is_enabled = false; | 191 return false; |
| 110 dbus_g_proxy_call(proxy_, "isEnabled", &error_, | 192 } |
| 111 G_TYPE_INVALID, | 193 } |
| 112 G_TYPE_BOOLEAN, &is_enabled, | |
| 113 G_TYPE_INVALID); | |
| 114 if (CheckError() || !is_enabled) | |
| 115 return false; | |
| 116 | |
| 117 // Get the wallet name. | |
| 118 char* wallet_name = NULL; | |
| 119 dbus_g_proxy_call(proxy_, "networkWallet", &error_, | |
| 120 G_TYPE_INVALID, | |
| 121 G_TYPE_STRING, &wallet_name, | |
| 122 G_TYPE_INVALID); | |
| 123 if (CheckError() || !wallet_name) | |
| 124 return false; | |
| 125 | |
| 126 wallet_name_.assign(wallet_name); | |
| 127 g_free(wallet_name); | |
| 128 | 194 |
| 129 return true; | 195 return true; |
| 130 } | 196 } |
| 131 | 197 |
| 132 bool NativeBackendKWallet::AddLogin(const PasswordForm& form) { | 198 bool NativeBackendKWallet::AddLogin(const PasswordForm& form) { |
| 133 int wallet_handle = WalletHandle(); | 199 int wallet_handle = WalletHandle(); |
| 134 if (wallet_handle == kInvalidKWalletHandle) | 200 if (wallet_handle == kInvalidKWalletHandle) |
| 135 return false; | 201 return false; |
| 136 | 202 |
| 137 PasswordFormList forms; | 203 PasswordFormList forms; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 | 262 |
| 197 // Update the entry in the wallet, possibly deleting it. | 263 // Update the entry in the wallet, possibly deleting it. |
| 198 bool ok = SetLoginsList(kept_forms, form.signon_realm, wallet_handle); | 264 bool ok = SetLoginsList(kept_forms, form.signon_realm, wallet_handle); |
| 199 | 265 |
| 200 STLDeleteElements(&kept_forms); | 266 STLDeleteElements(&kept_forms); |
| 201 return ok; | 267 return ok; |
| 202 } | 268 } |
| 203 | 269 |
| 204 bool NativeBackendKWallet::RemoveLoginsCreatedBetween( | 270 bool NativeBackendKWallet::RemoveLoginsCreatedBetween( |
| 205 const base::Time& delete_begin, | 271 const base::Time& delete_begin, |
| 206 const base::Time& delete_end) { | 272 const base::Time& delete_end) { |
|
satorux1
2011/09/12 19:28:57
You might want to add
DCHECK(BrowserThread::Curr
Mike Mammarella
2011/09/12 21:26:13
WalletHandle() has such a check, and this method n
satorux1
2011/09/12 22:28:21
It's a matter of taste so it's up to you, but I th
| |
| 207 int wallet_handle = WalletHandle(); | 273 int wallet_handle = WalletHandle(); |
| 208 if (wallet_handle == kInvalidKWalletHandle) | 274 if (wallet_handle == kInvalidKWalletHandle) |
| 209 return false; | 275 return false; |
| 210 | 276 |
| 211 // We could probably also use readEntryList here. | 277 // We could probably also use readEntryList here. |
| 212 char** realm_list = NULL; | 278 std::vector<std::string> realm_list; |
| 213 dbus_g_proxy_call(proxy_, "entryList", &error_, | 279 { |
| 214 G_TYPE_INT, wallet_handle, // handle | 280 dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| 215 G_TYPE_STRING, folder_name_.c_str(), // folder | 281 dbus::MessageWriter builder(&method_call); |
| 216 G_TYPE_STRING, app_name_.c_str(), // appid | 282 builder.AppendInt32(wallet_handle); // handle |
| 217 G_TYPE_INVALID, | 283 builder.AppendString(folder_name_); // folder |
| 218 G_TYPE_STRV, &realm_list, | 284 builder.AppendString(app_name_); // appid |
| 219 G_TYPE_INVALID); | 285 scoped_ptr<dbus::Response> response( |
| 220 if (CheckError()) | 286 kwallet_proxy_->CallMethodAndBlock( |
| 221 return false; | 287 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 288 if (!response.get()) { | |
| 289 LOG(ERROR) << "Error contacting kwalletd (entryList)"; | |
| 290 return false; | |
| 291 } | |
| 292 dbus::MessageReader reader(response.get()); | |
| 293 dbus::MessageReader array(response.get()); | |
| 294 if (!reader.PopArray(&array)) { | |
| 295 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 296 << response->ToString(); | |
| 297 return false; | |
| 298 } | |
| 299 while (array.HasMoreData()) { | |
| 300 std::string realm; | |
| 301 if (!array.PopString(&realm)) { | |
| 302 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 303 << response->ToString(); | |
| 304 return false; | |
| 305 } | |
| 306 realm_list.push_back(realm); | |
| 307 } | |
| 308 } | |
| 222 | 309 |
| 223 bool ok = true; | 310 bool ok = true; |
| 224 for (char** realm = realm_list; *realm; ++realm) { | 311 for (size_t i = 0; i < realm_list.size(); ++i) { |
| 225 GArray* byte_array = NULL; | 312 const std::string& signon_realm = realm_list[i]; |
| 226 dbus_g_proxy_call(proxy_, "readEntry", &error_, | 313 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| 227 G_TYPE_INT, wallet_handle, // handle | 314 dbus::MessageWriter builder(&method_call); |
| 228 G_TYPE_STRING, folder_name_.c_str(), // folder | 315 builder.AppendInt32(wallet_handle); // handle |
| 229 G_TYPE_STRING, *realm, // key | 316 builder.AppendString(folder_name_); // folder |
| 230 G_TYPE_STRING, app_name_.c_str(), // appid | 317 builder.AppendString(signon_realm); // key |
| 231 G_TYPE_INVALID, | 318 builder.AppendString(app_name_); // appid |
| 232 DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, | 319 scoped_ptr<dbus::Response> response( |
| 233 G_TYPE_INVALID); | 320 kwallet_proxy_->CallMethodAndBlock( |
| 234 | 321 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 235 if (CheckError() || !byte_array || | 322 if (!response.get()) { |
| 236 !CheckSerializedValue(byte_array, *realm)) { | 323 LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| 237 continue; | 324 continue; |
| 238 } | 325 } |
| 326 dbus::MessageReader reader(response.get()); | |
| 327 uint8_t* bytes = NULL; | |
| 328 size_t length = 0; | |
| 329 if (!reader.PopArrayOfBytes(&bytes, &length)) { | |
| 330 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | |
| 331 << response->ToString(); | |
| 332 continue; | |
| 333 } | |
| 334 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | |
| 335 continue; | |
| 239 | 336 |
| 240 string signon_realm(*realm); | 337 // Can't we all just agree on whether bytes are signed or not? Please? |
| 241 Pickle pickle(byte_array->data, byte_array->len); | 338 Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 242 PasswordFormList all_forms; | 339 PasswordFormList all_forms; |
| 243 DeserializeValue(signon_realm, pickle, &all_forms); | 340 DeserializeValue(signon_realm, pickle, &all_forms); |
| 244 g_array_free(byte_array, true); | |
| 245 | 341 |
| 246 PasswordFormList kept_forms; | 342 PasswordFormList kept_forms; |
| 247 kept_forms.reserve(all_forms.size()); | 343 kept_forms.reserve(all_forms.size()); |
| 248 for (size_t i = 0; i < all_forms.size(); ++i) { | 344 for (size_t i = 0; i < all_forms.size(); ++i) { |
| 249 if (delete_begin <= all_forms[i]->date_created && | 345 if (delete_begin <= all_forms[i]->date_created && |
| 250 (delete_end.is_null() || all_forms[i]->date_created < delete_end)) { | 346 (delete_end.is_null() || all_forms[i]->date_created < delete_end)) { |
| 251 delete all_forms[i]; | 347 delete all_forms[i]; |
| 252 } else { | 348 } else { |
| 253 kept_forms.push_back(all_forms[i]); | 349 kept_forms.push_back(all_forms[i]); |
| 254 } | 350 } |
| 255 } | 351 } |
| 256 | 352 |
| 257 if (!SetLoginsList(kept_forms, signon_realm, wallet_handle)) | 353 if (!SetLoginsList(kept_forms, signon_realm, wallet_handle)) |
| 258 ok = false; | 354 ok = false; |
| 259 STLDeleteElements(&kept_forms); | 355 STLDeleteElements(&kept_forms); |
| 260 } | 356 } |
| 261 g_strfreev(realm_list); | |
| 262 return ok; | 357 return ok; |
| 263 } | 358 } |
| 264 | 359 |
| 265 bool NativeBackendKWallet::GetLogins(const PasswordForm& form, | 360 bool NativeBackendKWallet::GetLogins(const PasswordForm& form, |
| 266 PasswordFormList* forms) { | 361 PasswordFormList* forms) { |
| 267 int wallet_handle = WalletHandle(); | 362 int wallet_handle = WalletHandle(); |
| 268 if (wallet_handle == kInvalidKWalletHandle) | 363 if (wallet_handle == kInvalidKWalletHandle) |
| 269 return false; | 364 return false; |
| 270 return GetLoginsList(forms, form.signon_realm, wallet_handle); | 365 return GetLoginsList(forms, form.signon_realm, wallet_handle); |
| 271 } | 366 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 287 } | 382 } |
| 288 | 383 |
| 289 bool NativeBackendKWallet::GetBlacklistLogins(PasswordFormList* forms) { | 384 bool NativeBackendKWallet::GetBlacklistLogins(PasswordFormList* forms) { |
| 290 int wallet_handle = WalletHandle(); | 385 int wallet_handle = WalletHandle(); |
| 291 if (wallet_handle == kInvalidKWalletHandle) | 386 if (wallet_handle == kInvalidKWalletHandle) |
| 292 return false; | 387 return false; |
| 293 return GetLoginsList(forms, false, wallet_handle); | 388 return GetLoginsList(forms, false, wallet_handle); |
| 294 } | 389 } |
| 295 | 390 |
| 296 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, | 391 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, |
| 297 const string& signon_realm, | 392 const std::string& signon_realm, |
| 298 int wallet_handle) { | 393 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
| |
| 299 // Is there an entry in the wallet? | 394 // Is there an entry in the wallet? |
| 300 gboolean has_entry = false; | 395 { |
| 301 dbus_g_proxy_call(proxy_, "hasEntry", &error_, | 396 dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); |
| 302 G_TYPE_INT, wallet_handle, // handle | 397 dbus::MessageWriter builder(&method_call); |
| 303 G_TYPE_STRING, folder_name_.c_str(), // folder | 398 builder.AppendInt32(wallet_handle); // handle |
| 304 G_TYPE_STRING, signon_realm.c_str(), // key | 399 builder.AppendString(folder_name_); // folder |
| 305 G_TYPE_STRING, app_name_.c_str(), // appid | 400 builder.AppendString(signon_realm); // key |
| 306 G_TYPE_INVALID, | 401 builder.AppendString(app_name_); // appid |
| 307 G_TYPE_BOOLEAN, &has_entry, | 402 scoped_ptr<dbus::Response> response( |
| 308 G_TYPE_INVALID); | 403 kwallet_proxy_->CallMethodAndBlock( |
| 309 | 404 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 310 if (CheckError()) | 405 if (!response.get()) { |
| 311 return false; | 406 LOG(ERROR) << "Error contacting kwalletd (hasEntry)"; |
| 312 if (!has_entry) { | 407 return false; |
| 313 // This is not an error. There just isn't a matching entry. | 408 } |
| 314 return true; | 409 dbus::MessageReader reader(response.get()); |
| 410 bool has_entry = false; | |
| 411 if (!reader.PopBool(&has_entry)) { | |
| 412 LOG(ERROR) << "Error reading response from kwalletd (hasEntry): " | |
| 413 << response->ToString(); | |
| 414 return false; | |
| 415 } | |
| 416 if (!has_entry) { | |
| 417 // This is not an error. There just isn't a matching entry. | |
| 418 return true; | |
| 419 } | |
| 315 } | 420 } |
| 316 | 421 |
| 317 GArray* byte_array = NULL; | 422 { |
| 318 dbus_g_proxy_call(proxy_, "readEntry", &error_, | 423 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| 319 G_TYPE_INT, wallet_handle, // handle | 424 dbus::MessageWriter builder(&method_call); |
| 320 G_TYPE_STRING, folder_name_.c_str(), // folder | 425 builder.AppendInt32(wallet_handle); // handle |
| 321 G_TYPE_STRING, signon_realm.c_str(), // key | 426 builder.AppendString(folder_name_); // folder |
| 322 G_TYPE_STRING, app_name_.c_str(), // appid | 427 builder.AppendString(signon_realm); // key |
| 323 G_TYPE_INVALID, | 428 builder.AppendString(app_name_); // appid |
| 324 DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, | 429 scoped_ptr<dbus::Response> response( |
| 325 G_TYPE_INVALID); | 430 kwallet_proxy_->CallMethodAndBlock( |
| 431 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 432 if (!response.get()) { | |
| 433 LOG(ERROR) << "Error contacting kwalletd (readEntry)"; | |
| 434 return false; | |
| 435 } | |
| 436 dbus::MessageReader reader(response.get()); | |
| 437 uint8_t* bytes = NULL; | |
| 438 size_t length = 0; | |
| 439 if (!reader.PopArrayOfBytes(&bytes, &length)) { | |
| 440 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | |
| 441 << response->ToString(); | |
| 442 return false; | |
| 443 } | |
| 444 if (!bytes) | |
| 445 return false; | |
| 446 if (!CheckSerializedValue(bytes, length, signon_realm)) { | |
| 447 // This is weird, but we choose not to call it an error. There is an | |
| 448 // invalid entry somehow, but by just ignoring it, we make it easier to | |
| 449 // repair without having to delete it using kwalletmanager (that is, by | |
| 450 // 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.
| |
| 451 return true; | |
| 452 } | |
| 326 | 453 |
| 327 if (CheckError() || !byte_array) | 454 // Can't we all just agree on whether bytes are signed or not? Please? |
| 328 return false; | 455 Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 329 if (!CheckSerializedValue(byte_array, signon_realm.c_str())) { | 456 PasswordFormList all_forms; |
| 330 // This is weird, but we choose not to call it an error. There's an invalid | 457 DeserializeValue(signon_realm, pickle, forms); |
| 331 // entry somehow, but by pretending it just doesn't exist, we make it easier | |
| 332 // to repair without having to delete it using kwalletmanager (that is, by | |
| 333 // just saving a new password within this realm to overwrite it). | |
| 334 g_array_free(byte_array, true); | |
| 335 return true; | |
| 336 } | 458 } |
| 337 | 459 |
| 338 Pickle pickle(byte_array->data, byte_array->len); | |
| 339 DeserializeValue(signon_realm, pickle, forms); | |
| 340 g_array_free(byte_array, true); | |
| 341 | |
| 342 return true; | 460 return true; |
| 343 } | 461 } |
| 344 | 462 |
| 345 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, | 463 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, |
| 346 bool autofillable, | 464 bool autofillable, |
| 347 int wallet_handle) { | 465 int wallet_handle) { |
| 348 PasswordFormList all_forms; | 466 PasswordFormList all_forms; |
| 349 if (!GetAllLogins(&all_forms, wallet_handle)) | 467 if (!GetAllLogins(&all_forms, wallet_handle)) |
| 350 return false; | 468 return false; |
| 351 | 469 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 377 forms->push_back(all_forms[i]); | 495 forms->push_back(all_forms[i]); |
| 378 } else { | 496 } else { |
| 379 delete all_forms[i]; | 497 delete all_forms[i]; |
| 380 } | 498 } |
| 381 } | 499 } |
| 382 | 500 |
| 383 return true; | 501 return true; |
| 384 } | 502 } |
| 385 | 503 |
| 386 bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, | 504 bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, |
| 387 int wallet_handle) { | 505 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().
| |
| 388 // We could probably also use readEntryList here. | 506 // We could probably also use readEntryList here. |
| 389 char** realm_list = NULL; | 507 std::vector<std::string> realm_list; |
| 390 dbus_g_proxy_call(proxy_, "entryList", &error_, | 508 { |
| 391 G_TYPE_INT, wallet_handle, // handle | 509 dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| 392 G_TYPE_STRING, folder_name_.c_str(), // folder | 510 dbus::MessageWriter builder(&method_call); |
| 393 G_TYPE_STRING, app_name_.c_str(), // appid | 511 builder.AppendInt32(wallet_handle); // handle |
| 394 G_TYPE_INVALID, | 512 builder.AppendString(folder_name_); // folder |
| 395 G_TYPE_STRV, &realm_list, | 513 builder.AppendString(app_name_); // appid |
| 396 G_TYPE_INVALID); | 514 scoped_ptr<dbus::Response> response( |
| 397 if (CheckError()) | 515 kwallet_proxy_->CallMethodAndBlock( |
| 398 return false; | 516 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 517 if (!response.get()) { | |
| 518 LOG(ERROR) << "Error contacting kwalletd (entryList)"; | |
| 519 return false; | |
| 520 } | |
| 521 dbus::MessageReader reader(response.get()); | |
| 522 dbus::MessageReader array(response.get()); | |
| 523 if (!reader.PopArray(&array)) { | |
| 524 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 525 << response->ToString(); | |
| 526 return false; | |
| 527 } | |
| 528 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
| |
| 529 std::string realm; | |
| 530 if (!array.PopString(&realm)) { | |
| 531 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 532 << response->ToString(); | |
| 533 return false; | |
| 534 } | |
| 535 realm_list.push_back(realm); | |
| 536 } | |
| 537 } | |
| 399 | 538 |
| 400 for (char** realm = realm_list; *realm; ++realm) { | 539 for (size_t i = 0; i < realm_list.size(); ++i) { |
| 401 GArray* byte_array = NULL; | 540 const std::string& signon_realm = realm_list[i]; |
| 402 dbus_g_proxy_call(proxy_, "readEntry", &error_, | 541 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| 403 G_TYPE_INT, wallet_handle, // handle | 542 dbus::MessageWriter builder(&method_call); |
| 404 G_TYPE_STRING, folder_name_.c_str(), // folder | 543 builder.AppendInt32(wallet_handle); // handle |
| 405 G_TYPE_STRING, *realm, // key | 544 builder.AppendString(folder_name_); // folder |
| 406 G_TYPE_STRING, app_name_.c_str(), // appid | 545 builder.AppendString(signon_realm); // key |
| 407 G_TYPE_INVALID, | 546 builder.AppendString(app_name_); // appid |
| 408 DBUS_TYPE_G_UCHAR_ARRAY, &byte_array, | 547 scoped_ptr<dbus::Response> response( |
| 409 G_TYPE_INVALID); | 548 kwallet_proxy_->CallMethodAndBlock( |
| 410 | 549 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 411 if (CheckError() || !byte_array || | 550 if (!response.get()) { |
| 412 !CheckSerializedValue(byte_array, *realm)) { | 551 LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| 413 continue; | 552 continue; |
| 414 } | 553 } |
| 554 dbus::MessageReader reader(response.get()); | |
| 555 uint8_t* bytes = NULL; | |
| 556 size_t length = 0; | |
| 557 if (!reader.PopArrayOfBytes(&bytes, &length)) { | |
| 558 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | |
| 559 << response->ToString(); | |
| 560 continue; | |
| 561 } | |
| 562 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | |
| 563 continue; | |
| 415 | 564 |
| 416 Pickle pickle(byte_array->data, byte_array->len); | 565 // Can't we all just agree on whether bytes are signed or not? Please? |
| 417 DeserializeValue(*realm, pickle, forms); | 566 Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 418 g_array_free(byte_array, true); | 567 PasswordFormList all_forms; |
| 568 DeserializeValue(signon_realm, pickle, forms); | |
| 419 } | 569 } |
| 420 g_strfreev(realm_list); | |
| 421 return true; | 570 return true; |
| 422 } | 571 } |
| 423 | 572 |
| 424 bool NativeBackendKWallet::SetLoginsList(const PasswordFormList& forms, | 573 bool NativeBackendKWallet::SetLoginsList(const PasswordFormList& forms, |
| 425 const string& signon_realm, | 574 const std::string& signon_realm, |
| 426 int wallet_handle) { | 575 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.
| |
| 427 if (forms.empty()) { | 576 if (forms.empty()) { |
| 428 // No items left? Remove the entry from the wallet. | 577 // No items left? Remove the entry from the wallet. |
| 578 dbus::MethodCall method_call(kKWalletInterface, "removeEntry"); | |
| 579 dbus::MessageWriter builder(&method_call); | |
| 580 builder.AppendInt32(wallet_handle); // handle | |
| 581 builder.AppendString(folder_name_); // folder | |
| 582 builder.AppendString(signon_realm); // key | |
| 583 builder.AppendString(app_name_); // appid | |
| 584 scoped_ptr<dbus::Response> response( | |
| 585 kwallet_proxy_->CallMethodAndBlock( | |
| 586 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 587 if (!response.get()) { | |
| 588 LOG(ERROR) << "Error contacting kwalletd (removeEntry)"; | |
| 589 return kInvalidKWalletHandle; | |
| 590 } | |
| 591 dbus::MessageReader reader(response.get()); | |
| 429 int ret = 0; | 592 int ret = 0; |
| 430 dbus_g_proxy_call(proxy_, "removeEntry", &error_, | 593 if (!reader.PopInt32(&ret)) { |
| 431 G_TYPE_INT, wallet_handle, // handle | 594 LOG(ERROR) << "Error reading response from kwalletd (removeEntry): " |
| 432 G_TYPE_STRING, folder_name_.c_str(), // folder | 595 << response->ToString(); |
| 433 G_TYPE_STRING, signon_realm.c_str(), // key | |
| 434 G_TYPE_STRING, app_name_.c_str(), // appid | |
| 435 G_TYPE_INVALID, | |
| 436 G_TYPE_INT, &ret, | |
| 437 G_TYPE_INVALID); | |
| 438 if (CheckError()) | |
| 439 return false; | 596 return false; |
| 597 } | |
| 440 if (ret != 0) | 598 if (ret != 0) |
| 441 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; | 599 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; |
| 442 return ret == 0; | 600 return ret == 0; |
| 443 } | 601 } |
| 444 | 602 |
| 445 Pickle value; | 603 Pickle value; |
| 446 SerializeValue(forms, &value); | 604 SerializeValue(forms, &value); |
| 447 | 605 |
| 448 // Convert the pickled bytes to a GByteArray. | 606 dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); |
| 449 GArray* byte_array = g_array_sized_new(false, false, sizeof(char), | 607 dbus::MessageWriter builder(&method_call); |
| 450 value.size()); | 608 builder.AppendInt32(wallet_handle); // handle |
| 451 g_array_append_vals(byte_array, value.data(), value.size()); | 609 builder.AppendString(folder_name_); // folder |
| 452 | 610 builder.AppendString(signon_realm); // key |
| 453 // Make the call. | 611 builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()), |
| 612 value.size()); // value | |
| 613 builder.AppendString(app_name_); // appid | |
| 614 scoped_ptr<dbus::Response> response( | |
| 615 kwallet_proxy_->CallMethodAndBlock( | |
| 616 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 617 if (!response.get()) { | |
| 618 LOG(ERROR) << "Error contacting kwalletd (writeEntry)"; | |
| 619 return kInvalidKWalletHandle; | |
| 620 } | |
| 621 dbus::MessageReader reader(response.get()); | |
| 454 int ret = 0; | 622 int ret = 0; |
| 455 dbus_g_proxy_call(proxy_, "writeEntry", &error_, | 623 if (!reader.PopInt32(&ret)) { |
| 456 G_TYPE_INT, wallet_handle, // handle | 624 LOG(ERROR) << "Error reading response from kwalletd (writeEntry): " |
| 457 G_TYPE_STRING, folder_name_.c_str(), // folder | 625 << response->ToString(); |
| 458 G_TYPE_STRING, signon_realm.c_str(), // key | |
| 459 DBUS_TYPE_G_UCHAR_ARRAY, byte_array, // value | |
| 460 G_TYPE_STRING, app_name_.c_str(), // appid | |
| 461 G_TYPE_INVALID, | |
| 462 G_TYPE_INT, &ret, | |
| 463 G_TYPE_INVALID); | |
| 464 g_array_free(byte_array, true); | |
| 465 | |
| 466 if (CheckError()) | |
| 467 return false; | 626 return false; |
| 627 } | |
| 468 if (ret != 0) | 628 if (ret != 0) |
| 469 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; | 629 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; |
| 470 return ret == 0; | 630 return ret == 0; |
| 471 } | 631 } |
| 472 | 632 |
| 473 bool NativeBackendKWallet::CompareForms(const PasswordForm& a, | 633 bool NativeBackendKWallet::CompareForms(const PasswordForm& a, |
| 474 const PasswordForm& b, | 634 const PasswordForm& b, |
| 475 bool update_check) { | 635 bool update_check) { |
| 476 // An update check doesn't care about the submit element. | 636 // An update check doesn't care about the submit element. |
| 477 if (!update_check && a.submit_element != b.submit_element) | 637 if (!update_check && a.submit_element != b.submit_element) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 498 pickle->WriteString16(form->password_element); | 658 pickle->WriteString16(form->password_element); |
| 499 pickle->WriteString16(form->password_value); | 659 pickle->WriteString16(form->password_value); |
| 500 pickle->WriteString16(form->submit_element); | 660 pickle->WriteString16(form->submit_element); |
| 501 pickle->WriteBool(form->ssl_valid); | 661 pickle->WriteBool(form->ssl_valid); |
| 502 pickle->WriteBool(form->preferred); | 662 pickle->WriteBool(form->preferred); |
| 503 pickle->WriteBool(form->blacklisted_by_user); | 663 pickle->WriteBool(form->blacklisted_by_user); |
| 504 pickle->WriteInt64(form->date_created.ToTimeT()); | 664 pickle->WriteInt64(form->date_created.ToTimeT()); |
| 505 } | 665 } |
| 506 } | 666 } |
| 507 | 667 |
| 508 bool NativeBackendKWallet::CheckSerializedValue(const GArray* byte_array, | 668 bool NativeBackendKWallet::CheckSerializedValue(const uint8_t* byte_array, |
| 509 const char* realm) { | 669 size_t length, |
| 670 const std::string& realm) { | |
| 510 const Pickle::Header* header = | 671 const Pickle::Header* header = |
| 511 reinterpret_cast<const Pickle::Header*>(byte_array->data); | 672 reinterpret_cast<const Pickle::Header*>(byte_array); |
| 512 if (byte_array->len < sizeof(*header) || | 673 if (length < sizeof(*header) || |
| 513 header->payload_size > byte_array->len - sizeof(*header)) { | 674 header->payload_size > length - sizeof(*header)) { |
| 514 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; | 675 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; |
| 515 return false; | 676 return false; |
| 516 } | 677 } |
| 517 return true; | 678 return true; |
| 518 } | 679 } |
| 519 | 680 |
| 520 void NativeBackendKWallet::DeserializeValue(const string& signon_realm, | 681 void NativeBackendKWallet::DeserializeValue(const std::string& signon_realm, |
| 521 const Pickle& pickle, | 682 const Pickle& pickle, |
| 522 PasswordFormList* forms) { | 683 PasswordFormList* forms) { |
| 523 void* iter = NULL; | 684 void* iter = NULL; |
| 524 | 685 |
| 525 int version = -1; | 686 int version = -1; |
| 526 if (!pickle.ReadInt(&iter, &version) || version != kPickleVersion) { | 687 if (!pickle.ReadInt(&iter, &version) || version != kPickleVersion) { |
| 527 // This is the only version so far, so anything else is an error. | 688 // This is the only version so far, so anything else is an error. |
| 528 LOG(ERROR) << "Failed to deserialize KWallet entry " | 689 LOG(ERROR) << "Failed to deserialize KWallet entry " |
| 529 << "(realm: " << signon_realm << ")"; | 690 << "(realm: " << signon_realm << ")"; |
| 530 return; | 691 return; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 break; | 733 break; |
| 573 } | 734 } |
| 574 form->scheme = static_cast<PasswordForm::Scheme>(scheme); | 735 form->scheme = static_cast<PasswordForm::Scheme>(scheme); |
| 575 form->date_created = base::Time::FromTimeT(date_created); | 736 form->date_created = base::Time::FromTimeT(date_created); |
| 576 forms->push_back(form.release()); | 737 forms->push_back(form.release()); |
| 577 } | 738 } |
| 578 } | 739 } |
| 579 | 740 |
| 580 bool NativeBackendKWallet::ReadGURL(const Pickle& pickle, void** iter, | 741 bool NativeBackendKWallet::ReadGURL(const Pickle& pickle, void** iter, |
| 581 GURL* url) { | 742 GURL* url) { |
| 582 string url_string; | 743 std::string url_string; |
| 583 if (!pickle.ReadString(iter, &url_string)) { | 744 if (!pickle.ReadString(iter, &url_string)) { |
| 584 LOG(ERROR) << "Failed to deserialize URL"; | 745 LOG(ERROR) << "Failed to deserialize URL"; |
| 585 *url = GURL(); | 746 *url = GURL(); |
| 586 return false; | 747 return false; |
| 587 } | 748 } |
| 588 *url = GURL(url_string); | 749 *url = GURL(url_string); |
| 589 return true; | 750 return true; |
| 590 } | 751 } |
| 591 | 752 |
| 592 bool NativeBackendKWallet::CheckError() { | |
| 593 if (error_) { | |
| 594 LOG(ERROR) << "Failed to complete KWallet call: " << error_->message; | |
| 595 g_error_free(error_); | |
| 596 error_ = NULL; | |
| 597 return true; | |
| 598 } | |
| 599 return false; | |
| 600 } | |
| 601 | |
| 602 int NativeBackendKWallet::WalletHandle() { | 753 int NativeBackendKWallet::WalletHandle() { |
| 603 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 754 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 755 | |
| 604 // Open the wallet. | 756 // Open the wallet. |
| 605 // TODO(mdm): Are we leaking these handles? Find out. | 757 // TODO(mdm): Are we leaking these handles? Find out. |
| 606 int handle = kInvalidKWalletHandle; | 758 int32_t handle = kInvalidKWalletHandle; |
| 607 dbus_g_proxy_call(proxy_, "open", &error_, | 759 { |
| 608 G_TYPE_STRING, wallet_name_.c_str(), // wallet | 760 dbus::MethodCall method_call(kKWalletInterface, "open"); |
| 609 G_TYPE_INT64, 0LL, // wid | 761 dbus::MessageWriter builder(&method_call); |
| 610 G_TYPE_STRING, app_name_.c_str(), // appid | 762 builder.AppendString(wallet_name_); // wallet |
| 611 G_TYPE_INVALID, | 763 builder.AppendInt64(0); // wid |
| 612 G_TYPE_INT, &handle, | 764 builder.AppendString(app_name_); // appid |
| 613 G_TYPE_INVALID); | 765 scoped_ptr<dbus::Response> response( |
| 614 if (CheckError() || handle == kInvalidKWalletHandle) | 766 kwallet_proxy_->CallMethodAndBlock( |
| 615 return kInvalidKWalletHandle; | 767 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 768 if (!response.get()) { | |
| 769 LOG(ERROR) << "Error contacting kwalletd (open)"; | |
| 770 return kInvalidKWalletHandle; | |
| 771 } | |
| 772 dbus::MessageReader reader(response.get()); | |
| 773 if (!reader.PopInt32(&handle)) { | |
| 774 LOG(ERROR) << "Error reading response from kwalletd (open): " | |
| 775 << response->ToString(); | |
| 776 return kInvalidKWalletHandle; | |
| 777 } | |
| 778 if (handle == kInvalidKWalletHandle) { | |
| 779 LOG(ERROR) << "Error obtaining KWallet handle"; | |
| 780 return kInvalidKWalletHandle; | |
| 781 } | |
| 782 } | |
| 616 | 783 |
| 617 // Check if our folder exists. | 784 // Check if our folder exists. |
| 618 gboolean has_folder = false; | 785 bool has_folder = false; |
| 619 dbus_g_proxy_call(proxy_, "hasFolder", &error_, | 786 { |
| 620 G_TYPE_INT, handle, // handle | 787 dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); |
| 621 G_TYPE_STRING, folder_name_.c_str(), // folder | 788 dbus::MessageWriter builder(&method_call); |
| 622 G_TYPE_STRING, app_name_.c_str(), // appid | 789 builder.AppendInt32(handle); // handle |
| 623 G_TYPE_INVALID, | 790 builder.AppendString(folder_name_); // folder |
| 624 G_TYPE_BOOLEAN, &has_folder, | 791 builder.AppendString(app_name_); // appid |
| 625 G_TYPE_INVALID); | 792 scoped_ptr<dbus::Response> response( |
| 626 if (CheckError()) | 793 kwallet_proxy_->CallMethodAndBlock( |
| 627 return kInvalidKWalletHandle; | 794 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 795 if (!response.get()) { | |
| 796 LOG(ERROR) << "Error contacting kwalletd (hasFolder)"; | |
| 797 return kInvalidKWalletHandle; | |
| 798 } | |
| 799 dbus::MessageReader reader(response.get()); | |
| 800 if (!reader.PopBool(&has_folder)) { | |
| 801 LOG(ERROR) << "Error reading response from kwalletd (hasFolder): " | |
| 802 << response->ToString(); | |
| 803 return kInvalidKWalletHandle; | |
| 804 } | |
| 805 } | |
| 628 | 806 |
| 629 // Create it if it didn't. | 807 // Create it if it didn't. |
| 630 if (!has_folder) { | 808 if (!has_folder) { |
| 631 gboolean success = false; | 809 dbus::MethodCall method_call(kKWalletInterface, "createFolder"); |
| 632 dbus_g_proxy_call(proxy_, "createFolder", &error_, | 810 dbus::MessageWriter builder(&method_call); |
| 633 G_TYPE_INT, handle, // handle | 811 builder.AppendInt32(handle); // handle |
| 634 G_TYPE_STRING, folder_name_.c_str(), // folder | 812 builder.AppendString(folder_name_); // folder |
| 635 G_TYPE_STRING, app_name_.c_str(), // appid | 813 builder.AppendString(app_name_); // appid |
| 636 G_TYPE_INVALID, | 814 scoped_ptr<dbus::Response> response( |
| 637 G_TYPE_BOOLEAN, &success, | 815 kwallet_proxy_->CallMethodAndBlock( |
| 638 G_TYPE_INVALID); | 816 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 639 if (CheckError() || !success) | 817 if (!response.get()) { |
| 818 LOG(ERROR) << "Error contacting kwalletd (createFolder)"; | |
| 640 return kInvalidKWalletHandle; | 819 return kInvalidKWalletHandle; |
| 820 } | |
| 821 dbus::MessageReader reader(response.get()); | |
| 822 bool success = false; | |
| 823 if (!reader.PopBool(&success)) { | |
| 824 LOG(ERROR) << "Error reading response from kwalletd (createFolder): " | |
| 825 << response->ToString(); | |
| 826 return kInvalidKWalletHandle; | |
| 827 } | |
| 828 if (!success) { | |
| 829 LOG(ERROR) << "Error creating KWallet folder"; | |
| 830 return kInvalidKWalletHandle; | |
| 831 } | |
| 641 } | 832 } |
| 642 | 833 |
| 643 // Successful initialization. Try migration if necessary. | 834 // Successful initialization. Try migration if necessary. |
| 644 if (!migrate_tried_) | 835 if (!migrate_tried_) |
| 645 MigrateToProfileSpecificLogins(); | 836 MigrateToProfileSpecificLogins(); |
| 646 | 837 |
| 647 return handle; | 838 return handle; |
| 648 } | 839 } |
| 649 | 840 |
| 650 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { | 841 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 // Each other profile must be able to migrate the shared data as well, | 884 // Each other profile must be able to migrate the shared data as well, |
| 694 // so we must leave it alone. After a few releases, we'll add code to | 885 // so we must leave it alone. After a few releases, we'll add code to |
| 695 // delete them, and eventually remove this migration code. | 886 // delete them, and eventually remove this migration code. |
| 696 // TODO(mdm): follow through with the plan above. | 887 // TODO(mdm): follow through with the plan above. |
| 697 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); | 888 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); |
| 698 } else { | 889 } else { |
| 699 // We failed to migrate for some reason. Use the old folder name. | 890 // We failed to migrate for some reason. Use the old folder name. |
| 700 folder_name_ = kKWalletFolder; | 891 folder_name_ = kKWalletFolder; |
| 701 } | 892 } |
| 702 } | 893 } |
| OLD | NEW |