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