| Index: chrome/browser/password_manager/kwallet_dbus.cc | 
| diff --git a/chrome/browser/password_manager/kwallet_dbus.cc b/chrome/browser/password_manager/kwallet_dbus.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..7a8022d8cea80fa4f63d346cb7545cf53f11110b | 
| --- /dev/null | 
| +++ b/chrome/browser/password_manager/kwallet_dbus.cc | 
| @@ -0,0 +1,344 @@ | 
| +// Copyright 2016 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include <chrome/browser/password_manager/kwallet_dbus.h> | 
| + | 
| +#include <algorithm> | 
| +#include <memory> | 
| + | 
| +#include "base/logging.h" | 
| +#include "dbus/bus.h" | 
| +#include "dbus/message.h" | 
| +#include "dbus/object_proxy.h" | 
| + | 
| +namespace { | 
| + | 
| +// DBus service, path, and interface names for klauncher and kwalletd. | 
| +const char kKWalletDName[] = "kwalletd"; | 
| +const char kKWalletD5Name[] = "kwalletd5"; | 
| +const char kKWalletServiceName[] = "org.kde.kwalletd"; | 
| +const char kKWallet5ServiceName[] = "org.kde.kwalletd5"; | 
| +const char kKWalletPath[] = "/modules/kwalletd"; | 
| +const char kKWallet5Path[] = "/modules/kwalletd5"; | 
| +const char kKWalletInterface[] = "org.kde.KWallet"; | 
| +const char kKLauncherServiceName[] = "org.kde.klauncher"; | 
| +const char kKLauncherPath[] = "/KLauncher"; | 
| +const char kKLauncherInterface[] = "org.kde.KLauncher"; | 
| + | 
| +}  // namespace | 
| + | 
| +KWalletDBus::KWalletDBus(base::nix::DesktopEnvironment desktop_env) | 
| +    : session_bus_(nullptr), kwallet_proxy_(nullptr) { | 
| +  if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE5) { | 
| +    dbus_service_name_ = kKWallet5ServiceName; | 
| +    dbus_path_ = kKWallet5Path; | 
| +    kwalletd_name_ = kKWalletD5Name; | 
| +  } else { | 
| +    dbus_service_name_ = kKWalletServiceName; | 
| +    dbus_path_ = kKWalletPath; | 
| +    kwalletd_name_ = kKWalletDName; | 
| +  } | 
| +} | 
| + | 
| +KWalletDBus::~KWalletDBus() = default; | 
| + | 
| +dbus::Bus* KWalletDBus::GetSessionBus() { | 
| +  return session_bus_.get(); | 
| +} | 
| + | 
| +void KWalletDBus::SetSessionBus(scoped_refptr<dbus::Bus> session_bus) { | 
| +  session_bus_ = session_bus; | 
| +  kwallet_proxy_ = session_bus_->GetObjectProxy(dbus_service_name_, | 
| +                                                dbus::ObjectPath(dbus_path_)); | 
| +} | 
| + | 
| +bool KWalletDBus::StartKWalletd() { | 
| +  dbus::ObjectProxy* klauncher = session_bus_->GetObjectProxy( | 
| +      kKLauncherServiceName, dbus::ObjectPath(kKLauncherPath)); | 
| + | 
| +  dbus::MethodCall method_call(kKLauncherInterface, | 
| +                               "start_service_by_desktop_name"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  std::vector<std::string> empty; | 
| +  builder.AppendString(kwalletd_name_);  // serviceName | 
| +  builder.AppendArrayOfStrings(empty);   // urls | 
| +  builder.AppendArrayOfStrings(empty);   // envs | 
| +  builder.AppendString(std::string());   // startup_id | 
| +  builder.AppendBool(false);             // blind | 
| +  std::unique_ptr<dbus::Response> response(klauncher->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting klauncher to start " << kwalletd_name_; | 
| +    return false; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  int32_t ret = -1; | 
| +  std::string dbus_name; | 
| +  std::string error; | 
| +  int32_t pid = -1; | 
| +  if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) || | 
| +      !reader.PopString(&error) || !reader.PopInt32(&pid)) { | 
| +    LOG(ERROR) << "Error reading response from klauncher to start " | 
| +               << kwalletd_name_ << ": " << response->ToString(); | 
| +    return false; | 
| +  } | 
| +  if (!error.empty() || ret) { | 
| +    LOG(ERROR) << "Error launching " << kwalletd_name_ << ": error '" << error | 
| +               << "' (code " << ret << ")"; | 
| +    return false; | 
| +  } | 
| + | 
| +  return true; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::IsEnabled(bool* enabled) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (isEnabled)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopBool(enabled)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (isEnabled): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  // Not enabled? Don't use KWallet. But also don't warn here. | 
| +  if (!enabled) { | 
| +    VLOG(1) << kwalletd_name_ << " reports that KWallet is not enabled."; | 
| +  } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::NetworkWallet(std::string* wallet_name) { | 
| +  // Get the wallet name. | 
| +  dbus::MethodCall method_call(kKWalletInterface, "networkWallet"); | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (networkWallet)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopString(wallet_name)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (networkWallet): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| + | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::Open(const std::string& wallet_name, | 
| +                                     const std::string& app_name, | 
| +                                     int* handle_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "open"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendString(wallet_name);  // wallet | 
| +  builder.AppendInt64(0);             // wid | 
| +  builder.AppendString(app_name);     // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (open)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopInt32(handle_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (open): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::HasEntry(const int wallet_handle, | 
| +                                         const std::string& folder_name, | 
| +                                         const std::string& signon_realm, | 
| +                                         const std::string& app_name, | 
| +                                         bool* has_entry) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(wallet_handle);  // handle | 
| +  builder.AppendString(folder_name);   // folder | 
| +  builder.AppendString(signon_realm);  // key | 
| +  builder.AppendString(app_name);      // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasEntry)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopBool(has_entry)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (hasEntry): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::ReadEntry(const int wallet_handle, | 
| +                                          const std::string& folder_name, | 
| +                                          const std::string& signon_realm, | 
| +                                          const std::string& app_name, | 
| +                                          std::vector<uint8_t>* bytes_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "readEntry"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(wallet_handle);  // handle | 
| +  builder.AppendString(folder_name);   // folder | 
| +  builder.AppendString(signon_realm);  // key | 
| +  builder.AppendString(app_name);      // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readEntry)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  size_t length = 0; | 
| +  const uint8_t* bytes_temp = nullptr; | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopArrayOfBytes(&bytes_temp, &length)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (readEntry): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  if (bytes_temp) { | 
| +    bytes_ptr->assign(bytes_temp, bytes_temp + length); | 
| +  } else { | 
| +    bytes_ptr->clear(); | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::EntryList( | 
| +    const int wallet_handle, | 
| +    const std::string& folder_name, | 
| +    const std::string& app_name, | 
| +    std::vector<std::string>* entry_list_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "entryList"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(wallet_handle);  // handle | 
| +  builder.AppendString(folder_name);   // folder | 
| +  builder.AppendString(app_name);      // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (entryList)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopArrayOfStrings(entry_list_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << "(entryList): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::RemoveEntry(const int wallet_handle, | 
| +                                            const std::string& folder_name, | 
| +                                            const std::string& signon_realm, | 
| +                                            const std::string& app_name, | 
| +                                            int* return_code_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "removeEntry"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(wallet_handle);  // handle | 
| +  builder.AppendString(folder_name);   // folder | 
| +  builder.AppendString(signon_realm);  // key | 
| +  builder.AppendString(app_name);      // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (removeEntry)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopInt32(return_code_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (removeEntry): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::WriteEntry(const int wallet_handle, | 
| +                                           const std::string& folder_name, | 
| +                                           const std::string& signon_realm, | 
| +                                           const std::string& app_name, | 
| +                                           const uint8_t* data, | 
| +                                           const size_t length, | 
| +                                           int* return_code_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(wallet_handle);        // handle | 
| +  builder.AppendString(folder_name);         // folder | 
| +  builder.AppendString(signon_realm);        // key | 
| +  builder.AppendArrayOfBytes(data, length);  // value | 
| +  builder.AppendString(app_name);            // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (writeEntry)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopInt32(return_code_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (writeEntry): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::HasFolder(const int handle, | 
| +                                          const std::string& folder_name, | 
| +                                          const std::string& app_name, | 
| +                                          bool* has_folder_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(handle);        // handle | 
| +  builder.AppendString(folder_name);  // folder | 
| +  builder.AppendString(app_name);     // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasFolder)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopBool(has_folder_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (hasFolder): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
| + | 
| +KWalletDBus::Error KWalletDBus::CreateFolder(const int handle, | 
| +                                             const std::string& folder_name, | 
| +                                             const std::string& app_name, | 
| +                                             bool* success_ptr) { | 
| +  dbus::MethodCall method_call(kKWalletInterface, "createFolder"); | 
| +  dbus::MessageWriter builder(&method_call); | 
| +  builder.AppendInt32(handle);        // handle | 
| +  builder.AppendString(folder_name);  // folder | 
| +  builder.AppendString(app_name);     // appid | 
| +  std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( | 
| +      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | 
| +  if (!response.get()) { | 
| +    LOG(ERROR) << "Error contacting << " << kwalletd_name_ << " (createFolder)"; | 
| +    return CANNOT_CONTACT; | 
| +  } | 
| +  dbus::MessageReader reader(response.get()); | 
| +  if (!reader.PopBool(success_ptr)) { | 
| +    LOG(ERROR) << "Error reading response from " << kwalletd_name_ | 
| +               << " (createFolder): " << response->ToString(); | 
| +    return CANNOT_READ; | 
| +  } | 
| +  return SUCCESS; | 
| +} | 
|  |