// Copyright 2018 The Chromium OS 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 "vm_tools/garcon/package_kit_proxy.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/threading/thread_task_runner_handle.h>
#include <dbus/message.h>
#include <dbus/property.h>
#include <dbus/scoped_dbus_error.h>
#include <vm_protos/proto_bindings/container_guest.grpc.pb.h>

namespace vm_tools {
namespace garcon {

namespace {

// Package ID suffix we require in order to perform an automatic upgrade, this
// corresponds to the repository the package comes from.
constexpr char kManagedPackageIdSuffix[] = ";google-stable-main";

// Constants for the PackageKit D-Bus service.
// See:
// https://github.com/hughsie/PackageKit/blob/master/src/org.freedesktop.PackageKit.Transaction.xml
constexpr char kPackageKitInterface[] = "org.freedesktop.PackageKit";
constexpr char kPackageKitServicePath[] = "/org/freedesktop/PackageKit";
constexpr char kPackageKitServiceName[] = "org.freedesktop.PackageKit";
constexpr char kPackageKitTransactionInterface[] =
    "org.freedesktop.PackageKit.Transaction";
constexpr char kSetHintsMethod[] = "SetHints";
constexpr char kCreateTransactionMethod[] = "CreateTransaction";
constexpr char kGetDetailsMethod[] = "GetDetails";
constexpr char kGetDetailsLocalMethod[] = "GetDetailsLocal";
constexpr char kSearchFilesMethod[] = "SearchFiles";
constexpr char kInstallFilesMethod[] = "InstallFiles";
constexpr char kInstallPackagesMethod[] = "InstallPackages";
constexpr char kRemovePackagesMethod[] = "RemovePackages";
constexpr char kRefreshCacheMethod[] = "RefreshCache";
constexpr char kResolveMethod[] = "Resolve";
constexpr char kGetUpdatesMethod[] = "GetUpdates";
constexpr char kUpdatePackagesMethod[] = "UpdatePackages";
constexpr char kErrorCodeSignal[] = "ErrorCode";
constexpr char kFinishedSignal[] = "Finished";
constexpr char kDetailsSignal[] = "Details";
constexpr char kPackageSignal[] = "Package";

// Key names for the Details signal from PackageKit.
constexpr char kDetailsKeyPackageId[] = "package-id";
constexpr char kDetailsKeyLicense[] = "license";
constexpr char kDetailsKeyDescription[] = "description";
constexpr char kDetailsKeyUrl[] = "url";
constexpr char kDetailsKeySize[] = "size";
constexpr char kDetailsKeySummary[] = "summary";

// See:
// https://www.freedesktop.org/software/PackageKit/gtk-doc/PackageKit-Enumerations.html#PkExitEnum
constexpr uint32_t kPackageKitExitCodeSuccess = 1;
// See:
// https://www.freedesktop.org/software/PackageKit/gtk-doc/PackageKit-Enumerations.html#PkStatusEnum
constexpr uint32_t kPackageKitStatusRemoving = 6;
constexpr uint32_t kPackageKitStatusDownload = 8;
constexpr uint32_t kPackageKitStatusInstall = 9;
// See:
// https://www.freedesktop.org/software/PackageKit/gtk-doc/PackageKit-Enumerations.html#PkFilterEnum
constexpr uint32_t kPackageKitFilterNone = 1;
constexpr uint32_t kPackageKitFilterInstalled = 2;
// See:
// https://www.freedesktop.org/software/PackageKit/gtk-doc/PackageKit-Enumerations.html#PkInfoEnum
constexpr uint32_t kPackageKitInfoSecurity = 8;
constexpr uint32_t kPackageKitInfoBlocked = 9;
// See:
// https://www.freedesktop.org/software/PackageKit/gtk-doc/PackageKit-Enumerations.html#PkTransactionFlagEnum
constexpr uint32_t kPackageKitTransactionFlagEnumNone = 0;

// Timeout for when we are querying for package information.
constexpr int kGetLinuxPackageInfoTimeoutSeconds = 60;
constexpr base::TimeDelta kGetLinuxPackageInfoTimeout =
    base::TimeDelta::FromSeconds(kGetLinuxPackageInfoTimeoutSeconds);

// Delay after startup for doing a repository cache refresh.
constexpr base::TimeDelta kRefreshCacheStartupDelay =
    base::TimeDelta::FromMinutes(5);

// Periodic delay between repository cache refreshes after we do the initial one
// after startup.
constexpr base::TimeDelta kRefreshCachePeriod = base::TimeDelta::FromDays(1);

// Ridiculously large size for a config file.
constexpr size_t kMaxConfigFileSize = 10 * 1024;  // 10 KB
// Constants for the configuration directory/files.
constexpr char kXdgConfigHomeEnvVar[] = "XDG_CONFIG_HOME";
constexpr char kDefaultConfigDir[] = ".config";
constexpr char kConfigFilename[] = "cros-garcon.conf";
constexpr char kDisableAutoCrosUpdatesSetting[] =
    "DisableAutomaticCrosPackageUpdates";
constexpr char kDisableAutoSecurityUpdatesSetting[] =
    "DisableAutomaticSecurityUpdates";

// Bitmask values for all the signals from PackageKit
constexpr uint32_t kErrorCodeSignalMask = 1 << 0;
constexpr uint32_t kFinishedSignalMask = 1 << 1;
constexpr uint32_t kPackageSignalMask = 1 << 2;
constexpr uint32_t kDetailsSignalMask = 1 << 3;
constexpr uint32_t kPropertiesSignalMask = 1 << 4;
constexpr uint32_t kValidSignalMask =
    kErrorCodeSignalMask | kFinishedSignalMask | kPackageSignalMask |
    kDetailsSignalMask | kPropertiesSignalMask;

// Parses the configuration file and returns the results through the parameters.
void CheckDisabledUpdates(bool* disable_cros_updates_out,
                          bool* disable_security_updates_out) {
  DCHECK(disable_cros_updates_out);
  DCHECK(disable_security_updates_out);
  *disable_cros_updates_out = false;
  *disable_security_updates_out = false;
  base::FilePath config_dir;
  const char* xdg_config_dir = getenv(kXdgConfigHomeEnvVar);
  if (!xdg_config_dir || strlen(xdg_config_dir) == 0) {
    config_dir = base::GetHomeDir().Append(kDefaultConfigDir);
  } else {
    config_dir = base::FilePath(xdg_config_dir);
  }
  base::FilePath config_file = config_dir.Append(kConfigFilename);
  // First read in the file as a string.
  std::string config_contents;
  if (!ReadFileToStringWithMaxSize(config_file, &config_contents,
                                   kMaxConfigFileSize)) {
    LOG(ERROR) << "Failed reading in config file: " << config_file.value();
    return;
  }
  base::StringPairs config_pairs;
  base::SplitStringIntoKeyValuePairs(config_contents, '=', '\n', &config_pairs);
  for (auto entry : config_pairs) {
    if (entry.first == kDisableAutoCrosUpdatesSetting) {
      *disable_cros_updates_out = (entry.second == "true");
    } else if (entry.first == kDisableAutoSecurityUpdatesSetting) {
      *disable_security_updates_out = (entry.second == "true");
    }
  }
}

struct PackageKitTransactionProperties : public dbus::PropertySet {
  // These are the only 2 properties we care about.
  dbus::Property<uint32_t> status;
  dbus::Property<uint32_t> percentage;
  PackageKitTransactionProperties(dbus::ObjectProxy* object_proxy,
                                  const PropertyChangedCallback callback)
      : dbus::PropertySet(
            object_proxy, kPackageKitTransactionInterface, callback) {
    RegisterProperty("Status", &status);
    RegisterProperty("Percentage", &percentage);
  }
};

// Base class for the helpers for interacting with PackageKit. This will handle
// all the odd D-Bus failures as well as PackageKit death. This object manages
// its own lifecycle, so it should always be created in a leaky fashion, but
// StartTransaction must ALWAYS be invoked after object creation to ensure
// proper cleanup.
class PackageKitTransaction : PackageKitProxy::PackageKitDeathObserver {
 public:
  explicit PackageKitTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      uint32_t signal_mask)
      : bus_(bus),
        packagekit_proxy_(packagekit_proxy),
        packagekit_service_proxy_(packagekit_service_proxy),
        signal_mask_(signal_mask) {
    DCHECK_EQ(signal_mask, signal_mask & kValidSignalMask);
    packagekit_proxy_->AddPackageKitDeathObserver(this);
  }
  virtual ~PackageKitTransaction() {
    if (transaction_path_.IsValid()) {
      bus_->RemoveObjectProxy(kPackageKitServiceName, transaction_path_,
                              base::DoNothing());
    }
    packagekit_proxy_->RemovePackageKitDeathObserver(this);
  }

