// Copyright (c) 2012 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 "update_engine/dbus_service.h"

#include <set>
#include <string>

#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <policy/device_policy.h>

#include "update_engine/clock_interface.h"
#include "update_engine/connection_manager.h"
#include "update_engine/dbus_constants.h"
#include "update_engine/hardware_interface.h"
#include "update_engine/omaha_request_params.h"
#include "update_engine/p2p_manager.h"
#include "update_engine/prefs.h"
#include "update_engine/update_attempter.h"
#include "update_engine/utils.h"

using std::set;
using std::string;
using chromeos_update_engine::AttemptUpdateFlags;
using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;

#define UPDATE_ENGINE_SERVICE_ERROR update_engine_service_error_quark ()
#define UPDATE_ENGINE_SERVICE_TYPE_ERROR \
  (update_engine_service_error_get_type())

enum UpdateEngineServiceError {
  UPDATE_ENGINE_SERVICE_ERROR_FAILED,
  UPDATE_ENGINE_SERVICE_NUM_ERRORS
};

static GQuark update_engine_service_error_quark(void) {
  static GQuark ret = 0;

  if (ret == 0)
    ret = g_quark_from_static_string("update_engine_service_error");

  return ret;
}

#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }

static GType update_engine_service_error_get_type(void) {
  static GType etype = 0;

  if (etype == 0) {
    static const GEnumValue values[] = {
      ENUM_ENTRY(UPDATE_ENGINE_SERVICE_ERROR_FAILED, "Failed"),
      { 0, 0, 0 }
    };
    G_STATIC_ASSERT(UPDATE_ENGINE_SERVICE_NUM_ERRORS ==
                    G_N_ELEMENTS(values) - 1);
    etype = g_enum_register_static("UpdateEngineServiceError", values);
  }

  return etype;
}

static const char kAUTestURLRequest[] = "autest";
// By default autest bypasses scattering. If we want to test scattering,
// we should use autest-scheduled. The Url used is same in both cases, but
// different params are passed to CheckForUpdate method.
static const char kScheduledAUTestURLRequest[] = "autest-scheduled";

static const char kAUTestURL[] =
    "https://omaha.sandbox.google.com/service/update2";

G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT)

static void update_engine_service_finalize(GObject* object) {
  G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object);
}

static void log_and_set_response_error(GError** error,
                                       UpdateEngineServiceError error_code,
                                       const string& reason) {
  LOG(ERROR) << "Sending DBus Failure: " << reason;
  g_set_error_literal(error, UPDATE_ENGINE_SERVICE_ERROR,
                      error_code, reason.c_str());
}

static guint status_update_signal = 0;

static void update_engine_service_class_init(UpdateEngineServiceClass* klass) {
  GObjectClass *object_class;
  object_class = G_OBJECT_CLASS(klass);
  object_class->finalize = update_engine_service_finalize;

  status_update_signal = g_signal_new(
      "status_update",
      G_OBJECT_CLASS_TYPE(klass),
      G_SIGNAL_RUN_LAST,
      0,  // 0 == no class method associated
      nullptr,  // Accumulator
      nullptr,  // Accumulator data
      nullptr,  // Marshaller
      G_TYPE_NONE,  // Return type
      5,  // param count:
      G_TYPE_INT64,
      G_TYPE_DOUBLE,
      G_TYPE_STRING,
      G_TYPE_STRING,
      G_TYPE_INT64);
}

static void update_engine_service_init(UpdateEngineService* object) {
  dbus_g_error_domain_register(UPDATE_ENGINE_SERVICE_ERROR,
                               "org.chromium.UpdateEngine.Error",
                               UPDATE_ENGINE_SERVICE_TYPE_ERROR);
}

UpdateEngineService* update_engine_service_new(void) {
  return reinterpret_cast<UpdateEngineService*>(
      g_object_new(UPDATE_ENGINE_TYPE_SERVICE, nullptr));
}

