// Copyright 2014 The Chromium 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 "google_apis/gcm/engine/gservices_settings.h"

#include "base/bind.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"

namespace {
// The expected time in seconds between periodic checkins.
const char kCheckinIntervalKey[] = "checkin_interval";
// The override URL to the checkin server.
const char kCheckinURLKey[] = "checkin_url";
// The MCS machine name to connect to.
const char kMCSHostnameKey[] = "gcm_hostname";
// The MCS port to connect to.
const char kMCSSecurePortKey[] = "gcm_secure_port";
// The URL to get MCS registration IDs.
const char kRegistrationURLKey[] = "gcm_registration_url";

const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60;  // seconds = 2 days.
const int64 kMinimumCheckinInterval = 12 * 60 * 60;      // seconds = 12 hours.
const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin";
const char kDefaultMCSHostname[] = "mtalk.google.com";
const int kDefaultMCSMainSecurePort = 5228;
const int kDefaultMCSFallbackSecurePort = 443;
const char kDefaultRegistrationURL[] =
    "https://android.clients.google.com/c2dm/register3";
// Settings that are to be deleted are marked with this prefix in checkin
// response.
const char kDeleteSettingPrefix[] = "delete_";
// Settings digest starts with verison number followed by '-'.
const char kDigestVersionPrefix[] = "1-";
const char kMCSEnpointTemplate[] = "https://%s:%d";
const int kMaxSecurePort = 65535;

std::string MakeMCSEndpoint(const std::string& mcs_hostname, int port) {
  return base::StringPrintf(kMCSEnpointTemplate, mcs_hostname.c_str(), port);
}

// Default settings can be omitted, as GServicesSettings class provides
// reasonable defaults.
bool CanBeOmitted(const std::string& settings_name) {
  return settings_name == kCheckinIntervalKey ||
         settings_name == kCheckinURLKey ||
         settings_name == kMCSHostnameKey ||
         settings_name == kMCSSecurePortKey ||
         settings_name == kRegistrationURLKey;
}

bool VerifyCheckinInterval(
    const gcm::GServicesSettings::SettingsMap& settings) {
  gcm::GServicesSettings::SettingsMap::const_iterator iter =
      settings.find(kCheckinIntervalKey);
  if (iter == settings.end())
    return CanBeOmitted(kCheckinIntervalKey);

  int64 checkin_interval = kMinimumCheckinInterval;
  if (!base::StringToInt64(iter->second, &checkin_interval)) {
    DVLOG(1) << "Failed to parse checkin interval: " << iter->second;
    return false;
  }
  if (checkin_interval == std::numeric_limits<int64>::max()) {
    DVLOG(1) << "Checkin interval is too big: " << checkin_interval;
    return false;
  }
  if (checkin_interval < kMinimumCheckinInterval) {
    DVLOG(1) << "Checkin interval: " << checkin_interval
             << " is less than allowed minimum: " << kMinimumCheckinInterval;
  }

  return true;
}

bool VerifyMCSEndpoint(const gcm::GServicesSettings::SettingsMap& settings) {
  std::string mcs_hostname;
  gcm::GServicesSettings::SettingsMap::const_iterator iter =
      settings.find(kMCSHostnameKey);
  if (iter == settings.end()) {
    // Because endpoint has 2 parts (hostname and port) we are defaulting and
    // moving on with verification.
    if (CanBeOmitted(kMCSHostnameKey))
      mcs_hostname = kDefaultMCSHostname;
    else
      return false;
  } else if (iter->second.empty()) {
    DVLOG(1) << "Empty MCS hostname provided.";
    return false;
  } else {
    mcs_hostname = iter->second;
  }

  int mcs_secure_port = 0;
  iter = settings.find(kMCSSecurePortKey);
  if (iter == settings.end()) {
    // Simlarly we might have to default the port, when only hostname is
    // provided.
    if (CanBeOmitted(kMCSSecurePortKey))
      mcs_secure_port = kDefaultMCSMainSecurePort;
    else
      return false;
  } else if (!base::StringToInt(iter->second, &mcs_secure_port)) {
    DVLOG(1) << "Failed to parse MCS secure port: " << iter->second;
    return false;
  }

  if (mcs_secure_port < 0 || mcs_secure_port > kMaxSecurePort) {
    DVLOG(1) << "Incorrect port value: " << mcs_secure_port;
    return false;
  }

  GURL mcs_main_endpoint(MakeMCSEndpoint(mcs_hostname, mcs_secure_port));
  if (!mcs_main_endpoint.is_valid()) {
    DVLOG(1) << "Invalid main MCS endpoint: "
             << mcs_main_endpoint.possibly_invalid_spec();
    return false;
  }
  GURL mcs_fallback_endpoint(
      MakeMCSEndpoint(mcs_hostname, kDefaultMCSFallbackSecurePort));
  if (!mcs_fallback_endpoint.is_valid()) {
    DVLOG(1) << "Invalid fallback MCS endpoint: "
             << mcs_fallback_endpoint.possibly_invalid_spec();
    return false;
  }

  return true;
}

bool VerifyCheckinURL(const gcm::GServicesSettings::SettingsMap& settings) {
  gcm::GServicesSettings::SettingsMap::const_iterator iter =
      settings.find(kCheckinURLKey);
  if (iter == settings.end())
    return CanBeOmitted(kCheckinURLKey);

  GURL checkin_url(iter->second);
  if (!checkin_url.is_valid()) {
    DVLOG(1) << "Invalid checkin URL provided: " << iter->second;
    return false;
  }

  return true;
}

bool VerifyRegistrationURL(
    const gcm::GServicesSettings::SettingsMap& settings) {
  gcm::GServicesSettings::SettingsMap::const_iterator iter =
      settings.find(kRegistrationURLKey);
  if (iter == settings.end())
    return CanBeOmitted(kRegistrationURLKey);

  GURL registration_url(iter->second);
  if (!registration_url.is_valid()) {
    DVLOG(1) << "Invalid registration URL provided: " << iter->second;
    return false;
  }

  return true;
}

bool VerifySettings(const gcm::GServicesSettings::SettingsMap& settings) {
  return VerifyCheckinInterval(settings) && VerifyMCSEndpoint(settings) &&
         VerifyCheckinURL(settings) && VerifyRegistrationURL(settings);
}

}  // namespace

