// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/child_process_security_policy_impl.h"

#include <tuple>
#include <utility>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/isolated_origin_util.h"
#include "content/browser/process_lock.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/url_info.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_or_resource_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_constants.h"
#include "net/base/filename_util.h"
#include "net/base/url_util.h"
#include "net/net_buildflags.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/file_system/file_permission_policy.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/browser/file_system/isolated_context.h"
#include "storage/common/file_system/file_system_util.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_constants.h"

namespace content {

namespace {

// Used internally only. These bit positions have no relationship to any
// underlying OS and can be changed to accommodate finer-grained permissions.
enum ChildProcessSecurityPermissions {
  READ_FILE_PERMISSION             = 1 << 0,
  WRITE_FILE_PERMISSION            = 1 << 1,
  CREATE_NEW_FILE_PERMISSION       = 1 << 2,
  CREATE_OVERWRITE_FILE_PERMISSION = 1 << 3,
  DELETE_FILE_PERMISSION           = 1 << 4,

  // Used by Media Galleries API
  COPY_INTO_FILE_PERMISSION        = 1 << 5,
};

// Used internally only. Bitmasks that are actually used by the Grant* and Can*
// methods. These contain one or more ChildProcessSecurityPermissions.
enum ChildProcessSecurityGrants {
  READ_FILE_GRANT              = READ_FILE_PERMISSION,
  WRITE_FILE_GRANT             = WRITE_FILE_PERMISSION,

  CREATE_NEW_FILE_GRANT        = CREATE_NEW_FILE_PERMISSION |
                                 COPY_INTO_FILE_PERMISSION,

  CREATE_READ_WRITE_FILE_GRANT = CREATE_NEW_FILE_PERMISSION |
                                 CREATE_OVERWRITE_FILE_PERMISSION |
                                 READ_FILE_PERMISSION |
                                 WRITE_FILE_PERMISSION |
                                 COPY_INTO_FILE_PERMISSION |
                                 DELETE_FILE_PERMISSION,

  COPY_INTO_FILE_GRANT         = COPY_INTO_FILE_PERMISSION,
  DELETE_FILE_GRANT            = DELETE_FILE_PERMISSION,
};

// https://crbug.com/646278 Valid blob URLs should contain canonically
// serialized origins.
bool IsMalformedBlobUrl(const GURL& url) {
  if (!url.SchemeIsBlob())
    return false;

  // If the part after blob: survives a roundtrip through url::Origin, then
  // it's a normal blob URL.
  std::string canonical_origin = url::Origin::Create(url).Serialize();
  canonical_origin.append(1, '/');
  if (base::StartsWith(url.GetContent(), canonical_origin,
                       base::CompareCase::INSENSITIVE_ASCII))
    return false;

  // This is a malformed blob URL.
  return true;
}

// Helper function that checks to make sure calls on
// CanAccessDataForOrigin() are only made on valid threads.
// TODO(acolwell): Expand the usage of this check to other
// ChildProcessSecurityPolicyImpl methods.
bool IsRunningOnExpectedThread() {
  if (BrowserThread::CurrentlyOn(BrowserThread::IO) ||
      BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    return true;
  }

  std::string thread_name(base::PlatformThread::GetName());

  // TODO(acolwell): Remove once all tests are updated to properly
  // identify that they are running on the UI or IO threads.
  if (thread_name.empty())
    return true;

  LOG(ERROR) << "Running on unexpected thread '" << thread_name << "'";
  return false;
}

base::debug::CrashKeyString* GetRequestedOriginCrashKey() {
  static auto* requested_origin_key = base::debug::AllocateCrashKeyString(
      "requested_origin", base::debug::CrashKeySize::Size256);
  return requested_origin_key;
}

base::debug::CrashKeyString* GetExpectedProcessLockKey() {
  static auto* expected_process_lock_key = base::debug::AllocateCrashKeyString(
      "expected_process_lock", base::debug::CrashKeySize::Size64);
  return expected_process_lock_key;
}

base::debug::CrashKeyString* GetKilledProcessOriginLockKey() {
  static auto* crash_key = base::debug::AllocateCrashKeyString(
      "killed_process_origin_lock", base::debug::CrashKeySize::Size64);
  return crash_key;
}

base::debug::CrashKeyString* GetCanAccessDataFailureReasonKey() {
  static auto* crash_key = base::debug::AllocateCrashKeyString(
      "can_access_data_failure_reason", base::debug::CrashKeySize::Size256);
  return crash_key;
}

base::debug::CrashKeyString* GetCanAccessDataKeepAliveDurationKey() {
  static auto* keep_alive_duration_key = base::debug::AllocateCrashKeyString(
      "keep_alive_duration", base::debug::CrashKeySize::Size256);
  return keep_alive_duration_key;
}

base::debug::CrashKeyString* GetCanAccessDataShutdownDelayRefCountKey() {
  static auto* shutdown_delay_key = base::debug::AllocateCrashKeyString(
      "shutdown_delay_ref_count", base::debug::CrashKeySize::Size32);
  return shutdown_delay_key;
}

base::debug::CrashKeyString* GetCanAccessDataProcessRFHCount() {
  static auto* process_rfh_count_key = base::debug::AllocateCrashKeyString(
      "process_rfh_count", base::debug::CrashKeySize::Size32);
  return process_rfh_count_key;
}

void LogCanAccessDataForOriginCrashKeys(
    const std::string& expected_process_lock,
    const std::string& killed_process_origin_lock,
    const std::string& requested_origin,
    const std::string& failure_reason,
    const std::string& keep_alive_durations,
    const std::string& shutdown_delay_ref_count,
    const std::string& process_rfh_count) {
  base::debug::SetCrashKeyString(GetExpectedProcessLockKey(),
                                 expected_process_lock);
  base::debug::SetCrashKeyString(GetKilledProcessOriginLockKey(),
                                 killed_process_origin_lock);
  base::debug::SetCrashKeyString(GetRequestedOriginCrashKey(),
                                 requested_origin);
  base::debug::SetCrashKeyString(GetCanAccessDataFailureReasonKey(),
                                 failure_reason);
  base::debug::SetCrashKeyString(GetCanAccessDataKeepAliveDurationKey(),
                                 keep_alive_durations);
  base::debug::SetCrashKeyString(GetCanAccessDataShutdownDelayRefCountKey(),
                                 shutdown_delay_ref_count);
  base::debug::SetCrashKeyString(GetCanAccessDataProcessRFHCount(),
                                 process_rfh_count);
}

// Checks whether a lock mismatch should be ignored to allow most visited tiles
// to commit in third-party NTP processes.
//
// TODO(crbug.com/566091): This exception should be removed once these tiles
// can be loaded in OOPIFs on the NTP.
bool AllowProcessLockMismatchForNTP(const ProcessLock& expected_lock,
                                    const ProcessLock& actual_lock) {
  // First, ensure that the expected lock corresponds to a WebUI site that
  // does not require its process to be locked.  This should only be the case
  // for sites used to load most visited tiles.
  const auto& webui_schemes = URLDataManagerBackend::GetWebUISchemes();
  if (!base::Contains(webui_schemes, expected_lock.lock_url().scheme())) {
    return false;
  }
  if (GetContentClient()->browser()->DoesWebUIUrlRequireProcessLock(
          expected_lock.lock_url())) {
    return false;
  }

  // Now, check that the actual lock corresponds to an NTP process (using its
  // site_url() since this check relies on checking effective URLs for NTPs),
  // and that the expected lock (based on the URL for which we're doing the
  // access check) is allowed to stay in that process. This restricts the lock
  // mismatch to just NTP processes, disallowing most visited tiles from being
  // embedded on sites in other processes.
  return GetContentClient()->browser()->ShouldStayInParentProcessForNTP(
      expected_lock.lock_url(), actual_lock.site_url());
}

}  // namespace

ChildProcessSecurityPolicyImpl::Handle::Handle()
    : child_id_(ChildProcessHost::kInvalidUniqueID) {}

ChildProcessSecurityPolicyImpl::Handle::Handle(int child_id,
                                               bool duplicating_handle)
    : child_id_(child_id) {
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  if (!policy->AddProcessReference(child_id_, duplicating_handle))
    child_id_ = ChildProcessHost::kInvalidUniqueID;
}

ChildProcessSecurityPolicyImpl::Handle::Handle(Handle&& rhs)
    : child_id_(rhs.child_id_) {
  rhs.child_id_ = ChildProcessHost::kInvalidUniqueID;
}

ChildProcessSecurityPolicyImpl::Handle
ChildProcessSecurityPolicyImpl::Handle::Duplicate() {
  return Handle(child_id_, /* duplicating_handle */ true);
}

ChildProcessSecurityPolicyImpl::Handle::~Handle() {
  if (child_id_ != ChildProcessHost::kInvalidUniqueID) {
    auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
    policy->RemoveProcessReference(child_id_);
  }
}

ChildProcessSecurityPolicyImpl::Handle& ChildProcessSecurityPolicyImpl::Handle::
operator=(Handle&& rhs) {
  if (child_id_ != ChildProcessHost::kInvalidUniqueID &&
      child_id_ != rhs.child_id_) {
    auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
    policy->RemoveProcessReference(child_id_);
  }
  child_id_ = rhs.child_id_;
  rhs.child_id_ = ChildProcessHost::kInvalidUniqueID;
  return *this;
}

bool ChildProcessSecurityPolicyImpl::Handle::is_valid() const {
  return child_id_ != ChildProcessHost::kInvalidUniqueID;
}

bool ChildProcessSecurityPolicyImpl::Handle::CanCommitURL(const GURL& url) {
  if (child_id_ == ChildProcessHost::kInvalidUniqueID)
    return false;

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  return policy->CanCommitURL(child_id_, url);
}

bool ChildProcessSecurityPolicyImpl::Handle::CanReadFile(
    const base::FilePath& file) {
  if (child_id_ == ChildProcessHost::kInvalidUniqueID)
    return false;

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  return policy->CanReadFile(child_id_, file);
}

bool ChildProcessSecurityPolicyImpl::Handle::CanReadFileSystemFile(
    const storage::FileSystemURL& url) {
  if (child_id_ == ChildProcessHost::kInvalidUniqueID)
    return false;

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  return policy->CanReadFileSystemFile(child_id_, url);
}

bool ChildProcessSecurityPolicyImpl::Handle::CanAccessDataForOrigin(
    const url::Origin& origin) {
  if (child_id_ == ChildProcessHost::kInvalidUniqueID) {
    LogCanAccessDataForOriginCrashKeys(
        "(unknown)", "(unknown)", origin.GetDebugString(), "handle_not_valid",
        "no_keep_alive_durations", "no shutdown delay ref count",
        "no process rfh count");
    return false;
  }

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  return policy->CanAccessDataForOrigin(child_id_, origin);
}

ChildProcessSecurityPolicyImpl::OriginAgentClusterOptInEntry::
    OriginAgentClusterOptInEntry(
        const OriginAgentClusterIsolationState& oac_isolation_state_in,
        const url::Origin& origin_in)
    : oac_isolation_state(oac_isolation_state_in), origin(origin_in) {}

ChildProcessSecurityPolicyImpl::OriginAgentClusterOptInEntry::
    OriginAgentClusterOptInEntry(const OriginAgentClusterOptInEntry&) = default;

ChildProcessSecurityPolicyImpl::OriginAgentClusterOptInEntry::
    ~OriginAgentClusterOptInEntry() = default;

// The SecurityState class is used to maintain per-child process security state
// information.
class ChildProcessSecurityPolicyImpl::SecurityState {
 public:
  typedef std::map<BrowsingInstanceId, OriginAgentClusterIsolationState>
      BrowsingInstanceInfoMap;

  explicit SecurityState(BrowserContext* browser_context)
      : enabled_bindings_(0),
        can_read_raw_cookies_(false),
        can_send_midi_sysex_(false),
        browser_context_(browser_context),
        resource_context_(browser_context->GetResourceContext()) {}

  SecurityState(const SecurityState&) = delete;
  SecurityState& operator=(const SecurityState&) = delete;

