Web MIDI: make naming convention be consistent
[chromium-blink-merge.git] / content / browser / child_process_security_policy_impl.cc
blobb115217fadb631dbfa518f31dd0227c27fa35126
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"
24 #include "url/gurl.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"
30 namespace content {
32 namespace {
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,
67 } // namespace
69 // The SecurityState class is used to maintain per-child process security state
70 // information.
71 class ChildProcessSecurityPolicyImpl::SecurityState {
72 public:
73 SecurityState()
74 : enabled_bindings_(0),
75 can_read_raw_cookies_(false),
76 can_send_midi_sysex_(false) { }
78 ~SecurityState() {
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();
84 ++iter) {
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,
123 int permissions) {
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,
130 int permissions) {
131 FileSystemMap::const_iterator it =
132 filesystem_permissions_.find(filesystem_id);
133 if (it == filesystem_permissions_.end())
134 return false;
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,
141 int permissions) {
142 DCHECK(!file.empty());
143 DCHECK(file.IsContentUri());
144 if (!permissions)
145 return false;
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;
150 return false;
152 #endif
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)) {
180 base::FilePath path;
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);
193 #endif
194 if (!permissions || file.empty() || !file.IsAbsolute())
195 return false;
196 base::FilePath current_path = file.StripTrailingSeparators();
197 base::FilePath last_path;
198 int skip = 0;
199 while (current_path != last_path) {
200 base::FilePath base_name = current_path.BaseName();
201 if (base_name.value() == base::FilePath::kParentDirectory) {
202 ++skip;
203 } else if (skip > 0) {
204 if (base_name.value() != base::FilePath::kCurrentDirectory)
205 --skip;
206 } else {
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();
215 return false;
218 bool CanLoadPage(const GURL& gurl) {
219 if (origin_lock_.is_empty())
220 return true;
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())
231 return true;
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))
247 return true;
249 if (origin_lock_.is_empty())
250 return true;
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) {
259 origin_lock_ = 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_;
274 private:
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
286 // or revoked.
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_;
301 GURL origin_lock_;
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();
333 // static
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_);
344 AddChild(child_id);
347 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id,
348 int main_render_process_id) {
349 base::AutoLock lock(lock_);
350 AddChild(child_id);
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.
360 delete it->second;
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) {
402 if (!url.is_valid())
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())
426 return;
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(
435 int child_id,
436 const GURL& url) {
437 if (!url.SchemeIs(kFileScheme))
438 return;
441 base::AutoLock lock(lock_);
442 SecurityStateMap::iterator state = security_state_.find(child_id);
443 if (state == security_state_.end())
444 return;
446 // When the child process has been commanded to request a file:// URL,
447 // then we grant it the capability for that URL only.
448 base::FilePath path;
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())
470 return;
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())
481 return;
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())
522 return;
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())
533 return;
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())
543 return;
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())
559 return;
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())
569 return;
571 state->second->RevokeReadRawCookies();
574 bool ChildProcessSecurityPolicyImpl::CanLoadPage(
575 int child_id,
576 const GURL& url,
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.
584 return true;
586 return true;
589 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
590 int child_id, const GURL& url) {
591 if (!url.is_valid())
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))
606 return false;
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.
617 return false;
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())
630 return false;
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(
644 int child_id,
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,
669 DELETE_FILE_GRANT);
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);
676 if (!result) {
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,
682 file,
683 permissions);
686 return result;
689 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
690 int child_id, const fileapi::FileSystemURL& url, int permissions) {
691 if (!url.is_valid())
692 return false;
694 if (url.path().ReferencesParent())
695 return false;
697 // Any write access is disallowed on the root path.
698 if (fileapi::VirtualPath::IsRootPath(url.path()) &&
699 (permissions & ~READ_FILE_GRANT)) {
700 return false;
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
706 // permissions).
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())
714 return false;
716 if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) &&
717 permissions & ~READ_FILE_GRANT) {
718 return false;
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)
725 return true;
727 return false;
730 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
731 int child_id,
732 const fileapi::FileSystemURL& url) {
733 return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
736 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
737 int child_id,
738 const fileapi::FileSystemURL& url) {
739 return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
742 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
743 int child_id,
744 const fileapi::FileSystemURL& url) {
745 return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
748 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
749 int child_id,
750 const fileapi::FileSystemURL& url) {
751 return HasPermissionsForFileSystemFile(child_id, url,
752 CREATE_READ_WRITE_FILE_GRANT);
755 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
756 int child_id,
757 const fileapi::FileSystemURL& url) {
758 return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
761 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
762 int child_id,
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())
772 return false;
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())
782 return false;
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.";
790 return;
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())
800 return false;
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())
809 return false;
810 return state->second->CanAccessCookiesForOrigin(gurl);
813 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id,
814 const GURL& gurl) {
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.
820 return true;
822 break;
826 base::AutoLock lock(lock_);
827 SecurityStateMap::iterator state = security_state_.find(child_id);
828 if (state == security_state_.end())
829 return false;
830 return state->second->CanSendCookiesForOrigin(gurl);
833 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
834 const GURL& gurl) {
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(
844 int child_id,
845 const std::string& filesystem_id,
846 int permission) {
847 base::AutoLock lock(lock_);
849 SecurityStateMap::iterator state = security_state_.find(child_id);
850 if (state == security_state_.end())
851 return;
852 state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
855 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
856 int child_id,
857 const std::string& filesystem_id,
858 int permission) {
859 base::AutoLock lock(lock_);
861 SecurityStateMap::iterator state = security_state_.find(child_id);
862 if (state == security_state_.end())
863 return false;
864 return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
867 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
868 fileapi::FileSystemType type,
869 int policy) {
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())
879 return false;
881 return state->second->can_send_midi_sysex();
884 } // namespace content