Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/pickle.h" | 17 #include "base/pickle.h" |
| 18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "base/synchronization/waitable_event.h" | 20 #include "base/synchronization/waitable_event.h" |
| 21 #include "base/threading/thread_restrictions.h" | 21 #include "base/threading/thread_restrictions.h" |
| 22 #include "chrome/grit/chromium_strings.h" | 22 #include "chrome/grit/chromium_strings.h" |
| 23 #include "components/autofill/core/common/password_form.h" | 23 #include "components/autofill/core/common/password_form.h" |
| 24 #include "components/password_manager/core/browser/password_manager_util.h" | 24 #include "components/password_manager/core/browser/password_manager_util.h" |
| 25 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
| 26 #include "dbus/bus.h" | 26 #include "dbus/bus.h" |
| 27 #include "dbus/message.h" | 27 #include "dbus/message.h" |
| 28 #include "dbus/object_path.h" | 28 #include "dbus/object_path.h" |
| 29 #include "dbus/object_proxy.h" | |
| 30 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 31 #include "url/origin.h" | 30 #include "url/origin.h" |
| 32 | 31 |
| 33 using autofill::PasswordForm; | 32 using autofill::PasswordForm; |
| 34 using content::BrowserThread; | 33 using content::BrowserThread; |
| 35 | 34 |
| 36 namespace { | 35 namespace { |
| 37 | 36 |
| 38 // In case the fields in the pickle ever change, version them so we can try to | 37 // In case the fields in the pickle ever change, version them so we can try to |
| 39 // read old pickles. (Note: do not eat old pickles past the expiration date.) | 38 // read old pickles. (Note: do not eat old pickles past the expiration date.) |
| 40 const int kPickleVersion = 8; | 39 const int kPickleVersion = 8; |
| 41 | 40 |
| 42 // We could localize this string, but then changing your locale would cause | 41 // We could localize this string, but then changing your locale would cause |
| 43 // you to lose access to all your stored passwords. Maybe best not to do that. | 42 // you to lose access to all your stored passwords. Maybe best not to do that. |
| 44 // Name of the folder to store passwords in. | 43 // Name of the folder to store passwords in. |
| 45 const char kKWalletFolder[] = "Chrome Form Data"; | 44 const char kKWalletFolder[] = "Chrome Form Data"; |
| 46 | 45 |
| 47 // DBus service, path, and interface names for klauncher and kwalletd. | |
| 48 const char kKWalletDName[] = "kwalletd"; | |
| 49 const char kKWalletD5Name[] = "kwalletd5"; | |
| 50 const char kKWalletServiceName[] = "org.kde.kwalletd"; | |
| 51 const char kKWallet5ServiceName[] = "org.kde.kwalletd5"; | |
| 52 const char kKWalletPath[] = "/modules/kwalletd"; | |
| 53 const char kKWallet5Path[] = "/modules/kwalletd5"; | |
| 54 const char kKWalletInterface[] = "org.kde.KWallet"; | |
| 55 const char kKLauncherServiceName[] = "org.kde.klauncher"; | |
| 56 const char kKLauncherPath[] = "/KLauncher"; | |
| 57 const char kKLauncherInterface[] = "org.kde.KLauncher"; | |
| 58 | |
| 59 // Checks a serialized list of PasswordForms for sanity. Returns true if OK. | 46 // Checks a serialized list of PasswordForms for sanity. Returns true if OK. |
| 60 // Note that |realm| is only used for generating a useful warning message. | 47 // Note that |realm| is only used for generating a useful warning message. |
| 61 bool CheckSerializedValue(const uint8_t* byte_array, | 48 bool CheckSerializedValue(const uint8_t* byte_array, |
| 62 size_t length, | 49 size_t length, |
| 63 const std::string& realm) { | 50 const std::string& realm) { |
| 64 const base::Pickle::Header* header = | 51 const base::Pickle::Header* header = |
| 65 reinterpret_cast<const base::Pickle::Header*>(byte_array); | 52 reinterpret_cast<const base::Pickle::Header*>(byte_array); |
| 66 if (length < sizeof(*header) || | 53 if (length < sizeof(*header) || |
| 67 header->payload_size > length - sizeof(*header)) { | 54 header->payload_size > length - sizeof(*header)) { |
| 68 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; | 55 LOG(WARNING) << "Invalid KWallet entry detected (realm: " << realm << ")"; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 } | 283 } |
| 297 | 284 |
| 298 void UMALogDeserializationStatus(bool success) { | 285 void UMALogDeserializationStatus(bool success) { |
| 299 UMA_HISTOGRAM_BOOLEAN("PasswordManager.KWalletDeserializationStatus", | 286 UMA_HISTOGRAM_BOOLEAN("PasswordManager.KWalletDeserializationStatus", |
| 300 success); | 287 success); |
| 301 } | 288 } |
| 302 | 289 |
| 303 } // namespace | 290 } // namespace |
| 304 | 291 |
| 305 NativeBackendKWallet::NativeBackendKWallet( | 292 NativeBackendKWallet::NativeBackendKWallet( |
| 306 LocalProfileId id, base::nix::DesktopEnvironment desktop_env) | 293 LocalProfileId id, |
| 294 base::nix::DesktopEnvironment desktop_env) | |
| 307 : profile_id_(id), | 295 : profile_id_(id), |
| 308 kwallet_proxy_(nullptr), | 296 kwallet_dbus_(desktop_env), |
| 309 app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) { | 297 app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) { |
| 310 folder_name_ = GetProfileSpecificFolderName(); | 298 folder_name_ = GetProfileSpecificFolderName(); |
| 311 | |
| 312 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE5) { | |
| 313 dbus_service_name_ = kKWallet5ServiceName; | |
| 314 dbus_path_ = kKWallet5Path; | |
| 315 kwalletd_name_ = kKWalletD5Name; | |
| 316 } else { | |
| 317 dbus_service_name_ = kKWalletServiceName; | |
| 318 dbus_path_ = kKWalletPath; | |
| 319 kwalletd_name_ = kKWalletDName; | |
| 320 } | |
| 321 } | 299 } |
| 322 | 300 |
| 323 NativeBackendKWallet::~NativeBackendKWallet() { | 301 NativeBackendKWallet::~NativeBackendKWallet() { |
| 324 // This destructor is called on the thread that is destroying the Profile | 302 // This destructor is called on the thread that is destroying the Profile |
| 325 // containing the PasswordStore that owns this NativeBackend. Generally that | 303 // containing the PasswordStore that owns this NativeBackend. Generally that |
| 326 // won't be the DB thread; it will be the UI thread. So we post a message to | 304 // won't be the DB thread; it will be the UI thread. So we post a message to |
| 327 // shut it down on the DB thread, and it will be destructed afterward when the | 305 // shut it down on the DB thread, and it will be destructed afterward when the |
| 328 // scoped_refptr<dbus::Bus> goes out of scope. The NativeBackend will be | 306 // scoped_refptr<dbus::Bus> goes out of scope. The NativeBackend will be |
| 329 // destroyed before that occurs, but that's OK. | 307 // destroyed before that occurs, but that's OK. |
| 330 if (session_bus_.get()) { | 308 if (kwallet_dbus_.GetBus()) { |
| 331 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 309 BrowserThread::PostTask( |
| 332 base::Bind(&dbus::Bus::ShutdownAndBlock, | 310 BrowserThread::DB, FROM_HERE, |
| 333 session_bus_.get())); | 311 base::Bind(&dbus::Bus::ShutdownAndBlock, kwallet_dbus_.GetBus())); |
| 334 } | 312 } |
| 335 } | 313 } |
| 336 | 314 |
| 337 bool NativeBackendKWallet::Init() { | 315 bool NativeBackendKWallet::Init() { |
| 338 // Without the |optional_bus| parameter, a real bus will be instantiated. | 316 // Without the |optional_bus| parameter, a real bus will be instantiated. |
| 339 return InitWithBus(scoped_refptr<dbus::Bus>()); | 317 return InitWithBus(scoped_refptr<dbus::Bus>()); |
| 340 } | 318 } |
| 341 | 319 |
| 342 bool NativeBackendKWallet::InitWithBus(scoped_refptr<dbus::Bus> optional_bus) { | 320 bool NativeBackendKWallet::InitWithBus(scoped_refptr<dbus::Bus> optional_bus) { |
| 343 // We must synchronously do a few DBus calls to figure out if initialization | 321 // We must synchronously do a few DBus calls to figure out if initialization |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 356 // This ScopedAllowWait should not be here. http://crbug.com/125331 | 334 // This ScopedAllowWait should not be here. http://crbug.com/125331 |
| 357 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 335 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 358 event.Wait(); | 336 event.Wait(); |
| 359 return success; | 337 return success; |
| 360 } | 338 } |
| 361 | 339 |
| 362 void NativeBackendKWallet::InitOnDBThread(scoped_refptr<dbus::Bus> optional_bus, | 340 void NativeBackendKWallet::InitOnDBThread(scoped_refptr<dbus::Bus> optional_bus, |
| 363 base::WaitableEvent* event, | 341 base::WaitableEvent* event, |
| 364 bool* success) { | 342 bool* success) { |
| 365 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 343 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 366 DCHECK(!session_bus_.get()); | 344 DCHECK(!kwallet_dbus_.GetBus()); |
| 367 if (optional_bus.get()) { | 345 if (optional_bus.get()) { |
| 368 // The optional_bus parameter is given when this method is called in tests. | 346 // The optional_bus parameter is given when this method is called in tests. |
| 369 session_bus_ = optional_bus; | 347 kwallet_dbus_.SetSessionBus(optional_bus); |
| 370 } else { | 348 } else { |
| 371 // Get a (real) connection to the session bus. | 349 // Get a (real) connection to the session bus. |
| 372 dbus::Bus::Options options; | 350 dbus::Bus::Options options; |
| 373 options.bus_type = dbus::Bus::SESSION; | 351 options.bus_type = dbus::Bus::SESSION; |
| 374 options.connection_type = dbus::Bus::PRIVATE; | 352 options.connection_type = dbus::Bus::PRIVATE; |
| 375 session_bus_ = new dbus::Bus(options); | 353 kwallet_dbus_.SetSessionBus(new dbus::Bus(options)); |
| 376 } | 354 } |
| 377 kwallet_proxy_ = | |
| 378 session_bus_->GetObjectProxy(dbus_service_name_, | |
| 379 dbus::ObjectPath(dbus_path_)); | |
| 380 // kwalletd may not be running. If we get a temporary failure initializing it, | 355 // kwalletd may not be running. If we get a temporary failure initializing it, |
| 381 // try to start it and then try again. (Note the short-circuit evaluation.) | 356 // try to start it and then try again. (Note the short-circuit evaluation.) |
| 382 const InitResult result = InitWallet(); | 357 const InitResult result = InitWallet(); |
| 383 *success = (result == INIT_SUCCESS || | 358 *success = (result == INIT_SUCCESS || |
| 384 (result == TEMPORARY_FAIL && | 359 (result == TEMPORARY_FAIL && |
| 385 StartKWalletd() && InitWallet() == INIT_SUCCESS)); | 360 StartKWalletd() && InitWallet() == INIT_SUCCESS)); |
| 386 event->Signal(); | 361 event->Signal(); |
| 387 } | 362 } |
| 388 | 363 |
| 389 bool NativeBackendKWallet::StartKWalletd() { | 364 bool NativeBackendKWallet::StartKWalletd() { |
| 390 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 365 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 391 // Sadly kwalletd doesn't use DBus activation, so we have to make a call to | 366 // Sadly kwalletd doesn't use DBus activation, so we have to make a call to |
| 392 // klauncher to start it. | 367 // klauncher to start it. |
|
vasilii
2016/06/10 16:58:10
Obsolete.
cfroussios
2016/06/16 12:29:08
Done.
| |
| 393 dbus::ObjectProxy* klauncher = | 368 return kwallet_dbus_.StartKWalletd(); |
| 394 session_bus_->GetObjectProxy(kKLauncherServiceName, | |
| 395 dbus::ObjectPath(kKLauncherPath)); | |
| 396 | |
| 397 dbus::MethodCall method_call(kKLauncherInterface, | |
| 398 "start_service_by_desktop_name"); | |
| 399 dbus::MessageWriter builder(&method_call); | |
| 400 std::vector<std::string> empty; | |
| 401 builder.AppendString(kwalletd_name_); // serviceName | |
| 402 builder.AppendArrayOfStrings(empty); // urls | |
| 403 builder.AppendArrayOfStrings(empty); // envs | |
| 404 builder.AppendString(std::string()); // startup_id | |
| 405 builder.AppendBool(false); // blind | |
| 406 std::unique_ptr<dbus::Response> response(klauncher->CallMethodAndBlock( | |
| 407 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 408 if (!response.get()) { | |
| 409 LOG(ERROR) << "Error contacting klauncher to start " << kwalletd_name_; | |
| 410 return false; | |
| 411 } | |
| 412 dbus::MessageReader reader(response.get()); | |
| 413 int32_t ret = -1; | |
| 414 std::string dbus_name; | |
| 415 std::string error; | |
| 416 int32_t pid = -1; | |
| 417 if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) || | |
| 418 !reader.PopString(&error) || !reader.PopInt32(&pid)) { | |
| 419 LOG(ERROR) << "Error reading response from klauncher to start " | |
| 420 << kwalletd_name_ << ": " << response->ToString(); | |
| 421 return false; | |
| 422 } | |
| 423 if (!error.empty() || ret) { | |
| 424 LOG(ERROR) << "Error launching " << kwalletd_name_ << ": error '" << error | |
| 425 << "' (code " << ret << ")"; | |
| 426 return false; | |
| 427 } | |
| 428 | |
| 429 return true; | |
| 430 } | 369 } |
| 431 | 370 |
| 432 NativeBackendKWallet::InitResult NativeBackendKWallet::InitWallet() { | 371 NativeBackendKWallet::InitResult NativeBackendKWallet::InitWallet() { |
| 433 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 372 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 434 { | |
| 435 // Check that KWallet is enabled. | |
| 436 dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); | |
| 437 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 438 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 439 if (!response.get()) { | |
| 440 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (isEnabled)"; | |
| 441 return TEMPORARY_FAIL; | |
| 442 } | |
| 443 dbus::MessageReader reader(response.get()); | |
| 444 bool enabled = false; | |
| 445 if (!reader.PopBool(&enabled)) { | |
| 446 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 447 << " (isEnabled): " << response->ToString(); | |
| 448 return PERMANENT_FAIL; | |
| 449 } | |
| 450 // Not enabled? Don't use KWallet. But also don't warn here. | |
| 451 if (!enabled) { | |
| 452 VLOG(1) << kwalletd_name_ << " reports that KWallet is not enabled."; | |
| 453 return PERMANENT_FAIL; | |
| 454 } | |
| 455 } | |
| 456 | 373 |
| 457 { | 374 KWalletDBus::Error error; |
| 458 // Get the wallet name. | 375 |
| 459 dbus::MethodCall method_call(kKWalletInterface, "networkWallet"); | 376 // Check that KWallet is enabled. |
| 460 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 377 bool enabled; |
|
vasilii
2016/06/10 16:58:10
init please
cfroussios
2016/06/16 12:29:09
Done.
| |
| 461 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 378 error = kwallet_dbus_.IsEnabled(&enabled); |
|
vasilii
2016/06/10 16:58:10
KWalletDBus::Error error = ...
cfroussios
2016/06/16 12:29:09
Done.
| |
| 462 if (!response.get()) { | 379 if (error == KWalletDBus::Error::CANNOT_CONTACT) |
| 463 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (networkWallet)"; | 380 return TEMPORARY_FAIL; |
| 464 return TEMPORARY_FAIL; | 381 if (error == KWalletDBus::Error::CANNOT_READ) |
| 465 } | 382 return PERMANENT_FAIL; |
| 466 dbus::MessageReader reader(response.get()); | 383 if (!enabled) |
| 467 if (!reader.PopString(&wallet_name_)) { | 384 return PERMANENT_FAIL; |
| 468 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 385 |
| 469 << " (networkWallet): " << response->ToString(); | 386 // Get the wallet name. |
| 470 return PERMANENT_FAIL; | 387 error = kwallet_dbus_.NetworkWallet(&wallet_name_); |
| 471 } | 388 if (error == KWalletDBus::Error::CANNOT_CONTACT) |
| 472 } | 389 return TEMPORARY_FAIL; |
| 390 if (error == KWalletDBus::Error::CANNOT_READ) | |
|
vasilii
2016/06/10 16:58:10
switch is more appropriate here and above. If you
cfroussios
2016/06/16 12:29:09
Done.
| |
| 391 return PERMANENT_FAIL; | |
| 473 | 392 |
| 474 return INIT_SUCCESS; | 393 return INIT_SUCCESS; |
| 475 } | 394 } |
| 476 | 395 |
| 477 password_manager::PasswordStoreChangeList NativeBackendKWallet::AddLogin( | 396 password_manager::PasswordStoreChangeList NativeBackendKWallet::AddLogin( |
| 478 const PasswordForm& form) { | 397 const PasswordForm& form) { |
| 479 int wallet_handle = WalletHandle(); | 398 int wallet_handle = WalletHandle(); |
| 480 if (wallet_handle == kInvalidKWalletHandle) | 399 if (wallet_handle == kInvalidKWalletHandle) |
| 481 return password_manager::PasswordStoreChangeList(); | 400 return password_manager::PasswordStoreChangeList(); |
| 482 | 401 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 631 return false; | 550 return false; |
| 632 return GetAllLoginsInternal(wallet_handle, forms); | 551 return GetAllLoginsInternal(wallet_handle, forms); |
| 633 } | 552 } |
| 634 | 553 |
| 635 bool NativeBackendKWallet::GetLoginsList( | 554 bool NativeBackendKWallet::GetLoginsList( |
| 636 const std::string& signon_realm, | 555 const std::string& signon_realm, |
| 637 int wallet_handle, | 556 int wallet_handle, |
| 638 ScopedVector<autofill::PasswordForm>* forms) { | 557 ScopedVector<autofill::PasswordForm>* forms) { |
| 639 forms->clear(); | 558 forms->clear(); |
| 640 // Is there an entry in the wallet? | 559 // Is there an entry in the wallet? |
| 641 { | 560 bool has_entry = false; |
| 642 dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); | 561 KWalletDBus::Error error = kwallet_dbus_.HasEntry( |
| 643 dbus::MessageWriter builder(&method_call); | 562 &has_entry, wallet_handle, folder_name_, signon_realm, app_name_); |
| 644 builder.AppendInt32(wallet_handle); // handle | 563 if (error) |
| 645 builder.AppendString(folder_name_); // folder | 564 return false; |
| 646 builder.AppendString(signon_realm); // key | 565 if (!has_entry) |
| 647 builder.AppendString(app_name_); // appid | 566 return true; |
| 648 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 567 |
| 649 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 568 const uint8_t* bytes = nullptr; |
| 650 if (!response.get()) { | 569 size_t length = 0; |
| 651 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasEntry)"; | 570 error = kwallet_dbus_.ReadEntry(&bytes, &length, wallet_handle, folder_name_, |
| 652 return false; | 571 signon_realm, app_name_); |
| 653 } | 572 if (error) |
| 654 dbus::MessageReader reader(response.get()); | 573 return false; |
| 655 bool has_entry = false; | 574 if (!CheckSerializedValue(bytes, length, signon_realm)) { |
| 656 if (!reader.PopBool(&has_entry)) { | 575 // This is weird, but we choose not to call it an error. There is an |
| 657 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 576 // invalid entry somehow, but by just ignoring it, we make it easier to |
| 658 << " (hasEntry): " << response->ToString(); | 577 // repair without having to delete it using kwalletmanager (that is, by |
| 659 return false; | 578 // just saving a new password within this realm to overwrite it). |
| 660 } | 579 return true; |
| 661 if (!has_entry) { | |
| 662 // This is not an error. There just isn't a matching entry. | |
| 663 return true; | |
| 664 } | |
| 665 } | 580 } |
| 666 | 581 |
| 667 { | 582 // Can't we all just agree on whether bytes are signed or not? Please? |
| 668 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); | 583 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
|
vasilii
2016/06/10 16:58:10
Would static_cast works here?
cfroussios
2016/06/16 12:29:09
Compile-time error.
| |
| 669 dbus::MessageWriter builder(&method_call); | 584 *forms = DeserializeValue(signon_realm, pickle); |
| 670 builder.AppendInt32(wallet_handle); // handle | |
| 671 builder.AppendString(folder_name_); // folder | |
| 672 builder.AppendString(signon_realm); // key | |
| 673 builder.AppendString(app_name_); // appid | |
| 674 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 675 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 676 if (!response.get()) { | |
| 677 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readEntry)"; | |
| 678 return false; | |
| 679 } | |
| 680 dbus::MessageReader reader(response.get()); | |
| 681 const uint8_t* bytes = nullptr; | |
| 682 size_t length = 0; | |
| 683 if (!reader.PopArrayOfBytes(&bytes, &length)) { | |
| 684 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 685 << " (readEntry): " << response->ToString(); | |
| 686 return false; | |
| 687 } | |
| 688 if (!bytes) | |
| 689 return false; | |
| 690 if (!CheckSerializedValue(bytes, length, signon_realm)) { | |
| 691 // This is weird, but we choose not to call it an error. There is an | |
| 692 // invalid entry somehow, but by just ignoring it, we make it easier to | |
| 693 // repair without having to delete it using kwalletmanager (that is, by | |
| 694 // just saving a new password within this realm to overwrite it). | |
| 695 return true; | |
| 696 } | |
| 697 | |
| 698 // Can't we all just agree on whether bytes are signed or not? Please? | |
| 699 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); | |
| 700 *forms = DeserializeValue(signon_realm, pickle); | |
| 701 } | |
| 702 | 585 |
| 703 return true; | 586 return true; |
| 704 } | 587 } |
| 705 | 588 |
| 706 bool NativeBackendKWallet::GetLoginsList( | 589 bool NativeBackendKWallet::GetLoginsList( |
| 707 BlacklistOptions options, | 590 BlacklistOptions options, |
| 708 int wallet_handle, | 591 int wallet_handle, |
| 709 ScopedVector<autofill::PasswordForm>* forms) { | 592 ScopedVector<autofill::PasswordForm>* forms) { |
| 710 forms->clear(); | 593 forms->clear(); |
| 711 ScopedVector<autofill::PasswordForm> all_forms; | 594 ScopedVector<autofill::PasswordForm> all_forms; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 | 631 |
| 749 return true; | 632 return true; |
| 750 } | 633 } |
| 751 | 634 |
| 752 bool NativeBackendKWallet::GetAllLoginsInternal( | 635 bool NativeBackendKWallet::GetAllLoginsInternal( |
| 753 int wallet_handle, | 636 int wallet_handle, |
| 754 ScopedVector<autofill::PasswordForm>* forms) { | 637 ScopedVector<autofill::PasswordForm>* forms) { |
| 755 // We could probably also use readEntryList here. | 638 // We could probably also use readEntryList here. |
| 756 std::vector<std::string> realm_list; | 639 std::vector<std::string> realm_list; |
| 757 { | 640 { |
| 758 dbus::MethodCall method_call(kKWalletInterface, "entryList"); | 641 KWalletDBus::Error error = kwallet_dbus_.EntryList( |
| 759 dbus::MessageWriter builder(&method_call); | 642 &realm_list, wallet_handle, folder_name_, app_name_); |
| 760 builder.AppendInt32(wallet_handle); // handle | 643 if (error) |
| 761 builder.AppendString(folder_name_); // folder | |
| 762 builder.AppendString(app_name_); // appid | |
| 763 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 764 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 765 if (!response.get()) { | |
| 766 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (entryList)"; | |
| 767 return false; | 644 return false; |
| 768 } | |
| 769 dbus::MessageReader reader(response.get()); | |
| 770 if (!reader.PopArrayOfStrings(&realm_list)) { | |
| 771 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 772 << "(entryList): " << response->ToString(); | |
| 773 return false; | |
| 774 } | |
| 775 } | 645 } |
| 776 | 646 |
| 777 forms->clear(); | 647 forms->clear(); |
| 778 for (const std::string& signon_realm : realm_list) { | 648 for (const std::string& signon_realm : realm_list) { |
| 779 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); | |
| 780 dbus::MessageWriter builder(&method_call); | |
| 781 builder.AppendInt32(wallet_handle); // handle | |
| 782 builder.AppendString(folder_name_); // folder | |
| 783 builder.AppendString(signon_realm); // key | |
| 784 builder.AppendString(app_name_); // appid | |
| 785 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 786 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 787 if (!response.get()) { | |
| 788 LOG(ERROR) << "Error contacting " << kwalletd_name_ << "(readEntry)"; | |
| 789 return false; | |
| 790 } | |
| 791 dbus::MessageReader reader(response.get()); | |
| 792 const uint8_t* bytes = nullptr; | 649 const uint8_t* bytes = nullptr; |
| 793 size_t length = 0; | 650 size_t length = 0; |
| 794 if (!reader.PopArrayOfBytes(&bytes, &length)) { | 651 KWalletDBus::Error error = kwallet_dbus_.ReadEntry( |
| 795 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 652 &bytes, &length, wallet_handle, folder_name_, signon_realm, app_name_); |
| 796 << " (readEntry): " << response->ToString(); | 653 if (error) |
| 797 return false; | 654 return false; |
| 798 } | |
| 799 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | 655 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| 800 continue; | 656 continue; |
| 801 | 657 |
| 802 // Can't we all just agree on whether bytes are signed or not? Please? | 658 // Can't we all just agree on whether bytes are signed or not? Please? |
| 803 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); | 659 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 804 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle)); | 660 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle)); |
| 805 } | 661 } |
| 806 return true; | 662 return true; |
| 807 } | 663 } |
| 808 | 664 |
| 809 bool NativeBackendKWallet::SetLoginsList( | 665 bool NativeBackendKWallet::SetLoginsList( |
| 810 const std::vector<autofill::PasswordForm*>& forms, | 666 const std::vector<autofill::PasswordForm*>& forms, |
| 811 const std::string& signon_realm, | 667 const std::string& signon_realm, |
| 812 int wallet_handle) { | 668 int wallet_handle) { |
| 813 if (forms.empty()) { | 669 if (forms.empty()) { |
| 814 // No items left? Remove the entry from the wallet. | 670 int ret = 0; |
| 815 dbus::MethodCall method_call(kKWalletInterface, "removeEntry"); | 671 KWalletDBus::Error error = kwallet_dbus_.RemoveEntry( |
| 816 dbus::MessageWriter builder(&method_call); | 672 &ret, wallet_handle, folder_name_, signon_realm, app_name_); |
| 817 builder.AppendInt32(wallet_handle); // handle | 673 if (error == KWalletDBus::CANNOT_CONTACT) |
| 818 builder.AppendString(folder_name_); // folder | 674 // TODO(cfroussios) how does this make sense? kInvalidKWalletHandle == -1 |
|
vasilii
2016/06/10 16:58:10
nonsense.
cfroussios
2016/06/16 12:29:09
Done.
| |
| 819 builder.AppendString(signon_realm); // key | |
| 820 builder.AppendString(app_name_); // appid | |
| 821 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 822 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 823 if (!response.get()) { | |
| 824 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (removeEntry)"; | |
| 825 return kInvalidKWalletHandle; | 675 return kInvalidKWalletHandle; |
| 826 } | 676 if (error == KWalletDBus::CANNOT_READ) |
| 827 dbus::MessageReader reader(response.get()); | |
| 828 int ret = 0; | |
| 829 if (!reader.PopInt32(&ret)) { | |
| 830 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 831 << " (removeEntry): " << response->ToString(); | |
| 832 return false; | 677 return false; |
| 833 } | |
| 834 if (ret != 0) | 678 if (ret != 0) |
| 835 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; | 679 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; |
| 836 return ret == 0; | 680 return ret == 0; |
| 837 } | 681 } |
| 838 | 682 |
| 839 base::Pickle value; | 683 base::Pickle value; |
| 840 SerializeValue(forms, &value); | 684 SerializeValue(forms, &value); |
| 841 | 685 |
| 842 dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); | 686 int ret = 0; |
| 843 dbus::MessageWriter builder(&method_call); | 687 KWalletDBus::Error error = kwallet_dbus_.WriteEntry( |
| 844 builder.AppendInt32(wallet_handle); // handle | 688 &ret, wallet_handle, folder_name_, signon_realm, |
| 845 builder.AppendString(folder_name_); // folder | 689 static_cast<const uint8_t*>(value.data()), value.size(), app_name_); |
| 846 builder.AppendString(signon_realm); // key | 690 if (error == KWalletDBus::CANNOT_CONTACT) |
| 847 builder.AppendArrayOfBytes(static_cast<const uint8_t*>(value.data()), | |
| 848 value.size()); // value | |
| 849 builder.AppendString(app_name_); // appid | |
| 850 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 851 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 852 if (!response.get()) { | |
| 853 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (writeEntry)"; | |
| 854 return kInvalidKWalletHandle; | 691 return kInvalidKWalletHandle; |
|
vasilii
2016/06/10 16:58:10
nonsense again
cfroussios
2016/06/16 12:29:09
Done.
| |
| 855 } | 692 if (error == KWalletDBus::CANNOT_READ) |
| 856 dbus::MessageReader reader(response.get()); | |
| 857 int ret = 0; | |
| 858 if (!reader.PopInt32(&ret)) { | |
| 859 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 860 << " (writeEntry): " << response->ToString(); | |
| 861 return false; | 693 return false; |
| 862 } | |
| 863 if (ret != 0) | 694 if (ret != 0) |
| 864 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; | 695 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; |
| 865 return ret == 0; | 696 return ret == 0; |
| 866 } | 697 } |
| 867 | 698 |
| 868 bool NativeBackendKWallet::RemoveLoginsBetween( | 699 bool NativeBackendKWallet::RemoveLoginsBetween( |
| 869 base::Time delete_begin, | 700 base::Time delete_begin, |
| 870 base::Time delete_end, | 701 base::Time delete_end, |
| 871 TimestampToCompare date_to_compare, | 702 TimestampToCompare date_to_compare, |
| 872 password_manager::PasswordStoreChangeList* changes) { | 703 password_manager::PasswordStoreChangeList* changes) { |
| 873 DCHECK(changes); | 704 DCHECK(changes); |
| 874 changes->clear(); | 705 changes->clear(); |
| 875 int wallet_handle = WalletHandle(); | 706 int wallet_handle = WalletHandle(); |
| 876 if (wallet_handle == kInvalidKWalletHandle) | 707 if (wallet_handle == kInvalidKWalletHandle) |
| 877 return false; | 708 return false; |
| 878 | 709 |
| 879 // We could probably also use readEntryList here. | 710 // We could probably also use readEntryList here. |
| 880 std::vector<std::string> realm_list; | 711 std::vector<std::string> realm_list; |
| 881 { | 712 { |
| 882 dbus::MethodCall method_call(kKWalletInterface, "entryList"); | 713 KWalletDBus::Error error = kwallet_dbus_.EntryList( |
| 883 dbus::MessageWriter builder(&method_call); | 714 &realm_list, wallet_handle, folder_name_, app_name_); |
| 884 builder.AppendInt32(wallet_handle); // handle | 715 if (error) |
| 885 builder.AppendString(folder_name_); // folder | |
| 886 builder.AppendString(app_name_); // appid | |
| 887 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 888 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 889 if (!response.get()) { | |
| 890 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (entryList)"; | |
| 891 return false; | 716 return false; |
| 892 } | |
| 893 dbus::MessageReader reader(response.get()); | |
| 894 dbus::MessageReader array(response.get()); | |
| 895 if (!reader.PopArray(&array)) { | |
| 896 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 897 << " (entryList): " << response->ToString(); | |
| 898 return false; | |
| 899 } | |
| 900 while (array.HasMoreData()) { | |
| 901 std::string realm; | |
| 902 if (!array.PopString(&realm)) { | |
| 903 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 904 << " (entryList): " << response->ToString(); | |
| 905 return false; | |
| 906 } | |
| 907 realm_list.push_back(realm); | |
| 908 } | |
| 909 } | 717 } |
| 910 | 718 |
| 911 bool ok = true; | 719 bool ok = true; |
| 912 for (size_t i = 0; i < realm_list.size(); ++i) { | 720 for (size_t i = 0; i < realm_list.size(); ++i) { |
| 913 const std::string& signon_realm = realm_list[i]; | 721 const std::string& signon_realm = realm_list[i]; |
| 914 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); | 722 |
| 915 dbus::MessageWriter builder(&method_call); | |
| 916 builder.AppendInt32(wallet_handle); // handle | |
| 917 builder.AppendString(folder_name_); // folder | |
| 918 builder.AppendString(signon_realm); // key | |
| 919 builder.AppendString(app_name_); // appid | |
| 920 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 921 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 922 if (!response.get()) { | |
| 923 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readEntry)"; | |
| 924 continue; | |
| 925 } | |
| 926 dbus::MessageReader reader(response.get()); | |
| 927 const uint8_t* bytes = nullptr; | 723 const uint8_t* bytes = nullptr; |
| 928 size_t length = 0; | 724 size_t length = 0; |
| 929 if (!reader.PopArrayOfBytes(&bytes, &length)) { | 725 KWalletDBus::Error error = kwallet_dbus_.ReadEntry( |
| 930 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 726 &bytes, &length, wallet_handle, folder_name_, signon_realm, app_name_); |
| 931 << " (readEntry): " << response->ToString(); | 727 if (error) |
| 932 continue; | 728 continue; |
| 933 } | |
| 934 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | 729 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| 935 continue; | 730 continue; |
| 936 | 731 |
| 937 // Can't we all just agree on whether bytes are signed or not? Please? | 732 // Can't we all just agree on whether bytes are signed or not? Please? |
| 938 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); | 733 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 939 ScopedVector<autofill::PasswordForm> all_forms = | 734 ScopedVector<autofill::PasswordForm> all_forms = |
| 940 DeserializeValue(signon_realm, pickle); | 735 DeserializeValue(signon_realm, pickle); |
| 941 | 736 |
| 942 ScopedVector<autofill::PasswordForm> kept_forms; | 737 ScopedVector<autofill::PasswordForm> kept_forms; |
| 943 kept_forms.reserve(all_forms.size()); | 738 kept_forms.reserve(all_forms.size()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1001 UMALogDeserializationStatus(success); | 796 UMALogDeserializationStatus(success); |
| 1002 return forms; | 797 return forms; |
| 1003 } | 798 } |
| 1004 | 799 |
| 1005 int NativeBackendKWallet::WalletHandle() { | 800 int NativeBackendKWallet::WalletHandle() { |
| 1006 DCHECK_CURRENTLY_ON(BrowserThread::DB); | 801 DCHECK_CURRENTLY_ON(BrowserThread::DB); |
| 1007 | 802 |
| 1008 // Open the wallet. | 803 // Open the wallet. |
| 1009 // TODO(mdm): Are we leaking these handles? Find out. | 804 // TODO(mdm): Are we leaking these handles? Find out. |
| 1010 int32_t handle = kInvalidKWalletHandle; | 805 int32_t handle = kInvalidKWalletHandle; |
| 1011 { | 806 { |
|
vasilii
2016/06/10 16:58:10
what is the point of those {} here and before?
cfroussios
2016/06/16 12:29:09
The previous author preferred scoping reappearing
| |
| 1012 dbus::MethodCall method_call(kKWalletInterface, "open"); | 807 KWalletDBus::Error error = |
| 1013 dbus::MessageWriter builder(&method_call); | 808 kwallet_dbus_.Open(&handle, wallet_name_, app_name_); |
| 1014 builder.AppendString(wallet_name_); // wallet | 809 if (error) |
| 1015 builder.AppendInt64(0); // wid | |
| 1016 builder.AppendString(app_name_); // appid | |
| 1017 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 1018 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 1019 if (!response.get()) { | |
| 1020 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (open)"; | |
| 1021 return kInvalidKWalletHandle; | 810 return kInvalidKWalletHandle; |
| 1022 } | |
| 1023 dbus::MessageReader reader(response.get()); | |
| 1024 if (!reader.PopInt32(&handle)) { | |
| 1025 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 1026 << " (open): " << response->ToString(); | |
| 1027 return kInvalidKWalletHandle; | |
| 1028 } | |
| 1029 if (handle == kInvalidKWalletHandle) { | 811 if (handle == kInvalidKWalletHandle) { |
| 1030 LOG(ERROR) << "Error obtaining KWallet handle"; | 812 LOG(ERROR) << "Error obtaining KWallet handle"; |
| 1031 return kInvalidKWalletHandle; | 813 return kInvalidKWalletHandle; |
| 1032 } | 814 } |
| 1033 } | 815 } |
| 1034 | 816 |
| 1035 // Check if our folder exists. | 817 // Check if our folder exists. |
| 1036 bool has_folder = false; | 818 bool has_folder = false; |
| 1037 { | 819 { |
| 1038 dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); | 820 KWalletDBus::Error error = |
| 1039 dbus::MessageWriter builder(&method_call); | 821 kwallet_dbus_.HasFolder(&has_folder, handle, folder_name_, app_name_); |
| 1040 builder.AppendInt32(handle); // handle | 822 if (error) |
| 1041 builder.AppendString(folder_name_); // folder | |
| 1042 builder.AppendString(app_name_); // appid | |
| 1043 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 1044 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 1045 if (!response.get()) { | |
| 1046 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasFolder)"; | |
| 1047 return kInvalidKWalletHandle; | 823 return kInvalidKWalletHandle; |
| 1048 } | |
| 1049 dbus::MessageReader reader(response.get()); | |
| 1050 if (!reader.PopBool(&has_folder)) { | |
| 1051 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 1052 << " (hasFolder): " << response->ToString(); | |
| 1053 return kInvalidKWalletHandle; | |
| 1054 } | |
| 1055 } | 824 } |
| 1056 | 825 |
| 1057 // Create it if it didn't. | 826 // Create it if it didn't. |
| 1058 if (!has_folder) { | 827 if (!has_folder) { |
| 1059 dbus::MethodCall method_call(kKWalletInterface, "createFolder"); | 828 bool success = false; |
| 1060 dbus::MessageWriter builder(&method_call); | 829 KWalletDBus::Error error = |
| 1061 builder.AppendInt32(handle); // handle | 830 kwallet_dbus_.CreateFolder(&success, handle, folder_name_, app_name_); |
| 1062 builder.AppendString(folder_name_); // folder | 831 if (error) |
| 1063 builder.AppendString(app_name_); // appid | |
| 1064 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | |
| 1065 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 1066 if (!response.get()) { | |
| 1067 LOG(ERROR) << "Error contacting << " << kwalletd_name_ | |
| 1068 << " (createFolder)"; | |
| 1069 return kInvalidKWalletHandle; | 832 return kInvalidKWalletHandle; |
| 1070 } | |
| 1071 dbus::MessageReader reader(response.get()); | |
| 1072 bool success = false; | |
| 1073 if (!reader.PopBool(&success)) { | |
| 1074 LOG(ERROR) << "Error reading response from " << kwalletd_name_ | |
| 1075 << " (createFolder): " << response->ToString(); | |
| 1076 return kInvalidKWalletHandle; | |
| 1077 } | |
| 1078 if (!success) { | 833 if (!success) { |
| 1079 LOG(ERROR) << "Error creating KWallet folder"; | 834 LOG(ERROR) << "Error creating KWallet folder"; |
| 1080 return kInvalidKWalletHandle; | 835 return kInvalidKWalletHandle; |
| 1081 } | 836 } |
| 1082 } | 837 } |
| 1083 | 838 |
| 1084 return handle; | 839 return handle; |
| 1085 } | 840 } |
| 1086 | 841 |
| 1087 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { | 842 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { |
| 1088 // Originally, the folder name was always just "Chrome Form Data". | 843 // Originally, the folder name was always just "Chrome Form Data". |
| 1089 // Now we use it to distinguish passwords for different profiles. | 844 // Now we use it to distinguish passwords for different profiles. |
| 1090 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); | 845 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); |
| 1091 } | 846 } |
| OLD | NEW |