Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / common / permissions / permissions_data.cc
blob50c25f0eb29ae21a59cd7eedd60cdd4a99ec799e
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"
19 #include "url/gurl.h"
20 #include "url/url_constants.h"
22 namespace extensions {
24 namespace {
26 PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
28 } // namespace
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() {
46 // static
47 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
48 g_policy_delegate = delegate;
51 // static
52 bool PermissionsData::CanSilentlyIncreasePermissions(
53 const Extension* extension) {
54 return extension->location() != Manifest::INTERNAL;
57 // static
58 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
59 if (extension->location() == Manifest::COMPONENT)
60 return true;
62 const ExtensionsClient::ScriptingWhitelist& whitelist =
63 ExtensionsClient::Get()->GetScriptingWhitelist();
65 return std::find(whitelist.begin(), whitelist.end(), extension->id()) !=
66 whitelist.end();
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");
75 // static
76 bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
77 const GURL& top_frame_url,
78 const Extension* extension,
79 std::string* error) {
80 if (extension && CanExecuteScriptEverywhere(extension))
81 return false;
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) {
86 if (error) {
87 *error = ErrorUtils::FormatErrorMessage(
88 manifest_errors::kCannotAccessPage,
89 document_url.spec());
91 return true;
94 if (!ExtensionsClient::Get()->IsScriptableURL(document_url, error))
95 return true;
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) {
101 if (error)
102 *error = manifest_errors::kCannotAccessChromeUrl;
103 return true;
106 if (extension && top_frame_url.SchemeIs(kExtensionScheme) &&
107 top_frame_url.host() != extension->id() && !allow_on_chrome_urls) {
108 if (error)
109 *error = manifest_errors::kCannotAccessExtensionUrl;
110 return true;
113 return false;
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(
125 int tab_id,
126 scoped_refptr<const PermissionSet> permissions) const {
127 base::AutoLock auto_lock(runtime_lock_);
128 CHECK_GE(tab_id, 0);
129 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id);
130 if (iter == tab_specific_permissions_.end())
131 tab_specific_permissions_[tab_id] = permissions;
132 else
133 iter->second =
134 PermissionSet::CreateUnion(iter->second.get(), permissions.get());
137 void PermissionsData::ClearTabSpecificPermissions(int tab_id) const {
138 base::AutoLock auto_lock(runtime_lock_);
139 CHECK_GE(tab_id, 0);
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(
153 int tab_id,
154 APIPermission::ID permission) const {
155 if (HasAPIPermission(permission))
156 return true;
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();
188 } else {
189 return PermissionMessageProvider::Get()->GetPermissionMessages(
190 active_permissions(), manifest_type_);
194 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings()
195 const {
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,
220 int tab_id,
221 int process_id,
222 std::string* error) const {
223 AccessType result = CanRunOnPage(extension,
224 document_url,
225 top_frame_url,
226 tab_id,
227 process_id,
228 active_permissions()->explicit_hosts(),
229 withheld_permissions()->explicit_hosts(),
230 error);
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,
239 int tab_id,
240 int process_id,
241 std::string* error) const {
242 return CanRunOnPage(extension,
243 document_url,
244 top_frame_url,
245 tab_id,
246 process_id,
247 active_permissions()->explicit_hosts(),
248 withheld_permissions()->explicit_hosts(),
249 error);
252 bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension,
253 const GURL& document_url,
254 const GURL& top_frame_url,
255 int tab_id,
256 int process_id,
257 std::string* error) const {
258 AccessType result = CanRunOnPage(extension,
259 document_url,
260 top_frame_url,
261 tab_id,
262 process_id,
263 active_permissions()->scriptable_hosts(),
264 withheld_permissions()->scriptable_hosts(),
265 error);
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,
274 int tab_id,
275 int process_id,
276 std::string* error) const {
277 return CanRunOnPage(extension,
278 document_url,
279 top_frame_url,
280 tab_id,
281 process_id,
282 active_permissions()->scriptable_hosts(),
283 withheld_permissions()->scriptable_hosts(),
284 error);
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))
293 return true;
295 if (tab_id >= 0) {
296 scoped_refptr<const PermissionSet> tab_permissions =
297 GetTabSpecificPermissions(tab_id);
298 if (tab_permissions.get() &&
299 tab_permissions->HasAPIPermission(APIPermission::kTab)) {
300 return true;
302 if (error)
303 *error = manifest_errors::kActiveTabPermissionNotGranted;
304 return false;
307 if (error)
308 *error = manifest_errors::kAllURLOrActiveTabNeeded;
309 return false;
312 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
313 int tab_id) const {
314 base::AutoLock auto_lock(runtime_lock_);
315 CHECK_GE(tab_id, 0);
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(
322 int tab_id,
323 const GURL& url) const {
324 if (tab_id >= 0) {
325 scoped_refptr<const PermissionSet> tab_permissions =
326 GetTabSpecificPermissions(tab_id);
327 if (tab_permissions.get() &&
328 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
329 return true;
332 return false;
335 PermissionsData::AccessType PermissionsData::CanRunOnPage(
336 const Extension* extension,
337 const GURL& document_url,
338 const GURL& top_frame_url,
339 int tab_id,
340 int process_id,
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;
362 if (error) {
363 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
364 document_url.spec());
366 return ACCESS_DENIED;
369 } // namespace extensions