
This change implements support for: * DefaultJavaScriptOptimizerSetting * JavaScriptOptimizerAllowedForSites * JavaScriptOptimizerBlockedForSites By: * Adding a method to ContentBrowserClient called AreV8OptimizationsDisabledForSite(), and implementing it in ChromeContentBrowserClient by checking the associated content setting * Storing whether v8 optimizations are disabled for a site in SiteInfo (sadly by adding a new constructor argument to it) * Storing whether v8 optimizations should be disabled as part of RenderProcessHost * Starting render processes with --disable-optimizing-compilers if a given RenderProcessHost should have optimizations disabled * Adding a browser test to ensure this logic works Bug: 338434846 Change-Id: Idb9a85d4eb73a7cc5bfc60d303809c714959a666 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5689960 Reviewed-by: Christian Dullweber <dullweber@chromium.org> Reviewed-by: Charlie Reis <creis@chromium.org> Reviewed-by: Calder Kitagawa <ckitagawa@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Yann Dago <ydago@chromium.org> Commit-Queue: Elly FJ <ellyjones@chromium.org> Cr-Commit-Position: refs/heads/main@{#1343526}
221 lines
8.0 KiB
C++
221 lines
8.0 KiB
C++
// Copyright 2021 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/process_lock.h"
|
|
|
|
#include "base/strings/stringprintf.h"
|
|
#include "content/browser/agent_cluster_key.h"
|
|
#include "content/public/browser/browser_thread.h"
|
|
#include "content/public/browser/web_exposed_isolation_level.h"
|
|
|
|
namespace content {
|
|
|
|
// static
|
|
ProcessLock ProcessLock::CreateAllowAnySite(
|
|
const StoragePartitionConfig& storage_partition_config,
|
|
const WebExposedIsolationInfo& web_exposed_isolation_info) {
|
|
WebExposedIsolationLevel web_exposed_isolation_level =
|
|
SiteInfo::ComputeWebExposedIsolationLevelForEmptySite(
|
|
web_exposed_isolation_info);
|
|
|
|
return ProcessLock(SiteInfo(
|
|
/*site_url=*/GURL(), /*process_lock_url=*/GURL(),
|
|
/*requires_origin_keyed_process=*/false,
|
|
/*requires_origin_keyed_process_by_default=*/false,
|
|
/*is_sandboxed=*/false, UrlInfo::kInvalidUniqueSandboxId,
|
|
storage_partition_config, web_exposed_isolation_info,
|
|
web_exposed_isolation_level, /*is_guest=*/false,
|
|
/*does_site_request_dedicated_process_for_coop=*/false,
|
|
/*is_jit_disabled=*/false, /*are_v8_optimizations_disabled=*/false,
|
|
/*is_pdf=*/false, /*is_fenced=*/false, std::nullopt));
|
|
}
|
|
|
|
// static
|
|
ProcessLock ProcessLock::Create(const IsolationContext& isolation_context,
|
|
const UrlInfo& url_info) {
|
|
DCHECK(url_info.storage_partition_config.has_value());
|
|
if (BrowserThread::CurrentlyOn(BrowserThread::UI))
|
|
return ProcessLock(SiteInfo::Create(isolation_context, url_info));
|
|
|
|
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
|
// On the IO thread we need to use a special SiteInfo creation method because
|
|
// we cannot properly compute some SiteInfo fields on that thread.
|
|
// ProcessLocks must always match no matter which thread they were created on,
|
|
// but the SiteInfo objects used to create them may not always match.
|
|
return ProcessLock(SiteInfo::CreateOnIOThread(isolation_context, url_info));
|
|
}
|
|
|
|
// static
|
|
ProcessLock ProcessLock::FromSiteInfo(const SiteInfo& site_info) {
|
|
return ProcessLock(site_info);
|
|
}
|
|
|
|
ProcessLock::ProcessLock(const SiteInfo& site_info) : site_info_(site_info) {}
|
|
|
|
ProcessLock::ProcessLock() = default;
|
|
|
|
ProcessLock::ProcessLock(const ProcessLock&) = default;
|
|
|
|
ProcessLock& ProcessLock::operator=(const ProcessLock&) = default;
|
|
|
|
ProcessLock::~ProcessLock() = default;
|
|
|
|
StoragePartitionConfig ProcessLock::GetStoragePartitionConfig() const {
|
|
DCHECK(site_info_.has_value());
|
|
return site_info_->storage_partition_config();
|
|
}
|
|
|
|
WebExposedIsolationInfo ProcessLock::GetWebExposedIsolationInfo() const {
|
|
return site_info_.has_value() ? site_info_->web_exposed_isolation_info()
|
|
: WebExposedIsolationInfo::CreateNonIsolated();
|
|
}
|
|
|
|
WebExposedIsolationLevel ProcessLock::GetWebExposedIsolationLevel() const {
|
|
return site_info_.has_value() ? site_info_->web_exposed_isolation_level()
|
|
: WebExposedIsolationLevel::kNotIsolated;
|
|
}
|
|
|
|
bool ProcessLock::IsASiteOrOrigin() const {
|
|
const GURL lock_url = ProcessLock::lock_url();
|
|
return lock_url.has_scheme() && lock_url.has_host() && lock_url.is_valid();
|
|
}
|
|
|
|
bool ProcessLock::HasOpaqueOrigin() const {
|
|
DCHECK(is_locked_to_site());
|
|
return url::Origin::Create(lock_url()).opaque();
|
|
}
|
|
|
|
bool ProcessLock::MatchesOrigin(const url::Origin& origin) const {
|
|
url::Origin process_lock_origin = url::Origin::Create(lock_url());
|
|
return origin == process_lock_origin;
|
|
}
|
|
|
|
bool ProcessLock::IsCompatibleWithWebExposedIsolation(
|
|
const SiteInfo& site_info) const {
|
|
if (!site_info_.has_value()) {
|
|
return true;
|
|
}
|
|
|
|
// Check if the WebExposedIsolationInfos are compatible.
|
|
if (site_info_->web_exposed_isolation_info() !=
|
|
site_info.web_exposed_isolation_info()) {
|
|
return false;
|
|
}
|
|
|
|
// Check if the CrossOriginIsolationKeys are compatible.
|
|
//
|
|
// TODO(crbug.com/349755777): Currently, this prevents a RenderProcessHost
|
|
// with a ProcessLock created with ProcessLock::CreateAllowAnySite to be
|
|
// reused for navigations to documents with DocumentIsolationPolicy, even if
|
|
// the RenderProcessHost has not been used and it would be safe to reuse it.
|
|
//
|
|
// Unfortunately, ProcessLock::CreateAllowAnySite will result in the
|
|
// associated RenderProcessHost to be marked as crossOriginIsolated or not,
|
|
// depending on the passed WebExposedIsolationInfo. It cannot be set to a
|
|
// different crossOriginIsolated status again (without removing checks that
|
|
// the COI status of the process cannot change).
|
|
//
|
|
// Therefore, we need this check to avoid reusing a process matching a
|
|
// ProcessLock created ProcessLock::CreateAllowAnySite, and triggering the COI
|
|
// state change check in the renderer process.
|
|
//
|
|
// We should refactor how COI status is set in the renderer process, so that
|
|
// unused RenderProcessHosts are not assigned a COI status. This will allow
|
|
// them to be reused regardless of the COI status of the navigation.
|
|
std::optional<AgentClusterKey::CrossOriginIsolationKey> this_coi_key =
|
|
site_info_->agent_cluster_key()
|
|
? site_info_->agent_cluster_key()->GetCrossOriginIsolationKey()
|
|
: std::nullopt;
|
|
std::optional<AgentClusterKey::CrossOriginIsolationKey> other_coi_key =
|
|
site_info.agent_cluster_key()
|
|
? site_info.agent_cluster_key()->GetCrossOriginIsolationKey()
|
|
: std::nullopt;
|
|
|
|
return this_coi_key == other_coi_key;
|
|
}
|
|
|
|
bool ProcessLock::operator==(const ProcessLock& rhs) const {
|
|
if (site_info_.has_value() != rhs.site_info_.has_value())
|
|
return false;
|
|
|
|
if (!site_info_.has_value()) // Neither has a value, so they're equal.
|
|
return true;
|
|
|
|
// At this point, both `this` and `rhs` are known to have valid SiteInfos.
|
|
// Here we proceed with a comparison almost identical to
|
|
// SiteInfo::MakeSecurityPrincipalKey(), except that `site_url_` is excluded.
|
|
return site_info_->ProcessLockCompareTo(rhs.site_info_.value()) == 0;
|
|
}
|
|
|
|
bool ProcessLock::operator!=(const ProcessLock& rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
bool ProcessLock::operator<(const ProcessLock& rhs) const {
|
|
if (!site_info_.has_value() && !rhs.site_info_.has_value())
|
|
return false;
|
|
if (!site_info_.has_value()) // Here rhs.site_info_.has_value() is true.
|
|
return true;
|
|
if (!rhs.site_info_.has_value()) // Here site_info_.has_value() is true.
|
|
return false;
|
|
|
|
// At this point, both `this` and `rhs` are known to have valid SiteInfos.
|
|
// Here we proceed with a comparison almost identical to
|
|
// SiteInfo::MakeSecurityPrincipalKey(), except that `site_url_` is excluded.
|
|
return site_info_->ProcessLockCompareTo(rhs.site_info_.value()) < 0;
|
|
}
|
|
|
|
std::string ProcessLock::ToString() const {
|
|
std::string ret = "{ ";
|
|
|
|
if (site_info_.has_value()) {
|
|
ret += lock_url().possibly_invalid_spec();
|
|
|
|
if (is_origin_keyed_process())
|
|
ret += " origin-keyed";
|
|
|
|
if (is_sandboxed()) {
|
|
ret += " sandboxed";
|
|
if (site_info_->unique_sandbox_id() != UrlInfo::kInvalidUniqueSandboxId)
|
|
ret += base::StringPrintf(" (id=%d)", site_info_->unique_sandbox_id());
|
|
}
|
|
|
|
if (is_pdf())
|
|
ret += " pdf";
|
|
|
|
if (is_guest())
|
|
ret += " guest";
|
|
|
|
if (is_fenced())
|
|
ret += " fenced";
|
|
|
|
if (GetWebExposedIsolationInfo().is_isolated()) {
|
|
ret += " cross-origin-isolated";
|
|
if (GetWebExposedIsolationInfo().is_isolated_application())
|
|
ret += "-application";
|
|
ret += " coi-origin='" +
|
|
GetWebExposedIsolationInfo().origin().GetDebugString() + "'";
|
|
}
|
|
|
|
if (!GetStoragePartitionConfig().is_default()) {
|
|
ret += ", partition=" + GetStoragePartitionConfig().partition_domain() +
|
|
"." + GetStoragePartitionConfig().partition_name();
|
|
if (GetStoragePartitionConfig().in_memory())
|
|
ret += ", in-memory";
|
|
}
|
|
} else {
|
|
ret += " no-site-info";
|
|
}
|
|
ret += " }";
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out, const ProcessLock& process_lock) {
|
|
return out << process_lock.ToString();
|
|
}
|
|
|
|
} // namespace content
|