// 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/site_instance_impl.h"

#include <string>
#include <tuple>

#include "base/check_is_test.h"
#include "base/containers/contains.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/trace_event/typed_macros.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/isolated_origin_util.h"
#include "content/browser/isolation_context.h"
#include "content/browser/process_lock.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/site_instance_group.h"
#include "content/browser/storage_partition_impl.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/content_browser_client.h"
#include "content/public/browser/process_allocation_context.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_ui_controller_factory.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
#include "url/origin.h"

namespace content {

using perfetto::protos::pbzero::ChromeTrackEvent;

namespace {

// Constant used to mark two call sites that must always agree on whether
// the default SiteInstance is allowed.
constexpr bool kCreateForURLAllowsDefaultSiteInstance = true;

// Asks the embedder whether effective URLs should be used when determining if
// |dest_url| should end up in |site_instance|.
// This is used to keep same-site scripting working for hosted apps.
bool ShouldCompareEffectiveURLs(BrowserContext* browser_context,
                                SiteInstanceImpl* site_instance,
                                bool for_outermost_main_frame,
                                const GURL& dest_url) {
  return site_instance->IsDefaultSiteInstance() ||
         GetContentClient()
             ->browser()
             ->ShouldCompareEffectiveURLsForSiteInstanceSelection(
                 browser_context, site_instance, for_outermost_main_frame,
                 site_instance->original_url(), dest_url);
}

SiteInstanceId::Generator g_site_instance_id_generator;

// Produce a crash report stack trace when GetProcess() is called on a
// SiteInstance that does not have a bound process.
// These calls should either be replaced with GetOrCreateProcess() if process
// creation was intentional, or the caller should be changed to avoid
// unnecessarily creating a process.
BASE_FEATURE(kTraceSiteInstanceGetProcessCreation,
             base::FEATURE_ENABLED_BY_DEFAULT);

// Whether to crash if GetProcess is called on a SiteInstance without a process.
const base::FeatureParam<bool> kCrashOnGetProcessCreation{
    &kTraceSiteInstanceGetProcessCreation, "crash_on_creation", true};

}  // namespace

// static
const GURL& SiteInstanceImpl::GetDefaultSiteURL() {
  struct DefaultSiteURL {
    const GURL url = GURL("http://unisolated.invalid");
  };
  static base::NoDestructor<DefaultSiteURL> default_site_url;
  return default_site_url->url;
}

class SiteInstanceImpl::DefaultSiteInstanceState {
 public:
  void AddSiteInfo(const SiteInfo& site_info) {
    default_site_url_set_.insert(site_info.site_url());
  }

  bool ContainsSite(const GURL& site_url) {
    return base::Contains(default_site_url_set_, site_url);
  }