gboolean update_engine_service_attempt_update(UpdateEngineService* self,
                                              gchar* app_version,
                                              gchar* omaha_url,
                                              GError **error) {
  return update_engine_service_attempt_update_with_flags(self,
                                                         app_version,
                                                         omaha_url,
                                                         0,  // No flags set.
                                                         error);
}

gboolean update_engine_service_attempt_update_with_flags(
    UpdateEngineService* self,
    gchar* app_version,
    gchar* omaha_url,
    gint flags_as_int,
    GError **error) {
  string update_app_version;
  string update_omaha_url;
  AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(flags_as_int);
  bool interactive = true;

  // Only non-official (e.g., dev and test) builds can override the current
  // version and update server URL over D-Bus. However, pointing to the
  // hardcoded test update server URL is always allowed.
  if (!self->system_state_->hardware()->IsOfficialBuild()) {
    if (app_version) {
      update_app_version = app_version;
    }
    if (omaha_url) {
      update_omaha_url = omaha_url;
    }
  }
  if (omaha_url) {
    if (strcmp(omaha_url, kScheduledAUTestURLRequest) == 0) {
      update_omaha_url = kAUTestURL;
      // pretend that it's not user-initiated even though it is,
      // so as to test scattering logic, etc. which get kicked off
      // only in scheduled update checks.
      interactive = false;
    } else if (strcmp(omaha_url, kAUTestURLRequest) == 0) {
      update_omaha_url = kAUTestURL;
    }
  }
  if (flags & kAttemptUpdateFlagNonInteractive)
    interactive = false;
  LOG(INFO) << "Attempt update: app_version=\"" << update_app_version << "\" "
            << "omaha_url=\"" << update_omaha_url << "\" "
            << "flags=0x" << std::hex << flags << " "
            << "interactive=" << (interactive? "yes" : "no");
  self->system_state_->update_attempter()->CheckForUpdate(update_app_version,
                                                          update_omaha_url,
                                                          interactive);
  return TRUE;
}

gboolean update_engine_service_attempt_rollback(UpdateEngineService* self,
                                                gboolean powerwash,
                                                GError **error) {
  LOG(INFO) << "Attempting rollback to non-active partitions.";

  if (!self->system_state_->update_attempter()->Rollback(powerwash)) {
    // TODO(dgarrett): Give a more specific error code/reason.
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Rollback attempt failed.");
    return FALSE;
  }

  return TRUE;
}

gboolean update_engine_service_can_rollback(UpdateEngineService* self,
                                            gboolean* out_can_rollback,
                                            GError **error) {
  bool can_rollback = self->system_state_->update_attempter()->CanRollback();
  LOG(INFO) << "Checking to see if we can rollback . Result: " << can_rollback;
  *out_can_rollback = can_rollback;
  return TRUE;
}

gboolean update_engine_service_get_rollback_partition(
    UpdateEngineService* self,
    gchar** out_rollback_partition_name,
    GError **error) {
  auto name = self->system_state_->update_attempter()->GetRollbackPartition();
  LOG(INFO) << "Getting rollback partition name. Result: " << name;
  *out_rollback_partition_name = g_strdup(name.c_str());
  return TRUE;
}

gboolean update_engine_service_get_kernel_devices(UpdateEngineService* self,
                                                  gchar** out_kernel_devices,
                                                  GError **error) {
  auto devices = self->system_state_->update_attempter()->GetKernelDevices();
  std::string info;
  for (const auto& device : devices) {
    base::StringAppendF(&info, "%d:%s\n",
                        device.second ? 1 : 0, device.first.c_str());
  }
  LOG(INFO) << "Available kernel devices: " << info;
  *out_kernel_devices = g_strdup(info.c_str());
  return TRUE;
}


gboolean update_engine_service_reset_status(UpdateEngineService* self,
                                            GError **error) {
  if (!self->system_state_->update_attempter()->ResetStatus()) {
    // TODO(dgarrett): Give a more specific error code/reason.
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "ResetStatus failed.");
    return FALSE;
  }

  return TRUE;
}

