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/platform_file.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h"
14 #include "content/browser/plugin_process_host.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/public/browser/child_process_data.h"
17 #include "content/public/browser/content_browser_client.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/common/bindings_policy.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "net/base/net_util.h"
23 #include "net/url_request/url_request.h"
25 #include "webkit/browser/fileapi/file_permission_policy.h"
26 #include "webkit/browser/fileapi/file_system_url.h"
27 #include "webkit/browser/fileapi/isolated_context.h"
28 #include "webkit/common/fileapi/file_system_util.h"
34 // Used internally only. These bit positions have no relationship to any
35 // underlying OS and can be changed to accommodate finer-grained permissions.
36 enum ChildProcessSecurityPermissions
{
37 READ_FILE_PERMISSION
= 1 << 0,
38 WRITE_FILE_PERMISSION
= 1 << 1,
39 CREATE_NEW_FILE_PERMISSION
= 1 << 2,
40 CREATE_OVERWRITE_FILE_PERMISSION
= 1 << 3,
41 DELETE_FILE_PERMISSION
= 1 << 4,
43 // Used by Media Galleries API
44 COPY_INTO_FILE_PERMISSION
= 1 << 5,
47 // Used internally only. Bitmasks that are actually used by the Grant* and Can*
48 // methods. These contain one or more ChildProcessSecurityPermissions.
49 enum ChildProcessSecurityGrants
{
50 READ_FILE_GRANT
= READ_FILE_PERMISSION
,
51 WRITE_FILE_GRANT
= WRITE_FILE_PERMISSION
,
53 CREATE_NEW_FILE_GRANT
= CREATE_NEW_FILE_PERMISSION
|
54 COPY_INTO_FILE_PERMISSION
,
56 CREATE_READ_WRITE_FILE_GRANT
= CREATE_NEW_FILE_PERMISSION
|
57 CREATE_OVERWRITE_FILE_PERMISSION
|
58 READ_FILE_PERMISSION
|
59 WRITE_FILE_PERMISSION
|
60 COPY_INTO_FILE_PERMISSION
|
61 DELETE_FILE_PERMISSION
,
63 COPY_INTO_FILE_GRANT
= COPY_INTO_FILE_PERMISSION
,
64 DELETE_FILE_GRANT
= DELETE_FILE_PERMISSION
,
69 // The SecurityState class is used to maintain per-child process security state
71 class ChildProcessSecurityPolicyImpl::SecurityState
{
74 : enabled_bindings_(0),
75 can_read_raw_cookies_(false),
76 can_send_midi_sysex_(false) { }
79 scheme_policy_
.clear();
80 fileapi::IsolatedContext
* isolated_context
=
81 fileapi::IsolatedContext::GetInstance();
82 for (FileSystemMap::iterator iter
= filesystem_permissions_
.begin();
83 iter
!= filesystem_permissions_
.end();
85 isolated_context
->RemoveReference(iter
->first
);
87 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions",
88 file_permissions_
.size());
91 // Grant permission to request URLs with the specified scheme.
92 void GrantScheme(const std::string
& scheme
) {
93 scheme_policy_
[scheme
] = true;
96 // Revoke permission to request URLs with the specified scheme.
97 void RevokeScheme(const std::string
& scheme
) {
98 scheme_policy_
[scheme
] = false;
101 // Grant certain permissions to a file.
102 void GrantPermissionsForFile(const base::FilePath
& file
, int permissions
) {
103 base::FilePath stripped
= file
.StripTrailingSeparators();
104 file_permissions_
[stripped
] |= permissions
;
105 UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength",
106 stripped
.value().size());
109 // Grant navigation to a file but not the file:// scheme in general.
110 void GrantRequestOfSpecificFile(const base::FilePath
&file
) {
111 request_file_set_
.insert(file
.StripTrailingSeparators());
114 // Revokes all permissions granted to a file.
115 void RevokeAllPermissionsForFile(const base::FilePath
& file
) {
116 base::FilePath stripped
= file
.StripTrailingSeparators();
117 file_permissions_
.erase(stripped
);
118 request_file_set_
.erase(stripped
);
121 // Grant certain permissions to a file.
122 void GrantPermissionsForFileSystem(const std::string
& filesystem_id
,
124 if (!ContainsKey(filesystem_permissions_
, filesystem_id
))
125 fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id
);
126 filesystem_permissions_
[filesystem_id
] |= permissions
;
129 bool HasPermissionsForFileSystem(const std::string
& filesystem_id
,
131 FileSystemMap::const_iterator it
=
132 filesystem_permissions_
.find(filesystem_id
);
133 if (it
== filesystem_permissions_
.end())
135 return (it
->second
& permissions
) == permissions
;
138 #if defined(OS_ANDROID)
139 // Determine if the certain permissions have been granted to a content URI.
140 bool HasPermissionsForContentUri(const base::FilePath
& file
,
142 DCHECK(!file
.empty());
143 DCHECK(file
.IsContentUri());
146 base::FilePath file_path
= file
.StripTrailingSeparators();
147 FileMap::const_iterator it
= file_permissions_
.find(file_path
);
148 if (it
!= file_permissions_
.end())
149 return (it
->second
& permissions
) == permissions
;
154 void GrantBindings(int bindings
) {
155 enabled_bindings_
|= bindings
;
158 void GrantReadRawCookies() {
159 can_read_raw_cookies_
= true;
162 void RevokeReadRawCookies() {
163 can_read_raw_cookies_
= false;
166 void GrantPermissionForMidiSysEx() {
167 can_send_midi_sysex_
= true;
170 // Determine whether permission has been granted to request |url|.
171 bool CanRequestURL(const GURL
& url
) {
172 // Having permission to a scheme implies permssion to all of its URLs.
173 SchemeMap::const_iterator
judgment(scheme_policy_
.find(url
.scheme()));
174 if (judgment
!= scheme_policy_
.end())
175 return judgment
->second
;
177 // file:// URLs are more granular. The child may have been given
178 // permission to a specific file but not the file:// scheme in general.
179 if (url
.SchemeIs(kFileScheme
)) {
181 if (net::FileURLToFilePath(url
, &path
))
182 return ContainsKey(request_file_set_
, path
);
185 return false; // Unmentioned schemes are disallowed.
188 // Determine if the certain permissions have been granted to a file.
189 bool HasPermissionsForFile(const base::FilePath
& file
, int permissions
) {
190 #if defined(OS_ANDROID)
191 if (file
.IsContentUri())
192 return HasPermissionsForContentUri(file
, permissions
);
194 if (!permissions
|| file
.empty() || !file
.IsAbsolute())
196 base::FilePath current_path
= file
.StripTrailingSeparators();
197 base::FilePath last_path
;
199 while (current_path
!= last_path
) {
200 base::FilePath base_name
= current_path
.BaseName();
201 if (base_name
.value() == base::FilePath::kParentDirectory
) {
203 } else if (skip
> 0) {
204 if (base_name
.value() != base::FilePath::kCurrentDirectory
)
207 FileMap::const_iterator it
= file_permissions_
.find(current_path
);
208 if (it
!= file_permissions_
.end())
209 return (it
->second
& permissions
) == permissions
;
211 last_path
= current_path
;
212 current_path
= current_path
.DirName();
218 bool CanLoadPage(const GURL
& gurl
) {
219 if (origin_lock_
.is_empty())
222 // TODO(creis): We must pass the valid browser_context to convert hosted
223 // apps URLs. Currently, hosted apps cannot be loaded in this mode.
224 // See http://crbug.com/160576.
225 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
226 return origin_lock_
== site_gurl
;
229 bool CanAccessCookiesForOrigin(const GURL
& gurl
) {
230 if (origin_lock_
.is_empty())
232 // TODO(creis): We must pass the valid browser_context to convert hosted
233 // apps URLs. Currently, hosted apps cannot set cookies in this mode.
234 // See http://crbug.com/160576.
235 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
236 return origin_lock_
== site_gurl
;
239 bool CanSendCookiesForOrigin(const GURL
& gurl
) {
240 // We only block cross-site cookies on network requests if the
241 // --enable-strict-site-isolation flag is passed. This is expected to break
242 // compatibility with many sites. The similar --site-per-process flag only
243 // blocks JavaScript access to cross-site cookies (in
244 // CanAccessCookiesForOrigin).
245 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
246 if (!command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
))
249 if (origin_lock_
.is_empty())
251 // TODO(creis): We must pass the valid browser_context to convert hosted
252 // apps URLs. Currently, hosted apps cannot set cookies in this mode.
253 // See http://crbug.com/160576.
254 GURL site_gurl
= SiteInstanceImpl::GetSiteForURL(NULL
, gurl
);
255 return origin_lock_
== site_gurl
;
258 void LockToOrigin(const GURL
& gurl
) {
262 bool has_web_ui_bindings() const {
263 return enabled_bindings_
& BINDINGS_POLICY_WEB_UI
;
266 bool can_read_raw_cookies() const {
267 return can_read_raw_cookies_
;
270 bool can_send_midi_sysex() const {
271 return can_send_midi_sysex_
;
275 typedef std::map
<std::string
, bool> SchemeMap
;
277 typedef int FilePermissionFlags
; // bit-set of PlatformFileFlags
278 typedef std::map
<base::FilePath
, FilePermissionFlags
> FileMap
;
279 typedef std::map
<std::string
, FilePermissionFlags
> FileSystemMap
;
280 typedef std::set
<base::FilePath
> FileSet
;
282 // Maps URL schemes to whether permission has been granted or revoked:
283 // |true| means the scheme has been granted.
284 // |false| means the scheme has been revoked.
285 // If a scheme is not present in the map, then it has never been granted
287 SchemeMap scheme_policy_
;
289 // The set of files the child process is permited to upload to the web.
290 FileMap file_permissions_
;
292 // The set of files the child process is permitted to load.
293 FileSet request_file_set_
;
295 int enabled_bindings_
;
297 bool can_read_raw_cookies_
;
299 bool can_send_midi_sysex_
;
303 // The set of isolated filesystems the child process is permitted to access.
304 FileSystemMap filesystem_permissions_
;
306 DISALLOW_COPY_AND_ASSIGN(SecurityState
);
309 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
310 // We know about these schemes and believe them to be safe.
311 RegisterWebSafeScheme(kHttpScheme
);
312 RegisterWebSafeScheme(kHttpsScheme
);
313 RegisterWebSafeScheme(kFtpScheme
);
314 RegisterWebSafeScheme(kDataScheme
);
315 RegisterWebSafeScheme("feed");
316 RegisterWebSafeScheme(chrome::kBlobScheme
);
317 RegisterWebSafeScheme(kFileSystemScheme
);
319 // We know about the following pseudo schemes and treat them specially.
320 RegisterPseudoScheme(chrome::kAboutScheme
);
321 RegisterPseudoScheme(kJavaScriptScheme
);
322 RegisterPseudoScheme(kViewSourceScheme
);
325 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
326 web_safe_schemes_
.clear();
327 pseudo_schemes_
.clear();
328 STLDeleteContainerPairSecondPointers(security_state_
.begin(),
329 security_state_
.end());
330 security_state_
.clear();
334 ChildProcessSecurityPolicy
* ChildProcessSecurityPolicy::GetInstance() {
335 return ChildProcessSecurityPolicyImpl::GetInstance();
338 ChildProcessSecurityPolicyImpl
* ChildProcessSecurityPolicyImpl::GetInstance() {
339 return Singleton
<ChildProcessSecurityPolicyImpl
>::get();
342 void ChildProcessSecurityPolicyImpl::Add(int child_id
) {
343 base::AutoLock
lock(lock_
);
347 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id
,
348 int main_render_process_id
) {
349 base::AutoLock
lock(lock_
);
351 worker_map_
[child_id
] = main_render_process_id
;
354 void ChildProcessSecurityPolicyImpl::Remove(int child_id
) {
355 base::AutoLock
lock(lock_
);
356 SecurityStateMap::iterator it
= security_state_
.find(child_id
);
357 if (it
== security_state_
.end())
358 return; // May be called multiple times.
361 security_state_
.erase(it
);
362 worker_map_
.erase(child_id
);
365 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
366 const std::string
& scheme
) {
367 base::AutoLock
lock(lock_
);
368 DCHECK_EQ(0U, web_safe_schemes_
.count(scheme
)) << "Add schemes at most once.";
369 DCHECK_EQ(0U, pseudo_schemes_
.count(scheme
))
370 << "Web-safe implies not pseudo.";
372 web_safe_schemes_
.insert(scheme
);
375 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
376 const std::string
& scheme
) {
377 base::AutoLock
lock(lock_
);
379 return ContainsKey(web_safe_schemes_
, scheme
);
382 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
383 const std::string
& scheme
) {
384 base::AutoLock
lock(lock_
);
385 DCHECK_EQ(0U, pseudo_schemes_
.count(scheme
)) << "Add schemes at most once.";
386 DCHECK_EQ(0U, web_safe_schemes_
.count(scheme
))
387 << "Pseudo implies not web-safe.";
389 pseudo_schemes_
.insert(scheme
);
392 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
393 const std::string
& scheme
) {
394 base::AutoLock
lock(lock_
);
396 return ContainsKey(pseudo_schemes_
, scheme
);
399 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
400 int child_id
, const GURL
& url
) {
403 return; // Can't grant the capability to request invalid URLs.
405 if (IsWebSafeScheme(url
.scheme()))
406 return; // The scheme has already been whitelisted for every child process.
408 if (IsPseudoScheme(url
.scheme())) {
409 // The view-source scheme is a special case of a pseudo-URL that eventually
410 // results in requesting its embedded URL.
411 if (url
.SchemeIs(kViewSourceScheme
)) {
412 // URLs with the view-source scheme typically look like:
413 // view-source:http://www.google.com/a
414 // In order to request these URLs, the child_id needs to be able to
415 // request the embedded URL.
416 GrantRequestURL(child_id
, GURL(url
.GetContent()));
419 return; // Can't grant the capability to request pseudo schemes.
423 base::AutoLock
lock(lock_
);
424 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
425 if (state
== security_state_
.end())
428 // When the child process has been commanded to request this scheme,
429 // we grant it the capability to request all URLs of that scheme.
430 state
->second
->GrantScheme(url
.scheme());
434 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
437 if (!url
.SchemeIs(kFileScheme
))
441 base::AutoLock
lock(lock_
);
442 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
443 if (state
== security_state_
.end())
446 // When the child process has been commanded to request a file:// URL,
447 // then we grant it the capability for that URL only.
449 if (net::FileURLToFilePath(url
, &path
))
450 state
->second
->GrantRequestOfSpecificFile(path
);
454 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id
,
455 const base::FilePath
& file
) {
456 GrantPermissionsForFile(child_id
, file
, READ_FILE_GRANT
);
459 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
460 int child_id
, const base::FilePath
& file
) {
461 GrantPermissionsForFile(child_id
, file
, CREATE_READ_WRITE_FILE_GRANT
);
464 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
465 int child_id
, const base::FilePath
& file
, int permissions
) {
466 base::AutoLock
lock(lock_
);
468 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
469 if (state
== security_state_
.end())
472 state
->second
->GrantPermissionsForFile(file
, permissions
);
475 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
476 int child_id
, const base::FilePath
& file
) {
477 base::AutoLock
lock(lock_
);
479 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
480 if (state
== security_state_
.end())
483 state
->second
->RevokeAllPermissionsForFile(file
);
486 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
487 int child_id
, const std::string
& filesystem_id
) {
488 GrantPermissionsForFileSystem(child_id
, filesystem_id
, READ_FILE_GRANT
);
491 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
492 int child_id
, const std::string
& filesystem_id
) {
493 GrantPermissionsForFileSystem(child_id
, filesystem_id
, WRITE_FILE_GRANT
);
496 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
497 int child_id
, const std::string
& filesystem_id
) {
498 GrantPermissionsForFileSystem(child_id
, filesystem_id
, CREATE_NEW_FILE_GRANT
);
501 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
502 int child_id
, const std::string
& filesystem_id
) {
503 GrantPermissionsForFileSystem(
504 child_id
, filesystem_id
, CREATE_READ_WRITE_FILE_GRANT
);
507 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
508 int child_id
, const std::string
& filesystem_id
) {
509 GrantPermissionsForFileSystem(child_id
, filesystem_id
, COPY_INTO_FILE_GRANT
);
512 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
513 int child_id
, const std::string
& filesystem_id
) {
514 GrantPermissionsForFileSystem(child_id
, filesystem_id
, DELETE_FILE_GRANT
);
517 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id
) {
518 base::AutoLock
lock(lock_
);
520 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
521 if (state
== security_state_
.end())
524 state
->second
->GrantPermissionForMidiSysEx();
527 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id
,
528 const std::string
& scheme
) {
529 base::AutoLock
lock(lock_
);
531 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
532 if (state
== security_state_
.end())
535 state
->second
->GrantScheme(scheme
);
538 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id
) {
539 base::AutoLock
lock(lock_
);
541 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
542 if (state
== security_state_
.end())
545 state
->second
->GrantBindings(BINDINGS_POLICY_WEB_UI
);
547 // Web UI bindings need the ability to request chrome: URLs.
548 state
->second
->GrantScheme(chrome::kChromeUIScheme
);
550 // Web UI pages can contain links to file:// URLs.
551 state
->second
->GrantScheme(kFileScheme
);
554 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id
) {
555 base::AutoLock
lock(lock_
);
557 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
558 if (state
== security_state_
.end())
561 state
->second
->GrantReadRawCookies();
564 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id
) {
565 base::AutoLock
lock(lock_
);
567 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
568 if (state
== security_state_
.end())
571 state
->second
->RevokeReadRawCookies();
574 bool ChildProcessSecurityPolicyImpl::CanLoadPage(
577 ResourceType::Type resource_type
) {
578 // If --site-per-process flag is passed, we should enforce
579 // stronger security restrictions on page navigation.
580 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
) &&
581 ResourceType::IsFrame(resource_type
)) {
582 // TODO(nasko): Do the proper check for site-per-process, once
583 // out-of-process iframes is ready to go.
589 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
590 int child_id
, const GURL
& url
) {
592 return false; // Can't request invalid URLs.
594 if (IsWebSafeScheme(url
.scheme()))
595 return true; // The scheme has been white-listed for every child process.
597 if (IsPseudoScheme(url
.scheme())) {
598 // There are a number of special cases for pseudo schemes.
600 if (url
.SchemeIs(kViewSourceScheme
)) {
601 // A view-source URL is allowed if the child process is permitted to
602 // request the embedded URL. Careful to avoid pointless recursion.
603 GURL
child_url(url
.GetContent());
604 if (child_url
.SchemeIs(kViewSourceScheme
) &&
605 url
.SchemeIs(kViewSourceScheme
))
608 return CanRequestURL(child_id
, child_url
);
611 if (LowerCaseEqualsASCII(url
.spec(), kAboutBlankURL
))
612 return true; // Every child process can request <about:blank>.
614 // URLs like <about:memory> and <about:crash> shouldn't be requestable by
615 // any child process. Also, this case covers <javascript:...>, which should
616 // be handled internally by the process and not kicked up to the browser.
620 if (!GetContentClient()->browser()->IsHandledURL(url
) &&
621 !net::URLRequest::IsHandledURL(url
)) {
622 return true; // This URL request is destined for ShellExecute.
626 base::AutoLock
lock(lock_
);
628 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
629 if (state
== security_state_
.end())
632 // Otherwise, we consult the child process's security state to see if it is
633 // allowed to request the URL.
634 return state
->second
->CanRequestURL(url
);
638 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id
,
639 const base::FilePath
& file
) {
640 return HasPermissionsForFile(child_id
, file
, READ_FILE_GRANT
);
643 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
645 const base::FilePath
& file
) {
646 return HasPermissionsForFile(child_id
, file
, CREATE_READ_WRITE_FILE_GRANT
);
649 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
650 int child_id
, const std::string
& filesystem_id
) {
651 return HasPermissionsForFileSystem(child_id
, filesystem_id
, READ_FILE_GRANT
);
654 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
655 int child_id
, const std::string
& filesystem_id
) {
656 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
657 READ_FILE_GRANT
| WRITE_FILE_GRANT
);
660 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
661 int child_id
, const std::string
& filesystem_id
) {
662 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
663 COPY_INTO_FILE_GRANT
);
666 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
667 int child_id
, const std::string
& filesystem_id
) {
668 return HasPermissionsForFileSystem(child_id
, filesystem_id
,
672 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
673 int child_id
, const base::FilePath
& file
, int permissions
) {
674 base::AutoLock
lock(lock_
);
675 bool result
= ChildProcessHasPermissionsForFile(child_id
, file
, permissions
);
677 // If this is a worker thread that has no access to a given file,
678 // let's check that its renderer process has access to that file instead.
679 WorkerToMainProcessMap::iterator iter
= worker_map_
.find(child_id
);
680 if (iter
!= worker_map_
.end() && iter
->second
!= 0) {
681 result
= ChildProcessHasPermissionsForFile(iter
->second
,
689 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
690 int child_id
, const fileapi::FileSystemURL
& url
, int permissions
) {
694 if (url
.path().ReferencesParent())
697 // Any write access is disallowed on the root path.
698 if (fileapi::VirtualPath::IsRootPath(url
.path()) &&
699 (permissions
& ~READ_FILE_GRANT
)) {
703 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
) {
704 // When Isolated filesystems is overlayed on top of another filesystem,
705 // its per-filesystem permission overrides the underlying filesystem
707 return HasPermissionsForFileSystem(
708 child_id
, url
.mount_filesystem_id(), permissions
);
711 FileSystemPermissionPolicyMap::iterator found
=
712 file_system_policy_map_
.find(url
.type());
713 if (found
== file_system_policy_map_
.end())
716 if ((found
->second
& fileapi::FILE_PERMISSION_READ_ONLY
) &&
717 permissions
& ~READ_FILE_GRANT
) {
721 if (found
->second
& fileapi::FILE_PERMISSION_USE_FILE_PERMISSION
)
722 return HasPermissionsForFile(child_id
, url
.path(), permissions
);
724 if (found
->second
& fileapi::FILE_PERMISSION_SANDBOX
)
730 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
732 const fileapi::FileSystemURL
& url
) {
733 return HasPermissionsForFileSystemFile(child_id
, url
, READ_FILE_GRANT
);
736 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
738 const fileapi::FileSystemURL
& url
) {
739 return HasPermissionsForFileSystemFile(child_id
, url
, WRITE_FILE_GRANT
);
742 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
744 const fileapi::FileSystemURL
& url
) {
745 return HasPermissionsForFileSystemFile(child_id
, url
, CREATE_NEW_FILE_GRANT
);
748 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
750 const fileapi::FileSystemURL
& url
) {
751 return HasPermissionsForFileSystemFile(child_id
, url
,
752 CREATE_READ_WRITE_FILE_GRANT
);
755 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
757 const fileapi::FileSystemURL
& url
) {
758 return HasPermissionsForFileSystemFile(child_id
, url
, COPY_INTO_FILE_GRANT
);
761 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
763 const fileapi::FileSystemURL
& url
) {
764 return HasPermissionsForFileSystemFile(child_id
, url
, DELETE_FILE_GRANT
);
767 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id
) {
768 base::AutoLock
lock(lock_
);
770 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
771 if (state
== security_state_
.end())
774 return state
->second
->has_web_ui_bindings();
777 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id
) {
778 base::AutoLock
lock(lock_
);
780 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
781 if (state
== security_state_
.end())
784 return state
->second
->can_read_raw_cookies();
787 void ChildProcessSecurityPolicyImpl::AddChild(int child_id
) {
788 if (security_state_
.count(child_id
) != 0) {
789 NOTREACHED() << "Add child process at most once.";
793 security_state_
[child_id
] = new SecurityState();
796 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
797 int child_id
, const base::FilePath
& file
, int permissions
) {
798 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
799 if (state
== security_state_
.end())
801 return state
->second
->HasPermissionsForFile(file
, permissions
);
804 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
805 int child_id
, const GURL
& gurl
) {
806 base::AutoLock
lock(lock_
);
807 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
808 if (state
== security_state_
.end())
810 return state
->second
->CanAccessCookiesForOrigin(gurl
);
813 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id
,
815 for (PluginProcessHostIterator iter
; !iter
.Done(); ++iter
) {
816 if (iter
.GetData().id
== child_id
) {
817 if (iter
.GetData().process_type
== PROCESS_TYPE_PLUGIN
) {
818 // NPAPI plugin processes are unsandboxed and so are trusted. Plugins
819 // can make request to any origin.
826 base::AutoLock
lock(lock_
);
827 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
828 if (state
== security_state_
.end())
830 return state
->second
->CanSendCookiesForOrigin(gurl
);
833 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id
,
835 // "gurl" can be currently empty in some cases, such as file://blah.
836 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL
, gurl
) == gurl
);
837 base::AutoLock
lock(lock_
);
838 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
839 DCHECK(state
!= security_state_
.end());
840 state
->second
->LockToOrigin(gurl
);
843 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
845 const std::string
& filesystem_id
,
847 base::AutoLock
lock(lock_
);
849 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
850 if (state
== security_state_
.end())
852 state
->second
->GrantPermissionsForFileSystem(filesystem_id
, permission
);
855 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
857 const std::string
& filesystem_id
,
859 base::AutoLock
lock(lock_
);
861 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
862 if (state
== security_state_
.end())
864 return state
->second
->HasPermissionsForFileSystem(filesystem_id
, permission
);
867 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
868 fileapi::FileSystemType type
,
870 base::AutoLock
lock(lock_
);
871 file_system_policy_map_
[type
] = policy
;
874 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id
) {
875 base::AutoLock
lock(lock_
);
877 SecurityStateMap::iterator state
= security_state_
.find(child_id
);
878 if (state
== security_state_
.end())
881 return state
->second
->can_send_midi_sysex();
884 } // namespace content