Home | History | Annotate | Download | only in browser
      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.
      4 
      5 #include "content/browser/child_process_security_policy_impl.h"
      6 
      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 "url/gurl.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"
     28 
     29 namespace content {
     30 
     31 namespace {
     32 
     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,
     41 
     42   // Used by Media Galleries API
     43   COPY_INTO_FILE_PERMISSION        = 1 << 5,
     44 };
     45 
     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,
     51 
     52   CREATE_NEW_FILE_GRANT        = CREATE_NEW_FILE_PERMISSION |
     53                                  COPY_INTO_FILE_PERMISSION,
     54 
     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,
     61 
     62   COPY_INTO_FILE_GRANT         = COPY_INTO_FILE_PERMISSION,
     63   DELETE_FILE_GRANT            = DELETE_FILE_PERMISSION,
     64 };
     65 
     66 }  // namespace
     67 
     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) { }
     76 
     77   ~SecurityState() {
     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();
     83          ++iter) {
     84       isolated_context->RemoveReference(iter->first);
     85     }
     86     UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions",
     87                          file_permissions_.size());
     88   }
     89 
     90   // Grant permission to request URLs with the specified scheme.
     91   void GrantScheme(const std::string& scheme) {
     92     scheme_policy_[scheme] = true;
     93   }
     94 
     95   // Revoke permission to request URLs with the specified scheme.
     96   void RevokeScheme(const std::string& scheme) {
     97     scheme_policy_[scheme] = false;
     98   }
     99 
    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());
    106   }
    107 
    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());
    111   }
    112 
    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);
    118   }
    119 
    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       fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id);
    125     filesystem_permissions_[filesystem_id] |= permissions;
    126   }
    127 
    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;
    135   }
    136 
    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;
    150   }
    151 #endif
    152 
    153   void GrantBindings(int bindings) {
    154     enabled_bindings_ |= bindings;
    155   }
    156 
    157   void GrantReadRawCookies() {
    158     can_read_raw_cookies_ = true;
    159   }
    160 
    161   void RevokeReadRawCookies() {
    162     can_read_raw_cookies_ = false;
    163   }
    164 
    165   void GrantPermissionForMidiSysEx() {
    166     can_send_midi_sysex_ = true;
    167   }
    168 
    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;
    175 
    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);
    182     }
    183 
    184     return false;  // Unmentioned schemes are disallowed.
    185   }
    186 
    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;
    209       }
    210       last_path = current_path;
    211       current_path = current_path.DirName();
    212     }
    213 
    214     return false;
    215   }
    216 
    217   bool CanLoadPage(const GURL& gurl) {
    218     if (origin_lock_.is_empty())
    219       return true;
    220 
    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;
    226   }
    227 
    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;
    236   }
    237 
    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))
    246       return true;
    247 
    248     if (origin_lock_.is_empty())
    249       return true;
    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;
    255   }
    256 
    257   void LockToOrigin(const GURL& gurl) {
    258     origin_lock_ = gurl;
    259   }
    260 
    261   bool has_web_ui_bindings() const {
    262     return enabled_bindings_ & BINDINGS_POLICY_WEB_UI;
    263   }
    264 
    265   bool can_read_raw_cookies() const {
    266     return can_read_raw_cookies_;
    267   }
    268 
    269   bool can_send_midi_sysex() const {
    270     return can_send_midi_sysex_;
    271   }
    272 
    273  private:
    274   typedef std::map<std::string, bool> SchemeMap;
    275 
    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;
    280 
    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
    285   // or revoked.
    286   SchemeMap scheme_policy_;
    287 
    288   // The set of files the child process is permited to upload to the web.
    289   FileMap file_permissions_;
    290 
    291   // The set of files the child process is permitted to load.
    292   FileSet request_file_set_;
    293 
    294   int enabled_bindings_;
    295 
    296   bool can_read_raw_cookies_;
    297 
    298   bool can_send_midi_sysex_;
    299 
    300   GURL origin_lock_;
    301 
    302   // The set of isolated filesystems the child process is permitted to access.
    303   FileSystemMap filesystem_permissions_;
    304 
    305   DISALLOW_COPY_AND_ASSIGN(SecurityState);
    306 };
    307 
    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);
    317 
    318   // We know about the following pseudo schemes and treat them specially.
    319   RegisterPseudoScheme(url::kAboutScheme);
    320   RegisterPseudoScheme(url::kJavaScriptScheme);
    321   RegisterPseudoScheme(kViewSourceScheme);
    322 }
    323 
    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();
    330 }
    331 
    332 // static
    333 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
    334   return ChildProcessSecurityPolicyImpl::GetInstance();
    335 }
    336 
    337 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
    338   return Singleton<ChildProcessSecurityPolicyImpl>::get();
    339 }
    340 
    341 void ChildProcessSecurityPolicyImpl::Add(int child_id) {
    342   base::AutoLock lock(lock_);
    343   AddChild(child_id);
    344 }
    345 
    346 void ChildProcessSecurityPolicyImpl::AddWorker(int child_id,
    347                                                int main_render_process_id) {
    348   base::AutoLock lock(lock_);
    349   AddChild(child_id);
    350   worker_map_[child_id] = main_render_process_id;
    351 }
    352 
    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.
    358 
    359   delete it->second;
    360   security_state_.erase(it);
    361   worker_map_.erase(child_id);
    362 }
    363 
    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.";
    370 
    371   web_safe_schemes_.insert(scheme);
    372 }
    373 
    374 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
    375     const std::string& scheme) {
    376   base::AutoLock lock(lock_);
    377 
    378   return ContainsKey(web_safe_schemes_, scheme);
    379 }
    380 
    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.";
    387 
    388   pseudo_schemes_.insert(scheme);
    389 }
    390 
    391 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
    392     const std::string& scheme) {
    393   base::AutoLock lock(lock_);
    394 
    395   return ContainsKey(pseudo_schemes_, scheme);
    396 }
    397 
    398 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
    399     int child_id, const GURL& url) {
    400 
    401   if (!url.is_valid())
    402     return;  // Can't grant the capability to request invalid URLs.
    403 
    404   if (IsWebSafeScheme(url.scheme()))
    405     return;  // The scheme has already been whitelisted for every child process.
    406 
    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()));
    416     }
    417 
    418     return;  // Can't grant the capability to request pseudo schemes.
    419   }
    420 
    421   {
    422     base::AutoLock lock(lock_);
    423     SecurityStateMap::iterator state = security_state_.find(child_id);
    424     if (state == security_state_.end())
    425       return;
    426 
    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());
    430   }
    431 }
    432 
    433 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
    434     int child_id,
    435     const GURL& url) {
    436   if (!url.SchemeIs(url::kFileScheme))
    437     return;
    438 
    439   {
    440     base::AutoLock lock(lock_);
    441     SecurityStateMap::iterator state = security_state_.find(child_id);
    442     if (state == security_state_.end())
    443       return;
    444 
    445     // When the child process has been commanded to request a file:// URL,
    446     // then we grant it the capability for that URL only.
    447     base::FilePath path;
    448     if (net::FileURLToFilePath(url, &path))
    449       state->second->GrantRequestOfSpecificFile(path);
    450   }
    451 }
    452 
    453 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
    454                                                    const base::FilePath& file) {
    455   GrantPermissionsForFile(child_id, file, READ_FILE_GRANT);
    456 }
    457 
    458 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
    459     int child_id, const base::FilePath& file) {
    460   GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
    461 }
    462 
    463 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id,
    464                                                    const base::FilePath& dir) {
    465   GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT);
    466 }
    467 
    468 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
    469     int child_id, const base::FilePath& dir) {
    470   GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT);
    471 }
    472 
    473 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
    474     int child_id, const base::FilePath& file, int permissions) {
    475   base::AutoLock lock(lock_);
    476 
    477   SecurityStateMap::iterator state = security_state_.find(child_id);
    478   if (state == security_state_.end())
    479     return;
    480 
    481   state->second->GrantPermissionsForFile(file, permissions);
    482 }
    483 
    484 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
    485     int child_id, const base::FilePath& file) {
    486   base::AutoLock lock(lock_);
    487 
    488   SecurityStateMap::iterator state = security_state_.find(child_id);
    489   if (state == security_state_.end())
    490     return;
    491 
    492   state->second->RevokeAllPermissionsForFile(file);
    493 }
    494 
    495 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
    496     int child_id, const std::string& filesystem_id) {
    497   GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
    498 }
    499 
    500 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
    501     int child_id, const std::string& filesystem_id) {
    502   GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT);
    503 }
    504 
    505 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
    506     int child_id, const std::string& filesystem_id) {
    507   GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT);
    508 }
    509 
    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);
    514 }
    515 
    516 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
    517     int child_id, const std::string& filesystem_id) {
    518   GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT);
    519 }
    520 
    521 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
    522     int child_id, const std::string& filesystem_id) {
    523   GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT);
    524 }
    525 
    526 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
    527   base::AutoLock lock(lock_);
    528 
    529   SecurityStateMap::iterator state = security_state_.find(child_id);
    530   if (state == security_state_.end())
    531     return;
    532 
    533   state->second->GrantPermissionForMidiSysEx();
    534 }
    535 
    536 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
    537                                                  const std::string& scheme) {
    538   base::AutoLock lock(lock_);
    539 
    540   SecurityStateMap::iterator state = security_state_.find(child_id);
    541   if (state == security_state_.end())
    542     return;
    543 
    544   state->second->GrantScheme(scheme);
    545 }
    546 
    547 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) {
    548   base::AutoLock lock(lock_);
    549 
    550   SecurityStateMap::iterator state = security_state_.find(child_id);
    551   if (state == security_state_.end())
    552     return;
    553 
    554   state->second->GrantBindings(BINDINGS_POLICY_WEB_UI);
    555 
    556   // Web UI bindings need the ability to request chrome: URLs.
    557   state->second->GrantScheme(kChromeUIScheme);
    558 
    559   // Web UI pages can contain links to file:// URLs.
    560   state->second->GrantScheme(url::kFileScheme);
    561 }
    562 
    563 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
    564   base::AutoLock lock(lock_);
    565 
    566   SecurityStateMap::iterator state = security_state_.find(child_id);
    567   if (state == security_state_.end())
    568     return;
    569 
    570   state->second->GrantReadRawCookies();
    571 }
    572 
    573 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) {
    574   base::AutoLock lock(lock_);
    575 
    576   SecurityStateMap::iterator state = security_state_.find(child_id);
    577   if (state == security_state_.end())
    578     return;
    579 
    580   state->second->RevokeReadRawCookies();
    581 }
    582 
    583 bool ChildProcessSecurityPolicyImpl::CanLoadPage(
    584     int child_id,
    585     const GURL& url,
    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.
    593     return true;
    594   }
    595   return true;
    596 }
    597 
    598 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
    599     int child_id, const GURL& url) {
    600   if (!url.is_valid())
    601     return false;  // Can't request invalid URLs.
    602 
    603   if (IsWebSafeScheme(url.scheme()))
    604     return true;  // The scheme has been white-listed for every child process.
    605 
    606   if (IsPseudoScheme(url.scheme())) {
    607     // There are a number of special cases for pseudo schemes.
    608 
    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))
    615           return false;
    616 
    617       return CanRequestURL(child_id, child_url);
    618     }
    619 
    620     if (LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
    621       return true;  // Every child process can request <about:blank>.
    622 
    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.
    626     return false;
    627   }
    628 
    629   if (!GetContentClient()->browser()->IsHandledURL(url) &&
    630       !net::URLRequest::IsHandledURL(url)) {
    631     return true;  // This URL request is destined for ShellExecute.
    632   }
    633 
    634   {
    635     base::AutoLock lock(lock_);
    636 
    637     SecurityStateMap::iterator state = security_state_.find(child_id);
    638     if (state == security_state_.end())
    639       return false;
    640 
    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);
    644   }
    645 }
    646 
    647 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
    648                                                  const base::FilePath& file) {
    649   return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
    650 }
    651 
    652 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
    653     int child_id,
    654     const base::FilePath& file) {
    655   return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
    656 }
    657 
    658 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
    659     int child_id, const std::string& filesystem_id) {
    660   return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
    661 }
    662 
    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);
    667 }
    668 
    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);
    673 }
    674 
    675 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
    676     int child_id, const std::string& filesystem_id) {
    677   return HasPermissionsForFileSystem(child_id, filesystem_id,
    678                                      DELETE_FILE_GRANT);
    679 }
    680 
    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);
    685   if (!result) {
    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,
    691                                                  file,
    692                                                  permissions);
    693     }
    694   }
    695   return result;
    696 }
    697 
    698 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
    699     int child_id, const fileapi::FileSystemURL& url, int permissions) {
    700   if (!url.is_valid())
    701     return false;
    702 
    703   if (url.path().ReferencesParent())
    704     return false;
    705 
    706   // Any write access is disallowed on the root path.
    707   if (fileapi::VirtualPath::IsRootPath(url.path()) &&
    708       (permissions & ~READ_FILE_GRANT)) {
    709     return false;
    710   }
    711 
    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
    715     // permissions).
    716     return HasPermissionsForFileSystem(
    717         child_id, url.mount_filesystem_id(), permissions);
    718   }
    719 
    720   FileSystemPermissionPolicyMap::iterator found =
    721       file_system_policy_map_.find(url.type());
    722   if (found == file_system_policy_map_.end())
    723     return false;
    724 
    725   if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) &&
    726       permissions & ~READ_FILE_GRANT) {
    727     return false;
    728   }
    729 
    730   if (found->second & fileapi::FILE_PERMISSION_USE_FILE_PERMISSION)
    731     return HasPermissionsForFile(child_id, url.path(), permissions);
    732 
    733   if (found->second & fileapi::FILE_PERMISSION_SANDBOX)
    734     return true;
    735 
    736   return false;
    737 }
    738 
    739 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
    740     int child_id,
    741     const fileapi::FileSystemURL& url) {
    742   return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
    743 }
    744 
    745 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
    746     int child_id,
    747     const fileapi::FileSystemURL& url) {
    748   return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
    749 }
    750 
    751 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
    752     int child_id,
    753     const fileapi::FileSystemURL& url) {
    754   return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
    755 }
    756 
    757 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
    758     int child_id,
    759     const fileapi::FileSystemURL& url) {
    760   return HasPermissionsForFileSystemFile(child_id, url,
    761                                          CREATE_READ_WRITE_FILE_GRANT);
    762 }
    763 
    764 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
    765     int child_id,
    766     const fileapi::FileSystemURL& url) {
    767   return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
    768 }
    769 
    770 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
    771     int child_id,
    772     const fileapi::FileSystemURL& url) {
    773   return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
    774 }
    775 
    776 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
    777   base::AutoLock lock(lock_);
    778 
    779   SecurityStateMap::iterator state = security_state_.find(child_id);
    780   if (state == security_state_.end())
    781     return false;
    782 
    783   return state->second->has_web_ui_bindings();
    784 }
    785 
    786 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
    787   base::AutoLock lock(lock_);
    788 
    789   SecurityStateMap::iterator state = security_state_.find(child_id);
    790   if (state == security_state_.end())
    791     return false;
    792 
    793   return state->second->can_read_raw_cookies();
    794 }
    795 
    796 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) {
    797   if (security_state_.count(child_id) != 0) {
    798     NOTREACHED() << "Add child process at most once.";
    799     return;
    800   }
    801 
    802   security_state_[child_id] = new SecurityState();
    803 }
    804 
    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())
    809     return false;
    810   return state->second->HasPermissionsForFile(file, permissions);
    811 }
    812 
    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())
    818     return false;
    819   return state->second->CanAccessCookiesForOrigin(gurl);
    820 }
    821 
    822 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id,
    823                                                              const GURL& gurl) {
    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.
    829         return true;
    830       }
    831       break;
    832     }
    833   }
    834 
    835   base::AutoLock lock(lock_);
    836   SecurityStateMap::iterator state = security_state_.find(child_id);
    837   if (state == security_state_.end())
    838     return false;
    839   return state->second->CanSendCookiesForOrigin(gurl);
    840 }
    841 
    842 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
    843                                                   const GURL& gurl) {
    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);
    850 }
    851 
    852 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
    853     int child_id,
    854     const std::string& filesystem_id,
    855     int permission) {
    856   base::AutoLock lock(lock_);
    857 
    858   SecurityStateMap::iterator state = security_state_.find(child_id);
    859   if (state == security_state_.end())
    860     return;
    861   state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
    862 }
    863 
    864 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
    865     int child_id,
    866     const std::string& filesystem_id,
    867     int permission) {
    868   base::AutoLock lock(lock_);
    869 
    870   SecurityStateMap::iterator state = security_state_.find(child_id);
    871   if (state == security_state_.end())
    872     return false;
    873   return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
    874 }
    875 
    876 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
    877     fileapi::FileSystemType type,
    878     int policy) {
    879   base::AutoLock lock(lock_);
    880   file_system_policy_map_[type] = policy;
    881 }
    882 
    883 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
    884   base::AutoLock lock(lock_);
    885 
    886   SecurityStateMap::iterator state = security_state_.find(child_id);
    887   if (state == security_state_.end())
    888     return false;
    889 
    890   return state->second->can_send_midi_sysex();
    891 }
    892 
    893 }  // namespace content
    894