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::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());
160 bool PermissionSet::IsEmpty() const {
161 // Not default if any host permissions are present.
162 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
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())
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
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())
215 for (APIPermissionSet::const_iterator i
= apis().begin();
216 i
!= apis().end(); ++i
) {
217 if (i
->info()->implies_full_url_access())
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())
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
;
267 for (URLPatternSet::const_iterator iter
= effective_hosts_
.begin();
268 iter
!= effective_hosts_
.end();
270 if (iter
->ImpliesAllHosts()) {
271 should_warn_all_hosts_
= WARN_ALL_HOSTS
;
276 should_warn_all_hosts_
= DONT_WARN_ALL_HOSTS
;
279 } // namespace extensions