blob: 22c44ca1273f4cebe0b26809e6f54db9089ea5f5 [file] [log] [blame]
// Copyright 2020 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 "base/test/scoped_feature_list.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/sct_reporting_service.h"
#include "chrome/browser/ssl/sct_reporting_service_factory.h"
#include "chrome/browser/ui/browser.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 "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/features.h"
// Observer that tracks SCT audit reports that the SCTReportingService has seen.
class CacheNotifyObserver : public SCTReportingService::TestObserver {
public:
CacheNotifyObserver() = default;
~CacheNotifyObserver() override = default;
CacheNotifyObserver(const CacheNotifyObserver&) = delete;
CacheNotifyObserver& operator=(const CacheNotifyObserver&) = delete;
// SCTReportingService::TestObserver:
void OnSCTReportReady(const std::string& cache_key) override {
cache_entries_seen_.push_back(cache_key);
}
const std::vector<std::string>& cache_entries_seen() const {
return cache_entries_seen_;
}
private:
std::vector<std::string> cache_entries_seen_;
};
class SCTReportingServiceBrowserTest : public InProcessBrowserTest {
public:
SCTReportingServiceBrowserTest() {
// Set sampling rate to 1.0 to ensure deterministic behavior.
scoped_feature_list_.InitWithFeaturesAndParameters(
{{network::features::kSCTAuditing,
{{network::features::kSCTAuditingSamplingRate.name, "1.0"}}}},
{});
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
true);
}
~SCTReportingServiceBrowserTest() override {
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
base::nullopt);
}
SCTReportingServiceBrowserTest(const SCTReportingServiceBrowserTest&) =
delete;
const SCTReportingServiceBrowserTest& operator=(
const SCTReportingServiceBrowserTest&) = delete;
void SetUpOnMainThread() override {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
host_resolver()->AddRule("*", "127.0.0.1");
https_server_.AddDefaultHandlers(GetChromeTestDataDir());
ASSERT_TRUE(https_server_.Start());
InProcessBrowserTest::SetUpOnMainThread();
}
protected:
SCTReportingServiceFactory* factory() {
return SCTReportingServiceFactory::GetInstance();
}
void SetExtendedReportingEnabled(bool enabled) {
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingScoutReportingEnabled, enabled);
}
void SetSafeBrowsingEnabled(bool enabled) {
browser()->profile()->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnabled,
enabled);
}
SCTReportingService* service() const {
return SCTReportingServiceFactory::GetForBrowserContext(
browser()->profile());
}
net::EmbeddedTestServer* https_server() { return &https_server_; }
private:
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
base::test::ScopedFeatureList scoped_feature_list_;
};
// Tests that reports should not be enqueued when extended reporting is not
// opted in.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
NotOptedIn_ShouldNotEnqueueReport) {
SetExtendedReportingEnabled(false);
// Add an observer to track reports that get sent to the embedder.
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
// Visit an HTTPS page.
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
// Check that no reports are enqueued.
EXPECT_EQ(0u, observer.cache_entries_seen().size());
// TODO(crbug.com/1107897): Check histograms once they are added.
}
// Tests that reports should be enqueued when extended reporting is opted in.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
OptedIn_ShouldEnqueueReport) {
// SetSafeBrowsingEnabled(true);
SetExtendedReportingEnabled(true);
// Add an observer to track reports that get sent to the embedder.
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
// Visit an HTTPS page.
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
// Check that one report was enqueued.
EXPECT_EQ(1u, observer.cache_entries_seen().size());
}
// Tests that disabling SafeBrowsing entirely should cause reports to not get
// enqueued.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest, DisableSafebrowsing) {
SetSafeBrowsingEnabled(false);
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
EXPECT_EQ(0u, observer.cache_entries_seen().size());
}
// Tests that we don't enqueue a report for a navigation with a cert error.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
CertErrorDoesNotEnqueueReport) {
SetExtendedReportingEnabled(true);
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
// Visit a page with an invalid cert.
ui_test_utils::NavigateToURL(browser(),
https_server()->GetURL("invalid.test", "/"));
EXPECT_EQ(0u, observer.cache_entries_seen().size());
}
// Tests that reports aren't enqueued for Incognito windows.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
IncognitoWindow_ShouldNotEnqueueReport) {
// Enable SBER in the main profile.
SetExtendedReportingEnabled(true);
// Create a new Incognito window and try to enable SBER in it.
auto* incognito = CreateIncognitoBrowser();
incognito->profile()->GetPrefs()->SetBoolean(
prefs::kSafeBrowsingScoutReportingEnabled, true);
auto* service =
SCTReportingServiceFactory::GetForBrowserContext(incognito->profile());
CacheNotifyObserver observer;
service->AddObserverForTesting(&observer);
ui_test_utils::NavigateToURL(incognito, https_server()->GetURL("/"));
EXPECT_EQ(0u, observer.cache_entries_seen().size());
}
// Tests that disabling Extended Reporting causes the cache to be cleared.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest,
OptingOutClearsSCTAuditingCache) {
// Enable SCT auditing and enqueue a report.
SetExtendedReportingEnabled(true);
// Add an observer to track reports that get sent to the embedder.
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
// Visit an HTTPS page.
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
// Check that one report was enqueued.
EXPECT_EQ(1u, observer.cache_entries_seen().size());
// Disable Extended Reporting which should clear the underlying cache.
SetExtendedReportingEnabled(false);
// We can check that the same report gets cached again instead of being
// deduplicated (i.e., the observer should see another cache entry
// notification).
SetExtendedReportingEnabled(true);
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
EXPECT_EQ(2u, observer.cache_entries_seen().size());
}
// TODO(crbug.com/1107975): Add test for "invalid SCTs should not get reported".
// This is blocked on https://crrev.com/c/1188845 to allow us to use the
// MockCertVerifier to mock CT results.
class SCTReportingServiceZeroSamplingRateBrowserTest
: public SCTReportingServiceBrowserTest {
public:
SCTReportingServiceZeroSamplingRateBrowserTest() {
scoped_feature_list_.InitWithFeaturesAndParameters(
{{network::features::kSCTAuditing,
{{network::features::kSCTAuditingSamplingRate.name, "0.0"}}}},
{});
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
true);
}
~SCTReportingServiceZeroSamplingRateBrowserTest() override {
SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
base::nullopt);
}
SCTReportingServiceZeroSamplingRateBrowserTest(
const SCTReportingServiceZeroSamplingRateBrowserTest&) = delete;
const SCTReportingServiceZeroSamplingRateBrowserTest& operator=(
const SCTReportingServiceZeroSamplingRateBrowserTest&) = delete;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Tests that the embedder is not notified when the sampling rate is zero.
IN_PROC_BROWSER_TEST_F(SCTReportingServiceZeroSamplingRateBrowserTest,
EmbedderNotNotified) {
SetExtendedReportingEnabled(true);
// Add an observer to track reports that get sent to the embedder.
CacheNotifyObserver observer;
service()->AddObserverForTesting(&observer);
// Visit an HTTPS page.
ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
// Check that no reports are observed.
EXPECT_EQ(0u, observer.cache_entries_seen().size());
}