Skip to content

Commit

Permalink
HTTPS by default on Desktop
Browse files Browse the repository at this point in the history
- Disabled, Standard, Strict modes
- Controlled by global and per-site shields settings
- Merge UI with HTTPS-Only Mode
- Behind HttpsByDefault feature flag
- Browser tests for each setting
  • Loading branch information
arthuredelstein committed Feb 3, 2023
1 parent dcdaf13 commit e7da857
Show file tree
Hide file tree
Showing 60 changed files with 1,094 additions and 31 deletions.
12 changes: 12 additions & 0 deletions app/brave_settings_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@
<message name="IDS_SETTINGS_STRICT_FINGERPRINTING" desc="Select value">
Strict, may break sites
</message>
<message name="IDS_SETTINGS_BRAVE_SHIELDS_HTTPS_UPGRADE_CONTROL_LABEL" desc="Default Brave https upgrade control setting label">
Upgrade connections to HTTPS
</message>
<message name="IDS_SETTINGS_STANDARD_HTTPS_UPGRADE" desc="Select value">
Standard
</message>
<message name="IDS_SETTINGS_DISABLED_HTTPS_UPGRADE" desc="Select value">
Disabled
</message>
<message name="IDS_SETTINGS_STRICT_HTTPS_UPGRADE" desc="Select value">
Strict
</message>
<message name="IDS_SETTINGS_BRAVE_SHIELDS_COOKIE_CONTROL_LABEL" desc="Default Brave cookies control setting label">
Block cookies
</message>
Expand Down
5 changes: 5 additions & 0 deletions browser/BUILD.gn
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Copyright (c) 2022 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/.

import("//brave/build/config.gni")
import("//build/buildflag_header.gni")
import("//build/config/features.gni")
Expand Down
10 changes: 10 additions & 0 deletions browser/about_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@ constexpr char kAllowCertainClientHintsDescription[] =
"Allows setting certain request client hints (sec-ch-ua, sec-ch-ua-mobile, "
"sec-ch-ua-platform)";

constexpr char kHttpsByDefaultName[] = "Use HTTPS by Default";
constexpr char kHttpsByDefaultDescription[] =
"Attempt to connect to all websites using HTTPS before falling back to "
"HTTP.";

#if defined(TOOLKIT_VIEWS)
constexpr char kBraveVerticalTabsName[] = "Vertical tabs";
constexpr char kBraveVerticalTabsDescription[] =
Expand Down Expand Up @@ -839,6 +844,11 @@ constexpr char kRestrictEventSourcePoolDescription[] =
flag_descriptions::kBraveSyncSendAllHistoryDescription, \
kOsAll, FEATURE_VALUE_TYPE( \
brave_sync::features::kBraveSyncSendAllHistory)}, \
{"https-by-default", \
flag_descriptions::kHttpsByDefaultName, \
flag_descriptions::kHttpsByDefaultDescription, \
kOsAll, FEATURE_VALUE_TYPE( \
blink::features::kHttpsByDefault)}, \
BRAVE_IPFS_FEATURE_ENTRIES \
BRAVE_NATIVE_WALLET_FEATURE_ENTRIES \
BRAVE_NEWS_FEATURE_ENTRIES \
Expand Down
8 changes: 7 additions & 1 deletion browser/brave_browser_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class AdBlockService;
class HTTPSEverywhereService;
} // namespace brave_shields

namespace https_upgrade_exceptions {
class HttpsUpgradeExceptionsService;
} // namespace https_upgrade_exceptions

namespace brave_stats {
class BraveStatsUpdater;
} // namespace brave_stats
Expand All @@ -66,7 +70,7 @@ class NTPBackgroundImagesService;
namespace tor {
class BraveTorClientUpdater;
class BraveTorPluggableTransportUpdater;
}
} // namespace tor

