// Copyright (c) 2012 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 "chrome/common/extensions/features/simple_feature.h"

#include <map>
#include <vector>

#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/features/feature_channel.h"

using chrome::VersionInfo;

namespace extensions {

namespace {

struct Mappings {
  Mappings() {
    extension_types["extension"] = Manifest::TYPE_EXTENSION;
    extension_types["theme"] = Manifest::TYPE_THEME;
    extension_types["legacy_packaged_app"] = Manifest::TYPE_LEGACY_PACKAGED_APP;
    extension_types["hosted_app"] = Manifest::TYPE_HOSTED_APP;
    extension_types["platform_app"] = Manifest::TYPE_PLATFORM_APP;
    extension_types["shared_module"] = Manifest::TYPE_SHARED_MODULE;

    contexts["blessed_extension"] = Feature::BLESSED_EXTENSION_CONTEXT;
    contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT;
    contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT;
    contexts["web_page"] = Feature::WEB_PAGE_CONTEXT;

    locations["component"] = Feature::COMPONENT_LOCATION;

    platforms["chromeos"] = Feature::CHROMEOS_PLATFORM;

    channels["trunk"] = VersionInfo::CHANNEL_UNKNOWN;
    channels["canary"] = VersionInfo::CHANNEL_CANARY;
    channels["dev"] = VersionInfo::CHANNEL_DEV;
    channels["beta"] = VersionInfo::CHANNEL_BETA;
    channels["stable"] = VersionInfo::CHANNEL_STABLE;
  }

  std::map<std::string, Manifest::Type> extension_types;
  std::map<std::string, Feature::Context> contexts;
  std::map<std::string, Feature::Location> locations;
  std::map<std::string, Feature::Platform> platforms;
  std::map<std::string, VersionInfo::Channel> channels;
};

base::LazyInstance<Mappings> g_mappings = LAZY_INSTANCE_INITIALIZER;

std::string GetChannelName(VersionInfo::Channel channel) {
  typedef std::map<std::string, VersionInfo::Channel> ChannelsMap;
  ChannelsMap channels = g_mappings.Get().channels;
  for (ChannelsMap::iterator i = channels.begin(); i != channels.end(); ++i) {
    if (i->second == channel)
      return i->first;
  }
  NOTREACHED();
  return "unknown";
}

// TODO(aa): Can we replace all this manual parsing with JSON schema stuff?

void ParseSet(const base::DictionaryValue* value,
              const std::string& property,
              std::set<std::string>* set) {
  const base::ListValue* list_value = NULL;
  if (!value->GetList(property, &list_value))
    return;

  set->clear();
  for (size_t i = 0; i < list_value->GetSize(); ++i) {
    std::string str_val;
    CHECK(list_value->GetString(i, &str_val)) << property << " " << i;
    set->insert(str_val);
  }
}

template<typename T>
void ParseEnum(const std::string& string_value,
               T* enum_value,
               const std::map<std::string, T>& mapping) {
  typename std::map<std::string, T>::const_iterator iter =
      mapping.find(string_value);
  CHECK(iter != mapping.end()) << string_value;
  *enum_value = iter->second;
}

template<typename T>
void ParseEnum(const base::DictionaryValue* value,
               const std::string& property,
               T* enum_value,
               const std::map<std::string, T>& mapping) {
  std::string string_value;
  if (!value->GetString(property, &string_value))
    return;

  ParseEnum(string_value, enum_value, mapping);
}

template<typename T>
void ParseEnumSet(const base::DictionaryValue* value,
                  const std::string& property,
                  std::set<T>* enum_set,
                  const std::map<std::string, T>& mapping) {
  if (!value->HasKey(property))
    return;

  enum_set->clear();

  std::string property_string;
  if (value->GetString(property, &property_string)) {
    if (property_string == "all") {
      for (typename std::map<std::string, T>::const_iterator j =
               mapping.begin(); j != mapping.end(); ++j) {
        enum_set->insert(j->second);
      }
    }
    return;
  }

  std::set<std::string> string_set;
  ParseSet(value, property, &string_set);
  for (std::set<std::string>::iterator iter = string_set.begin();
       iter != string_set.end(); ++iter) {
    T enum_value = static_cast<T>(0);
    ParseEnum(*iter, &enum_value, mapping);
    enum_set->insert(enum_value);
  }
}

void ParseURLPatterns(const base::DictionaryValue* value,
                      const std::string& key,
                      URLPatternSet* set) {
  const base::ListValue* matches = NULL;
  if (value->GetList(key, &matches)) {
    set->ClearPatterns();
    for (size_t i = 0; i < matches->GetSize(); ++i) {
      std::string pattern;
      CHECK(matches->GetString(i, &pattern));
      set->AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern));
    }
  }
}

