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 using extensions::URLPatternSet
;
20 void AddPatternsAndRemovePaths(const URLPatternSet
& set
, URLPatternSet
* out
) {
22 for (URLPatternSet::const_iterator i
= set
.begin(); i
!= set
.end(); ++i
) {
31 namespace extensions
{
37 PermissionSet::PermissionSet() {}
39 PermissionSet::PermissionSet(
40 const APIPermissionSet
& apis
,
41 const ManifestPermissionSet
& manifest_permissions
,
42 const URLPatternSet
& explicit_hosts
,
43 const URLPatternSet
& scriptable_hosts
)
45 manifest_permissions_(manifest_permissions
),
46 scriptable_hosts_(scriptable_hosts
) {
47 AddPatternsAndRemovePaths(explicit_hosts
, &explicit_hosts_
);
48 InitImplicitPermissions();
53 PermissionSet
* PermissionSet::CreateDifference(
54 const PermissionSet
* set1
,
55 const PermissionSet
* set2
) {
56 scoped_refptr
<PermissionSet
> empty
= new PermissionSet();
57 const PermissionSet
* set1_safe
= (set1
== NULL
) ? empty
.get() : set1
;
58 const PermissionSet
* set2_safe
= (set2
== NULL
) ? empty
.get() : set2
;
60 APIPermissionSet apis
;
61 APIPermissionSet::Difference(set1_safe
->apis(), set2_safe
->apis(), &apis
);
63 ManifestPermissionSet manifest_permissions
;
64 ManifestPermissionSet::Difference(set1_safe
->manifest_permissions(),
65 set2_safe
->manifest_permissions(),
66 &manifest_permissions
);
68 URLPatternSet explicit_hosts
;
69 URLPatternSet::CreateDifference(set1_safe
->explicit_hosts(),
70 set2_safe
->explicit_hosts(),
73 URLPatternSet scriptable_hosts
;
74 URLPatternSet::CreateDifference(set1_safe
->scriptable_hosts(),
75 set2_safe
->scriptable_hosts(),
78 return new PermissionSet(apis
, manifest_permissions
,
79 explicit_hosts
, scriptable_hosts
);
83 PermissionSet
* PermissionSet::CreateIntersection(
84 const PermissionSet
* set1
,
85 const PermissionSet
* set2
) {
86 scoped_refptr
<PermissionSet
> empty
= new PermissionSet();
87 const PermissionSet
* set1_safe
= (set1
== NULL
) ? empty
.get() : set1
;
88 const PermissionSet
* set2_safe
= (set2
== NULL
) ? empty
.get() : set2
;
90 APIPermissionSet apis
;
91 APIPermissionSet::Intersection(set1_safe
->apis(), set2_safe
->apis(), &apis
);
93 ManifestPermissionSet manifest_permissions
;
94 ManifestPermissionSet::Intersection(set1_safe
->manifest_permissions(),
95 set2_safe
->manifest_permissions(),
96 &manifest_permissions
);
98 URLPatternSet explicit_hosts
;
99 URLPatternSet::CreateIntersection(set1_safe
->explicit_hosts(),
100 set2_safe
->explicit_hosts(),
103 URLPatternSet scriptable_hosts
;
104 URLPatternSet::CreateIntersection(set1_safe
->scriptable_hosts(),
105 set2_safe
->scriptable_hosts(),
108 return new PermissionSet(apis
, manifest_permissions
,
109 explicit_hosts
, scriptable_hosts
);
113 PermissionSet
* PermissionSet::CreateUnion(
114 const PermissionSet
* set1
,
115 const PermissionSet
* set2
) {
116 scoped_refptr
<PermissionSet
> empty
= new PermissionSet();
117 const PermissionSet
* set1_safe
= (set1
== NULL
) ? empty
.get() : set1
;
118 const PermissionSet
* set2_safe
= (set2
== NULL
) ? empty
.get() : set2
;
120 APIPermissionSet apis
;
121 APIPermissionSet::Union(set1_safe
->apis(), set2_safe
->apis(), &apis
);
123 ManifestPermissionSet manifest_permissions
;
124 ManifestPermissionSet::Union(set1_safe
->manifest_permissions(),
125 set2_safe
->manifest_permissions(),
126 &manifest_permissions
);
128 URLPatternSet explicit_hosts
;
129 URLPatternSet::CreateUnion(set1_safe
->explicit_hosts(),
130 set2_safe
->explicit_hosts(),
133 URLPatternSet scriptable_hosts
;
134 URLPatternSet::CreateUnion(set1_safe
->scriptable_hosts(),
135 set2_safe
->scriptable_hosts(),
138 return new PermissionSet(apis
, manifest_permissions
,
139 explicit_hosts
, scriptable_hosts
);
142 bool PermissionSet::operator==(
143 const PermissionSet
& rhs
) const {
144 return apis_
== rhs
.apis_
&&
145 manifest_permissions_
== rhs
.manifest_permissions_
&&
146 scriptable_hosts_
== rhs
.scriptable_hosts_
&&
147 explicit_hosts_
== rhs
.explicit_hosts_
;
150 bool PermissionSet::Contains(const PermissionSet
& set
) const {
151 return apis_
.Contains(set
.apis()) &&
152 manifest_permissions_
.Contains(set
.manifest_permissions()) &&
153 explicit_hosts().Contains(set
.explicit_hosts()) &&
154 scriptable_hosts().Contains(set
.scriptable_hosts());
157 std::set
<std::string
> PermissionSet::GetAPIsAsStrings() const {
158 std::set
<std::string
> apis_str
;
159 for (APIPermissionSet::const_iterator i
= apis_
.begin();
160 i
!= apis_
.end(); ++i
) {
161 apis_str
.insert(i
->name());
166 bool PermissionSet::IsEmpty() const {
167 // Not default if any host permissions are present.
168 if (!(explicit_hosts().is_empty() && scriptable_hosts().is_empty()))
171 // Or if it has no api permissions.
172 return apis().empty() && manifest_permissions().empty();
175 bool PermissionSet::HasAPIPermission(
176 APIPermission::ID id
) const {
177 return apis().find(id
) != apis().end();
180 bool PermissionSet::HasAPIPermission(const std::string
& permission_name
) const {
181 const APIPermissionInfo
* permission
=
182 PermissionsInfo::GetInstance()->GetByName(permission_name
);
183 // Ensure our PermissionsProvider is aware of this permission.
184 CHECK(permission
) << permission_name
;
185 return (permission
&& apis_
.count(permission
->id()));
188 bool PermissionSet::CheckAPIPermission(APIPermission::ID permission
) const {
189 return CheckAPIPermissionWithParam(permission
, NULL
);
192 bool PermissionSet::CheckAPIPermissionWithParam(
193 APIPermission::ID permission
,
194 const APIPermission::CheckParam
* param
) const {
195 APIPermissionSet::const_iterator iter
= apis().find(permission
);
196 if (iter
== apis().end())
198 return iter
->Check(param
);
201 bool PermissionSet::HasExplicitAccessToOrigin(
202 const GURL
& origin
) const {
203 return explicit_hosts().MatchesURL(origin
);
206 bool PermissionSet::HasScriptableAccessToURL(
207 const GURL
& origin
) const {
208 // We only need to check our host list to verify access. The host list should
209 // already reflect any special rules (such as chrome://favicon, all hosts
211 return scriptable_hosts().MatchesURL(origin
);
214 bool PermissionSet::HasEffectiveAccessToAllHosts() const {
215 // There are two ways this set can have effective access to all hosts:
216 // 1) it has an <all_urls> URL pattern.
217 // 2) it has a named permission with implied full URL access.
218 for (URLPatternSet::const_iterator host
= effective_hosts().begin();
219 host
!= effective_hosts().end(); ++host
) {
220 if (host
->match_all_urls() ||
221 (host
->match_subdomains() && host
->host().empty()))
225 for (APIPermissionSet::const_iterator i
= apis().begin();
226 i
!= apis().end(); ++i
) {
227 if (i
->info()->implies_full_url_access())
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 // TODO(fsamuel): Is there a better way to request access to the WebRequest
254 // API without exposing it to the Chrome App?
255 if (apis_
.find(APIPermission::kWebView
) != apis_
.end())
256 apis_
.insert(APIPermission::kWebRequestInternal
);
258 // The webRequest permission implies the internal version as well.
259 if (apis_
.find(APIPermission::kWebRequest
) != apis_
.end())
260 apis_
.insert(APIPermission::kWebRequestInternal
);
262 // The fileBrowserHandler permission implies the internal version as well.
263 if (apis_
.find(APIPermission::kFileBrowserHandler
) != apis_
.end())
264 apis_
.insert(APIPermission::kFileBrowserHandlerInternal
);
267 void PermissionSet::InitEffectiveHosts() {
268 effective_hosts_
.ClearPatterns();
270 URLPatternSet::CreateUnion(
271 explicit_hosts(), scriptable_hosts(), &effective_hosts_
);
274 } // namespace extensions