  ~SecurityState() {
    storage::IsolatedContext* isolated_context =
        storage::IsolatedContext::GetInstance();
    for (auto iter = filesystem_permissions_.begin();
         iter != filesystem_permissions_.end(); ++iter) {
      isolated_context->RemoveReference(iter->first);
    }
    UMA_HISTOGRAM_COUNTS_10000(
        "SiteIsolation.BrowsingInstance.MaxCountPerProcess",
        max_browsing_instance_count_);
  }

  // Grant permission to request and commit URLs with the specified origin.
  void GrantCommitOrigin(const url::Origin& origin) {
    if (origin.opaque())
      return;
    origin_map_[origin] = CommitRequestPolicy::kCommitAndRequest;
  }

  void GrantRequestOrigin(const url::Origin& origin) {
    if (origin.opaque())
      return;
    // Anything already in |origin_map_| must have at least request permission
    // already. In that case, the emplace() below will be a no-op.
    origin_map_.emplace(origin, CommitRequestPolicy::kRequestOnly);
  }

  void GrantCommitScheme(const std::string& scheme) {
    scheme_map_[scheme] = CommitRequestPolicy::kCommitAndRequest;
  }

  void GrantRequestScheme(const std::string& scheme) {
    // Anything already in |scheme_map_| must have at least request permission
    // already. In that case, the emplace() below will be a no-op.
    scheme_map_.emplace(scheme, CommitRequestPolicy::kRequestOnly);
  }

  // Grant certain permissions to a file.
  void GrantPermissionsForFile(const base::FilePath& file, int permissions) {
    base::FilePath stripped = file.StripTrailingSeparators();
    file_permissions_[stripped] |= permissions;
  }

  // Grant navigation to a file but not the file:// scheme in general.
  void GrantRequestOfSpecificFile(const base::FilePath &file) {
    request_file_set_.insert(file.StripTrailingSeparators());
  }

  // Revokes all permissions granted to a file.
  void RevokeAllPermissionsForFile(const base::FilePath& file) {
    base::FilePath stripped = file.StripTrailingSeparators();
    file_permissions_.erase(stripped);
    request_file_set_.erase(stripped);
  }

  // Grant certain permissions to a file.
  void GrantPermissionsForFileSystem(const std::string& filesystem_id,
                                     int permissions) {
    if (!base::Contains(filesystem_permissions_, filesystem_id))
      storage::IsolatedContext::GetInstance()->AddReference(filesystem_id);
    filesystem_permissions_[filesystem_id] |= permissions;
  }

  bool HasPermissionsForFileSystem(const std::string& filesystem_id,
                                   int permissions) {
    FileSystemMap::const_iterator it =
        filesystem_permissions_.find(filesystem_id);
    if (it == filesystem_permissions_.end())
      return false;
    return (it->second & permissions) == permissions;
  }

#if BUILDFLAG(IS_ANDROID)
  // Determine if the certain permissions have been granted to a content URI.
  bool HasPermissionsForContentUri(const base::FilePath& file,
                                   int permissions) {
    DCHECK(!file.empty());
    DCHECK(file.IsContentUri());
    if (!permissions)
      return false;
    base::FilePath file_path = file.StripTrailingSeparators();
    FileMap::const_iterator it = file_permissions_.find(file_path);
    if (it != file_permissions_.end())
      return (it->second & permissions) == permissions;
    return false;
  }
#endif

  void GrantBindings(int bindings) {
    enabled_bindings_ |= bindings;
  }

  void GrantReadRawCookies() {
    can_read_raw_cookies_ = true;
  }

  void RevokeReadRawCookies() {
    can_read_raw_cookies_ = false;
  }

  void GrantPermissionForMidiSysEx() {
    can_send_midi_sysex_ = true;
  }

  // Determine whether permission has been granted to commit |url|.
  bool CanCommitURL(const GURL& url) {
    DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem())
        << "inner_url extraction should be done already.";
    // Having permission to a scheme implies permission to all of its URLs.
    auto scheme_judgment = scheme_map_.find(url.scheme());
    if (scheme_judgment != scheme_map_.end() &&
        scheme_judgment->second == CommitRequestPolicy::kCommitAndRequest) {
      return true;
    }

    // Check for permission for specific origin.
    if (CanCommitOrigin(url::Origin::Create(url)))
      return true;

    // file:// URLs may sometimes be more granular, e.g. dragging and dropping a
    // file from the local filesystem. The child itself may not have been
    // granted access to the entire file:// scheme, but it should still be
    // allowed to request the dragged and dropped file.
    if (url.SchemeIs(url::kFileScheme)) {
      base::FilePath path;
      if (net::FileURLToFilePath(url, &path))
        return base::Contains(request_file_set_, path);
    }

    return false;  // Unmentioned schemes are disallowed.
  }

  bool CanRequestURL(const GURL& url) {
    DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem())
        << "inner_url extraction should be done already.";
    // Having permission to a scheme implies permission to all of its URLs.
    auto scheme_judgment = scheme_map_.find(url.scheme());
    if (scheme_judgment != scheme_map_.end())
      return true;

    if (CanRequestOrigin(url::Origin::Create(url)))
      return true;

    // Otherwise, delegate to CanCommitURL. Unmentioned schemes are disallowed.
    // TODO(dcheng): It would be nice to avoid constructing the origin twice.
    return CanCommitURL(url);
  }

  // Determine if the certain permissions have been granted to a file.
  bool HasPermissionsForFile(const base::FilePath& file, int permissions) {
#if BUILDFLAG(IS_ANDROID)
    if (file.IsContentUri())
      return HasPermissionsForContentUri(file, permissions);
#endif
    if (!permissions || file.empty() || !file.IsAbsolute())
      return false;
    base::FilePath current_path = file.StripTrailingSeparators();
    base::FilePath last_path;
    int skip = 0;
    while (current_path != last_path) {
      base::FilePath base_name = current_path.BaseName();
      if (base_name.value() == base::FilePath::kParentDirectory) {
        ++skip;
      } else if (skip > 0) {
        if (base_name.value() != base::FilePath::kCurrentDirectory)
          --skip;
      } else {
        FileMap::const_iterator it = file_permissions_.find(current_path);
        if (it != file_permissions_.end())
          return (it->second & permissions) == permissions;
      }
      last_path = current_path;
      current_path = current_path.DirName();
    }

    return false;
  }

  void SetProcessLock(const ProcessLock& lock_to_set,
                      const IsolationContext& context,
                      bool is_process_used) {
    CHECK(!lock_to_set.is_invalid());
    CHECK(!process_lock_.is_locked_to_site());
    CHECK_NE(SiteInstanceImpl::GetDefaultSiteURL(), lock_to_set.lock_url());

    if (process_lock_.is_invalid()) {
      DCHECK(browsing_instance_info_map_.empty());
      CHECK(lock_to_set.allows_any_site() || lock_to_set.is_locked_to_site());
    } else {
      // Verify that we are not trying to update the lock with different
      // COOP/COEP information.
      CHECK_EQ(process_lock_.GetWebExposedIsolationInfo(),
               lock_to_set.GetWebExposedIsolationInfo());

      if (process_lock_.allows_any_site()) {
        // TODO(acolwell): Remove ability to lock to an allows_any_site
        // lock multiple times. Legacy behavior allows the old "lock to site"
        // path to generate an "allow_any_site" lock if an empty URL is passed
        // to SiteInstanceImpl::SetSite().
        CHECK(lock_to_set.allows_any_site() || lock_to_set.is_locked_to_site());

        // Do not allow a lock to become more strict if the process has already
        // been used to render any pages.
        if (lock_to_set.is_locked_to_site()) {
          CHECK(!is_process_used)
              << "Cannot lock an already used process to " << lock_to_set;
        }
      } else {
        NOTREACHED() << "Unexpected lock type.";
      }
    }

    process_lock_ = lock_to_set;
    AddBrowsingInstanceInfo(context);
  }

  void AddBrowsingInstanceInfo(const IsolationContext& context) {
    DCHECK(!context.browsing_instance_id().is_null());
    browsing_instance_info_map_.insert(
        {context.browsing_instance_id(), context.default_isolation_state()});

    // Track the maximum number of BrowsingInstances in the process in case
    // we need to remove delayed cleanup and let the set grow unbounded.
    // Also track the default isolation state for this BrowsingInstance for
    // future access checks, since the global default can change over time.
    if (browsing_instance_info_map_.size() > max_browsing_instance_count_) {
      max_browsing_instance_count_ = browsing_instance_info_map_.size();
    }
  }

  const ProcessLock& process_lock() const { return process_lock_; }

  const BrowsingInstanceInfoMap& browsing_instance_info() {
    return browsing_instance_info_map_;
  }

  void ClearBrowsingInstanceId(const BrowsingInstanceId& id) {
    browsing_instance_info_map_.erase(id);
  }

  bool has_web_ui_bindings() const {
    return enabled_bindings_ & kWebUIBindingsPolicyMask;
  }

  bool can_read_raw_cookies() const {
    return can_read_raw_cookies_;
  }

  bool can_send_midi_sysex() const {
    return can_send_midi_sysex_;
  }

  BrowserOrResourceContext GetBrowserOrResourceContext() const {
    if (BrowserThread::CurrentlyOn(BrowserThread::UI) && browser_context_)
      return BrowserOrResourceContext(browser_context_);

    if (BrowserThread::CurrentlyOn(BrowserThread::IO) && resource_context_)
      return BrowserOrResourceContext(resource_context_);

    return BrowserOrResourceContext();
  }

  void ClearBrowserContextIfMatches(const BrowserContext* browser_context) {
    if (browser_context == browser_context_)
      browser_context_ = nullptr;
  }

 private:
  enum class CommitRequestPolicy {
    kRequestOnly,
    kCommitAndRequest,
  };

  bool CanCommitOrigin(const url::Origin& origin) {
    auto it = origin_map_.find(origin);
    if (it == origin_map_.end())
      return false;
    return it->second == CommitRequestPolicy::kCommitAndRequest;
  }

  bool CanRequestOrigin(const url::Origin& origin) {
    // Anything already in |origin_map_| must have at least request permissions
    // already.
    return origin_map_.find(origin) != origin_map_.end();
  }

  typedef std::map<std::string, CommitRequestPolicy> SchemeMap;
  typedef std::map<url::Origin, CommitRequestPolicy> OriginMap;

  typedef int FilePermissionFlags;  // bit-set of base::File::Flags
  typedef std::map<base::FilePath, FilePermissionFlags> FileMap;
  typedef std::map<std::string, FilePermissionFlags> FileSystemMap;
  typedef std::set<base::FilePath> FileSet;

  // Maps URL schemes to commit/request policies the child process has been
  // granted. There is no provision for revoking.
  SchemeMap scheme_map_;

  // The map of URL origins to commit/request policies the child process has
  // been granted. There is no provision for revoking.
  OriginMap origin_map_;

  // The set of files the child process is permited to upload to the web.
  FileMap file_permissions_;

  // The set of files the child process is permitted to load.
  FileSet request_file_set_;

  int enabled_bindings_;

  bool can_read_raw_cookies_;

  bool can_send_midi_sysex_;

  ProcessLock process_lock_;

  // A map containing the IDs of all BrowsingInstances with documents in this
  // process, along with their default isolation states. Empty when
  // |process_lock_| is invalid, or if all BrowsingInstances in the
  // SecurityState have been destroyed.
  //
  // After a process is locked, it might be reused by navigations from frames
  // in other BrowsingInstances, e.g., when we're over process limit and when
  // those navigations utilize the same process lock. This set tracks all the
  // BrowsingInstances that share this process.
  //
  // This is needed for security checks on the IO thread, where we only know
  // the process ID and need to compute the expected origin lock, which
  // requires knowing the set of applicable isolated origins in each respective
  // BrowsingInstance.
  BrowsingInstanceInfoMap browsing_instance_info_map_;

  // The maximum number of BrowsingInstances that have been in this
  // SecurityState's RenderProcessHost, for metrics.
  unsigned max_browsing_instance_count_ = 0;

  // The set of isolated filesystems the child process is permitted to access.
  FileSystemMap filesystem_permissions_;

  raw_ptr<BrowserContext> browser_context_;
  raw_ptr<ResourceContext, DanglingUntriaged> resource_context_;
};