 private:
  // Keeps track of the site URLs that have been mapped to the default
  // SiteInstance.
  // TODO(wjmaclean): Revise this to store SiteInfos instead of GURLs.
  std::set<GURL> default_site_url_set_;
};

SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
    : id_(g_site_instance_id_generator.GenerateNextId()),
      browsing_instance_(browsing_instance),
      can_associate_with_spare_process_(true),
      site_info_(browsing_instance->isolation_context()
                     .browser_or_resource_context()
                     .ToBrowserContext()),
      has_site_(false),
      process_reuse_policy_(ProcessReusePolicy::kDefault),
      is_for_service_worker_(false),
      process_assignment_(SiteInstanceProcessAssignment::UNKNOWN) {
  DCHECK(browsing_instance);
}

SiteInstanceImpl::~SiteInstanceImpl() {
  if (destruction_callback_for_testing_) {
    std::move(destruction_callback_for_testing_).Run();
  }

  // Now that no one is referencing us, we can safely remove ourselves from
  // the BrowsingInstance.  Any future visits to a page from this site
  // (within the same BrowsingInstance) can safely create a new SiteInstance.
  if (has_site_)
    browsing_instance_->UnregisterSiteInstance(this);

  if (has_group()) {
    group()->RemoveSiteInstance(this);
    ResetSiteInstanceGroup();
  }
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::Create(
    BrowserContext* browser_context) {
  DCHECK(browser_context);
  return base::WrapRefCounted(new SiteInstanceImpl(new BrowsingInstance(
      browser_context, WebExposedIsolationInfo::CreateNonIsolated(),
      /*is_guest=*/false, /*is_fenced=*/false,
      /*is_fixed_storage_partition=*/false)));
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForUrlInfo(
    BrowserContext* browser_context,
    const UrlInfo& url_info,
    bool is_guest,
    bool is_fenced,
    bool is_fixed_storage_partition) {
  TRACE_EVENT("navigation", "SiteInstanceImpl::CreateForUrlInfo", "url_info",
              url_info);
  DCHECK(url_info.is_sandboxed ||
         url_info.unique_sandbox_id == UrlInfo::kInvalidUniqueSandboxId);
  CHECK(!is_guest || url_info.storage_partition_config.has_value());
  DCHECK(browser_context);

  // This will create a new SiteInstance and BrowsingInstance.
  scoped_refptr<BrowsingInstance> instance(
      new BrowsingInstance(browser_context,
                           url_info.web_exposed_isolation_info.value_or(
                               WebExposedIsolationInfo::CreateNonIsolated()),
                           is_guest, is_fenced, is_fixed_storage_partition));

  // Note: The |allow_default_instance| value used here MUST match the value
  // used in DoesSiteForURLMatch().
  return instance->GetSiteInstanceForURL(
      url_info, kCreateForURLAllowsDefaultSiteInstance);
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForServiceWorker(
    BrowserContext* browser_context,
    const UrlInfo& url_info,
    bool can_reuse_process,
    bool is_guest,
    bool is_fenced) {
  DCHECK(!url_info.url.SchemeIs(kChromeErrorScheme));
  DCHECK(url_info.storage_partition_config.has_value());

  // This will create a new SiteInstance and BrowsingInstance.
  // TODO(crbug.com/40186710): Verify that having different common COOP
  // origins does not hinder the ability of a ServiceWorker to share its page's
  // process.
  scoped_refptr<BrowsingInstance> instance(new BrowsingInstance(
      browser_context,
      url_info.web_exposed_isolation_info.value_or(
          WebExposedIsolationInfo::CreateNonIsolated()),
      is_guest, is_fenced,
      // It should be safe to just default this to true since the
      // BrowsingInstance is not shared with frames, and there are no
      // navigations happening in service workers.
      /*is_fixed_storage_partition=*/true));

  // We do NOT want to allow the default site instance here because workers
  // need to be kept separate from other sites.
  scoped_refptr<SiteInstanceImpl> site_instance =
      instance->GetSiteInstanceForURL(url_info,
                                      /* allow_default_instance */ false);

  DCHECK(!site_instance->GetSiteInfo().is_error_page());
  DCHECK_EQ(site_instance->IsGuest(), is_guest);
  site_instance->is_for_service_worker_ = true;

  // Attempt to reuse a renderer process if possible. Note that in the
  // <webview> case, process reuse isn't currently supported and a new
  // process will always be created (https://crbug.com/752667).
  DCHECK(site_instance->process_reuse_policy() ==
             ProcessReusePolicy::kDefault ||
         site_instance->process_reuse_policy() ==
             ProcessReusePolicy::kProcessPerSite);
  if (can_reuse_process) {
    site_instance->set_process_reuse_policy(
        ProcessReusePolicy::kReusePendingOrCommittedSiteWorker);
  }
  return site_instance;
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForGuest(
    BrowserContext* browser_context,
    const StoragePartitionConfig& partition_config) {
  DCHECK(browser_context);
  DCHECK(!partition_config.is_default());

  auto guest_site_info =
      SiteInfo::CreateForGuest(browser_context, partition_config);
  scoped_refptr<SiteInstanceImpl> site_instance =
      base::WrapRefCounted(new SiteInstanceImpl(new BrowsingInstance(
          browser_context, guest_site_info.web_exposed_isolation_info(),
          /*is_guest=*/true,
          /*is_fenced=*/false,
          /*is_fixed_storage_partition=*/true)));

  site_instance->SetSiteInfoInternal(guest_site_info);
  return site_instance;
}

// static
scoped_refptr<SiteInstanceImpl>
SiteInstanceImpl::CreateForFixedStoragePartition(
    BrowserContext* browser_context,
    const GURL& url,
    const StoragePartitionConfig& partition_config) {
  CHECK(browser_context);
  CHECK(!partition_config.is_default());

  return SiteInstanceImpl::CreateForUrlInfo(
      browser_context,
      UrlInfo(UrlInfoInit(url).WithStoragePartitionConfig(partition_config)),
      /*is_guest=*/false,
      /*is_fenced=*/false, /*is_fixed_storage_partition=*/true);
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForFencedFrame(
    SiteInstanceImpl* embedder_site_instance) {
  DCHECK(embedder_site_instance);
  BrowserContext* browser_context = embedder_site_instance->GetBrowserContext();
  bool should_isolate_fenced_frames =
      SiteIsolationPolicy::IsProcessIsolationForFencedFramesEnabled();
  scoped_refptr<SiteInstanceImpl> site_instance =
      base::WrapRefCounted(new SiteInstanceImpl(new BrowsingInstance(
          browser_context, embedder_site_instance->GetWebExposedIsolationInfo(),
          embedder_site_instance->IsGuest(),
          /*is_fenced=*/should_isolate_fenced_frames,
          embedder_site_instance->IsFixedStoragePartition())));

  // Give the new fenced frame SiteInstance the same site url as its embedder's
  // SiteInstance to allow it to reuse its embedder's process. We avoid doing
  // this in the default SiteInstance case as the url will be invalid; process
  // reuse will still happen below though, as the embedder's SiteInstance's
  // process will not be locked to any site.
  // Note: Even when process isolation for fenced frames is enabled, we will
  // still be able to reuse the embedder's process below, because we set its
  // SiteInfo to be the embedder's SiteInfo, and |is_fenced| will be false. The
  // process will change after the first navigation (the new SiteInstance will
  // have a SiteInfo with is_fenced set to true).
  if (!embedder_site_instance->IsDefaultSiteInstance()) {
    site_instance->SetSite(embedder_site_instance->GetSiteInfo());
  } else if (embedder_site_instance->IsGuest()) {
    // For guests, in the case where the embedder is not a default SiteInstance,
    // we reuse the embedder's SiteInfo above. When the embedder is
    // a default SiteInstance, we explicitly create a SiteInfo through
    // CreateForGuest.
    // TODO(crbug.com/40230422): When we support fenced frame process isolation
    // with partial or no site isolation modes, we will be able to reach this
    // code path and will need to also set is_fenced for the SiteInfo created
    // below.
    DCHECK(!should_isolate_fenced_frames);
    site_instance->SetSite(SiteInfo::CreateForGuest(
        browser_context, embedder_site_instance->GetStoragePartitionConfig()));
  }
  DCHECK_EQ(embedder_site_instance->IsGuest(), site_instance->IsGuest());
  if (embedder_site_instance->HasProcess()) {
    site_instance->ReuseExistingProcessIfPossible(
        embedder_site_instance->GetProcess());
  }
  return site_instance;
}

// static
scoped_refptr<SiteInstanceImpl>
SiteInstanceImpl::CreateReusableInstanceForTesting(
    BrowserContext* browser_context,
    const GURL& url) {
  DCHECK(browser_context);
  // This will create a new SiteInstance and BrowsingInstance.
  scoped_refptr<BrowsingInstance> instance(new BrowsingInstance(
      browser_context, WebExposedIsolationInfo::CreateNonIsolated(),
      /*is_guest=*/false, /*is_fenced=*/false,
      /*is_fixed_storage_partition=*/false));
  auto site_instance = instance->GetSiteInstanceForURL(
      UrlInfo(UrlInfoInit(url)), /* allow_default_instance */ false);
  site_instance->set_process_reuse_policy(
      ProcessReusePolicy::kReusePendingOrCommittedSiteSubframe);
  // Proactively create a process since many callers of this function in tests
  // rely on site_instance->GetProcess().
  site_instance->GetOrCreateProcess(
      ProcessAllocationContext{ProcessAllocationSource::kTest});
  return site_instance;
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForTesting(
    BrowserContext* browser_context,
    const GURL& url) {
  DCHECK(browser_context);
  return SiteInstanceImpl::CreateForUrlInfo(
      browser_context, UrlInfo::CreateForTesting(url),
      /*is_guest=*/false,
      /*is_fenced=*/false,
      /*is_fixed_storage_partition=*/false);
}

// static
bool SiteInstanceImpl::ShouldAssignSiteForUrlInfo(const UrlInfo& url_info) {
  // Only empty document schemes can leave SiteInstances unassigned.
  if (!base::Contains(url::GetEmptyDocumentSchemes(),
                      url_info.url.GetScheme())) {
    return true;
  }

  if (url_info.url.SchemeIs(url::kAboutScheme)) {
    // TODO(alexmos):  Currently, we force about: URLs that are not about:blank
    // to assign a site. This has been the legacy behavior, and it's unclear
    // whether this matters one way or another, so we can consider changing
    // this if there's a good motivation.
    if (!url_info.url.IsAboutBlank()) {
      return true;
    }

    // Check if the UrlInfo carries an inherited origin for about:blank, such
    // as with a renderer-initiated about:blank navigation where the origin is
    // taken from the navigation's initiator.  In such cases, the SiteInstance
    // assignment must also honor a valid initiator origin (which could require
    // a dedicated process), and hence it cannot be left unassigned.
    //
    // Note that starting an about:blank navigation from an opaque unique
    // origin is safe to leave unassigned. Some Android tests currently rely on
    // that behavior.
    if (url_info.origin.has_value() &&
        url_info.origin->GetTupleOrPrecursorTupleIfOpaque().IsValid()) {
      return true;
    }

    // Otherwise, it is ok for about:blank to not "use up" a new SiteInstance.
    // The SiteInstance can still be used for a normal web site. For example,
    // this is used for newly-created tabs.
    return false;
  }

  // Do not assign a site for other empty document schemes. One notable use of
  // this is for Android's native NTP, which uses the chrome-native: scheme.
  return false;
}

SiteInstanceId SiteInstanceImpl::GetId() {
  return id_;
}

BrowsingInstanceId SiteInstanceImpl::GetBrowsingInstanceId() {
  return browsing_instance_->isolation_context().browsing_instance_id();
}

const IsolationContext& SiteInstanceImpl::GetIsolationContext() {
  return browsing_instance_->isolation_context();
}

bool SiteInstanceImpl::IsDefaultSiteInstance() const {
  return default_site_instance_state_ != nullptr;
}

void SiteInstanceImpl::AddSiteInfoToDefault(const SiteInfo& site_info) {
  DCHECK(!ShouldUseDefaultSiteInstanceGroup());
  DCHECK(IsDefaultSiteInstance());
  default_site_instance_state_->AddSiteInfo(site_info);
}

bool SiteInstanceImpl::IsSiteInDefaultSiteInstance(const GURL& site_url) const {
  DCHECK(IsDefaultSiteInstance());
  return default_site_instance_state_->ContainsSite(site_url);
}

SiteInstanceGroup*
SiteInstanceImpl::DefaultSiteInstanceGroupForBrowsingInstance() const {
  return browsing_instance()->default_site_instance_group();
}

// static
BrowsingInstanceId SiteInstanceImpl::NextBrowsingInstanceId() {
  return BrowsingInstance::NextBrowsingInstanceId();
}

bool SiteInstanceImpl::HasProcess() {
  if (has_group())
    return true;

  // If we would use process-per-site for this site, also check if there is an
  // existing process that we would use if GetOrCreateProcess() were called.
  if (ShouldUseProcessPerSite() &&
      RenderProcessHostImpl::GetSoleProcessHostForSite(GetIsolationContext(),
                                                       site_info_)) {
    return true;
  }

  return false;
}

RenderProcessHost* SiteInstanceImpl::GetProcess() {
  // TODO(crbug.com/388998723):
  // Change this function to either add a CHECK(HasProcess()) or return null if
  // there is no bound process after collecting and fixing any
  // DumpWithoutCrashing reports.
  if (!HasProcess() &&
      base::FeatureList::IsEnabled(kTraceSiteInstanceGetProcessCreation)) {
    if (kCrashOnGetProcessCreation.Get()) {
      CHECK(false);
    }
  }
  return GetOrCreateProcess(ProcessAllocationContext{
      ProcessAllocationSource::kNoProcessCreationExpected});
}

RenderProcessHost* SiteInstanceImpl::GetOrCreateProcess(
    const ProcessAllocationContext& context) {
  if (!HasProcess() &&
      base::FeatureList::IsEnabled(kTraceSiteInstanceGetProcessCreation) &&
      context.source == ProcessAllocationSource::kNoProcessCreationExpected) {
    base::debug::DumpWithoutCrashing();
  }
  // Create a new SiteInstanceGroup and RenderProcessHost if there isn't one.
  // All SiteInstances within a SiteInstanceGroup share a process and
  // AgentSchedulingGroupHost. A group must have a process. If the process gets
  // destructed, `site_instance_group_` will get cleared, and another one with a
  // new process will be assigned the next time GetProcess() gets called.
  if (!has_group()) {
    // Check if the ProcessReusePolicy should be updated.
    if (ShouldUseProcessPerSite()) {
      process_reuse_policy_ = ProcessReusePolicy::kProcessPerSite;
    } else if (process_reuse_policy_ == ProcessReusePolicy::kProcessPerSite) {
      process_reuse_policy_ = ProcessReusePolicy::kDefault;
    }
    ProcessAllocationContext allocation_context = context;
    if (allocation_context.navigation_context.has_value()) {
      allocation_context.navigation_context->requires_new_process_for_coop =
          coop_reuse_process_failed_;
    }

    // See if `this` can be placed in the default SiteInstanceGroup, otherwise
    // create a process and associated SiteInstanceGroup.
    if (CanPutSiteInstanceInDefaultGroup() &&
        browsing_instance_->has_default_site_instance_group()) {
      browsing_instance_->default_site_instance_group()->AddSiteInstance(this);
      SetSiteInstanceGroup(browsing_instance_->default_site_instance_group());
    } else {
      SetProcessInternal(RenderProcessHostImpl::GetProcessHostForSiteInstance(
          this, allocation_context));
    }
  }
  DCHECK(site_instance_group_);

  return site_instance_group_->process();
}

RenderProcessHost* SiteInstanceImpl::GetOrCreateProcess(
    base::PassKey<SiteInstanceProcessCreationClient>) {
  return GetOrCreateProcess(
      ProcessAllocationContext{ProcessAllocationSource::kEmbedder});
}

RenderProcessHost* SiteInstanceImpl::GetOrCreateProcessForTesting() {
  CHECK_IS_TEST();
  return GetOrCreateProcess(
      ProcessAllocationContext{ProcessAllocationSource::kTest});
}

SiteInstanceGroupId SiteInstanceImpl::GetSiteInstanceGroupId() {
  return has_group() ? site_instance_group_->GetId() : SiteInstanceGroupId(0);
}

bool SiteInstanceImpl::ShouldUseProcessPerSite() const {
  BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
  return has_site_ && site_info_.ShouldUseProcessPerSite(browser_context);
}

void SiteInstanceImpl::ReuseExistingProcessIfPossible(
    RenderProcessHost* existing_process) {
  if (HasProcess())
    return;

  // We should not reuse `existing_process` if the destination uses
  // process-per-site. Note that this includes the case where the process for
  // the site is not there yet (so we're going to create a new process).  Note
  // also that this does not apply for the reverse case: if the existing process
  // is used for a process-per-site site, it is ok to reuse this for the new
  // page (regardless of the site).
  if (ShouldUseProcessPerSite())
    return;

  // Do not reuse the process if it's not suitable for this SiteInstance. For
  // example, this won't allow reusing a process if it's locked to a site that's
  // different from this SiteInstance's site.
  if (!RenderProcessHostImpl::MayReuseAndIsSuitable(existing_process, this)) {
    return;
  }

  // If `this` can go in the default SiteInstanceGroup and one exists, prefer
  // that SiteInstanceGroup and process.
  if (CanPutSiteInstanceInDefaultGroup() &&
      browsing_instance()->has_default_site_instance_group()) {
    return;
  }

  // TODO(crbug.com/40676483): Don't try to reuse process if either of the
  // SiteInstances are cross-origin isolated (uses COOP/COEP).
  SetProcessInternal(existing_process);
}

void SiteInstanceImpl::SetProcessInternal(RenderProcessHost* process) {
  if (!site_instance_group_) {
    site_instance_group_ = base::WrapRefCounted(
        new SiteInstanceGroup(browsing_instance(), process));
    site_instance_group_->AddSiteInstance(this);
  }

  // Check if the process created should become the default SiteInstanceGroup's
  // process. If so, set `site_instance_group_` to be the default
  // SiteInstanceGroup. We should only get here if a process needs to be created
  // for the default SiteInstanceGroup.
  if (CanPutSiteInstanceInDefaultGroup()) {
    MaybeSetDefaultSiteInstanceGroup();
  }

  LockProcessIfNeeded();

  // If we are using process-per-site, we need to register this process
  // for the current site so that we can find it again.  (If no site is set
  // at this time, we will register it in SetSite().)
  if (process_reuse_policy_ == ProcessReusePolicy::kProcessPerSite &&
      has_site_) {
    RenderProcessHostImpl::RegisterSoleProcessHostForSite(
        site_instance_group_->process(), this);
  }

  TRACE_EVENT2("navigation", "SiteInstanceImpl::SetProcessInternal", "site id",
               id_.value(), "process id",
               site_instance_group_->process()->GetDeprecatedID());

  // Inform the embedder if the SiteInstance now has both the process and the
  // site assigned. Note that this can be called either here or when setting
  // the site in SetSiteInfoInternal() below. This could be called multiple
  // times if the SiteInstance's RenderProcessHost goes away and a new one
  // replaces it later.
  if (has_site_) {
    GetContentClient()->browser()->SiteInstanceGotProcessAndSite(this);
  }
}

bool SiteInstanceImpl::CanAssociateWithSpareProcess() {
  return can_associate_with_spare_process_;
}

void SiteInstanceImpl::PreventAssociationWithSpareProcess() {
  can_associate_with_spare_process_ = false;
}

void SiteInstanceImpl::SetSite(const UrlInfo& url_info) {
  const GURL& url = url_info.url;
  // TODO(creis): Consider calling ShouldAssignSiteForURL internally, rather
  // than before multiple call sites.  See https://crbug.com/949220.
  TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite", "site id",
               id_.value(), "url_info", url_info);
  // A SiteInstance's site should not change.
  // TODO(creis): When following links or script navigations, we can currently
  // render pages from other sites in this SiteInstance.  This will eventually
  // be fixed, but until then, we should still not set the site of a
  // SiteInstance more than once.
  DCHECK(!has_site_);

  original_url_ = url;
  // Convert |url| into an appropriate SiteInfo that can be passed to
  // SetSiteInfoInternal(). We must do this transformation for any arbitrary
  // URL we get from a user, a navigation, or script.
  SetSiteInfoInternal(browsing_instance_->GetSiteInfoForURL(
      url_info, /* allow_default_instance */ false));
}

void SiteInstanceImpl::SetSite(const SiteInfo& site_info) {
  TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite", "site id",
               id_.value(), "siteinfo", site_info.GetDebugString());
  DCHECK(!has_site_);
  SetSiteInfoInternal(site_info);
}

void SiteInstanceImpl::SetSiteInfoToDefault(
    const StoragePartitionConfig& storage_partition_config) {
  TRACE_EVENT1("navigation", "SiteInstanceImpl::SetSiteInfoToDefault",
               "site id", id_.value());
  DCHECK(!has_site_);
  default_site_instance_state_ = std::make_unique<DefaultSiteInstanceState>();
  original_url_ = GetDefaultSiteURL();
  SetSiteInfoInternal(SiteInfo::CreateForDefaultSiteInstance(
      GetIsolationContext(), storage_partition_config,
      GetWebExposedIsolationInfo(),
      /*cross_origin_isolation_key=*/std::nullopt));
}

void SiteInstanceImpl::SetSiteInfoInternal(const SiteInfo& site_info) {
  // TODO(acolwell): Add logic to validate |site_url| and |lock_url| are valid.
  DCHECK(!has_site_);
  CHECK_EQ(site_info.web_exposed_isolation_info(),
           browsing_instance_->web_exposed_isolation_info());

  if (verify_storage_partition_info_) {
    auto old_partition_config = site_info_.storage_partition_config();
    auto new_partition_config = site_info.storage_partition_config();
    CHECK_EQ(old_partition_config, new_partition_config);
  }
  // Remember that this SiteInstance has been used to load a URL, even if the
  // URL is invalid.
  has_site_ = true;
  site_info_ = site_info;

  // Now that we have a site, register it with the BrowsingInstance.  This
  // ensures that we won't create another SiteInstance for this site within
  // the same BrowsingInstance, because all same-site pages within a
  // BrowsingInstance can script each other.
  browsing_instance_->RegisterSiteInstance(this);

  if (site_info_.oac_status() ==
      AgentClusterKey::OACStatus::kOriginKeyedByHeader) {
    CHECK(site_info_.agent_cluster_key().IsOriginKeyed());
    // Track this origin's isolation in the current BrowsingInstance, if it has
    // received an origin-keyed process due to an explicit opt-in. This is
    // needed to consistently isolate future navigations to this origin in this
    // BrowsingInstance, even if its opt-in status changes later.
    ChildProcessSecurityPolicyImpl* policy =
        ChildProcessSecurityPolicyImpl::GetInstance();
    // This is one of two places that origins can be marked as opted-in, the
    // other is
    // NavigationRequest::AddSameProcessOriginAgentClusterStateIfNecessary().
    // This site handles the case where OAC isolation gets a separate process.
    // In future, when SiteInstance Groups are complete, this may revert to
    // being the only call site.
    policy->AddOriginAgentClusterStateForBrowsingInstance(
        browsing_instance_->isolation_context(),
        site_info_.agent_cluster_key().GetOrigin(),
        OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
            true /* had_oac_request */,
            true /* requires_origin_keyed_process */));
  }

  if (site_info_.does_site_request_dedicated_process_for_coop()) {
    // If there was a request to process-isolate `site_info_` from COOP
    // headers, notify ChildProcessSecurityPolicy about the new isolated origin
    // in the current BrowsingInstance.  Note that we must convert the origin
    // to a site to avoid breaking document.domain.  Typically, the process
    // lock URL would already correspond to a site (since we isolate sites, not
    // origins, by default), but this isn't always the case.  For example, this
    // SiteInstance could be isolated with the origin granularity due to
    // Origin-Agent-Cluster (see site_info_.oac_status() above).
    url::Origin origin =
        site_info_.agent_cluster_key().IsOriginKeyed()
            ? site_info_.agent_cluster_key().GetOrigin()
            : url::Origin::Create(site_info_.agent_cluster_key().GetSite());
    GURL site(SiteInfo::GetSiteForOrigin(origin));
    ChildProcessSecurityPolicyImpl* policy =
        ChildProcessSecurityPolicyImpl::GetInstance();
    policy->AddCoopIsolatedOriginForBrowsingInstance(
        browsing_instance_->isolation_context(), url::Origin::Create(site),
        ChildProcessSecurityPolicy::IsolatedOriginSource::WEB_TRIGGERED);
  }

  // Update the process reuse policy based on the site.
  bool should_use_process_per_site = ShouldUseProcessPerSite();
  if (should_use_process_per_site)
    process_reuse_policy_ = ProcessReusePolicy::kProcessPerSite;

  if (has_group()) {
    LockProcessIfNeeded();

    // Inform the embedder if the SiteInstance now has both the process and the
    // site assigned. Note that this can be called either here or when setting
    // the process in SetProcessInternal() above.
    GetContentClient()->browser()->SiteInstanceGotProcessAndSite(this);

    // Ensure the process is registered for this site if necessary.
    if (should_use_process_per_site) {
      RenderProcessHostImpl::RegisterSoleProcessHostForSite(
          site_instance_group_->process(), this);
    }
  }
}

void SiteInstanceImpl::ConvertToDefaultOrSetSite(const UrlInfo& url_info) {
  DCHECK(!has_site_);

  if (!ShouldUseDefaultSiteInstanceGroup() &&
      !browsing_instance_->has_default_site_instance()) {
    // We want to set a SiteInfo in this SiteInstance, from information in a
    // UrlInfo. The WebExposedIsolationInfo must be compatible for this
    // function to not violate WebExposedIsolationInfo isolation invariant
    // within a BrowsingInstance.
    DCHECK(WebExposedIsolationInfo::AreCompatible(
        url_info.web_exposed_isolation_info, GetWebExposedIsolationInfo()));

    // If |url_info| has a null WebExposedIsolationInfo, it is compatible with
    // any isolation state. We reuse the isolation state of the browsing
    // instance for the SiteInfo, to preserve the invariant.
    UrlInfo updated_url_info = url_info;
    updated_url_info.web_exposed_isolation_info = GetWebExposedIsolationInfo();

    const SiteInfo site_info =
        SiteInfo::Create(GetIsolationContext(), updated_url_info);
    if (CanBePlacedInDefaultSiteInstanceOrGroup(
            GetIsolationContext(), updated_url_info.url, site_info)) {
      SetSiteInfoToDefault(site_info.storage_partition_config());
      AddSiteInfoToDefault(site_info);

      DCHECK(browsing_instance_->has_default_site_instance());
      return;
    }
  }

  SetSite(url_info);

  // If `this` should go in the default SiteInstanceGroup, it needs to be a
  // regular SiteInstance with a site (unlike the default SiteInstance), so
  // SetSite needs to be called first.
  if (ShouldUseDefaultSiteInstanceGroup()) {
    MaybeSetDefaultSiteInstanceGroup();
  }
}

void SiteInstanceImpl::MaybeSetDefaultSiteInstanceGroup() {
  CHECK(ShouldUseDefaultSiteInstanceGroup());
  if (!browsing_instance_->has_default_site_instance_group() &&
      CanBePlacedInDefaultSiteInstanceOrGroup(GetIsolationContext(),
                                              GetSiteURL(), site_info_)) {
    CHECK(HasProcess());
    CHECK(has_group());
    browsing_instance_->set_default_site_instance_group(
        site_instance_group_->GetWeakPtr());
  }
}

bool SiteInstanceImpl::CanPutSiteInstanceInDefaultGroup() {
  return ShouldUseDefaultSiteInstanceGroup() &&
         CanBePlacedInDefaultSiteInstanceOrGroup(GetIsolationContext(),
                                                 GetSiteURL(), site_info_);
}

SiteInstanceProcessAssignment
SiteInstanceImpl::GetLastProcessAssignmentOutcome() {
  return process_assignment_;
}

const GURL& SiteInstanceImpl::GetSiteURL() const {
  return site_info_.site_url();
}

const SiteInfo& SiteInstanceImpl::GetSiteInfo() {
  return site_info_;
}

SiteInfo SiteInstanceImpl::DeriveSiteInfo(
    const UrlInfo& url_info,
    bool is_related,
    bool disregard_web_exposed_isolation_info) {
  if (is_related) {
    return browsing_instance_->GetSiteInfoForURL(
        url_info, /* allow_default_instance */ true);
  }

  // If we care about WebExposedIsolationInfo, verify that the passed in
  // WebExposedIsolationInfo is compatible with the internal state. If they
  // don't, the semantics of the function would be unclear.
  if (!disregard_web_exposed_isolation_info) {
    DCHECK(WebExposedIsolationInfo::AreCompatible(
        url_info.web_exposed_isolation_info, GetWebExposedIsolationInfo()));
  }

  // At this stage, we either have two values of WebExposedIsolationInfo that
  // can be resolved into one, for example when UrlInfo has an empty
  // WebExposedIsolationInfo and it is matchable with any isolation state. Or we
  // are trying to compute other state, regardless of what the passed in
  // WebExposedIsolationInfos are. In both cases, we simply use the
  // SiteInstance's value.
  UrlInfo overridden_url_info = url_info;
  overridden_url_info.web_exposed_isolation_info = GetWebExposedIsolationInfo();

  // Keep the same StoragePartition when the storage partition is fixed (e.g.
  // for <webview>).
  if (IsFixedStoragePartition()) {
    overridden_url_info.storage_partition_config =
        GetSiteInfo().storage_partition_config();
  }

  return SiteInfo::Create(GetIsolationContext(), overridden_url_info);
}

bool SiteInstanceImpl::HasSite() const {
  return has_site_;
}

bool SiteInstanceImpl::HasRelatedSiteInstance(const SiteInfo& site_info) {
  return browsing_instance_->HasSiteInstance(site_info);
}

scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
    const GURL& url) {
  return GetRelatedSiteInstanceImpl(UrlInfo(UrlInfoInit(url)));
}

scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::GetRelatedSiteInstanceImpl(
    const UrlInfo& url_info) {
  return browsing_instance_->GetSiteInstanceForURL(
      url_info, /* allow_default_instance */ true);
}

scoped_refptr<SiteInstanceImpl>
SiteInstanceImpl::GetMaybeGroupRelatedSiteInstanceImpl(
    const UrlInfo& url_info) {
  // There has to be an existing SiteInstanceGroup in order to get one in the
  // same group.
  CHECK(site_instance_group_);
  return browsing_instance_->GetMaybeGroupRelatedSiteInstanceForURL(
      url_info, site_instance_group_.get());
}

AgentSchedulingGroupHost& SiteInstanceImpl::GetOrCreateAgentSchedulingGroup() {
  // Currently GetOrCreateAgentSchedulingGroup is called in the following
  // cases:
  // * From the RFH constructor created by CreateSpeculativeRenderFrameHost,
  //   the function will explicitly create the process for the site instance
  //   before constructing the RFH.
  // * From the RFH constructor created by InitRoot, the function will
  //   explicitly create the process for the site instance before
  //   constructing the RFH.
  // * From the RFH constructor created by InitChild, the child RFH is assumed
  //   to share the same process as the parent so the process will already be
  //   present.
  // * In SharedStorageRenderThreadWorkletDriver::StartWorkletService, the
  //   constructor of SharedStorageRenderThreadWorkletDriver will create
  //   the process for the site instance.
  // Since this is called when SiteInstance already has a process in all these
  // cases, and since site_instance_group_ is created when the SiteInstance's
  // process is set, there should be no case here when there is no
  // site_instance_group_, and no need to call GetOrCreateProcess().
  //
  // TODO(crbug.com/388998723): Remove the call to GetProcess() after
  // verifying there is no DumpWithoutCrashing reports.
  if (!site_instance_group_) {
    GetProcess();
  }

  return site_instance_group_->agent_scheduling_group();
}

void SiteInstanceImpl::SetSiteInstanceGroup(SiteInstanceGroup* group) {
  // At this point, `this` should not belong to a group. If `this` is being
  // created, then there should be no group set. If the group is being set
  // because the SiteInstance is getting a new process, the old one should have
  // been cleared.
  CHECK(!site_instance_group_);
  site_instance_group_ = group;
}

void SiteInstanceImpl::ResetSiteInstanceGroup() {
  site_instance_group_.reset();
}

bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) {
  return browsing_instance_.get() ==
         static_cast<const SiteInstanceImpl*>(instance)
             ->browsing_instance_.get();
}

size_t SiteInstanceImpl::GetRelatedActiveContentsCount() {
  return browsing_instance_->active_contents_count();
}

namespace {

bool SandboxConfigurationsMatch(const SiteInfo& site_info,
                                const UrlInfo& url_info) {
  return site_info.is_sandboxed() == url_info.is_sandboxed &&
         site_info.unique_sandbox_id() == url_info.unique_sandbox_id;
}

}  // namespace

bool SiteInstanceImpl::IsSuitableForUrlInfo(const UrlInfo& url_info) {
  TRACE_EVENT2("navigation", "SiteInstanceImpl::IsSuitableForUrlInfo",
               ChromeTrackEvent::kSiteInstance, this, "url_info", url_info);
  const GURL& url = url_info.url;
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // If the URL to navigate to can be associated with any site instance,
  // we want to keep it in the same process.
  if (blink::IsRendererDebugURL(url))
    return true;

  // Any process can host an about:blank URL, except the one used for error
  // pages, which should not commit successful navigations.  This check avoids a
  // process transfer for browser-initiated navigations to about:blank in a
  // dedicated process; without it, IsSuitableHost would consider this process
  // unsuitable for about:blank when it compares process locks.
  // Renderer-initiated navigations will handle about:blank navigations
  // elsewhere and leave them in the source SiteInstance, along with
  // about:srcdoc and data:.
  if (url.IsAboutBlank() && !site_info_.is_error_page())
    return true;

  // The is_sandboxed flags and unique_sandbox_ids must match for this to be a
  // suitable SiteInstance.
  if (!SandboxConfigurationsMatch(GetSiteInfo(), url_info))
    return false;

  // If the site URL is an extension (e.g., for hosted apps or WebUI) but the
  // process is not (or vice versa), make sure we notice and fix it.

  // Note: This call must return information that is identical to what
  // would be reported in the SiteInstance returned by
  // GetRelatedSiteInstance(url).
  SiteInfo site_info = DeriveSiteInfo(url_info, /* is_related= */ true);

  // If this is a default SiteInstance and the BrowsingInstance gives us a
  // non-default SiteInfo even when we explicitly allow the default SiteInstance
  // to be considered, then |url| does not belong in the same process as this
  // SiteInstance.
  if (IsDefaultSiteInstance() && site_info != site_info_)
    return false;

  // Note that HasProcess() may return true if site_instance_group_->process_ is
  // null, in process-per-site cases where there's an existing process
  // available. We want to use such a process in the IsSuitableHost check, so we
  // may end up assigning process_ in the GetProcess() call below.
  if (!HasProcess()) {
    // If there is no process or site, then this is a new SiteInstance that can
    // be used for anything.
    if (!HasSite())
      return true;

    // If there is no process but there is a site, then the process must have
    // been discarded after we navigated away.  If the SiteInfos match, then it
    // is safe to use this SiteInstance unless it is a guest. Guests are a
    // special case because we need to be consistent with the HasProcess() path
    // and the IsSuitableHost() call below always returns false for guests.
    if (site_info_ == site_info)
      return !IsGuest();

    // If the site URLs do not match, but neither this SiteInstance nor the
    // destination site_url require dedicated processes, then it is safe to use
    // this SiteInstance.
    if (!RequiresDedicatedProcess() &&
        !site_info.RequiresDedicatedProcess(GetIsolationContext())) {
      return true;
    }

    // Otherwise, there's no process, the SiteInfos don't match, and at least
    // one of them requires a dedicated process, so it is not safe to use this
    // SiteInstance.
    return false;
  }

  return RenderProcessHostImpl::IsSuitableHost(
      GetProcess(), GetIsolationContext(), site_info);
}

bool SiteInstanceImpl::RequiresDedicatedProcess() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!has_site_)
    return false;

