Atomic: Notify Watcher to observe device fd
[chromium-blink-merge.git] / extensions / common / permissions / permission_set.cc
blobf9874114b30671d1f68baf0cb855ec559646bdab
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::operator!=(const PermissionSet& rhs) const {
145 return !(*this == rhs);
148 bool PermissionSet::Contains(const PermissionSet& set) const {
149 return apis_.Contains(set.apis()) &&
150 manifest_permissions_.Contains(set.manifest_permissions()) &&
151 explicit_hosts().Contains(set.explicit_hosts()) &&
152 scriptable_hosts().Contains(set.scriptable_hosts());
155 std::set<std::string> PermissionSet::GetAPIsAsStrings() const {
156 std::set<std::string> apis_str;
157 for (APIPermissionSet::const_iterator i = apis_.begin();
158 i != apis_.end(); ++i) {
159 apis_str.insert(i->name());
161 return apis_str;
164 bool PermissionSet::IsEmpty() const {
165 // Not default if any host permissions are present.
166 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
167 return false;
169 // Or if it has no api permissions.
170 return apis().empty() && manifest_permissions().empty();
173 bool PermissionSet::HasAPIPermission(
174 APIPermission::ID id) const {
175 return apis().find(id) != apis().end();
178 bool PermissionSet::HasAPIPermission(const std::string& permission_name) const {
179 const APIPermissionInfo* permission =
180 PermissionsInfo::GetInstance()->GetByName(permission_name);
181 // Ensure our PermissionsProvider is aware of this permission.
182 CHECK(permission) << permission_name;
183 return (permission && apis_.count(permission->id()));
186 bool PermissionSet::CheckAPIPermission(APIPermission::ID permission) const {
187 return CheckAPIPermissionWithParam(permission, NULL);
190 bool PermissionSet::CheckAPIPermissionWithParam(
191 APIPermission::ID permission,
192 const APIPermission::CheckParam* param) const {
193 APIPermissionSet::const_iterator iter = apis().find(permission);
194 if (iter == apis().end())
195 return false;
196 return iter->Check(param);
199 bool PermissionSet::HasExplicitAccessToOrigin(
200 const GURL& origin) const {
201 return explicit_hosts().MatchesURL(origin);
204 bool PermissionSet::HasScriptableAccessToURL(
205 const GURL& origin) const {
206 // We only need to check our host list to verify access. The host list should
207 // already reflect any special rules (such as chrome://favicon, all hosts
208 // access, etc.).
209 return scriptable_hosts().MatchesURL(origin);
212 bool PermissionSet::HasEffectiveAccessToAllHosts() const {
213 // There are two ways this set can have effective access to all hosts:
214 // 1) it has an <all_urls> URL pattern.
215 // 2) it has a named permission with implied full URL access.
216 if (effective_hosts().MatchesAllURLs())
217 return true;
219 for (APIPermissionSet::const_iterator i = apis().begin();
220 i != apis().end(); ++i) {
221 if (i->info()->implies_full_url_access())
222 return true;
224 return false;
227 bool PermissionSet::ShouldWarnAllHosts() const {
228 if (should_warn_all_hosts_ == UNINITIALIZED)
229 InitShouldWarnAllHosts();
230 return should_warn_all_hosts_ == WARN_ALL_HOSTS;
233 bool PermissionSet::HasEffectiveAccessToURL(const GURL& url) const {
234 return effective_hosts().MatchesURL(url);
237 bool PermissionSet::HasEffectiveFullAccess() const {
238 for (APIPermissionSet::const_iterator i = apis().begin();
239 i != apis().end(); ++i) {
240 if (i->info()->implies_full_access())
241 return true;
243 return false;
246 PermissionSet::~PermissionSet() {}
248 void PermissionSet::InitImplicitPermissions() {
249 // The downloads permission implies the internal version as well.
250 if (apis_.find(APIPermission::kDownloads) != apis_.end())
251 apis_.insert(APIPermission::kDownloadsInternal);
253 // The fileBrowserHandler permission implies the internal version as well.
254 if (apis_.find(APIPermission::kFileBrowserHandler) != apis_.end())
255 apis_.insert(APIPermission::kFileBrowserHandlerInternal);
258 void PermissionSet::InitEffectiveHosts() {
259 effective_hosts_.ClearPatterns();
261 URLPatternSet::CreateUnion(
262 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
265 void PermissionSet::InitShouldWarnAllHosts() const {
266 if (HasEffectiveAccessToAllHosts()) {
267 should_warn_all_hosts_ = WARN_ALL_HOSTS;
268 return;
271 for (URLPatternSet::const_iterator iter = effective_hosts_.begin();
272 iter != effective_hosts_.end();
273 ++iter) {
274 if (iter->ImpliesAllHosts()) {
275 should_warn_all_hosts_ = WARN_ALL_HOSTS;
276 return;
280 should_warn_all_hosts_ = DONT_WARN_ALL_HOSTS;
283 } // namespace extensions