namespace gcm {

// static
const base::TimeDelta GServicesSettings::MinimumCheckinInterval() {
  return base::TimeDelta::FromSeconds(kMinimumCheckinInterval);
}

// static
const GURL GServicesSettings::DefaultCheckinURL() {
  return GURL(kDefaultCheckinURL);
}

// static
std::string GServicesSettings::CalculateDigest(const SettingsMap& settings) {
  unsigned char hash[base::kSHA1Length];
  std::string data;
  for (SettingsMap::const_iterator iter = settings.begin();
       iter != settings.end();
       ++iter) {
    data += iter->first;
    data += '\0';
    data += iter->second;
    data += '\0';
  }
  base::SHA1HashBytes(
      reinterpret_cast<const unsigned char*>(&data[0]), data.size(), hash);
  std::string digest =
      kDigestVersionPrefix + base::HexEncode(hash, base::kSHA1Length);
  digest = StringToLowerASCII(digest);
  return digest;
}

GServicesSettings::GServicesSettings() : weak_ptr_factory_(this) {
  digest_ = CalculateDigest(settings_);
}

GServicesSettings::~GServicesSettings() {
}

bool GServicesSettings::UpdateFromCheckinResponse(
    const checkin_proto::AndroidCheckinResponse& checkin_response) {
  if (!checkin_response.has_settings_diff()) {
    DVLOG(1) << "Field settings_diff not set in response.";
    return false;
  }

  bool settings_diff = checkin_response.settings_diff();
  SettingsMap new_settings;
  // Only reuse the existing settings, if we are given a settings difference.
  if (settings_diff)
    new_settings = settings_map();

  for (int i = 0; i < checkin_response.setting_size(); ++i) {
    std::string name = checkin_response.setting(i).name();
    if (name.empty()) {
      DVLOG(1) << "Setting name is empty";
      return false;
    }

    if (settings_diff && name.find(kDeleteSettingPrefix) == 0) {
      std::string setting_to_delete =
          name.substr(arraysize(kDeleteSettingPrefix) - 1);
      new_settings.erase(setting_to_delete);
      DVLOG(1) << "Setting deleted: " << setting_to_delete;
    } else {
      std::string value = checkin_response.setting(i).value();
      new_settings[name] = value;
      DVLOG(1) << "New setting: '" << name << "' : '" << value << "'";
    }
  }

  if (!VerifySettings(new_settings))
    return false;

  settings_.swap(new_settings);
  digest_ = CalculateDigest(settings_);
  return true;
}

void GServicesSettings::UpdateFromLoadResult(
    const GCMStore::LoadResult& load_result) {
  // No need to try to update settings when load_result is empty.
  if (load_result.gservices_settings.empty())
    return;
  if (!VerifySettings(load_result.gservices_settings))
    return;
  std::string digest = CalculateDigest(load_result.gservices_settings);
  if (digest != load_result.gservices_digest) {
    DVLOG(1) << "G-services settings digest mismatch. "
             << "Expected digest: " << load_result.gservices_digest
             << ". Calculated digest is: " << digest;
    return;
  }

  settings_ = load_result.gservices_settings;
  digest_ = load_result.gservices_digest;
}

base::TimeDelta GServicesSettings::GetCheckinInterval() const {
  int64 checkin_interval = kMinimumCheckinInterval;
  SettingsMap::const_iterator iter = settings_.find(kCheckinIntervalKey);
  if (iter == settings_.end() ||
      !base::StringToInt64(iter->second, &checkin_interval)) {
    checkin_interval = kDefaultCheckinInterval;
  }

  if (checkin_interval < kMinimumCheckinInterval)
    checkin_interval = kMinimumCheckinInterval;

  return base::TimeDelta::FromSeconds(checkin_interval);
}

GURL GServicesSettings::GetCheckinURL() const {
  SettingsMap::const_iterator iter = settings_.find(kCheckinURLKey);
  if (iter == settings_.end() || iter->second.empty())
    return GURL(kDefaultCheckinURL);
  return GURL(iter->second);
}

GURL GServicesSettings::GetMCSMainEndpoint() const {
  // Get alternative hostname or use default.
  std::string mcs_hostname;
  SettingsMap::const_iterator iter = settings_.find(kMCSHostnameKey);
  if (iter != settings_.end() && !iter->second.empty())
    mcs_hostname = iter->second;
  else
    mcs_hostname = kDefaultMCSHostname;

  // Get alternative secure port or use defualt.
  int mcs_secure_port = 0;
  iter = settings_.find(kMCSSecurePortKey);
  if (iter == settings_.end() || iter->second.empty() ||
      !base::StringToInt(iter->second, &mcs_secure_port)) {
    mcs_secure_port = kDefaultMCSMainSecurePort;
  }

  // If constructed address makes sense use it.
  GURL mcs_endpoint(MakeMCSEndpoint(mcs_hostname, mcs_secure_port));
  if (mcs_endpoint.is_valid())
    return mcs_endpoint;

  // Otherwise use default settings.
  return GURL(MakeMCSEndpoint(kDefaultMCSHostname, kDefaultMCSMainSecurePort));
}

GURL GServicesSettings::GetMCSFallbackEndpoint() const {
  // Get alternative hostname or use default.
  std::string mcs_hostname;
  SettingsMap::const_iterator iter = settings_.find(kMCSHostnameKey);
  if (iter != settings_.end() && !iter->second.empty())
    mcs_hostname = iter->second;
  else
    mcs_hostname = kDefaultMCSHostname;

  // If constructed address makes sense use it.
  GURL mcs_endpoint(
      MakeMCSEndpoint(mcs_hostname, kDefaultMCSFallbackSecurePort));
  if (mcs_endpoint.is_valid())
    return mcs_endpoint;

  return GURL(
      MakeMCSEndpoint(kDefaultMCSHostname, kDefaultMCSFallbackSecurePort));
}

GURL GServicesSettings::GetRegistrationURL() const {
  SettingsMap::const_iterator iter = settings_.find(kRegistrationURLKey);
  if (iter == settings_.end() || iter->second.empty())
    return GURL(kDefaultRegistrationURL);
  return GURL(iter->second);
}

}  // namespace gcm
