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"
11 namespace extensions
{
15 void AddPatternsAndRemovePaths(const URLPatternSet
& set
, URLPatternSet
* out
) {
17 for (URLPatternSet::const_iterator i
= set
.begin(); i
!= set
.end(); ++i
) {
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
)
38 manifest_permissions_(manifest_permissions
),
39 scriptable_hosts_(scriptable_hosts
),
40 should_warn_all_hosts_(UNINITIALIZED
) {
41 AddPatternsAndRemovePaths(explicit_hosts
, &explicit_hosts_
);
42 InitImplicitPermissions();
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(),
67 URLPatternSet scriptable_hosts
;
68 URLPatternSet::CreateDifference(set1_safe
->scriptable_hosts(),
69 set2_safe
->scriptable_hosts(),
72 return new PermissionSet(apis
, manifest_permissions
,
73 explicit_hosts
, scriptable_hosts
);
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(),
97 URLPatternSet scriptable_hosts
;
98 URLPatternSet::CreateIntersection(set1_safe
->scriptable_hosts(),
99 set2_safe
->scriptable_hosts(),
102 return new PermissionSet(apis
, manifest_permissions
,
103 explicit_hosts
, scriptable_hosts
);
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(),
127 URLPatternSet scriptable_hosts
;
128 URLPatternSet::CreateUnion(set1_safe
->scriptable_hosts(),
129 set2_safe
->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());
164 bool PermissionSet::IsEmpty() const {
165 // Not default if any host permissions are present.
166 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
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())
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
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())
219 for (APIPermissionSet::const_iterator i
= apis().begin();
220 i
!= apis().end(); ++i
) {
221 if (i
->info()->implies_full_url_access())
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())
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
;
271 for (URLPatternSet::const_iterator iter
= effective_hosts_
.begin();
272 iter
!= effective_hosts_
.end();
274 if (iter
->ImpliesAllHosts()) {
275 should_warn_all_hosts_
= WARN_ALL_HOSTS
;
280 should_warn_all_hosts_
= DONT_WARN_ALL_HOSTS
;
283 } // namespace extensions