  return site_info_.RequiresDedicatedProcess(GetIsolationContext());
}

bool SiteInstanceImpl::IsSandboxed() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!has_site_) {
    return false;
  }

  return site_info_.is_sandboxed();
}

void SiteInstanceImpl::IncrementRelatedActiveContentsCount() {
  browsing_instance_->IncrementActiveContentsCount();
}

void SiteInstanceImpl::DecrementRelatedActiveContentsCount() {
  browsing_instance_->DecrementActiveContentsCount();
}

BrowserContext* SiteInstanceImpl::GetBrowserContext() {
  return browsing_instance_->GetBrowserContext();
}

// static
scoped_refptr<SiteInstance> SiteInstance::Create(
    BrowserContext* browser_context) {
  DCHECK(browser_context);
  return SiteInstanceImpl::Create(browser_context);
}

// static
scoped_refptr<SiteInstance> SiteInstance::CreateForURL(
    BrowserContext* browser_context,
    const GURL& url) {
  return SiteInstanceImpl::CreateForURL(browser_context, url);
}

// static
scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
    BrowserContext* browser_context,
    const GURL& url) {
  DCHECK(browser_context);
  return SiteInstanceImpl::CreateForUrlInfo(
      browser_context, UrlInfo(UrlInfoInit(url)), /*is_guest=*/false,
      /*is_fenced=*/false, /*is_fixed_storage_partition=*/false);
}

