blob: e871e3b12f66fe306f90d9168585b14c57d6e137 [file] [log] [blame]
// Copyright 2023 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/coop_related_group.h"
#include "content/browser/browsing_instance.h"
#include "content/browser/site_instance_impl.h"
#include "base/logging.h"
namespace content {
// Start the CoopRelatedGroup ID counter from 1 to avoid a conflict with the
// invalid CoopRelatedGroupId value, which is 0 in its underlying IdType32.
int CoopRelatedGroup::next_coop_related_group_id_ = 1;
CoopRelatedGroup::CoopRelatedGroup(BrowserContext* browser_context,
bool is_guest,
bool is_fenced)
: id_(CoopRelatedGroupId::FromUnsafeValue(next_coop_related_group_id_++)),
browser_context_(browser_context),
is_guest_(is_guest),
is_fenced_(is_fenced) {}
CoopRelatedGroup::~CoopRelatedGroup() = default;
CoopRelatedGroupId CoopRelatedGroup::GetId() {
return id_;
}
scoped_refptr<BrowsingInstance>
CoopRelatedGroup::FindSuitableBrowsingInstanceForCoopPolicy(
const absl::optional<url::Origin>& common_coop_origin,
const WebExposedIsolationInfo& web_exposed_isolation_info) {
for (BrowsingInstance* current_browsing_instance :
coop_related_browsing_instances_) {
// Note: We don't need to know if the common_coop_origin value is the result
// of COOP: same-origin or COOP: restrict-properties. We will only ever
// reach this function when doing a swap within the CoopRelatedGroup, so it
// is necessarily for COOP: restrict-properties. WebExposedIsolationInfo is
// used to know if COEP was set together with it or not.
if ((current_browsing_instance->common_coop_origin() ==
common_coop_origin) &&
(current_browsing_instance->web_exposed_isolation_info() ==
web_exposed_isolation_info)) {
return base::WrapRefCounted<BrowsingInstance>(current_browsing_instance);
}
}
return nullptr;
}
scoped_refptr<BrowsingInstance>
CoopRelatedGroup::GetOrCreateBrowsingInstanceForCoopPolicy(
const absl::optional<url::Origin>& common_coop_origin,
const WebExposedIsolationInfo& web_exposed_isolation_info) {
scoped_refptr<BrowsingInstance> browsing_instance =
FindSuitableBrowsingInstanceForCoopPolicy(common_coop_origin,
web_exposed_isolation_info);
if (browsing_instance.get()) {
return browsing_instance;
}
return base::WrapRefCounted<BrowsingInstance>(new BrowsingInstance(
browser_context_, web_exposed_isolation_info, is_guest_, is_fenced_,
base::WrapRefCounted<CoopRelatedGroup>(this), common_coop_origin));
}
void CoopRelatedGroup::RegisterBrowsingInstance(
BrowsingInstance* browsing_instance) {
// We should never register the same BrowsingInstance twice. If that happens,
// we're not reusing the BrowsingInstance via GetBrowsingInstanceForCoop()
// somewhere when we should be doing so.
auto it = find(coop_related_browsing_instances_.begin(),
coop_related_browsing_instances_.end(), browsing_instance);
CHECK(it == coop_related_browsing_instances_.end());
// We should also never record a second BrowsingInstance with the same Policy
// as an existing BrowsingInstance.
scoped_refptr<BrowsingInstance> duplicated_policy_browsing_instance =
FindSuitableBrowsingInstanceForCoopPolicy(
browsing_instance->common_coop_origin(),
browsing_instance->web_exposed_isolation_info());
CHECK(duplicated_policy_browsing_instance.get() == nullptr);
coop_related_browsing_instances_.push_back(browsing_instance);
}
void CoopRelatedGroup::UnregisterBrowsingInstance(
BrowsingInstance* browsing_instance) {
auto it = find(coop_related_browsing_instances_.begin(),
coop_related_browsing_instances_.end(), browsing_instance);
CHECK(it != coop_related_browsing_instances_.end());
coop_related_browsing_instances_.erase(it);
}
scoped_refptr<SiteInstanceImpl>
CoopRelatedGroup::GetCoopRelatedSiteInstanceForURL(const UrlInfo& url_info,
bool allow_default_si) {
// Fenced frames should never be able to request other SiteInstances in the
// same CoopRelatedGroup, as they cannot open popups without noopener and COOP
// is not enforced within the frame.
DCHECK(!is_fenced_);
scoped_refptr<BrowsingInstance> target_browsing_instance =
GetOrCreateBrowsingInstanceForCoopPolicy(
url_info.common_coop_origin,
url_info.web_exposed_isolation_info.value_or(
WebExposedIsolationInfo::CreateNonIsolated()));
return target_browsing_instance->GetSiteInstanceForURL(url_info,
allow_default_si);
}
} // namespace content