| 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..ed147586513ba854f9d766ac71e01ea7dd2d7ba0
|
| --- /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 = -1;
|
| + 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;
|
| +}
|
|
|