gboolean update_engine_service_get_status(UpdateEngineService* self,
                                          int64_t* last_checked_time,
                                          double* progress,
                                          gchar** current_operation,
                                          gchar** new_version,
                                          int64_t* new_size,
                                          GError **error) {
  string current_op;
  string new_version_str;

  CHECK(self->system_state_->update_attempter()->GetStatus(last_checked_time,
                                                           progress,
                                                           &current_op,
                                                           &new_version_str,
                                                           new_size));
  *current_operation = g_strdup(current_op.c_str());
  *new_version = g_strdup(new_version_str.c_str());

  if (!*current_operation) {
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Unable to find current_operation.");
    return FALSE;
  }

  if (!*new_version) {
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Unable to find vew_version.");
    return FALSE;
  }

  return TRUE;
}

gboolean update_engine_service_reboot_if_needed(UpdateEngineService* self,
                                                GError **error) {
  if (!self->system_state_->update_attempter()->RebootIfNeeded()) {
    // TODO(dgarrett): Give a more specific error code/reason.
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Reboot not needed, or attempt failed.");
    return FALSE;
  }
  return TRUE;
}

gboolean update_engine_service_set_channel(UpdateEngineService* self,
                                           gchar* target_channel,
                                           gboolean is_powerwash_allowed,
                                           GError **error) {
  if (!target_channel) {
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Target channel to set not specified.");
    return FALSE;
  }

  const policy::DevicePolicy* device_policy =
      self->system_state_->device_policy();

  // The device_policy is loaded in a lazy way before an update check. Load it
  // now from the libchromeos cache if it wasn't already loaded.
  if (!device_policy) {
    chromeos_update_engine::UpdateAttempter* update_attempter =
        self->system_state_->update_attempter();
    if (update_attempter) {
      update_attempter->RefreshDevicePolicy();
      device_policy = self->system_state_->device_policy();
    }
  }

  bool delegated = false;
  if (device_policy &&
      device_policy->GetReleaseChannelDelegated(&delegated) && !delegated) {
    log_and_set_response_error(
        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
        "Cannot set target channel explicitly when channel "
        "policy/settings is not delegated");
    return FALSE;
  }

  LOG(INFO) << "Setting destination channel to: " << target_channel;
  if (!self->system_state_->request_params()->SetTargetChannel(
          target_channel, is_powerwash_allowed)) {
    // TODO(dgarrett): Give a more specific error code/reason.
    log_and_set_response_error(error,
                               UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Setting channel failed.");
    return FALSE;
  }

  return TRUE;
}

gboolean update_engine_service_get_channel(UpdateEngineService* self,
                                           gboolean get_current_channel,
                                           gchar** channel,
                                           GError **error) {
  chromeos_update_engine::OmahaRequestParams* rp =
      self->system_state_->request_params();

  string channel_str = get_current_channel ?
      rp->current_channel() : rp->target_channel();

  *channel = g_strdup(channel_str.c_str());
  return TRUE;
}

gboolean update_engine_service_set_p2p_update_permission(
    UpdateEngineService* self,
    gboolean enabled,
    GError **error) {
  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();
  chromeos_update_engine::P2PManager* p2p_manager =
      self->system_state_->p2p_manager();

  bool p2p_was_enabled = p2p_manager && p2p_manager->IsP2PEnabled();

  if (!prefs->SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, enabled)) {
    log_and_set_response_error(
        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
        string("Error setting the update over cellular to ") +
        (enabled ? "true." : "false."));
    return FALSE;
  }

  // If P2P is being effectively disabled (IsP2PEnabled() reports the change)
  // then we need to shutdown the service.
  if (p2p_was_enabled && !p2p_manager->IsP2PEnabled())
    p2p_manager->EnsureP2PNotRunning();

  return TRUE;
}

