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/extension.h"
12 #include "extensions/common/extensions_client.h"
13 #include "extensions/common/manifest.h"
14 #include "extensions/common/manifest_constants.h"
15 #include "extensions/common/manifest_handlers/permissions_parser.h"
16 #include "extensions/common/permissions/permission_message_util.h"
17 #include "extensions/common/switches.h"
18 #include "extensions/common/url_pattern_set.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::CanExecuteScriptEverywhere(const Extension
* extension
) {
53 if (extension
->location() == Manifest::COMPONENT
)
56 const ExtensionsClient::ScriptingWhitelist
& whitelist
=
57 ExtensionsClient::Get()->GetScriptingWhitelist();
59 return std::find(whitelist
.begin(), whitelist
.end(), extension
->id()) !=
64 bool PermissionsData::ScriptsMayRequireActionForExtension(
65 const Extension
* extension
,
66 const PermissionSet
* permissions
) {
67 // An extension may require user action to execute scripts iff the extension
68 // shows up in chrome:extensions (so the user can grant withheld permissions),
69 // is not part of chrome or corporate policy, not on the scripting whitelist,
70 // and requires enough permissions that we should withhold them.
71 return extension
->ShouldDisplayInExtensionSettings() &&
72 !Manifest::IsPolicyLocation(extension
->location()) &&
73 !Manifest::IsComponentLocation(extension
->location()) &&
74 !CanExecuteScriptEverywhere(extension
) &&
75 permissions
->ShouldWarnAllHosts();
78 bool PermissionsData::ShouldSkipPermissionWarnings(
79 const std::string
& extension_id
) {
80 // See http://b/4946060 for more details.
81 return extension_id
== std::string("nckgahadagoaajjgafhacjanaoiihapd");
85 bool PermissionsData::IsRestrictedUrl(const GURL
& document_url
,
86 const GURL
& top_frame_url
,
87 const Extension
* extension
,
89 if (extension
&& CanExecuteScriptEverywhere(extension
))
92 // Check if the scheme is valid for extensions. If not, return.
93 if (!URLPattern::IsValidSchemeForExtensions(document_url
.scheme()) &&
94 document_url
.spec() != url::kAboutBlankURL
) {
96 *error
= ErrorUtils::FormatErrorMessage(
97 manifest_errors::kCannotAccessPage
,
103 if (!ExtensionsClient::Get()->IsScriptableURL(document_url
, error
))
106 bool allow_on_chrome_urls
= base::CommandLine::ForCurrentProcess()->HasSwitch(
107 switches::kExtensionsOnChromeURLs
);
108 if (document_url
.SchemeIs(content::kChromeUIScheme
) &&
109 !allow_on_chrome_urls
) {
111 *error
= manifest_errors::kCannotAccessChromeUrl
;
115 if (extension
&& top_frame_url
.SchemeIs(kExtensionScheme
) &&
116 top_frame_url
.host() != extension
->id() && !allow_on_chrome_urls
) {
118 *error
= manifest_errors::kCannotAccessExtensionUrl
;
125 void PermissionsData::SetPermissions(
126 const scoped_refptr
<const PermissionSet
>& active
,
127 const scoped_refptr
<const PermissionSet
>& withheld
) const {
128 base::AutoLock
auto_lock(runtime_lock_
);
129 active_permissions_unsafe_
= active
;
130 withheld_permissions_unsafe_
= withheld
;
133 void PermissionsData::UpdateTabSpecificPermissions(
135 scoped_refptr
<const PermissionSet
> permissions
) const {
136 base::AutoLock
auto_lock(runtime_lock_
);
138 TabPermissionsMap::iterator iter
= tab_specific_permissions_
.find(tab_id
);
139 if (iter
== tab_specific_permissions_
.end())
140 tab_specific_permissions_
[tab_id
] = permissions
;
143 PermissionSet::CreateUnion(iter
->second
.get(), permissions
.get());
146 void PermissionsData::ClearTabSpecificPermissions(int tab_id
) const {
147 base::AutoLock
auto_lock(runtime_lock_
);
149 tab_specific_permissions_
.erase(tab_id
);
152 bool PermissionsData::HasAPIPermission(APIPermission::ID permission
) const {
153 return active_permissions()->HasAPIPermission(permission
);
156 bool PermissionsData::HasAPIPermission(
157 const std::string
& permission_name
) const {
158 return active_permissions()->HasAPIPermission(permission_name
);
161 bool PermissionsData::HasAPIPermissionForTab(
163 APIPermission::ID permission
) const {
164 if (HasAPIPermission(permission
))
167 scoped_refptr
<const PermissionSet
> tab_permissions
=
168 GetTabSpecificPermissions(tab_id
);
170 // Place autolock below the HasAPIPermission() and
171 // GetTabSpecificPermissions(), since each already acquires the lock.
172 base::AutoLock
auto_lock(runtime_lock_
);
173 return tab_permissions
.get() && tab_permissions
->HasAPIPermission(permission
);
176 bool PermissionsData::CheckAPIPermissionWithParam(
177 APIPermission::ID permission
,
178 const APIPermission::CheckParam
* param
) const {
179 return active_permissions()->CheckAPIPermissionWithParam(permission
, param
);
182 URLPatternSet
PermissionsData::GetEffectiveHostPermissions() const {
183 base::AutoLock
auto_lock(runtime_lock_
);
184 URLPatternSet effective_hosts
= active_permissions_unsafe_
->effective_hosts();
185 for (const auto& val
: tab_specific_permissions_
)
186 effective_hosts
.AddPatterns(val
.second
->effective_hosts());
187 return effective_hosts
;
190 bool PermissionsData::HasHostPermission(const GURL
& url
) const {
191 return active_permissions()->HasExplicitAccessToOrigin(url
);
194 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
195 return active_permissions()->HasEffectiveAccessToAllHosts();
198 PermissionMessageIDs
PermissionsData::GetLegacyPermissionMessageIDs() const {
199 if (ShouldSkipPermissionWarnings(extension_id_
)) {
200 return PermissionMessageIDs();
202 return PermissionMessageProvider::Get()->GetLegacyPermissionMessageIDs(
203 active_permissions().get(), manifest_type_
);
207 PermissionMessageStrings
PermissionsData::GetPermissionMessageStrings() const {
208 if (ShouldSkipPermissionWarnings(extension_id_
))
209 return PermissionMessageStrings();
210 return PermissionMessageProvider::Get()->GetPermissionMessageStrings(
211 active_permissions().get(), manifest_type_
);
214 std::vector
<base::string16
> PermissionsData::GetLegacyPermissionMessageStrings()
216 if (ShouldSkipPermissionWarnings(extension_id_
))
217 return std::vector
<base::string16
>();
218 return PermissionMessageProvider::Get()->GetLegacyWarningMessages(
219 active_permissions().get(), manifest_type_
);
222 std::vector
<base::string16
>
223 PermissionsData::GetLegacyPermissionMessageDetailsStrings() const {
224 if (ShouldSkipPermissionWarnings(extension_id_
))
225 return std::vector
<base::string16
>();
226 return PermissionMessageProvider::Get()->GetLegacyWarningMessagesDetails(
227 active_permissions().get(), manifest_type_
);
230 CoalescedPermissionMessages
PermissionsData::GetCoalescedPermissionMessages()
232 return PermissionMessageProvider::Get()->GetCoalescedPermissionMessages(
233 PermissionMessageProvider::Get()->GetAllPermissionIDs(
234 active_permissions().get(), manifest_type_
));
237 bool PermissionsData::HasWithheldImpliedAllHosts() const {
238 // Since we currently only withhold all_hosts, it's sufficient to check
239 // that either set is not empty.
240 return !withheld_permissions()->explicit_hosts().is_empty() ||
241 !withheld_permissions()->scriptable_hosts().is_empty();
244 bool PermissionsData::CanAccessPage(const Extension
* extension
,
245 const GURL
& document_url
,
246 const GURL
& top_frame_url
,
249 std::string
* error
) const {
250 AccessType result
= CanRunOnPage(extension
,
255 active_permissions()->explicit_hosts(),
256 withheld_permissions()->explicit_hosts(),
258 // TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED.
259 return result
== ACCESS_ALLOWED
|| result
== ACCESS_WITHHELD
;
262 PermissionsData::AccessType
PermissionsData::GetPageAccess(
263 const Extension
* extension
,
264 const GURL
& document_url
,
265 const GURL
& top_frame_url
,
268 std::string
* error
) const {
269 return CanRunOnPage(extension
,
274 active_permissions()->explicit_hosts(),
275 withheld_permissions()->explicit_hosts(),
279 bool PermissionsData::CanRunContentScriptOnPage(const Extension
* extension
,
280 const GURL
& document_url
,
281 const GURL
& top_frame_url
,
284 std::string
* error
) const {
285 AccessType result
= CanRunOnPage(extension
,
290 active_permissions()->scriptable_hosts(),
291 withheld_permissions()->scriptable_hosts(),
293 // TODO(rdevlin.cronin) Update callers so that they only need ACCESS_ALLOWED.
294 return result
== ACCESS_ALLOWED
|| result
== ACCESS_WITHHELD
;
297 PermissionsData::AccessType
PermissionsData::GetContentScriptAccess(
298 const Extension
* extension
,
299 const GURL
& document_url
,
300 const GURL
& top_frame_url
,
303 std::string
* error
) const {
304 return CanRunOnPage(extension
,
309 active_permissions()->scriptable_hosts(),
310 withheld_permissions()->scriptable_hosts(),
314 bool PermissionsData::CanCaptureVisiblePage(int tab_id
,
315 std::string
* error
) const {
316 const URLPattern
all_urls(URLPattern::SCHEME_ALL
,
317 URLPattern::kAllUrlsPattern
);
319 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls
))
323 scoped_refptr
<const PermissionSet
> tab_permissions
=
324 GetTabSpecificPermissions(tab_id
);
325 if (tab_permissions
.get() &&
326 tab_permissions
->HasAPIPermission(APIPermission::kTab
)) {
330 *error
= manifest_errors::kActiveTabPermissionNotGranted
;
335 *error
= manifest_errors::kAllURLOrActiveTabNeeded
;
339 scoped_refptr
<const PermissionSet
> PermissionsData::GetTabSpecificPermissions(
341 base::AutoLock
auto_lock(runtime_lock_
);
343 TabPermissionsMap::const_iterator iter
=
344 tab_specific_permissions_
.find(tab_id
);
345 return (iter
!= tab_specific_permissions_
.end()) ? iter
->second
: NULL
;
348 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
350 const GURL
& url
) const {
352 scoped_refptr
<const PermissionSet
> tab_permissions
=
353 GetTabSpecificPermissions(tab_id
);
354 if (tab_permissions
.get() &&
355 tab_permissions
->explicit_hosts().MatchesSecurityOrigin(url
)) {
362 PermissionsData::AccessType
PermissionsData::CanRunOnPage(
363 const Extension
* extension
,
364 const GURL
& document_url
,
365 const GURL
& top_frame_url
,
368 const URLPatternSet
& permitted_url_patterns
,
369 const URLPatternSet
& withheld_url_patterns
,
370 std::string
* error
) const {
371 if (g_policy_delegate
&&
372 !g_policy_delegate
->CanExecuteScriptOnPage(
373 extension
, document_url
, top_frame_url
, tab_id
, process_id
, error
)) {
374 return ACCESS_DENIED
;
377 if (IsRestrictedUrl(document_url
, top_frame_url
, extension
, error
))
378 return ACCESS_DENIED
;
380 if (HasTabSpecificPermissionToExecuteScript(tab_id
, top_frame_url
))
381 return ACCESS_ALLOWED
;
383 if (permitted_url_patterns
.MatchesURL(document_url
))
384 return ACCESS_ALLOWED
;
386 if (withheld_url_patterns
.MatchesURL(document_url
))
387 return ACCESS_WITHHELD
;
390 *error
= ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage
,
391 document_url
.spec());
393 return ACCESS_DENIED
;
396 } // namespace extensions