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 "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"
     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     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);
     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       storage::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 base::CommandLine& command_line =
    245         *base::CommandLine::ForCurrentProcess();
    246     if (!command_line.HasSwitch(switches::kEnableStrictSiteIsolation))
    247       return true;
    248 
    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;
    256   }
    257 
    258   void LockToOrigin(const GURL& gurl) {
    259     origin_lock_ = gurl;
    260   }
    261 
    262   bool has_web_ui_bindings() const {
    263     return enabled_bindings_ & BINDINGS_POLICY_WEB_UI;
    264   }
    265 
    266   bool can_read_raw_cookies() const {
    267     return can_read_raw_cookies_;
    268   }
    269 
    270   bool can_send_midi_sysex() const {
    271     return can_send_midi_sysex_;
    272   }
    273 
    274  private:
    275   typedef std::map<std::string, bool> SchemeMap;
    276 
    277   typedef int FilePermissionFlags;  // bit-set of base::File::Flags
    278   typedef std::map<base::FilePath, FilePermissionFlags> FileMap;
    279   typedef std::map<std::string, FilePermissionFlags> FileSystemMap;
    280   typedef std::set<base::FilePath> FileSet;
    281 
    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_;
    288 
    289   // The set of files the child process is permited to upload to the web.
    290   FileMap file_permissions_;
    291 
    292   // The set of files the child process is permitted to load.
    293   FileSet request_file_set_;
    294 
    295   int enabled_bindings_;
    296 
    297   bool can_read_raw_cookies_;
    298 
    299   bool can_send_midi_sysex_;
    300 
    301   GURL origin_lock_;
    302 
    303   // The set of isolated filesystems the child process is permitted to access.
    304   FileSystemMap filesystem_permissions_;
    305 
    306   DISALLOW_COPY_AND_ASSIGN(SecurityState);
    307 };
    308 
    309 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
    310   // We know about these schemes and believe them to be safe.
    311   RegisterWebSafeScheme(url::kHttpScheme);
    312   RegisterWebSafeScheme(url::kHttpsScheme);
    313   RegisterWebSafeScheme(url::kFtpScheme);
    314   RegisterWebSafeScheme(url::kDataScheme);
    315   RegisterWebSafeScheme("feed");
    316   RegisterWebSafeScheme(url::kBlobScheme);
    317   RegisterWebSafeScheme(url::kFileSystemScheme);
    318 
    319   // We know about the following pseudo schemes and treat them specially.
    320   RegisterPseudoScheme(url::kAboutScheme);
    321   RegisterPseudoScheme(url::kJavaScriptScheme);
    322   RegisterPseudoScheme(kViewSourceScheme);
    323 }
    324 
    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();
    331 }
    332 
    333 // static
    334 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
    335   return ChildProcessSecurityPolicyImpl::GetInstance();
    336 }
    337 
    338 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
    339   return Singleton<ChildProcessSecurityPolicyImpl>::get();
    340 }
    341 
    342 void ChildProcessSecurityPolicyImpl::Add(int child_id) {
    343   base::AutoLock lock(lock_);
    344   AddChild(child_id);
    345 }
    346 
    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;
    352 }
    353 
    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.
    359 
    360   delete it->second;
    361   security_state_.erase(it);
    362   worker_map_.erase(child_id);
    363 }
    364 
    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.";
    371 
    372   web_safe_schemes_.insert(scheme);
    373 }
    374 
    375 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
    376     const std::string& scheme) {
    377   base::AutoLock lock(lock_);
    378 
    379   return ContainsKey(web_safe_schemes_, scheme);
    380 }
    381 
    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.";
    388 
    389   pseudo_schemes_.insert(scheme);
    390 }
    391 
    392 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
    393     const std::string& scheme) {
    394   base::AutoLock lock(lock_);
    395 
    396   return ContainsKey(pseudo_schemes_, scheme);
    397 }
    398 
    399 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
    400     int child_id, const GURL& url) {
    401 
    402   if (!url.is_valid())
    403     return;  // Can't grant the capability to request invalid URLs.
    404 
    405   if (IsWebSafeScheme(url.scheme()))
    406     return;  // The scheme has already been whitelisted for every child process.
    407 
    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()));
    417     }
    418 
    419     return;  // Can't grant the capability to request pseudo schemes.
    420   }
    421 
    422   {
    423     base::AutoLock lock(lock_);
    424     SecurityStateMap::iterator state = security_state_.find(child_id);
    425     if (state == security_state_.end())
    426       return;
    427 
    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());
    431   }
    432 }
    433 
    434 void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
    435     int child_id,
    436     const GURL& url) {
    437   if (!url.SchemeIs(url::kFileScheme))
    438     return;
    439 
    440   {
    441     base::AutoLock lock(lock_);
    442     SecurityStateMap::iterator state = security_state_.find(child_id);
    443     if (state == security_state_.end())
    444       return;
    445 
    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);
    451   }
    452 }
    453 
    454 void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
    455                                                    const base::FilePath& file) {
    456   GrantPermissionsForFile(child_id, file, READ_FILE_GRANT);
    457 }
    458 
    459 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
    460     int child_id, const base::FilePath& file) {
    461   GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
    462 }
    463 
    464 void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id,
    465                                                    const base::FilePath& dir) {
    466   GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT);
    467 }
    468 
    469 void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
    470     int child_id, const base::FilePath& dir) {
    471   GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT);
    472 }
    473 
    474 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
    475     int child_id, const base::FilePath& file, int permissions) {
    476   base::AutoLock lock(lock_);
    477 
    478   SecurityStateMap::iterator state = security_state_.find(child_id);
    479   if (state == security_state_.end())
    480     return;
    481 
    482   state->second->GrantPermissionsForFile(file, permissions);
    483 }
    484 
    485 void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
    486     int child_id, const base::FilePath& file) {
    487   base::AutoLock lock(lock_);
    488 
    489   SecurityStateMap::iterator state = security_state_.find(child_id);
    490   if (state == security_state_.end())
    491     return;
    492 
    493   state->second->RevokeAllPermissionsForFile(file);
    494 }
    495 
    496 void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
    497     int child_id, const std::string& filesystem_id) {
    498   GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
    499 }
    500 
    501 void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
    502     int child_id, const std::string& filesystem_id) {
    503   GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT);
    504 }
    505 
    506 void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
    507     int child_id, const std::string& filesystem_id) {
    508   GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT);
    509 }
    510 
    511 void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
    512     int child_id, const std::string& filesystem_id) {
    513   GrantPermissionsForFileSystem(
    514       child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT);
    515 }
    516 
    517 void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
    518     int child_id, const std::string& filesystem_id) {
    519   GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT);
    520 }
    521 
    522 void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
    523     int child_id, const std::string& filesystem_id) {
    524   GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT);
    525 }
    526 
    527 void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
    528   base::AutoLock lock(lock_);
    529 
    530   SecurityStateMap::iterator state = security_state_.find(child_id);
    531   if (state == security_state_.end())
    532     return;
    533 
    534   state->second->GrantPermissionForMidiSysEx();
    535 }
    536 
    537 void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
    538                                                  const std::string& scheme) {
    539   base::AutoLock lock(lock_);
    540 
    541   SecurityStateMap::iterator state = security_state_.find(child_id);
    542   if (state == security_state_.end())
    543     return;
    544 
    545   state->second->GrantScheme(scheme);
    546 }
    547 
    548 void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) {
    549   base::AutoLock lock(lock_);
    550 
    551   SecurityStateMap::iterator state = security_state_.find(child_id);
    552   if (state == security_state_.end())
    553     return;
    554 
    555   state->second->GrantBindings(BINDINGS_POLICY_WEB_UI);
    556 
    557   // Web UI bindings need the ability to request chrome: URLs.
    558   state->second->GrantScheme(kChromeUIScheme);
    559 
    560   // Web UI pages can contain links to file:// URLs.
    561   state->second->GrantScheme(url::kFileScheme);
    562 }
    563 
    564 void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
    565   base::AutoLock lock(lock_);
    566 
    567   SecurityStateMap::iterator state = security_state_.find(child_id);
    568   if (state == security_state_.end())
    569     return;
    570 
    571   state->second->GrantReadRawCookies();
    572 }
    573 
    574 void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) {
    575   base::AutoLock lock(lock_);
    576 
    577   SecurityStateMap::iterator state = security_state_.find(child_id);
    578   if (state == security_state_.end())
    579     return;
    580 
    581   state->second->RevokeReadRawCookies();
    582 }
    583 
    584 bool ChildProcessSecurityPolicyImpl::CanLoadPage(int child_id,
    585                                                  const GURL& url,
    586                                                  ResourceType resource_type) {
    587   // If --site-per-process flag is passed, we should enforce
    588   // stronger security restrictions on page navigation.
    589   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
    590           switches::kSitePerProcess) &&
    591       IsResourceTypeFrame(resource_type)) {
    592     // TODO(nasko): Do the proper check for site-per-process, once
    593     // out-of-process iframes is ready to go.
    594     return true;
    595   }
    596   return true;
    597 }
    598 
    599 bool ChildProcessSecurityPolicyImpl::CanRequestURL(
    600     int child_id, const GURL& url) {
    601   if (!url.is_valid())
    602     return false;  // Can't request invalid URLs.
    603 
    604   if (IsWebSafeScheme(url.scheme()))
    605     return true;  // The scheme has been white-listed for every child process.
    606 
    607   if (IsPseudoScheme(url.scheme())) {
    608     // There are a number of special cases for pseudo schemes.
    609 
    610     if (url.SchemeIs(kViewSourceScheme)) {
    611       // A view-source URL is allowed if the child process is permitted to
    612       // request the embedded URL. Careful to avoid pointless recursion.
    613       GURL child_url(url.GetContent());
    614       if (child_url.SchemeIs(kViewSourceScheme) &&
    615           url.SchemeIs(kViewSourceScheme))
    616           return false;
    617 
    618       return CanRequestURL(child_id, child_url);
    619     }
    620 
    621     if (LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
    622       return true;  // Every child process can request <about:blank>.
    623 
    624     // URLs like <about:memory> and <about:crash> shouldn't be requestable by
    625     // any child process.  Also, this case covers <javascript:...>, which should
    626     // be handled internally by the process and not kicked up to the browser.
    627     return false;
    628   }
    629 
    630   if (!GetContentClient()->browser()->IsHandledURL(url) &&
    631       !net::URLRequest::IsHandledURL(url)) {
    632     return true;  // This URL request is destined for ShellExecute.
    633   }
    634 
    635   {
    636     base::AutoLock lock(lock_);
    637 
    638     SecurityStateMap::iterator state = security_state_.find(child_id);
    639     if (state == security_state_.end())
    640       return false;
    641 
    642     // Otherwise, we consult the child process's security state to see if it is
    643     // allowed to request the URL.
    644     return state->second->CanRequestURL(url);
    645   }
    646 }
    647 
    648 bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
    649                                                  const base::FilePath& file) {
    650   return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
    651 }
    652 
    653 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
    654     int child_id,
    655     const base::FilePath& file) {
    656   return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
    657 }
    658 
    659 bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
    660     int child_id, const std::string& filesystem_id) {
    661   return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
    662 }
    663 
    664 bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
    665     int child_id, const std::string& filesystem_id) {
    666   return HasPermissionsForFileSystem(child_id, filesystem_id,
    667                                      READ_FILE_GRANT | WRITE_FILE_GRANT);
    668 }
    669 
    670 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
    671     int child_id, const std::string& filesystem_id) {
    672   return HasPermissionsForFileSystem(child_id, filesystem_id,
    673                                      COPY_INTO_FILE_GRANT);
    674 }
    675 
    676 bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
    677     int child_id, const std::string& filesystem_id) {
    678   return HasPermissionsForFileSystem(child_id, filesystem_id,
    679                                      DELETE_FILE_GRANT);
    680 }
    681 
    682 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
    683     int child_id, const base::FilePath& file, int permissions) {
    684   base::AutoLock lock(lock_);
    685   bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions);
    686   if (!result) {
    687     // If this is a worker thread that has no access to a given file,
    688     // let's check that its renderer process has access to that file instead.
    689     WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id);
    690     if (iter != worker_map_.end() && iter->second != 0) {
    691       result = ChildProcessHasPermissionsForFile(iter->second,
    692                                                  file,
    693                                                  permissions);
    694     }
    695   }
    696   return result;
    697 }
    698 
    699 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
    700     int child_id,
    701     const storage::FileSystemURL& url,
    702     int permissions) {
    703   if (!url.is_valid())
    704     return false;
    705 
    706   if (url.path().ReferencesParent())
    707     return false;
    708 
    709   // Any write access is disallowed on the root path.
    710   if (storage::VirtualPath::IsRootPath(url.path()) &&
    711       (permissions & ~READ_FILE_GRANT)) {
    712     return false;
    713   }
    714 
    715   if (url.mount_type() == storage::kFileSystemTypeIsolated) {
    716     // When Isolated filesystems is overlayed on top of another filesystem,
    717     // its per-filesystem permission overrides the underlying filesystem
    718     // permissions).
    719     return HasPermissionsForFileSystem(
    720         child_id, url.mount_filesystem_id(), permissions);
    721   }
    722 
    723   FileSystemPermissionPolicyMap::iterator found =
    724       file_system_policy_map_.find(url.type());
    725   if (found == file_system_policy_map_.end())
    726     return false;
    727 
    728   if ((found->second & storage::FILE_PERMISSION_READ_ONLY) &&
    729       permissions & ~READ_FILE_GRANT) {
    730     return false;
    731   }
    732 
    733   if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
    734     return HasPermissionsForFile(child_id, url.path(), permissions);
    735 
    736   if (found->second & storage::FILE_PERMISSION_SANDBOX)
    737     return true;
    738 
    739   return false;
    740 }
    741 
    742 bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
    743     int child_id,
    744     const storage::FileSystemURL& url) {
    745   return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
    746 }
    747 
    748 bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
    749     int child_id,
    750     const storage::FileSystemURL& url) {
    751   return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
    752 }
    753 
    754 bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
    755     int child_id,
    756     const storage::FileSystemURL& url) {
    757   return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
    758 }
    759 
    760 bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
    761     int child_id,
    762     const storage::FileSystemURL& url) {
    763   return HasPermissionsForFileSystemFile(child_id, url,
    764                                          CREATE_READ_WRITE_FILE_GRANT);
    765 }
    766 
    767 bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
    768     int child_id,
    769     const storage::FileSystemURL& url) {
    770   return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
    771 }
    772 
    773 bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
    774     int child_id,
    775     const storage::FileSystemURL& url) {
    776   return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
    777 }
    778 
    779 bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
    780   base::AutoLock lock(lock_);
    781 
    782   SecurityStateMap::iterator state = security_state_.find(child_id);
    783   if (state == security_state_.end())
    784     return false;
    785 
    786   return state->second->has_web_ui_bindings();
    787 }
    788 
    789 bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
    790   base::AutoLock lock(lock_);
    791 
    792   SecurityStateMap::iterator state = security_state_.find(child_id);
    793   if (state == security_state_.end())
    794     return false;
    795 
    796   return state->second->can_read_raw_cookies();
    797 }
    798 
    799 void ChildProcessSecurityPolicyImpl::AddChild(int child_id) {
    800   if (security_state_.count(child_id) != 0) {
    801     NOTREACHED() << "Add child process at most once.";
    802     return;
    803   }
    804 
    805   security_state_[child_id] = new SecurityState();
    806 }
    807 
    808 bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
    809     int child_id, const base::FilePath& file, int permissions) {
    810   SecurityStateMap::iterator state = security_state_.find(child_id);
    811   if (state == security_state_.end())
    812     return false;
    813   return state->second->HasPermissionsForFile(file, permissions);
    814 }
    815 
    816 bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
    817     int child_id, const GURL& gurl) {
    818   base::AutoLock lock(lock_);
    819   SecurityStateMap::iterator state = security_state_.find(child_id);
    820   if (state == security_state_.end())
    821     return false;
    822   return state->second->CanAccessCookiesForOrigin(gurl);
    823 }
    824 
    825 bool ChildProcessSecurityPolicyImpl::CanSendCookiesForOrigin(int child_id,
    826                                                              const GURL& gurl) {
    827   for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
    828     if (iter.GetData().id == child_id) {
    829       if (iter.GetData().process_type == PROCESS_TYPE_PLUGIN) {
    830         // NPAPI plugin processes are unsandboxed and so are trusted. Plugins
    831         // can make request to any origin.
    832         return true;
    833       }
    834       break;
    835     }
    836   }
    837 
    838   base::AutoLock lock(lock_);
    839   SecurityStateMap::iterator state = security_state_.find(child_id);
    840   if (state == security_state_.end())
    841     return false;
    842   return state->second->CanSendCookiesForOrigin(gurl);
    843 }
    844 
    845 void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
    846                                                   const GURL& gurl) {
    847   // "gurl" can be currently empty in some cases, such as file://blah.
    848   DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl);
    849   base::AutoLock lock(lock_);
    850   SecurityStateMap::iterator state = security_state_.find(child_id);
    851   DCHECK(state != security_state_.end());
    852   state->second->LockToOrigin(gurl);
    853 }
    854 
    855 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
    856     int child_id,
    857     const std::string& filesystem_id,
    858     int permission) {
    859   base::AutoLock lock(lock_);
    860 
    861   SecurityStateMap::iterator state = security_state_.find(child_id);
    862   if (state == security_state_.end())
    863     return;
    864   state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
    865 }
    866 
    867 bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
    868     int child_id,
    869     const std::string& filesystem_id,
    870     int permission) {
    871   base::AutoLock lock(lock_);
    872 
    873   SecurityStateMap::iterator state = security_state_.find(child_id);
    874   if (state == security_state_.end())
    875     return false;
    876   return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
    877 }
    878 
    879 void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
    880     storage::FileSystemType type,
    881     int policy) {
    882   base::AutoLock lock(lock_);
    883   file_system_policy_map_[type] = policy;
    884 }
    885 
    886 bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
    887   base::AutoLock lock(lock_);
    888 
    889   SecurityStateMap::iterator state = security_state_.find(child_id);
    890   if (state == security_state_.end())
    891     return false;
    892 
    893   return state->second->can_send_midi_sysex();
    894 }
    895 
    896 }  // namespace content
    897