gboolean update_engine_service_get_p2p_update_permission(
    UpdateEngineService* self,
    gboolean* enabled,
    GError **error) {
  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();

  bool p2p_pref = false;  // Default if no setting is present.
  if (prefs->Exists(chromeos_update_engine::kPrefsP2PEnabled) &&
      !prefs->GetBoolean(chromeos_update_engine::kPrefsP2PEnabled, &p2p_pref)) {
    log_and_set_response_error(error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "Error getting the P2PEnabled setting.");
    return FALSE;
  }

  *enabled = p2p_pref;
  return TRUE;
}

gboolean update_engine_service_set_update_over_cellular_permission(
    UpdateEngineService* self,
    gboolean allowed,
    GError **error) {
  set<string> allowed_types;
  const policy::DevicePolicy* device_policy =
      self->system_state_->device_policy();

  // The device_policy is loaded in a lazy way before an update check. Load it
  // now from the libchromeos cache if it wasn't already loaded.
  if (!device_policy) {
    chromeos_update_engine::UpdateAttempter* update_attempter =
        self->system_state_->update_attempter();
    if (update_attempter) {
      update_attempter->RefreshDevicePolicy();
      device_policy = self->system_state_->device_policy();
    }
  }

  // Check if this setting is allowed by the device policy.
  if (device_policy &&
      device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
    log_and_set_response_error(
        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
        "Ignoring the update over cellular setting since there's "
        "a device policy enforcing this setting.");
    return FALSE;
  }

  // If the policy wasn't loaded yet, then it is still OK to change the local
  // setting because the policy will be checked again during the update check.

  chromeos_update_engine::PrefsInterface* prefs = self->system_state_->prefs();

  if (!prefs->SetBoolean(
      chromeos_update_engine::kPrefsUpdateOverCellularPermission,
      allowed)) {
    log_and_set_response_error(
        error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
        string("Error setting the update over cellular to ") +
        (allowed ? "true" : "false"));
    return FALSE;
  }

  return TRUE;
}

gboolean update_engine_service_get_update_over_cellular_permission(
    UpdateEngineService* self,
    gboolean* allowed,
    GError **error) {
  chromeos_update_engine::ConnectionManager* cm =
      self->system_state_->connection_manager();

  // The device_policy is loaded in a lazy way before an update check and is
  // used to determine if an update is allowed over cellular. Load the device
  // policy now from the libchromeos cache if it wasn't already loaded.
  if (!self->system_state_->device_policy()) {
    chromeos_update_engine::UpdateAttempter* update_attempter =
        self->system_state_->update_attempter();
    if (update_attempter)
      update_attempter->RefreshDevicePolicy();
  }

  // Return the current setting based on the same logic used while checking for
  // updates. A log message could be printed as the result of this test.
  LOG(INFO) << "Checking if updates over cellular networks are allowed:";
  *allowed = cm->IsUpdateAllowedOver(
      chromeos_update_engine::kNetCellular,
      chromeos_update_engine::NetworkTethering::kUnknown);

  return TRUE;
}

gboolean update_engine_service_get_duration_since_update(
    UpdateEngineService* self,
    gint64* out_usec_wallclock,
    GError **error) {

  base::Time time;
  if (!self->system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) {
    log_and_set_response_error(error, UPDATE_ENGINE_SERVICE_ERROR_FAILED,
                               "No pending update.");
    return FALSE;
  }

  chromeos_update_engine::ClockInterface *clock = self->system_state_->clock();
  *out_usec_wallclock = (clock->GetBootTime() - time).InMicroseconds();
  return TRUE;
}

gboolean update_engine_service_emit_status_update(
    UpdateEngineService* self,
    gint64 last_checked_time,
    gdouble progress,
    const gchar* current_operation,
    const gchar* new_version,
    gint64 new_size) {
  g_signal_emit(self,
                status_update_signal,
                0,
                last_checked_time,
                progress,
                current_operation,
                new_version,
                new_size);
  return TRUE;
}

gboolean update_engine_service_get_prev_version(
    UpdateEngineService* self,
    gchar** prev_version,
    GError **error) {
  std::string ver = self->system_state_->update_attempter()->GetPrevVersion();
  *prev_version = g_strdup(ver.c_str());
  return TRUE;
}