// IsolatedOriginEntry implementation.
ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::IsolatedOriginEntry(
    const url::Origin& origin,
    bool applies_to_future_browsing_instances,
    BrowsingInstanceId browsing_instance_id,
    BrowserContext* browser_context,
    ResourceContext* resource_context,
    bool isolate_all_subdomains,
    IsolatedOriginSource source)
    : origin_(origin),
      applies_to_future_browsing_instances_(
          applies_to_future_browsing_instances),
      browsing_instance_id_(browsing_instance_id),
      browser_context_(browser_context),
      resource_context_(resource_context),
      isolate_all_subdomains_(isolate_all_subdomains),
      source_(source) {
  // If there is a BrowserContext, there must also be a ResourceContext
  // associated with this entry.
  DCHECK_EQ(!browser_context, !resource_context);
}

ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::IsolatedOriginEntry(
    const IsolatedOriginEntry& other) = default;

ChildProcessSecurityPolicyImpl::IsolatedOriginEntry&
ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::operator=(
    const IsolatedOriginEntry& other) = default;

ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::IsolatedOriginEntry(
    IsolatedOriginEntry&& other) = default;

ChildProcessSecurityPolicyImpl::IsolatedOriginEntry&
ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::operator=(
    IsolatedOriginEntry&& other) = default;

ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::~IsolatedOriginEntry() =
    default;

bool ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::
    AppliesToAllBrowserContexts() const {
  return !browser_context_;
}

bool ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::MatchesProfile(
    const BrowserOrResourceContext& browser_or_resource_context) const {
  DCHECK(IsRunningOnExpectedThread());

  // Globally isolated origins aren't associated with any particular profile
  // and should apply to all profiles.
  if (AppliesToAllBrowserContexts())
    return true;

  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    return browser_context_ == browser_or_resource_context.ToBrowserContext();
  } else if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
    return resource_context_ == browser_or_resource_context.ToResourceContext();
  }
  NOTREACHED();
  return false;
}

bool ChildProcessSecurityPolicyImpl::IsolatedOriginEntry::
    MatchesBrowsingInstance(BrowsingInstanceId browsing_instance_id) const {
  if (applies_to_future_browsing_instances_)
    return browsing_instance_id_ <= browsing_instance_id;

  return browsing_instance_id_ == browsing_instance_id;
}

// Make sure BrowsingInstance state is cleaned up after the max amount of time
// RenderProcessHost might stick around for various IncrementKeepAliveRefCount
// calls. For now, track that as the KeepAliveHandleFactory timeout (the current
// longest value) plus the unload timeout, with a bit of an extra margin.
// // TODO(wjmaclean): Refactor IncrementKeepAliveRefCount to track how much
// time is needed rather than leaving the interval open ended, so that we can
// enforce a max delay here and in RenderProcessHost. https://crbug.com/1181838
ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl()
    : browsing_instance_cleanup_delay_(
          RenderProcessHostImpl::kKeepAliveHandleFactoryTimeout +
          base::Seconds(2)) {
  // We know about these schemes and believe them to be safe.
  RegisterWebSafeScheme(url::kHttpScheme);
  RegisterWebSafeScheme(url::kHttpsScheme);
#if BUILDFLAG(ENABLE_WEBSOCKETS)
  RegisterWebSafeScheme(url::kWsScheme);
  RegisterWebSafeScheme(url::kWssScheme);
#endif  // BUILDFLAG(ENABLE_WEBSOCKETS)
  RegisterWebSafeScheme(url::kDataScheme);

  // TODO(nick): https://crbug.com/651534 blob: and filesystem: schemes embed
  // other origins, so we should not treat them as web safe. Remove callers of
  // IsWebSafeScheme(), and then eliminate the next two lines.
  RegisterWebSafeScheme(url::kBlobScheme);
  RegisterWebSafeScheme(url::kFileSystemScheme);

  // We know about the following pseudo schemes and treat them specially.
  RegisterPseudoScheme(url::kAboutScheme);
  RegisterPseudoScheme(url::kJavaScriptScheme);
  RegisterPseudoScheme(kViewSourceScheme);
  RegisterPseudoScheme(kGoogleChromeScheme);
}

ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
}

// static
ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
  return ChildProcessSecurityPolicyImpl::GetInstance();
}

ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
  return base::Singleton<ChildProcessSecurityPolicyImpl>::get();
}

void ChildProcessSecurityPolicyImpl::Add(int child_id,
                                         BrowserContext* browser_context) {
  DCHECK(browser_context);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(child_id, ChildProcessHost::kInvalidUniqueID);
  base::AutoLock lock(lock_);
  if (security_state_.find(child_id) != security_state_.end()) {
    NOTREACHED() << "Add child process at most once.";
    return;
  }

  security_state_[child_id] = std::make_unique<SecurityState>(browser_context);
  CHECK(AddProcessReferenceLocked(child_id, /* duplicating_handle */ false));
}

void ChildProcessSecurityPolicyImpl::AddForTesting(
    int child_id,
    BrowserContext* browser_context) {
  Add(child_id, browser_context);
  LockProcess(
      IsolationContext(BrowsingInstanceId(1), browser_context,
                       /*is_guest=*/false, /*is_fenced=*/false,
                       OriginAgentClusterIsolationState::CreateNonIsolated()),
      child_id, /*is_process_used=*/false,
      ProcessLock::CreateAllowAnySite(
          StoragePartitionConfig::CreateDefault(browser_context),
          WebExposedIsolationInfo::CreateNonIsolated()));
}

void ChildProcessSecurityPolicyImpl::Remove(int child_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(child_id, ChildProcessHost::kInvalidUniqueID);
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  // Moving the existing SecurityState object into a pending map so
  // that we can preserve permission state and avoid mutations to this
  // state after Remove() has been called.
  pending_remove_state_[child_id] = std::move(state->second);
  security_state_.erase(child_id);

  RemoveProcessReferenceLocked(child_id);
}

void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);
  DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
      << "Add schemes at most once.";
  DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
      << "Web-safe implies not pseudo.";

  schemes_okay_to_request_in_any_process_.insert(scheme);
  schemes_okay_to_commit_in_any_process_.insert(scheme);
}

void ChildProcessSecurityPolicyImpl::RegisterWebSafeIsolatedScheme(
    const std::string& scheme,
    bool always_allow_in_origin_headers) {
  base::AutoLock lock(lock_);
  DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
      << "Add schemes at most once.";
  DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
      << "Web-safe implies not pseudo.";

  schemes_okay_to_request_in_any_process_.insert(scheme);
  if (always_allow_in_origin_headers)
    schemes_okay_to_appear_as_origin_headers_.insert(scheme);
}

bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);

  return base::Contains(schemes_okay_to_request_in_any_process_, scheme);
}

void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);
  DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once.";
  DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
      << "Pseudo implies not web-safe.";
  DCHECK_EQ(0U, schemes_okay_to_commit_in_any_process_.count(scheme))
      << "Pseudo implies not web-safe.";

  pseudo_schemes_.insert(scheme);
}

bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);

  return base::Contains(pseudo_schemes_, scheme);
}

void ChildProcessSecurityPolicyImpl::ClearRegisteredSchemeForTesting(
    const std::string& scheme) {
  base::AutoLock lock(lock_);
  schemes_okay_to_request_in_any_process_.erase(scheme);
  schemes_okay_to_commit_in_any_process_.erase(scheme);
  pseudo_schemes_.erase(scheme);
}

void ChildProcessSecurityPolicyImpl::GrantCommitURL(int child_id,
                                                    const GURL& url) {
  // Can't grant the capability to commit invalid URLs.
  if (!url.is_valid())
    return;

  // Can't grant the capability to commit pseudo schemes.
  if (IsPseudoScheme(url.scheme()))
    return;

  url::Origin origin = url::Origin::Create(url);

  // Blob and filesystem URLs require special treatment; grant access to the
  // inner origin they embed instead.
  // TODO(dcheng): Can this logic be simplified to just derive an origin up
  // front and use that? That probably requires fixing GURL canonicalization of
  // blob URLs though. For now, be consistent with how CanRequestURL and
  // CanCommitURL normalize.
  if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
    if (IsMalformedBlobUrl(url))
      return;

    GrantCommitURL(child_id, GURL(origin.Serialize()));
  }

  // TODO(dcheng): In the future, URLs with opaque origins would ideally carry
  // around an origin with them, so we wouldn't need to grant commit access to
  // the entire scheme.
  if (!origin.opaque())
    GrantCommitOrigin(child_id, origin);

  // The scheme has already been whitelisted for every child process, so no need
  // to do anything else.
  if (IsWebSafeScheme(url.scheme()))
    return;

  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  if (origin.opaque()) {
    // If it's impossible to grant commit rights to just the origin (among other
    // things, URLs with non-standard schemes will be treated as opaque
    // origins), then grant access to commit all URLs of that scheme.
    state->second->GrantCommitScheme(url.scheme());
  } else {
    // When the child process has been commanded to request this scheme, grant
    // it the capability to request all URLs of that scheme.
    state->second->GrantRequestScheme(url.scheme());
  }
}

void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
    int child_id,
    const GURL& url) {
  if (!url.SchemeIs(url::kFileScheme))
    return;

  {
    base::AutoLock lock(lock_);
    auto state = security_state_.find(child_id);
    if (state == security_state_.end())
      return;

    // When the child process has been commanded to request a file:// URL,
    // then we grant it the capability for that URL only.
    base::FilePath path;
    if (net::FileURLToFilePath(url, &path))
      state->second->GrantRequestOfSpecificFile(path);
  }
}

void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
                                                   const base::FilePath& file) {
  GrantPermissionsForFile(child_id, file, READ_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFile(
    int child_id, const base::FilePath& file) {
  GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id,
                                                   const base::FilePath& dir) {
  GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
    int child_id, const base::FilePath& dir) {
  GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
    int child_id, const base::FilePath& file, int permissions) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantPermissionsForFile(file, permissions);
}

void ChildProcessSecurityPolicyImpl::RevokeAllPermissionsForFile(
    int child_id, const base::FilePath& file) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->RevokeAllPermissionsForFile(file);
}

void ChildProcessSecurityPolicyImpl::GrantReadFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantWriteFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id, WRITE_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantCreateFileForFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id, CREATE_NEW_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantCreateReadWriteFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(
      child_id, filesystem_id, CREATE_READ_WRITE_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantCopyIntoFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id, COPY_INTO_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantDeleteFromFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id, DELETE_FILE_GRANT);
}

void ChildProcessSecurityPolicyImpl::GrantSendMidiSysExMessage(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantPermissionForMidiSysEx();
}

void ChildProcessSecurityPolicyImpl::GrantCommitOrigin(
    int child_id,
    const url::Origin& origin) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantCommitOrigin(origin);
}

void ChildProcessSecurityPolicyImpl::GrantRequestOrigin(
    int child_id,
    const url::Origin& origin) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantRequestOrigin(origin);
}

void ChildProcessSecurityPolicyImpl::GrantRequestScheme(
    int child_id,
    const std::string& scheme) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantRequestScheme(scheme);
}

void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id,
                                                        int bindings) {
  // Only WebUI bindings should come through here.
  CHECK(bindings & kWebUIBindingsPolicyMask);
  CHECK_EQ(0, bindings & ~kWebUIBindingsPolicyMask);

  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantBindings(bindings);
}

void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantReadRawCookies();
}

void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->RevokeReadRawCookies();
}

