// Copyright (c) 2011 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/omaha_request_params.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/utsname.h>

#include <map>
#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <policy/device_policy.h>

#include "update_engine/constants.h"
#include "update_engine/hardware_interface.h"
#include "update_engine/simple_key_value_store.h"
#include "update_engine/system_state.h"
#include "update_engine/utils.h"

#define CALL_MEMBER_FN(object, member) ((object).*(member))

using std::map;
using std::string;
using std::vector;

namespace chromeos_update_engine {

const char* const OmahaRequestParams::kAppId(
    "{87efface-864d-49a5-9bb3-4b050a7c227a}");
const char* const OmahaRequestParams::kOsPlatform("Chrome OS");
const char* const OmahaRequestParams::kOsVersion("Indy");
const char* const kProductionOmahaUrl(
    "https://tools.google.com/service/update2");

const char* const OmahaRequestParams::kUpdateChannelKey(
    "CHROMEOS_RELEASE_TRACK");
const char* const OmahaRequestParams::kIsPowerwashAllowedKey(
    "CHROMEOS_IS_POWERWASH_ALLOWED");

const char* kChannelsByStability[] = {
    // This list has to be sorted from least stable to most stable channel.
    "canary-channel",
    "dev-channel",
    "beta-channel",
    "stable-channel",
};

bool OmahaRequestParams::Init(const std::string& in_app_version,
                              const std::string& in_update_url,
                              bool in_interactive) {
  LOG(INFO) << "Initializing parameters for this update attempt";
  InitFromLsbValue();
  bool stateful_override = !ShouldLockDown();
  os_platform_ = OmahaRequestParams::kOsPlatform;
  os_version_ = OmahaRequestParams::kOsVersion;
  app_version_ = in_app_version.empty() ?
      GetLsbValue("CHROMEOS_RELEASE_VERSION", "", nullptr, stateful_override) :
      in_app_version;
  os_sp_ = app_version_ + "_" + GetMachineType();
  os_board_ = GetLsbValue("CHROMEOS_RELEASE_BOARD",
                          "",
                          nullptr,
                          stateful_override);
  string release_app_id = GetLsbValue("CHROMEOS_RELEASE_APPID",
                                      OmahaRequestParams::kAppId,
                                      nullptr,
                                      stateful_override);
  board_app_id_ = GetLsbValue("CHROMEOS_BOARD_APPID",
                              release_app_id,
                              nullptr,
                              stateful_override);
  canary_app_id_ = GetLsbValue("CHROMEOS_CANARY_APPID",
                               release_app_id,
                               nullptr,
                               stateful_override);
  app_lang_ = "en-US";
  hwid_ = system_state_->hardware()->GetHardwareClass();
  if (CollectECFWVersions()) {
    fw_version_ = system_state_->hardware()->GetFirmwareVersion();
    ec_version_ = system_state_->hardware()->GetECVersion();
  }

  if (current_channel_ == target_channel_) {
    // deltas are only okay if the /.nodelta file does not exist.  if we don't
    // know (i.e. stat() returns some unexpected error), then err on the side of
    // caution and say deltas are not okay.
    struct stat stbuf;
    delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) &&
                  (errno == ENOENT);

  } else {
    LOG(INFO) << "Disabling deltas as a channel change is pending";
    // For now, disable delta updates if the current channel is different from
    // the channel that we're sending to the update server because such updates
    // are destined to fail -- the current rootfs hash will be different than
    // the expected hash due to the different channel in /etc/lsb-release.
    delta_okay_ = false;
  }

  if (in_update_url.empty())
    update_url_ = GetLsbValue("CHROMEOS_AUSERVER", kProductionOmahaUrl, nullptr,
                              stateful_override);
  else
    update_url_ = in_update_url;

  // Set the interactive flag accordingly.
  interactive_ = in_interactive;
  return true;
}

bool OmahaRequestParams::CollectECFWVersions() const {
  return {
      StartsWithASCII(hwid_, string("SAMS ALEX"), true) ||
      StartsWithASCII(hwid_, string("BUTTERFLY"), true) ||
      StartsWithASCII(hwid_, string("LUMPY"), true) ||
      StartsWithASCII(hwid_, string("PARROT"), true) ||
      StartsWithASCII(hwid_, string("SPRING"), true) ||
      StartsWithASCII(hwid_, string("SNOW"), true)
  };
}

