diff --git a/components/BUILD.gn b/components/BUILD.gn index bfdb5013a07..f51573300ea 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -38,6 +38,7 @@ test("brave_components_unittests") { "//brave/components/brave_sync:unit_tests", "//brave/components/component_updater:unit_tests", "//brave/components/email_aliases:unit_tests", + "//brave/components/https_upgrade_exceptions/browser:unit_tests", "//brave/components/json:unit_tests", "//brave/components/local_ai/core:unit_tests", "//brave/components/static_redirect_helper:unit_tests", diff --git a/components/https_upgrade_exceptions/browser/BUILD.gn b/components/https_upgrade_exceptions/browser/BUILD.gn index 237db2ceef2..00c67248c20 100644 --- a/components/https_upgrade_exceptions/browser/BUILD.gn +++ b/components/https_upgrade_exceptions/browser/BUILD.gn @@ -14,7 +14,19 @@ static_library("browser") { deps = [ "//base", "//brave/components/brave_component_updater/browser", - "//net:net_features", + "//net", "//url", ] } + +source_set("unit_tests") { + testonly = true + sources = [ "https_upgrade_exceptions_service_unittest.cc" ] + + deps = [ + ":browser", + "//base/test:test_support", + "//net:net_features", + "//testing/gtest", + ] +} diff --git a/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.cc b/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.cc index 16ca6973bde..132b3c401dd 100644 --- a/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.cc +++ b/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.cc @@ -74,7 +74,13 @@ bool HttpsUpgradeExceptionsService::CanUpgradeToHTTPS(const GURL& url) { // don't upgrade any websites yet. return false; } - // Allow upgrade only if the domain is not on the exceptions list. + + // The exceptions list is provided by the "Brave Local Data Files Updater" + // CRX. It contains a list of hosts that should be excluded from HTTPS + // upgrades. The matching logic checks only the host name, as a result, if a + // subdomain is not explicitly listed, it will still be upgraded to HTTPS. + // For example, if a.com is on the list, a.com will not be upgraded, but + // sub.a.com will be upgraded. return !exceptional_domains_.contains(url.host()); } diff --git a/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service_unittest.cc b/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service_unittest.cc new file mode 100644 index 00000000000..5bc36299a77 --- /dev/null +++ b/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service_unittest.cc @@ -0,0 +1,102 @@ +/* Copyright (c) 2026 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.h" + +#include +#include + +#include "base/test/scoped_feature_list.h" +#include "net/base/features.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// The list of exceptions contains TLDs+1 +constexpr char kExceptionList[] = "a.com"; + +} // namespace + +class HttpsUpgradeExceptionsServiceBaseTest : public testing::Test { + public: + void SetUp() override { + local_data_files_service_ = + brave_component_updater::LocalDataFilesServiceFactory(nullptr); + https_upgrade_exceptions_service_ = std::make_unique< + https_upgrade_exceptions::HttpsUpgradeExceptionsService>( + local_data_files_service_.get()); + ASSERT_TRUE(https_upgrade_exceptions_service_); + + testing::Test::SetUp(); + } + + https_upgrade_exceptions::HttpsUpgradeExceptionsService* + https_upgrade_exceptions_service() { + return https_upgrade_exceptions_service_.get(); + } + + private: + std::unique_ptr + local_data_files_service_; + std::unique_ptr + https_upgrade_exceptions_service_; +}; + +class HttpsUpgradeExceptionsServiceFeatureDisabledTest + : public HttpsUpgradeExceptionsServiceBaseTest { + public: + HttpsUpgradeExceptionsServiceFeatureDisabledTest() { + feature_list_.InitAndDisableFeature(net::features::kBraveHttpsByDefault); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(HttpsUpgradeExceptionsServiceFeatureDisabledTest, + CanUpgradeToHTTPS_DisabledFeature) { + const auto a_url = GURL("http://a.com"); + EXPECT_FALSE(https_upgrade_exceptions_service()->CanUpgradeToHTTPS(a_url)); + + https_upgrade_exceptions_service()->OnDATFileDataReady(kExceptionList); + EXPECT_FALSE(https_upgrade_exceptions_service()->CanUpgradeToHTTPS(a_url)); +} + +class HttpsUpgradeExceptionsServiceFeatureEnabledTest + : public HttpsUpgradeExceptionsServiceBaseTest { + public: + HttpsUpgradeExceptionsServiceFeatureEnabledTest() { + feature_list_.InitAndEnableFeature(net::features::kBraveHttpsByDefault); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(HttpsUpgradeExceptionsServiceFeatureEnabledTest, + CanUpgradeToHTTPS_NotReady) { + const auto a_url = GURL("http://a.com"); + EXPECT_FALSE(https_upgrade_exceptions_service()->CanUpgradeToHTTPS(a_url)); +} + +TEST_F(HttpsUpgradeExceptionsServiceFeatureEnabledTest, CanUpgradeToHTTPS) { + struct TestCases { + std::string name; + GURL url; + bool can_upgrade; + } kTestCases[] = { + {"Do not upgrade as exception", GURL("http://a.com"), false}, + {"Do not upgrade as wrong schema", GURL("chrome://a.com"), false}, + {"Simple Upgrade to HTTPS", GURL("http://b.com"), true}}; + + https_upgrade_exceptions_service()->OnDATFileDataReady(kExceptionList); + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(testing::Message() << test_case.name); + EXPECT_EQ( + https_upgrade_exceptions_service()->CanUpgradeToHTTPS(test_case.url), + test_case.can_upgrade); + } +}