blob: a05e328eb168e0585f27652381f9cd216e12f2ee [file] [log] [blame]
// Copyright (c) 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/content_navigation_policy.h"
#include <bitset>
#include "base/command_line.h"
#include "base/metrics/field_trial_params.h"
#include "base/system/sys_info.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
namespace content {
bool DeviceHasEnoughMemoryForBackForwardCache() {
// This method make sure that the physical memory of device is greater than
// the allowed threshold and enables back-forward cache if the feature
// kBackForwardCacheMemoryControl is enabled.
// It is important to check the base::FeatureList to avoid activating any
// field trial groups if BFCache is disabled due to memory threshold.
if (base::FeatureList::IsEnabled(features::kBackForwardCacheMemoryControl)) {
int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
features::kBackForwardCacheMemoryControl,
"memory_threshold_for_back_forward_cache_in_mb", 0);
return base::SysInfo::AmountOfPhysicalMemoryMB() > memory_threshold_mb;
}
// If the feature kBackForwardCacheMemoryControl is not enabled, all the
// devices are included by default.
return true;
}
bool IsBackForwardCacheDisabledByCommandLine() {
if (base::CommandLine::InitializedForCurrentProcess() &&
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableBackForwardCache)) {
return true;
}
return false;
}
bool IsBackForwardCacheEnabled() {
if (!DeviceHasEnoughMemoryForBackForwardCache())
return false;
if (IsBackForwardCacheDisabledByCommandLine())
return false;
// The feature needs to be checked last, because checking the feature
// activates the field trial and assigns the client either to a control or an
// experiment group - such assignment should be final.
return base::FeatureList::IsEnabled(features::kBackForwardCache);
}
bool IsSameSiteBackForwardCacheEnabled() {
if (!IsBackForwardCacheEnabled())
return false;
static constexpr base::FeatureParam<bool> enable_same_site_back_forward_cache(
&features::kBackForwardCache, "enable_same_site", false);
return enable_same_site_back_forward_cache.Get();
}
bool ShouldSkipSameSiteBackForwardCacheForPageWithUnload() {
if (!IsSameSiteBackForwardCacheEnabled())
return true;
static constexpr base::FeatureParam<bool> skip_same_site_if_unload_exists(
&features::kBackForwardCache, "skip_same_site_if_unload_exists", false);
return skip_same_site_if_unload_exists.Get();
}
bool CanCrossSiteNavigationsProactivelySwapBrowsingInstances() {
return IsProactivelySwapBrowsingInstanceEnabled() ||
IsBackForwardCacheEnabled();
}
const char kProactivelySwapBrowsingInstanceLevelParameterName[] = "level";
constexpr base::FeatureParam<ProactivelySwapBrowsingInstanceLevel>::Option
proactively_swap_browsing_instance_levels[] = {
{ProactivelySwapBrowsingInstanceLevel::kDisabled, "Disabled"},
{ProactivelySwapBrowsingInstanceLevel::kCrossSiteSwapProcess,
"CrossSiteSwapProcess"},
{ProactivelySwapBrowsingInstanceLevel::kCrossSiteReuseProcess,
"CrossSiteReuseProcess"},
{ProactivelySwapBrowsingInstanceLevel::kSameSite, "SameSite"}};
const base::FeatureParam<ProactivelySwapBrowsingInstanceLevel>
proactively_swap_browsing_instance_level{
&features::kProactivelySwapBrowsingInstance,
kProactivelySwapBrowsingInstanceLevelParameterName,
ProactivelySwapBrowsingInstanceLevel::kDisabled,
&proactively_swap_browsing_instance_levels};
std::string GetProactivelySwapBrowsingInstanceLevelName(
ProactivelySwapBrowsingInstanceLevel level) {
return proactively_swap_browsing_instance_level.GetName(level);
}
std::array<std::string,
static_cast<size_t>(ProactivelySwapBrowsingInstanceLevel::kMaxValue)>
ProactivelySwapBrowsingInstanceFeatureEnabledLevelValues() {
return {
GetProactivelySwapBrowsingInstanceLevelName(
ProactivelySwapBrowsingInstanceLevel::kCrossSiteSwapProcess),
GetProactivelySwapBrowsingInstanceLevelName(
ProactivelySwapBrowsingInstanceLevel::kCrossSiteReuseProcess),
GetProactivelySwapBrowsingInstanceLevelName(
ProactivelySwapBrowsingInstanceLevel::kSameSite),
};
}
ProactivelySwapBrowsingInstanceLevel GetProactivelySwapBrowsingInstanceLevel() {
if (base::FeatureList::IsEnabled(features::kProactivelySwapBrowsingInstance))
return proactively_swap_browsing_instance_level.Get();
return ProactivelySwapBrowsingInstanceLevel::kDisabled;
}
bool IsProactivelySwapBrowsingInstanceEnabled() {
return GetProactivelySwapBrowsingInstanceLevel() >=
ProactivelySwapBrowsingInstanceLevel::kCrossSiteSwapProcess;
}
bool IsProactivelySwapBrowsingInstanceWithProcessReuseEnabled() {
return GetProactivelySwapBrowsingInstanceLevel() >=
ProactivelySwapBrowsingInstanceLevel::kCrossSiteReuseProcess;
}
bool IsProactivelySwapBrowsingInstanceOnSameSiteNavigationEnabled() {
return GetProactivelySwapBrowsingInstanceLevel() >=
ProactivelySwapBrowsingInstanceLevel::kSameSite;
}
const char kRenderDocumentLevelParameterName[] = "level";
constexpr base::FeatureParam<RenderDocumentLevel>::Option
render_document_levels[] = {
{RenderDocumentLevel::kCrashedFrame, "crashed-frame"},
{RenderDocumentLevel::kSubframe, "subframe"}};
const base::FeatureParam<RenderDocumentLevel> render_document_level{
&features::kRenderDocument, kRenderDocumentLevelParameterName,
RenderDocumentLevel::kCrashedFrame, &render_document_levels};
RenderDocumentLevel GetRenderDocumentLevel() {
if (base::FeatureList::IsEnabled(features::kRenderDocument))
return render_document_level.Get();
return RenderDocumentLevel::kCrashedFrame;
}
std::string GetRenderDocumentLevelName(RenderDocumentLevel level) {
return render_document_level.GetName(level);
}
bool ShouldCreateNewHostForSameSiteSubframe() {
return GetRenderDocumentLevel() >= RenderDocumentLevel::kSubframe;
}
} // namespace content