bool OmahaRequestParams::SetTargetChannel(const std::string& new_target_channel,
                                          bool is_powerwash_allowed) {
  LOG(INFO) << "SetTargetChannel called with " << new_target_channel
            << ", Is Powerwash Allowed = "
            << utils::ToString(is_powerwash_allowed)
            << ". Current channel = " << current_channel_
            << ", existing target channel = " << target_channel_
            << ", download channel = " << download_channel_;
  TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel));
  KeyValueStore lsb_release;
  base::FilePath kFile(root_ + kStatefulPartition + "/etc/lsb-release");

  lsb_release.Load(kFile.value());
  lsb_release.SetString(kUpdateChannelKey, new_target_channel);
  lsb_release.SetBoolean(kIsPowerwashAllowedKey, is_powerwash_allowed);

  TEST_AND_RETURN_FALSE(base::CreateDirectory(kFile.DirName()));
  TEST_AND_RETURN_FALSE(lsb_release.Save(kFile.value()));
  target_channel_ = new_target_channel;
  is_powerwash_allowed_ = is_powerwash_allowed;
  return true;
}

void OmahaRequestParams::SetTargetChannelFromLsbValue() {
  string target_channel_new_value = GetLsbValue(
      kUpdateChannelKey,
      current_channel_,
      &chromeos_update_engine::OmahaRequestParams::IsValidChannel,
      true);  // stateful_override

  if (target_channel_ != target_channel_new_value) {
    target_channel_ = target_channel_new_value;
    LOG(INFO) << "Target Channel set to " << target_channel_
              << " from LSB file";
  }
}

void OmahaRequestParams::SetCurrentChannelFromLsbValue() {
  string current_channel_new_value = GetLsbValue(
      kUpdateChannelKey,
      current_channel_,
      nullptr,  // No need to validate the read-only rootfs channel.
      false);  // stateful_override is false so we get the current channel.

  if (current_channel_ != current_channel_new_value) {
    current_channel_ = current_channel_new_value;
    LOG(INFO) << "Current Channel set to " << current_channel_
              << " from LSB file in rootfs";
  }
}

void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() {
  string is_powerwash_allowed_str = GetLsbValue(
      kIsPowerwashAllowedKey,
      "false",
      nullptr,  // no need to validate
      true);  // always get it from stateful, as that's the only place it'll be
  bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true");
  if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) {
    is_powerwash_allowed_ = is_powerwash_allowed_new_value;
    LOG(INFO) << "Powerwash Allowed set to "
              << utils::ToString(is_powerwash_allowed_)
              << " from LSB file in stateful";
  }
}

void OmahaRequestParams::UpdateDownloadChannel() {
  if (download_channel_ != target_channel_) {
    download_channel_ = target_channel_;
    LOG(INFO) << "Download channel for this attempt = " << download_channel_;
  }
}

void OmahaRequestParams::InitFromLsbValue() {
  SetCurrentChannelFromLsbValue();
  SetTargetChannelFromLsbValue();
  SetIsPowerwashAllowedFromLsbValue();
  UpdateDownloadChannel();
}

string OmahaRequestParams::GetLsbValue(const string& key,
                                       const string& default_value,
                                       ValueValidator validator,
                                       bool stateful_override) const {
  vector<string> files;
  if (stateful_override) {
    files.push_back(string(kStatefulPartition) + "/etc/lsb-release");
  }
  files.push_back("/etc/lsb-release");
  for (vector<string>::const_iterator it = files.begin();
       it != files.end(); ++it) {
    // TODO(adlr): make sure files checked are owned as root (and all their
    // parents are recursively, too).
    KeyValueStore data;
    if (!data.Load(root_ + *it))
      continue;

    string value;
    if (data.GetString(key, &value)) {
      if (validator && !CALL_MEMBER_FN(*this, validator)(value)) {
        continue;
      }
      return value;
    }
  }
  // not found
  return default_value;
}

string OmahaRequestParams::GetMachineType() const {
  struct utsname buf;
  string ret;
  if (uname(&buf) == 0)
    ret = buf.machine;
  return ret;
}

bool OmahaRequestParams::ShouldLockDown() const {
  if (force_lock_down_) {
    return forced_lock_down_;
  }
  return system_state_->hardware()->IsOfficialBuild() &&
            system_state_->hardware()->IsNormalBootMode();
}

bool OmahaRequestParams::IsValidChannel(const std::string& channel) const {
  return GetChannelIndex(channel) >= 0;
}

void OmahaRequestParams::set_root(const std::string& root) {
  root_ = root;
  InitFromLsbValue();
}

void OmahaRequestParams::SetLockDown(bool lock) {
  force_lock_down_ = true;
  forced_lock_down_ = lock;
}

int OmahaRequestParams::GetChannelIndex(const std::string& channel) const {
  for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
    if (channel == kChannelsByStability[t])
      return t;

  return -1;
}

bool OmahaRequestParams::to_more_stable_channel() const {
  int current_channel_index = GetChannelIndex(current_channel_);
  int download_channel_index = GetChannelIndex(download_channel_);

  return download_channel_index > current_channel_index;
}

string OmahaRequestParams::GetAppId() const {
  return download_channel_ == "canary-channel" ? canary_app_id_ : board_app_id_;
}

}  // namespace chromeos_update_engine
