1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/common/extension_set.h"
6
7#include "base/callback.h"
8#include "base/logging.h"
9#include "base/stl_util.h"
10#include "extensions/common/constants.h"
11#include "extensions/common/extension.h"
12#include "extensions/common/manifest_handlers/sandboxed_page_info.h"
13
14namespace extensions {
15
16ExtensionSet::const_iterator::const_iterator() {}
17
18ExtensionSet::const_iterator::const_iterator(const const_iterator& other)
19    : it_(other.it_) {
20}
21
22ExtensionSet::const_iterator::const_iterator(ExtensionMap::const_iterator it)
23    : it_(it) {
24}
25
26ExtensionSet::const_iterator::~const_iterator() {}
27
28ExtensionSet::ExtensionSet() {
29}
30
31ExtensionSet::~ExtensionSet() {
32}
33
34size_t ExtensionSet::size() const {
35  return extensions_.size();
36}
37
38bool ExtensionSet::is_empty() const {
39  return extensions_.empty();
40}
41
42bool ExtensionSet::Contains(const std::string& extension_id) const {
43  return extensions_.find(extension_id) != extensions_.end();
44}
45
46bool ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) {
47  bool was_present = ContainsKey(extensions_, extension->id());
48  extensions_[extension->id()] = extension;
49  if (!was_present && !modification_callback_.is_null())
50    modification_callback_.Run(GetIDs());
51  return !was_present;
52}
53
54bool ExtensionSet::InsertAll(const ExtensionSet& extensions) {
55  size_t before = size();
56  for (ExtensionSet::const_iterator iter = extensions.begin();
57       iter != extensions.end(); ++iter) {
58    Insert(*iter);
59  }
60  return size() != before;
61}
62
63bool ExtensionSet::Remove(const std::string& id) {
64  bool was_present = extensions_.erase(id) > 0;
65  if (was_present && !modification_callback_.is_null())
66    modification_callback_.Run(GetIDs());
67  return was_present;
68}
69
70void ExtensionSet::Clear() {
71  extensions_.clear();
72}
73
74std::string ExtensionSet::GetExtensionOrAppIDByURL(const GURL& url) const {
75  if (url.SchemeIs(kExtensionScheme))
76    return url.host();
77
78  const Extension* extension = GetHostedAppByURL(url);
79  if (!extension)
80    return std::string();
81
82  return extension->id();
83}
84
85const Extension* ExtensionSet::GetExtensionOrAppByURL(const GURL& url) const {
86  if (url.SchemeIs(kExtensionScheme))
87    return GetByID(url.host());
88
89  return GetHostedAppByURL(url);
90}
91
92const Extension* ExtensionSet::GetAppByURL(const GURL& url) const {
93  const Extension* extension = GetExtensionOrAppByURL(url);
94  return (extension && extension->is_app()) ? extension : NULL;
95}
96
97const Extension* ExtensionSet::GetHostedAppByURL(const GURL& url) const {
98  for (ExtensionMap::const_iterator iter = extensions_.begin();
99       iter != extensions_.end(); ++iter) {
100    if (iter->second->web_extent().MatchesURL(url))
101      return iter->second.get();
102  }
103
104  return NULL;
105}
106
107const Extension* ExtensionSet::GetHostedAppByOverlappingWebExtent(
108    const URLPatternSet& extent) const {
109  for (ExtensionMap::const_iterator iter = extensions_.begin();
110       iter != extensions_.end(); ++iter) {
111    if (iter->second->web_extent().OverlapsWith(extent))
112      return iter->second.get();
113  }
114
115  return NULL;
116}
117
118bool ExtensionSet::InSameExtent(const GURL& old_url,
119                                const GURL& new_url) const {
120  return GetExtensionOrAppByURL(old_url) ==
121      GetExtensionOrAppByURL(new_url);
122}
123
124const Extension* ExtensionSet::GetByID(const std::string& id) const {
125  ExtensionMap::const_iterator i = extensions_.find(id);
126  if (i != extensions_.end())
127    return i->second.get();
128  else
129    return NULL;
130}
131
132ExtensionIdSet ExtensionSet::GetIDs() const {
133  ExtensionIdSet ids;
134  for (ExtensionMap::const_iterator it = extensions_.begin();
135       it != extensions_.end(); ++it) {
136    ids.insert(it->first);
137  }
138  return ids;
139}
140
141bool ExtensionSet::ExtensionBindingsAllowed(const GURL& url) const {
142  if (url.SchemeIs(kExtensionScheme))
143    return true;
144
145  for (ExtensionMap::const_iterator it = extensions_.begin();
146       it != extensions_.end(); ++it) {
147    if (it->second->location() == Manifest::COMPONENT &&
148        it->second->web_extent().MatchesURL(url))
149      return true;
150  }
151
152  return false;
153}
154
155}  // namespace extensions
156