bool ChildProcessSecurityPolicyImpl::CanRequestURL(
    int child_id, const GURL& url) {
  if (!url.is_valid())
    return false;  // Can't request invalid URLs.

  const std::string& scheme = url.scheme();

  // Every child process can request <about:blank>, <about:blank?foo>,
  // <about:blank/#foo> and <about:srcdoc>.
  //
  // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be
  // requestable by any child process.  Also, this case covers
  // <javascript:...>, which should be handled internally by the process and
  // not kicked up to the browser.
  // TODO(dcheng): Figure out why this check is different from CanCommitURL,
  // which checks for direct equality with kAboutBlankURL.
  if (IsPseudoScheme(scheme))
    return url.IsAboutBlank() || url.IsAboutSrcdoc();

  // Blob and filesystem URLs require special treatment; validate the inner
  // origin they embed.
  if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
    if (IsMalformedBlobUrl(url))
      return false;

    url::Origin origin = url::Origin::Create(url);
    return origin.opaque() || CanRequestURL(child_id, GURL(origin.Serialize()));
  }

  if (IsWebSafeScheme(scheme))
    return true;

  {
    base::AutoLock lock(lock_);

    auto state = security_state_.find(child_id);
    if (state == security_state_.end())
      return false;

    // Otherwise, we consult the child process's security state to see if it is
    // allowed to request the URL.
    if (state->second->CanRequestURL(url))
      return true;
  }

  // If |url| has WebUI scheme, the process must usually be locked, unless
  // running in single-process mode. Since this is a check whether the process
  // can request |url|, the check must operate based on scheme because one WebUI
  // should be able to request subresources from another WebUI of the same
  // scheme.
  const auto& webui_schemes = URLDataManagerBackend::GetWebUISchemes();
  if (!RenderProcessHost::run_renderer_in_process() &&
      base::Contains(webui_schemes, url.scheme())) {
    bool should_be_locked =
        GetContentClient()->browser()->DoesWebUIUrlRequireProcessLock(url);
    if (should_be_locked) {
      const ProcessLock lock = GetProcessLock(child_id);
      if (!lock.is_locked_to_site() || !lock.matches_scheme(url.scheme()))
        return false;
    }
  }

  // Also allow URLs destined for ShellExecute and not the browser itself.
  return !GetContentClient()->browser()->IsHandledURL(url);
}

bool ChildProcessSecurityPolicyImpl::CanRedirectToURL(const GURL& url) {
  if (!url.is_valid())
    return false;  // Can't redirect to invalid URLs.

  const std::string& scheme = url.scheme();

  // Can't redirect to error pages.
  if (scheme == kChromeErrorScheme)
    return false;

  if (IsPseudoScheme(scheme)) {
    // Redirects to a pseudo scheme (about, javascript, view-source, ...) are
    // not allowed. An exception is made for <about:blank> and its variations.
    return url.IsAboutBlank();
  }

  // Note about redirects and special URLs:
  // * data-url: Blocked by net::DataProtocolHandler::IsSafeRedirectTarget().
  // * filesystem-url: Blocked by
  // storage::FilesystemProtocolHandler::IsSafeRedirectTarget().
  // Depending on their inner origins and if the request is browser-initiated or
  // renderer-initiated, blob-urls might get blocked by CanCommitURL or in
  // DocumentLoader::RedirectReceived. If not blocked, a 'file not found'
  // response will be generated in net::BlobURLRequestJob::DidStart().

  return true;
}

bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
                                                  const GURL& url) {
  if (!url.is_valid())
    return false;  // Can't commit invalid URLs.

  const std::string& scheme = url.scheme();

  // Of all the pseudo schemes, only about:blank and about:srcdoc are allowed to
  // commit.
  if (IsPseudoScheme(scheme))
    return url.IsAboutBlank() || url.IsAboutSrcdoc();

  // Blob and filesystem URLs require special treatment; validate the inner
  // origin they embed.
  if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
    if (IsMalformedBlobUrl(url))
      return false;

    url::Origin origin = url::Origin::Create(url);
    return origin.opaque() || CanCommitURL(child_id, GURL(origin.Serialize()));
  }

  // With site isolation, a URL from a site may only be committed in a process
  // dedicated to that site.  This check will ensure that |url| can't commit if
  // the process is locked to a different site.
  if (!CanAccessDataForMaybeOpaqueOrigin(
          child_id, url, false /* url_is_precursor_of_opaque_origin */))
    return false;

  {
    base::AutoLock lock(lock_);

    // Most schemes can commit in any process. Note that we check
    // schemes_okay_to_commit_in_any_process_ here, which is stricter than
    // IsWebSafeScheme().
    //
    // TODO(creis, nick): https://crbug.com/515309: The line below does not
    // enforce that http pages cannot commit in an extension process.
    if (base::Contains(schemes_okay_to_commit_in_any_process_, scheme))
      return true;

    auto* state = GetSecurityState(child_id);
    if (!state)
      return false;

    // Otherwise, we consult the child process's security state to see if it is
    // allowed to commit the URL.
    return state->CanCommitURL(url);
  }
}

bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
                                                 const base::FilePath& file) {
  return HasPermissionsForFile(child_id, file, READ_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanReadAllFiles(
    int child_id,
    const std::vector<base::FilePath>& files) {
  return base::ranges::all_of(files,
                              [this, child_id](const base::FilePath& file) {
                                return CanReadFile(child_id, file);
                              });
}

bool ChildProcessSecurityPolicyImpl::CanReadRequestBody(
    int child_id,
    const storage::FileSystemContext* file_system_context,
    const scoped_refptr<network::ResourceRequestBody>& body) {
  if (!body)
    return true;

  for (const network::DataElement& element : *body->elements()) {
    switch (element.type()) {
      case network::DataElement::Tag::kFile:
        if (!CanReadFile(child_id,
                         element.As<network::DataElementFile>().path()))
          return false;
        break;

      case network::DataElement::Tag::kBytes:
        // Data is self-contained within |body| - no need to check access.
        break;

      case network::DataElement::Tag::kDataPipe:
        // Data is self-contained within |body| - no need to check access.
        break;

      default:
        // Fail safe - deny access.
        NOTREACHED();
        return false;
    }
  }
  return true;
}

bool ChildProcessSecurityPolicyImpl::CanReadRequestBody(
    RenderProcessHost* process,
    const scoped_refptr<network::ResourceRequestBody>& body) {
  CHECK(process);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  return CanReadRequestBody(
      process->GetID(), process->GetStoragePartition()->GetFileSystemContext(),
      body);
}

bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFile(
    int child_id,
    const base::FilePath& file) {
  return HasPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id, filesystem_id, READ_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id, filesystem_id,
                                     READ_FILE_GRANT | WRITE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id, filesystem_id,
                                     COPY_INTO_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanDeleteFromFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id, filesystem_id,
                                     DELETE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
    int child_id, const base::FilePath& file, int permissions) {
  base::AutoLock lock(lock_);
  return ChildProcessHasPermissionsForFile(child_id, file, permissions);
}

bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url,
    int permissions) {
  if (!filesystem_url.is_valid())
    return false;

  if (filesystem_url.path().ReferencesParent())
    return false;

  // Any write access is disallowed on the root path.
  if (storage::VirtualPath::IsRootPath(filesystem_url.path()) &&
      (permissions & ~READ_FILE_GRANT)) {
    return false;
  }

  if (filesystem_url.mount_type() == storage::kFileSystemTypeIsolated) {
    // When Isolated filesystems is overlayed on top of another filesystem,
    // its per-filesystem permission overrides the underlying filesystem
    // permissions).
    return HasPermissionsForFileSystem(
        child_id, filesystem_url.mount_filesystem_id(), permissions);
  }

  // If |filesystem_url.origin()| is not committable in this process, then this
  // page should not be able to place content in that origin via the filesystem
  // API either.
  // TODO(lukasza): Audit whether CanAccessDataForOrigin can be used directly
  // here.
  if (!CanCommitURL(child_id, filesystem_url.origin().GetURL()))
    return false;

  int found_permissions = 0;
  {
    base::AutoLock lock(lock_);
    auto found = file_system_policy_map_.find(filesystem_url.type());
    if (found == file_system_policy_map_.end())
      return false;
    found_permissions = found->second;
  }

  if ((found_permissions & storage::FILE_PERMISSION_READ_ONLY) &&
      permissions & ~READ_FILE_GRANT) {
    return false;
  }

  // Note that HasPermissionsForFile (called below) will internally acquire the
  // |lock_|, therefore the |lock_| has to be released before the call (since
  // base::Lock is not reentrant).
  if (found_permissions & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
    return HasPermissionsForFile(child_id, filesystem_url.path(), permissions);

  if (found_permissions & storage::FILE_PERMISSION_SANDBOX)
    return true;

  return false;
}

bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         READ_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         WRITE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         CREATE_NEW_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         CREATE_READ_WRITE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         COPY_INTO_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
    int child_id,
    const storage::FileSystemURL& filesystem_url) {
  return HasPermissionsForFileSystemFile(child_id, filesystem_url,
                                         DELETE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanMoveFileSystemFile(
    int child_id,
    const storage::FileSystemURL& src_url,
    const storage::FileSystemURL& dest_url) {
  return HasPermissionsForFileSystemFile(child_id, dest_url,
                                         CREATE_NEW_FILE_GRANT) &&
         HasPermissionsForFileSystemFile(child_id, src_url, READ_FILE_GRANT) &&
         HasPermissionsForFileSystemFile(child_id, src_url, DELETE_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::CanCopyFileSystemFile(
    int child_id,
    const storage::FileSystemURL& src_url,
    const storage::FileSystemURL& dest_url) {
  return HasPermissionsForFileSystemFile(child_id, src_url, READ_FILE_GRANT) &&
         HasPermissionsForFileSystemFile(child_id, dest_url,
                                         COPY_INTO_FILE_GRANT);
}

bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;

  return state->second->has_web_ui_bindings();
}

bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;

  return state->second->can_read_raw_cookies();
}

bool ChildProcessSecurityPolicyImpl::ChildProcessHasPermissionsForFile(
    int child_id, const base::FilePath& file, int permissions) {
  auto* state = GetSecurityState(child_id);
  if (!state)
    return false;
  return state->HasPermissionsForFile(file, permissions);
}

size_t ChildProcessSecurityPolicyImpl::BrowsingInstanceIdCountForTesting(
    int child_id) {
  base::AutoLock lock(lock_);
  SecurityState* security_state = GetSecurityState(child_id);
  if (security_state)
    return security_state->browsing_instance_info().size();
  return 0;
}

CanCommitStatus ChildProcessSecurityPolicyImpl::CanCommitOriginAndUrl(
    int child_id,
    const IsolationContext& isolation_context,
    const UrlInfo& url_info) {
  DCHECK(url_info.origin.has_value());
  const url::Origin url_origin =
      url::Origin::Resolve(url_info.url, *url_info.origin);
  if (!CanAccessDataForOrigin(child_id, url_origin)) {
    // Check for special cases, like blob:null/ and data: URLs, where the
    // origin does not contain information to match against the process lock,
    // but using the whole URL can result in a process lock match.  Note that
    // the origin being committed in `url_info.origin` will not actually be
    // used when computing `expected_process_lock` below in many cases; see
    // https://crbug.com/1320402.
    const auto expected_process_lock =
        ProcessLock::Create(isolation_context, url_info);
    const ProcessLock& actual_process_lock = GetProcessLock(child_id);
    if (actual_process_lock == expected_process_lock)
      return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;

    return CanCommitStatus::CANNOT_COMMIT_URL;
  }

  if (!CanAccessDataForOrigin(child_id, *url_info.origin))
    return CanCommitStatus::CANNOT_COMMIT_ORIGIN;

  // Ensure that the origin derived from |url| is consistent with |origin|.
  // Note: We can't use origin.IsSameOriginWith() here because opaque origins
  // with precursors may have different nonce values.
  const auto url_tuple_or_precursor_tuple =
      url_origin.GetTupleOrPrecursorTupleIfOpaque();
  const auto origin_tuple_or_precursor_tuple =
      url_info.origin->GetTupleOrPrecursorTupleIfOpaque();

  if (url_tuple_or_precursor_tuple.IsValid() &&
      origin_tuple_or_precursor_tuple.IsValid() &&
      origin_tuple_or_precursor_tuple != url_tuple_or_precursor_tuple) {
    // Allow a WebView specific exception for origins that have a data scheme.
    // WebView converts data: URLs into non-opaque data:// origins which is
    // different than what all other builds do. This causes the consistency
    // check to fail because we try to compare a data:// origin with an opaque
    // origin that contains precursor info.
    if (url_tuple_or_precursor_tuple.scheme() == url::kDataScheme &&
        url::AllowNonStandardSchemesForAndroidWebView()) {
      return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
    }

    return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
  }

  return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
}

bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(
    int child_id,
    const url::Origin& origin) {
  if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
    // Ensure this is only called on the UI thread, which is the only thread
    // with sufficient information to do the full set of checks.
    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  } else {
    // For legacy cases, this may be called on multiple threads.
    DCHECK(IsRunningOnExpectedThread());
  }

  GURL url_to_check;
  if (origin.opaque()) {
    auto precursor_tuple = origin.GetTupleOrPrecursorTupleIfOpaque();
    if (!precursor_tuple.IsValid()) {
      // Allow opaque origins w/o precursors (if the security state exists).
      // TODO(acolwell): Investigate all cases that trigger this path (e.g.,
      // browser-initiated navigations to data: URLs) and fix them so we have
      // precursor information (or the process lock is compatible with a missing
      // precursor). Remove this logic once that has been completed.
      base::AutoLock lock(lock_);
      SecurityState* security_state = GetSecurityState(child_id);
      return !!security_state;
    } else {
      url_to_check = precursor_tuple.GetURL();
    }
  } else {
    url_to_check = origin.GetURL();
  }
  bool success = CanAccessDataForMaybeOpaqueOrigin(child_id, url_to_check,
                                                   origin.opaque());
  if (success)
    return true;

  // Note: LogCanAccessDataForOriginCrashKeys() is called in the
  // CanAccessDataForOrigin() call above. The code below overrides the origin
  // crash key set in that call with data from |origin| because it provides
  // more accurate information than the origin derived from |url_to_check|.
  auto* requested_origin_key = GetRequestedOriginCrashKey();
  base::debug::SetCrashKeyString(requested_origin_key, origin.GetDebugString());
  return false;
}

bool ChildProcessSecurityPolicyImpl::CanAccessDataForMaybeOpaqueOrigin(
    int child_id,
    const GURL& url,
    bool url_is_precursor_of_opaque_origin) {
  if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
    // Ensure this is only called on the UI thread, which is the only thread
    // with sufficient information to do the full set of checks.
    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  } else {
    // For legacy cases, this may be called on multiple threads.
    DCHECK(IsRunningOnExpectedThread());
  }

  base::AutoLock lock(lock_);

  SecurityState* security_state = GetSecurityState(child_id);
  BrowserOrResourceContext browser_or_resource_context;
  if (security_state)
    browser_or_resource_context = security_state->GetBrowserOrResourceContext();

  ProcessLock expected_process_lock;
  std::string failure_reason;

  if (!security_state) {
    failure_reason = "no_security_state";
  } else if (!browser_or_resource_context) {
    failure_reason = "no_browser_or_resource_context";
  } else {
    ProcessLock actual_process_lock = security_state->process_lock();

    // Deny access if the process is unlocked. An unlocked process means that
    // the process has not been associated with a SiteInstance yet and therefore
    // this request is likely invalid.
    if (actual_process_lock.is_invalid()) {
      failure_reason = "process_lock_is_invalid";
    } else {
      // Loop over all BrowsingInstanceIDs in the SecurityState, and return true
      // if any of them would return true, otherwise return false. This allows
      // the checks to be slightly stricter in cases where all BrowsingInstances
      // agree (e.g., whether an origin is considered isolated and thus
      // inaccessible from a site-locked process).  When the BrowsingInstances
      // do not agree, the check might be slightly weaker (as the least common
      // denominator), but the differences must never violate the ProcessLock.
      if (security_state->browsing_instance_info().empty()) {
        // If no BrowsingInstances are found, then the some of the state we need
        // to perform an accurate check is unexpectedly missing, because there
        // should always be a BrowsingInstance for such requests, even from
        // workers. Thus, we should usually kill the process in this case, so
        // that a compromised renderer can't bypass checks by sending IPCs when
        // no BrowsingInstances are left.
        //
        // However, if the requested `url` is compatible with the current
        // ProcessLock, then there is no need to kill the process because the
        // checks would have passed anyway. To reduce the number of crashes
        // while we debug why no BrowsingInstances were found (in
        // https://crbug.com/1148542), we'll allow requests with an acceptable
        // process lock to proceed.
        // TODO(1148542): Remove this when known cases of having no
        // BrowsingInstance IDs are solved.
        url::Origin origin(url::Origin::Create(url));
        bool matches_origin_keyed_process =
            actual_process_lock.is_origin_keyed_process() &&
            actual_process_lock.lock_url() == origin.GetURL();
        bool matches_site_keyed_process =
            !actual_process_lock.is_origin_keyed_process() &&
            actual_process_lock.lock_url() ==
                SiteInfo::GetSiteForOrigin(origin);
        // ProcessLocks with is_pdf() = true actually means that the process is
        // not supposed to access certain resources from the lock's site/origin,
        // so it's safest here to fall through in that case. See discussion of
        // https://crbug.com/1271197 below.
        if (!actual_process_lock.is_pdf()) {
          // If the ProcessLock isn't locked to a site, we should fall through
          // since we have no way of knowing if the requested url was expecting
          // to be in a locked process.
          if (actual_process_lock.is_locked_to_site()) {
            if (matches_origin_keyed_process || matches_site_keyed_process) {
              return true;
            } else {
              failure_reason = base::StringPrintf(
                  "No BrowsingInstanceIDs: Lock Mismatch. lock = %s vs. "
                  "requested_url = %s ",
                  actual_process_lock.ToString().c_str(), url.spec().c_str());
            }
          } else {
            failure_reason =
                "No BrowsingInstanceIDs: process not locked to site";
          }
        } else {
          failure_reason = "No BrowsingInstanceIDs: process lock is_pdf";
        }
        // This will fall through to the call to
        // LogCanAccessDataForOriginCrashKeys below, then return false.
      }
      for (auto browsing_instance_info_entry :
           security_state->browsing_instance_info()) {
        auto& browsing_instance_id = browsing_instance_info_entry.first;
        auto& default_isolation_state = browsing_instance_info_entry.second;
        // In the case of multiple BrowsingInstances in the SecurityState, note
        // that failure reasons will only be reported if none of the
        // BrowsingInstances allow access. In that event, |failure_reason|
        // contains the concatenated reasons for each BrowsingInstance, each
        // prefaced by its id.
        failure_reason += base::StringPrintf(
            "[BI=%d]", browsing_instance_id.GetUnsafeValue());

        // Use the actual process lock's state to compute `is_guest` and
        // `is_fenced` for the expected process lock's `isolation_context`.
        // Guest status and fenced status doesn't currently influence the
        // outcome of this access check, and even if it did, `url` wouldn't be
        // sufficient to tell whether the request belongs solely to a guest (or
        // non-guest) or fenced process.  Note that a guest isn't allowed to
        // access data outside of its own StoragePartition, but this is enforced
        // by other means (e.g., resource access APIs can't name an alternate
        // StoragePartition).
        IsolationContext isolation_context(
            browsing_instance_id, browser_or_resource_context,
            actual_process_lock.is_guest(), actual_process_lock.is_fenced(),
            default_isolation_state);

        // NOTE: If we're on the IO thread, the call to
        // ProcessLock::Create() below will return a ProcessLock with
        // an (internally) identical site_url, one that does not use effective
        // URLs. That's ok in this instance since we only ever look at the lock
        // url.
        //
        // Since we are dealing with a valid ProcessLock at this point, we know
        // the lock contains a valid StoragePartitionConfig and COOP/COEP
        // information because that information must be provided when creating
        // the locks.
        //
        // At this point, any origin opt-in isolation requests should be
        // complete, so to avoid the possibility of opting something set
        // |origin_isolation_request| to kNone below (this happens by default in
        // UrlInfoInit's ctor).  Note: We might need to revisit this if
        // CanAccessDataForOrigin() needs to be called while a SiteInstance is
        // being determined for a navigation, i.e. during
        // GetSiteInstanceForNavigationRequest().  If this happens, we'd need
        // to plumb UrlInfo::origin_isolation_request value from the ongoing
        // NavigationRequest into here. Also, we would likely need to attach
        // the BrowsingInstanceID to UrlInfo once the SiteInstance has been
        // determined in case the RenderProcess has multiple BrowsingInstances
        // in it.
        // TODO(acolwell): Provide a way for callers, that know their request's
        // require COOP/COEP handling, to pass in their COOP/COEP information
        // so it can be used here instead of the values in
        // |actual_process_lock|.
        // TODO(crbug.com/1271197): The code below is subtly incorrect in cases
        // where actual_process_lock.is_pdf() is true, since in the case of PDFs
        // the lock is intended to prevent access to the lock's site/origin,
        // while still allowing the navigation to commit.
        expected_process_lock = ProcessLock::Create(
            isolation_context,
            UrlInfo(UrlInfoInit(url)
                        .WithStoragePartitionConfig(
                            actual_process_lock.GetStoragePartitionConfig())
                        .WithWebExposedIsolationInfo(
                            actual_process_lock.GetWebExposedIsolationInfo())
                        .WithIsPdf(actual_process_lock.is_pdf())
                        .WithSandbox(actual_process_lock.is_sandboxed())
                        .WithUniqueSandboxId(
                            actual_process_lock.unique_sandbox_id())));

        if (actual_process_lock.is_locked_to_site()) {
          // Jail-style enforcement - a process with a lock can only access
          // data from origins that require exactly the same lock.
          if (actual_process_lock == expected_process_lock)
            return true;

          // TODO(acolwell, nasko): https://crbug.com/1029092: Ensure the
          // precursor of opaque origins matches the renderer's origin lock.
          if (url_is_precursor_of_opaque_origin) {
            const GURL& lock_url = actual_process_lock.lock_url();
            // SitePerProcessBrowserTest
            // .TwoBlobURLsWithNullOriginDontShareProcess.
            if (lock_url.SchemeIsBlob() &&
                base::StartsWith(lock_url.path_piece(), "null/")) {
              return true;
            }

            // DeclarativeApiTest.PersistRules.
            if (actual_process_lock.matches_scheme(url::kDataScheme))
              return true;
          }

          // Make an exception to allow most visited tiles to commit in
          // third-party NTP processes.
          // TODO(crbug.com/566091): This exception should be removed once
          // these tiles can be loaded in OOPIFs on the NTP.
          if (AllowProcessLockMismatchForNTP(expected_process_lock,
                                             actual_process_lock)) {
            return true;
          }

          // TODO(wjmaclean): We should update the ProcessLock comparison API
          // to return a reason why two locks differ.
          if (actual_process_lock.lock_url() !=
              expected_process_lock.lock_url()) {
            failure_reason += "lock_mismatch:url ";
            // If the actual lock is same-site to the expected lock, then this
            // is an isolated origins mismatch; in that case we add text to
            // |failure_reason| to make this case easy to search for.
            // Note: We don't compare ports, since the mismatch might be between
            // isolated and non-isolated.
            url::Origin actual_origin =
                url::Origin::Create(actual_process_lock.lock_url());
            url::Origin expected_origin =
                url::Origin::Create(expected_process_lock.lock_url());
            if (actual_process_lock.lock_url() ==
                    SiteInfo::GetSiteForOrigin(expected_origin) ||
                expected_process_lock.lock_url() ==
                    SiteInfo::GetSiteForOrigin(actual_origin)) {
              failure_reason += "[origin vs site mismatch] ";
            }
          } else {
            // TODO(wjmaclean,alexmos): Apparently this might not be true
            // anymore, since is_pdf() and web_exposed_isolation_info() have
            // been added to the ProcessLock. We need to update the code here to
            // differentiate these cases, as well as adding documentation (or
            // some other mechanism) to prevent these getting out of sync in
            // future.
            failure_reason += "lock_mismatch:requires_origin_keyed_process ";
          }
        } else {
          // Citadel-style enforcement - an unlocked process should not be
          // able to access data from origins that require a lock.

          // Allow the corresponding base::Feature to turn off enforcement.
          if (!base::FeatureList::IsEnabled(kSiteIsolationCitadelEnforcement)) {
            return true;
          }

          // Skip these checks on the IO thread, since we can't use
          // RenderProcessHost or ShouldLockProcessToSite() there.
          //
          // TODO(crbug.com/764958): Remove this once this is reachable only on
          // the UI thread.
          if (!ShouldRestrictCanAccessDataForOriginToUIThread() &&
              BrowserThread::CurrentlyOn(BrowserThread::IO)) {
            return true;
          }

          DCHECK_CURRENTLY_ON(BrowserThread::UI);

          // TODO(lukasza): Consider making the checks below IO-thread-friendly,
          // by storing |is_unused| inside SecurityState.
          RenderProcessHost* process = RenderProcessHostImpl::FromID(child_id);
          if (process) {  // |process| can be null in unittests
            // Unlocked process can be legitimately used when navigating from an
            // unused process (about:blank, NTP on Android) to an isolated
            // origin. See also https://crbug.com/945399.  Returning |true|
            // below will allow such navigations to succeed (i.e. pass
            // CanCommitOriginAndUrl checks). We don't expect unused processes
            // to be used outside of navigations (e.g. when checking
            // CanAccessDataForOrigin for localStorage, etc.).
            if (process->IsUnused())
              return true;
          }

          // See the ProcessLock::Create() call above regarding why we pass
          // kNone for |origin_isolation_request| below.
          SiteInfo site_info = SiteInfo::Create(
              isolation_context,
              UrlInfo(UrlInfoInit(url).WithWebExposedIsolationInfo(
                  actual_process_lock.GetWebExposedIsolationInfo())));

          // A process that's not locked to any site can only access data from
          // origins that do not require a locked process.
          if (!site_info.ShouldLockProcessToSite(isolation_context))
            return true;

          failure_reason += " citadel_enforcement ";
          if (url_is_precursor_of_opaque_origin) {
            failure_reason += "for_precursor ";
          }
        }
      }
    }
  }

  // Record the duration of KeepAlive requests to include in the crash keys.
  std::string keep_alive_durations;
  std::string shutdown_delay_ref_count;
  std::string process_rfh_count;
  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    if (auto* process = RenderProcessHostImpl::FromID(child_id)) {
      keep_alive_durations = process->GetKeepAliveDurations();
      shutdown_delay_ref_count =
          base::NumberToString(process->GetShutdownDelayRefCount());
      process_rfh_count =
          base::NumberToString(process->GetRenderFrameHostCount());
    }
  } else {
    keep_alive_durations = "no durations available: on IO thread.";
  }

  // Returning false here will result in a renderer kill.  Set some crash
  // keys that will help understand the circumstances of that kill.
  LogCanAccessDataForOriginCrashKeys(
      expected_process_lock.ToString(),
      GetKilledProcessOriginLock(security_state),
      url.DeprecatedGetOriginAsURL().spec(), failure_reason,
      keep_alive_durations, shutdown_delay_ref_count, process_rfh_count);
  return false;
}

