1 // Copyright (c) 2012 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 "content/browser/child_process_security_policy_impl.h"
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "content/browser/plugin_process_host.h"
14 #include "content/browser/site_instance_impl.h"
15 #include "content/public/browser/child_process_data.h"
16 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/common/bindings_policy.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/url_constants.h"
21 #include "net/base/filename_util.h"
22 #include "net/url_request/url_request.h"
24 #include "webkit/browser/fileapi/file_permission_policy.h"
25 #include "webkit/browser/fileapi/file_system_url.h"
26 #include "webkit/browser/fileapi/isolated_context.h"
27 #include "webkit/common/fileapi/file_system_util.h"
33 // Used internally only. These bit positions have no relationship to any
34 // underlying OS and can be changed to accommodate finer-grained permissions.
35 enum ChildProcessSecurityPermissions
{
36 READ_FILE_PERMISSION
= 1 << 0,
37 WRITE_FILE_PERMISSION
= 1 << 1,
38 CREATE_NEW_FILE_PERMISSION
= 1 << 2,
39 CREATE_OVERWRITE_FILE_PERMISSION
= 1 << 3,
40 DELETE_FILE_PERMISSION
= 1 << 4,
42 // Used by Media Galleries API
43 COPY_INTO_FILE_PERMISSION
= 1 << 5,
46 // Used internally only. Bitmasks that are actually used by the Grant* and Can*
47 // methods. These contain one or more ChildProcessSecurityPermissions.
48 enum ChildProcessSecurityGrants
{
49 READ_FILE_GRANT
= READ_FILE_PERMISSION
,
50 WRITE_FILE_GRANT
= WRITE_FILE_PERMISSION
,
52 CREATE_NEW_FILE_GRANT
= CREATE_NEW_FILE_PERMISSION
|
53 COPY_INTO_FILE_PERMISSION
,
55 CREATE_READ_WRITE_FILE_GRANT
= CREATE_NEW_FILE_PERMISSION
|
56 CREATE_OVERWRITE_FILE_PERMISSION
|
57 READ_FILE_PERMISSION
|
58 WRITE_FILE_PERMISSION
|
59 COPY_INTO_FILE_PERMISSION
|
60 DELETE_FILE_PERMISSION
,
62 COPY_INTO_FILE_GRANT
= COPY_INTO_FILE_PERMISSION
,
63 DELETE_FILE_GRANT
= DELETE_FILE_PERMISSION
,
68 // The SecurityState class is used to maintain per-child process security state
70 class ChildProcessSecurityPolicyImpl::SecurityState
{
73 : enabled_bindings_(0),
74 can_read_raw_cookies_(false),
75 can_send_midi_sysex_(false) { }
78 scheme_policy_
.clear();
79 fileapi::IsolatedContext
* isolated_context
=
80 fileapi::IsolatedContext::GetInstance();
81 for (FileSystemMap::iterator iter
= filesystem_permissions_
.begin();
82 iter
!= filesystem_permissions_
.end();
84 isolated_context
->RemoveReference(iter
->first
);
86 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions",
87 file_permissions_
.size());
90 // Grant permission to request URLs with the specified scheme.
91 void GrantScheme(const std::string
& scheme
) {
92 scheme_policy_
[scheme
] = true;
95 // Revoke permission to request URLs with the specified scheme.
96 void RevokeScheme(const std::string
& scheme
) {
97 scheme_policy_
[scheme
] = false;
100 // Grant certain permissions to a file.
101 void GrantPermissionsForFile(const base::FilePath
& file
, int permissions
) {
102 base::FilePath stripped
= file
.StripTrailingSeparators();
103 file_permissions_
[stripped
] |= permissions
;
104 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength",
105 stripped
.value().size());
108 // Grant navigation to a file but not the file:// scheme in general.
109 void GrantRequestOfSpecificFile(const base::FilePath
&file
) {
110 request_file_set_
.insert(file
.StripTrailingSeparators());
113 // Revokes all permissions granted to a file.
114 void RevokeAllPermissionsForFile(const base::FilePath
& file
) {
115 base::FilePath stripped
= file
.StripTrailingSeparators();
116 file_permissions_
.erase(stripped
);
117 request_file_set_
.erase(stripped
);
120 // Grant certain permissions to a file.
121 void GrantPermissionsForFileSystem(const std::string
& filesystem_id
,
123 if (!ContainsKey(filesystem_permissions_
, filesystem_id
))
124 fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id
);
125 filesystem_permissions_
[filesystem_id
] |= permissions
;
128 bool HasPermissionsForFileSystem(const std::string
& filesystem_id
,
130 FileSystemMap::const_iterator it
=
131 filesystem_permissions_
.find(filesystem_id
);
132 if (it
== filesystem_permissions_
.end())
134 return (it
->second
& permissions
) == permissions
;
137 #if defined(OS_ANDROID)
138 // Determine if the certain permissions have been granted to a content URI.
139 bool HasPermissionsForContentUri(const base::FilePath
& file
,
141 DCHECK(!file
.empty());
142 DCHECK(file
.IsContentUri());
145 base::FilePath file_path
= file
.StripTrailingSeparators();
146 FileMap::const_iterator it
= file_permissions_
.find(file_path
);
147 if (it
!= file_permissions_
.end())
148 return (it
->second
& permissions
) == permissions
;
153 void GrantBindings(int bindings
) {
154 enabled_bindings_
|= bindings
;
157 void GrantReadRawCookies() {
158 can_read_raw_cookies_
= true;
161 void RevokeReadRawCookies() {
162 can_read_raw_cookies_
= false;
165 void GrantPermissionForMidiSysEx() {
166 can_send_midi_sysex_
= true;
169 // Determine whether permission has been granted to request |url|.
170 bool CanRequestURL(const GURL
& url
) {
171 // Having permission to a scheme implies permssion to all of its URLs.
172 SchemeMap::const_iterator
judgment(scheme_policy_
.find(url
.scheme()));
173 if (judgment
!= scheme_policy_
.end())
174 return judgment
->second
;
176 // file:// URLs are more granular. The child may have been given
177 // permission to a specific file but not the file:// scheme in general.
178 if (url
.SchemeIs(url::kFileScheme
)) {
180 if (net::FileURLToFilePath(url
, &path
))
181 return ContainsKey(request_file_set_
, path
);
184 return false; // Unmentioned schemes are disallowed.
187 // Determine if the certain permissions have been granted to a file.
188 bool HasPermissionsForFile(const base::FilePath
& file
, int permissions
) {
189 #if defined(OS_ANDROID)
190 if (file
.IsContentUri())
191 return HasPermissionsForContentUri(file
, permissions
);
193 if (!permissions
|| file
.empty() || !file
.IsAbsolute())
195 base::FilePath current_path
= file
.StripTrailingSeparators();
196 base::FilePath last_path
;
198 while (current_path
!= last_path
) {
199 base::FilePath base_name
= current_path
.BaseName();
200 if (base_name
.value() == base::FilePath::kParentDirectory
) {
202 } else if (skip
> 0) {
203 if (base_name
.value() != base::FilePath::kCurrentDirectory
)
206 FileMap::const_iterator it
= file_permissions_
.find(current_path
);
207 if (it
!= file_permissions_
.end())
208 return (it
->second
& permissions
) == permissions
;
210 last_path
= current_path
;
211 current_path
= current_path
.DirName();
217 bool CanLoadPage(const GURL
& gurl
) {
218 if (origin_lock_
.is_empty())
221 // TODO(creis): We must pass the valid browser_context to convert hosted
222 // apps URLs. Currently, hosted apps cannot be loaded in this mode.
223 // See http://crbug.com/160576.
224 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
225 return origin_lock_
== site_gurl
;
228 bool CanAccessCookiesForOrigin(const GURL
& gurl
) {
229 if (origin_lock_
.is_empty())
231 // TODO(creis): We must pass the valid browser_context to convert hosted
232 // apps URLs. Currently, hosted apps cannot set cookies in this mode.
233 // See http://crbug.com/160576.
234 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
235 return origin_lock_
== site_gurl
;
238 bool CanSendCookiesForOrigin(const GURL
& gurl
) {
239 // We only block cross-site cookies on network requests if the
240 // --enable-strict-site-isolation flag is passed. This is expected to break
241 // compatibility with many sites. The similar --site-per-process flag only
242 // blocks JavaScript access to cross-site cookies (in
243 // CanAccessCookiesForOrigin).
244 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
245 if (!command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
))
248 if (origin_lock_
.is_empty())
250 // TODO(creis): We must pass the valid browser_context to convert hosted
251 // apps URLs. Currently, hosted apps cannot set cookies in this mode.
252 // See http://crbug.com/160576.
253 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
254 return origin_lock_
== site_gurl
;
257 void LockToOrigin(const GURL
& gurl
) {
261 bool has_web_ui_bindings() const {
262 return enabled_bindings_
& BINDINGS_POLICY_WEB_UI
;
265 bool can_read_raw_cookies() const {
266 return can_read_raw_cookies_
;
269 bool can_send_midi_sysex() const {
270 return can_send_midi_sysex_
;
274 typedef std::map
<std::string
, bool> SchemeMap
;
276 typedef int FilePermissionFlags
; // bit-set of base::File::Flags
277 typedef std::map
<base::FilePath
, FilePermissionFlags
> FileMap
;
278 typedef std::map
<std::string
, FilePermissionFlags
> FileSystemMap
;
279 typedef std::set
<base::FilePath
> FileSet
;
281 // Maps URL schemes to whether permission has been granted or revoked:
282 // |true| means the scheme has been granted.
283 // |false| means the scheme has been revoked.
284 // If a scheme is not present in the map, then it has never been granted
286 SchemeMap scheme_policy_
;
288 // The set of files the child process is permited to upload to the web.
289 FileMap file_permissions_
;
291 // The set of files the child process is permitted to load.
292 FileSet request_file_set_
;
294 int enabled_bindings_
;
296 bool can_read_raw_cookies_
;
298 bool can_send_midi_sysex_
;
302 // The set of isolated filesystems the child process is permitted to access.
303 FileSystemMap filesystem_permissions_
;
305 DISALLOW_COPY_AND_ASSIGN(SecurityState
);
308 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
309 // We know about these schemes and believe them to be safe.
310 RegisterWebSafeScheme(url::kHttpScheme
);
311 RegisterWebSafeScheme(url::kHttpsScheme
);
312 RegisterWebSafeScheme(url::kFtpScheme
);
313 RegisterWebSafeScheme(url::kDataScheme
);
314 RegisterWebSafeScheme("feed");
315 RegisterWebSafeScheme(url::kBlobScheme
);
316 RegisterWebSafeScheme(url::kFileSystemScheme
);
318 // We know about the following pseudo schemes and treat them specially.
319 RegisterPseudoScheme(url::kAboutScheme
);
320 RegisterPseudoScheme(url::kJavaScriptScheme
);
321 RegisterPseudoScheme(kViewSourceScheme
);
324 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
325 web_safe_schemes_
.clear();
326 pseudo_schemes_
.clear();
327 STLDeleteContainerPairSecondPointers(security_state_
.begin(),
328 security_state_
.end());
329 security_state_
.clear();
333 ChildProcessSecurityPolicy
* ChildProcessSecurityPolicy::GetInstance() {
334 return ChildProcessSecurityPolicyImpl::GetInstance();
337 ChildProcessSecurityPolicyImpl
* ChildProcessSecurityPolicyImpl::GetInstance() {
338 return Singleton
<ChildProcessSecurityPolicyImpl
>::get();
341 void ChildProcessSecurityPolicyImpl::Add(int child_id
) {
342 base::AutoLock
lock(lock_
);
346 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id
,
347 int main_render_process_id
) {
348 base::AutoLock
lock(lock_
);
350 worker_map_
[child_id
] = main_render_process_id
;
353 void ChildProcessSecurityPolicyImpl::Remove(int child_id
) {
354 base::AutoLock
lock(lock_
);
355 SecurityStateMap::iterator it
= security_state_
.find(child_id
);
356 if (it
== security_state_
.end())
357 return; // May be called multiple times.
360 security_state_
.erase(it
);
361 worker_map_
.erase(child_id
);
364 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
365 const std::string
& scheme
) {
366 base::AutoLock
lock(lock_
);
367 DCHECK_EQ(0U, web_safe_schemes_
.count(scheme
)) << "Add schemes at most once.";
368 DCHECK_EQ(0U, pseudo_schemes_
.count(scheme
))
369 << "Web-safe implies not pseudo.";
371 web_safe_schemes_
.insert(scheme
);
374 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
375 const std::string
& scheme
) {
376 base::AutoLock
lock(lock_
);
378 return ContainsKey(web_safe_schemes_
, scheme
);
381 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
382 const std::string
& scheme
) {
383 base::AutoLock
lock(lock_
);
384 DCHECK_EQ(0U, pseudo_schemes_
.count(scheme
)) << "Add schemes at most once.";
385 DCHECK_EQ(0U, web_safe_schemes_
.count(scheme
))
386 << "Pseudo implies not web-safe.";
388 pseudo_schemes_
.insert(scheme
);
391 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
392 const std::string
& scheme
) {
393 base::AutoLock
lock(lock_
);
395 return ContainsKey(pseudo_schemes_
, scheme
);
398 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
399 int child_id
, const GURL
& url
) {
402 return; // Can't grant the capability to request invalid URLs.
404 if (IsWebSafeScheme(url
.scheme()))
405 return; // The scheme has already been whitelisted for every child process.
407 if (IsPseudoScheme(url
.scheme())) {
408 // The view-source scheme is a special case of a pseudo-URL that eventually
409 // results in requesting its embedded URL.
410 if (url
.SchemeIs(kViewSourceScheme
)) {
411 // URLs with the view-source scheme typically look like:
412 // view-source:http://www.google.com/a
413 // In order to request these URLs, the child_id needs to be able to
414 // request the embedded URL.
415 GrantRequestURL(child_id
, GURL(url
.GetContent()));
418 return; // Can't grant the capability to request pseudo schemes.
422 base::AutoLock
lock(lock_
);
423 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
424 if (state
== security_state_
.end())
427 // When the child process has been commanded to request this scheme,
428 // we grant it the capability to request all URLs of that scheme.
429 state
->second
->GrantScheme(url
.scheme());
433 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
436 if (!url
.SchemeIs(url::kFileScheme
))
440 base::AutoLock
lock(lock_
);
441 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
442 if (state
== security_state_
.end())
445 // When the child process has been commanded to request a file:// URL,
446 // then we grant it the capability for that URL only.
448 if (net::FileURLToFilePath(url
, &path
))
449 state
->second
->GrantRequestOfSpecificFile(path
);
453 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id
,
454 const base::FilePath
& file
) {
455 GrantPermissionsForFile(child_id
, file
, READ_FILE_GRANT
);
458 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
459 int child_id
, const base::FilePath
& file
) {
460 GrantPermissionsForFile(child_id
, file
, CREATE_READ_WRITE_FILE_GRANT
);
463 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id
,
464 const base::FilePath
& dir
) {
465 GrantPermissionsForFile(child_id
, dir
, COPY_INTO_FILE_GRANT
);
468 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
469 int child_id
, const base::FilePath
& dir
) {
470 GrantPermissionsForFile(child_id
, dir
, DELETE_FILE_GRANT
);
473 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
474 int child_id
, const base::FilePath
& file
, int permissions
) {
475 base::AutoLock
lock(lock_
);
477 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
478 if (state
== security_state_
.end())
481 state
->second
->GrantPermissionsForFile(file
, permissions
);
484 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
485 int child_id
, const base::FilePath
& file
) {
486 base::AutoLock
lock(lock_
);
488 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
489 if (state
== security_state_
.end())
492 state
->second
->RevokeAllPermissionsForFile(file
);
495 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
496 int child_id
, const std::string
& filesystem_id
) {
497 GrantPermissionsForFileSystem(child_id
, filesystem_id
, READ_FILE_GRANT
);
500 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
501 int child_id
, const std::string
& filesystem_id
) {
502 GrantPermissionsForFileSystem(child_id
, filesystem_id
, WRITE_FILE_GRANT
);
505 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
506 int child_id
, const std::string
& filesystem_id
) {
507 GrantPermissionsForFileSystem(child_id
, filesystem_id
, CREATE_NEW_FILE_GRANT
);
510 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
511 int child_id
, const std::string
& filesystem_id
) {
512 GrantPermissionsForFileSystem(
513 child_id
, filesystem_id
, CREATE_READ_WRITE_FILE_GRANT
);
516 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
517 int child_id
, const std::string
& filesystem_id
) {
518 GrantPermissionsForFileSystem(child_id
, filesystem_id
, COPY_INTO_FILE_GRANT
);
521 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
522 int child_id
, const std::string
& filesystem_id
) {
523 GrantPermissionsForFileSystem(child_id
, filesystem_id
, DELETE_FILE_GRANT
);
526 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id
) {
527 base::AutoLock
lock(lock_
);
529 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
530 if (state
== security_state_
.end())
533 state
->second
->GrantPermissionForMidiSysEx();
536 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id
,
537 const std::string
& scheme
) {
538 base::AutoLock
lock(lock_
);
540 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
541 if (state
== security_state_
.end())
544 state
->second
->GrantScheme(scheme
);
547 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id
) {
548 base::AutoLock
lock(lock_
);
550 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
551 if (state
== security_state_
.end())
554 state
->second
->GrantBindings(BINDINGS_POLICY_WEB_UI
);
556 // Web UI bindings need the ability to request chrome: URLs.
557 state
->second
->GrantScheme(kChromeUIScheme
);
559 // Web UI pages can contain links to file:// URLs.
560 state
->second
->GrantScheme(url::kFileScheme
);
563 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id
) {
564 base::AutoLock
lock(lock_
);
566 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
567 if (state
== security_state_
.end())
570 state
->second
->GrantReadRawCookies();
573 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id
) {
574 base::AutoLock
lock(lock_
);
576 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
577 if (state
== security_state_
.end())
580 state
->second
->RevokeReadRawCookies();
583 bool ChildProcessSecurityPolicyImpl::CanLoadPage(
586 ResourceType::Type resource_type
) {
587 // If --site-per-process flag is passed, we should enforce
588 // stronger security restrictions on page navigation.
589 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
) &&
590 ResourceType::IsFrame(resource_type
)) {
591 // TODO(nasko): Do the proper check for site-per-process, once
592 // out-of-process iframes is ready to go.
598 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
599 int child_id
, const GURL
& url
) {
601 return false; // Can't request invalid URLs.
603 if (IsWebSafeScheme(url
.scheme()))
604 return true; // The scheme has been white-listed for every child process.
606 if (IsPseudoScheme(url
.scheme())) {
607 // There are a number of special cases for pseudo schemes.
609 if (url
.SchemeIs(kViewSourceScheme
)) {
610 // A view-source URL is allowed if the child process is permitted to
611 // request the embedded URL. Careful to avoid pointless recursion.
612 GURL
child_url(url
.GetContent());
613 if (child_url
.SchemeIs(kViewSourceScheme
) &&
614 url
.SchemeIs(kViewSourceScheme
))
617 return CanRequestURL(child_id
, child_url
);
620 if (LowerCaseEqualsASCII(url
.spec(), url::kAboutBlankURL
))
621 return true; // Every child process can request <about:blank>.
623 // URLs like <about:memory> and <about:crash> shouldn't be requestable by
624 // any child process. Also, this case covers <javascript:...>, which should
625 // be handled internally by the process and not kicked up to the browser.
629 if (!GetContentClient()->browser()->IsHandledURL(url
) &&
630 !net::URLRequest::IsHandledURL(url
)) {
631 return true; // This URL request is destined for ShellExecute.
635 base::AutoLock
lock(lock_
);
637 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
638 if (state
== security_state_
.end())
641 // Otherwise, we consult the child process's security state to see if it is
642 // allowed to request the URL.
643 return state
->second
->CanRequestURL(url
);
647 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id
,
648 const base::FilePath
& file
) {
649 return HasPermissionsForFile(child_id
, file
, READ_FILE_GRANT
);
652 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
654 const base::FilePath
& file
) {
655 return HasPermissionsForFile(child_id
, file
, CREATE_READ_WRITE_FILE_GRANT
);
658 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
659 int child_id
, const std::string
& filesystem_id
) {
660 return HasPermissionsForFileSystem(child_id
, filesystem_id
, READ_FILE_GRANT
);
663 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
664 int child_id
, const std::string
& filesystem_id
) {
665 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
666 READ_FILE_GRANT
| WRITE_FILE_GRANT
);
669 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
670 int child_id
, const std::string
& filesystem_id
) {
671 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
672 COPY_INTO_FILE_GRANT
);
675 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
676 int child_id
, const std::string
& filesystem_id
) {
677 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
681 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
682 int child_id
, const base::FilePath
& file
, int permissions
) {
683 base::AutoLock
lock(lock_
);
684 bool result
= ChildProcessHasPermissionsForFile(child_id
, file
, permissions
);
686 // If this is a worker thread that has no access to a given file,
687 // let's check that its renderer process has access to that file instead.
688 WorkerToMainProcessMap::iterator iter
= worker_map_
.find(child_id
);
689 if (iter
!= worker_map_
.end() && iter
->second
!= 0) {
690 result
= ChildProcessHasPermissionsForFile(iter
->second
,
698 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
699 int child_id
, const fileapi::FileSystemURL
& url
, int permissions
) {
703 if (url
.path().ReferencesParent())
706 // Any write access is disallowed on the root path.
707 if (fileapi::VirtualPath::IsRootPath(url
.path()) &&
708 (permissions
& ~READ_FILE_GRANT
)) {
712 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
) {
713 // When Isolated filesystems is overlayed on top of another filesystem,
714 // its per-filesystem permission overrides the underlying filesystem
716 return HasPermissionsForFileSystem(
717 child_id
, url
.mount_filesystem_id(), permissions
);
720 FileSystemPermissionPolicyMap::iterator found
=
721 file_system_policy_map_
.find(url
.type());
722 if (found
== file_system_policy_map_
.end())
725 if ((found
->second
& fileapi::FILE_PERMISSION_READ_ONLY
) &&
726 permissions
& ~READ_FILE_GRANT
) {
730 if (found
->second
& fileapi::FILE_PERMISSION_USE_FILE_PERMISSION
)
731 return HasPermissionsForFile(child_id
, url
.path(), permissions
);
733 if (found
->second
& fileapi::FILE_PERMISSION_SANDBOX
)
739 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
741 const fileapi::FileSystemURL
& url
) {
742 return HasPermissionsForFileSystemFile(child_id
, url
, READ_FILE_GRANT
);
745 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
747 const fileapi::FileSystemURL
& url
) {
748 return HasPermissionsForFileSystemFile(child_id
, url
, WRITE_FILE_GRANT
);
751 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
753 const fileapi::FileSystemURL
& url
) {
754 return HasPermissionsForFileSystemFile(child_id
, url
, CREATE_NEW_FILE_GRANT
);
757 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
759 const fileapi::FileSystemURL
& url
) {
760 return HasPermissionsForFileSystemFile(child_id
, url
,
761 CREATE_READ_WRITE_FILE_GRANT
);
764 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
766 const fileapi::FileSystemURL
& url
) {
767 return HasPermissionsForFileSystemFile(child_id
, url
, COPY_INTO_FILE_GRANT
);
770 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
772 const fileapi::FileSystemURL
& url
) {
773 return HasPermissionsForFileSystemFile(child_id
, url
, DELETE_FILE_GRANT
);
776 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id
) {
777 base::AutoLock
lock(lock_
);
779 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
780 if (state
== security_state_
.end())
783 return state
->second
->has_web_ui_bindings();
786 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id
) {
787 base::AutoLock
lock(lock_
);
789 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
790 if (state
== security_state_
.end())
793 return state
->second
->can_read_raw_cookies();
796 void ChildProcessSecurityPolicyImpl::AddChild(int child_id
) {
797 if (security_state_
.count(child_id
) != 0) {
798 NOTREACHED() << "Add child process at most once.";
802 security_state_
[child_id
] = new SecurityState();
805 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
806 int child_id
, const base::FilePath
& file
, int permissions
) {
807 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
808 if (state
== security_state_
.end())
810 return state
->second
->HasPermissionsForFile(file
, permissions
);
813 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
814 int child_id
, const GURL
& gurl
) {
815 base::AutoLock
lock(lock_
);
816 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
817 if (state
== security_state_
.end())
819 return state
->second
->CanAccessCookiesForOrigin(gurl
);
822 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id
,
824 for (PluginProcessHostIterator iter
; !iter
.Done(); ++iter
) {
825 if (iter
.GetData().id
== child_id
) {
826 if (iter
.GetData().process_type
== PROCESS_TYPE_PLUGIN
) {
827 // NPAPI plugin processes are unsandboxed and so are trusted. Plugins
828 // can make request to any origin.
835 base::AutoLock
lock(lock_
);
836 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
837 if (state
== security_state_
.end())
839 return state
->second
->CanSendCookiesForOrigin(gurl
);
842 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id
,
844 // "gurl" can be currently empty in some cases, such as file://blah.
845 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL
, gurl
) == gurl
);
846 base::AutoLock
lock(lock_
);
847 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
848 DCHECK(state
!= security_state_
.end());
849 state
->second
->LockToOrigin(gurl
);
852 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
854 const std::string
& filesystem_id
,
856 base::AutoLock
lock(lock_
);
858 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
859 if (state
== security_state_
.end())
861 state
->second
->GrantPermissionsForFileSystem(filesystem_id
, permission
);
864 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
866 const std::string
& filesystem_id
,
868 base::AutoLock
lock(lock_
);
870 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
871 if (state
== security_state_
.end())
873 return state
->second
->HasPermissionsForFileSystem(filesystem_id
, permission
);
876 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
877 fileapi::FileSystemType type
,
879 base::AutoLock
lock(lock_
);
880 file_system_policy_map_
[type
] = policy
;
883 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id
) {
884 base::AutoLock
lock(lock_
);
886 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
887 if (state
== security_state_
.end())
890 return state
->second
->can_send_midi_sysex();
893 } // namespace content