  // This MUST be invoked after object construction in order to ensure proper
  // cleanup. Even if this fails, it will take care of its own destruction.
  void StartTransaction() {
    // Create a transaction with PackageKit for performing the operation.
    dbus::MethodCall method_call(kPackageKitInterface,
                                 kCreateTransactionMethod);
    dbus::MessageWriter writer(&method_call);
    std::unique_ptr<dbus::Response> dbus_response =
        packagekit_service_proxy_->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    if (!dbus_response) {
      GeneralErrorInternal("Failure calling CreateTransaction");
      return;
    }
    // CreateTransaction returns the object path for the transaction session we
    // have created.
    dbus::MessageReader reader(dbus_response.get());
    if (!reader.PopObjectPath(&transaction_path_)) {
      GeneralErrorInternal(
          "Failure reading object path from transaction result");
      return;
    }
    transaction_proxy_ =
        bus_->GetObjectProxy(kPackageKitServiceName, transaction_path_);
    if (!transaction_proxy_) {
      GeneralErrorInternal("Failed to get proxy for transaction");
      return;
    }

    // Set the hint that we don't support interactivity. I haven't seen a case
    // of this yet, but it seems like a good idea to set it if it does occur.
    // Set locale with UTF-8 to support unicode in control files.  This is
    // what 'pkcon get-details-local <file>' does.
    dbus::MethodCall sethints_call(kPackageKitTransactionInterface,
                                   kSetHintsMethod);
    dbus::MessageWriter sethints_writer(&sethints_call);
    sethints_writer.AppendArrayOfStrings(
        {"locale=en_US.UTF-8", "interactive=false"});
    dbus_response = transaction_proxy_->CallMethodAndBlockWithErrorDetails(
        &sethints_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    if (!dbus_response) {
      // Don't propagate a failure, this was just a hint.
      LOG(WARNING) << "Failure calling SetHints - " << dbus_error_.name()
                   << ": " << dbus_error_.message();
    }

    // Hook up all the necessary signals to PackageKit for monitoring the
    // transaction. After these are all hooked up, we will invoke the method
    // so the subclass can initiate the actual request.

    // The properties Signal is special, there exists a helper class for that
    // where we don't manage hooking up the signals ourself.
    if (signal_mask_ & kPropertiesSignalMask) {
      // Remove the bit from the mask to indicate we processed it already.
      signal_mask_ = signal_mask_ & ~kPropertiesSignalMask;
      transaction_properties_ =
          std::make_unique<PackageKitTransactionProperties>(
              transaction_proxy_,
              base::Bind(&PackageKitTransaction::OnPackageKitPropertyChanged,
                         base::Unretained(this)));
      transaction_properties_->ConnectSignals();
      transaction_properties_->GetAll();
    }

    if (signal_mask_ == 0) {
      // No signals to hookup, just go right into the request.
      if (!ExecuteRequest(transaction_proxy_)) {
        GeneralErrorInternal(
            "Failure executing the request in the transaction");
        return;
      }
    }
    ConnectNextSignal();
  }

  // Override to execute the actual request within the transaction such as
  // GetUpdates, RefreshCache, etc. Returns true if the call succeeded, false
  // otherwise. If this method fails, then GeneralError will be invoked.
  virtual bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) = 0;

  // Invoked when something went wrong in the D-Bus communication, the object
  // will self-destruct after this call.
  virtual void GeneralError(const std::string& details) {
    LOG(ERROR) << details;
  }

  // Invoked when the corresponding signals are received and decoded. If a
  // Finished signal occurs, then no other calls will be made after that and
  // this object will self-destruct.
  virtual void ErrorReceived(uint32_t error_code, const std::string& details) {
    LOG(ERROR) << "Error occured with PackageKit transaction with code: "
               << error_code << " and details: " << details;
  }
  virtual void FinishedReceived(uint32_t exit_code) {
    if (exit_code == kPackageKitExitCodeSuccess) {
      LOG(INFO) << "PackageKit transaction completed successfully";
    } else {
      LOG(ERROR) << "PackageKit transaction failed with code: " << exit_code;
    }
  }
  virtual void PackageReceived(uint32_t code,
                               const std::string& package_id,
                               const std::string& summary) {}
  virtual void DetailsReceived(const std::string& package_id,
                               const std::string& license,
                               const std::string& description,
                               const std::string& project_url,
                               uint64_t size,
                               const std::string& summary) {}
  virtual void PropertyChangeReceived(
      const std::string& name, PackageKitTransactionProperties* properties) {}

 private:
  // PackageKitDeathObserver overrides:
  void OnPackageKitDeath() {
    GeneralErrorInternal("PackageKit D-Bus service died, abort operation");
  }

  void GeneralErrorInternal(const std::string& details) {
    if (dbus_error_.is_set()) {
      GeneralError(details + "(error=" + dbus_error_.name() + ": " +
                   dbus_error_.message() + ")");
    } else {
      GeneralError(details);
    }
    // An unknown error has occurred, we should self-destruct now.
    delete this;
  }

