chrome/browser/extensions: Remove use of MessageLoopProxy and deprecated MessageLoop...
[chromium-blink-merge.git] / content / browser / child_process_security_policy_impl.cc
blobbb4a3e217a5a38a496ba7c7d7ea9da9f2ab4284a
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"
23 #include "storage/browser/fileapi/file_permission_policy.h"
24 #include "storage/browser/fileapi/file_system_url.h"
25 #include "storage/browser/fileapi/isolated_context.h"
26 #include "storage/common/fileapi/file_system_util.h"
27 #include "url/gurl.h"
29 namespace content {
31 namespace {
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,
66 } // namespace
68 // The SecurityState class is used to maintain per-child process security state
69 // information.
70 class ChildProcessSecurityPolicyImpl::SecurityState {
71 public:
72 SecurityState()
73 : enabled_bindings_(0),
74 can_read_raw_cookies_(false),
75 can_send_midi_sysex_(false) { }
77 ~SecurityState() {
78 scheme_policy_.clear();
79 storage::IsolatedContext* isolated_context =
80 storage::IsolatedContext::GetInstance();
81 for (FileSystemMap::iterator iter = filesystem_permissions_.begin();
82 iter != filesystem_permissions_.end();
83 ++iter) {
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,
122 int permissions) {
123 if (!ContainsKey(filesystem_permissions_, filesystem_id))
124 storage::IsolatedContext::GetInstance()->AddReference(filesystem_id);
125 filesystem_permissions_[filesystem_id] |= permissions;
128 bool HasPermissionsForFileSystem(const std::string& filesystem_id,
129 int permissions) {
130 FileSystemMap::const_iterator it =
131 filesystem_permissions_.find(filesystem_id);
132 if (it == filesystem_permissions_.end())
133 return false;
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,
140 int permissions) {
141 DCHECK(!file.empty());
142 DCHECK(file.IsContentUri());
143 if (!permissions)
144 return false;
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;
149 return false;
151 #endif
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)) {
179 base::FilePath path;
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);
192 #endif
193 if (!permissions || file.empty() || !file.IsAbsolute())
194 return false;
195 base::FilePath current_path = file.StripTrailingSeparators();
196 base::FilePath last_path;
197 int skip = 0;
198 while (current_path != last_path) {
199 base::FilePath base_name = current_path.BaseName();
200 if (base_name.value() == base::FilePath::kParentDirectory) {
201 ++skip;
202 } else if (skip > 0) {
203 if (base_name.value() != base::FilePath::kCurrentDirectory)
204 --skip;
205 } else {
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();
214 return false;
217 bool CanLoadPage(const GURL& gurl) {
218 if (origin_lock_.is_empty())
219 return true;
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())
230 return true;
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 void LockToOrigin(const GURL& gurl) {
239 origin_lock_ = gurl;
242 bool has_web_ui_bindings() const {
243 return enabled_bindings_ & BINDINGS_POLICY_WEB_UI;
246 bool can_read_raw_cookies() const {
247 return can_read_raw_cookies_;
250 bool can_send_midi_sysex() const {
251 return can_send_midi_sysex_;
254 private:
255 typedef std::map<std::string, bool> SchemeMap;
257 typedef int FilePermissionFlags; // bit-set of base::File::Flags
258 typedef std::map<base::FilePath, FilePermissionFlags> FileMap;
259 typedef std::map<std::string, FilePermissionFlags> FileSystemMap;
260 typedef std::set<base::FilePath> FileSet;
262 // Maps URL schemes to whether permission has been granted or revoked:
263 // |true| means the scheme has been granted.
264 // |false| means the scheme has been revoked.
265 // If a scheme is not present in the map, then it has never been granted
266 // or revoked.
267 SchemeMap scheme_policy_;
269 // The set of files the child process is permited to upload to the web.
270 FileMap file_permissions_;
272 // The set of files the child process is permitted to load.
273 FileSet request_file_set_;
275 int enabled_bindings_;
277 bool can_read_raw_cookies_;
279 bool can_send_midi_sysex_;
281 GURL origin_lock_;
283 // The set of isolated filesystems the child process is permitted to access.
284 FileSystemMap filesystem_permissions_;
286 DISALLOW_COPY_AND_ASSIGN(SecurityState);
289 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
290 // We know about these schemes and believe them to be safe.
291 RegisterWebSafeScheme(url::kHttpScheme);
292 RegisterWebSafeScheme(url::kHttpsScheme);
293 RegisterWebSafeScheme(url::kFtpScheme);
294 RegisterWebSafeScheme(url::kDataScheme);
295 RegisterWebSafeScheme("feed");
296 RegisterWebSafeScheme(url::kBlobScheme);
297 RegisterWebSafeScheme(url::kFileSystemScheme);
299 // We know about the following pseudo schemes and treat them specially.
300 RegisterPseudoScheme(url::kAboutScheme);
301 RegisterPseudoScheme(url::kJavaScriptScheme);
302 RegisterPseudoScheme(kViewSourceScheme);
305 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
306 web_safe_schemes_.clear();
307 pseudo_schemes_.clear();
308 STLDeleteContainerPairSecondPointers(security_state_.begin(),
309 security_state_.end());
310 security_state_.clear();
313 // static
314 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
315 return ChildProcessSecurityPolicyImpl::GetInstance();
318 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
319 return Singleton<ChildProcessSecurityPolicyImpl>::get();
322 void ChildProcessSecurityPolicyImpl::Add(int child_id) {
323 base::AutoLock lock(lock_);
324 AddChild(child_id);
327 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id,
328 int main_render_process_id) {
329 base::AutoLock lock(lock_);
330 AddChild(child_id);
331 worker_map_[child_id] = main_render_process_id;
334 void ChildProcessSecurityPolicyImpl::Remove(int child_id) {
335 base::AutoLock lock(lock_);
336 SecurityStateMap::iterator it = security_state_.find(child_id);
337 if (it == security_state_.end())
338 return; // May be called multiple times.
340 delete it->second;
341 security_state_.erase(it);
342 worker_map_.erase(child_id);
345 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
346 const std::string& scheme) {
347 base::AutoLock lock(lock_);
348 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) << "Add schemes at most once.";
349 DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
350 << "Web-safe implies not pseudo.";
352 web_safe_schemes_.insert(scheme);
355 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
356 const std::string& scheme) {
357 base::AutoLock lock(lock_);
359 return ContainsKey(web_safe_schemes_, scheme);
362 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
363 const std::string& scheme) {
364 base::AutoLock lock(lock_);
365 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once.";
366 DCHECK_EQ(0U, web_safe_schemes_.count(scheme))
367 << "Pseudo implies not web-safe.";
369 pseudo_schemes_.insert(scheme);
372 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
373 const std::string& scheme) {
374 base::AutoLock lock(lock_);
376 return ContainsKey(pseudo_schemes_, scheme);
379 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
380 int child_id, const GURL& url) {
382 if (!url.is_valid())
383 return; // Can't grant the capability to request invalid URLs.
385 if (IsWebSafeScheme(url.scheme()))
386 return; // The scheme has already been whitelisted for every child process.
388 if (IsPseudoScheme(url.scheme())) {
389 // The view-source scheme is a special case of a pseudo-URL that eventually
390 // results in requesting its embedded URL.
391 if (url.SchemeIs(kViewSourceScheme)) {
392 // URLs with the view-source scheme typically look like:
393 // view-source:http://www.google.com/a
394 // In order to request these URLs, the child_id needs to be able to
395 // request the embedded URL.
396 GrantRequestURL(child_id, GURL(url.GetContent()));
399 return; // Can't grant the capability to request pseudo schemes.
403 base::AutoLock lock(lock_);
404 SecurityStateMap::iterator state = security_state_.find(child_id);
405 if (state == security_state_.end())
406 return;
408 // When the child process has been commanded to request this scheme,
409 // we grant it the capability to request all URLs of that scheme.
410 state->second->GrantScheme(url.scheme());
414 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
415 int child_id,
416 const GURL& url) {
417 if (!url.SchemeIs(url::kFileScheme))
418 return;
421 base::AutoLock lock(lock_);
422 SecurityStateMap::iterator state = security_state_.find(child_id);
423 if (state == security_state_.end())
424 return;
426 // When the child process has been commanded to request a file:// URL,
427 // then we grant it the capability for that URL only.
428 base::FilePath path;
429 if (net::FileURLToFilePath(url, &path))
430 state->second->GrantRequestOfSpecificFile(path);
434 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
435 const base::FilePath& file) {
436 GrantPermissionsForFile(child_id, file, READ_FILE_GRANT);
439 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
440 int child_id, const base::FilePath& file) {
441 GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
444 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id,
445 const base::FilePath& dir) {
446 GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT);
449 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
450 int child_id, const base::FilePath& dir) {
451 GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT);
454 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
455 int child_id, const base::FilePath& file, int permissions) {
456 base::AutoLock lock(lock_);
458 SecurityStateMap::iterator state = security_state_.find(child_id);
459 if (state == security_state_.end())
460 return;
462 state->second->GrantPermissionsForFile(file, permissions);
465 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
466 int child_id, const base::FilePath& file) {
467 base::AutoLock lock(lock_);
469 SecurityStateMap::iterator state = security_state_.find(child_id);
470 if (state == security_state_.end())
471 return;
473 state->second->RevokeAllPermissionsForFile(file);
476 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
477 int child_id, const std::string& filesystem_id) {
478 GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
481 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
482 int child_id, const std::string& filesystem_id) {
483 GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT);
486 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
487 int child_id, const std::string& filesystem_id) {
488 GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT);
491 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
492 int child_id, const std::string& filesystem_id) {
493 GrantPermissionsForFileSystem(
494 child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT);
497 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
498 int child_id, const std::string& filesystem_id) {
499 GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT);
502 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
503 int child_id, const std::string& filesystem_id) {
504 GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT);
507 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
508 base::AutoLock lock(lock_);
510 SecurityStateMap::iterator state = security_state_.find(child_id);
511 if (state == security_state_.end())
512 return;
514 state->second->GrantPermissionForMidiSysEx();
517 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
518 const std::string& scheme) {
519 base::AutoLock lock(lock_);
521 SecurityStateMap::iterator state = security_state_.find(child_id);
522 if (state == security_state_.end())
523 return;
525 state->second->GrantScheme(scheme);
528 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) {
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->GrantBindings(BINDINGS_POLICY_WEB_UI);
537 // Web UI bindings need the ability to request chrome: URLs.
538 state->second->GrantScheme(kChromeUIScheme);
540 // Web UI pages can contain links to file:// URLs.
541 state->second->GrantScheme(url::kFileScheme);
544 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
545 base::AutoLock lock(lock_);
547 SecurityStateMap::iterator state = security_state_.find(child_id);
548 if (state == security_state_.end())
549 return;
551 state->second->GrantReadRawCookies();
554 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(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->RevokeReadRawCookies();
564 bool ChildProcessSecurityPolicyImpl::CanLoadPage(int child_id,
565 const GURL& url,
566 ResourceType resource_type) {
567 // If --site-per-process flag is passed, we should enforce
568 // stronger security restrictions on page navigation.
569 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
570 switches::kSitePerProcess) &&
571 IsResourceTypeFrame(resource_type)) {
572 // TODO(nasko): Do the proper check for site-per-process, once
573 // out-of-process iframes is ready to go.
574 return true;
576 return true;
579 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
580 int child_id, const GURL& url) {
581 if (!url.is_valid())
582 return false; // Can't request invalid URLs.
584 if (IsWebSafeScheme(url.scheme()))
585 return true; // The scheme has been white-listed for every child process.
587 if (IsPseudoScheme(url.scheme())) {
588 // There are a number of special cases for pseudo schemes.
590 if (url.SchemeIs(kViewSourceScheme)) {
591 // A view-source URL is allowed if the child process is permitted to
592 // request the embedded URL. Careful to avoid pointless recursion.
593 GURL child_url(url.GetContent());
594 if (child_url.SchemeIs(kViewSourceScheme) &&
595 url.SchemeIs(kViewSourceScheme))
596 return false;
598 return CanRequestURL(child_id, child_url);
601 if (base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
602 return true; // Every child process can request <about:blank>.
604 // URLs like <about:memory> and <about:crash> shouldn't be requestable by
605 // any child process. Also, this case covers <javascript:...>, which should
606 // be handled internally by the process and not kicked up to the browser.
607 return false;
610 if (!GetContentClient()->browser()->IsHandledURL(url) &&
611 !net::URLRequest::IsHandledURL(url)) {
612 return true; // This URL request is destined for ShellExecute.
616 base::AutoLock lock(lock_);
618 SecurityStateMap::iterator state = security_state_.find(child_id);
619 if (state == security_state_.end())
620 return false;
622 // Otherwise, we consult the child process's security state to see if it is
623 // allowed to request the URL.
624 return state->second->CanRequestURL(url);
628 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
629 const base::FilePath& file) {
630 return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
633 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
634 int child_id,
635 const base::FilePath& file) {
636 return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
639 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
640 int child_id, const std::string& filesystem_id) {
641 return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
644 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
645 int child_id, const std::string& filesystem_id) {
646 return HasPermissionsForFileSystem(child_id, filesystem_id,
647 READ_FILE_GRANT | WRITE_FILE_GRANT);
650 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
651 int child_id, const std::string& filesystem_id) {
652 return HasPermissionsForFileSystem(child_id, filesystem_id,
653 COPY_INTO_FILE_GRANT);
656 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
657 int child_id, const std::string& filesystem_id) {
658 return HasPermissionsForFileSystem(child_id, filesystem_id,
659 DELETE_FILE_GRANT);
662 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
663 int child_id, const base::FilePath& file, int permissions) {
664 base::AutoLock lock(lock_);
665 bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions);
666 if (!result) {
667 // If this is a worker thread that has no access to a given file,
668 // let's check that its renderer process has access to that file instead.
669 WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id);
670 if (iter != worker_map_.end() && iter->second != 0) {
671 result = ChildProcessHasPermissionsForFile(iter->second,
672 file,
673 permissions);
676 return result;
679 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
680 int child_id,
681 const storage::FileSystemURL& url,
682 int permissions) {
683 if (!url.is_valid())
684 return false;
686 if (url.path().ReferencesParent())
687 return false;
689 // Any write access is disallowed on the root path.
690 if (storage::VirtualPath::IsRootPath(url.path()) &&
691 (permissions & ~READ_FILE_GRANT)) {
692 return false;
695 if (url.mount_type() == storage::kFileSystemTypeIsolated) {
696 // When Isolated filesystems is overlayed on top of another filesystem,
697 // its per-filesystem permission overrides the underlying filesystem
698 // permissions).
699 return HasPermissionsForFileSystem(
700 child_id, url.mount_filesystem_id(), permissions);
703 FileSystemPermissionPolicyMap::iterator found =
704 file_system_policy_map_.find(url.type());
705 if (found == file_system_policy_map_.end())
706 return false;
708 if ((found->second & storage::FILE_PERMISSION_READ_ONLY) &&
709 permissions & ~READ_FILE_GRANT) {
710 return false;
713 if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
714 return HasPermissionsForFile(child_id, url.path(), permissions);
716 if (found->second & storage::FILE_PERMISSION_SANDBOX)
717 return true;
719 return false;
722 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
723 int child_id,
724 const storage::FileSystemURL& url) {
725 return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
728 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
729 int child_id,
730 const storage::FileSystemURL& url) {
731 return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
734 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
735 int child_id,
736 const storage::FileSystemURL& url) {
737 return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
740 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
741 int child_id,
742 const storage::FileSystemURL& url) {
743 return HasPermissionsForFileSystemFile(child_id, url,
744 CREATE_READ_WRITE_FILE_GRANT);
747 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
748 int child_id,
749 const storage::FileSystemURL& url) {
750 return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
753 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
754 int child_id,
755 const storage::FileSystemURL& url) {
756 return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
759 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
760 base::AutoLock lock(lock_);
762 SecurityStateMap::iterator state = security_state_.find(child_id);
763 if (state == security_state_.end())
764 return false;
766 return state->second->has_web_ui_bindings();
769 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
770 base::AutoLock lock(lock_);
772 SecurityStateMap::iterator state = security_state_.find(child_id);
773 if (state == security_state_.end())
774 return false;
776 return state->second->can_read_raw_cookies();
779 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) {
780 if (security_state_.count(child_id) != 0) {
781 NOTREACHED() << "Add child process at most once.";
782 return;
785 security_state_[child_id] = new SecurityState();
788 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
789 int child_id, const base::FilePath& file, int permissions) {
790 SecurityStateMap::iterator state = security_state_.find(child_id);
791 if (state == security_state_.end())
792 return false;
793 return state->second->HasPermissionsForFile(file, permissions);
796 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
797 int child_id, const GURL& gurl) {
798 base::AutoLock lock(lock_);
799 SecurityStateMap::iterator state = security_state_.find(child_id);
800 if (state == security_state_.end())
801 return false;
802 return state->second->CanAccessCookiesForOrigin(gurl);
805 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
806 const GURL& gurl) {
807 // "gurl" can be currently empty in some cases, such as file://blah.
808 DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl);
809 base::AutoLock lock(lock_);
810 SecurityStateMap::iterator state = security_state_.find(child_id);
811 DCHECK(state != security_state_.end());
812 state->second->LockToOrigin(gurl);
815 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
816 int child_id,
817 const std::string& filesystem_id,
818 int permission) {
819 base::AutoLock lock(lock_);
821 SecurityStateMap::iterator state = security_state_.find(child_id);
822 if (state == security_state_.end())
823 return;
824 state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
827 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
828 int child_id,
829 const std::string& filesystem_id,
830 int permission) {
831 base::AutoLock lock(lock_);
833 SecurityStateMap::iterator state = security_state_.find(child_id);
834 if (state == security_state_.end())
835 return false;
836 return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
839 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
840 storage::FileSystemType type,
841 int policy) {
842 base::AutoLock lock(lock_);
843 file_system_policy_map_[type] = policy;
846 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
847 base::AutoLock lock(lock_);
849 SecurityStateMap::iterator state = security_state_.find(child_id);
850 if (state == security_state_.end())
851 return false;
853 return state->second->can_send_midi_sysex();
856 } // namespace content