// 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
      NULL,  // Accumulator
      NULL,  // Accumulator data
      NULL,  // 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, NULL));
}

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();

  // The default for not present setting is false.
  if (!prefs->Exists(chromeos_update_engine::kPrefsP2PEnabled)) {
    *enabled = false;
    return TRUE;
  }

  bool p2p_pref = false;
  if (!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;
}