  void ConnectNextSignal() {
    std::string signal_name;
    dbus::ObjectProxy::SignalCallback signal_callback;
    if (signal_mask_ & kErrorCodeSignalMask) {
      signal_mask_ = signal_mask_ & ~kErrorCodeSignalMask;
      signal_name.assign(kErrorCodeSignal);
      signal_callback = base::Bind(&PackageKitTransaction::OnErrorSignal,
                                   base::Unretained(this));
    } else if (signal_mask_ & kFinishedSignalMask) {
      signal_mask_ = signal_mask_ & ~kFinishedSignalMask;
      signal_name.assign(kFinishedSignal);
      signal_callback = base::Bind(&PackageKitTransaction::OnFinishedSignal,
                                   base::Unretained(this));
    } else if (signal_mask_ & kPackageSignalMask) {
      signal_mask_ = signal_mask_ & ~kPackageSignalMask;
      signal_name.assign(kPackageSignal);
      signal_callback = base::Bind(&PackageKitTransaction::OnPackageSignal,
                                   base::Unretained(this));
    } else if (signal_mask_ & kDetailsSignalMask) {
      signal_mask_ = signal_mask_ & ~kDetailsSignalMask;
      signal_name.assign(kDetailsSignal);
      signal_callback = base::Bind(&PackageKitTransaction::OnDetailsSignal,
                                   base::Unretained(this));
    } else {
      NOTREACHED();
    }

    transaction_proxy_->ConnectToSignal(
        kPackageKitTransactionInterface, signal_name, signal_callback,
        base::Bind(&PackageKitTransaction::OnSignalConnected,
                   base::Unretained(this)));
  }

  void OnSignalConnected(const std::string& interface_name,
                         const std::string& signal_name,
                         bool is_connected) {
    if (!is_connected) {
      // Any failures in signal hookups mean we should abort.
      GeneralErrorInternal("Failed to hookup " + signal_name + " signal");
      return;
    }
    if (signal_mask_ == 0) {
      // Done hooking up our signals, let the subclass invoke the request.
      if (!ExecuteRequest(transaction_proxy_)) {
        GeneralErrorInternal(
            "Failure executing the request in the transaction");
      }
    } else {
      ConnectNextSignal();
    }
  }

  void OnErrorSignal(dbus::Signal* signal) {
    CHECK(signal);
    dbus::MessageReader reader(signal);
    uint32_t code;
    std::string details;
    if (!reader.PopUint32(&code) || !reader.PopString(&details)) {
      GeneralErrorInternal("Failure parsing PackageKit error signal");
      return;
    }
    ErrorReceived(code, details);
  }

  void OnFinishedSignal(dbus::Signal* signal) {
    CHECK(signal);
    dbus::MessageReader reader(signal);
    uint32_t exit_code;
    if (!reader.PopUint32(&exit_code)) {
      GeneralErrorInternal("Failure parsing PackageKit finished signal");
      return;
    }
    FinishedReceived(exit_code);
    // We are done, we should self-destruct.
    delete this;
  }

  void OnPackageSignal(dbus::Signal* signal) {
    CHECK(signal);
    dbus::MessageReader reader(signal);
    uint32_t code;
    std::string package_id;
    std::string summary;
    if (!reader.PopUint32(&code) || !reader.PopString(&package_id) ||
        !reader.PopString(&summary)) {
      GeneralErrorInternal("Failure parsing PackageKit Package signal");
      return;
    }
    PackageReceived(code, package_id, summary);
  }

  void OnDetailsSignal(dbus::Signal* signal) {
    CHECK(signal);
    dbus::MessageReader reader(signal);
    // Read all of the details on the package. This is an array of dict entries
    // with string keys and variant values.
    dbus::MessageReader array_reader(nullptr);
    if (!reader.PopArray(&array_reader)) {
      GeneralErrorInternal("Failure parsing PackageKit Details signal");
      return;
    }
    std::string package_id;
    std::string license;
    std::string description;
    std::string project_url;
    uint64_t size = 0;
    std::string summary;
    while (array_reader.HasMoreData()) {
      dbus::MessageReader dict_entry_reader(nullptr);
      if (array_reader.PopDictEntry(&dict_entry_reader)) {
        dbus::MessageReader value_reader(nullptr);
        std::string name;
        if (!dict_entry_reader.PopString(&name) ||
            !dict_entry_reader.PopVariant(&value_reader)) {
          LOG(WARNING) << "Error popping dictionary entry from D-Bus message";
          continue;
        }
        if (name == kDetailsKeyPackageId) {
          if (!value_reader.PopString(&package_id)) {
            LOG(WARNING) << "Error popping package_id from details";
          }
        } else if (name == kDetailsKeyLicense) {
          if (!value_reader.PopString(&license)) {
            LOG(WARNING) << "Error popping license from details";
          }
        } else if (name == kDetailsKeyDescription) {
          if (!value_reader.PopString(&description)) {
            LOG(WARNING) << "Error popping description from details";
          }
        } else if (name == kDetailsKeyUrl) {
          if (!value_reader.PopString(&project_url)) {
            LOG(WARNING) << "Error popping url from details";
          }
        } else if (name == kDetailsKeySize) {
          if (!value_reader.PopUint64(&size)) {
            LOG(WARNING) << "Error popping size from details";
          }
        } else if (name == kDetailsKeySummary) {
          if (!value_reader.PopString(&summary)) {
            LOG(WARNING) << "Error popping summary from details";
          }
        }
      }
    }
    DetailsReceived(package_id, license, description, project_url, size,
                    summary);
  }

  void OnPackageKitPropertyChanged(const std::string& name) {
    PropertyChangeReceived(name, transaction_properties_.get());
  }

 protected:
  scoped_refptr<dbus::Bus> bus_;
  dbus::ScopedDBusError dbus_error_;
  PackageKitProxy* packagekit_proxy_;            // Not owned.
  scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy_;  // Not owned.

 private:
  uint32_t signal_mask_;

  dbus::ObjectProxy* transaction_proxy_;  // Owned by bus_.
  dbus::ObjectPath transaction_path_;
  std::unique_ptr<PackageKitTransactionProperties> transaction_properties_;

  DISALLOW_COPY_AND_ASSIGN(PackageKitTransaction);
};

// Sublcass for handling GetDetailsLocal and GetDetails transactions. If
// |data->package_id| is empty, uses the |data->file_path| and GetDetailsLocal,
// else uses |data->package_id| and GetDetails.
class GetDetailsTransaction : public PackageKitTransaction {
 public:
  GetDetailsTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      std::shared_ptr<PackageKitProxy::PackageInfoTransactionData> data)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kDetailsSignalMask),
        data_(data) {
    data_->result = false;
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Problem with GetDetailsLocal transaction: " << details;
    // Check if we've already indicated we are done.
    if (data_->event.IsSignaled())
      return;
    data_->error.assign(details);
    data_->event.Signal();
  }

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    std::string method_name;
    std::string value;
    if (data_->package_id.empty()) {
      method_name = kGetDetailsLocalMethod;
      value = data_->file_path.value();
    } else {
      method_name = kGetDetailsMethod;
      value = data_->package_id;
    }