// Gets a human-readable name for the given extension type.
std::string GetDisplayTypeName(Manifest::Type type) {
  switch (type) {
    case Manifest::TYPE_UNKNOWN:
      return "unknown";
    case Manifest::TYPE_EXTENSION:
      return "extension";
    case Manifest::TYPE_HOSTED_APP:
      return "hosted app";
    case Manifest::TYPE_LEGACY_PACKAGED_APP:
      return "legacy packaged app";
    case Manifest::TYPE_PLATFORM_APP:
      return "packaged app";
    case Manifest::TYPE_THEME:
      return "theme";
    case Manifest::TYPE_USER_SCRIPT:
      return "user script";
    case Manifest::TYPE_SHARED_MODULE:
      return "shared module";
  }

  NOTREACHED();
  return std::string();
}

std::string HashExtensionId(const std::string& extension_id) {
  const std::string id_hash = base::SHA1HashString(extension_id);
  DCHECK(id_hash.length() == base::kSHA1Length);
  return base::HexEncode(id_hash.c_str(), id_hash.length());
}

}  // namespace

SimpleFeature::SimpleFeature()
  : location_(UNSPECIFIED_LOCATION),
    platform_(UNSPECIFIED_PLATFORM),
    min_manifest_version_(0),
    max_manifest_version_(0),
    channel_(VersionInfo::CHANNEL_UNKNOWN),
    has_parent_(false),
    channel_has_been_set_(false) {
}

SimpleFeature::SimpleFeature(const SimpleFeature& other)
    : whitelist_(other.whitelist_),
      extension_types_(other.extension_types_),
      contexts_(other.contexts_),
      matches_(other.matches_),
      location_(other.location_),
      platform_(other.platform_),
      min_manifest_version_(other.min_manifest_version_),
      max_manifest_version_(other.max_manifest_version_),
      channel_(other.channel_),
      has_parent_(other.has_parent_),
      channel_has_been_set_(other.channel_has_been_set_) {
}

SimpleFeature::~SimpleFeature() {
}

bool SimpleFeature::Equals(const SimpleFeature& other) const {
  return whitelist_ == other.whitelist_ &&
      extension_types_ == other.extension_types_ &&
      contexts_ == other.contexts_ &&
      matches_ == other.matches_ &&
      location_ == other.location_ &&
      platform_ == other.platform_ &&
      min_manifest_version_ == other.min_manifest_version_ &&
      max_manifest_version_ == other.max_manifest_version_ &&
      channel_ == other.channel_ &&
      has_parent_ == other.has_parent_ &&
      channel_has_been_set_ == other.channel_has_been_set_;
}

