blob: a91cfd046d8e3764eb2d6ae90a64e87f8a55baef [file] [log] [blame]
// Copyright 2019 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/site_isolation/site_isolation_policy.h"
#include "base/metrics/histogram_macros.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/site_isolation_policy.h"
// static
bool SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled() {
// If the user has explicitly enabled site isolation for password sites from
// chrome://flags or from the command line, honor this regardless of policies
// that may disable site isolation. In particular, this means that the
// chrome://flags switch for this feature takes precedence over any memory
// threshold restrictions and over a switch for disabling site isolation.
if (base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine(
features::kSiteIsolationForPasswordSites.name,
base::FeatureList::OVERRIDE_ENABLE_FEATURE)) {
return true;
}
// Don't isolate anything when site isolation is turned off by the user or
// policy. This includes things like the switches::kDisableSiteIsolation
// command-line switch, the corresponding "Disable site isolation" entry in
// chrome://flags, enterprise policy controlled via
// switches::kDisableSiteIsolationForPolicy, and memory threshold checks in
// ShouldDisableSiteIsolationDueToMemoryThreshold().
if (!content::SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
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::kSiteIsolationForPasswordSites);
}
// static
bool SiteIsolationPolicy::IsEnterprisePolicyApplicable() {
#if defined(OS_ANDROID)
// https://crbug.com/844118: Limiting policy to devices with > 1GB RAM.
// Using 1077 rather than 1024 because 1) it helps ensure that devices with
// exactly 1GB of RAM won't get included because of inaccuracies or off-by-one
// errors and 2) this is the bucket boundary in Memory.Stats.Win.TotalPhys2.
bool have_enough_memory = base::SysInfo::AmountOfPhysicalMemoryMB() > 1077;
return have_enough_memory;
#else
return true;
#endif
}
// static
bool SiteIsolationPolicy::ShouldDisableSiteIsolationDueToMemoryThreshold() {
// The memory threshold behavior differs for desktop and Android:
// - Android uses a 1900MB default threshold, which is the threshold used by
// password-triggered site isolation - see docs in
// https://crbug.com/849815. This can be overridden via a param defined in
// a kSitePerProcessOnlyForHighMemoryClients field trial.
// - Desktop does not enforce a default memory threshold, but for now we
// still support a threshold defined via a
// kSitePerProcessOnlyForHighMemoryClients field trial. The trial
// typically carries the threshold in a param; if it doesn't, use a default
// that's slightly higher than 1GB (see https://crbug.com/844118).
//
// TODO(alexmos): currently, this threshold applies to all site isolation
// modes. Eventually, we may need separate thresholds for different modes,
// such as full site isolation vs. password-triggered site isolation.
#if defined(OS_ANDROID)
constexpr int kDefaultMemoryThresholdMb = 1900;
#else
constexpr int kDefaultMemoryThresholdMb = 1077;
#endif
// TODO(acolwell): Rename feature since it now affects more than just the
// site-per-process case.
if (base::FeatureList::IsEnabled(
features::kSitePerProcessOnlyForHighMemoryClients)) {
int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
features::kSitePerProcessOnlyForHighMemoryClients,
features::kSitePerProcessOnlyForHighMemoryClientsParamName,
kDefaultMemoryThresholdMb);
return base::SysInfo::AmountOfPhysicalMemoryMB() <= memory_threshold_mb;
}
#if defined(OS_ANDROID)
if (base::SysInfo::AmountOfPhysicalMemoryMB() <= kDefaultMemoryThresholdMb) {
return true;
}
#endif
return false;
}
// static
void SiteIsolationPolicy::ApplyPersistedIsolatedOrigins(Profile* profile) {
// If the user turned off password-triggered isolation, don't apply any
// stored isolated origins, but also don't clear them from prefs, so that
// they can be used if password-triggered isolation is re-enabled later.
if (!IsIsolationForPasswordSitesEnabled())
return;
std::vector<url::Origin> origins;
for (const auto& value :
*profile->GetPrefs()->GetList(prefs::kUserTriggeredIsolatedOrigins)) {
origins.push_back(url::Origin::Create(GURL(value.GetString())));
}
if (!origins.empty()) {
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
using IsolatedOriginSource =
content::ChildProcessSecurityPolicy::IsolatedOriginSource;
policy->AddIsolatedOrigins(origins, IsolatedOriginSource::USER_TRIGGERED,
/* browser_context = */ profile);
}
UMA_HISTOGRAM_COUNTS_1000(
"SiteIsolation.SavedUserTriggeredIsolatedOrigins.Size", origins.size());
}