    dbus::MethodCall method_call(kPackageKitTransactionInterface, method_name);
    dbus::MessageWriter writer(&method_call);
    writer.AppendArrayOfStrings({value});

    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure querying Linux package of: " << details;
    // Check if we've already indicated we are done.
    if (data_->event.IsSignaled())
      return;
    // We will still get a Finished signal where we finalize everything.
    data_->error.assign(details);
  }

  void FinishedReceived(uint32_t exit_code) override {
    LOG(INFO) << "Finished with query for Linux package info";
    // Check if we've already indicated we are done.
    if (data_->event.IsSignaled())
      return;
    // If this is a failure, the error message should have already been set via
    // that callback.
    data_->result = kPackageKitExitCodeSuccess == exit_code;
    data_->event.Signal();
  }

  void DetailsReceived(const std::string& package_id,
                       const std::string& license,
                       const std::string& description,
                       const std::string& project_url,
                       uint64_t size,
                       const std::string& summary) override {
    // Check if we've already indicated we are done.
    if (data_->event.IsSignaled())
      return;
    data_->pkg_info->package_id.assign(package_id);
    data_->pkg_info->license.assign(license);
    data_->pkg_info->description.assign(description);
    data_->pkg_info->project_url.assign(project_url);
    data_->pkg_info->size = size;
    data_->pkg_info->summary.assign(summary);
  }

 private:
  std::shared_ptr<PackageKitProxy::PackageInfoTransactionData> data_;
};

// Subclass for handling SearchFiles transaction. Different from GetDetailsLocal
// in that we do a callback on the current thread instead of saving the
// information to a structure in order to return it on a different thread.
class SearchFilesTransaction : public PackageKitTransaction {
 public:
  SearchFilesTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      const base::FilePath& file_path,
      PackageKitProxy::PackageSearchCallback callback)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPackageSignalMask),
        file_path_(file_path),
        callback_(std::move(callback)),
        callback_called_(false) {}

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kSearchFilesMethod);
    dbus::MessageWriter writer(&method_call);
    // As explained in the comments for
    // PackageKitProxy::SearchLinuxPackagesForFile, we only consider installed
    // packages.
    writer.AppendUint64(kPackageKitFilterInstalled);
    writer.AppendArrayOfStrings({file_path_.value()});
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Problem with SearchFiles transaction for file "
               << file_path_.value() << ": " << details;
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    callback_.Run(false /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), details);
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure searching local Linux Packages by file "
               << file_path_.value() << ": " << details;
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    // We will still get a Finished signal where we finalize everything, but
    // no need to wait for it.
    callback_.Run(false /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), details);
  }

  void PackageReceived(uint32_t code,
                       const std::string& package_id,
                       const std::string& summary) override {
    LOG(INFO) << "Got a package for local file " << file_path_.value();
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    PackageKitProxy::LinuxPackageInfo pkg_info;
    pkg_info.package_id = package_id;
    pkg_info.summary = summary;
    callback_.Run(true /*success*/, true /*pkg_found*/, pkg_info, "");
  }

  void FinishedReceived(uint32_t exit_code) override {
    LOG(INFO) << "Finished with SearchFiles transaction for local file "
              << file_path_.value();
    if (callback_called_)
      return;
    callback_called_ = true;

    // If we got here without calling the callback, PackageKit couldn't find a
    // package corresponding to the file.
    callback_.Run(true /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), "");
  }

 private:
  base::FilePath file_path_;
  PackageKitProxy::PackageSearchCallback callback_;
  bool callback_called_;
};

// Sublcass for handling InstallFiles and InstallPackages. If |package_id|
// is empty, uses |file_path| and InstallFiles transaction, else it uses
// |package_id| and InstallPackages transaction.
class InstallTransaction : public PackageKitTransaction {
 public:
  InstallTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      PackageKitProxy::PackageKitObserver* observer,
      base::FilePath file_path,
      std::string command_uuid,
      std::unique_ptr<PackageKitProxy::BlockingOperationActiveClearer> clearer)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPropertiesSignalMask),
        file_path_(file_path),
        command_uuid_(command_uuid),
        clearer_(std::move(clearer)),
        observer_(observer) {}

  InstallTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      PackageKitProxy::PackageKitObserver* observer,
      std::string package_id,
      std::string command_uuid,
      std::unique_ptr<PackageKitProxy::BlockingOperationActiveClearer> clearer)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPropertiesSignalMask),
        package_id_(package_id),
        command_uuid_(command_uuid),
        clearer_(std::move(clearer)),
        observer_(observer) {}

  void GeneralError(const std::string& details) override {
    if (!observer_)
      return;
    observer_->OnInstallCompletion(command_uuid_, false, details);
    observer_ = nullptr;
  }

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    std::string method_name;
    std::string value;
    if (package_id_.empty()) {
      method_name = kInstallFilesMethod;
      value = file_path_.value();
    } else {
      method_name = kInstallPackagesMethod;
      value = package_id_;
    }
    dbus::MethodCall method_call(kPackageKitTransactionInterface, method_name);
    dbus::MessageWriter writer(&method_call);
    writer.AppendUint64(0);  // Allow installing untrusted files.
    writer.AppendArrayOfStrings({value});

    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure installing Linux package of: " << details;
    if (!observer_)
      return;
    observer_->OnInstallCompletion(command_uuid_, false, details);
    observer_ = nullptr;
  }

  void FinishedReceived(uint32_t exit_code) override {
    LOG(INFO) << "Finished installing Linux package result: " << exit_code;
    if (!observer_)
      return;
    observer_->OnInstallCompletion(
        command_uuid_, kPackageKitExitCodeSuccess == exit_code,
        "Exit Code: " + base::NumberToString(exit_code));
    observer_ = nullptr;
  }

  void PropertyChangeReceived(
      const std::string& name,
      PackageKitTransactionProperties* properties) override {
    if (!observer_)
      return;
    // There's only 2 progress states we actually care about which are logical
    // to report to the user. These are downloading and installing, which
    // correspond to similar experiences in Android and elsewhere. There are
    // various other phases this goes through, but they happen rather quickly
    // and would not be worth informing the user of.
    if (name != properties->percentage.name()) {
      // We only want to see progress percentage changes and then we filter
      // these below based on the current status.
      return;
    }
    vm_tools::container::InstallLinuxPackageProgressInfo::Status status;
    switch (properties->status.value()) {
      case kPackageKitStatusDownload:
        status =
            vm_tools::container::InstallLinuxPackageProgressInfo::DOWNLOADING;
        break;
      case kPackageKitStatusInstall:
        status =
            vm_tools::container::InstallLinuxPackageProgressInfo::INSTALLING;
        break;
      default:
        // Not a status state we care about.
        return;
    }
    int percentage = properties->percentage.value();
    // PackageKit uses 101 for the percent when it doesn't know, treat that as
    // zero because you see this at the beginning of phases.
    if (percentage == 101)
      percentage = 0;
    observer_->OnInstallProgress(command_uuid_, status, percentage);
  }

 private:
  base::FilePath file_path_;
  std::string package_id_;
  std::string command_uuid_;
  // Ensure blocking_operation_active is cleared when this object is deleted.
  std::unique_ptr<PackageKitProxy::BlockingOperationActiveClearer> clearer_;
  PackageKitProxy::PackageKitObserver* observer_;  // Not owned.
};