void ChildProcessSecurityPolicyImpl::IncludeIsolationContext(
    int child_id,
    const IsolationContext& isolation_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::AutoLock lock(lock_);
  auto* state = GetSecurityState(child_id);
  DCHECK(state);
  state->AddBrowsingInstanceInfo(isolation_context);
}

void ChildProcessSecurityPolicyImpl::LockProcess(
    const IsolationContext& context,
    int child_id,
    bool is_process_used,
    const ProcessLock& process_lock) {
  // LockProcess should only be called on the UI thread (OTOH, it is okay to
  // call GetProcessLock from any thread).
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::AutoLock lock(lock_);
  auto state = security_state_.find(child_id);
  DCHECK(state != security_state_.end());
  state->second->SetProcessLock(process_lock, context, is_process_used);
}

void ChildProcessSecurityPolicyImpl::LockProcessForTesting(
    const IsolationContext& isolation_context,
    int child_id,
    const GURL& url) {
  SiteInfo site_info = SiteInfo::CreateForTesting(isolation_context, url);
  LockProcess(isolation_context, child_id, /* is_process_used=*/false,
              ProcessLock::FromSiteInfo(site_info));
}

ProcessLock ChildProcessSecurityPolicyImpl::GetProcessLock(int child_id) {
  base::AutoLock lock(lock_);
  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return ProcessLock();
  return state->second->process_lock();
}

void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
    int child_id,
    const std::string& filesystem_id,
    int permission) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;
  state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
}

bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
    int child_id,
    const std::string& filesystem_id,
    int permission) {
  base::AutoLock lock(lock_);

  auto* state = GetSecurityState(child_id);
  if (!state)
    return false;
  return state->HasPermissionsForFileSystem(filesystem_id, permission);
}

void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
    storage::FileSystemType type,
    int policy) {
  base::AutoLock lock(lock_);
  file_system_policy_map_[type] = policy;
}

bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
  base::AutoLock lock(lock_);

  auto state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;

  return state->second->can_send_midi_sysex();
}

void ChildProcessSecurityPolicyImpl::AddFutureIsolatedOrigins(
    const std::vector<url::Origin>& origins_to_add,
    IsolatedOriginSource source,
    BrowserContext* browser_context) {
  std::vector<IsolatedOriginPattern> patterns;
  patterns.reserve(origins_to_add.size());
  base::ranges::transform(
      origins_to_add, std::back_inserter(patterns),
      [](const url::Origin& o) { return IsolatedOriginPattern(o); });
  AddFutureIsolatedOrigins(patterns, source, browser_context);
}

void ChildProcessSecurityPolicyImpl::AddFutureIsolatedOrigins(
    base::StringPiece origins_to_add,
    IsolatedOriginSource source,
    BrowserContext* browser_context) {
  std::vector<IsolatedOriginPattern> patterns =
      ParseIsolatedOrigins(origins_to_add);
  AddFutureIsolatedOrigins(patterns, source, browser_context);
}

void ChildProcessSecurityPolicyImpl::AddFutureIsolatedOrigins(
    const std::vector<IsolatedOriginPattern>& patterns,
    IsolatedOriginSource source,
    BrowserContext* browser_context) {
  // This can only be called from the UI thread, as it reads state that's only
  // available (and is only safe to be retrieved) on the UI thread, such as
  // BrowsingInstance IDs.
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::AutoLock isolated_origins_lock(isolated_origins_lock_);

  for (const IsolatedOriginPattern& pattern : patterns) {
    if (!pattern.is_valid()) {
      LOG(ERROR) << "Invalid isolated origin: " << pattern.pattern();
      continue;
    }

    url::Origin origin_to_add = pattern.origin();

    // Isolated origins added here should apply only to future
    // BrowsingInstances and processes.  Determine the first BrowsingInstance
    // ID to which they should apply.
    BrowsingInstanceId browsing_instance_id =
        SiteInstanceImpl::NextBrowsingInstanceId();

    AddIsolatedOriginInternal(browser_context, origin_to_add,
                              true /* applies_to_future_browsing_instances */,
                              browsing_instance_id,
                              pattern.isolate_all_subdomains(), source);
  }
}

void ChildProcessSecurityPolicyImpl::AddIsolatedOriginInternal(
    BrowserContext* browser_context,
    const url::Origin& origin_to_add,
    bool applies_to_future_browsing_instances,
    BrowsingInstanceId browsing_instance_id,
    bool isolate_all_subdomains,
    IsolatedOriginSource source) {
  // GetSiteForOrigin() is used to look up the site URL of |origin| to speed
  // up the isolated origin lookup.  This only performs a straightforward
  // translation of an origin to eTLD+1; it does *not* take into account
  // effective URLs, isolated origins, and other logic that's not needed
  // here, but *is* typically needed for making process model decisions. Be
  // very careful about using GetSiteForOrigin() elsewhere, and consider
  // whether you should be using SiteInfo::Create() instead.
  GURL key(SiteInfo::GetSiteForOrigin(origin_to_add));

  // Check if the origin to be added already exists, in which case it may not
  // need to be added again.
  bool should_add = true;
  for (const auto& entry : isolated_origins_[key]) {
    // TODO(alexmos): The exact origin comparison here allows redundant entries
    // with certain uses of `isolate_all_subdomains`.  See
    // https://crbug.com/1184580.
    if (entry.origin() != origin_to_add)
      continue;
    // If the added origin already exists for the same BrowserContext and
    // covers the same BrowsingInstances, don't re-add it.
    if (entry.browser_context() == browser_context) {
      if (entry.applies_to_future_browsing_instances() &&
          entry.browsing_instance_id() <= browsing_instance_id) {
        // If the existing entry applies to future BrowsingInstances, and it
        // has a lower/same BrowsingInstance ID, don't re-add the origin.  Note
        // that if the new isolated origin is also requested to apply to future
        // BrowsingInstances, the threshold ID must necessarily be greater than
        // the old ID, since NextBrowsingInstanceId() returns monotonically
        // increasing IDs.
        if (applies_to_future_browsing_instances)
          DCHECK_LE(entry.browsing_instance_id(), browsing_instance_id);
        should_add = false;
        break;
      } else if (!entry.applies_to_future_browsing_instances() &&
                 entry.browsing_instance_id() == browsing_instance_id) {
        // Otherwise, don't re-add the origin if the existing entry is for the
        // same BrowsingInstance ID.  Note that if an origin had been added for
        // a specific BrowsingInstance, we can't later receive a request to
        // isolate that origin within future BrowsingInstances that start at
        // the same (or lower) BrowsingInstance. Requests to isolate future
        // BrowsingInstances should always reference
        // SiteInstanceImpl::NextBrowsingInstanceId(), which always refers to
        // an ID that's greater than any existing BrowsingInstance ID.
        DCHECK(!applies_to_future_browsing_instances);

        should_add = false;
        break;
      }
    }

    // Otherwise, allow the origin to be added again for a different profile
    // (or globally for all profiles), possibly with a different
    // BrowsingInstance ID cutoff.  Note that a particular origin might have
    // multiple entries, each one for a different profile, so we must loop
    // over all such existing entries before concluding that |origin| really
    // needs to be added.
  }

  if (should_add) {
    ResourceContext* resource_context =
        browser_context ? browser_context->GetResourceContext() : nullptr;
    IsolatedOriginEntry entry(std::move(origin_to_add),
                              applies_to_future_browsing_instances,
                              browsing_instance_id, browser_context,
                              resource_context, isolate_all_subdomains, source);
    isolated_origins_[key].emplace_back(std::move(entry));
  }
}

void ChildProcessSecurityPolicyImpl::RemoveStateForBrowserContext(
    const BrowserContext& browser_context) {
  {
    base::AutoLock isolated_origins_lock(isolated_origins_lock_);

    for (auto& iter : isolated_origins_) {
      base::EraseIf(iter.second,
                    [&browser_context](const IsolatedOriginEntry& entry) {
                      // Remove if BrowserContext matches.
                      return (entry.browser_context() == &browser_context);
                    });
    }

    // Also remove map entries for site URLs which no longer have any
    // IsolatedOriginEntries remaining.
    base::EraseIf(isolated_origins_,
                  [](const auto& pair) { return pair.second.empty(); });
  }

  {
    base::AutoLock lock(lock_);
    for (auto& pair : security_state_)
      pair.second->ClearBrowserContextIfMatches(&browser_context);

    for (auto& pair : pending_remove_state_)
      pair.second->ClearBrowserContextIfMatches(&browser_context);
  }
}

bool ChildProcessSecurityPolicyImpl::IsIsolatedOrigin(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    bool origin_requests_isolation) {
  url::Origin unused_result;
  return GetMatchingProcessIsolatedOrigin(
      isolation_context, origin, origin_requests_isolation, &unused_result);
}

bool ChildProcessSecurityPolicyImpl::IsGloballyIsolatedOriginForTesting(
    const url::Origin& origin) {
  BrowserOrResourceContext no_browser_context;
  BrowsingInstanceId null_browsing_instance_id;
  IsolationContext isolation_context(
      null_browsing_instance_id, no_browser_context, /*is_guest=*/false,
      /*is_fenced=*/false,
      OriginAgentClusterIsolationState::CreateNonIsolated());
  return IsIsolatedOrigin(isolation_context, origin, false);
}

std::vector<url::Origin> ChildProcessSecurityPolicyImpl::GetIsolatedOrigins(
    absl::optional<IsolatedOriginSource> source,
    BrowserContext* browser_context) {
  std::vector<url::Origin> origins;
  base::AutoLock isolated_origins_lock(isolated_origins_lock_);
  for (const auto& iter : isolated_origins_) {
    for (const auto& isolated_origin_entry : iter.second) {
      if (source && source.value() != isolated_origin_entry.source())
        continue;

      // If browser_context is specified, ensure that the entry matches it.  If
      // the browser_context is not specified, only consider entries that are
      // not associated with a profile (i.e., which apply globally to the
      // entire browser).
      bool matches_profile =
          browser_context ? isolated_origin_entry.MatchesProfile(
                                BrowserOrResourceContext(browser_context))
                          : isolated_origin_entry.AppliesToAllBrowserContexts();
      if (!matches_profile)
        continue;

      // Do not include origins that only apply to specific BrowsingInstances.
      if (!isolated_origin_entry.applies_to_future_browsing_instances())
        continue;

      origins.push_back(isolated_origin_entry.origin());
    }
  }
  return origins;
}

