Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: chrome/browser/password_manager/native_backend_kwallet_x.cc

Issue 2057123002: Refactor native_backend_kwallet_x (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cleanup Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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_.GetSessionBus()) {
331 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 309 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
332 base::Bind(&dbus::Bus::ShutdownAndBlock, 310 base::Bind(&dbus::Bus::ShutdownAndBlock,
333 session_bus_.get())); 311 kwallet_dbus_.GetSessionBus()));
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
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_.GetSessionBus());
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 && kwallet_dbus_.StartKWalletd() &&
385 StartKWalletd() && InitWallet() == INIT_SUCCESS)); 360 InitWallet() == INIT_SUCCESS));
386 event->Signal(); 361 event->Signal();
387 } 362 }
388 363
389 bool NativeBackendKWallet::StartKWalletd() {
390 DCHECK_CURRENTLY_ON(BrowserThread::DB);
391 // Sadly kwalletd doesn't use DBus activation, so we have to make a call to
392 // klauncher to start it.
393 dbus::ObjectProxy* klauncher =
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 }
431
432 NativeBackendKWallet::InitResult NativeBackendKWallet::InitWallet() { 364 NativeBackendKWallet::InitResult NativeBackendKWallet::InitWallet() {
433 DCHECK_CURRENTLY_ON(BrowserThread::DB); 365 DCHECK_CURRENTLY_ON(BrowserThread::DB);
434 { 366
435 // Check that KWallet is enabled. 367 // Check that KWallet is enabled.
436 dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); 368 bool enabled = false;
437 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( 369 KWalletDBus::Error error = kwallet_dbus_.IsEnabled(&enabled);
438 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); 370 switch (error) {
439 if (!response.get()) { 371 case KWalletDBus::Error::CANNOT_CONTACT:
440 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (isEnabled)";
441 return TEMPORARY_FAIL; 372 return TEMPORARY_FAIL;
442 } 373 case KWalletDBus::Error::CANNOT_READ:
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; 374 return PERMANENT_FAIL;
449 } 375 case KWalletDBus::Error::SUCCESS:
450 // Not enabled? Don't use KWallet. But also don't warn here. 376 break;
451 if (!enabled) { 377 }
452 VLOG(1) << kwalletd_name_ << " reports that KWallet is not enabled."; 378 if (!enabled)
379 return PERMANENT_FAIL;
380
381 // Get the wallet name.
382 error = kwallet_dbus_.NetworkWallet(&wallet_name_);
383 switch (error) {
384 case KWalletDBus::Error::CANNOT_CONTACT:
385 return TEMPORARY_FAIL;
386 case KWalletDBus::Error::CANNOT_READ:
453 return PERMANENT_FAIL; 387 return PERMANENT_FAIL;
454 } 388 case KWalletDBus::Error::SUCCESS:
389 return INIT_SUCCESS;
455 } 390 }
456
457 {
458 // Get the wallet name.
459 dbus::MethodCall method_call(kKWalletInterface, "networkWallet");
460 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
461 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
462 if (!response.get()) {
463 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (networkWallet)";
464 return TEMPORARY_FAIL;
465 }
466 dbus::MessageReader reader(response.get());
467 if (!reader.PopString(&wallet_name_)) {
468 LOG(ERROR) << "Error reading response from " << kwalletd_name_
469 << " (networkWallet): " << response->ToString();
470 return PERMANENT_FAIL;
471 }
472 }
473
474 return INIT_SUCCESS;
475 } 391 }
476 392
477 password_manager::PasswordStoreChangeList NativeBackendKWallet::AddLogin( 393 password_manager::PasswordStoreChangeList NativeBackendKWallet::AddLogin(
478 const PasswordForm& form) { 394 const PasswordForm& form) {
479 int wallet_handle = WalletHandle(); 395 int wallet_handle = WalletHandle();
480 if (wallet_handle == kInvalidKWalletHandle) 396 if (wallet_handle == kInvalidKWalletHandle)
481 return password_manager::PasswordStoreChangeList(); 397 return password_manager::PasswordStoreChangeList();
482 398
483 ScopedVector<autofill::PasswordForm> forms; 399 ScopedVector<autofill::PasswordForm> forms;
484 if (!GetLoginsList(form.signon_realm, wallet_handle, &forms)) 400 if (!GetLoginsList(form.signon_realm, wallet_handle, &forms))
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 return false; 547 return false;
632 return GetAllLoginsInternal(wallet_handle, forms); 548 return GetAllLoginsInternal(wallet_handle, forms);
633 } 549 }
634 550
635 bool NativeBackendKWallet::GetLoginsList( 551 bool NativeBackendKWallet::GetLoginsList(
636 const std::string& signon_realm, 552 const std::string& signon_realm,
637 int wallet_handle, 553 int wallet_handle,
638 ScopedVector<autofill::PasswordForm>* forms) { 554 ScopedVector<autofill::PasswordForm>* forms) {
639 forms->clear(); 555 forms->clear();
640 // Is there an entry in the wallet? 556 // Is there an entry in the wallet?
641 { 557 bool has_entry = false;
642 dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); 558 KWalletDBus::Error error = kwallet_dbus_.HasEntry(
643 dbus::MessageWriter builder(&method_call); 559 wallet_handle, folder_name_, signon_realm, app_name_, &has_entry);
644 builder.AppendInt32(wallet_handle); // handle 560 if (error)
645 builder.AppendString(folder_name_); // folder 561 return false;
646 builder.AppendString(signon_realm); // key 562 if (!has_entry)
647 builder.AppendString(app_name_); // appid 563 return true;
648 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( 564
649 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); 565 std::vector<uint8_t> bytes;
650 if (!response.get()) { 566 error = kwallet_dbus_.ReadEntry(wallet_handle, folder_name_, signon_realm,
651 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasEntry)"; 567 app_name_, &bytes);
652 return false; 568 if (error)
653 } 569 return false;
654 dbus::MessageReader reader(response.get()); 570 if (bytes.size() &&
vasilii 2016/06/17 14:43:41 !bytes.empty()
cfroussios 2016/06/20 13:00:43 Done.
655 bool has_entry = false; 571 !CheckSerializedValue(bytes.data(), bytes.size(), signon_realm)) {
656 if (!reader.PopBool(&has_entry)) { 572 // This is weird, but we choose not to call it an error. There is an
657 LOG(ERROR) << "Error reading response from " << kwalletd_name_ 573 // invalid entry somehow, but by just ignoring it, we make it easier to
658 << " (hasEntry): " << response->ToString(); 574 // repair without having to delete it using kwalletmanager (that is, by
659 return false; 575 // just saving a new password within this realm to overwrite it).
660 } 576 return true;
661 if (!has_entry) {
662 // This is not an error. There just isn't a matching entry.
663 return true;
664 }
665 } 577 }
666 578
667 { 579 // Can't we all just agree on whether bytes are signed or not? Please?
668 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); 580 base::Pickle pickle(reinterpret_cast<const char*>(bytes.data()),
669 dbus::MessageWriter builder(&method_call); 581 bytes.size());
670 builder.AppendInt32(wallet_handle); // handle 582 *forms = DeserializeValue(signon_realm, pickle);
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 583
703 return true; 584 return true;
704 } 585 }
705 586
706 bool NativeBackendKWallet::GetLoginsList( 587 bool NativeBackendKWallet::GetLoginsList(
707 BlacklistOptions options, 588 BlacklistOptions options,
708 int wallet_handle, 589 int wallet_handle,
709 ScopedVector<autofill::PasswordForm>* forms) { 590 ScopedVector<autofill::PasswordForm>* forms) {
710 forms->clear(); 591 forms->clear();
711 ScopedVector<autofill::PasswordForm> all_forms; 592 ScopedVector<autofill::PasswordForm> all_forms;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 } 628 }
748 629
749 return true; 630 return true;
750 } 631 }
751 632
752 bool NativeBackendKWallet::GetAllLoginsInternal( 633 bool NativeBackendKWallet::GetAllLoginsInternal(
753 int wallet_handle, 634 int wallet_handle,
754 ScopedVector<autofill::PasswordForm>* forms) { 635 ScopedVector<autofill::PasswordForm>* forms) {
755 // We could probably also use readEntryList here. 636 // We could probably also use readEntryList here.
756 std::vector<std::string> realm_list; 637 std::vector<std::string> realm_list;
757 { 638 KWalletDBus::Error error = kwallet_dbus_.EntryList(
758 dbus::MethodCall method_call(kKWalletInterface, "entryList"); 639 wallet_handle, folder_name_, app_name_, &realm_list);
759 dbus::MessageWriter builder(&method_call); 640 if (error)
760 builder.AppendInt32(wallet_handle); // handle 641 return false;
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;
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 }
776 642
777 forms->clear(); 643 forms->clear();
778 for (const std::string& signon_realm : realm_list) { 644 for (const std::string& signon_realm : realm_list) {
779 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); 645 std::vector<uint8_t> bytes;
780 dbus::MessageWriter builder(&method_call); 646 KWalletDBus::Error error = kwallet_dbus_.ReadEntry(
781 builder.AppendInt32(wallet_handle); // handle 647 wallet_handle, folder_name_, signon_realm, app_name_, &bytes);
782 builder.AppendString(folder_name_); // folder 648 if (error)
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; 649 return false;
790 } 650 if (bytes.size() == 0 ||
791 dbus::MessageReader reader(response.get()); 651 !CheckSerializedValue(bytes.data(), bytes.size(), signon_realm))
792 const uint8_t* bytes = nullptr;
793 size_t length = 0;
794 if (!reader.PopArrayOfBytes(&bytes, &length)) {
795 LOG(ERROR) << "Error reading response from " << kwalletd_name_
796 << " (readEntry): " << response->ToString();
797 return false;
798 }
799 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm))
800 continue; 652 continue;
801 653
802 // Can't we all just agree on whether bytes are signed or not? Please? 654 // Can't we all just agree on whether bytes are signed or not? Please?
803 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); 655 base::Pickle pickle(reinterpret_cast<const char*>(bytes.data()),
656 bytes.size());
804 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle)); 657 AppendSecondToFirst(forms, DeserializeValue(signon_realm, pickle));
805 } 658 }
806 return true; 659 return true;
807 } 660 }
808 661
809 bool NativeBackendKWallet::SetLoginsList( 662 bool NativeBackendKWallet::SetLoginsList(
810 const std::vector<autofill::PasswordForm*>& forms, 663 const std::vector<autofill::PasswordForm*>& forms,
811 const std::string& signon_realm, 664 const std::string& signon_realm,
812 int wallet_handle) { 665 int wallet_handle) {
813 if (forms.empty()) { 666 if (forms.empty()) {
814 // No items left? Remove the entry from the wallet.
815 dbus::MethodCall method_call(kKWalletInterface, "removeEntry");
816 dbus::MessageWriter builder(&method_call);
817 builder.AppendInt32(wallet_handle); // handle
818 builder.AppendString(folder_name_); // folder
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;
826 }
827 dbus::MessageReader reader(response.get());
828 int ret = 0; 667 int ret = 0;
829 if (!reader.PopInt32(&ret)) { 668 KWalletDBus::Error error = kwallet_dbus_.RemoveEntry(
830 LOG(ERROR) << "Error reading response from " << kwalletd_name_ 669 wallet_handle, folder_name_, signon_realm, app_name_, &ret);
831 << " (removeEntry): " << response->ToString(); 670 if (error)
832 return false; 671 return false;
833 }
834 if (ret != 0) 672 if (ret != 0)
835 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry"; 673 LOG(ERROR) << "Bad return code " << ret << " from KWallet removeEntry";
836 return ret == 0; 674 return ret == 0;
837 } 675 }
838 676
839 base::Pickle value; 677 base::Pickle value;
840 SerializeValue(forms, &value); 678 SerializeValue(forms, &value);
841 679
842 dbus::MethodCall method_call(kKWalletInterface, "writeEntry");
843 dbus::MessageWriter builder(&method_call);
844 builder.AppendInt32(wallet_handle); // handle
845 builder.AppendString(folder_name_); // folder
846 builder.AppendString(signon_realm); // key
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;
855 }
856 dbus::MessageReader reader(response.get());
857 int ret = 0; 680 int ret = 0;
858 if (!reader.PopInt32(&ret)) { 681 KWalletDBus::Error error = kwallet_dbus_.WriteEntry(
859 LOG(ERROR) << "Error reading response from " << kwalletd_name_ 682 wallet_handle, folder_name_, signon_realm, app_name_,
860 << " (writeEntry): " << response->ToString(); 683 static_cast<const uint8_t*>(value.data()), value.size(), &ret);
684 if (error)
861 return false; 685 return false;
862 }
863 if (ret != 0) 686 if (ret != 0)
864 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry"; 687 LOG(ERROR) << "Bad return code " << ret << " from KWallet writeEntry";
865 return ret == 0; 688 return ret == 0;
866 } 689 }
867 690
868 bool NativeBackendKWallet::RemoveLoginsBetween( 691 bool NativeBackendKWallet::RemoveLoginsBetween(
869 base::Time delete_begin, 692 base::Time delete_begin,
870 base::Time delete_end, 693 base::Time delete_end,
871 TimestampToCompare date_to_compare, 694 TimestampToCompare date_to_compare,
872 password_manager::PasswordStoreChangeList* changes) { 695 password_manager::PasswordStoreChangeList* changes) {
873 DCHECK(changes); 696 DCHECK(changes);
874 changes->clear(); 697 changes->clear();
875 int wallet_handle = WalletHandle(); 698 int wallet_handle = WalletHandle();
876 if (wallet_handle == kInvalidKWalletHandle) 699 if (wallet_handle == kInvalidKWalletHandle)
877 return false; 700 return false;
878 701
879 // We could probably also use readEntryList here. 702 // We could probably also use readEntryList here.
880 std::vector<std::string> realm_list; 703 std::vector<std::string> realm_list;
881 { 704 KWalletDBus::Error error = kwallet_dbus_.EntryList(
882 dbus::MethodCall method_call(kKWalletInterface, "entryList"); 705 wallet_handle, folder_name_, app_name_, &realm_list);
883 dbus::MessageWriter builder(&method_call); 706 if (error)
884 builder.AppendInt32(wallet_handle); // handle 707 return false;
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;
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 }
910 708
911 bool ok = true; 709 bool ok = true;
912 for (size_t i = 0; i < realm_list.size(); ++i) { 710 for (size_t i = 0; i < realm_list.size(); ++i) {
913 const std::string& signon_realm = realm_list[i]; 711 const std::string& signon_realm = realm_list[i];
914 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); 712
915 dbus::MessageWriter builder(&method_call); 713 std::vector<uint8_t> bytes;
916 builder.AppendInt32(wallet_handle); // handle 714 KWalletDBus::Error error = kwallet_dbus_.ReadEntry(
917 builder.AppendString(folder_name_); // folder 715 wallet_handle, folder_name_, signon_realm, app_name_, &bytes);
918 builder.AppendString(signon_realm); // key 716 if (error)
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; 717 continue;
925 } 718 if (bytes.size() == 0 ||
926 dbus::MessageReader reader(response.get()); 719 !CheckSerializedValue(bytes.data(), bytes.size(), signon_realm))
927 const uint8_t* bytes = nullptr;
928 size_t length = 0;
929 if (!reader.PopArrayOfBytes(&bytes, &length)) {
930 LOG(ERROR) << "Error reading response from " << kwalletd_name_
931 << " (readEntry): " << response->ToString();
932 continue;
933 }
934 if (!bytes || !CheckSerializedValue(bytes, length, signon_realm))
935 continue; 720 continue;
936 721
937 // Can't we all just agree on whether bytes are signed or not? Please? 722 // Can't we all just agree on whether bytes are signed or not? Please?
938 base::Pickle pickle(reinterpret_cast<const char*>(bytes), length); 723 base::Pickle pickle(reinterpret_cast<const char*>(bytes.data()),
724 bytes.size());
939 ScopedVector<autofill::PasswordForm> all_forms = 725 ScopedVector<autofill::PasswordForm> all_forms =
940 DeserializeValue(signon_realm, pickle); 726 DeserializeValue(signon_realm, pickle);
941 727
942 ScopedVector<autofill::PasswordForm> kept_forms; 728 ScopedVector<autofill::PasswordForm> kept_forms;
943 kept_forms.reserve(all_forms.size()); 729 kept_forms.reserve(all_forms.size());
944 base::Time autofill::PasswordForm::*date_member = 730 base::Time autofill::PasswordForm::*date_member =
945 date_to_compare == CREATION_TIMESTAMP 731 date_to_compare == CREATION_TIMESTAMP
946 ? &autofill::PasswordForm::date_created 732 ? &autofill::PasswordForm::date_created
947 : &autofill::PasswordForm::date_synced; 733 : &autofill::PasswordForm::date_synced;
948 for (auto& saved_form : all_forms) { 734 for (auto& saved_form : all_forms) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 UMALogDeserializationStatus(success); 787 UMALogDeserializationStatus(success);
1002 return forms; 788 return forms;
1003 } 789 }
1004 790
1005 int NativeBackendKWallet::WalletHandle() { 791 int NativeBackendKWallet::WalletHandle() {
1006 DCHECK_CURRENTLY_ON(BrowserThread::DB); 792 DCHECK_CURRENTLY_ON(BrowserThread::DB);
1007 793
1008 // Open the wallet. 794 // Open the wallet.
1009 // TODO(mdm): Are we leaking these handles? Find out. 795 // TODO(mdm): Are we leaking these handles? Find out.
1010 int32_t handle = kInvalidKWalletHandle; 796 int32_t handle = kInvalidKWalletHandle;
1011 { 797 KWalletDBus::Error error =
1012 dbus::MethodCall method_call(kKWalletInterface, "open"); 798 kwallet_dbus_.Open(wallet_name_, app_name_, &handle);
1013 dbus::MessageWriter builder(&method_call); 799 if (error)
1014 builder.AppendString(wallet_name_); // wallet 800 return kInvalidKWalletHandle;
1015 builder.AppendInt64(0); // wid 801 if (handle == kInvalidKWalletHandle) {
1016 builder.AppendString(app_name_); // appid 802 LOG(ERROR) << "Error obtaining KWallet handle";
1017 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( 803 return kInvalidKWalletHandle;
1018 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
1019 if (!response.get()) {
1020 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (open)";
1021 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) {
1030 LOG(ERROR) << "Error obtaining KWallet handle";
1031 return kInvalidKWalletHandle;
1032 }
1033 } 804 }
1034 805
1035 // Check if our folder exists. 806 // Check if our folder exists.
1036 bool has_folder = false; 807 bool has_folder = false;
1037 { 808 error = kwallet_dbus_.HasFolder(handle, folder_name_, app_name_, &has_folder);
1038 dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); 809 if (error)
1039 dbus::MessageWriter builder(&method_call); 810 return kInvalidKWalletHandle;
1040 builder.AppendInt32(handle); // handle
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;
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 }
1056 811
1057 // Create it if it didn't. 812 // Create it if it didn't.
1058 if (!has_folder) { 813 if (!has_folder) {
1059 dbus::MethodCall method_call(kKWalletInterface, "createFolder"); 814 bool success = false;
1060 dbus::MessageWriter builder(&method_call); 815 error =
1061 builder.AppendInt32(handle); // handle 816 kwallet_dbus_.CreateFolder(handle, folder_name_, app_name_, &success);
1062 builder.AppendString(folder_name_); // folder 817 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; 818 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) { 819 if (!success) {
1079 LOG(ERROR) << "Error creating KWallet folder"; 820 LOG(ERROR) << "Error creating KWallet folder";
1080 return kInvalidKWalletHandle; 821 return kInvalidKWalletHandle;
1081 } 822 }
1082 } 823 }
1083 824
1084 return handle; 825 return handle;
1085 } 826 }
1086 827
1087 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const { 828 std::string NativeBackendKWallet::GetProfileSpecificFolderName() const {
1088 // Originally, the folder name was always just "Chrome Form Data". 829 // Originally, the folder name was always just "Chrome Form Data".
1089 // Now we use it to distinguish passwords for different profiles. 830 // Now we use it to distinguish passwords for different profiles.
1090 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_); 831 return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_);
1091 } 832 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698