// Runs a RemovePackages transaction as part of a larger
// UninstallPackageOwningFile chain. The only reason that this is specific to
// UninstallPackageOwningFile is the name of the observer functions called.
// This could be used in other uninstall chains if it had generic callbacks,
// but right now UninstallPackageOwningFile is the only way of uninstalling
// anything, so more complexity would be a YAGNI smell.
class UninstallPackagesTransaction : public PackageKitTransaction {
 public:
  UninstallPackagesTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      const std::string& package_id,
      std::unique_ptr<PackageKitProxy::BlockingOperationActiveClearer> clearer,
      PackageKitProxy::PackageKitObserver* observer)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPropertiesSignalMask),
        package_id_(package_id),
        clearer_(std::move(clearer)),
        observer_(observer) {}

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kRemovePackagesMethod);
    dbus::MessageWriter writer(&method_call);
    // Transaction flags: we are not simulating the transaction.
    writer.AppendUint64(kPackageKitTransactionFlagEnumNone);
    // Package IDs
    writer.AppendArrayOfStrings({package_id_});
    // Boolean: allow_deps. If true, we will remove all dependent packages. If
    // false, we will fail if the package has dependencies. We don't want to
    // surprise the user by removing packages they weren't expected, so we
    // currently hardcode this to false.
    writer.AppendBool(false);
    // Boolean: autoremove. If true, removes packages that were installed
    // together with the to-be-removed package which are no longer depending on.
    // We hardcode this to true; many Chromebooks have limited storage and we
    // don't want to rely on the user knowing they need to run special cleanup
    // commands.
    writer.AppendBool(true);
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "General error uninstalling package: " << details;
    if (!observer_) {
      return;
    }
    observer_->OnUninstallCompletion(false, details);
    observer_ = nullptr;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Error uninstalling package: " << details << " (code "
               << error_code << ")";
    if (!observer_) {
      return;
    }
    observer_->OnUninstallCompletion(false, details);
    observer_ = nullptr;
  }

  void PropertyChangeReceived(
      const std::string& name,
      PackageKitTransactionProperties* properties) override {
    VLOG(3) << "PropertyChangeReceived:" << name
            << ", status: " << properties->status.value()
            << ", %: " << properties->percentage.value();
    // There are several states, but the only one that takes any significant
    // time is the 'Removing' state.
    if (properties->status.value() != kPackageKitStatusRemoving) {
      return;
    }

    if (!observer_) {
      return;
    }

    int percentage = properties->percentage.value();
    // PackageKit uses 101 for the percent when it doesn't know, treat that as
    // zero because you see this at the beginning of phases.
    if (percentage == 101) {
      percentage = 0;
    }

    observer_->OnUninstallProgress(percentage);
  }

  void FinishedReceived(uint32_t exit_code) override {
    if (!observer_) {
      return;
    }
    if (exit_code == kPackageKitExitCodeSuccess) {
      LOG(INFO) << "Uninstall transaction completed successfully";
      observer_->OnUninstallCompletion(true, "");
    } else {
      LOG(ERROR) << "Uninstall transaction failed with code: " << exit_code;
      observer_->OnUninstallCompletion(
          false, "Uninstall transaction failed with code: " +
                     base::NumberToString(exit_code));
    }
    observer_ = nullptr;
  }

 private:
  std::string package_id_;
  // Ensure blocking_operation_active is cleared when this object is deleted.
  std::unique_ptr<PackageKitProxy::BlockingOperationActiveClearer> clearer_;
  PackageKitProxy::PackageKitObserver* observer_;  // Not owned.
};

// Sublcass for handling UpdatePackages transaction.
class UpdatePackagesTransaction : public PackageKitTransaction {
 public:
  UpdatePackagesTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
      std::vector<std::string> package_ids)
      : PackageKitTransaction(bus,
                              packagekit_proxy,
                              packagekit_service_proxy,
                              kErrorCodeSignalMask | kFinishedSignalMask),
        package_ids_(package_ids) {
    LOG(INFO) << "Attempting to upgrade package IDs: "
              << base::JoinString(package_ids, ", ");
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Error occurred with UpdatePackages: " << details;
  }

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kUpdatePackagesMethod);
    dbus::MessageWriter writer(&method_call);
    writer.AppendUint64(0);  // No transaction flag.
    writer.AppendArrayOfStrings(package_ids_);
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure with UpdatePackages of: " << details;
  }

  void FinishedReceived(uint32_t exit_code) override {
    if (exit_code == kPackageKitExitCodeSuccess) {
      LOG(INFO) << "Successfully performed upgrade of managed packages";
    } else {
      // PackageKit will log the specific error itself.
      LOG(ERROR) << "Failure performing upgrade of managed packages, code: "
                 << exit_code;
    }
  }

 private:
  std::vector<std::string> package_ids_;
};

// Sublcass for handling GetUpdates transaction.
class GetUpdatesTransaction : public PackageKitTransaction {
 public:
  GetUpdatesTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPackageSignalMask) {
    CheckDisabledUpdates(&cros_updates_disabled_, &security_updates_disabled_);
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Error occurred with GetUpdates: " << details;
  }

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kGetUpdatesMethod);
    dbus::MessageWriter writer(&method_call);
    // Set the filter to installed packages.
    writer.AppendUint64(kPackageKitFilterInstalled);
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure with GetUpdates of: " << details;
  }

  void PackageReceived(uint32_t code,
                       const std::string& package_id,
                       const std::string& /* summary */) override {
    if (!cros_updates_disabled_ &&
        base::EndsWith(package_id, kManagedPackageIdSuffix,
                       base::CompareCase::SENSITIVE)) {
      if (code == kPackageKitInfoBlocked) {
        LOG(WARNING) << "Managed package is blocked from upgrading: "
                     << package_id;
      } else {
        LOG(INFO) << "Found managed package that is upgradeable, add it to the "
                  << "list: " << package_id;
        package_ids_.emplace_back(package_id);
      }
    } else if (!security_updates_disabled_ && code == kPackageKitInfoSecurity) {
      LOG(INFO) << "Found package with security update, add it to the "
                << "list: " << package_id;
      package_ids_.emplace_back(package_id);
    }
  }

  void FinishedReceived(uint32_t exit_code) override {
    if (exit_code == kPackageKitExitCodeSuccess) {
      LOG(INFO) << "PackageKit GetUpdates transaction has completed with "
                << package_ids_.size() << " available managed updates";
      if (!package_ids_.empty()) {
        // This object is intentionally leaked and will clean itself up when
        // done with all the D-Bus communication.
        UpdatePackagesTransaction* transaction = new UpdatePackagesTransaction(
            bus_, packagekit_proxy_, packagekit_service_proxy_,
            std::move(package_ids_));
        transaction->StartTransaction();
      }
    } else {
      LOG(ERROR) << "Failure performing GetUpdates, code: " << exit_code;
    }
  }

 private:
  std::vector<std::string> package_ids_;
  bool cros_updates_disabled_;
  bool security_updates_disabled_;
};