bool ChildProcessSecurityPolicyImpl::IsIsolatedSiteFromSource(
    const url::Origin& origin,
    IsolatedOriginSource source) {
  base::AutoLock isolated_origins_lock(isolated_origins_lock_);
  GURL site_url = SiteInfo::GetSiteForOrigin(origin);
  auto it = isolated_origins_.find(site_url);
  if (it == isolated_origins_.end())
    return false;
  url::Origin site_origin = url::Origin::Create(site_url);
  for (const auto& entry : it->second) {
    if (entry.source() == source && entry.origin() == site_origin)
      return true;
  }
  return false;
}

bool ChildProcessSecurityPolicyImpl::GetMatchingProcessIsolatedOrigin(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    bool requests_origin_keyed_process,
    url::Origin* result) {
  // GetSiteForOrigin() is used to look up the site URL of |origin| to speed
  // up the isolated origin lookup.  This only performs a straightforward
  // translation of an origin to eTLD+1; it does *not* take into account
  // effective URLs, isolated origins, and other logic that's not needed
  // here, but *is* typically needed for making process model decisions. Be
  // very careful about using GetSiteForOrigin() elsewhere, and consider
  // whether you should be using GetSiteForURL() instead.
  return GetMatchingProcessIsolatedOrigin(
      isolation_context, origin, requests_origin_keyed_process,
      SiteInfo::GetSiteForOrigin(origin), result);
}

bool ChildProcessSecurityPolicyImpl::GetMatchingProcessIsolatedOrigin(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    bool requests_origin_keyed_process,
    const GURL& site_url,
    url::Origin* result) {
  DCHECK(IsRunningOnExpectedThread());

  *result = url::Origin();
  base::AutoLock isolated_origins_lock(isolated_origins_lock_);

  // If |isolation_context| does not specify a BrowsingInstance ID, then assume
  // that we want to retrieve the latest applicable information; i.e., return
  // the latest matching isolated origins that would apply to future
  // BrowsingInstances.  Using NextBrowsingInstanceId() will match all
  // available IsolatedOriginEntries.
  BrowsingInstanceId browsing_instance_id(
      isolation_context.browsing_instance_id());

  if (browsing_instance_id.is_null()) {
    browsing_instance_id = SiteInstanceImpl::NextBrowsingInstanceId();
  } else {
    // Check the opt-in isolation status of |origin| in |isolation_context|.
    // Note that while IsolatedOrigins considers any sub-origin of an isolated
    // origin as also being isolated, with opt-in we will always either return
    // false, or true with result set to |origin|. We give priority to origins
    // requesting opt-in isolation over command-line isolation, but don't check
    // for opt-in if we didn't get a valid BrowsingInstance id.
    // Note: This should only return a full origin if we are doing
    // process-isolated Origin-keyed Agent Clusters, which will only be the case
    // when site-isolation is enabled. Otherwise we put the origin into its
    // corresponding site, even if Origin-keyed Agent Clusters will be enabled
    // on the renderer side.
    // TODO(wjmaclean,alexmos,acolwell): We should revisit this when we have
    // SiteInstanceGroups, since at that point we can again return an origin
    // here (and thus create a new SiteInstance) even when
    // IsProcessIsolationForOriginAgentClusterEnabled() returns false; in that
    // case a SiteInstanceGroup will allow a logical group of SiteInstances that
    // live same-process.
    if (SiteIsolationPolicy::IsProcessIsolationForOriginAgentClusterEnabled()) {
      OriginAgentClusterIsolationState oac_isolation_state_request =
          requests_origin_keyed_process
              ? OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
                    true /* requires_origin_keyed_process */)
              : OriginAgentClusterIsolationState::CreateNonIsolated();
      OriginAgentClusterIsolationState oac_isolation_state_result =
          DetermineOriginAgentClusterIsolation(isolation_context, origin,
                                               oac_isolation_state_request);
      if (oac_isolation_state_result.requires_origin_keyed_process()) {
        *result = origin;
        return true;
      }
    }
  }

  // Look up the list of origins corresponding to |origin|'s site.
  auto it = isolated_origins_.find(site_url);

  // Subtle corner case: if the site's host ends with a dot, do the lookup
  // without it.  A trailing dot shouldn't be able to bypass isolated origins:
  // if "https://foo.com" is an isolated origin, "https://foo.com." should
  // match it.
  if (it == isolated_origins_.end() && site_url.has_host() &&
      site_url.host_piece().back() == '.') {
    GURL::Replacements replacements;
    base::StringPiece host(site_url.host_piece());
    host.remove_suffix(1);
    replacements.SetHostStr(host);
    it = isolated_origins_.find(site_url.ReplaceComponents(replacements));
  }

  // Looks for all isolated origins that were already isolated at the time
  // |isolation_context| was created. If multiple isolated origins are
  // registered with a common domain suffix, return the most specific one.  For
  // example, if foo.isolated.com and isolated.com are both isolated origins,
  // bar.foo.isolated.com should return foo.isolated.com.
  bool found = false;
  if (it != isolated_origins_.end()) {
    for (const auto& isolated_origin_entry : it->second) {
      // If this isolated origin applies only to a specific profile, don't
      // use it for a different profile.
      if (!isolated_origin_entry.MatchesProfile(
              isolation_context.browser_or_resource_context()))
        continue;

      if (isolated_origin_entry.MatchesBrowsingInstance(browsing_instance_id) &&
          IsolatedOriginUtil::DoesOriginMatchIsolatedOrigin(
              origin, isolated_origin_entry.origin())) {
        // If a match has been found that requires all subdomains to be isolated
        // then return immediately. |origin| is returned to ensure proper
        // process isolation, e.g. https://a.b.c.isolated.com matches an
        // IsolatedOriginEntry constructed from http://[*.]isolated.com, so
        // https://a.b.c.isolated.com must be returned.
        if (isolated_origin_entry.isolate_all_subdomains()) {
          *result = origin;
          uint16_t default_port = url::DefaultPortForScheme(
              origin.scheme().data(), origin.scheme().length());

          if (origin.port() != default_port) {
            *result = url::Origin::Create(GURL(origin.scheme() +
                                               url::kStandardSchemeSeparator +
                                               origin.host()));
          }

          return true;
        }

        if (!found || result->host().length() <
                          isolated_origin_entry.origin().host().length()) {
          *result = isolated_origin_entry.origin();
          found = true;
        }
      }
    }
  }

  return found;
}

OriginAgentClusterIsolationState
ChildProcessSecurityPolicyImpl::DetermineOriginAgentClusterIsolation(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    const OriginAgentClusterIsolationState& requested_isolation_state) {
  if (!IsolatedOriginUtil::IsValidOriginForOptInIsolation(origin))
    return OriginAgentClusterIsolationState::CreateNonIsolated();

  // See if the same origin exists in the BrowsingInstance already, and if so
  // return its isolation status.
  // There are two cases we're worried about here: (i) we've previously seen the
  // origin and isolated it, in which case we should continue to isolate it, and
  // (ii) we've previously seen the origin and *not* isolated it, in which case
  // we should continue to not isolate it.
  BrowsingInstanceId browsing_instance_id(
      isolation_context.browsing_instance_id());

  if (!browsing_instance_id.is_null()) {
    base::AutoLock origins_isolation_opt_in_lock(
        origins_isolation_opt_in_lock_);

    // Look for |origin| in the isolation status list.
    OriginAgentClusterIsolationState* oac_isolation_state =
        LookupOriginIsolationState(browsing_instance_id, origin);

    if (oac_isolation_state)
      return *oac_isolation_state;
  }

  // If we get to this point, then |origin| is neither opted-in nor opted-out.
  // At this point we allow opting in if it's requested. This is true for
  // either logical OriginAgentCluster, or OriginAgentCluster with an
  // origin-keyed process.
  return requested_isolation_state;
}

bool ChildProcessSecurityPolicyImpl::
    HasOriginEverRequestedOriginAgentClusterValue(
        BrowserContext* browser_context,
        const url::Origin& origin) {
  base::AutoLock origins_isolation_opt_in_lock(origins_isolation_opt_in_lock_);
  return base::Contains(origin_isolation_opt_ins_and_outs_, browser_context) &&
         base::Contains(origin_isolation_opt_ins_and_outs_[browser_context],
                        origin);
}

OriginAgentClusterIsolationState*
ChildProcessSecurityPolicyImpl::LookupOriginIsolationState(
    const BrowsingInstanceId& browsing_instance_id,
    const url::Origin& origin) {
  auto it_isolation_by_browsing_instance =
      origin_isolation_by_browsing_instance_.find(browsing_instance_id);
  if (it_isolation_by_browsing_instance ==
      origin_isolation_by_browsing_instance_.end()) {
    return nullptr;
  }
  auto& origin_list = it_isolation_by_browsing_instance->second;
  auto it_origin_list = base::ranges::find(
      origin_list, origin, &OriginAgentClusterOptInEntry::origin);
  if (it_origin_list != origin_list.end())
    return &(it_origin_list->oac_isolation_state);
  return nullptr;
}

void ChildProcessSecurityPolicyImpl::AddDefaultIsolatedOriginIfNeeded(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    bool is_global_walk_or_frame_removal) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!IsolatedOriginUtil::IsValidOriginForOptInIsolation(origin))
    return;

  BrowsingInstanceId browsing_instance_id(
      isolation_context.browsing_instance_id());
  // All callers to this function live on the UI thread, so the IsolationContext
  // should contain a BrowserContext*.
  BrowserContext* browser_context =
      isolation_context.browser_or_resource_context().ToBrowserContext();
  DCHECK(browser_context);
  CHECK(!browsing_instance_id.is_null());

  base::AutoLock origins_isolation_opt_in_lock(origins_isolation_opt_in_lock_);

  // Commits of origins that have ever sent the OriginAgentCluster header in
  // this BrowserContext are tracked in every BrowsingInstance in this
  // BrowserContext, to avoid having to do multiple global walks. If the origin
  // isn't in the list of such origins (i.e., the common case), return early to
  // avoid unnecessary work, since this is called on every commit. Skip this
  // during global walks and frame removals, since we do want to track the
  // origin's non-isolated status in those cases.
  if (!is_global_walk_or_frame_removal &&
      !(base::Contains(origin_isolation_opt_ins_and_outs_, browser_context) &&
        base::Contains(origin_isolation_opt_ins_and_outs_[browser_context],
                       origin))) {
    return;
  }

  // If |origin| is already in the opt-in-out list, then we don't want to add it
  // to the list. Technically this check is unnecessary during global
  // walks (when the origin won't be in this list yet), but it matters during
  // frame removal (when we don't want to add an opted-in origin to the
  // list as non-isolated when its frame is removed).
  if (LookupOriginIsolationState(browsing_instance_id, origin))
    return;

  // Since there was no prior record for this BrowsingInstance, track that this
  // origin should use the default isolation model in use by the
  // BrowsingInstance.
  origin_isolation_by_browsing_instance_[browsing_instance_id].emplace_back(
      isolation_context.default_isolation_state(), origin);
}

void ChildProcessSecurityPolicyImpl::
    RemoveOptInIsolatedOriginsForBrowsingInstance(
        const BrowsingInstanceId& browsing_instance_id) {
  // After a suitable delay, remove this BrowsingInstance's info from any
  // SecurityStates that are using it.
  // TODO(wjmaclean): Monitor the CanAccessDataForOrigin crash key in renderer
  // kills to see if we get post-BrowsingInstance-destruction ProcessLock
  // mismatches, indicating this cleanup should be further delayed.
  auto task_closure = [](const BrowsingInstanceId id) {
    ChildProcessSecurityPolicyImpl* policy =
        ChildProcessSecurityPolicyImpl::GetInstance();
    policy->RemoveOptInIsolatedOriginsForBrowsingInstanceInternal(id);
  };
  if (browsing_instance_cleanup_delay_.is_positive()) {
    // Do the actual state cleanup after posting a task to the IO thread, to
    // give a chance for any last unprocessed tasks to be handled. The cleanup
    // itself locks the data structures and can safely happen from either
    // thread.
    GetIOThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE, base::BindOnce(task_closure, browsing_instance_id),
        browsing_instance_cleanup_delay_);
  } else {
    // Since this is just used in tests, it's ok to do it on either thread.
    task_closure(browsing_instance_id);
  }
}