// static
scoped_refptr<SiteInstance> SiteInstance::CreateForGuest(
    BrowserContext* browser_context,
    const StoragePartitionConfig& partition_config) {
  DCHECK(browser_context);
  return SiteInstanceImpl::CreateForGuest(browser_context, partition_config);
}

// static
scoped_refptr<SiteInstance> SiteInstance::CreateForFixedStoragePartition(
    BrowserContext* browser_context,
    const GURL& url,
    const StoragePartitionConfig& partition_config) {
  CHECK(browser_context);
  return SiteInstanceImpl::CreateForFixedStoragePartition(browser_context, url,
                                                          partition_config);
}

// static
bool SiteInstance::ShouldAssignSiteForURL(const GURL& url) {
  return SiteInstanceImpl::ShouldAssignSiteForUrlInfo(
      UrlInfo(UrlInfoInit(url)));
}

bool SiteInstanceImpl::IsSameSiteWithURL(const GURL& url) {
  return IsSameSiteWithURLInfo(UrlInfo(UrlInfoInit(url)));
}

bool SiteInstanceImpl::IsSameSiteWithURLInfo(const UrlInfo& url_info) {
  const GURL& url = url_info.url;
  if (IsDefaultSiteInstance()) {
    // about:blank URLs should always be considered same site just like they are
    // in IsSameSite().
    if (url.IsAboutBlank())
      return true;

    // Consider |url| the same site if it could be handled by the
    // default SiteInstance and we don't already have a SiteInstance for
    // this URL.
    // TODO(acolwell): Remove HasSiteInstance() call once we have a way to
    // prevent SiteInstances with no site URL from being used for URLs
    // that should be routed to the default SiteInstance.
    DCHECK_EQ(site_info_.site_url(), GetDefaultSiteURL());

    // We're only interested in knowning if we're same-site.
    // WebExposedIsolationInfo should not come into play here so we make them
    // match explicitly.
    UrlInfo updated_url_info = url_info;
    updated_url_info.web_exposed_isolation_info = GetWebExposedIsolationInfo();

    auto site_info = SiteInfo::Create(GetIsolationContext(), updated_url_info);
    return CanBePlacedInDefaultSiteInstanceOrGroup(GetIsolationContext(), url,
                                                   site_info) &&
           !browsing_instance_->HasSiteInstance(site_info);
  }

  return SiteInstanceImpl::IsSameSite(
      GetIsolationContext(), UrlInfo(UrlInfoInit(site_info_.site_url())),
      url_info, true /* should_compare_effective_urls */);
}