// Sublcass for handling RefreshCache transaction.
class RefreshCacheTransaction : public PackageKitTransaction {
 public:
  RefreshCacheTransaction(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy)
      : PackageKitTransaction(bus,
                              packagekit_proxy,
                              packagekit_service_proxy,
                              kErrorCodeSignalMask | kFinishedSignalMask) {}

  static void RefreshCacheNow(
      scoped_refptr<dbus::Bus> bus,
      PackageKitProxy* packagekit_proxy,
      scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy) {
    bool disable_cros_updates;
    bool disable_security_updates;
    CheckDisabledUpdates(&disable_cros_updates, &disable_security_updates);
    if (disable_cros_updates && disable_security_updates) {
      // Don't do the update now, but schedule another one for later and we will
      // check the setting again then.
      LOG(INFO) << "Not performing automatic update because they are disabled";
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&RefreshCacheNow, bus, packagekit_proxy,
                     packagekit_service_proxy),
          kRefreshCachePeriod);
      return;
    }

    LOG(INFO) << "Refreshing the remote repository packages";
    // This object is intentionally leaked and will clean itself up when done
    // with all the D-Bus communication.
    RefreshCacheTransaction* transaction = new RefreshCacheTransaction(
        bus, packagekit_proxy, packagekit_service_proxy);
    transaction->StartTransaction();
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Error occurred with RefreshCache: " << details;
    ScheduleNextCacheRefresh();
  }

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kRefreshCacheMethod);
    dbus::MessageWriter writer(&method_call);
    writer.AppendBool(false);  // Don't force cache wipe.
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure with RefreshCache of: " << details;
  }

 private:
  void ScheduleNextCacheRefresh() {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&RefreshCacheNow, bus_, packagekit_proxy_,
                   packagekit_service_proxy_),
        kRefreshCachePeriod);
  }

 public:
  void FinishedReceived(uint32_t exit_code) override {
    if (exit_code == kPackageKitExitCodeSuccess) {
      LOG(INFO) << "Successfully performed refresh of package cache";
      // Now we need to get the list of updatable packages that we control so we
      // can perform upgrades on anything that's available.
      // This object is intentionally leaked and will clean itself up when done
      // with all the D-Bus communication.
      GetUpdatesTransaction* transaction = new GetUpdatesTransaction(
          bus_, packagekit_proxy_, packagekit_service_proxy_);
      transaction->StartTransaction();
    } else {
      LOG(ERROR) << "Failure performing refresh of package cache, code: "
                 << exit_code;
    }
    ScheduleNextCacheRefresh();
  }
};

// Sublcass for handling Resolve transaction.
class ResolveTransaction : public PackageKitTransaction {
 public:
  ResolveTransaction(scoped_refptr<dbus::Bus> bus,
                     PackageKitProxy* packagekit_proxy,
                     scoped_refptr<dbus::ObjectProxy> packagekit_service_proxy,
                     const std::string& package_name,
                     PackageKitProxy::PackageSearchCallback callback)
      : PackageKitTransaction(
            bus,
            packagekit_proxy,
            packagekit_service_proxy,
            kErrorCodeSignalMask | kFinishedSignalMask | kPackageSignalMask),
        package_name_(package_name),
        callback_(std::move(callback)),
        callback_called_(false) {}

  bool ExecuteRequest(dbus::ObjectProxy* transaction_proxy) override {
    dbus::MethodCall method_call(kPackageKitTransactionInterface,
                                 kResolveMethod);
    dbus::MessageWriter writer(&method_call);
    writer.AppendUint64(kPackageKitFilterNone);
    writer.AppendArrayOfStrings({package_name_});
    std::unique_ptr<dbus::Response> dbus_response =
        transaction_proxy->CallMethodAndBlockWithErrorDetails(
            &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &dbus_error_);
    return !!dbus_response;
  }

  void GeneralError(const std::string& details) override {
    LOG(ERROR) << "Problem with Resolve transaction for package: "
               << package_name_ << ": " << details;
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    callback_.Run(false /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), details);
  }

  void ErrorReceived(uint32_t error_code, const std::string& details) override {
    LOG(ERROR) << "Failure resolving package " << package_name_ << ": "
               << details;
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    // We will still get a Finished signal where we finalize everything, but
    // no need to wait for it.
    callback_.Run(false /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), details);
  }

  void PackageReceived(uint32_t code,
                       const std::string& package_id,
                       const std::string& summary) override {
    LOG(INFO) << "Got a package for package name: " << package_name_;
    // Check if we've already done the callback.
    if (callback_called_)
      return;
    callback_called_ = true;
    PackageKitProxy::LinuxPackageInfo pkg_info;
    pkg_info.package_id = package_id;
    pkg_info.summary = summary;
    callback_.Run(true /*success*/, true /*pkg_found*/, pkg_info, "");
  }

  void FinishedReceived(uint32_t exit_code) override {
    LOG(INFO) << "Finished resolving package name";
    if (callback_called_)
      return;
    callback_called_ = true;

    // If we got here without calling the callback, PackageKit couldn't resolve
    // the package name into a package id.
    callback_.Run(true /*success*/, false /*pkg_found*/,
                  PackageKitProxy::LinuxPackageInfo(), "");
  }

 private:
  std::string package_name_;
  PackageKitProxy::PackageSearchCallback callback_;
  bool callback_called_;
};

}  // namespace

PackageKitProxy::BlockingOperationActiveClearer::BlockingOperationActiveClearer(
    base::Lock* blocking_operation_active_mutex,
    bool* blocking_operation_active)
    : blocking_operation_active_mutex_(blocking_operation_active_mutex),
      blocking_operation_active_(blocking_operation_active) {}

PackageKitProxy::BlockingOperationActiveClearer::
    ~BlockingOperationActiveClearer() {
  base::AutoLock auto_lock(*blocking_operation_active_mutex_);
  *blocking_operation_active_ = false;
}

PackageKitProxy::PackageInfoTransactionData::PackageInfoTransactionData(
    const base::FilePath& file_path_in,
    std::shared_ptr<LinuxPackageInfo> pkg_info_in)
    : file_path(file_path_in),
      event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
            base::WaitableEvent::InitialState::NOT_SIGNALED),
      pkg_info(pkg_info_in) {}

