// 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);
  }
  PackageKitTransaction(const PackageKitTransaction&) = delete;
  PackageKitTransaction& operator=(const PackageKitTransaction&) = delete;

  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_;
};

// 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
