// 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 "components/permissions/features.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());
}

base::WeakPtr<ResourceContext> GetResourceContext(
    BrowserContext* browser_context) {
  ResourceContext* resource_context = browser_context->GetResourceContext();
  return resource_context ? resource_context->GetWeakPtr() : nullptr;
}

}  // 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_(false),
        can_send_midi_sysex_(false),
        browser_context_(browser_context),
        resource_context_(GetResourceContext(browser_context)) {
    if (!base::FeatureList::IsEnabled(
            permissions::features::kBlockMidiByDefault)) {
      can_send_midi_ = true;
    }
  }

  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 GrantPermissionForMidi() { can_send_midi_ = true; }

  void GrantPermissionForMidiSysEx() {
    can_send_midi_ = true;
    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 CanSendMidi() const {
    if (base::FeatureList::IsEnabled(
            permissions::features::kBlockMidiByDefault)) {
      // Ensure the flags are in a consistent state: we can only send SysEx
      // messages if we can also send non-SysEx messages
      CHECK(can_send_midi_ || !can_send_midi_sysex_);
      return can_send_midi_;
    } else {
      return true;
    }
  }

  bool CanSendMidiSysEx() const {
    if (base::FeatureList::IsEnabled(
            permissions::features::kBlockMidiByDefault)) {
      // Ensure the flags are in a consistent state: we can only send SysEx
      // messages if we can also send non-SysEx messages
      CHECK(can_send_midi_ || !can_send_midi_sysex_);
    }
    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_.get());

    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 base::Contains(origin_map_, origin);
  }

  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_;

  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_;
  base::WeakPtr<ResourceContext> 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 (base::Contains(security_state_, child_id)) {
    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::GrantSendMidiMessage(int child_id) {
  if (base::FeatureList::IsEnabled(
          permissions::features::kBlockMidiByDefault)) {
    base::AutoLock lock(lock_);

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

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

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(
                  features::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::CanSendMidiMessage(int child_id) {
  base::AutoLock lock(lock_);

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

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

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->CanSendMidiSysEx();
}

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;
}

OriginAgentClusterIsolationState*
ChildProcessSecurityPolicyImpl::LookupOriginIsolationStateForTesting(
    const BrowsingInstanceId& browsing_instance_id,
    const url::Origin& origin) {
  base::AutoLock lock(origins_isolation_opt_in_lock_);
  return LookupOriginIsolationState(browsing_instance_id, origin);
}

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) {
  // 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);
  DCHECK(
      is_origin_agent_cluster ||
      SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
          isolation_context.browser_or_resource_context().ToBrowserContext()));

  // 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;

  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 (!base::Contains(security_state_, child_id)) {
    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