bool SiteInstanceImpl::IsGuest() {
  return site_info_.is_guest();
}

bool SiteInstanceImpl::IsFixedStoragePartition() {
  bool is_fixed_storage_partition =
      browsing_instance_->is_fixed_storage_partition();
  if (IsGuest()) {
    CHECK(is_fixed_storage_partition);
  }
  return is_fixed_storage_partition;
}

bool SiteInstanceImpl::IsJitDisabled() {
  return site_info_.is_jit_disabled();
}

bool SiteInstanceImpl::AreV8OptimizationsDisabled() {
  return site_info_.are_v8_optimizations_disabled();
}

bool SiteInstanceImpl::IsPdf() {
  return site_info_.is_pdf();
}

const StoragePartitionConfig& SiteInstanceImpl::GetStoragePartitionConfig() {
  if (!has_site_) {
    // Note: `site_info_` has not been set yet. This is ok as long as the
    // StoragePartition of this SiteInstance does not change when `site_info_`
    // is actually set. Enable the verification code in SetSiteInfoInternal()
    // to verify that the storage partition info does not change.
    verify_storage_partition_info_ = true;
  }
  return site_info_.storage_partition_config();
}

std::string SiteInstanceImpl::GetPartitionDomain(
    StoragePartitionImpl* storage_partition) {
  auto storage_partition_config = GetStoragePartitionConfig();

  // The DCHECK here is to allow the trybots to detect any attempt to introduce
  // new code that violates this assumption.
  DCHECK_EQ(storage_partition->GetPartitionDomain(),
            storage_partition_config.partition_domain());

  if (storage_partition->GetPartitionDomain() !=
      storage_partition_config.partition_domain()) {
    // Trigger crash logging if we encounter a case that violates our
    // assumptions.
    SCOPED_CRASH_KEY_STRING256("GetPartitionDomain", "domain",
                               storage_partition->GetPartitionDomain());
    SCOPED_CRASH_KEY_STRING256("GetPartitionDomain", "config_domain_key",
                               storage_partition_config.partition_domain());

    base::debug::DumpWithoutCrashing();

    // Return the value from the config to preserve legacy behavior until we
    // can land a fix.
    return storage_partition_config.partition_domain();
  }
  return storage_partition->GetPartitionDomain();
}