std::string SimpleFeature::Parse(const base::DictionaryValue* value) {
  ParseURLPatterns(value, "matches", &matches_);
  ParseSet(value, "whitelist", &whitelist_);
  ParseSet(value, "dependencies", &dependencies_);
  ParseEnumSet<Manifest::Type>(value, "extension_types", &extension_types_,
                                g_mappings.Get().extension_types);
  ParseEnumSet<Context>(value, "contexts", &contexts_,
                        g_mappings.Get().contexts);
  ParseEnum<Location>(value, "location", &location_,
                      g_mappings.Get().locations);
  ParseEnum<Platform>(value, "platform", &platform_,
                      g_mappings.Get().platforms);
  value->GetInteger("min_manifest_version", &min_manifest_version_);
  value->GetInteger("max_manifest_version", &max_manifest_version_);
  ParseEnum<VersionInfo::Channel>(
      value, "channel", &channel_,
      g_mappings.Get().channels);

  no_parent_ = false;
  value->GetBoolean("noparent", &no_parent_);

  // The "trunk" channel uses VersionInfo::CHANNEL_UNKNOWN, so we need to keep
  // track of whether the channel has been set or not separately.
  channel_has_been_set_ |= value->HasKey("channel");
  if (!channel_has_been_set_ && dependencies_.empty())
    return name() + ": Must supply a value for channel or dependencies.";

  if (matches_.is_empty() && contexts_.count(WEB_PAGE_CONTEXT) != 0) {
    return name() + ": Allowing web_page contexts requires supplying a value " +
        "for matches.";
  }

  return std::string();
}

Feature::Availability SimpleFeature::IsAvailableToManifest(
    const std::string& extension_id,
    Manifest::Type type,
    Location location,
    int manifest_version,
    Platform platform) const {
  // Component extensions can access any feature.
  if (location == COMPONENT_LOCATION)
    return CreateAvailability(IS_AVAILABLE, type);

  if (!whitelist_.empty()) {
    if (!IsIdInWhitelist(extension_id)) {
      // TODO(aa): This is gross. There should be a better way to test the
      // whitelist.
      CommandLine* command_line = CommandLine::ForCurrentProcess();
      if (!command_line->HasSwitch(switches::kWhitelistedExtensionID))
        return CreateAvailability(NOT_FOUND_IN_WHITELIST, type);

      std::string whitelist_switch_value =
          CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
              switches::kWhitelistedExtensionID);
      if (extension_id != whitelist_switch_value)
        return CreateAvailability(NOT_FOUND_IN_WHITELIST, type);
    }
  }

  // HACK(kalman): user script -> extension. Solve this in a more generic way
  // when we compile feature files.
  Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ?
      Manifest::TYPE_EXTENSION : type;
  if (!extension_types_.empty() &&
      extension_types_.find(type_to_check) == extension_types_.end()) {
    return CreateAvailability(INVALID_TYPE, type);
  }

  if (location_ != UNSPECIFIED_LOCATION && location_ != location)
    return CreateAvailability(INVALID_LOCATION, type);

  if (platform_ != UNSPECIFIED_PLATFORM && platform_ != platform)
    return CreateAvailability(INVALID_PLATFORM, type);

  if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_)
    return CreateAvailability(INVALID_MIN_MANIFEST_VERSION, type);

  if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_)
    return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type);

  if (channel_has_been_set_ && channel_ < GetCurrentChannel())
    return CreateAvailability(UNSUPPORTED_CHANNEL, type);

  return CreateAvailability(IS_AVAILABLE, type);
}

Feature::Availability SimpleFeature::IsAvailableToContext(
    const Extension* extension,
    SimpleFeature::Context context,
    const GURL& url,
    SimpleFeature::Platform platform) const {
  if (extension) {
    Availability result = IsAvailableToManifest(
        extension->id(),
        extension->GetType(),
        ConvertLocation(extension->location()),
        extension->manifest_version(),
        platform);
    if (!result.is_available())
      return result;
  }

  if (!contexts_.empty() && contexts_.find(context) == contexts_.end()) {
    return extension ?
        CreateAvailability(INVALID_CONTEXT, extension->GetType()) :
        CreateAvailability(INVALID_CONTEXT);
  }

  if (!matches_.is_empty() && !matches_.MatchesURL(url))
    return CreateAvailability(INVALID_URL, url);

  return CreateAvailability(IS_AVAILABLE);
}

