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 |