PackageKitProxy::PackageInfoTransactionData::PackageInfoTransactionData(
    const std::string& package_id_in,
    std::shared_ptr<LinuxPackageInfo> pkg_info_in)
    : package_id(package_id_in),
      event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
            base::WaitableEvent::InitialState::NOT_SIGNALED),
      pkg_info(pkg_info_in) {}

// static
std::unique_ptr<PackageKitProxy> PackageKitProxy::Create(
    PackageKitObserver* observer) {
  if (!observer)
    return nullptr;
  auto pk_proxy = base::WrapUnique(new PackageKitProxy(observer));
  if (!pk_proxy->Init()) {
    pk_proxy.reset();
  }
  return pk_proxy;
}

PackageKitProxy::PackageKitProxy(PackageKitObserver* observer)
    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
      observer_(observer),
      blocking_operation_active_(false) {}

PackageKitProxy::~PackageKitProxy() = default;

bool PackageKitProxy::Init() {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  dbus::Bus::Options opts;
  opts.bus_type = dbus::Bus::SYSTEM;
  bus_ = new dbus::Bus(std::move(opts));
  if (!bus_->Connect()) {
    LOG(ERROR) << "Failed to connect to system bus";
    return false;
  }
  packagekit_service_proxy_ = bus_->GetObjectProxy(
      kPackageKitServiceName, dbus::ObjectPath(kPackageKitServicePath));
  if (!packagekit_service_proxy_) {
    LOG(ERROR) << "Failed to get PackageKit D-Bus proxy";
    return false;
  }
  packagekit_service_proxy_->WaitForServiceToBeAvailable(base::Bind(
      &PackageKitProxy::OnPackageKitServiceAvailable, base::Unretained(this)));

  // Fire off a delayed task to do a repo update so that we can do automatic
  // upgrades on our managed packages.
  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&RefreshCacheTransaction::RefreshCacheNow, bus_,
                 base::Unretained(this), packagekit_service_proxy_),
      kRefreshCacheStartupDelay);
  return true;
}

bool PackageKitProxy::GetLinuxPackageInfoFromFilePath(
    const base::FilePath& file_path,
    std::shared_ptr<LinuxPackageInfo> out_pkg_info,
    std::string* out_error) {
  CHECK(out_error);
  // We use another var for the error message into the D-Bus thread call so we
  // don't have contention with that var in the case of a timeout since we want
  // to set the error in a timeout, but not the pkg_info. Shared pointers are
  // used so that if the call times out the pointers are still valid on the
  // D-Bus thread.
  std::shared_ptr<PackageInfoTransactionData> data =
      std::make_shared<PackageInfoTransactionData>(file_path, out_pkg_info);
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&PackageKitProxy::GetLinuxPackageInfoOnDBusThread,
                            base::Unretained(this), data));

  bool result;
  if (!data->event.TimedWait(kGetLinuxPackageInfoTimeout)) {
    LOG(ERROR) << "Timeout waiting on Linux package info";
    out_error->assign("Timeout");
    result = false;
  } else {
    out_error->assign(data->error);
    result = data->result;
  }
  return result;
}

bool PackageKitProxy::GetLinuxPackageInfoFromPackageName(
    const std::string& package_name,
    std::shared_ptr<LinuxPackageInfo> out_pkg_info,
    std::string* out_error) {
  CHECK(out_error);
  // We use another var for the error message into the D-Bus thread call so we
  // don't have contention with that var in the case of a timeout since we want
  // to set the error in a timeout, but not the pkg_info. Shared pointers are
  // used so that if the call times out the pointers are still valid on the
  // D-Bus thread.

  // We put |package_name| into the |package_id| field because we use it in an
  // error message later.
  std::shared_ptr<PackageInfoTransactionData> data =
      std::make_shared<PackageInfoTransactionData>(package_name, out_pkg_info);

  ResolvePackageName(
      package_name,
      base::Bind(
          &PackageKitProxy::
              GetLinuxPackageInfoFromPackageNameResolvePackageNameCallback,
          base::Unretained(this), data, out_error));

  bool result;
  if (!data->event.TimedWait(kGetLinuxPackageInfoTimeout)) {
    LOG(ERROR) << "Timeout waiting on Linux package info";
    out_error->assign("Timeout");
    result = false;
  } else {
    out_error->assign(data->error);
    result = data->result;
  }
  return result;
}

void PackageKitProxy::ResolvePackageName(const std::string& package_name,
                                         PackageSearchCallback callback) {
  LOG(INFO) << "Resolving package name: " << package_name;
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&PackageKitProxy::ResolvePackageNameOnDBusThread,
                 base::Unretained(this), package_name, std::move(callback)));
}

void PackageKitProxy::
    GetLinuxPackageInfoFromPackageNameResolvePackageNameCallback(
        std::shared_ptr<PackageInfoTransactionData> data,
        std::string* out_error,
        bool success,
        bool pkg_resolved,
        const LinuxPackageInfo& pkg_info,
        const std::string& error) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!success) {
    data->error =
        "GetLinuxPackageInfoFromPackageName failed at resolve package name "
        "step: " +
        error;
    data->result = false;
    LOG(ERROR) << data->error;
    data->event.Signal();
    return;
  }

  if (!pkg_resolved) {
    data->error = "GetLinuxPackageInfoFromPackageName failed to resolve: " +
                  data->package_id + " into a package_id";
    data->result = false;
    LOG(ERROR) << data->error;
    data->event.Signal();
    return;
  }
  LOG(INFO) << "Getting package details for " << pkg_info.package_id;
  data->package_id = pkg_info.package_id;
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&PackageKitProxy::GetLinuxPackageInfoOnDBusThread,
                            base::Unretained(this), data));
}

vm_tools::container::InstallLinuxPackageResponse::Status
PackageKitProxy::InstallLinuxPackageFromFilePath(
    const base::FilePath& file_path,
    const std::string& command_uuid,
    std::string* out_error) {
  // Make sure we don't already have one in progress.
  {  // Scope mutex lock
    base::AutoLock auto_lock(blocking_operation_active_mutex_);
    if (blocking_operation_active_) {
      *out_error = "Install or other blocking operation is already active";
      LOG(ERROR) << *out_error;
      return vm_tools::container::InstallLinuxPackageResponse::
          INSTALL_ALREADY_ACTIVE;
    }
    blocking_operation_active_ = true;
  }  // Release mutex lock
  // We own blocking_operation_active, make sure we clear it later.
  auto clearer = std::make_unique<BlockingOperationActiveClearer>(
      &blocking_operation_active_mutex_, &blocking_operation_active_);
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&PackageKitProxy::InstallLinuxPackageFromFilePathOnDBusThread,
                 base::Unretained(this), file_path, command_uuid,
                 base::Passed(&clearer)));
  return vm_tools::container::InstallLinuxPackageResponse::STARTED;
}

