blob: 9589e49c1fde5115cd4c33d2f4cc513c80da3905 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/resource_coordinator/session_restore_policy.h"
#include "base/no_destructor.h"
#include "base/system/sys_info.h"
#include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
namespace resource_coordinator {
namespace {
class SysInfoDelegate : public SessionRestorePolicy::Delegate {
public:
SysInfoDelegate() {}
~SysInfoDelegate() override {}
size_t GetNumberOfCores() const override {
return base::SysInfo::NumberOfProcessors();
}
size_t GetFreeMemoryMiB() const override {
constexpr int64_t kMibibytesInBytes = 1 << 20;
int64_t free_mem =
base::SysInfo::AmountOfAvailablePhysicalMemory() / kMibibytesInBytes;
DCHECK(free_mem >= 0);
return free_mem;
}
base::TimeTicks NowTicks() const override { return base::TimeTicks::Now(); }
size_t GetSiteEngagementScore(content::WebContents* contents) const override {
// Get the active navigation entry. Restored tabs should always have one.
auto& controller = contents->GetController();
auto* nav_entry =
controller.GetEntryAtIndex(controller.GetCurrentEntryIndex());
DCHECK(nav_entry);
auto* engagement_svc = SiteEngagementService::Get(
Profile::FromBrowserContext(contents->GetBrowserContext()));
double engagement =
engagement_svc->GetDetails(nav_entry->GetURL()).total_score;
// Return the engagement as an integer.
return engagement;
}
static SysInfoDelegate* Get() {
static base::NoDestructor<SysInfoDelegate> delegate;
return delegate.get();
}
};
} // namespace
SessionRestorePolicy::SessionRestorePolicy()
: policy_enabled_(
base::FeatureList::IsEnabled(features::kInfiniteSessionRestore)),
delegate_(SysInfoDelegate::Get()),
parsed_params_(GetInfiniteSessionRestoreParams()),
params_(&parsed_params_),
simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
SessionRestorePolicy::~SessionRestorePolicy() = default;
bool SessionRestorePolicy::ShouldLoad(content::WebContents* contents) const {
// If the policy is disabled then always return true.
if (!policy_enabled_)
return true;
if (tab_loads_started_ < params_->min_tabs_to_restore)
return true;
if (params_->max_tabs_to_restore != 0 &&
tab_loads_started_ >= params_->max_tabs_to_restore) {
return false;
}
// If there is a free memory constraint then enforce it.
if (params_->mb_free_memory_per_tab_to_restore != 0) {
size_t free_mem_mb = delegate_->GetFreeMemoryMiB();
if (free_mem_mb < params_->mb_free_memory_per_tab_to_restore)
return false;
}
// Enforce a max time since use if one is specified.
if (!params_->max_time_since_last_use_to_restore.is_zero()) {
base::TimeDelta time_since_active =
delegate_->NowTicks() - contents->GetLastActiveTime();
if (time_since_active > params_->max_time_since_last_use_to_restore)
return false;
}
// Enforce a minimum site engagement score.
if (delegate_->GetSiteEngagementScore(contents) <
params_->min_site_engagement_to_restore) {
return false;
}
return true;
}
void SessionRestorePolicy::NotifyTabLoadStarted() {
++tab_loads_started_;
}
SessionRestorePolicy::SessionRestorePolicy(
bool policy_enabled,
const Delegate* delegate,
const InfiniteSessionRestoreParams* params)
: policy_enabled_(policy_enabled),
delegate_(delegate),
params_(params),
simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
// static
size_t SessionRestorePolicy::CalculateSimultaneousTabLoads(
size_t min_loads,
size_t max_loads,
size_t cores_per_load,
size_t num_cores) {
DCHECK(max_loads == 0 || min_loads <= max_loads);
DCHECK(num_cores > 0);
size_t loads = 0;
// Setting |cores_per_load| == 0 means that no per-core limit is applied.
if (cores_per_load == 0) {
loads = std::numeric_limits<size_t>::max();
} else {
loads = num_cores / cores_per_load;
}
// If |max_loads| isn't zero then apply the maximum that it implies.
if (max_loads != 0)
loads = std::min(loads, max_loads);
loads = std::max(loads, min_loads);
return loads;
}
size_t SessionRestorePolicy::CalculateSimultaneousTabLoadsFromParams() const {
// If the policy is disabled then there are no limits on the simultaneous tab
// loads.
if (!policy_enabled_)
return std::numeric_limits<size_t>::max();
return CalculateSimultaneousTabLoads(
params_->min_simultaneous_tab_loads, params_->max_simultaneous_tab_loads,
params_->cores_per_simultaneous_tab_load, delegate_->GetNumberOfCores());
}
void SessionRestorePolicy::SetTabLoadsStartedForTesting(
size_t tab_loads_started) {
tab_loads_started_ = tab_loads_started;
}
SessionRestorePolicy::Delegate::Delegate() {}
SessionRestorePolicy::Delegate::~Delegate() {}
} // namespace resource_coordinator