namespace ipfs {
class BraveIpfsClientUpdater;
Expand All @@ -86,6 +90,8 @@ class BraveBrowserProcess {
virtual ~BraveBrowserProcess();
virtual void StartBraveServices() = 0;
virtual brave_shields::AdBlockService* ad_block_service() = 0;
virtual https_upgrade_exceptions::HttpsUpgradeExceptionsService*
https_upgrade_exceptions_service() = 0;
#if BUILDFLAG(ENABLE_GREASELION)
virtual greaselion::GreaselionDownloadService*
greaselion_download_service() = 0;
Expand Down
16 changes: 16 additions & 0 deletions browser/brave_browser_process_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "brave/components/constants/pref_names.h"
#include "brave/components/debounce/browser/debounce_component_installer.h"
#include "brave/components/debounce/common/features.h"
#include "brave/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.h"
#include "brave/components/misc_metrics/menu_metrics.h"
#include "brave/components/ntp_background_images/browser/ntp_background_images_service.h"
#include "brave/components/p3a/brave_p3a_service.h"
Expand All @@ -55,6 +56,7 @@
#include "content/public/browser/child_process_security_policy.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_GREASELION)
Expand Down Expand Up @@ -200,6 +202,10 @@ void BraveBrowserProcessImpl::StartBraveServices() {
https_everywhere_service()->Start();
resource_component();

if (base::FeatureList::IsEnabled(blink::features::kHttpsByDefault)) {
https_upgrade_exceptions_service();
}

#if BUILDFLAG(ENABLE_GREASELION)
greaselion_download_service();
#endif
Expand Down Expand Up @@ -242,6 +248,16 @@ BraveBrowserProcessImpl::ntp_background_images_service() {
return ntp_background_images_service_.get();
}

https_upgrade_exceptions::HttpsUpgradeExceptionsService*
BraveBrowserProcessImpl::https_upgrade_exceptions_service() {
if (!https_upgrade_exceptions_service_) {
https_upgrade_exceptions_service_ =
https_upgrade_exceptions::HttpsUpgradeExceptionsServiceFactory(
local_data_files_service());
}
return https_upgrade_exceptions_service_.get();
}

#if BUILDFLAG(ENABLE_GREASELION)
greaselion::GreaselionDownloadService*
BraveBrowserProcessImpl::greaselion_download_service() {
Expand Down
12 changes: 10 additions & 2 deletions browser/brave_browser_process_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class AdBlockService;
class HTTPSEverywhereService;
} // namespace brave_shields

namespace https_upgrade_exceptions {
class HttpsUpgradeExceptionsService;
} // namespace https_upgrade_exceptions

namespace brave_stats {
class BraveStatsUpdater;
} // namespace brave_stats
Expand All @@ -63,7 +67,7 @@ class NTPBackgroundImagesService;
namespace tor {
class BraveTorClientUpdater;
class BraveTorPluggableTransportUpdater;
}
} // namespace tor

namespace ipfs {
class BraveIpfsClientUpdater;
Expand All @@ -76,7 +80,7 @@ class SpeedreaderRewriterService;
namespace brave_ads {
class BraveStatsUpdaterHelper;
class ResourceComponent;
}
} // namespace brave_ads

class BraveBrowserProcessImpl : public BraveBrowserProcess,
public BrowserProcessImpl {
Expand All @@ -95,6 +99,8 @@ class BraveBrowserProcessImpl : public BraveBrowserProcess,

void StartBraveServices() override;
brave_shields::AdBlockService* ad_block_service() override;
https_upgrade_exceptions::HttpsUpgradeExceptionsService*
https_upgrade_exceptions_service() override;
#if BUILDFLAG(ENABLE_GREASELION)
greaselion::GreaselionDownloadService* greaselion_download_service() override;
#endif
Expand Down Expand Up @@ -156,6 +162,8 @@ class BraveBrowserProcessImpl : public BraveBrowserProcess,
std::unique_ptr<brave_component_updater::BraveComponent::Delegate>
brave_component_updater_delegate_;
std::unique_ptr<brave_shields::AdBlockService> ad_block_service_;
std::unique_ptr<https_upgrade_exceptions::HttpsUpgradeExceptionsService>
https_upgrade_exceptions_service_;
#if BUILDFLAG(ENABLE_GREASELION)
std::unique_ptr<greaselion::GreaselionDownloadService>
greaselion_download_service_;
Expand Down
167 changes: 167 additions & 0 deletions browser/brave_shields/https_upgrade_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* Copyright (c) 2022 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/browser/brave_browser_process.h"
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/https_upgrade_exceptions/browser/https_upgrade_exceptions_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/https_only_mode_upgrade_interceptor.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/cert/x509_certificate.h"
#include "net/dns/mock_host_resolver.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"

using blink::features::kHttpsByDefault;
using brave_shields::ControlType;

namespace {

enum PageResult { HTTP, HTTPS, INTERSTITIAL };

struct TestStruct {
bool init_secure;
const char* domain;
ControlType control_type;
PageResult expected_result;
};

const TestStruct test_combinations[] = {
{false, "insecure1.test", ControlType::ALLOW, PageResult::HTTP},
{false, "insecure2.test", ControlType::BLOCK_THIRD_PARTY, PageResult::HTTP},
{false, "insecure3.test", ControlType::BLOCK, PageResult::INTERSTITIAL},
{false, "upgradable1.test", ControlType::ALLOW, PageResult::HTTP},
{false, "upgradable2.test", ControlType::BLOCK_THIRD_PARTY,
PageResult::HTTPS},
{false, "upgradable3.test", ControlType::BLOCK, PageResult::HTTPS},
{true, "secure1.test", ControlType::ALLOW, PageResult::HTTPS},
{true, "secure2.test", ControlType::BLOCK_THIRD_PARTY, PageResult::HTTPS},
{true, "secure3.test", ControlType::BLOCK, PageResult::HTTPS}};

} // namespace

class HttpsUpgradeBrowserTest : public InProcessBrowserTest {
public:
HttpsUpgradeBrowserTest() = default;
~HttpsUpgradeBrowserTest() override = default;

void SetUp() override {
feature_list_.InitAndEnableFeature(kHttpsByDefault);
InProcessBrowserTest::SetUp();
}

void SetUpOnMainThread() override {
g_brave_browser_process->https_upgrade_exceptions_service()
->SetIsReadyForTesting();
// By default allow all hosts on HTTPS.
mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
host_resolver()->AddRule("*", "127.0.0.1");

// Set up "insecure.test" as a hostname with an SSL error. HTTPS upgrades
// to this host will fail, (or fall back in some cases).
scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
net::CertVerifyResult verify_result;
verify_result.is_issued_by_known_root = false;
verify_result.verified_cert = cert;
verify_result.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
mock_cert_verifier_.mock_cert_verifier()->AddResultForCertAndHost(
cert, "insecure1.test", verify_result, net::ERR_CERT_INVALID);
mock_cert_verifier_.mock_cert_verifier()->AddResultForCertAndHost(
cert, "insecure2.test", verify_result, net::ERR_CERT_INVALID);
mock_cert_verifier_.mock_cert_verifier()->AddResultForCertAndHost(
cert, "insecure3.test", verify_result, net::ERR_CERT_INVALID);

http_server_.AddDefaultHandlers(GetChromeTestDataDir());
https_server_.AddDefaultHandlers(GetChromeTestDataDir());
ASSERT_TRUE(http_server_.Start());
ASSERT_TRUE(https_server_.Start());

HttpsOnlyModeUpgradeInterceptor::SetHttpsPortForTesting(
https_server()->port());
HttpsOnlyModeUpgradeInterceptor::SetHttpPortForTesting(
http_server()->port());
}

void SetUpCommandLine(base::CommandLine* command_line) override {
mock_cert_verifier_.SetUpCommandLine(command_line);
}

void SetUpInProcessBrowserTestFixture() override {
mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
}

void TearDownInProcessBrowserTestFixture() override {
mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
}

bool NavigateToURLUntilLoadStop(const GURL& url) {
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
return WaitForLoadStop(Contents());
}

content::WebContents* Contents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}

HostContentSettingsMap* ContentSettings() {
return HostContentSettingsMapFactory::GetForProfile(browser()->profile());
}

protected:
net::EmbeddedTestServer* http_server() { return &http_server_; }
net::EmbeddedTestServer* https_server() { return &https_server_; }

private:
base::test::ScopedFeatureList feature_list_;
net::EmbeddedTestServer http_server_{net::EmbeddedTestServer::TYPE_HTTP};
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
content::ContentMockCertVerifier mock_cert_verifier_;
};

// If the user navigates to an HTTP URL for a site that supports HTTPS, the
// navigation should end up on the HTTPS version of the URL.
IN_PROC_BROWSER_TEST_F(HttpsUpgradeBrowserTest, CheckUpgrades) {
for (bool global_setting : {true, false}) {
for (const TestStruct test : test_combinations) {
GURL initial_url =
test.init_secure ? https_server()->GetURL(test.domain, "/simple.html")
: http_server()->GetURL(test.domain, "/simple.html");
brave_shields::SetHttpsUpgradeControlType(
ContentSettings(), test.control_type,
global_setting ? GURL() : initial_url,
g_browser_process->local_state());
base::RunLoop().RunUntilIdle();
content::TestNavigationObserver nav_observer(Contents(), 1);
NavigateToURLUntilLoadStop(initial_url);
nav_observer.Wait();
bool navigation_succeeded = nav_observer.last_navigation_succeeded();
bool interstitial_showing =
chrome_browser_interstitials::IsShowingInterstitial(Contents());
if (test.expected_result == PageResult::INTERSTITIAL) {
EXPECT_TRUE(interstitial_showing);
EXPECT_FALSE(navigation_succeeded);
} else {
EXPECT_FALSE(interstitial_showing);
EXPECT_TRUE(navigation_succeeded);
GURL final_url =
(test.expected_result == PageResult::HTTP ? http_server()
: https_server())
->GetURL(test.domain, "/simple.html");
EXPECT_EQ(final_url, Contents()->GetLastCommittedURL());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ TEST_F(BraveContentSettingsRegistryTest, Inheritance) {
ContentSettingsType::BRAVE_COOKIES,
ContentSettingsType::BRAVE_SPEEDREADER,
ContentSettingsType::BRAVE_GOOGLE_SIGN_IN,
ContentSettingsType::BRAVE_HTTPS_UPGRADE,
};

for (const ContentSettingsInfo* info : *registry()) {
Expand Down
2 changes: 2 additions & 0 deletions browser/net/url_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ std::shared_ptr<brave::BraveRequestInfo> BraveRequestInfo::MakeCTX(
brave_shields::ControlType::BLOCK;
ctx->allow_http_upgradable_resource =
!brave_shields::GetHTTPSEverywhereEnabled(map, ctx->tab_origin);
ctx->https_upgrade_setting =
brave_shields::GetHttpsUpgradeControlType(map, ctx->tab_origin);

// HACK: after we fix multiple creations of BraveRequestInfo we should
// use only tab_origin. Since we recreate BraveRequestInfo during consequent
Expand Down
1 change: 1 addition & 0 deletions browser/net/url_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct BraveRequestInfo {
// initiated.
bool aggressive_blocking = false;
bool allow_http_upgradable_resource = false;
int https_upgrade_setting = 0;
bool allow_referrers = false;
bool is_webtorrent_disabled = false;
int frame_tree_node_id = 0;
Expand Down
5 changes: 3 additions & 2 deletions browser/profiles/brave_profile_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ void BraveProfileManager::InitProfileUserPrefs(Profile* profile) {
brave::SetDefaultSearchVersion(profile, profile->IsNewProfile());
brave::SetDefaultThirdPartyCookieBlockValue(profile);
perf::MaybeEnableBraveFeatureForPerfTesting(profile);
brave::MigrateHttpsUpgradeSettings(profile);
}

void BraveProfileManager::DoFinalInitForServices(Profile* profile,
Expand Down Expand Up @@ -132,8 +133,8 @@ bool BraveProfileManager::IsAllowedProfilePath(
}

bool BraveProfileManager::LoadProfileByPath(const base::FilePath& profile_path,
bool incognito,
ProfileLoadedCallback callback) {
bool incognito,
ProfileLoadedCallback callback) {
#if BUILDFLAG(ENABLE_TOR)
// Prevent legacy tor session profile to be loaded so we won't hit
// DCHECK(!GetProfileAttributesWithPath(...)). Workaround for legacy tor guest
Expand Down
Loading

0 comments on commit e7da857

Please sign in to comment.