1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
// Copyright 2020 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/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 "build/build_config.h"
#include "content/common/features.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "net/base/features.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
// kBackForwardCacheMemoryControls 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::kBackForwardCacheMemoryControls)) {
// On Android, BackForwardCache is enabled for devices with 1200MB memory or
// above.
int default_memory_threshold_mb =
#if BUILDFLAG(IS_ANDROID)
1200;
#else
// Desktop has lower memory limitations compared to Android allowing us
// to enable BackForwardCache for all devices.
0;
#endif
int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
features::kBackForwardCacheMemoryControls,
"memory_threshold_for_back_forward_cache_in_mb",
default_memory_threshold_mb);
return base::SysInfo::AmountOfPhysicalMemoryMB() > memory_threshold_mb;
}
// If the feature kBackForwardCacheMemoryControls 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() {
bool has_enough_memory = DeviceHasEnoughMemoryForBackForwardCache();
if (!has_enough_memory) {
// When the device does not have enough memory for BackForwardCache, return
// false so we won't try to put things in the back/forward cache.
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. This allows us to keep
// the BackForwardCache field trial to include only devices that have enough
// memory for BackForwardCache, and those devices only.
if (base::FeatureList::IsEnabled(features::kBackForwardCache)) {
// When the device does have enough memory for BackForwardCache, return
// true so we won't try to put things in the back/forward cache.
return true;
}
return false;
}
bool CanCrossSiteNavigationsProactivelySwapBrowsingInstances() {
return IsBackForwardCacheEnabled();
}
const char kRenderDocumentLevelParameterName[] = "level";
constexpr base::FeatureParam<RenderDocumentLevel>::Option
render_document_levels[] = {
{RenderDocumentLevel::kCrashedFrame, "crashed-frame"},
{RenderDocumentLevel::kNonLocalRootSubframe, "non-local-root-subframe"},
{RenderDocumentLevel::kSubframe, "subframe"},
{RenderDocumentLevel::kAllFrames, "all-frames"}};
const base::FeatureParam<RenderDocumentLevel> render_document_level{
&features::kRenderDocument, kRenderDocumentLevelParameterName,
RenderDocumentLevel::kSubframe, &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 ShouldCreateNewRenderFrameHostOnSameSiteNavigation(
bool is_main_frame,
bool is_local_root,
bool has_committed_any_navigation,
bool must_be_replaced) {
if (must_be_replaced) {
return true;
}
if (!has_committed_any_navigation) {
return false;
}
RenderDocumentLevel level = GetRenderDocumentLevel();
if (is_main_frame) {
CHECK(is_local_root);
return level >= RenderDocumentLevel::kAllFrames;
}
if (is_local_root) {
return level >= RenderDocumentLevel::kSubframe;
}
return level >= RenderDocumentLevel::kNonLocalRootSubframe;
}
bool ShouldCreateNewHostForAllFrames() {
return GetRenderDocumentLevel() >= RenderDocumentLevel::kAllFrames;
}
bool ShouldSkipEarlyCommitPendingForCrashedFrame() {
static bool skip_early_commit_pending_for_crashed_frame =
base::FeatureList::IsEnabled(
features::kSkipEarlyCommitPendingForCrashedFrame);
return skip_early_commit_pending_for_crashed_frame;
}
static constexpr base::FeatureParam<NavigationQueueingFeatureLevel>::Option
kNavigationQueueingFeatureLevels[] = {
{NavigationQueueingFeatureLevel::kNone, "none"},
{NavigationQueueingFeatureLevel::kAvoidRedundantCancellations,
"avoid-redundant"},
{NavigationQueueingFeatureLevel::kFull, "full"}};
const base::FeatureParam<NavigationQueueingFeatureLevel>
kNavigationQueueingFeatureLevelParam{
&features::kQueueNavigationsWhileWaitingForCommit, "queueing_level",
NavigationQueueingFeatureLevel::kFull,
&kNavigationQueueingFeatureLevels};
NavigationQueueingFeatureLevel GetNavigationQueueingFeatureLevel() {
if (GetRenderDocumentLevel() >= RenderDocumentLevel::kNonLocalRootSubframe) {
// When RenderDocument is enabled with a level of "non-local-root-subframe"
// or more, navigation queueing needs to be enabled too, to avoid crashes.
return NavigationQueueingFeatureLevel::kFull;
}
if (base::FeatureList::IsEnabled(
features::kQueueNavigationsWhileWaitingForCommit)) {
return kNavigationQueueingFeatureLevelParam.Get();
}
return NavigationQueueingFeatureLevel::kNone;
}
bool ShouldAvoidRedundantNavigationCancellations() {
return GetNavigationQueueingFeatureLevel() >=
NavigationQueueingFeatureLevel::kAvoidRedundantCancellations;
}
bool ShouldQueueNavigationsWhenPendingCommitRFHExists() {
return GetNavigationQueueingFeatureLevel() ==
NavigationQueueingFeatureLevel::kFull;
}
bool ShouldCreateSiteInstanceForDataUrls() {
return base::FeatureList::IsEnabled(features::kSiteInstanceGroupsForDataUrls);
}
bool ShouldUseDefaultSiteInstanceGroup() {
return base::FeatureList::IsEnabled(features::kDefaultSiteInstanceGroups);
}
} // namespace content
|