Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / extensions / common / permissions / permission_set.cc
blobee21137fcdcba4e481e5ad0a8a9364552ed7d084
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 <algorithm>
8 #include <iterator>
9 #include <string>
11 #include "extensions/common/permissions/permissions_info.h"
12 #include "extensions/common/url_pattern.h"
13 #include "extensions/common/url_pattern_set.h"
14 #include "url/gurl.h"
16 namespace extensions {
18 namespace {
20 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) {
21 DCHECK(out);
22 for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) {
23 URLPattern p = *i;
24 p.SetPath("/*");
25 out->AddPattern(p);
29 } // namespace
32 // PermissionSet
35 PermissionSet::PermissionSet() : should_warn_all_hosts_(UNINITIALIZED) {}
37 PermissionSet::PermissionSet(
38 const APIPermissionSet& apis,
39 const ManifestPermissionSet& manifest_permissions,
40 const URLPatternSet& explicit_hosts,
41 const URLPatternSet& scriptable_hosts)
42 : apis_(apis),
43 manifest_permissions_(manifest_permissions),
44 scriptable_hosts_(scriptable_hosts),
45 should_warn_all_hosts_(UNINITIALIZED) {
46 AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_);
47 InitImplicitPermissions();
48 InitEffectiveHosts();
51 // static
52 PermissionSet* PermissionSet::CreateDifference(
53 const PermissionSet* set1,
54 const PermissionSet* set2) {
55 scoped_refptr<PermissionSet> empty = new PermissionSet();
56 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
57 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
59 APIPermissionSet apis;
60 APIPermissionSet::Difference(set1_safe->apis(), set2_safe->apis(), &apis);
62 ManifestPermissionSet manifest_permissions;
63 ManifestPermissionSet::Difference(set1_safe->manifest_permissions(),
64 set2_safe->manifest_permissions(),
65 &manifest_permissions);
67 URLPatternSet explicit_hosts;
68 URLPatternSet::CreateDifference(set1_safe->explicit_hosts(),
69 set2_safe->explicit_hosts(),
70 &explicit_hosts);
72 URLPatternSet scriptable_hosts;
73 URLPatternSet::CreateDifference(set1_safe->scriptable_hosts(),
74 set2_safe->scriptable_hosts(),
75 &scriptable_hosts);
77 return new PermissionSet(apis, manifest_permissions,
78 explicit_hosts, scriptable_hosts);
81 // static
82 PermissionSet* PermissionSet::CreateIntersection(
83 const PermissionSet* set1,
84 const PermissionSet* set2) {
85 scoped_refptr<PermissionSet> empty = new PermissionSet();
86 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
87 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
89 APIPermissionSet apis;
90 APIPermissionSet::Intersection(set1_safe->apis(), set2_safe->apis(), &apis);
92 ManifestPermissionSet manifest_permissions;
93 ManifestPermissionSet::Intersection(set1_safe->manifest_permissions(),
94 set2_safe->manifest_permissions(),
95 &manifest_permissions);
97 URLPatternSet explicit_hosts;
98 URLPatternSet::CreateIntersection(set1_safe->explicit_hosts(),
99 set2_safe->explicit_hosts(),
100 &explicit_hosts);
102 URLPatternSet scriptable_hosts;
103 URLPatternSet::CreateIntersection(set1_safe->scriptable_hosts(),
104 set2_safe->scriptable_hosts(),
105 &scriptable_hosts);
107 return new PermissionSet(apis, manifest_permissions,
108 explicit_hosts, scriptable_hosts);
111 // static
112 PermissionSet* PermissionSet::CreateUnion(
113 const PermissionSet* set1,
114 const PermissionSet* set2) {
115 scoped_refptr<PermissionSet> empty = new PermissionSet();
116 const PermissionSet* set1_safe = (set1 == NULL) ? empty.get() : set1;
117 const PermissionSet* set2_safe = (set2 == NULL) ? empty.get() : set2;
119 APIPermissionSet apis;
120 APIPermissionSet::Union(set1_safe->apis(), set2_safe->apis(), &apis);
122 ManifestPermissionSet manifest_permissions;
123 ManifestPermissionSet::Union(set1_safe->manifest_permissions(),
124 set2_safe->manifest_permissions(),
125 &manifest_permissions);
127 URLPatternSet explicit_hosts;
128 URLPatternSet::CreateUnion(set1_safe->explicit_hosts(),
129 set2_safe->explicit_hosts(),
130 &explicit_hosts);
132 URLPatternSet scriptable_hosts;
133 URLPatternSet::CreateUnion(set1_safe->scriptable_hosts(),
134 set2_safe->scriptable_hosts(),
135 &scriptable_hosts);
137 return new PermissionSet(apis, manifest_permissions,
138 explicit_hosts, scriptable_hosts);
141 bool PermissionSet::operator==(
142 const PermissionSet& rhs) const {
143 return apis_ == rhs.apis_ &&
144 manifest_permissions_ == rhs.manifest_permissions_ &&
145 scriptable_hosts_ == rhs.scriptable_hosts_ &&
146 explicit_hosts_ == rhs.explicit_hosts_;
149 bool PermissionSet::Contains(const PermissionSet& set) const {
150 return apis_.Contains(set.apis()) &&
151 manifest_permissions_.Contains(set.manifest_permissions()) &&
152 explicit_hosts().Contains(set.explicit_hosts()) &&
153 scriptable_hosts().Contains(set.scriptable_hosts());
156 std::set<std::string> PermissionSet::GetAPIsAsStrings() const {
157 std::set<std::string> apis_str;
158 for (APIPermissionSet::const_iterator i = apis_.begin();
159 i != apis_.end(); ++i) {
160 apis_str.insert(i->name());
162 return apis_str;
165 bool PermissionSet::IsEmpty() const {
166 // Not default if any host permissions are present.
167 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
168 return false;
170 // Or if it has no api permissions.
171 return apis().empty() && manifest_permissions().empty();
174 bool PermissionSet::HasAPIPermission(
175 APIPermission::ID id) const {
176 return apis().find(id) != apis().end();
179 bool PermissionSet::HasAPIPermission(const std::string& permission_name) const {
180 const APIPermissionInfo* permission =
181 PermissionsInfo::GetInstance()->GetByName(permission_name);
182 // Ensure our PermissionsProvider is aware of this permission.
183 CHECK(permission) << permission_name;
184 return (permission && apis_.count(permission->id()));
187 bool PermissionSet::CheckAPIPermission(APIPermission::ID permission) const {
188 return CheckAPIPermissionWithParam(permission, NULL);
191 bool PermissionSet::CheckAPIPermissionWithParam(
192 APIPermission::ID permission,
193 const APIPermission::CheckParam* param) const {
194 APIPermissionSet::const_iterator iter = apis().find(permission);
195 if (iter == apis().end())
196 return false;
197 return iter->Check(param);
200 bool PermissionSet::HasExplicitAccessToOrigin(
201 const GURL& origin) const {
202 return explicit_hosts().MatchesURL(origin);
205 bool PermissionSet::HasScriptableAccessToURL(
206 const GURL& origin) const {
207 // We only need to check our host list to verify access. The host list should
208 // already reflect any special rules (such as chrome://favicon, all hosts
209 // access, etc.).
210 return scriptable_hosts().MatchesURL(origin);
213 bool PermissionSet::HasEffectiveAccessToAllHosts() const {
214 // There are two ways this set can have effective access to all hosts:
215 // 1) it has an <all_urls> URL pattern.
216 // 2) it has a named permission with implied full URL access.
217 if (effective_hosts().MatchesAllURLs())
218 return true;
220 for (APIPermissionSet::const_iterator i = apis().begin();
221 i != apis().end(); ++i) {
222 if (i->info()->implies_full_url_access())
223 return true;
225 return false;
228 bool PermissionSet::ShouldWarnAllHosts() const {
229 if (should_warn_all_hosts_ == UNINITIALIZED)
230 InitShouldWarnAllHosts();
231 return should_warn_all_hosts_ == WARN_ALL_HOSTS;
234 bool PermissionSet::HasEffectiveAccessToURL(const GURL& url) const {
235 return effective_hosts().MatchesURL(url);
238 bool PermissionSet::HasEffectiveFullAccess() const {
239 for (APIPermissionSet::const_iterator i = apis().begin();
240 i != apis().end(); ++i) {
241 if (i->info()->implies_full_access())
242 return true;
244 return false;
247 PermissionSet::~PermissionSet() {}
249 void PermissionSet::InitImplicitPermissions() {
250 // The downloads permission implies the internal version as well.
251 if (apis_.find(APIPermission::kDownloads) != apis_.end())
252 apis_.insert(APIPermission::kDownloadsInternal);
254 // The fileBrowserHandler permission implies the internal version as well.
255 if (apis_.find(APIPermission::kFileBrowserHandler) != apis_.end())
256 apis_.insert(APIPermission::kFileBrowserHandlerInternal);
259 void PermissionSet::InitEffectiveHosts() {
260 effective_hosts_.ClearPatterns();
262 URLPatternSet::CreateUnion(
263 explicit_hosts(), scriptable_hosts(), &effective_hosts_);
266 void PermissionSet::InitShouldWarnAllHosts() const {
267 if (HasEffectiveAccessToAllHosts()) {
268 should_warn_all_hosts_ = WARN_ALL_HOSTS;
269 return;
272 for (URLPatternSet::const_iterator iter = effective_hosts_.begin();
273 iter != effective_hosts_.end();
274 ++iter) {
275 if (iter->ImpliesAllHosts()) {
276 should_warn_all_hosts_ = WARN_ALL_HOSTS;
277 return;
281 should_warn_all_hosts_ = DONT_WARN_ALL_HOSTS;
284 } // namespace extensions