std::string SimpleFeature::GetAvailabilityMessage(
    AvailabilityResult result, Manifest::Type type, const GURL& url) const {
  switch (result) {
    case IS_AVAILABLE:
      return std::string();
    case NOT_FOUND_IN_WHITELIST:
      return base::StringPrintf(
          "'%s' is not allowed for specified extension ID.",
          name().c_str());
    case INVALID_URL:
      return base::StringPrintf("'%s' is not allowed on %s.",
                                name().c_str(), url.spec().c_str());
    case INVALID_TYPE: {
      std::string allowed_type_names;
      // Turn the set of allowed types into a vector so that it's easier to
      // inject the appropriate separator into the display string.
      std::vector<Manifest::Type> extension_types(
          extension_types_.begin(), extension_types_.end());
      for (size_t i = 0; i < extension_types.size(); i++) {
        // Pluralize type name.
        allowed_type_names += GetDisplayTypeName(extension_types[i]) + "s";
        if (i == extension_types_.size() - 2) {
          allowed_type_names += " and ";
        } else if (i != extension_types_.size() - 1) {
          allowed_type_names += ", ";
        }
      }

      return base::StringPrintf(
          "'%s' is only allowed for %s, and this is a %s.",
          name().c_str(),
          allowed_type_names.c_str(),
          GetDisplayTypeName(type).c_str());
    }
    case INVALID_CONTEXT:
      return base::StringPrintf(
          "'%s' is not allowed for specified context type content script, "
          " extension page, web page, etc.).",
          name().c_str());
    case INVALID_LOCATION:
      return base::StringPrintf(
          "'%s' is not allowed for specified install location.",
          name().c_str());
    case INVALID_PLATFORM:
      return base::StringPrintf(
          "'%s' is not allowed for specified platform.",
          name().c_str());
    case INVALID_MIN_MANIFEST_VERSION:
      return base::StringPrintf(
          "'%s' requires manifest version of at least %d.",
          name().c_str(),
          min_manifest_version_);
    case INVALID_MAX_MANIFEST_VERSION:
      return base::StringPrintf(
          "'%s' requires manifest version of %d or lower.",
          name().c_str(),
          max_manifest_version_);
    case NOT_PRESENT:
      return base::StringPrintf(
          "'%s' requires a different Feature that is not present.",
          name().c_str());
    case UNSUPPORTED_CHANNEL:
      return base::StringPrintf(
          "'%s' requires Google Chrome %s channel or newer, and this is the "
              "%s channel.",
          name().c_str(),
          GetChannelName(channel_).c_str(),
          GetChannelName(GetCurrentChannel()).c_str());
  }

  NOTREACHED();
  return std::string();
}

Feature::Availability SimpleFeature::CreateAvailability(
    AvailabilityResult result) const {
  return Availability(
      result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL()));
}

Feature::Availability SimpleFeature::CreateAvailability(
    AvailabilityResult result, Manifest::Type type) const {
  return Availability(result, GetAvailabilityMessage(result, type, GURL()));
}

Feature::Availability SimpleFeature::CreateAvailability(
    AvailabilityResult result,
    const GURL& url) const {
  return Availability(
      result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, url));
}

std::set<Feature::Context>* SimpleFeature::GetContexts() {
  return &contexts_;
}

bool SimpleFeature::IsInternal() const {
  NOTREACHED();
  return false;
}

bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id) const {
  return IsIdInWhitelist(extension_id, whitelist_);
}

// static
bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id,
                                    const std::set<std::string>& whitelist) {
  // Belt-and-suspenders philosophy here. We should be pretty confident by this
  // point that we've validated the extension ID format, but in case something
  // slips through, we avoid a class of attack where creative ID manipulation
  // leads to hash collisions.
  if (extension_id.length() != 32)  // 128 bits / 4 = 32 mpdecimal characters
    return false;

  if (whitelist.find(extension_id) != whitelist.end() ||
      whitelist.find(HashExtensionId(extension_id)) != whitelist.end()) {
    return true;
  }

  return false;
}

}  // namespace extensions