vm_tools::container::InstallLinuxPackageResponse::Status
PackageKitProxy::InstallLinuxPackageFromPackageId(
    const std::string& package_id,
    const std::string& command_uuid,
    std::string* out_error) {
  // Make sure we don't already have one in progress.
  {  // Scope mutex lock
    base::AutoLock auto_lock(blocking_operation_active_mutex_);
    if (blocking_operation_active_) {
      *out_error = "Install or other blocking operation is already active";
      LOG(ERROR) << *out_error;
      return vm_tools::container::InstallLinuxPackageResponse::
          INSTALL_ALREADY_ACTIVE;
    }
    blocking_operation_active_ = true;
  }  // Release mutex lock
  // We own blocking_operation_active, make sure we clear it later.
  auto clearer = std::make_unique<BlockingOperationActiveClearer>(
      &blocking_operation_active_mutex_, &blocking_operation_active_);
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&PackageKitProxy::InstallLinuxPackageFromPackageIdOnDBusThread,
                 base::Unretained(this), package_id, command_uuid,
                 base::Passed(&clearer)));
  return vm_tools::container::InstallLinuxPackageResponse::STARTED;
}

vm_tools::container::UninstallPackageOwningFileResponse::Status
PackageKitProxy::UninstallPackageOwningFile(const base::FilePath& file_path,
                                            std::string* out_error) {
  // Fail if there is a blocking operation in progress.
  {  // Scope mutex lock
    base::AutoLock auto_lock(blocking_operation_active_mutex_);
    if (blocking_operation_active_) {
      *out_error = "Uninstall or other blocking operation is already active";
      LOG(ERROR) << *out_error;
      return vm_tools::container::UninstallPackageOwningFileResponse::
          BLOCKING_OPERATION_IN_PROGRESS;
    }
    blocking_operation_active_ = true;
  }  // Release mutex lock
  // We own blocking_operation_active, make sure we clear it later.
  auto clearer = std::make_unique<BlockingOperationActiveClearer>(
      &blocking_operation_active_mutex_, &blocking_operation_active_);

  // Start search
  PackageSearchCallback callback = base::Bind(
      &PackageKitProxy::UninstallPackageOwningFileSearchForFileCallback,
      base::Unretained(this), file_path, base::Passed(&clearer));
  SearchLinuxPackagesForFile(file_path, std::move(callback));
  return vm_tools::container::UninstallPackageOwningFileResponse::STARTED;
}

void PackageKitProxy::UninstallPackageOwningFileSearchForFileCallback(
    base::FilePath file_path,
    std::unique_ptr<BlockingOperationActiveClearer>
        blocking_operation_active_lock,
    bool success,
    bool pkg_found,
    const LinuxPackageInfo& pkg_info,
    const std::string& error) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!success) {
    LOG(ERROR) << "UninstallPackageOwningFile failed at search package step: "
               << error;
    if (observer_) {
      observer_->OnUninstallCompletion(false, error);
    }
    return;
  }

  if (!pkg_found) {
    LOG(ERROR) << "UninstallPackageOwningFile failed to find a package for "
               << file_path.value();
    if (observer_) {
      observer_->OnUninstallCompletion(
          false, "Could not find package that owns " + file_path.value());
    }
    return;
  }
  LOG(INFO) << "Uninstalling Linux package " << pkg_info.package_id;
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  UninstallPackagesTransaction* transaction = new UninstallPackagesTransaction(
      bus_, this, packagekit_service_proxy_, pkg_info.package_id,
      std::move(blocking_operation_active_lock), observer_);
  transaction->StartTransaction();
}

void PackageKitProxy::SearchLinuxPackagesForFile(
    const base::FilePath& file_path, PackageSearchCallback callback) {
  LOG(INFO) << "Searching for local Linux package that owns "
            << file_path.value();
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&PackageKitProxy::SearchLinuxPackagesForFileOnDBusThread,
                 base::Unretained(this), file_path, std::move(callback)));
}

void PackageKitProxy::AddPackageKitDeathObserver(
    PackageKitDeathObserver* observer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  death_observers_.AddObserver(observer);
}

void PackageKitProxy::RemovePackageKitDeathObserver(
    PackageKitDeathObserver* observer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  death_observers_.RemoveObserver(observer);
}

void PackageKitProxy::GetLinuxPackageInfoOnDBusThread(
    std::shared_ptr<PackageInfoTransactionData> data) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  LOG(INFO) << "Getting information on Linux package";
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  GetDetailsTransaction* transaction =
      new GetDetailsTransaction(bus_, this, packagekit_service_proxy_, data);
  transaction->StartTransaction();
}

void PackageKitProxy::InstallLinuxPackageFromFilePathOnDBusThread(
    const base::FilePath& file_path,
    const std::string& command_uuid,
    std::unique_ptr<BlockingOperationActiveClearer> clearer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  InstallTransaction* transaction =
      new InstallTransaction(bus_, this, packagekit_service_proxy_, observer_,
                             file_path, command_uuid, std::move(clearer));
  transaction->StartTransaction();
}

void PackageKitProxy::InstallLinuxPackageFromPackageIdOnDBusThread(
    const std::string& package_id,
    const std::string& command_uuid,
    std::unique_ptr<BlockingOperationActiveClearer> clearer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  InstallTransaction* transaction =
      new InstallTransaction(bus_, this, packagekit_service_proxy_, observer_,
                             package_id, command_uuid, std::move(clearer));
  transaction->StartTransaction();
}

void PackageKitProxy::SearchLinuxPackagesForFileOnDBusThread(
    const base::FilePath& file_path, PackageSearchCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  SearchFilesTransaction* transaction = new SearchFilesTransaction(
      bus_, this, packagekit_service_proxy_, file_path, std::move(callback));
  transaction->StartTransaction();
}

void PackageKitProxy::ResolvePackageNameOnDBusThread(
    const std::string& package_name, PackageSearchCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  // This object is intentionally leaked and will clean itself up when done
  // with all the D-Bus communication.
  ResolveTransaction* transaction = new ResolveTransaction(
      bus_, this, packagekit_service_proxy_, package_name, std::move(callback));
  transaction->StartTransaction();
}

void PackageKitProxy::OnPackageKitNameOwnerChanged(
    const std::string& old_owner, const std::string& new_owner) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (new_owner.empty()) {
    for (PackageKitDeathObserver& obs : death_observers_)
      obs.OnPackageKitDeath();
  }
}

void PackageKitProxy::OnPackageKitServiceAvailable(bool service_is_available) {
  if (service_is_available) {
    packagekit_service_proxy_->SetNameOwnerChangedCallback(
        base::Bind(&PackageKitProxy::OnPackageKitNameOwnerChanged,
                   base::Unretained(this)));
  }
}

}  // namespace garcon
}  // namespace vm_tools
