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"
11 #include "extensions/common/permissions/permissions_info.h"
12 #include "extensions/common/url_pattern.h"
13 #include "extensions/common/url_pattern_set.h"
16 namespace extensions
{
20 void AddPatternsAndRemovePaths(const URLPatternSet
& set
, URLPatternSet
* out
) {
22 for (URLPatternSet::const_iterator i
= set
.begin(); i
!= set
.end(); ++i
) {
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
)
43 manifest_permissions_(manifest_permissions
),
44 scriptable_hosts_(scriptable_hosts
),
45 should_warn_all_hosts_(UNINITIALIZED
) {
46 AddPatternsAndRemovePaths(explicit_hosts
, &explicit_hosts_
);
47 InitImplicitPermissions();
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(),
72 URLPatternSet scriptable_hosts
;
73 URLPatternSet::CreateDifference(set1_safe
->scriptable_hosts(),
74 set2_safe
->scriptable_hosts(),
77 return new PermissionSet(apis
, manifest_permissions
,
78 explicit_hosts
, scriptable_hosts
);
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(),
102 URLPatternSet scriptable_hosts
;
103 URLPatternSet::CreateIntersection(set1_safe
->scriptable_hosts(),
104 set2_safe
->scriptable_hosts(),
107 return new PermissionSet(apis
, manifest_permissions
,
108 explicit_hosts
, scriptable_hosts
);
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(),
132 URLPatternSet scriptable_hosts
;
133 URLPatternSet::CreateUnion(set1_safe
->scriptable_hosts(),
134 set2_safe
->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());
165 bool PermissionSet::IsEmpty() const {
166 // Not default if any host permissions are present.
167 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
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())
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
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())
220 for (APIPermissionSet::const_iterator i
= apis().begin();
221 i
!= apis().end(); ++i
) {
222 if (i
->info()->implies_full_url_access())
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())
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
;
272 for (URLPatternSet::const_iterator iter
= effective_hosts_
.begin();
273 iter
!= effective_hosts_
.end();
275 if (iter
->ImpliesAllHosts()) {
276 should_warn_all_hosts_
= WARN_ALL_HOSTS
;
281 should_warn_all_hosts_
= DONT_WARN_ALL_HOSTS
;
284 } // namespace extensions