bool SiteInstanceImpl::IsOriginalUrlSameSite(
    const UrlInfo& dest_url_info,
    bool should_compare_effective_urls) {
  if (IsDefaultSiteInstance())
    return IsSameSiteWithURLInfo(dest_url_info);

  // Here we use an |origin_isolation_request| of kNone (done implicitly in the
  // UrlInfoInit constructor) when converting |original_url_| to UrlInfo, since
  // (i) the isolation status of this SiteInstance was determined at the time
  // |original_url_| was set, and in this case it is |dest_url_info| that is
  // currently navigating, and that's where the current isolation request (if
  // any) is stored. Whether or not this SiteInstance has origin isolation is a
  // separate question, and not what the UrlInfo for |original_url_| is supposed
  // to reflect.
  return IsSameSite(GetIsolationContext(), UrlInfo(UrlInfoInit(original_url_)),
                    dest_url_info, should_compare_effective_urls);
}

bool SiteInstanceImpl::IsNavigationSameSite(
    const GURL& last_successful_url,
    const url::Origin& last_committed_origin,
    bool for_outermost_main_frame,
    const UrlInfo& dest_url_info) {
  // The is_sandboxed flags and unique_sandbox_ids must match for this to be a
  // same-site navigation.
  if (!SandboxConfigurationsMatch(GetSiteInfo(), dest_url_info))
    return false;

  // Similarly, do not consider PDF and non-PDF documents to be same-site; they
  // should never share a SiteInstance. See https://crbug.com/359345045.
  if (IsPdf() != dest_url_info.is_pdf) {
    return false;
  }

  const GURL& dest_url = dest_url_info.url;
  BrowserContext* browser_context = GetBrowserContext();

  bool should_compare_effective_urls = ShouldCompareEffectiveURLs(
      browser_context, this, for_outermost_main_frame, dest_url);
  // If IsSuitableForUrlInfo finds a process type mismatch, return false
  // even if |dest_url| is same-site.  (The URL may have been installed as an
  // app since the last time we visited it.)
  //
  // This check must be skipped for certain same-site navigations from a hosted
  // app to non-hosted app, and vice versa, to keep them in the same process
  // due to scripting requirements. Otherwise, this would return false due to
  // a process privilege level mismatch.
  //
  // TODO(alexmos): Skipping this check is dangerous, since other bits in
  // SiteInfo may disqualify the navigation from being same-site, even when a
  // hosted app URL embeds a non-hosted-app same-site URL. Two of these cases,
  // sandboxed frames and PDF, are currently handled explicitly above, and a
  // couple more are handled in the callers of this function, but this should be
  // refactored to more systematically check everything else in SiteInfo. See
  // https://crbug.com/349777779.
  bool should_check_for_wrong_process =
      !IsNavigationAllowedToStayInSameProcessDueToEffectiveURLs(
          browser_context, for_outermost_main_frame, dest_url);
  if (should_check_for_wrong_process && !IsSuitableForUrlInfo(dest_url_info))
    return false;

  // In the common case, we use the last successful URL. Thus, we compare
  // against the last successful commit when deciding whether to swap this time.
  // We convert |last_successful_url| to UrlInfo with |origin_isolation_request|
  // set to kNone (done implicitly in the UrlInfoInit constructor) since it
  // isn't currently navigating.
  if (IsSameSite(GetIsolationContext(),
                 UrlInfo(UrlInfoInit(last_successful_url)), dest_url_info,
                 should_compare_effective_urls)) {
    return true;
  }

  // It is possible that last_successful_url was a nonstandard scheme (for
  // example, "about:blank"). If so, examine the last committed origin to
  // determine the site.
  // Similar to above, convert |last_committed_origin| to UrlInfo with
  // |origin_isolation_request| set to kNone: this is done implicitly in the
  // UrlInfoInit constructor.
  if (!last_committed_origin.opaque() &&
      IsSameSite(GetIsolationContext(),
                 UrlInfo(UrlInfoInit(GURL(last_committed_origin.Serialize()))),
                 dest_url_info, should_compare_effective_urls)) {
    return true;
  }

  // If the last successful URL was "about:blank" with a unique origin (which
  // implies that it was a browser-initiated navigation to "about:blank"), none
  // of the cases above apply, but we should still allow a scenario like
  // foo.com -> about:blank -> foo.com to be treated as same-site, as some
  // tests rely on that behavior.  To accomplish this, compare |dest_url|
  // against the site URL.
  if (last_successful_url.IsAboutBlank() && last_committed_origin.opaque() &&
      IsOriginalUrlSameSite(dest_url_info, should_compare_effective_urls)) {
    return true;
  }

  // Not same-site.
  return false;
}

bool SiteInstanceImpl::IsNavigationAllowedToStayInSameProcessDueToEffectiveURLs(
    BrowserContext* browser_context,
    bool for_outermost_main_frame,
    const GURL& dest_url) {
  if (ShouldCompareEffectiveURLs(browser_context, this,
                                 for_outermost_main_frame, dest_url)) {
    return false;
  }

  bool src_has_effective_url = !IsDefaultSiteInstance() &&
                               HasEffectiveURL(browser_context, original_url());
  if (src_has_effective_url)
    return true;
  return HasEffectiveURL(browser_context, dest_url);
}