void ChildProcessSecurityPolicyImpl::
    RemoveOptInIsolatedOriginsForBrowsingInstanceInternal(
        const BrowsingInstanceId browsing_instance_id) {
  // If a BrowsingInstance is destructing, we should always have an id for it.
  CHECK(!browsing_instance_id.is_null());

  {
    // content_unittests don't always report being on the IO thread.
    DCHECK(IsRunningOnExpectedThread());
    base::AutoLock lock(lock_);
    for (auto& it : security_state_)
      it.second->ClearBrowsingInstanceId(browsing_instance_id);
    // Note: if the BrowsingInstanceId set is empty at the end of this function,
    // we must never remove the ProcessLock in case the associated RenderProcess
    // is compromised, in which case we wouldn't want to reuse it for another
    // origin.
  }

  {
    base::AutoLock origins_isolation_opt_in_lock(
        origins_isolation_opt_in_lock_);
    origin_isolation_by_browsing_instance_.erase(browsing_instance_id);
  }

  {
    base::AutoLock isolated_origins_lock(isolated_origins_lock_);
    for (auto& iter : isolated_origins_) {
      base::EraseIf(iter.second, [&browsing_instance_id](
                                     const IsolatedOriginEntry& entry) {
        // Remove entries that are specific to `browsing_instance_id` and
        // do not apply to future BrowsingInstances.
        return (entry.browsing_instance_id() == browsing_instance_id &&
                !entry.applies_to_future_browsing_instances());
      });
    }
  }
}

void ChildProcessSecurityPolicyImpl::AddCoopIsolatedOriginForBrowsingInstance(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    IsolatedOriginSource source) {
  // We ought to have validated the origin prior to getting here.  If the
  // origin isn't valid at this point, something has gone wrong.
  CHECK(IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
      << "Trying to isolate invalid origin: " << origin;

  // This can only be called from the UI thread, as it reads state that's only
  // available (and is only safe to be retrieved) on the UI thread, such as
  // BrowsingInstance IDs.
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BrowsingInstanceId browsing_instance_id(
      isolation_context.browsing_instance_id());
  // This function should only be called when a BrowsingInstance is registering
  // a new SiteInstance, so |browsing_instance_id| should always be defined.
  CHECK(!browsing_instance_id.is_null());

  // For site-keyed isolation, add `origin` to the isolated_origins_ map (which
  // supports subdomain matching).
  // Ensure that `origin` is a site (scheme + eTLD+1) rather than any origin.
  auto site_origin = url::Origin::Create(SiteInfo::GetSiteForOrigin(origin));
  CHECK_EQ(origin, site_origin);

  base::AutoLock isolated_origins_lock(isolated_origins_lock_);

  // Explicitly set `applies_to_future_browsing_instances` to false to only
  // isolate `origin` within the provided BrowsingInstance, but not future
  // ones.  Note that it's possible for `origin` to also become isolated for
  // future BrowsingInstances if AddFutureIsolatedOrigins() is called for it
  // later.
  AddIsolatedOriginInternal(
      isolation_context.browser_or_resource_context().ToBrowserContext(),
      origin, false /* applies_to_future_browsing_instances */,
      isolation_context.browsing_instance_id(),
      false /* isolate_all_subdomains */, source);
}

void ChildProcessSecurityPolicyImpl::AddOriginIsolationStateForBrowsingInstance(
    const IsolationContext& isolation_context,
    const url::Origin& origin,
    bool is_origin_agent_cluster,
    bool requires_origin_keyed_process) {
  DCHECK(is_origin_agent_cluster ||
         base::FeatureList::IsEnabled(
             blink::features::kOriginAgentClusterDefaultEnabled));
  // We ought to have validated the origin prior to getting here.  If the
  // origin isn't valid at this point, something has gone wrong.
  CHECK((is_origin_agent_cluster &&
         IsolatedOriginUtil::IsValidOriginForOptInIsolation(origin)) ||
        // The second part of this check is specific to OAC-by-default, and is
        // required to allow explicit opt-outs for HTTP schemed origins. See
        // OriginAgentClusterInsecureEnabledBrowserTest.DocumentDomain_Disabled.
        IsolatedOriginUtil::IsValidOriginForOptOutIsolation(origin))
      << "Trying to isolate invalid origin: " << origin;

  // This can only be called from the UI thread, as it reads state that's only
  // available (and is only safe to be retrieved) on the UI thread, such as
  // BrowsingInstance IDs.
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BrowsingInstanceId browsing_instance_id(
      isolation_context.browsing_instance_id());
  // This function should only be called when a BrowsingInstance is registering
  // a new SiteInstance, so |browsing_instance_id| should always be defined.
  CHECK(!browsing_instance_id.is_null());

  // For origin-keyed isolation, use the origin_isolation_by_browsing_instance_
  // map.
  base::AutoLock origins_isolation_opt_in_lock(origins_isolation_opt_in_lock_);
  auto it = origin_isolation_by_browsing_instance_.find(browsing_instance_id);
  if (it == origin_isolation_by_browsing_instance_.end()) {
    std::tie(it, std::ignore) = origin_isolation_by_browsing_instance_.emplace(
        browsing_instance_id, std::vector<OriginAgentClusterOptInEntry>());
  }

  // We only support adding new entries, not modifying existing ones. If at
  // some point in the future we allow isolation status to change during the
  // lifetime of a BrowsingInstance, then this will need to be updated.
  if (!base::Contains(it->second, origin,
                      &OriginAgentClusterOptInEntry::origin)) {
    it->second.emplace_back(
        is_origin_agent_cluster
            ? OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
                  requires_origin_keyed_process)
            : OriginAgentClusterIsolationState::CreateNonIsolated(),
        origin);
  }
}

bool ChildProcessSecurityPolicyImpl::UpdateOriginIsolationOptInListIfNecessary(
    BrowserContext* browser_context,
    const url::Origin& origin) {
  if (!IsolatedOriginUtil::IsValidOriginForOptInIsolation(origin))
    return false;

  base::AutoLock origins_isolation_opt_in_lock(origins_isolation_opt_in_lock_);

  if (base::Contains(origin_isolation_opt_ins_and_outs_, browser_context) &&
      base::Contains(origin_isolation_opt_ins_and_outs_[browser_context],
                     origin)) {
    return false;
  }

  origin_isolation_opt_ins_and_outs_[browser_context].insert(origin);
  return true;
}

void ChildProcessSecurityPolicyImpl::RemoveIsolatedOriginForTesting(
    const url::Origin& origin) {
  GURL key(SiteInfo::GetSiteForOrigin(origin));
  base::AutoLock isolated_origins_lock(isolated_origins_lock_);
  base::EraseIf(isolated_origins_[key],
                [&origin](const IsolatedOriginEntry& entry) {
                  // Remove if origin matches.
                  return (entry.origin() == origin);
                });
  if (isolated_origins_[key].empty())
    isolated_origins_.erase(key);
}

void ChildProcessSecurityPolicyImpl::ClearIsolatedOriginsForTesting() {
  base::AutoLock isolated_origins_lock(isolated_origins_lock_);
  isolated_origins_.clear();
}

ChildProcessSecurityPolicyImpl::SecurityState*
ChildProcessSecurityPolicyImpl::GetSecurityState(int child_id) {
  auto itr = security_state_.find(child_id);
  if (itr != security_state_.end())
    return itr->second.get();

  auto pending_itr = pending_remove_state_.find(child_id);
  if (pending_itr == pending_remove_state_.end())
    return nullptr;

  // At this point the SecurityState in the map is being kept alive
  // by a Handle object or we are waiting for the deletion task to be run on
  // the IO thread.
  SecurityState* pending_security_state = pending_itr->second.get();

  auto count_itr = process_reference_counts_.find(child_id);
  if (count_itr != process_reference_counts_.end()) {
    // There must be a Handle that still holds a reference to this
    // pending state so it is safe to return. The assumption is that the
    // owner of this Handle is making a security check.
    return pending_security_state;
  }

  // Since we don't have an entry in |process_reference_counts_| it means
  // that we are waiting for the deletion task posted to the IO thread to run.
  // Only allow the state to be accessed by the IO thread in this situation.
  if (BrowserThread::CurrentlyOn(BrowserThread::IO))
    return pending_security_state;

  return nullptr;
}

std::vector<IsolatedOriginPattern>
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
    base::StringPiece pattern_list) {
  std::vector<base::StringPiece> origin_strings = base::SplitStringPiece(
      pattern_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  std::vector<IsolatedOriginPattern> patterns;
  patterns.reserve(origin_strings.size());

  for (const base::StringPiece& origin_string : origin_strings)
    patterns.emplace_back(origin_string);

  return patterns;
}

// static
std::string ChildProcessSecurityPolicyImpl::GetKilledProcessOriginLock(
    const SecurityState* security_state) {
  if (!security_state)
    return "(child id not found)";

  if (!security_state->GetBrowserOrResourceContext())
    return "(empty and null context)";

  return security_state->process_lock().ToString();
}

void ChildProcessSecurityPolicyImpl::LogKilledProcessOriginLock(int child_id) {
  base::AutoLock lock(lock_);
  const auto itr = security_state_.find(child_id);
  const SecurityState* security_state =
      itr != security_state_.end() ? itr->second.get() : nullptr;

  base::debug::SetCrashKeyString(GetKilledProcessOriginLockKey(),
                                 GetKilledProcessOriginLock(security_state));
}

ChildProcessSecurityPolicyImpl::Handle
ChildProcessSecurityPolicyImpl::CreateHandle(int child_id) {
  return Handle(child_id, /* duplicating_handle */ false);
}

bool ChildProcessSecurityPolicyImpl::AddProcessReference(
    int child_id,
    bool duplicating_handle) {
  base::AutoLock lock(lock_);
  return AddProcessReferenceLocked(child_id, duplicating_handle);
}

bool ChildProcessSecurityPolicyImpl::AddProcessReferenceLocked(
    int child_id,
    bool duplicating_handle) {
  if (child_id == ChildProcessHost::kInvalidUniqueID)
    return false;

  // Check to see if the SecurityState has been removed from |security_state_|
  // via a Remove() call. This corresponds to the process being destroyed.
  if (security_state_.find(child_id) == security_state_.end()) {
    if (!duplicating_handle) {
      // Do not allow Handles to be created after the process has been
      // destroyed, unless they are being duplicated.
      return false;
    }

    // The process has been destroyed but we are allowing an existing Handle
    // to be duplicated. Verify that the process reference count is available
    // and indicates another Handle has a reference.
    auto itr = process_reference_counts_.find(child_id);
    CHECK(itr != process_reference_counts_.end());
    CHECK_GT(itr->second, 0);
  }

  ++process_reference_counts_[child_id];
  return true;
}

void ChildProcessSecurityPolicyImpl::RemoveProcessReference(int child_id) {
  base::AutoLock lock(lock_);
  RemoveProcessReferenceLocked(child_id);
}

void ChildProcessSecurityPolicyImpl::RemoveProcessReferenceLocked(
    int child_id) {
  auto itr = process_reference_counts_.find(child_id);
  CHECK(itr != process_reference_counts_.end());

  if (itr->second > 1) {
    itr->second--;
    return;
  }

  DCHECK_EQ(itr->second, 1);
  process_reference_counts_.erase(itr);

  // |child_id| could be inside tasks that are on the IO thread task queues. We
  // need to keep the |pending_remove_state_| entry around until we have
  // successfully executed a task on the IO thread. This should ensure that any
  // pending tasks on the IO thread will have completed before we remove the
  // entry.
  // TODO(acolwell): Remove this call once all objects on the IO thread have
  // been converted to use Handles.
  GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(
                     [](ChildProcessSecurityPolicyImpl* policy, int child_id) {
                       DCHECK_CURRENTLY_ON(BrowserThread::IO);
                       base::AutoLock lock(policy->lock_);
                       policy->pending_remove_state_.erase(child_id);
                     },
                     base::Unretained(this), child_id));
}

}  // namespace content
