| 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 <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 kept_forms.push_back(all_forms[i]); | 349 kept_forms.push_back(all_forms[i]); |
| 350 } | 350 } |
| 351 | 351 |
| 352 // Update the entry in the wallet, possibly deleting it. | 352 // Update the entry in the wallet, possibly deleting it. |
| 353 bool ok = SetLoginsList(kept_forms, form.signon_realm, wallet_handle); | 353 bool ok = SetLoginsList(kept_forms, form.signon_realm, wallet_handle); |
| 354 | 354 |
| 355 STLDeleteElements(&kept_forms); | 355 STLDeleteElements(&kept_forms); |
| 356 return ok; | 356 return ok; |
| 357 } | 357 } |
| 358 | 358 |
| 359 bool NativeBackendKWallet::RemoveLoginsCreatedBetween( | 359 bool NativeBackendKWallet::RemoveLoginsCreatedBetween(base::Time delete_begin, |
| 360 const base::Time& delete_begin, | 360 base::Time delete_end) { |
| 361 const base::Time& delete_end) { | 361 password_manager::PasswordStoreChangeList changes; |
| 362 int wallet_handle = WalletHandle(); | 362 return RemoveLoginsBetween( |
| 363 if (wallet_handle == kInvalidKWalletHandle) | 363 delete_begin, delete_end, CREATION_TIMESTAMP, &changes); |
| 364 return false; | 364 } |
| 365 | 365 |
| 366 // We could probably also use readEntryList here. | 366 bool NativeBackendKWallet::RemoveLoginsSyncedBetween( |
| 367 std::vector<std::string> realm_list; | 367 base::Time delete_begin, |
| 368 { | 368 base::Time delete_end, |
| 369 dbus::MethodCall method_call(kKWalletInterface, "entryList"); | 369 password_manager::PasswordStoreChangeList* changes) { |
| 370 dbus::MessageWriter builder(&method_call); | 370 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); |
| 371 builder.AppendInt32(wallet_handle); // handle | |
| 372 builder.AppendString(folder_name_); // folder | |
| 373 builder.AppendString(app_name_); // appid | |
| 374 scoped_ptr<dbus::Response> response( | |
| 375 kwallet_proxy_->CallMethodAndBlock( | |
| 376 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 377 if (!response.get()) { | |
| 378 LOG(ERROR) << "Error contacting kwalletd (entryList)"; | |
| 379 return false; | |
| 380 } | |
| 381 dbus::MessageReader reader(response.get()); | |
| 382 dbus::MessageReader array(response.get()); | |
| 383 if (!reader.PopArray(&array)) { | |
| 384 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 385 << response->ToString(); | |
| 386 return false; | |
| 387 } | |
| 388 while (array.HasMoreData()) { | |
| 389 std::string realm; | |
| 390 if (!array.PopString(&realm)) { | |
| 391 LOG(ERROR) << "Error reading response from kwalletd (entryList): " | |
| 392 << response->ToString(); | |
| 393 return false; | |
| 394 } | |
| 395 realm_list.push_back(realm); | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 bool ok = true; | |
| 400 for (size_t i = 0; i < realm_list.size(); ++i) { | |
| 401 const std::string& signon_realm = realm_list[i]; | |
| 402 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); | |
| 403 dbus::MessageWriter builder(&method_call); | |
| 404 builder.AppendInt32(wallet_handle); // handle | |
| 405 builder.AppendString(folder_name_); // folder | |
| 406 builder.AppendString(signon_realm); // key | |
| 407 builder.AppendString(app_name_); // appid | |
| 408 scoped_ptr<dbus::Response> response( | |
| 409 kwallet_proxy_->CallMethodAndBlock( | |
| 410 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 411 if (!response.get()) { | |
| 412 LOG(ERROR) << "Error contacting kwalletd (readEntry)"; | |
| 413 continue; | |
| 414 } | |
| 415 dbus::MessageReader reader(response.get()); | |
| 416 const uint8_t* bytes = NULL; | |
| 417 size_t length = 0; | |
| 418 if (!reader.PopArrayOfBytes(&bytes, &length)) { | |
| 419 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " | |
| 420 << response->ToString(); | |
| 421 continue; | |
| 422 } | |
| 423 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) | |
| 424 continue; | |
| 425 | |
| 426 // Can't we all just agree on whether bytes are signed or not? Please? | |
| 427 Pickle pickle(reinterpret_cast<const char*>(bytes), length); | |
| 428 PasswordFormList all_forms; | |
| 429 DeserializeValue(signon_realm, pickle, &all_forms); | |
| 430 | |
| 431 PasswordFormList kept_forms; | |
| 432 kept_forms.reserve(all_forms.size()); | |
| 433 for (size_t i = 0; i < all_forms.size(); ++i) { | |
| 434 if (delete_begin <= all_forms[i]->date_created && | |
| 435 (delete_end.is_null() || all_forms[i]->date_created < delete_end)) { | |
| 436 delete all_forms[i]; | |
| 437 } else { | |
| 438 kept_forms.push_back(all_forms[i]); | |
| 439 } | |
| 440 } | |
| 441 | |
| 442 if (!SetLoginsList(kept_forms, signon_realm, wallet_handle)) | |
| 443 ok = false; | |
| 444 STLDeleteElements(&kept_forms); | |
| 445 } | |
| 446 return ok; | |
| 447 } | 371 } |
| 448 | 372 |
| 449 bool NativeBackendKWallet::GetLogins(const PasswordForm& form, | 373 bool NativeBackendKWallet::GetLogins(const PasswordForm& form, |
| 450 PasswordFormList* forms) { | 374 PasswordFormList* forms) { |
| 451 int wallet_handle = WalletHandle(); | 375 int wallet_handle = WalletHandle(); |
| 452 if (wallet_handle == kInvalidKWalletHandle) | 376 if (wallet_handle == kInvalidKWalletHandle) |
| 453 return false; | 377 return false; |
| 454 return GetLoginsList(forms, form.signon_realm, wallet_handle); | 378 return GetLoginsList(forms, form.signon_realm, wallet_handle); |
| 455 } | 379 } |
| 456 | 380 |
| 457 bool NativeBackendKWallet::GetLoginsCreatedBetween(const base::Time& get_begin, | 381 bool NativeBackendKWallet::GetLoginsCreatedBetween(base::Time get_begin, |
| 458 const base::Time& get_end, | 382 base::Time get_end, |
| 459 PasswordFormList* forms) { | 383 PasswordFormList* forms) { |
| 460 int wallet_handle = WalletHandle(); | 384 int wallet_handle = WalletHandle(); |
| 461 if (wallet_handle == kInvalidKWalletHandle) | 385 if (wallet_handle == kInvalidKWalletHandle) |
| 462 return false; | 386 return false; |
| 463 return GetLoginsList(forms, get_begin, get_end, wallet_handle); | 387 return GetLoginsList( |
| 388 forms, get_begin, get_end, wallet_handle, CREATION_TIMESTAMP); |
| 464 } | 389 } |
| 465 | 390 |
| 466 bool NativeBackendKWallet::GetAutofillableLogins(PasswordFormList* forms) { | 391 bool NativeBackendKWallet::GetAutofillableLogins(PasswordFormList* forms) { |
| 467 int wallet_handle = WalletHandle(); | 392 int wallet_handle = WalletHandle(); |
| 468 if (wallet_handle == kInvalidKWalletHandle) | 393 if (wallet_handle == kInvalidKWalletHandle) |
| 469 return false; | 394 return false; |
| 470 return GetLoginsList(forms, true, wallet_handle); | 395 return GetLoginsList(forms, true, wallet_handle); |
| 471 } | 396 } |
| 472 | 397 |
| 473 bool NativeBackendKWallet::GetBlacklistLogins(PasswordFormList* forms) { | 398 bool NativeBackendKWallet::GetBlacklistLogins(PasswordFormList* forms) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 else | 489 else |
| 565 delete all_forms[i]; | 490 delete all_forms[i]; |
| 566 } | 491 } |
| 567 | 492 |
| 568 return true; | 493 return true; |
| 569 } | 494 } |
| 570 | 495 |
| 571 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, | 496 bool NativeBackendKWallet::GetLoginsList(PasswordFormList* forms, |
| 572 const base::Time& begin, | 497 const base::Time& begin, |
| 573 const base::Time& end, | 498 const base::Time& end, |
| 574 int wallet_handle) { | 499 int wallet_handle, |
| 500 TimestampToCompare date_to_compare) { |
| 575 PasswordFormList all_forms; | 501 PasswordFormList all_forms; |
| 576 if (!GetAllLogins(&all_forms, wallet_handle)) | 502 if (!GetAllLogins(&all_forms, wallet_handle)) |
| 577 return false; | 503 return false; |
| 578 | 504 |
| 579 // We have to read all the entries, and then filter them here. | 505 // We have to read all the entries, and then filter them here. |
| 506 base::Time autofill::PasswordForm::*date_member = |
| 507 date_to_compare == CREATION_TIMESTAMP |
| 508 ? &autofill::PasswordForm::date_created |
| 509 : &autofill::PasswordForm::date_synced; |
| 580 forms->reserve(forms->size() + all_forms.size()); | 510 forms->reserve(forms->size() + all_forms.size()); |
| 581 for (size_t i = 0; i < all_forms.size(); ++i) { | 511 for (size_t i = 0; i < all_forms.size(); ++i) { |
| 582 if (begin <= all_forms[i]->date_created && | 512 if (begin <= all_forms[i]->*date_member && |
| 583 (end.is_null() || all_forms[i]->date_created < end)) { | 513 (end.is_null() || all_forms[i]->*date_member < end)) { |
| 584 forms->push_back(all_forms[i]); | 514 forms->push_back(all_forms[i]); |
| 585 } else { | 515 } else { |
| 586 delete all_forms[i]; | 516 delete all_forms[i]; |
| 587 } | 517 } |
| 588 } | 518 } |
| 589 | 519 |
| 590 return true; | 520 return true; |
| 591 } | 521 } |
| 592 | 522 |
| 593 bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, | 523 bool NativeBackendKWallet::GetAllLogins(PasswordFormList* forms, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 if (!reader.PopInt32(&ret)) { | 632 if (!reader.PopInt32(&ret)) { |
| 703 LOG(ERROR) << "Error reading response from kwalletd (writeEntry): " | 633 LOG(ERROR) << "Error reading response from kwalletd (writeEntry): " |
| 704 << response->ToString(); | 634 << response->ToString(); |
| 705 return false; | 635 return false; |
| 706 } | 636 } |
| 707 if (ret != 0) | 637 if (ret != 0) |
| 708 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; | 638 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; |
| 709 return ret == 0; | 639 return ret == 0; |
| 710 } | 640 } |
| 711 | 641 |
| 642 bool NativeBackendKWallet::RemoveLoginsBetween( |
| 643 base::Time delete_begin, |
| 644 base::Time delete_end, |
| 645 TimestampToCompare date_to_compare, |
| 646 password_manager::PasswordStoreChangeList* changes) { |
| 647 DCHECK(changes); |
| 648 changes->clear(); |
| 649 int wallet_handle = WalletHandle(); |
| 650 if (wallet_handle == kInvalidKWalletHandle) |
| 651 return false; |
| 652 |
| 653 // We could probably also use readEntryList here. |
| 654 std::vector<std::string> realm_list; |
| 655 { |
| 656 dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| 657 dbus::MessageWriter builder(&method_call); |
| 658 builder.AppendInt32(wallet_handle); // handle |
| 659 builder.AppendString(folder_name_); // folder |
| 660 builder.AppendString(app_name_); // appid |
| 661 scoped_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 662 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 663 if (!response.get()) { |
| 664 LOG(ERROR) << "Error contacting kwalletd (entryList)"; |
| 665 return false; |
| 666 } |
| 667 dbus::MessageReader reader(response.get()); |
| 668 dbus::MessageReader array(response.get()); |
| 669 if (!reader.PopArray(&array)) { |
| 670 LOG(ERROR) << "Error reading response from kwalletd (entryList): " |
| 671 << response->ToString(); |
| 672 return false; |
| 673 } |
| 674 while (array.HasMoreData()) { |
| 675 std::string realm; |
| 676 if (!array.PopString(&realm)) { |
| 677 LOG(ERROR) << "Error reading response from kwalletd (entryList): " |
| 678 << response->ToString(); |
| 679 return false; |
| 680 } |
| 681 realm_list.push_back(realm); |
| 682 } |
| 683 } |
| 684 |
| 685 bool ok = true; |
| 686 for (size_t i = 0; i < realm_list.size(); ++i) { |
| 687 const std::string& signon_realm = realm_list[i]; |
| 688 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| 689 dbus::MessageWriter builder(&method_call); |
| 690 builder.AppendInt32(wallet_handle); // handle |
| 691 builder.AppendString(folder_name_); // folder |
| 692 builder.AppendString(signon_realm); // key |
| 693 builder.AppendString(app_name_); // appid |
| 694 scoped_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 695 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 696 if (!response.get()) { |
| 697 LOG(ERROR) << "Error contacting kwalletd (readEntry)"; |
| 698 continue; |
| 699 } |
| 700 dbus::MessageReader reader(response.get()); |
| 701 const uint8_t* bytes = NULL; |
| 702 size_t length = 0; |
| 703 if (!reader.PopArrayOfBytes(&bytes, &length)) { |
| 704 LOG(ERROR) << "Error reading response from kwalletd (readEntry): " |
| 705 << response->ToString(); |
| 706 continue; |
| 707 } |
| 708 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm)) |
| 709 continue; |
| 710 |
| 711 // Can't we all just agree on whether bytes are signed or not? Please? |
| 712 Pickle pickle(reinterpret_cast<const char*>(bytes), length); |
| 713 PasswordFormList all_forms; |
| 714 DeserializeValue(signon_realm, pickle, &all_forms); |
| 715 |
| 716 PasswordFormList kept_forms; |
| 717 kept_forms.reserve(all_forms.size()); |
| 718 base::Time autofill::PasswordForm::*date_member = |
| 719 date_to_compare == CREATION_TIMESTAMP |
| 720 ? &autofill::PasswordForm::date_created |
| 721 : &autofill::PasswordForm::date_synced; |
| 722 for (size_t i = 0; i < all_forms.size(); ++i) { |
| 723 if (delete_begin <= all_forms[i]->*date_member && |
| 724 (delete_end.is_null() || all_forms[i]->*date_member < delete_end)) { |
| 725 changes->push_back(password_manager::PasswordStoreChange( |
| 726 password_manager::PasswordStoreChange::REMOVE, *all_forms[i])); |
| 727 delete all_forms[i]; |
| 728 } else { |
| 729 kept_forms.push_back(all_forms[i]); |
| 730 } |
| 731 } |
| 732 |
| 733 if (!SetLoginsList(kept_forms, signon_realm, wallet_handle)) { |
| 734 ok = false; |
| 735 changes->clear(); |
| 736 } |
| 737 STLDeleteElements(&kept_forms); |
| 738 } |
| 739 return ok; |
| 740 } |
| 741 |
| 712 // static | 742 // static |
| 713 void NativeBackendKWallet::SerializeValue(const PasswordFormList& forms, | 743 void NativeBackendKWallet::SerializeValue(const PasswordFormList& forms, |
| 714 Pickle* pickle) { | 744 Pickle* pickle) { |
| 715 pickle->WriteInt(kPickleVersion); | 745 pickle->WriteInt(kPickleVersion); |
| 716 pickle->WriteUInt64(forms.size()); | 746 pickle->WriteUInt64(forms.size()); |
| 717 for (PasswordFormList::const_iterator it = forms.begin(); | 747 for (PasswordFormList::const_iterator it = forms.begin(); |
| 718 it != forms.end(); ++it) { | 748 it != forms.end(); ++it) { |
| 719 const PasswordForm* form = *it; | 749 const PasswordForm* form = *it; |
| 720 pickle->WriteInt(form->scheme); | 750 pickle->WriteInt(form->scheme); |
| 721 pickle->WriteString(form->origin.spec()); | 751 pickle->WriteString(form->origin.spec()); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 } | 974 } |
| 945 | 975 |
| 946 return handle; | 976 return handle; |
| 947 } | 977 } |
| 948 | 978 |
| 949 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { | 979 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { |
| 950 // Originally, the folder name was always just "Chrome Form Data". | 980 // Originally, the folder name was always just "Chrome Form Data". |
| 951 // Now we use it to distinguish passwords for different profiles. | 981 // Now we use it to distinguish passwords for different profiles. |
| 952 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); | 982 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); |
| 953 } | 983 } |
| OLD | NEW |