Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / extensions / common / permissions / permission_set.cc
blob65236ac45781c0d2e11867a94c959789247ec0ee
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.
5 #include "extensions/common/permissions/permission_set.h"
7 #include "extensions/common/permissions/permissions_info.h"
8 #include "extensions/common/url_pattern.h"
9 #include "url/gurl.h"
11 namespace extensions {
13 namespace {
15 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) {
16 DCHECK(out);
17 for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) {
18 URLPattern p = *i;
19 p.SetPath("/*");
20 out->AddPattern(p);
24 } // namespace
27 // PermissionSet
30 PermissionSet::PermissionSet() : should_warn_all_hosts_(UNINITIALIZED) {}
32 PermissionSet::PermissionSet(
33 const APIPermissionSet& apis,
34 const ManifestPermissionSet& manifest_permissions,
35 const URLPatternSet& explicit_hosts,
36 const URLPatternSet& scriptable_hosts)
37 : apis_(apis),
38 manifest_permissions_(manifest_permissions),
39 scriptable_hosts_(scriptable_hosts),
40 should_warn_all_hosts_(UNINITIALIZED) {
41 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
42 InitImplicitPermissions();
43 InitEffectiveHosts();
46 // static
47 PermissionSet* PermissionSet::CreateDifference(
48 const PermissionSet* set1,
49 const PermissionSet* set2) {
50 scoped_refptr<PermissionSet> empty = new PermissionSet();
51 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
52 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
54 APIPermissionSet apis;
55 APIPermissionSet::Difference(set1_safe->apis(), set2_safe->apis(), &apis);
57 ManifestPermissionSet manifest_permissions;
58 ManifestPermissionSet::Difference(set1_safe->manifest_permissions(),
59 set2_safe->manifest_permissions(),
60 &manifest_permissions);
62 URLPatternSet explicit_hosts;
63 URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
64 set2_safe->explicit_hosts(),
65 &explicit_hosts);
67 URLPatternSet scriptable_hosts;
68 URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
69 set2_safe->scriptable_hosts(),
70 &scriptable_hosts);
72 return new PermissionSet(apis, manifest_permissions,
73 explicit_hosts, scriptable_hosts);
76 // static
77 PermissionSet* PermissionSet::CreateIntersection(
78 const PermissionSet* set1,
79 const PermissionSet* set2) {
80 scoped_refptr<PermissionSet> empty = new PermissionSet();
81 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
82 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
84 APIPermissionSet apis;
85 APIPermissionSet::Intersection(set1_safe->apis(), set2_safe->apis(), &apis);
87 ManifestPermissionSet manifest_permissions;
88 ManifestPermissionSet::Intersection(set1_safe->manifest_permissions(),
89 set2_safe->manifest_permissions(),
90 &manifest_permissions);
92 URLPatternSet explicit_hosts;
93 URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
94 set2_safe->explicit_hosts(),
95 &explicit_hosts);
97 URLPatternSet scriptable_hosts;
98 URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
99 set2_safe->scriptable_hosts(),
100 &scriptable_hosts);
102 return new PermissionSet(apis, manifest_permissions,
103 explicit_hosts, scriptable_hosts);
106 // static
107 PermissionSet* PermissionSet::CreateUnion(
108 const PermissionSet* set1,
109 const PermissionSet* set2) {
110 scoped_refptr<PermissionSet> empty = new PermissionSet();
111 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
112 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
114 APIPermissionSet apis;
115 APIPermissionSet::Union(set1_safe->apis(), set2_safe->apis(), &apis);
117 ManifestPermissionSet manifest_permissions;
118 ManifestPermissionSet::Union(set1_safe->manifest_permissions(),
119 set2_safe->manifest_permissions(),
120 &manifest_permissions);
122 URLPatternSet explicit_hosts;
123 URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
124 set2_safe->explicit_hosts(),
125 &explicit_hosts);
127 URLPatternSet scriptable_hosts;
128 URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
129 set2_safe->scriptable_hosts(),
130 &scriptable_hosts);
132 return new PermissionSet(apis, manifest_permissions,
133 explicit_hosts, scriptable_hosts);
136 bool PermissionSet::operator==(
137 const PermissionSet& rhs) const {
138 return apis_ == rhs.apis_ &&
139 manifest_permissions_ == rhs.manifest_permissions_ &&
140 scriptable_hosts_ == rhs.scriptable_hosts_ &&
141 explicit_hosts_ == rhs.explicit_hosts_;
144 bool PermissionSet::Contains(const PermissionSet& set) const {
145 return apis_.Contains(set.apis()) &&
146 manifest_permissions_.Contains(set.manifest_permissions()) &&
147 explicit_hosts().Contains(set.explicit_hosts()) &&
148 scriptable_hosts().Contains(set.scriptable_hosts());
151 std::set<std::string> PermissionSet::GetAPIsAsStrings() const {
152 std::set<std::string> apis_str;
153 for (APIPermissionSet::const_iterator i = apis_.begin();
154 i != apis_.end(); ++i) {
155 apis_str.insert(i->name());
157 return apis_str;
160 bool PermissionSet::IsEmpty() const {
161 // Not default if any host permissions are present.
162 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
163 return false;
165 // Or if it has no api permissions.
166 return apis().empty() && manifest_permissions().empty();
169 bool PermissionSet::HasAPIPermission(
170 APIPermission::ID id) const {
171 return apis().find(id) != apis().end();
174 bool PermissionSet::HasAPIPermission(const std::string& permission_name) const {
175 const APIPermissionInfo* permission =
176 PermissionsInfo::GetInstance()->GetByName(permission_name);
177 // Ensure our PermissionsProvider is aware of this permission.
178 CHECK(permission) << permission_name;
179 return (permission && apis_.count(permission->id()));
182 bool PermissionSet::CheckAPIPermission(APIPermission::ID permission) const {
183 return CheckAPIPermissionWithParam(permission, NULL);
186 bool PermissionSet::CheckAPIPermissionWithParam(
187 APIPermission::ID permission,
188 const APIPermission::CheckParam* param) const {
189 APIPermissionSet::const_iterator iter = apis().find(permission);
190 if (iter == apis().end())
191 return false;
192 return iter->Check(param);
195 bool PermissionSet::HasExplicitAccessToOrigin(
196 const GURL& origin) const {
197 return explicit_hosts().MatchesURL(origin);
200 bool PermissionSet::HasScriptableAccessToURL(
201 const GURL& origin) const {
202 // We only need to check our host list to verify access. The host list should
203 // already reflect any special rules (such as chrome://favicon, all hosts
204 // access, etc.).
205 return scriptable_hosts().MatchesURL(origin);
208 bool PermissionSet::HasEffectiveAccessToAllHosts() const {
209 // There are two ways this set can have effective access to all hosts:
210 // 1) it has an <all_urls> URL pattern.
211 // 2) it has a named permission with implied full URL access.
212 if (effective_hosts().MatchesAllURLs())
213 return true;
215 for (APIPermissionSet::const_iterator i = apis().begin();
216 i != apis().end(); ++i) {
217 if (i->info()->implies_full_url_access())
218 return true;
220 return false;
223 bool PermissionSet::ShouldWarnAllHosts() const {
224 if (should_warn_all_hosts_ == UNINITIALIZED)
225 InitShouldWarnAllHosts();
226 return should_warn_all_hosts_ == WARN_ALL_HOSTS;
229 bool PermissionSet::HasEffectiveAccessToURL(const GURL& url) const {
230 return effective_hosts().MatchesURL(url);
233 bool PermissionSet::HasEffectiveFullAccess() const {
234 for (APIPermissionSet::const_iterator i = apis().begin();
235 i != apis().end(); ++i) {
236 if (i->info()->implies_full_access())
237 return true;
239 return false;
242 PermissionSet::~PermissionSet() {}
244 void PermissionSet::InitImplicitPermissions() {
245 // The downloads permission implies the internal version as well.
246 if (apis_.find(APIPermission::kDownloads) != apis_.end())
247 apis_.insert(APIPermission::kDownloadsInternal);
249 // The fileBrowserHandler permission implies the internal version as well.
250 if (apis_.find(APIPermission::kFileBrowserHandler) != apis_.end())
251 apis_.insert(APIPermission::kFileBrowserHandlerInternal);
254 void PermissionSet::InitEffectiveHosts() {
255 effective_hosts_.ClearPatterns();
257 URLPatternSet::CreateUnion(
258 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
261 void PermissionSet::InitShouldWarnAllHosts() const {
262 if (HasEffectiveAccessToAllHosts()) {
263 should_warn_all_hosts_ = WARN_ALL_HOSTS;
264 return;
267 for (URLPatternSet::const_iterator iter = effective_hosts_.begin();
268 iter != effective_hosts_.end();
269 ++iter) {
270 if (iter->ImpliesAllHosts()) {
271 should_warn_all_hosts_ = WARN_ALL_HOSTS;
272 return;
276 should_warn_all_hosts_ = DONT_WARN_ALL_HOSTS;
279 } // namespace extensions