blob: ae08674966a3a996132fe893c0e85292fd85877e [file]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/proxy_config/proxy_prefs_utils.h"
#include <string>
#include "components/policy/core/common/policy_types.h"
#include "components/prefs/testing_pref_service.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "net/base/proxy_chain.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_constants.h"
namespace proxy_config {
TEST(ProxyPrefsUtilsTest, ProxyOverrideRuleHostFromString) {
url::SchemeHostPort scheme_host_port =
ProxyOverrideRuleHostFromString("https://google.com:123");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpsScheme);
ASSERT_EQ(scheme_host_port.host(), "google.com");
ASSERT_EQ(scheme_host_port.port(), 123);
scheme_host_port = ProxyOverrideRuleHostFromString("google.com:123");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpScheme);
ASSERT_EQ(scheme_host_port.host(), "google.com");
ASSERT_EQ(scheme_host_port.port(), 123);
scheme_host_port = ProxyOverrideRuleHostFromString("https://google.com");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpsScheme);
ASSERT_EQ(scheme_host_port.host(), "google.com");
ASSERT_EQ(scheme_host_port.port(), 443);
scheme_host_port = ProxyOverrideRuleHostFromString("google.com");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpScheme);
ASSERT_EQ(scheme_host_port.host(), "google.com");
ASSERT_EQ(scheme_host_port.port(), 80);
scheme_host_port = ProxyOverrideRuleHostFromString("192.168.1.1");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpScheme);
ASSERT_EQ(scheme_host_port.host(), "192.168.1.1");
ASSERT_EQ(scheme_host_port.port(), 80);
scheme_host_port =
ProxyOverrideRuleHostFromString("https://[3ffe:2a00:100:7031:0:0::1]");
ASSERT_TRUE(scheme_host_port.IsValid());
ASSERT_EQ(scheme_host_port.scheme(), url::kHttpsScheme);
ASSERT_EQ(scheme_host_port.host(), "[3ffe:2a00:100:7031::1]");
ASSERT_EQ(scheme_host_port.port(), 443);
ASSERT_FALSE(ProxyOverrideRuleHostFromString("https://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleHostFromString("http://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleHostFromString("://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleHostFromString("123456789").IsValid());
}
TEST(ProxyPrefsUtilsTest, ProxyOverrideRuleProxyFromString) {
net::ProxyChain proxy_chain =
ProxyOverrideRuleProxyFromString("https://google.com:123");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_HTTPS);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 123);
proxy_chain = ProxyOverrideRuleProxyFromString("https://google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_HTTPS);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 443);
proxy_chain = ProxyOverrideRuleProxyFromString("HTTPS google.com:123");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_HTTPS);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 123);
proxy_chain = ProxyOverrideRuleProxyFromString("HTTPS google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_HTTPS);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 443);
proxy_chain = ProxyOverrideRuleProxyFromString("socks4://google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_SOCKS4);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 1080);
proxy_chain = ProxyOverrideRuleProxyFromString("SOCKS4 google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_SOCKS4);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 1080);
proxy_chain = ProxyOverrideRuleProxyFromString("socks5://google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_SOCKS5);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 1080);
proxy_chain = ProxyOverrideRuleProxyFromString("SOCKS5 google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_SOCKS5);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 1080);
proxy_chain = ProxyOverrideRuleProxyFromString("PROXY google.com");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_EQ(proxy_chain.First().scheme(), net::ProxyServer::SCHEME_HTTP);
ASSERT_EQ(proxy_chain.First().GetHost(), "google.com");
ASSERT_EQ(proxy_chain.First().GetPort(), 80);
proxy_chain = ProxyOverrideRuleProxyFromString("DIRECT");
ASSERT_TRUE(proxy_chain.IsValid());
ASSERT_TRUE(proxy_chain.is_direct());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("google").IsValid());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("google.com").IsValid());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("https://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("http://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("://").IsValid());
ASSERT_FALSE(ProxyOverrideRuleProxyFromString("123456789").IsValid());
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
namespace {
void SetAffiliationPrefs(TestingPrefServiceSimple& prefs,
bool affiliated,
int enabled_for_all_users) {
prefs.SetBoolean(prefs::kProxyOverrideRulesAffiliation, affiliated);
prefs.SetInteger(prefs::kEnableProxyOverrideRulesForAllUsers,
enabled_for_all_users);
}
void VerifyUnaffiliatedRestriction(TestingPrefServiceSimple& prefs,
bool expected_restricted) {
// Unaffiliated: restricted if `expected_restricted` is true.
SetAffiliationPrefs(prefs, /*affiliated=*/false, /*enabled_for_all_users=*/0);
EXPECT_EQ(ProxyOverrideRulesAllowed(&prefs), !expected_restricted);
// Unaffiliated but enabled by policy: always allowed.
SetAffiliationPrefs(prefs, /*affiliated=*/false, /*enabled_for_all_users=*/1);
EXPECT_TRUE(ProxyOverrideRulesAllowed(&prefs));
// Affiliated: always allowed.
SetAffiliationPrefs(prefs, /*affiliated=*/true, /*enabled_for_all_users=*/0);
EXPECT_TRUE(ProxyOverrideRulesAllowed(&prefs));
}
} // namespace
TEST(ProxyPrefsUtilsTest, ProxyOverrideRulesAllowed) {
TestingPrefServiceSimple prefs;
PrefProxyConfigTrackerImpl::RegisterProfilePrefs(prefs.registry());
// If `kProxyOverrideRules` is not managed by policy or controlled by an
// extension, it is always allowed.
SetAffiliationPrefs(prefs, /*affiliated=*/false, /*enabled_for_all_users=*/0);
EXPECT_TRUE(ProxyOverrideRulesAllowed(&prefs));
// Scenario 1: `kProxyOverrideRules` is controlled by an extension.
// Affiliation is checked, but scope is ignored.
prefs.SetExtensionPref(prefs::kProxyOverrideRules,
base::Value(base::Value::Type::LIST));
prefs.SetInteger(prefs::kProxyOverrideRulesScope,
policy::POLICY_SCOPE_MACHINE);
VerifyUnaffiliatedRestriction(prefs, /*expected_restricted=*/true);
prefs.SetInteger(prefs::kProxyOverrideRulesScope, policy::POLICY_SCOPE_USER);
VerifyUnaffiliatedRestriction(prefs, /*expected_restricted=*/true);
// Scenario 2: `kProxyOverrideRules` is managed by policy.
prefs.SetManagedPref(prefs::kProxyOverrideRules,
base::Value(base::Value::Type::LIST));
// If rules are set at the machine scope, they are always allowed.
prefs.SetInteger(prefs::kProxyOverrideRulesScope,
policy::POLICY_SCOPE_MACHINE);
VerifyUnaffiliatedRestriction(prefs, /*expected_restricted=*/false);
// If rules are set at the user scope, they are restricted for unaffiliated
// users.
prefs.SetInteger(prefs::kProxyOverrideRulesScope, policy::POLICY_SCOPE_USER);
VerifyUnaffiliatedRestriction(prefs, /*expected_restricted=*/true);
}
#endif
} // namespace proxy_config