// Copyright 2013 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/extension_set.h"

#include "base/callback.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
#include "url/origin.h"

namespace extensions {

namespace {

std::string GetExtensionIdByURL(const GURL& url) {
  if (url.SchemeIs(kExtensionScheme))
    return url.host();

  // Trying url::Origin is important to properly handle extension schemes inside
  // blob: and filesystem: URLs, which won't match the extension scheme check
  // above.
  url::Origin origin = url::Origin::Create(url);
  if (origin.scheme() == kExtensionScheme)
    return origin.host();

  return std::string();
}

}  // namespace

ExtensionSet::const_iterator::const_iterator() {}

ExtensionSet::const_iterator::const_iterator(const const_iterator& other)
    : it_(other.it_) {
}

ExtensionSet::const_iterator::const_iterator(ExtensionMap::const_iterator it)
    : it_(it) {
}

ExtensionSet::const_iterator::~const_iterator() {}

ExtensionSet::ExtensionSet() {
}

ExtensionSet::~ExtensionSet() {
}

size_t ExtensionSet::size() const {
  return extensions_.size();
}

bool ExtensionSet::is_empty() const {
  return extensions_.empty();
}

bool ExtensionSet::Contains(const std::string& extension_id) const {
  return extensions_.find(extension_id) != extensions_.end();
}

bool ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) {
  bool was_present = base::ContainsKey(extensions_, extension->id());
  extensions_[extension->id()] = extension;
  return !was_present;
}

bool ExtensionSet::InsertAll(const ExtensionSet& extensions) {
  size_t before = size();
  for (ExtensionSet::const_iterator iter = extensions.begin();
       iter != extensions.end(); ++iter) {
    Insert(*iter);
  }
  return size() != before;
}

bool ExtensionSet::Remove(const std::string& id) {
  return extensions_.erase(id) > 0;
}

void ExtensionSet::Clear() {
  extensions_.clear();
}

std::string ExtensionSet::GetExtensionOrAppIDByURL(const GURL& url) const {
  std::string extension_id = GetExtensionIdByURL(url);
  if (!extension_id.empty())
    return extension_id;

  // GetHostedAppByURL already supports filesystem: URLs (via MatchesURL).
  // TODO(crbug/852162): Add support for blob: URLs in MatchesURL.
  const Extension* extension = GetHostedAppByURL(url);
  if (!extension)
    return std::string();

  return extension->id();
}

const Extension* ExtensionSet::GetExtensionOrAppByURL(const GURL& url) const {
  std::string extension_id = GetExtensionIdByURL(url);
  if (!extension_id.empty())
    return GetByID(extension_id);

  // GetHostedAppByURL already supports filesystem: URLs (via MatchesURL).
  // TODO(crbug/852162): Add support for blob: URLs in MatchesURL.
  return GetHostedAppByURL(url);
}

const Extension* ExtensionSet::GetAppByURL(const GURL& url) const {
  const Extension* extension = GetExtensionOrAppByURL(url);
  return (extension && extension->is_app()) ? extension : NULL;
}

const Extension* ExtensionSet::GetHostedAppByURL(const GURL& url) const {
  for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) {
    if (iter->second->web_extent().MatchesURL(url))
      return iter->second.get();
  }

  return NULL;
}

const Extension* ExtensionSet::GetHostedAppByOverlappingWebExtent(
    const URLPatternSet& extent) const {
  for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) {
    if (iter->second->web_extent().OverlapsWith(extent))
      return iter->second.get();
  }

  return NULL;
}

bool ExtensionSet::InSameExtent(const GURL& old_url,
                                const GURL& new_url) const {
  return GetExtensionOrAppByURL(old_url) ==
      GetExtensionOrAppByURL(new_url);
}

const Extension* ExtensionSet::GetByID(const std::string& id) const {
  auto i = extensions_.find(id);
  if (i != extensions_.end())
    return i->second.get();
  else
    return NULL;
}

ExtensionIdSet ExtensionSet::GetIDs() const {
  ExtensionIdSet ids;
  for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) {
    ids.insert(it->first);
  }
  return ids;
}

bool ExtensionSet::ExtensionBindingsAllowed(const GURL& url) const {
  if (url.SchemeIs(kExtensionScheme))
    return true;

  for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) {
    if (it->second->location() == Manifest::COMPONENT &&
        it->second->web_extent().MatchesURL(url))
      return true;
  }

  return false;
}

}  // namespace extensions