// static
bool SiteInstanceImpl::IsSameSite(const IsolationContext& isolation_context,
                                  const UrlInfo& real_src_url_info,
                                  const UrlInfo& real_dest_url_info,
                                  bool should_compare_effective_urls) {
  const GURL& real_src_url = real_src_url_info.url;
  const GURL& real_dest_url = real_dest_url_info.url;

  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  BrowserContext* browser_context =
      isolation_context.browser_or_resource_context().ToBrowserContext();
  DCHECK(browser_context);
  DCHECK_NE(real_src_url, GetDefaultSiteURL());

  GURL src_url =
      should_compare_effective_urls
          ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_src_url)
          : real_src_url;
  GURL dest_url =
      should_compare_effective_urls
          ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_dest_url)
          : real_dest_url;

  // We infer web site boundaries based on the registered domain name of the
  // top-level page and the scheme.  We do not pay attention to the port if
  // one is present, because pages served from different ports can still
  // access each other if they change their document.domain variable.

  // Some special URLs will match the site instance of any other URL. This is
  // done before checking both of them for validity, since we want these URLs
  // to have the same site instance as even an invalid one.
  if (blink::IsRendererDebugURL(src_url) || blink::IsRendererDebugURL(dest_url))
    return true;

  // If either URL is invalid, they aren't part of the same site.
  if (!src_url.is_valid() || !dest_url.is_valid())
    return false;

  // To be same-site they must have the same `is_sandbox` flag.
  if (real_src_url_info.is_sandboxed != real_dest_url_info.is_sandboxed)
    return false;

  // If the destination url is just a blank page, we treat them as part of the
  // same site.
  if (dest_url.IsAboutBlank()) {
    // TODO(crbug.com/40266169): It's actually possible for the
    // about:blank page to inherit an origin that doesn't match `src_origin`. In
    // that case we shouldn't treat it as same-site. Consider changing this
    // behavior if all tests can pass.
    return true;
  }

  // If the source and destination URLs are equal excluding the hash, they have
  // the same site.  This matters for file URLs, where SameDomainOrHost() would
  // otherwise return false below.
  if (src_url.EqualsIgnoringRef(dest_url))
    return true;

  url::Origin src_origin = url::Origin::Create(src_url);
  url::Origin dest_origin = url::Origin::Create(dest_url);

  // If the schemes differ, they aren't part of the same site.
  if (src_origin.scheme() != dest_origin.scheme())
    return false;

  // Rely on an origin comparison if StrictOriginIsolation is enabled for all
  // URLs, or if we're comparing against a sandboxed iframe in a per-origin
  // mode. Due to an earlier check, at this point
  // `real_src_url_info.is_sandboxed` and `real_dest_url_info.is_sandboxed` are
  // known to have the same value.
  if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() ||
      (real_src_url_info.is_sandboxed &&
       blink::features::kIsolateSandboxedIframesGroupingParam.Get() ==
           blink::features::IsolateSandboxedIframesGrouping::kPerOrigin)) {
    return src_origin == dest_origin;
  }

  if (!net::registry_controlled_domains::SameDomainOrHost(
          src_origin, dest_origin,
          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
    return false;
  }

  // If the sites are the same, check isolated origins.  If either URL matches
  // an isolated origin, compare origins rather than sites.  As an optimization
  // to avoid unneeded isolated origin lookups, shortcut this check if the two
  // origins are the same.
  if (src_origin == dest_origin)
    return true;

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  url::Origin src_isolated_origin;
  url::Origin dest_isolated_origin;
  bool src_origin_is_isolated = policy->GetMatchingProcessIsolatedOrigin(
      isolation_context, src_origin,
      real_src_url_info.RequestsOriginKeyedProcess(isolation_context),
      &src_isolated_origin);
  bool dest_origin_is_isolated = policy->GetMatchingProcessIsolatedOrigin(
      isolation_context, dest_origin,
      real_dest_url_info.RequestsOriginKeyedProcess(isolation_context),
      &dest_isolated_origin);
  if (src_origin_is_isolated || dest_origin_is_isolated) {
    // Compare most specific matching origins to ensure that a subdomain of an
    // isolated origin (e.g., https://subdomain.isolated.foo.com) also matches
    // the isolated origin's site URL (e.g., https://isolated.foo.com).
    return src_isolated_origin == dest_isolated_origin;
  }

  return true;
}

bool SiteInstanceImpl::DoesSiteInfoForURLMatch(const UrlInfo& url_info) {
  // We want to compare this SiteInstance's SiteInfo to the SiteInfo that would
  // be generated by the passed in UrlInfo. For them to match, the
  // WebExposedIsolationInfo must be compatible.
  if (!WebExposedIsolationInfo::AreCompatible(
          url_info.web_exposed_isolation_info, GetWebExposedIsolationInfo())) {
    return false;
  }

  // Similarly, the CrossOriginIsolationKeys should match.
  if (GetSiteInfo().agent_cluster_key().GetCrossOriginIsolationKey() !=
      url_info.cross_origin_isolation_key) {
    return false;
  }

  // If the passed in UrlInfo has a null WebExposedIsolationInfo, meaning that
  // it is compatible with any isolation state, we reuse the isolation state of
  // this SiteInstance's SiteInfo so the member comparison of SiteInfos will
  // match.
  UrlInfo updated_url_info = url_info;
  updated_url_info.web_exposed_isolation_info =
      site_info_.web_exposed_isolation_info();

  auto site_info = SiteInfo::Create(GetIsolationContext(), updated_url_info);
  if (!ShouldUseDefaultSiteInstanceGroup() &&
      kCreateForURLAllowsDefaultSiteInstance &&
      CanBePlacedInDefaultSiteInstanceOrGroup(GetIsolationContext(),
                                              url_info.url, site_info)) {
    site_info = SiteInfo::CreateForDefaultSiteInstance(
        GetIsolationContext(), site_info.storage_partition_config(),
        GetWebExposedIsolationInfo(),
        site_info.agent_cluster_key().GetCrossOriginIsolationKey());
  }

  return site_info_.IsExactMatch(site_info);
}

void SiteInstanceImpl::RegisterAsDefaultOriginIsolation(
    const url::Origin& previously_visited_origin) {
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  policy->AddDefaultIsolatedOriginIfNeeded(
      GetIsolationContext(), previously_visited_origin,
      true /* is_global_walk_or_frame_removal */);
}

// static
bool SiteInstanceImpl::CanBePlacedInDefaultSiteInstanceOrGroup(
    const IsolationContext& isolation_context,
    const GURL& url,
    const SiteInfo& site_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Empty URLs, like the initial empty document, should not be placed in the
  // default SiteInstance or group. The initial empty document's SiteInstance
  // can be reused, including for navigations to isolated sites. Avoid the case
  // where a SiteInstance or group set as the default can then become isolated.
  if (url.is_empty()) {
    return false;
  }

  // Exclude "file://" URLs from the default SiteInstance to prevent the
  // default SiteInstance/Group process from accumulating file access grants
  // that could be exploited by other non-isolated sites.
  if (url.SchemeIs(url::kFileScheme))
    return false;

  // Don't use the default SiteInstance/Group when SiteInstance doesn't assign a
  // site URL for |url|, since in that case the SiteInstance should remain
  // unused, and a subsequent navigation should always be able to reuse it,
  // whether or not it's to a site requiring a dedicated process or to a site
  // that will use the default SiteInstance/Group.
  if (!ShouldAssignSiteForURL(url))
    return false;

  // Allow the default SiteInstance to be used for sites that don't need to be
  // isolated in their own process.
  return !site_info.RequiresDedicatedProcess(isolation_context);
}

// static
GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
                                       const GURL& url) {
  DCHECK(browser_context);
  return GetContentClient()
      ->browser()
      ->GetEffectiveURL(browser_context, url)
      .value_or(url);
}

// static
bool SiteInstanceImpl::HasEffectiveURL(BrowserContext* browser_context,
                                       const GURL& url) {
  return GetEffectiveURL(browser_context, url) != url;
}

void SiteInstanceImpl::LockProcessIfNeeded() {
  TRACE_EVENT("navigation", "SiteInstanceImpl::LockProcessIfNeeded",
              ChromeTrackEvent::kSiteInstance, this);
  RenderProcessHost* process = site_instance_group_->process();
  ChildProcessSecurityPolicyImpl* policy =
      ChildProcessSecurityPolicyImpl::GetInstance();
  ProcessLock process_lock = process->GetProcessLock();
  StoragePartitionImpl* storage_partition =
      static_cast<StoragePartitionImpl*>(process->GetStoragePartition());
  if (!has_site_) {
    CHECK(!process_lock.IsLockedToSite())
        << "A process that's already locked to " << process_lock.ToString()
        << " cannot be updated to a more permissive lock";
    // Update the process lock state to signal that the process has been
    // associated with a SiteInstance that is not locked to a site yet.  Note
    // that even if the process lock is already set to a lock that allows any
    // site, we still need to notify ChildProcessSecurityPolicy about the
    // current SiteInstance's IsolationContext, so that the corresponding
    // BrowsingInstance can be associated with |process_|.  See
    // https://crbug.com/1135539.
    // Note that the CrossOriginIsolationKey passed here is null because a
    // non-assigned SiteInstance cannot have non-default COOP/COEP/DIP values.
    if (process_lock.is_invalid()) {
      auto new_process_lock = ProcessLock::CreateAllowAnySite(
          storage_partition->GetConfig(), GetWebExposedIsolationInfo(),
          /*cross_origin_isolation_key=*/std::nullopt);
      process->SetProcessLock(GetIsolationContext(), new_process_lock);
    } else {
      CHECK(process_lock.AllowsAnySite())
          << "Unexpected process lock " << process_lock.ToString();
      policy->IncludeIsolationContext(process->GetDeprecatedID(),
                                      GetIsolationContext());
    }
    return;
  }

  DCHECK(HasSite());
  DCHECK_EQ(storage_partition->GetConfig(),
            site_info_.storage_partition_config());

  if (site_info_.ShouldLockProcessToSite(GetIsolationContext())) {
    ProcessLock lock_to_set = ProcessLock::FromSiteInfo(GetSiteInfo());
    if (!process_lock.IsLockedToSite()) {
      // TODO(nick): When all sites are isolated, this operation provides
      // strong protection. If only some sites are isolated, we need
      // additional logic to prevent the non-isolated sites from requesting
      // resources for isolated sites. https://crbug.com/509125
      TRACE_EVENT_INSTANT(
          "navigation",
          "SiteInstanceImpl::LockProcessIfNeeded_set_process_lock", "lock",
          lock_to_set.ToString());
      process->SetProcessLock(GetIsolationContext(), lock_to_set);
    } else if (process_lock != lock_to_set) {
      // We should never attempt to reassign a different origin lock to a
      // process.
      base::debug::SetCrashKeyString(bad_message::GetRequestedSiteInfoKey(),
                                     site_info_.GetDebugString());
      policy->LogKilledProcessOriginLock(process->GetDeprecatedID());
      NOTREACHED() << "Trying to lock a process to " << lock_to_set.ToString()
                   << " but the process is already locked to "
                   << process_lock.ToString();
    } else {
      // Process already has the right origin lock assigned.  This case will
      // happen for commits to |site_info_| after the first one.
    }
  } else {
    if (process_lock.IsLockedToSite()) {
      // The site that we're committing doesn't require a dedicated
      // process, but it has been put in a process for a site that does.
      base::debug::SetCrashKeyString(bad_message::GetRequestedSiteInfoKey(),
                                     site_info_.GetDebugString());
      policy->LogKilledProcessOriginLock(process->GetDeprecatedID());
      NOTREACHED() << "Trying to commit non-isolated site " << site_info_
                   << " in process locked to " << process_lock.ToString();
    } else if (process_lock.is_invalid()) {
      // Update the process lock state to signal that the process has been
      // associated with a SiteInstance that is not locked to a site yet.
      // TODO(crbug.com/342365083): When COOP and COEP transition to using
      // CrossOriginIsolationKeys, pass the CrossOriginIsolationKey shared by
      // all documents in the Browsing Instance with COOP and COEP.
      auto new_process_lock = ProcessLock::CreateAllowAnySite(
          storage_partition->GetConfig(), GetWebExposedIsolationInfo(),
          /*cross_origin_isolation_key=*/std::nullopt);
      process->SetProcessLock(GetIsolationContext(), new_process_lock);
    } else {
      CHECK(process_lock.AllowsAnySite())
          << "Unexpected process lock " << process_lock.ToString();
    }
  }

  // From now on, this process should be considered "tainted" for future
  // process reuse decisions:
  // (1) If |site_info_| required a dedicated process, this SiteInstance's
  //     process can only host URLs for the same site.
  // (2) Even if |site_info_| does not require a dedicated process, this
  //     SiteInstance's process still cannot be reused to host other sites
  //     requiring dedicated sites in the future.
  // We can get here either when we commit a URL into a SiteInstance that does
  // not yet have a site, or when we create a process for a SiteInstance with a
  // preassigned site.
  process->SetIsUsed();

  // Track which isolation contexts use the given process.  This lets
  // ChildProcessSecurityPolicyImpl (e.g. CanAccessDataForOrigin) determine
  // whether a given URL should require a lock or not (a dynamically isolated
  // origin may require a lock in some isolation contexts but not in others).
  policy->IncludeIsolationContext(process->GetDeprecatedID(),
                                  GetIsolationContext());
}

