// 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 "extensions/common/manifest_handlers/externally_connectable.h"

#include <algorithm>

#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/api/extensions_manifest_types.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/permissions_parser.h"
#include "extensions/common/permissions/api_permission_set.h"
#include "extensions/common/url_pattern.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h"

namespace rcd = net::registry_controlled_domains;

namespace extensions {

namespace externally_connectable_errors {
const char kErrorInvalidMatchPattern[] = "Invalid match pattern '*'";
const char kErrorInvalidId[] = "Invalid ID '*'";
const char kErrorNothingSpecified[] =
    "'externally_connectable' specifies neither 'matches' nor 'ids'; "
    "nothing will be able to connect";
const char kErrorTopLevelDomainsNotAllowed[] =
    "\"*\" is an effective top level domain for which wildcard subdomains such "
    "as \"*\" are not allowed";
const char kErrorWildcardHostsNotAllowed[] =
    "Wildcard domain patterns such as \"*\" are not allowed";
}  // namespace externally_connectable_errors

namespace keys = extensions::manifest_keys;
namespace errors = externally_connectable_errors;
using core_api::extensions_manifest_types::ExternallyConnectable;

namespace {

const char kAllIds[] = "*";

template <typename T>
std::vector<T> Sorted(const std::vector<T>& in) {
  std::vector<T> out = in;
  std::sort(out.begin(), out.end());
  return out;
}

}  // namespace

ExternallyConnectableHandler::ExternallyConnectableHandler() {
}

ExternallyConnectableHandler::~ExternallyConnectableHandler() {
}

bool ExternallyConnectableHandler::Parse(Extension* extension,
                                         base::string16* error) {
  const base::Value* externally_connectable = NULL;
  CHECK(extension->manifest()->Get(keys::kExternallyConnectable,
                                   &externally_connectable));
  std::vector<InstallWarning> install_warnings;
  scoped_ptr<ExternallyConnectableInfo> info =
      ExternallyConnectableInfo::FromValue(*externally_connectable,
                                           &install_warnings,
                                           error);
  if (!info)
    return false;
  if (!info->matches.is_empty()) {
    PermissionsParser::AddAPIPermission(extension,
                                        APIPermission::kWebConnectable);
  }
  extension->AddInstallWarnings(install_warnings);
  extension->SetManifestData(keys::kExternallyConnectable, info.release());
  return true;
}

const std::vector<std::string> ExternallyConnectableHandler::Keys() const {
  return SingleKey(keys::kExternallyConnectable);
}

// static
ExternallyConnectableInfo* ExternallyConnectableInfo::Get(
    const Extension* extension) {
  return static_cast<ExternallyConnectableInfo*>(
      extension->GetManifestData(keys::kExternallyConnectable));
}

// static
scoped_ptr<ExternallyConnectableInfo> ExternallyConnectableInfo::FromValue(
    const base::Value& value,
    std::vector<InstallWarning>* install_warnings,
    base::string16* error) {
  scoped_ptr<ExternallyConnectable> externally_connectable =
      ExternallyConnectable::FromValue(value, error);
  if (!externally_connectable)
    return scoped_ptr<ExternallyConnectableInfo>();

  URLPatternSet matches;

  if (externally_connectable->matches) {
    for (std::vector<std::string>::iterator it =
             externally_connectable->matches->begin();
         it != externally_connectable->matches->end();
         ++it) {
      // Safe to use SCHEME_ALL here; externally_connectable gives a page ->
      // extension communication path, not the other way.
      URLPattern pattern(URLPattern::SCHEME_ALL);
      if (pattern.Parse(*it) != URLPattern::PARSE_SUCCESS) {
        *error = ErrorUtils::FormatErrorMessageUTF16(
            errors::kErrorInvalidMatchPattern, *it);
        return scoped_ptr<ExternallyConnectableInfo>();
      }

      // Wildcard hosts are not allowed.
      if (pattern.host().empty()) {
        // Warning not error for forwards compatibility.
        install_warnings->push_back(
            InstallWarning(ErrorUtils::FormatErrorMessage(
                               errors::kErrorWildcardHostsNotAllowed, *it),
                           keys::kExternallyConnectable,
                           *it));
        continue;
      }

      // Wildcards on subdomains of a TLD are not allowed.
      size_t registry_length = rcd::GetRegistryLength(
          pattern.host(),
          // This means that things that look like TLDs - the foobar in
          // http://google.foobar - count as TLDs.
          rcd::INCLUDE_UNKNOWN_REGISTRIES,
          // This means that effective TLDs like appspot.com count as TLDs;
          // codereview.appspot.com and evil.appspot.com are different.
          rcd::INCLUDE_PRIVATE_REGISTRIES);

      if (registry_length == std::string::npos) {
        // The URL parsing combined with host().empty() should have caught this.
        NOTREACHED() << *it;
        *error = ErrorUtils::FormatErrorMessageUTF16(
            errors::kErrorInvalidMatchPattern, *it);
        return scoped_ptr<ExternallyConnectableInfo>();
      }

      // Broad match patterns like "*.com", "*.co.uk", and even "*.appspot.com"
      // are not allowed. However just "appspot.com" is ok.
      if (registry_length == 0 && pattern.match_subdomains()) {
        // Warning not error for forwards compatibility.
        install_warnings->push_back(
            InstallWarning(ErrorUtils::FormatErrorMessage(
                               errors::kErrorTopLevelDomainsNotAllowed,
                               pattern.host().c_str(),
                               *it),
                           keys::kExternallyConnectable,
                           *it));
        continue;
      }

      matches.AddPattern(pattern);
    }
  }

  std::vector<std::string> ids;
  bool all_ids = false;

  if (externally_connectable->ids) {
    for (std::vector<std::string>::iterator it =
             externally_connectable->ids->begin();
         it != externally_connectable->ids->end();
         ++it) {
      if (*it == kAllIds) {
        all_ids = true;
      } else if (Extension::IdIsValid(*it)) {
        ids.push_back(*it);
      } else {
        *error =
            ErrorUtils::FormatErrorMessageUTF16(errors::kErrorInvalidId, *it);
        return scoped_ptr<ExternallyConnectableInfo>();
      }
    }
  }

  if (!externally_connectable->matches && !externally_connectable->ids) {
    install_warnings->push_back(InstallWarning(errors::kErrorNothingSpecified,
                                               keys::kExternallyConnectable));
  }

  bool accepts_tls_channel_id =
      externally_connectable->accepts_tls_channel_id.get() &&
      *externally_connectable->accepts_tls_channel_id;
  return make_scoped_ptr(new ExternallyConnectableInfo(
      matches, ids, all_ids, accepts_tls_channel_id));
}

ExternallyConnectableInfo::~ExternallyConnectableInfo() {
}

ExternallyConnectableInfo::ExternallyConnectableInfo(
    const URLPatternSet& matches,
    const std::vector<std::string>& ids,
    bool all_ids,
    bool accepts_tls_channel_id)
    : matches(matches),
      ids(Sorted(ids)),
      all_ids(all_ids),
      accepts_tls_channel_id(accepts_tls_channel_id) {
}

bool ExternallyConnectableInfo::IdCanConnect(const std::string& id) {
  if (all_ids)
    return true;
  DCHECK(base::STLIsSorted(ids));
  return std::binary_search(ids.begin(), ids.end(), id);
}

}  // namespace extensions
