1 // Copyright (c) 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/permissions_data.h"
7 #include "base/command_line.h"
8 #include "content/public/common/url_constants.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/error_utils.h"
11 #include "extensions/common/extensions_client.h"
12 #include "extensions/common/manifest.h"
13 #include "extensions/common/manifest_constants.h"
14 #include "extensions/common/manifest_handlers/permissions_parser.h"
15 #include "extensions/common/permissions/permission_message_provider.h"
16 #include "extensions/common/switches.h"
17 #include "extensions/common/url_pattern_set.h"
18 #include "extensions/common/user_script.h"
20 #include "url/url_constants.h"
22 namespace extensions
{
26 PermissionsData::PolicyDelegate
* g_policy_delegate
= NULL
;
30 PermissionsData::PermissionsData(const Extension
* extension
)
31 : extension_id_(extension
->id()), manifest_type_(extension
->GetType()) {
32 base::AutoLock
auto_lock(runtime_lock_
);
33 scoped_refptr
<const PermissionSet
> required_permissions
=
34 PermissionsParser::GetRequiredPermissions(extension
);
35 active_permissions_unsafe_
=
36 new PermissionSet(required_permissions
->apis(),
37 required_permissions
->manifest_permissions(),
38 required_permissions
->explicit_hosts(),
39 required_permissions
->scriptable_hosts());
40 withheld_permissions_unsafe_
= new PermissionSet();
43 PermissionsData::~PermissionsData() {
47 void PermissionsData::SetPolicyDelegate(PolicyDelegate
* delegate
) {
48 g_policy_delegate
= delegate
;
52 bool PermissionsData::CanSilentlyIncreasePermissions(
53 const Extension
* extension
) {
54 return extension
->location() != Manifest::INTERNAL
;
58 bool PermissionsData::CanExecuteScriptEverywhere(const Extension
* extension
) {
59 if (extension
->location() == Manifest::COMPONENT
)
62 const ExtensionsClient::ScriptingWhitelist
& whitelist
=
63 ExtensionsClient::Get()->GetScriptingWhitelist();
65 return std::find(whitelist
.begin(), whitelist
.end(), extension
->id()) !=
69 bool PermissionsData::ShouldSkipPermissionWarnings(
70 const std::string
& extension_id
) {
71 // See http://b/4946060 for more details.
72 return extension_id
== std::string("nckgahadagoaajjgafhacjanaoiihapd");
76 bool PermissionsData::IsRestrictedUrl(const GURL
& document_url
,
77 const GURL
& top_frame_url
,
78 const Extension
* extension
,
80 if (extension
&& CanExecuteScriptEverywhere(extension
))
83 // Check if the scheme is valid for extensions. If not, return.
84 if (!URLPattern::IsValidSchemeForExtensions(document_url
.scheme()) &&
85 document_url
.spec() != url::kAboutBlankURL
) {
87 *error
= ErrorUtils::FormatErrorMessage(
88 manifest_errors::kCannotAccessPage
,
94 if (!ExtensionsClient::Get()->IsScriptableURL(document_url
, error
))
97 bool allow_on_chrome_urls
= base::CommandLine::ForCurrentProcess()->HasSwitch(
98 switches::kExtensionsOnChromeURLs
);
99 if (document_url
.SchemeIs(content::kChromeUIScheme
) &&
100 !allow_on_chrome_urls
) {
102 *error
= manifest_errors::kCannotAccessChromeUrl
;
106 if (extension
&& top_frame_url
.SchemeIs(kExtensionScheme
) &&
107 top_frame_url
.host() != extension
->id() && !allow_on_chrome_urls
) {
109 *error
= manifest_errors::kCannotAccessExtensionUrl
;
116 void PermissionsData::SetPermissions(
117 const scoped_refptr
<const PermissionSet
>& active
,
118 const scoped_refptr
<const PermissionSet
>& withheld
) const {
119 base::AutoLock
auto_lock(runtime_lock_
);
120 active_permissions_unsafe_
= active
;
121 withheld_permissions_unsafe_
= withheld
;
124 void PermissionsData::UpdateTabSpecificPermissions(
126 scoped_refptr
<const PermissionSet
> permissions
) const {
127 base::AutoLock
auto_lock(runtime_lock_
);
129 TabPermissionsMap::iterator iter
= tab_specific_permissions_
.find(tab_id
);
130 if (iter
== tab_specific_permissions_
.end())
131 tab_specific_permissions_
[tab_id
] = permissions
;
134 PermissionSet::CreateUnion(iter
->second
.get(), permissions
.get());
137 void PermissionsData::ClearTabSpecificPermissions(int tab_id
) const {
138 base::AutoLock
auto_lock(runtime_lock_
);
140 tab_specific_permissions_
.erase(tab_id
);
143 bool PermissionsData::HasAPIPermission(APIPermission::ID permission
) const {
144 return active_permissions()->HasAPIPermission(permission
);
147 bool PermissionsData::HasAPIPermission(
148 const std::string
& permission_name
) const {
149 return active_permissions()->HasAPIPermission(permission_name
);
152 bool PermissionsData::HasAPIPermissionForTab(
154 APIPermission::ID permission
) const {
155 if (HasAPIPermission(permission
))
158 scoped_refptr
<const PermissionSet
> tab_permissions
=
159 GetTabSpecificPermissions(tab_id
);
161 // Place autolock below the HasAPIPermission() and
162 // GetTabSpecificPermissions(), since each already acquires the lock.
163 base::AutoLock
auto_lock(runtime_lock_
);
164 return tab_permissions
.get() && tab_permissions
->HasAPIPermission(permission
);
167 bool PermissionsData::CheckAPIPermissionWithParam(
168 APIPermission::ID permission
,
169 const APIPermission::CheckParam
* param
) const {
170 return active_permissions()->CheckAPIPermissionWithParam(permission
, param
);
173 const URLPatternSet
& PermissionsData::GetEffectiveHostPermissions() const {
174 return active_permissions()->effective_hosts();
177 bool PermissionsData::HasHostPermission(const GURL
& url
) const {
178 return active_permissions()->HasExplicitAccessToOrigin(url
);
181 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
182 return active_permissions()->HasEffectiveAccessToAllHosts();
185 PermissionMessages
PermissionsData::GetPermissionMessages() const {
186 if (ShouldSkipPermissionWarnings(extension_id_
)) {
187 return PermissionMessages();
189 return PermissionMessageProvider::Get()->GetPermissionMessages(
190 active_permissions(), manifest_type_
);
194 std::vector
<base::string16
> PermissionsData::GetPermissionMessageStrings()
196 if (ShouldSkipPermissionWarnings(extension_id_
))
197 return std::vector
<base::string16
>();
198 return PermissionMessageProvider::Get()->GetWarningMessages(
199 active_permissions(), manifest_type_
);
202 std::vector
<base::string16
>
203 PermissionsData::GetPermissionMessageDetailsStrings() const {
204 if (ShouldSkipPermissionWarnings(extension_id_
))
205 return std::vector
<base::string16
>();
206 return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
207 active_permissions(), manifest_type_
);
210 bool PermissionsData::HasWithheldImpliedAllHosts() const {
211 // Since we currently only withhold all_hosts, it's sufficient to check
212 // that either set is not empty.
213 return !withheld_permissions()->explicit_hosts().is_empty() ||
214 !withheld_permissions()->scriptable_hosts().is_empty();
217 bool PermissionsData::CanAccessPage(const Extension
* extension
,
218 const GURL
& document_url
,
219 const GURL
& top_frame_url
,
222 std::string
* error
) const {
223 AccessType result
= CanRunOnPage(extension
,
228 active_permissions()->explicit_hosts(),
229 withheld_permissions()->explicit_hosts(),
231 // TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED.
232 return result
== ACCESS_ALLOWED
|| result
== ACCESS_WITHHELD
;
235 PermissionsData::AccessType
PermissionsData::GetPageAccess(
236 const Extension
* extension
,
237 const GURL
& document_url
,
238 const GURL
& top_frame_url
,
241 std::string
* error
) const {
242 return CanRunOnPage(extension
,
247 active_permissions()->explicit_hosts(),
248 withheld_permissions()->explicit_hosts(),
252 bool PermissionsData::CanRunContentScriptOnPage(const Extension
* extension
,
253 const GURL
& document_url
,
254 const GURL
& top_frame_url
,
257 std::string
* error
) const {
258 AccessType result
= CanRunOnPage(extension
,
263 active_permissions()->scriptable_hosts(),
264 withheld_permissions()->scriptable_hosts(),
266 // TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED.
267 return result
== ACCESS_ALLOWED
|| result
== ACCESS_WITHHELD
;
270 PermissionsData::AccessType
PermissionsData::GetContentScriptAccess(
271 const Extension
* extension
,
272 const GURL
& document_url
,
273 const GURL
& top_frame_url
,
276 std::string
* error
) const {
277 return CanRunOnPage(extension
,
282 active_permissions()->scriptable_hosts(),
283 withheld_permissions()->scriptable_hosts(),
287 bool PermissionsData::CanCaptureVisiblePage(int tab_id
,
288 std::string
* error
) const {
289 const URLPattern
all_urls(URLPattern::SCHEME_ALL
,
290 URLPattern::kAllUrlsPattern
);
292 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls
))
296 scoped_refptr
<const PermissionSet
> tab_permissions
=
297 GetTabSpecificPermissions(tab_id
);
298 if (tab_permissions
.get() &&
299 tab_permissions
->HasAPIPermission(APIPermission::kTab
)) {
303 *error
= manifest_errors::kActiveTabPermissionNotGranted
;
308 *error
= manifest_errors::kAllURLOrActiveTabNeeded
;
312 scoped_refptr
<const PermissionSet
> PermissionsData::GetTabSpecificPermissions(
314 base::AutoLock
auto_lock(runtime_lock_
);
316 TabPermissionsMap::const_iterator iter
=
317 tab_specific_permissions_
.find(tab_id
);
318 return (iter
!= tab_specific_permissions_
.end()) ? iter
->second
: NULL
;
321 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
323 const GURL
& url
) const {
325 scoped_refptr
<const PermissionSet
> tab_permissions
=
326 GetTabSpecificPermissions(tab_id
);
327 if (tab_permissions
.get() &&
328 tab_permissions
->explicit_hosts().MatchesSecurityOrigin(url
)) {
335 PermissionsData::AccessType
PermissionsData::CanRunOnPage(
336 const Extension
* extension
,
337 const GURL
& document_url
,
338 const GURL
& top_frame_url
,
341 const URLPatternSet
& permitted_url_patterns
,
342 const URLPatternSet
& withheld_url_patterns
,
343 std::string
* error
) const {
344 if (g_policy_delegate
&&
345 !g_policy_delegate
->CanExecuteScriptOnPage(
346 extension
, document_url
, top_frame_url
, tab_id
, process_id
, error
)) {
347 return ACCESS_DENIED
;
350 if (IsRestrictedUrl(document_url
, top_frame_url
, extension
, error
))
351 return ACCESS_DENIED
;
353 if (HasTabSpecificPermissionToExecuteScript(tab_id
, top_frame_url
))
354 return ACCESS_ALLOWED
;
356 if (permitted_url_patterns
.MatchesURL(document_url
))
357 return ACCESS_ALLOWED
;
359 if (withheld_url_patterns
.MatchesURL(document_url
))
360 return ACCESS_WITHHELD
;
363 *error
= ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage
,
364 document_url
.spec());
366 return ACCESS_DENIED
;
369 } // namespace extensions