const WebExposedIsolationInfo& SiteInstanceImpl::GetWebExposedIsolationInfo()
    const {
  return browsing_instance_->web_exposed_isolation_info();
}

bool SiteInstanceImpl::IsCrossOriginIsolated() const {
  return GetWebExposedIsolationInfo().is_isolated() ||
         site_info_.agent_cluster_key().IsCrossOriginIsolated();
}

// static
void SiteInstance::StartIsolatingSite(
    BrowserContext* context,
    const GURL& url,
    ChildProcessSecurityPolicy::IsolatedOriginSource source,
    bool should_persist) {
  if (!SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
    return;

  // Ignore attempts to isolate origins that are not supported.  Do this here
  // instead of relying on AddFutureIsolatedOrigins()'s internal validation, to
  // avoid the runtime warning generated by the latter.
  url::Origin origin(url::Origin::Create(url));
  if (!IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
    return;

  // Convert |url| to a site, to avoid breaking document.domain.  Note that
  // this doesn't use effective URL resolution or other special cases from
  // GetSiteForURL() and simply converts |origin| to a scheme and eTLD+1.
  GURL site(SiteInfo::GetSiteForOrigin(origin));

  ChildProcessSecurityPolicyImpl* policy =
      ChildProcessSecurityPolicyImpl::GetInstance();
  url::Origin site_origin(url::Origin::Create(site));
  policy->AddFutureIsolatedOrigins({site_origin}, source, context);

  // This function currently assumes the new isolated site should persist
  // across restarts, so ask the embedder to save it, excluding off-the-record
  // profiles.
  if (!context->IsOffTheRecord() && should_persist) {
    GetContentClient()->browser()->PersistIsolatedOrigin(context, site_origin,
                                                         source);
  }
}

void SiteInstanceImpl::WriteIntoTrace(
    perfetto::TracedProto<perfetto::protos::pbzero::SiteInstance> proto) {
  proto->set_site_instance_id(GetId().value());
  proto->set_browsing_instance_id(GetBrowsingInstanceId().value());
  proto->set_is_default(IsDefaultSiteInstance());
  proto->set_has_process(HasProcess());
  proto->set_related_active_contents_count(GetRelatedActiveContentsCount());

  proto.Set(TraceProto::kSiteInstanceGroup, group());
  if (group()) {
    proto->set_active_rfh_count(site_instance_group_->active_frame_count());
  }

  perfetto::TracedDictionary dict = std::move(proto).AddDebugAnnotations();
  dict.Add("site_info", site_info_);
}

int SiteInstanceImpl::EstimateOriginAgentClusterOverheadForMetrics() {
  return browsing_instance_->EstimateOriginAgentClusterOverhead();
}

scoped_refptr<SiteInstanceImpl>
SiteInstanceImpl::GetCompatibleSandboxedSiteInstance(
    const UrlInfo& url_info,
    const url::Origin& parent_origin) {
  DCHECK(!IsDefaultSiteInstance());
  DCHECK(has_site_);
  DCHECK(!GetSiteInfo().is_sandboxed());
  DCHECK(url_info.url.IsAboutSrcdoc());

  UrlInfo sandboxed_url_info = url_info;
  // Since the input `url_info` has a srcdoc url, using the url as-is will
  // result in a SiteInfo that's not very specific, so we need something more
  // meaningful. Ideally we'd use the UrlInfo used to load the parent, but we
  // don't have that anymore, so we use the parent's origin which should be
  // close enough. We use GetTupleOrPrecursorTupleIfOpaque in case
  // `parent_origin` is opaque.
  sandboxed_url_info.url =
      parent_origin.GetTupleOrPrecursorTupleIfOpaque().GetURL();
  // The `url_info` should already have its is_sandboxed flag set if we're here.
  DCHECK(sandboxed_url_info.is_sandboxed);
  DCHECK(!sandboxed_url_info.origin);
  // At this point assume all other fields in the input `url_info` are correct.
  auto sandboxed_site_info =
      SiteInfo::Create(GetIsolationContext(), sandboxed_url_info);

  auto result =
      browsing_instance_->GetSiteInstanceForSiteInfo(sandboxed_site_info);
  result->original_url_ = original_url_;
  return result;
}

RenderProcessHost* SiteInstanceImpl::GetDefaultProcessForBrowsingInstance() {
  if (ShouldUseDefaultSiteInstanceGroup()) {
    return browsing_instance_->has_default_site_instance_group()
               ? browsing_instance_->default_site_instance_group()->process()
               : nullptr;
  } else {
    if (SiteInstanceImpl* default_instance =
            browsing_instance_->default_site_instance()) {
      return default_instance->HasProcess() ? default_instance->GetProcess()
                                            : nullptr;
    }
    return nullptr;
  }
}

void SiteInstanceImpl::SetProcessForTesting(RenderProcessHost* process) {
  SetProcessInternal(process);
}

void SiteInstanceImpl::IncrementActiveDocumentCount(
    const SiteInfo& url_derived_site_info) {
  if (url_derived_site_info.site_url().is_empty()) {
    // This can happen when this function is called when destructing an active
    // RenderFrameHost, e.g. on frame detach. In this case, there's no need to
    // increment the count.
    return;
  }
  active_document_counts_[url_derived_site_info]++;
}

void SiteInstanceImpl::DecrementActiveDocumentCount(
    const SiteInfo& url_derived_site_info) {
  if (url_derived_site_info.site_url().is_empty()) {
    // This can happen when this function is called for the initial
    // RenderFrameHost, whose `url_derived_site_info` was never set. In that
    // case, `IncrementActiveDocumentCount()` will never be called and the map
    // won't contain the SiteInfo, so just return early here.
    return;
  }
  auto it = active_document_counts_.find(url_derived_site_info);
  CHECK(it != active_document_counts_.end());
  auto& count = it->second;
  --count;
  if (count == 0) {
    active_document_counts_.erase(url_derived_site_info);
  }
}

size_t SiteInstanceImpl::GetActiveDocumentCount(
    const SiteInfo& url_derived_site_info) {
  if (auto it = active_document_counts_.find(url_derived_site_info);
      it != active_document_counts_.end()) {
    return it->second;
  }
  return 0;
}

}  // namespace content
