3218 lines
146 KiB
C++
3218 lines
146 KiB
C++
// Copyright 2014 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "net/http/http_server_properties_manager.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/feature_list.h"
|
|
#include "base/functional/bind.h"
|
|
#include "base/functional/callback.h"
|
|
#include "base/json/json_writer.h"
|
|
#include "base/memory/ptr_util.h"
|
|
#include "base/memory/raw_ptr.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/task/single_thread_task_runner.h"
|
|
#include "base/test/bind.h"
|
|
#include "base/test/scoped_feature_list.h"
|
|
#include "base/test/values_test_util.h"
|
|
#include "base/time/default_tick_clock.h"
|
|
#include "base/time/time.h"
|
|
#include "base/values.h"
|
|
#include "net/base/features.h"
|
|
#include "net/base/ip_address.h"
|
|
#include "net/base/schemeful_site.h"
|
|
#include "net/http/http_network_session.h"
|
|
#include "net/http/http_server_properties.h"
|
|
#include "net/quic/quic_context.h"
|
|
#include "net/test/test_with_task_environment.h"
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "url/gurl.h"
|
|
|
|
namespace net {
|
|
|
|
namespace {
|
|
|
|
using base::StringPrintf;
|
|
using ::testing::_;
|
|
using ::testing::AtLeast;
|
|
using ::testing::Invoke;
|
|
using ::testing::Mock;
|
|
using ::testing::StrictMock;
|
|
|
|
enum class NetworkAnonymizationKeyMode {
|
|
kDisabled,
|
|
kEnabled,
|
|
};
|
|
|
|
const NetworkAnonymizationKeyMode kNetworkAnonymizationKeyModes[] = {
|
|
NetworkAnonymizationKeyMode::kDisabled,
|
|
NetworkAnonymizationKeyMode::kEnabled,
|
|
};
|
|
|
|
std::unique_ptr<base::test::ScopedFeatureList> SetNetworkAnonymizationKeyMode(
|
|
NetworkAnonymizationKeyMode mode) {
|
|
auto feature_list = std::make_unique<base::test::ScopedFeatureList>();
|
|
switch (mode) {
|
|
case NetworkAnonymizationKeyMode::kDisabled:
|
|
feature_list->InitAndDisableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
break;
|
|
case NetworkAnonymizationKeyMode::kEnabled:
|
|
feature_list->InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
break;
|
|
}
|
|
return feature_list;
|
|
}
|
|
|
|
class MockPrefDelegate : public net::HttpServerProperties::PrefDelegate {
|
|
public:
|
|
MockPrefDelegate() = default;
|
|
|
|
MockPrefDelegate(const MockPrefDelegate&) = delete;
|
|
MockPrefDelegate& operator=(const MockPrefDelegate&) = delete;
|
|
|
|
~MockPrefDelegate() override = default;
|
|
|
|
// HttpServerProperties::PrefDelegate implementation.
|
|
const base::Value::Dict& GetServerProperties() const override {
|
|
return prefs_;
|
|
}
|
|
|
|
void SetServerProperties(base::Value::Dict dict,
|
|
base::OnceClosure callback) override {
|
|
prefs_.clear();
|
|
prefs_.Merge(std::move(dict));
|
|
++num_pref_updates_;
|
|
if (!prefs_changed_callback_.is_null())
|
|
std::move(prefs_changed_callback_).Run();
|
|
if (!extra_prefs_changed_callback_.is_null())
|
|
std::move(extra_prefs_changed_callback_).Run();
|
|
set_properties_callback_ = std::move(callback);
|
|
}
|
|
|
|
void WaitForPrefLoad(base::OnceClosure callback) override {
|
|
CHECK(prefs_changed_callback_.is_null());
|
|
prefs_changed_callback_ = std::move(callback);
|
|
}
|
|
|
|
void InitializePrefs(base::Value::Dict dict) {
|
|
ASSERT_FALSE(prefs_changed_callback_.is_null());
|
|
prefs_ = std::move(dict);
|
|
std::move(prefs_changed_callback_).Run();
|
|
}
|
|
|
|
int GetAndClearNumPrefUpdates() {
|
|
int out = num_pref_updates_;
|
|
num_pref_updates_ = 0;
|
|
return out;
|
|
}
|
|
|
|
// Additional callback to call when prefs are updated, used to check prefs are
|
|
// updated on destruction.
|
|
void set_extra_update_prefs_callback(base::OnceClosure callback) {
|
|
extra_prefs_changed_callback_ = std::move(callback);
|
|
}
|
|
|
|
// Returns the base::OnceCallback, if any, passed to the last call to
|
|
// SetServerProperties().
|
|
base::OnceClosure GetSetPropertiesCallback() {
|
|
return std::move(set_properties_callback_);
|
|
}
|
|
|
|
private:
|
|
base::Value::Dict prefs_;
|
|
base::OnceClosure prefs_changed_callback_;
|
|
base::OnceClosure extra_prefs_changed_callback_;
|
|
int num_pref_updates_ = 0;
|
|
|
|
base::OnceClosure set_properties_callback_;
|
|
};
|
|
|
|
// Converts |server_info_map| to a base::Value::Dict by running it through an
|
|
// HttpServerPropertiesManager. Other fields are left empty.
|
|
base::Value::Dict ServerInfoMapToDict(
|
|
const HttpServerProperties::ServerInfoMap& server_info_map) {
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
// Callback that shouldn't be invoked - this method short-circuits loading
|
|
// prefs by calling HttpServerPropertiesManager::WriteToPrefs() before prefs
|
|
// are loaded.
|
|
HttpServerPropertiesManager::OnPrefsLoadedCallback on_prefs_loaded_callback =
|
|
base::BindOnce(
|
|
[](std::unique_ptr<HttpServerProperties::ServerInfoMap>
|
|
server_info_map,
|
|
const IPAddress& last_quic_address,
|
|
std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
|
|
quic_server_info_map,
|
|
std::unique_ptr<BrokenAlternativeServiceList>
|
|
broken_alternative_service_list,
|
|
std::unique_ptr<RecentlyBrokenAlternativeServices>
|
|
recently_broken_alternative_services) { ADD_FAILURE(); });
|
|
HttpServerPropertiesManager manager(
|
|
std::move(pref_delegate), std::move(on_prefs_loaded_callback),
|
|
10 /* max_server_configs_stored_in_properties */, nullptr /* net_log */,
|
|
base::DefaultTickClock::GetInstance());
|
|
manager.WriteToPrefs(
|
|
server_info_map, HttpServerPropertiesManager::GetCannonicalSuffix(),
|
|
IPAddress() /* last_quic_address */,
|
|
HttpServerProperties::QuicServerInfoMap(10),
|
|
BrokenAlternativeServiceList(), RecentlyBrokenAlternativeServices(10),
|
|
base::OnceClosure());
|
|
|
|
return unowned_pref_delegate->GetServerProperties().Clone();
|
|
}
|
|
|
|
// Does the inverse of ServerInfoMapToDict(). Ignores fields other than the
|
|
// ServerInfoMap.
|
|
std::unique_ptr<HttpServerProperties::ServerInfoMap> DictToServerInfoMap(
|
|
base::Value::Dict dict) {
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
|
|
std::unique_ptr<HttpServerProperties::ServerInfoMap> out;
|
|
bool callback_invoked = false;
|
|
HttpServerPropertiesManager::OnPrefsLoadedCallback on_prefs_loaded_callback =
|
|
base::BindLambdaForTesting(
|
|
[&](std::unique_ptr<HttpServerProperties::ServerInfoMap>
|
|
server_info_map,
|
|
const IPAddress& last_quic_address,
|
|
std::unique_ptr<HttpServerProperties::QuicServerInfoMap>
|
|
quic_server_info_map,
|
|
std::unique_ptr<BrokenAlternativeServiceList>
|
|
broken_alternative_service_list,
|
|
std::unique_ptr<RecentlyBrokenAlternativeServices>
|
|
recently_broken_alternative_services) {
|
|
ASSERT_FALSE(callback_invoked);
|
|
callback_invoked = true;
|
|
out = std::move(server_info_map);
|
|
});
|
|
|
|
HttpServerPropertiesManager manager(
|
|
std::move(pref_delegate), std::move(on_prefs_loaded_callback),
|
|
10 /* max_server_configs_stored_in_properties */, nullptr /* net_log */,
|
|
base::DefaultTickClock::GetInstance());
|
|
|
|
unowned_pref_delegate->InitializePrefs(std::move(dict));
|
|
EXPECT_TRUE(callback_invoked);
|
|
return out;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class HttpServerPropertiesManagerTest : public testing::Test,
|
|
public WithTaskEnvironment {
|
|
public:
|
|
HttpServerPropertiesManagerTest(const HttpServerPropertiesManagerTest&) =
|
|
delete;
|
|
HttpServerPropertiesManagerTest& operator=(
|
|
const HttpServerPropertiesManagerTest&) = delete;
|
|
|
|
protected:
|
|
HttpServerPropertiesManagerTest()
|
|
: WithTaskEnvironment(
|
|
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
|
|
|
|
void SetUp() override {
|
|
one_day_from_now_ = base::Time::Now() + base::Days(1);
|
|
advertised_versions_ = DefaultSupportedQuicVersions();
|
|
auto pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
pref_delegate_ = pref_delegate.get();
|
|
|
|
http_server_props_ = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
|
|
EXPECT_FALSE(http_server_props_->IsInitialized());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
}
|
|
|
|
// Wrapper around |pref_delegate_|'s InitializePrefs() method that has a
|
|
// couple extra expectations about whether any tasks are posted, and if a pref
|
|
// update is queued.
|
|
//
|
|
// |expect_pref_update| should be true if a pref update is expected to be
|
|
// queued in response to the load.
|
|
void InitializePrefs(base::Value::Dict dict = base::Value::Dict(),
|
|
bool expect_pref_update = false) {
|
|
EXPECT_FALSE(http_server_props_->IsInitialized());
|
|
pref_delegate_->InitializePrefs(std::move(dict));
|
|
EXPECT_TRUE(http_server_props_->IsInitialized());
|
|
if (!expect_pref_update) {
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
} else {
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
}
|
|
}
|
|
|
|
void TearDown() override {
|
|
// Run pending non-delayed tasks but don't FastForwardUntilNoTasksRemain()
|
|
// as some delayed tasks may forever repost (e.g. because impl doesn't use a
|
|
// mock clock and doesn't see timings as having expired, ref.
|
|
// HttpServerProperties::
|
|
// ScheduleBrokenAlternateProtocolMappingsExpiration()).
|
|
base::RunLoop().RunUntilIdle();
|
|
http_server_props_.reset();
|
|
}
|
|
|
|
bool HasAlternativeService(
|
|
const url::SchemeHostPort& server,
|
|
const NetworkAnonymizationKey& network_anonymization_key) {
|
|
const AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(
|
|
server, network_anonymization_key);
|
|
return !alternative_service_info_vector.empty();
|
|
}
|
|
|
|
// Returns a dictionary with only the version field populated.
|
|
static base::Value::Dict DictWithVersion() {
|
|
base::Value::Dict http_server_properties_dict;
|
|
http_server_properties_dict.Set("version", 5);
|
|
return http_server_properties_dict;
|
|
}
|
|
|
|
raw_ptr<MockPrefDelegate>
|
|
pref_delegate_; // Owned by HttpServerPropertiesManager.
|
|
std::unique_ptr<HttpServerProperties> http_server_props_;
|
|
base::Time one_day_from_now_;
|
|
quic::ParsedQuicVersionVector advertised_versions_;
|
|
};
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
|
|
base::Value::Dict server_pref_dict;
|
|
|
|
// Set supports_spdy for www.google.com:65536.
|
|
server_pref_dict.Set("supports_spdy", true);
|
|
|
|
// Set up alternative_service for www.google.com:65536.
|
|
base::Value::Dict alternative_service_dict;
|
|
alternative_service_dict.Set("protocol_str", "h2");
|
|
alternative_service_dict.Set("port", 80);
|
|
base::Value::List alternative_service_list;
|
|
alternative_service_list.Append(std::move(alternative_service_dict));
|
|
server_pref_dict.Set("alternative_service",
|
|
std::move(alternative_service_list));
|
|
|
|
// Set up ServerNetworkStats for www.google.com:65536.
|
|
base::Value::Dict stats;
|
|
stats.Set("srtt", 10);
|
|
server_pref_dict.Set("network_stats", std::move(stats));
|
|
|
|
// Set the server preference for www.google.com:65536.
|
|
base::Value::Dict servers_dict;
|
|
servers_dict.Set("www.google.com:65536", std::move(server_pref_dict));
|
|
base::Value::List servers_list;
|
|
servers_list.Append(std::move(servers_dict));
|
|
base::Value::Dict http_server_properties_dict = DictWithVersion();
|
|
http_server_properties_dict.Set("servers", std::move(servers_list));
|
|
|
|
// Set quic_server_info for www.google.com:65536.
|
|
base::Value::Dict quic_servers_dict;
|
|
base::Value::Dict quic_server_pref_dict1;
|
|
quic_server_pref_dict1.Set("server_info", "quic_server_info1");
|
|
quic_servers_dict.Set("http://mail.google.com:65536",
|
|
std::move(quic_server_pref_dict1));
|
|
|
|
http_server_properties_dict.Set("quic_servers", std::move(quic_servers_dict));
|
|
|
|
// Set up the pref.
|
|
InitializePrefs(std::move(http_server_properties_dict));
|
|
|
|
// Verify that nothing is set.
|
|
HostPortPair google_host_port_pair =
|
|
HostPortPair::FromString("www.google.com:65536");
|
|
url::SchemeHostPort gooler_server("http", google_host_port_pair.host(),
|
|
google_host_port_pair.port());
|
|
|
|
EXPECT_FALSE(http_server_props_->SupportsRequestPriority(
|
|
gooler_server, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(HasAlternativeService(gooler_server, NetworkAnonymizationKey()));
|
|
const ServerNetworkStats* stats1 = http_server_props_->GetServerNetworkStats(
|
|
gooler_server, NetworkAnonymizationKey());
|
|
EXPECT_EQ(nullptr, stats1);
|
|
EXPECT_EQ(0u, http_server_props_->quic_server_info_map().size());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
|
|
base::Value::Dict server_pref_dict;
|
|
|
|
// Set supports_spdy for www.google.com:80.
|
|
server_pref_dict.Set("supports_spdy", true);
|
|
|
|
// Set up alternative_service for www.google.com:80.
|
|
base::Value::Dict alternative_service_dict;
|
|
alternative_service_dict.Set("protocol_str", "h2");
|
|
alternative_service_dict.Set("port", 65536);
|
|
base::Value::List alternative_service_list;
|
|
alternative_service_list.Append(std::move(alternative_service_dict));
|
|
server_pref_dict.Set("alternative_service",
|
|
std::move(alternative_service_list));
|
|
|
|
// Set the server preference for www.google.com:80.
|
|
base::Value::Dict servers_dict;
|
|
servers_dict.Set("www.google.com:80", std::move(server_pref_dict));
|
|
base::Value::List servers_list;
|
|
servers_list.Append(std::move(servers_dict));
|
|
base::Value::Dict http_server_properties_dict = DictWithVersion();
|
|
http_server_properties_dict.Set("servers", std::move(servers_list));
|
|
|
|
// Set up the pref.
|
|
InitializePrefs(std::move(http_server_properties_dict));
|
|
|
|
// Verify alternative service is not set.
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(url::SchemeHostPort("http", "www.google.com", 80),
|
|
NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
|
|
InitializePrefs();
|
|
|
|
// Add mail.google.com:443 as a supporting spdy server.
|
|
url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
|
|
EXPECT_FALSE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
http_server_props_->SetSupportsSpdy(spdy_server, NetworkAnonymizationKey(),
|
|
true);
|
|
// Setting the value to the same thing again should not trigger another pref
|
|
// update.
|
|
http_server_props_->SetSupportsSpdy(spdy_server, NetworkAnonymizationKey(),
|
|
true);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Setting the value to the same thing again should not trigger another pref
|
|
// update.
|
|
http_server_props_->SetSupportsSpdy(spdy_server, NetworkAnonymizationKey(),
|
|
true);
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
|
|
EXPECT_TRUE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
// Regression test for crbug.com/670519. Test that there is only one pref update
|
|
// scheduled if multiple updates happen in a given time period. Subsequent pref
|
|
// update could also be scheduled once the previous scheduled update is
|
|
// completed.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
SinglePrefUpdateForTwoSpdyServerCacheChanges) {
|
|
InitializePrefs();
|
|
|
|
// Post an update task. SetSupportsSpdy calls ScheduleUpdatePrefs with a delay
|
|
// of 60ms.
|
|
url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
|
|
EXPECT_FALSE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
http_server_props_->SetSupportsSpdy(spdy_server, NetworkAnonymizationKey(),
|
|
true);
|
|
// The pref update task should be scheduled.
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
// Move forward the task runner short by 20ms.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting() -
|
|
base::Milliseconds(20));
|
|
|
|
// Set another spdy server to trigger another call to
|
|
// ScheduleUpdatePrefs. There should be no new update posted.
|
|
url::SchemeHostPort spdy_server2("https", "drive.google.com", 443);
|
|
http_server_props_->SetSupportsSpdy(spdy_server2, NetworkAnonymizationKey(),
|
|
true);
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
// Move forward the extra 20ms. The pref update should be executed.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardBy(base::Milliseconds(20));
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
|
|
EXPECT_TRUE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server2, NetworkAnonymizationKey()));
|
|
// Set the third spdy server to trigger one more call to
|
|
// ScheduleUpdatePrefs. A new update task should be posted now since the
|
|
// previous one is completed.
|
|
url::SchemeHostPort spdy_server3("https", "maps.google.com", 443);
|
|
http_server_props_->SetSupportsSpdy(spdy_server3, NetworkAnonymizationKey(),
|
|
true);
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, GetAlternativeServiceInfos) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
const AlternativeService alternative_service(kProtoHTTP2, "mail.google.com",
|
|
443);
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
// ExpectScheduleUpdatePrefs() should be called only once.
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
EXPECT_EQ(alternative_service,
|
|
alternative_service_info_vector[0].alternative_service());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, SetAlternativeServices) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
AlternativeServiceInfoVector alternative_service_info_vector;
|
|
const AlternativeService alternative_service1(kProtoHTTP2, "mail.google.com",
|
|
443);
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
alternative_service1, one_day_from_now_));
|
|
const AlternativeService alternative_service2(kProtoQUIC, "mail.google.com",
|
|
1234);
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
alternative_service2, one_day_from_now_, advertised_versions_));
|
|
http_server_props_->SetAlternativeServices(spdy_server_mail,
|
|
NetworkAnonymizationKey(),
|
|
alternative_service_info_vector);
|
|
// ExpectScheduleUpdatePrefs() should be called only once.
|
|
http_server_props_->SetAlternativeServices(spdy_server_mail,
|
|
NetworkAnonymizationKey(),
|
|
alternative_service_info_vector);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
AlternativeServiceInfoVector alternative_service_info_vector2 =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(2u, alternative_service_info_vector2.size());
|
|
EXPECT_EQ(alternative_service1,
|
|
alternative_service_info_vector2[0].alternative_service());
|
|
EXPECT_EQ(alternative_service2,
|
|
alternative_service_info_vector2[1].alternative_service());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, SetAlternativeServicesEmpty) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
const AlternativeService alternative_service(kProtoHTTP2, "mail.google.com",
|
|
443);
|
|
http_server_props_->SetAlternativeServices(spdy_server_mail,
|
|
NetworkAnonymizationKey(),
|
|
AlternativeServiceInfoVector());
|
|
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail;
|
|
AlternativeService alternative_service;
|
|
|
|
spdy_server_mail = url::SchemeHostPort("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
alternative_service = AlternativeService(kProtoHTTP2, "mail.google.com", 443);
|
|
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->MarkAlternativeServiceBroken(alternative_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
// In addition to the pref update task, there's now a task to mark the
|
|
// alternative service as no longer broken.
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->ConfirmAlternativeService(alternative_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
// Run the task.
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
// Check the case that prefs are loaded only after setting alternative service
|
|
// info. Prefs should not be written until after the load happens.
|
|
TEST_F(HttpServerPropertiesManagerTest, LateLoadAlternativeServiceInfo) {
|
|
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
const AlternativeService alternative_service(kProtoHTTP2, "mail.google.com",
|
|
443);
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
EXPECT_EQ(alternative_service,
|
|
alternative_service_info_vector[0].alternative_service());
|
|
|
|
// Initializing prefs does not result in a task to write the prefs.
|
|
InitializePrefs(base::Value::Dict(),
|
|
/*expect_pref_update=*/true);
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ(1u, alternative_service_info_vector.size());
|
|
|
|
// Updating the entry should result in a task to save prefs. Have to at least
|
|
// double (or half) the lifetime, to ensure the change triggers a save to
|
|
// prefs.
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_ + base::Days(2));
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ(1u, alternative_service_info_vector.size());
|
|
}
|
|
|
|
// Check the case that prefs are cleared before they're loaded.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
ClearPrefsBeforeLoadAlternativeServiceInfo) {
|
|
url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
const AlternativeService alternative_service(kProtoHTTP2, "mail.google.com",
|
|
443);
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
EXPECT_EQ(alternative_service,
|
|
alternative_service_info_vector[0].alternative_service());
|
|
|
|
// Clearing prefs should result in a task to write the prefs.
|
|
bool callback_invoked_ = false;
|
|
http_server_props_->Clear(base::BindOnce(
|
|
[](bool* callback_invoked) {
|
|
EXPECT_FALSE(*callback_invoked);
|
|
*callback_invoked = true;
|
|
},
|
|
&callback_invoked_));
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_FALSE(callback_invoked_);
|
|
std::move(pref_delegate_->GetSetPropertiesCallback()).Run();
|
|
EXPECT_TRUE(callback_invoked_);
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ(0u, alternative_service_info_vector.size());
|
|
|
|
// Re-creating the entry should result in a task to save prefs.
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(spdy_server_mail,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ(1u, alternative_service_info_vector.size());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
ConfirmBrokenUntilDefaultNetworkChanges) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail;
|
|
AlternativeService alternative_service;
|
|
|
|
spdy_server_mail = url::SchemeHostPort("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
alternative_service = AlternativeService(kProtoHTTP2, "mail.google.com", 443);
|
|
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
|
|
alternative_service, NetworkAnonymizationKey());
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
// In addition to the pref update task, there's now a task to mark the
|
|
// alternative service as no longer broken.
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->ConfirmAlternativeService(alternative_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
// Run the task.
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
OnDefaultNetworkChangedWithBrokenUntilDefaultNetworkChanges) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail;
|
|
AlternativeService alternative_service;
|
|
|
|
spdy_server_mail = url::SchemeHostPort("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
alternative_service = AlternativeService(kProtoHTTP2, "mail.google.com", 443);
|
|
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
|
|
alternative_service, NetworkAnonymizationKey());
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
// In addition to the pref update task, there's now a task to mark the
|
|
// alternative service as no longer broken.
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->OnDefaultNetworkChanged();
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
// Run the task.
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, OnDefaultNetworkChangedWithBrokenOnly) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort spdy_server_mail;
|
|
AlternativeService alternative_service;
|
|
|
|
spdy_server_mail = url::SchemeHostPort("http", "mail.google.com", 80);
|
|
EXPECT_FALSE(
|
|
HasAlternativeService(spdy_server_mail, NetworkAnonymizationKey()));
|
|
alternative_service = AlternativeService(kProtoHTTP2, "mail.google.com", 443);
|
|
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
spdy_server_mail, NetworkAnonymizationKey(), alternative_service,
|
|
one_day_from_now_);
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->MarkAlternativeServiceBroken(alternative_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
// In addition to the pref update task, there's now a task to mark the
|
|
// alternative service as no longer broken.
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
http_server_props_->OnDefaultNetworkChanged();
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
|
|
// Run the task.
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
alternative_service, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, LastLocalAddressWhenQuicWorked) {
|
|
InitializePrefs();
|
|
|
|
IPAddress actual_address(127, 0, 0, 1);
|
|
EXPECT_FALSE(http_server_props_->HasLastLocalAddressWhenQuicWorked());
|
|
EXPECT_FALSE(
|
|
http_server_props_->WasLastLocalAddressWhenQuicWorked(actual_address));
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_TRUE(
|
|
http_server_props_->WasLastLocalAddressWhenQuicWorked(actual_address));
|
|
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, ServerNetworkStats) {
|
|
InitializePrefs();
|
|
|
|
url::SchemeHostPort mail_server("http", "mail.google.com", 80);
|
|
const ServerNetworkStats* stats = http_server_props_->GetServerNetworkStats(
|
|
mail_server, NetworkAnonymizationKey());
|
|
EXPECT_EQ(nullptr, stats);
|
|
ServerNetworkStats stats1;
|
|
stats1.srtt = base::Microseconds(10);
|
|
http_server_props_->SetServerNetworkStats(mail_server,
|
|
NetworkAnonymizationKey(), stats1);
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetServerNetworkStats(mail_server,
|
|
NetworkAnonymizationKey(), stats1);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetServerNetworkStats(mail_server,
|
|
NetworkAnonymizationKey(), stats1);
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(GetPendingMainThreadTaskCount(), 0u);
|
|
|
|
const ServerNetworkStats* stats2 = http_server_props_->GetServerNetworkStats(
|
|
mail_server, NetworkAnonymizationKey());
|
|
EXPECT_EQ(10, stats2->srtt.ToInternalValue());
|
|
|
|
http_server_props_->ClearServerNetworkStats(mail_server,
|
|
NetworkAnonymizationKey());
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_EQ(nullptr, http_server_props_->GetServerNetworkStats(
|
|
mail_server, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, QuicServerInfo) {
|
|
InitializePrefs();
|
|
|
|
quic::QuicServerId mail_quic_server_id("mail.google.com", 80, false);
|
|
EXPECT_EQ(nullptr, http_server_props_->GetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey()));
|
|
std::string quic_server_info1("quic_server_info1");
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
|
|
// Run the task.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_EQ(quic_server_info1,
|
|
*http_server_props_->GetQuicServerInfo(mail_quic_server_id,
|
|
NetworkAnonymizationKey()));
|
|
|
|
// Another task should not be scheduled.
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_EQ(0u, GetPendingMainThreadTaskCount());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, Clear) {
|
|
InitializePrefs();
|
|
|
|
const url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
|
|
const IPAddress actual_address(127, 0, 0, 1);
|
|
const quic::QuicServerId mail_quic_server_id("mail.google.com", 80, false);
|
|
const std::string quic_server_info1("quic_server_info1");
|
|
const AlternativeService alternative_service(kProtoHTTP2, "mail.google.com",
|
|
1234);
|
|
const AlternativeService broken_alternative_service(
|
|
kProtoHTTP2, "broken.google.com", 1234);
|
|
|
|
AlternativeServiceInfoVector alt_svc_info_vector;
|
|
alt_svc_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
alternative_service, one_day_from_now_));
|
|
alt_svc_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
broken_alternative_service, one_day_from_now_));
|
|
http_server_props_->SetAlternativeServices(
|
|
spdy_server, NetworkAnonymizationKey(), alt_svc_info_vector);
|
|
|
|
http_server_props_->MarkAlternativeServiceBroken(broken_alternative_service,
|
|
NetworkAnonymizationKey());
|
|
http_server_props_->SetSupportsSpdy(spdy_server, NetworkAnonymizationKey(),
|
|
true);
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
ServerNetworkStats stats;
|
|
stats.srtt = base::Microseconds(10);
|
|
http_server_props_->SetServerNetworkStats(spdy_server,
|
|
NetworkAnonymizationKey(), stats);
|
|
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
|
|
// Advance time by just enough so that the prefs update task is executed but
|
|
// not the task to expire the brokenness of |broken_alternative_service|.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
broken_alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(HasAlternativeService(spdy_server, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(
|
|
http_server_props_->WasLastLocalAddressWhenQuicWorked(actual_address));
|
|
const ServerNetworkStats* stats1 = http_server_props_->GetServerNetworkStats(
|
|
spdy_server, NetworkAnonymizationKey());
|
|
EXPECT_EQ(10, stats1->srtt.ToInternalValue());
|
|
EXPECT_EQ(quic_server_info1,
|
|
*http_server_props_->GetQuicServerInfo(mail_quic_server_id,
|
|
NetworkAnonymizationKey()));
|
|
|
|
// Clear http server data, which should instantly update prefs.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
bool callback_invoked_ = false;
|
|
http_server_props_->Clear(base::BindOnce(
|
|
[](bool* callback_invoked) {
|
|
EXPECT_FALSE(*callback_invoked);
|
|
*callback_invoked = true;
|
|
},
|
|
&callback_invoked_));
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_FALSE(callback_invoked_);
|
|
std::move(pref_delegate_->GetSetPropertiesCallback()).Run();
|
|
EXPECT_TRUE(callback_invoked_);
|
|
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
broken_alternative_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->SupportsRequestPriority(
|
|
spdy_server, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(HasAlternativeService(spdy_server, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->HasLastLocalAddressWhenQuicWorked());
|
|
const ServerNetworkStats* stats2 = http_server_props_->GetServerNetworkStats(
|
|
spdy_server, NetworkAnonymizationKey());
|
|
EXPECT_EQ(nullptr, stats2);
|
|
EXPECT_EQ(nullptr, http_server_props_->GetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
// https://crbug.com/444956: Add 200 alternative_service servers followed by
|
|
// supports_quic and verify we have read supports_quic from prefs.
|
|
TEST_F(HttpServerPropertiesManagerTest, BadLastLocalAddressWhenQuicWorked) {
|
|
base::Value::List servers_list;
|
|
|
|
for (int i = 1; i <= 200; ++i) {
|
|
// Set up alternative_service for www.google.com:i.
|
|
base::Value::Dict server_dict;
|
|
base::Value::Dict alternative_service_dict;
|
|
alternative_service_dict.Set("protocol_str", "quic");
|
|
alternative_service_dict.Set("port", i);
|
|
base::Value::List alternative_service_list;
|
|
alternative_service_list.Append(std::move(alternative_service_dict));
|
|
server_dict.Set("alternative_service", std::move(alternative_service_list));
|
|
server_dict.Set("server", StringPrintf("https://www.google.com:%d", i));
|
|
server_dict.Set("anonymization", base::Value(base::Value::Type::LIST));
|
|
servers_list.Append(std::move(server_dict));
|
|
}
|
|
|
|
// Set the server preference for http://mail.google.com server.
|
|
base::Value::Dict server_dict2;
|
|
server_dict2.Set("server", "https://mail.google.com");
|
|
server_dict2.Set("anonymization", base::Value(base::Value::Type::LIST));
|
|
servers_list.Append(std::move(server_dict2));
|
|
|
|
base::Value::Dict http_server_properties_dict = DictWithVersion();
|
|
http_server_properties_dict.Set("servers", std::move(servers_list));
|
|
|
|
// Set up SupportsQuic for 127.0.0.1
|
|
base::Value::Dict supports_quic;
|
|
supports_quic.Set("used_quic", true);
|
|
supports_quic.Set("address", "127.0.0.1");
|
|
http_server_properties_dict.Set("supports_quic", std::move(supports_quic));
|
|
|
|
// Set up the pref.
|
|
InitializePrefs(std::move(http_server_properties_dict));
|
|
|
|
// Verify alternative service.
|
|
for (int i = 1; i <= 200; ++i) {
|
|
GURL server_gurl;
|
|
server_gurl = GURL(StringPrintf("https://www.google.com:%d", i));
|
|
url::SchemeHostPort server(server_gurl);
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(
|
|
server, NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
EXPECT_EQ(
|
|
kProtoQUIC,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ(i, alternative_service_info_vector[0].alternative_service().port);
|
|
}
|
|
|
|
// Verify WasLastLocalAddressWhenQuicWorked.
|
|
ASSERT_TRUE(http_server_props_->WasLastLocalAddressWhenQuicWorked(
|
|
IPAddress::IPv4Localhost()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, UpdatePrefsWithCache) {
|
|
InitializePrefs();
|
|
|
|
const url::SchemeHostPort server_www("https", "www.google.com", 80);
|
|
const url::SchemeHostPort server_mail("https", "mail.google.com", 80);
|
|
|
|
// #1 & #2: Set alternate protocol.
|
|
AlternativeServiceInfoVector alternative_service_info_vector;
|
|
AlternativeService www_alternative_service1(kProtoHTTP2, "", 443);
|
|
base::Time expiration1;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
www_alternative_service1, expiration1));
|
|
|
|
AlternativeService www_alternative_service2(kProtoHTTP2, "www.google.com",
|
|
1234);
|
|
base::Time expiration2;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2));
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
www_alternative_service2, expiration2));
|
|
http_server_props_->SetAlternativeServices(
|
|
server_www, NetworkAnonymizationKey(), alternative_service_info_vector);
|
|
|
|
AlternativeService mail_alternative_service(kProtoHTTP2, "foo.google.com",
|
|
444);
|
|
base::Time expiration3 = base::Time::Max();
|
|
http_server_props_->SetHttp2AlternativeService(
|
|
server_mail, NetworkAnonymizationKey(), mail_alternative_service,
|
|
expiration3);
|
|
|
|
http_server_props_->MarkAlternativeServiceBroken(www_alternative_service2,
|
|
NetworkAnonymizationKey());
|
|
http_server_props_->MarkAlternativeServiceRecentlyBroken(
|
|
mail_alternative_service, NetworkAnonymizationKey());
|
|
|
|
// #3: Set SPDY server map
|
|
http_server_props_->SetSupportsSpdy(server_www, NetworkAnonymizationKey(),
|
|
false);
|
|
http_server_props_->SetSupportsSpdy(server_mail, NetworkAnonymizationKey(),
|
|
true);
|
|
http_server_props_->SetSupportsSpdy(
|
|
url::SchemeHostPort("http", "not_persisted.com", 80),
|
|
NetworkAnonymizationKey(), false);
|
|
|
|
// #4: Set ServerNetworkStats.
|
|
ServerNetworkStats stats;
|
|
stats.srtt = base::TimeDelta::FromInternalValue(42);
|
|
http_server_props_->SetServerNetworkStats(server_mail,
|
|
NetworkAnonymizationKey(), stats);
|
|
|
|
// #5: Set quic_server_info string.
|
|
quic::QuicServerId mail_quic_server_id("mail.google.com", 80, false);
|
|
std::string quic_server_info1("quic_server_info1");
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
|
|
// #6: Set SupportsQuic.
|
|
IPAddress actual_address(127, 0, 0, 1);
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
|
|
base::Time time_before_prefs_update = base::Time::Now();
|
|
|
|
// Update Prefs.
|
|
// The task runner has a remaining pending task to expire
|
|
// |www_alternative_service2| in 5 minutes. Fast forward enough such
|
|
// that the prefs update task is executed but not the task to expire
|
|
// |broken_alternative_service|.
|
|
EXPECT_EQ(2u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
EXPECT_EQ(1u, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
base::Time time_after_prefs_update = base::Time::Now();
|
|
|
|
// Verify |pref_delegate_|'s server dict.
|
|
// In HttpServerPropertiesManager, broken alternative services' expiration
|
|
// times are converted from TimeTicks to Time before being written to JSON by
|
|
// using the difference between Time::Now() and TimeTicks::Now().
|
|
// To verify these expiration times, |time_before_prefs_update| and
|
|
// |time_after_prefs_update| provide lower and upper bounds for the
|
|
// Time::Now() value used by the manager for this conversion.
|
|
//
|
|
// A copy of |pref_delegate_|'s server dict will be created, and the broken
|
|
// alternative service's "broken_until" field is removed and verified
|
|
// separately. The rest of the server dict copy is verified afterwards.
|
|
base::Value::Dict server_dict = pref_delegate_->GetServerProperties().Clone();
|
|
|
|
// Extract and remove the "broken_until" string for "www.google.com:1234".
|
|
base::Value::List* broken_alt_svc_list =
|
|
server_dict.FindList("broken_alternative_services");
|
|
ASSERT_TRUE(broken_alt_svc_list);
|
|
ASSERT_EQ(2u, broken_alt_svc_list->size());
|
|
base::Value& broken_alt_svcs_list_entry = (*broken_alt_svc_list)[0];
|
|
const std::string* broken_until_str =
|
|
broken_alt_svcs_list_entry.GetDict().FindString("broken_until");
|
|
ASSERT_TRUE(broken_until_str);
|
|
const std::string expiration_string = *broken_until_str;
|
|
broken_alt_svcs_list_entry.GetDict().Remove("broken_until");
|
|
|
|
// Expiration time of "www.google.com:1234" should be 5 minutes minus the
|
|
// update-prefs-delay from when the prefs were written.
|
|
int64_t expiration_int64;
|
|
ASSERT_TRUE(base::StringToInt64(expiration_string, &expiration_int64));
|
|
base::TimeDelta expiration_delta =
|
|
base::Minutes(5) - HttpServerProperties::GetUpdatePrefsDelayForTesting();
|
|
time_t time_t_of_prefs_update = static_cast<time_t>(expiration_int64);
|
|
EXPECT_LE((time_before_prefs_update + expiration_delta).ToTimeT(),
|
|
time_t_of_prefs_update);
|
|
EXPECT_GE((time_after_prefs_update + expiration_delta).ToTimeT(),
|
|
time_t_of_prefs_update);
|
|
|
|
// Verify all other preferences.
|
|
const char expected_json[] =
|
|
"{"
|
|
"\"broken_alternative_services\":"
|
|
"[{\"anonymization\":[],\"broken_count\":1,\"host\":\"www.google.com\","
|
|
"\"port\":1234,\"protocol_str\":\"h2\"},"
|
|
"{\"anonymization\":[],\"broken_count\":1,\"host\":\"foo.google.com\","
|
|
"\"port\":444,\"protocol_str\":\"h2\"}],"
|
|
"\"quic_servers\":"
|
|
"[{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}],"
|
|
"\"servers\":["
|
|
"{\"alternative_service\":[{\"advertised_alpns\":[],"
|
|
"\"expiration\":\"13756212000000000\",\"port\":443,"
|
|
"\"protocol_str\":\"h2\"},"
|
|
"{\"advertised_alpns\":[],\"expiration\":\"13758804000000000\","
|
|
"\"host\":\"www.google.com\",\"port\":1234,\"protocol_str\":\"h2\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"server\":\"https://www.google.com:80\"},"
|
|
"{\"alternative_service\":[{\"advertised_alpns\":[],"
|
|
"\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\","
|
|
"\"port\":444,\"protocol_str\":\"h2\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"network_stats\":{\"srtt\":42},"
|
|
"\"server\":\"https://mail.google.com:80\","
|
|
"\"supports_spdy\":true}],"
|
|
"\"supports_quic\":{\"address\":\"127.0.0.1\",\"used_quic\":true},"
|
|
"\"version\":5}";
|
|
|
|
std::string preferences_json;
|
|
EXPECT_TRUE(base::JSONWriter::Write(server_dict, &preferences_json));
|
|
EXPECT_EQ(expected_json, preferences_json);
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, ParseAlternativeServiceInfo) {
|
|
InitializePrefs();
|
|
|
|
base::Value::Dict server_dict = base::test::ParseJsonDict(
|
|
"{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"h2\"},"
|
|
"{\"port\":123,\"protocol_str\":\"quic\","
|
|
"\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\","
|
|
"\"port\":1234,\"protocol_str\":\"h2\","
|
|
"\"expiration\":\"13758804000000000\"}]}");
|
|
|
|
const url::SchemeHostPort server("https", "example.com", 443);
|
|
HttpServerProperties::ServerInfo server_info;
|
|
EXPECT_TRUE(HttpServerPropertiesManager::ParseAlternativeServiceInfo(
|
|
server, server_dict, &server_info));
|
|
|
|
ASSERT_TRUE(server_info.alternative_services.has_value());
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
server_info.alternative_services.value();
|
|
ASSERT_EQ(3u, alternative_service_info_vector.size());
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ("", alternative_service_info_vector[0].alternative_service().host);
|
|
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
|
|
// Expiration defaults to one day from now, testing with tolerance.
|
|
const base::Time now = base::Time::Now();
|
|
const base::Time expiration = alternative_service_info_vector[0].expiration();
|
|
EXPECT_LE(now + base::Hours(23), expiration);
|
|
EXPECT_GE(now + base::Days(1), expiration);
|
|
|
|
EXPECT_EQ(kProtoQUIC,
|
|
alternative_service_info_vector[1].alternative_service().protocol);
|
|
EXPECT_EQ("", alternative_service_info_vector[1].alternative_service().host);
|
|
EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service().port);
|
|
// numeric_limits<int64_t>::max() represents base::Time::Max().
|
|
EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration());
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[2].alternative_service().protocol);
|
|
EXPECT_EQ("example.org",
|
|
alternative_service_info_vector[2].alternative_service().host);
|
|
EXPECT_EQ(1234,
|
|
alternative_service_info_vector[2].alternative_service().port);
|
|
base::Time expected_expiration;
|
|
ASSERT_TRUE(
|
|
base::Time::FromUTCString("2036-12-31 10:00:00", &expected_expiration));
|
|
EXPECT_EQ(expected_expiration,
|
|
alternative_service_info_vector[2].expiration());
|
|
|
|
// No other fields should have been populated.
|
|
server_info.alternative_services.reset();
|
|
EXPECT_TRUE(server_info.empty());
|
|
}
|
|
|
|
// Regression test for https://crbug.com/615497.
|
|
TEST_F(HttpServerPropertiesManagerTest, DoNotLoadAltSvcForInsecureOrigins) {
|
|
InitializePrefs();
|
|
|
|
base::Value::Dict server_dict = base::test::ParseJsonDict(
|
|
"{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"h2\","
|
|
"\"expiration\":\"9223372036854775807\"}]}");
|
|
|
|
const url::SchemeHostPort server("http", "example.com", 80);
|
|
HttpServerProperties::ServerInfo server_info;
|
|
EXPECT_FALSE(HttpServerPropertiesManager::ParseAlternativeServiceInfo(
|
|
server, server_dict, &server_info));
|
|
EXPECT_TRUE(server_info.empty());
|
|
}
|
|
|
|
// Do not persist expired alternative service entries to disk.
|
|
TEST_F(HttpServerPropertiesManagerTest, DoNotPersistExpiredAlternativeService) {
|
|
InitializePrefs();
|
|
|
|
AlternativeServiceInfoVector alternative_service_info_vector;
|
|
|
|
const AlternativeService broken_alternative_service(
|
|
kProtoHTTP2, "broken.example.com", 443);
|
|
const base::Time time_one_day_later = base::Time::Now() + base::Days(1);
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
broken_alternative_service, time_one_day_later));
|
|
// #1: MarkAlternativeServiceBroken().
|
|
http_server_props_->MarkAlternativeServiceBroken(broken_alternative_service,
|
|
NetworkAnonymizationKey());
|
|
|
|
const AlternativeService expired_alternative_service(
|
|
kProtoHTTP2, "expired.example.com", 443);
|
|
const base::Time time_one_day_ago = base::Time::Now() - base::Days(1);
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
expired_alternative_service, time_one_day_ago));
|
|
|
|
const AlternativeService valid_alternative_service(kProtoHTTP2,
|
|
"valid.example.com", 443);
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
valid_alternative_service, time_one_day_later));
|
|
|
|
const url::SchemeHostPort server("https", "www.example.com", 443);
|
|
// #2: SetAlternativeServices().
|
|
http_server_props_->SetAlternativeServices(server, NetworkAnonymizationKey(),
|
|
alternative_service_info_vector);
|
|
|
|
// |net_test_task_runner_| has a remaining pending task to expire
|
|
// |broken_alternative_service| at |time_one_day_later|. Fast forward enough
|
|
// such that the prefs update task is executed but not the task to expire
|
|
// |broken_alternative_service|.
|
|
EXPECT_EQ(2U, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
EXPECT_EQ(1U, GetPendingMainThreadTaskCount());
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
const base::Value::Dict& pref_dict = pref_delegate_->GetServerProperties();
|
|
|
|
const base::Value::List* servers_list = pref_dict.FindList("servers");
|
|
ASSERT_TRUE(servers_list);
|
|
auto it = servers_list->begin();
|
|
const base::Value& server_pref_dict = *it;
|
|
ASSERT_TRUE(server_pref_dict.is_dict());
|
|
|
|
const std::string* server_str =
|
|
server_pref_dict.GetDict().FindString("server");
|
|
ASSERT_TRUE(server_str);
|
|
EXPECT_EQ("https://www.example.com", *server_str);
|
|
|
|
const base::Value* network_anonymization_key_value =
|
|
server_pref_dict.GetDict().Find("anonymization");
|
|
ASSERT_TRUE(network_anonymization_key_value);
|
|
ASSERT_EQ(base::Value::Type::LIST, network_anonymization_key_value->type());
|
|
EXPECT_TRUE(network_anonymization_key_value->GetList().empty());
|
|
|
|
const base::Value::List* altsvc_list =
|
|
server_pref_dict.GetDict().FindList("alternative_service");
|
|
ASSERT_TRUE(altsvc_list);
|
|
|
|
ASSERT_EQ(2u, altsvc_list->size());
|
|
|
|
const base::Value& altsvc_entry = (*altsvc_list)[0];
|
|
ASSERT_TRUE(altsvc_entry.is_dict());
|
|
const std::string* hostname = altsvc_entry.GetDict().FindString("host");
|
|
|
|
ASSERT_TRUE(hostname);
|
|
EXPECT_EQ("broken.example.com", *hostname);
|
|
|
|
const base::Value& altsvc_entry2 = (*altsvc_list)[1];
|
|
ASSERT_TRUE(altsvc_entry.is_dict());
|
|
hostname = altsvc_entry2.GetDict().FindString("host");
|
|
ASSERT_TRUE(hostname);
|
|
EXPECT_EQ("valid.example.com", *hostname);
|
|
}
|
|
|
|
// Test that expired alternative service entries on disk are ignored.
|
|
TEST_F(HttpServerPropertiesManagerTest, DoNotLoadExpiredAlternativeService) {
|
|
InitializePrefs();
|
|
|
|
base::Value::List alternative_service_list;
|
|
base::Value::Dict expired_dict;
|
|
expired_dict.Set("protocol_str", "h2");
|
|
expired_dict.Set("host", "expired.example.com");
|
|
expired_dict.Set("port", 443);
|
|
base::Time time_one_day_ago = base::Time::Now() - base::Days(1);
|
|
expired_dict.Set("expiration",
|
|
base::NumberToString(time_one_day_ago.ToInternalValue()));
|
|
alternative_service_list.Append(std::move(expired_dict));
|
|
|
|
base::Value::Dict valid_dict;
|
|
valid_dict.Set("protocol_str", "h2");
|
|
valid_dict.Set("host", "valid.example.com");
|
|
valid_dict.Set("port", 443);
|
|
valid_dict.Set("expiration",
|
|
base::NumberToString(one_day_from_now_.ToInternalValue()));
|
|
alternative_service_list.Append(std::move(valid_dict));
|
|
|
|
base::Value::Dict server_pref_dict;
|
|
server_pref_dict.Set("alternative_service",
|
|
std::move(alternative_service_list));
|
|
|
|
const url::SchemeHostPort server("https", "example.com", 443);
|
|
HttpServerProperties::ServerInfo server_info;
|
|
ASSERT_TRUE(HttpServerPropertiesManager::ParseAlternativeServiceInfo(
|
|
server, server_pref_dict, &server_info));
|
|
|
|
ASSERT_TRUE(server_info.alternative_services.has_value());
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
server_info.alternative_services.value();
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ("valid.example.com",
|
|
alternative_service_info_vector[0].alternative_service().host);
|
|
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
|
|
EXPECT_EQ(one_day_from_now_, alternative_service_info_vector[0].expiration());
|
|
|
|
// No other fields should have been populated.
|
|
server_info.alternative_services.reset();
|
|
EXPECT_TRUE(server_info.empty());
|
|
}
|
|
|
|
// Make sure prefs are updated on destruction.
|
|
TEST_F(HttpServerPropertiesManagerTest, UpdatePrefsOnShutdown) {
|
|
InitializePrefs();
|
|
|
|
int pref_updates = 0;
|
|
pref_delegate_->set_extra_update_prefs_callback(
|
|
base::BindRepeating([](int* updates) { (*updates)++; }, &pref_updates));
|
|
http_server_props_.reset();
|
|
EXPECT_EQ(1, pref_updates);
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, PersistAdvertisedVersionsToPref) {
|
|
InitializePrefs();
|
|
|
|
const url::SchemeHostPort server_www("https", "www.google.com", 80);
|
|
const url::SchemeHostPort server_mail("https", "mail.google.com", 80);
|
|
|
|
// #1 & #2: Set alternate protocol.
|
|
AlternativeServiceInfoVector alternative_service_info_vector;
|
|
// Quic alternative service set with two advertised QUIC versions.
|
|
AlternativeService quic_alternative_service1(kProtoQUIC, "", 443);
|
|
base::Time expiration1;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
|
|
quic::ParsedQuicVersionVector advertised_versions = {
|
|
quic::ParsedQuicVersion::Q046(), quic::ParsedQuicVersion::Q043()};
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
quic_alternative_service1, expiration1, advertised_versions));
|
|
// HTTP/2 alternative service should not set any advertised version.
|
|
AlternativeService h2_alternative_service(kProtoHTTP2, "www.google.com",
|
|
1234);
|
|
base::Time expiration2;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2));
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
h2_alternative_service, expiration2));
|
|
http_server_props_->SetAlternativeServices(
|
|
server_www, NetworkAnonymizationKey(), alternative_service_info_vector);
|
|
|
|
// Set another QUIC alternative service with a single advertised QUIC version.
|
|
AlternativeService mail_alternative_service(kProtoQUIC, "foo.google.com",
|
|
444);
|
|
base::Time expiration3 = base::Time::Max();
|
|
http_server_props_->SetQuicAlternativeService(
|
|
server_mail, NetworkAnonymizationKey(), mail_alternative_service,
|
|
expiration3, advertised_versions_);
|
|
// #3: Set ServerNetworkStats.
|
|
ServerNetworkStats stats;
|
|
stats.srtt = base::TimeDelta::FromInternalValue(42);
|
|
http_server_props_->SetServerNetworkStats(server_mail,
|
|
NetworkAnonymizationKey(), stats);
|
|
|
|
// #4: Set quic_server_info string.
|
|
quic::QuicServerId mail_quic_server_id("mail.google.com", 80, false);
|
|
std::string quic_server_info1("quic_server_info1");
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
|
|
// #5: Set SupportsQuic.
|
|
IPAddress actual_address(127, 0, 0, 1);
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
|
|
// Update Prefs.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Verify preferences with correct advertised version field.
|
|
const char expected_json[] =
|
|
"{\"quic_servers\":["
|
|
"{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}],"
|
|
"\"servers\":["
|
|
"{\"alternative_service\":[{"
|
|
"\"advertised_alpns\":[\"h3-Q046\",\"h3-Q043\"],\"expiration\":"
|
|
"\"13756212000000000\","
|
|
"\"port\":443,\"protocol_str\":\"quic\"},{\"advertised_alpns\":[],"
|
|
"\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\","
|
|
"\"port\":1234,\"protocol_str\":\"h2\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"server\":\"https://www.google.com:80\"},"
|
|
"{\"alternative_service\":[{"
|
|
"\"advertised_alpns\":[\"h3\"],"
|
|
"\"expiration\":\"9223372036854775807\","
|
|
"\"host\":\"foo.google.com\",\"port\":444,\"protocol_str\":\"quic\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"network_stats\":{\"srtt\":42},"
|
|
"\"server\":\"https://mail.google.com:80\"}],"
|
|
"\"supports_quic\":{"
|
|
"\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":5}";
|
|
|
|
const base::Value::Dict& http_server_properties =
|
|
pref_delegate_->GetServerProperties();
|
|
std::string preferences_json;
|
|
EXPECT_TRUE(
|
|
base::JSONWriter::Write(http_server_properties, &preferences_json));
|
|
EXPECT_EQ(expected_json, preferences_json);
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, ReadAdvertisedVersionsFromPref) {
|
|
InitializePrefs();
|
|
|
|
base::Value::Dict server_dict = base::test::ParseJsonDict(
|
|
"{\"alternative_service\":["
|
|
"{\"port\":443,\"protocol_str\":\"quic\"},"
|
|
"{\"port\":123,\"protocol_str\":\"quic\","
|
|
"\"expiration\":\"9223372036854775807\","
|
|
// Add 33 which we know is not supported, as regression test for
|
|
// https://crbug.com/1061509
|
|
"\"advertised_alpns\":[\"h3-Q033\",\"h3-Q046\",\"h3-Q043\"]}]}");
|
|
|
|
const url::SchemeHostPort server("https", "example.com", 443);
|
|
HttpServerProperties::ServerInfo server_info;
|
|
EXPECT_TRUE(HttpServerPropertiesManager::ParseAlternativeServiceInfo(
|
|
server, server_dict, &server_info));
|
|
|
|
ASSERT_TRUE(server_info.alternative_services.has_value());
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
server_info.alternative_services.value();
|
|
ASSERT_EQ(2u, alternative_service_info_vector.size());
|
|
|
|
// Verify the first alternative service with no advertised version listed.
|
|
EXPECT_EQ(kProtoQUIC,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ("", alternative_service_info_vector[0].alternative_service().host);
|
|
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
|
|
// Expiration defaults to one day from now, testing with tolerance.
|
|
const base::Time now = base::Time::Now();
|
|
const base::Time expiration = alternative_service_info_vector[0].expiration();
|
|
EXPECT_LE(now + base::Hours(23), expiration);
|
|
EXPECT_GE(now + base::Days(1), expiration);
|
|
EXPECT_TRUE(alternative_service_info_vector[0].advertised_versions().empty());
|
|
|
|
// Verify the second alterntaive service with two advertised versions.
|
|
EXPECT_EQ(kProtoQUIC,
|
|
alternative_service_info_vector[1].alternative_service().protocol);
|
|
EXPECT_EQ("", alternative_service_info_vector[1].alternative_service().host);
|
|
EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service().port);
|
|
EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration());
|
|
// Verify advertised versions.
|
|
const quic::ParsedQuicVersionVector loaded_advertised_versions =
|
|
alternative_service_info_vector[1].advertised_versions();
|
|
ASSERT_EQ(2u, loaded_advertised_versions.size());
|
|
EXPECT_EQ(quic::ParsedQuicVersion::Q043(), loaded_advertised_versions[0]);
|
|
EXPECT_EQ(quic::ParsedQuicVersion::Q046(), loaded_advertised_versions[1]);
|
|
|
|
// No other fields should have been populated.
|
|
server_info.alternative_services.reset();
|
|
EXPECT_TRUE(server_info.empty());
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
UpdatePrefWhenAdvertisedVersionsChange) {
|
|
InitializePrefs();
|
|
|
|
const url::SchemeHostPort server_www("https", "www.google.com", 80);
|
|
|
|
// #1: Set alternate protocol.
|
|
AlternativeServiceInfoVector alternative_service_info_vector;
|
|
// Quic alternative service set with a single QUIC version: Q046.
|
|
AlternativeService quic_alternative_service1(kProtoQUIC, "", 443);
|
|
base::Time expiration1;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1));
|
|
alternative_service_info_vector.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
quic_alternative_service1, expiration1, advertised_versions_));
|
|
http_server_props_->SetAlternativeServices(
|
|
server_www, NetworkAnonymizationKey(), alternative_service_info_vector);
|
|
|
|
// Set quic_server_info string.
|
|
quic::QuicServerId mail_quic_server_id("mail.google.com", 80, false);
|
|
std::string quic_server_info1("quic_server_info1");
|
|
http_server_props_->SetQuicServerInfo(
|
|
mail_quic_server_id, NetworkAnonymizationKey(), quic_server_info1);
|
|
|
|
// Set SupportsQuic.
|
|
IPAddress actual_address(127, 0, 0, 1);
|
|
http_server_props_->SetLastLocalAddressWhenQuicWorked(actual_address);
|
|
|
|
// Update Prefs.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Verify preferences with correct advertised version field.
|
|
const char expected_json[] =
|
|
"{\"quic_servers\":"
|
|
"[{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}],"
|
|
"\"servers\":["
|
|
"{\"alternative_service\":[{"
|
|
"\"advertised_alpns\":[\"h3\"],"
|
|
"\"expiration\":\"13756212000000000\",\"port\":443,"
|
|
"\"protocol_str\":\"quic\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"server\":\"https://www.google.com:80\"}],"
|
|
"\"supports_quic\":"
|
|
"{\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":5}";
|
|
|
|
const base::Value::Dict& http_server_properties =
|
|
pref_delegate_->GetServerProperties();
|
|
std::string preferences_json;
|
|
EXPECT_TRUE(
|
|
base::JSONWriter::Write(http_server_properties, &preferences_json));
|
|
EXPECT_EQ(expected_json, preferences_json);
|
|
|
|
// #2: Set AlternativeService with different advertised_versions for the same
|
|
// AlternativeService.
|
|
AlternativeServiceInfoVector alternative_service_info_vector_2;
|
|
// Quic alternative service set with two advertised QUIC versions.
|
|
quic::ParsedQuicVersionVector advertised_versions = {
|
|
quic::ParsedQuicVersion::Q046(), quic::ParsedQuicVersion::Q043()};
|
|
alternative_service_info_vector_2.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
quic_alternative_service1, expiration1, advertised_versions));
|
|
http_server_props_->SetAlternativeServices(
|
|
server_www, NetworkAnonymizationKey(), alternative_service_info_vector_2);
|
|
|
|
// Update Prefs.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Verify preferences updated with new advertised versions.
|
|
const char expected_json_updated[] =
|
|
"{\"quic_servers\":"
|
|
"[{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}],"
|
|
"\"servers\":["
|
|
"{\"alternative_service\":"
|
|
"[{\"advertised_alpns\":[\"h3-Q046\",\"h3-Q043\"],"
|
|
"\"expiration\":\"13756212000000000\",\"port\":443,"
|
|
"\"protocol_str\":\"quic\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"server\":\"https://www.google.com:80\"}],"
|
|
"\"supports_quic\":"
|
|
"{\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":5}";
|
|
EXPECT_TRUE(
|
|
base::JSONWriter::Write(http_server_properties, &preferences_json));
|
|
EXPECT_EQ(expected_json_updated, preferences_json);
|
|
|
|
// #3: Set AlternativeService with same advertised_versions.
|
|
AlternativeServiceInfoVector alternative_service_info_vector_3;
|
|
// A same set of QUIC versions but listed in a different order.
|
|
quic::ParsedQuicVersionVector advertised_versions_2 = {
|
|
quic::ParsedQuicVersion::Q043(), quic::ParsedQuicVersion::Q046()};
|
|
alternative_service_info_vector_3.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
quic_alternative_service1, expiration1, advertised_versions_2));
|
|
http_server_props_->SetAlternativeServices(
|
|
server_www, NetworkAnonymizationKey(), alternative_service_info_vector_3);
|
|
|
|
// Change in version ordering causes prefs update.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Verify preferences updated with new advertised versions.
|
|
const char expected_json_updated2[] =
|
|
"{\"quic_servers\":"
|
|
"[{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}],"
|
|
"\"servers\":["
|
|
"{\"alternative_service\":"
|
|
"[{\"advertised_alpns\":[\"h3-Q043\",\"h3-Q046\"],"
|
|
"\"expiration\":\"13756212000000000\",\"port\":443,"
|
|
"\"protocol_str\":\"quic\"}],"
|
|
"\"anonymization\":[],"
|
|
"\"server\":\"https://www.google.com:80\"}],"
|
|
"\"supports_quic\":"
|
|
"{\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":5}";
|
|
EXPECT_TRUE(
|
|
base::JSONWriter::Write(http_server_properties, &preferences_json));
|
|
EXPECT_EQ(expected_json_updated2, preferences_json);
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
|
|
AlternativeService cached_broken_service(kProtoQUIC, "cached_broken", 443);
|
|
AlternativeService cached_broken_service2(kProtoQUIC, "cached_broken2", 443);
|
|
AlternativeService cached_recently_broken_service(kProtoQUIC,
|
|
"cached_rbroken", 443);
|
|
|
|
http_server_props_->MarkAlternativeServiceBroken(cached_broken_service,
|
|
NetworkAnonymizationKey());
|
|
http_server_props_->MarkAlternativeServiceBroken(cached_broken_service2,
|
|
NetworkAnonymizationKey());
|
|
http_server_props_->MarkAlternativeServiceRecentlyBroken(
|
|
cached_recently_broken_service, NetworkAnonymizationKey());
|
|
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
// There should be a task to remove remove alt services from the cache of
|
|
// broken alt services. There should be no task to update the prefs, since the
|
|
// prefs file hasn't been loaded yet.
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
|
|
// Load the |pref_delegate_| with some JSON to verify updating the cache from
|
|
// prefs. For the broken alternative services "www.google.com:1234" and
|
|
// "cached_broken", the expiration time will be one day from now.
|
|
|
|
std::string expiration_str =
|
|
base::NumberToString(static_cast<int64_t>(one_day_from_now_.ToTimeT()));
|
|
|
|
base::Value::Dict server_dict = base::test::ParseJsonDict(
|
|
"{"
|
|
"\"broken_alternative_services\":["
|
|
"{\"broken_until\":\"" +
|
|
expiration_str +
|
|
"\","
|
|
"\"host\":\"www.google.com\",\"anonymization\":[],"
|
|
"\"port\":1234,\"protocol_str\":\"h2\"},"
|
|
"{\"broken_count\":2,\"broken_until\":\"" +
|
|
expiration_str +
|
|
"\","
|
|
"\"host\":\"cached_broken\",\"anonymization\":[],"
|
|
"\"port\":443,\"protocol_str\":\"quic\"},"
|
|
"{\"broken_count\":3,"
|
|
"\"host\":\"cached_rbroken\",\"anonymization\":[],"
|
|
"\"port\":443,\"protocol_str\":\"quic\"}],"
|
|
"\"quic_servers\":["
|
|
"{\"anonymization\":[],"
|
|
"\"server_id\":\"https://mail.google.com:80\","
|
|
"\"server_info\":\"quic_server_info1\"}"
|
|
"],"
|
|
"\"servers\":["
|
|
"{\"server\":\"https://www.google.com:80\","
|
|
"\"anonymization\":[],"
|
|
"\"alternative_service\":["
|
|
"{\"expiration\":\"13756212000000000\",\"port\":443,"
|
|
"\"protocol_str\":\"h2\"},"
|
|
"{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\","
|
|
"\"port\":1234,\"protocol_str\":\"h2\"}"
|
|
"]"
|
|
"},"
|
|
"{\"server\":\"https://mail.google.com:80\","
|
|
"\"anonymization\":[],"
|
|
"\"alternative_service\":["
|
|
"{\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\","
|
|
"\"port\":444,\"protocol_str\":\"h2\"}"
|
|
"],"
|
|
"\"network_stats\":{\"srtt\":42}"
|
|
"}"
|
|
"],"
|
|
"\"supports_quic\":"
|
|
"{\"address\":\"127.0.0.1\",\"used_quic\":true},"
|
|
"\"version\":5"
|
|
"}");
|
|
|
|
// Don't use the test fixture's InitializePrefs() method, since there are
|
|
// pending tasks. Initializing prefs should queue a pref update task, since
|
|
// prefs have been modified.
|
|
pref_delegate_->InitializePrefs(std::move(server_dict));
|
|
EXPECT_TRUE(http_server_props_->IsInitialized());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
|
|
// Run until prefs are updated.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
|
|
//
|
|
// Verify alternative service info for https://www.google.com
|
|
//
|
|
AlternativeServiceInfoVector alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(
|
|
url::SchemeHostPort("https", "www.google.com", 80),
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(2u, alternative_service_info_vector.size());
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ("www.google.com",
|
|
alternative_service_info_vector[0].alternative_service().host);
|
|
EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service().port);
|
|
EXPECT_EQ(
|
|
"13756212000000000",
|
|
base::NumberToString(
|
|
alternative_service_info_vector[0].expiration().ToInternalValue()));
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[1].alternative_service().protocol);
|
|
EXPECT_EQ("www.google.com",
|
|
alternative_service_info_vector[1].alternative_service().host);
|
|
EXPECT_EQ(1234,
|
|
alternative_service_info_vector[1].alternative_service().port);
|
|
EXPECT_EQ(
|
|
"13758804000000000",
|
|
base::NumberToString(
|
|
alternative_service_info_vector[1].expiration().ToInternalValue()));
|
|
|
|
//
|
|
// Verify alternative service info for https://mail.google.com
|
|
//
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(
|
|
url::SchemeHostPort("https", "mail.google.com", 80),
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
|
|
EXPECT_EQ(kProtoHTTP2,
|
|
alternative_service_info_vector[0].alternative_service().protocol);
|
|
EXPECT_EQ("foo.google.com",
|
|
alternative_service_info_vector[0].alternative_service().host);
|
|
EXPECT_EQ(444, alternative_service_info_vector[0].alternative_service().port);
|
|
EXPECT_EQ(
|
|
"9223372036854775807",
|
|
base::NumberToString(
|
|
alternative_service_info_vector[0].expiration().ToInternalValue()));
|
|
|
|
//
|
|
// Verify broken alternative services.
|
|
//
|
|
AlternativeService prefs_broken_service(kProtoHTTP2, "www.google.com", 1234);
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
|
|
// Verify brokenness expiration times.
|
|
// |cached_broken_service|'s expiration time should've been overwritten by the
|
|
// prefs to be approximately 1 day from now. |cached_broken_service2|'s
|
|
// expiration time should still be 5 minutes due to being marked broken.
|
|
// |prefs_broken_service|'s expiration time should be approximately 1 day from
|
|
// now which comes from the prefs.
|
|
FastForwardBy(base::Minutes(5) -
|
|
HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
FastForwardBy(base::Days(1));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
|
|
// Now that |prefs_broken_service|'s brokenness has expired, it should've
|
|
// been removed from the alternative services info vectors of all servers.
|
|
alternative_service_info_vector =
|
|
http_server_props_->GetAlternativeServiceInfos(
|
|
url::SchemeHostPort("https", "www.google.com", 80),
|
|
NetworkAnonymizationKey());
|
|
ASSERT_EQ(1u, alternative_service_info_vector.size());
|
|
|
|
//
|
|
// Verify recently broken alternative services.
|
|
//
|
|
|
|
// If an entry is already in cache, the broken count in the prefs should
|
|
// overwrite the one in the cache.
|
|
// |prefs_broken_service| should have broken-count 1 from prefs.
|
|
// |cached_recently_broken_service| should have broken-count 3 from prefs.
|
|
// |cached_broken_service| should have broken-count 2 from prefs.
|
|
// |cached_broken_service2| should have broken-count 1 from being marked
|
|
// broken.
|
|
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
cached_recently_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(http_server_props_->WasAlternativeServiceRecentlyBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
// Make sure |prefs_broken_service| has the right expiration delay when marked
|
|
// broken. Since |prefs_broken_service| had no broken_count specified in the
|
|
// prefs, a broken_count value of 1 should have been assumed by
|
|
// |http_server_props_|.
|
|
http_server_props_->MarkAlternativeServiceBroken(prefs_broken_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardBy(base::Minutes(10) - base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
FastForwardBy(base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
prefs_broken_service, NetworkAnonymizationKey()));
|
|
// Make sure |cached_recently_broken_service| has the right expiration delay
|
|
// when marked broken.
|
|
http_server_props_->MarkAlternativeServiceBroken(
|
|
cached_recently_broken_service, NetworkAnonymizationKey());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardBy(base::Minutes(40) - base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_recently_broken_service, NetworkAnonymizationKey()));
|
|
FastForwardBy(base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_recently_broken_service, NetworkAnonymizationKey()));
|
|
// Make sure |cached_broken_service| has the right expiration delay when
|
|
// marked broken.
|
|
http_server_props_->MarkAlternativeServiceBroken(cached_broken_service,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardBy(base::Minutes(20) - base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
FastForwardBy(base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service, NetworkAnonymizationKey()));
|
|
// Make sure |cached_broken_service2| has the right expiration delay when
|
|
// marked broken.
|
|
http_server_props_->MarkAlternativeServiceBroken(cached_broken_service2,
|
|
NetworkAnonymizationKey());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardBy(base::Minutes(10) - base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_TRUE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
FastForwardBy(base::TimeDelta::FromInternalValue(1));
|
|
EXPECT_FALSE(http_server_props_->IsAlternativeServiceBroken(
|
|
cached_broken_service2, NetworkAnonymizationKey()));
|
|
|
|
//
|
|
// Verify ServerNetworkStats.
|
|
//
|
|
const ServerNetworkStats* server_network_stats =
|
|
http_server_props_->GetServerNetworkStats(
|
|
url::SchemeHostPort("https", "mail.google.com", 80),
|
|
NetworkAnonymizationKey());
|
|
EXPECT_TRUE(server_network_stats);
|
|
EXPECT_EQ(server_network_stats->srtt, base::TimeDelta::FromInternalValue(42));
|
|
|
|
//
|
|
// Verify QUIC server info.
|
|
//
|
|
const std::string* quic_server_info = http_server_props_->GetQuicServerInfo(
|
|
quic::QuicServerId("mail.google.com", 80, false),
|
|
NetworkAnonymizationKey());
|
|
EXPECT_EQ("quic_server_info1", *quic_server_info);
|
|
|
|
//
|
|
// Verify supports QUIC.
|
|
//
|
|
IPAddress actual_address(127, 0, 0, 1);
|
|
EXPECT_TRUE(
|
|
http_server_props_->WasLastLocalAddressWhenQuicWorked(actual_address));
|
|
EXPECT_EQ(4, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
}
|
|
|
|
// Check the interaction of ForceHTTP11 with saving/restoring settings.
|
|
// In particular, ForceHTTP11 is not saved, and it should not overwrite or be
|
|
// overitten by loaded data.
|
|
TEST_F(HttpServerPropertiesManagerTest, ForceHTTP11) {
|
|
const url::SchemeHostPort kServer1("https", "foo.test", 443);
|
|
const url::SchemeHostPort kServer2("https", "bar.test", 443);
|
|
const url::SchemeHostPort kServer3("https", "baz.test", 443);
|
|
|
|
// Create and initialize an HttpServerProperties with no state.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set kServer1 to support H2, but require HTTP/1.1. Set kServer2 to only
|
|
// require HTTP/1.1.
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->RequiresHTTP11(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->RequiresHTTP11(kServer2, NetworkAnonymizationKey()));
|
|
properties->SetSupportsSpdy(kServer1, NetworkAnonymizationKey(), true);
|
|
properties->SetHTTP11Required(kServer1, NetworkAnonymizationKey());
|
|
properties->SetHTTP11Required(kServer2, NetworkAnonymizationKey());
|
|
EXPECT_TRUE(properties->GetSupportsSpdy(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer2, NetworkAnonymizationKey()));
|
|
|
|
// Wait until the data's been written to prefs, and then tear down the
|
|
// HttpServerProperties.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
base::Value::Dict saved_value =
|
|
unowned_pref_delegate->GetServerProperties().Clone();
|
|
properties.reset();
|
|
|
|
// Only information on kServer1 should have been saved to prefs.
|
|
std::string preferences_json;
|
|
base::JSONWriter::Write(saved_value, &preferences_json);
|
|
EXPECT_EQ(
|
|
"{\"servers\":["
|
|
"{\"anonymization\":[],"
|
|
"\"server\":\"https://foo.test\","
|
|
"\"supports_spdy\":true}],"
|
|
"\"version\":5}",
|
|
preferences_json);
|
|
|
|
// Create a new HttpServerProperties using the value saved to prefs above.
|
|
pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
unowned_pref_delegate = pref_delegate.get();
|
|
properties = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
|
|
// Before the data has loaded, set kServer1 and kServer3 as requiring
|
|
// HTTP/1.1.
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->RequiresHTTP11(kServer1, NetworkAnonymizationKey()));
|
|
properties->SetHTTP11Required(kServer1, NetworkAnonymizationKey());
|
|
properties->SetHTTP11Required(kServer3, NetworkAnonymizationKey());
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->RequiresHTTP11(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer3, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer3, NetworkAnonymizationKey()));
|
|
|
|
// The data loads.
|
|
unowned_pref_delegate->InitializePrefs(std::move(saved_value));
|
|
|
|
// The properties should contain a combination of the old and new data.
|
|
EXPECT_TRUE(properties->GetSupportsSpdy(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->RequiresHTTP11(kServer2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer3, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->RequiresHTTP11(kServer3, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, NetworkAnonymizationKeyServerInfo) {
|
|
const SchemefulSite kSite1(GURL("https://foo.test/"));
|
|
const SchemefulSite kSite2(GURL("https://bar.test/"));
|
|
const SchemefulSite kOpaqueSite(GURL("data:text/plain,Hello World"));
|
|
const url::SchemeHostPort kServer("https", "baz.test", 443);
|
|
const url::SchemeHostPort kServer2("https", "zab.test", 443);
|
|
|
|
HttpServerProperties::ServerInfo server_info;
|
|
server_info.supports_spdy = true;
|
|
|
|
for (auto save_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(save_network_anonymization_key_mode));
|
|
|
|
// Save prefs using |save_network_anonymization_key_mode|.
|
|
base::Value::Dict saved_value;
|
|
{
|
|
// Configure the the feature.
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(save_network_anonymization_key_mode);
|
|
|
|
// This parameter is normally calculated by HttpServerProperties based on
|
|
// the kPartitionHttpServerPropertiesByNetworkIsolationKey feature, but
|
|
// this test doesn't use that class.
|
|
bool use_network_anonymization_key =
|
|
save_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled;
|
|
|
|
HttpServerProperties::ServerInfoMap server_info_map;
|
|
|
|
// Add server info entry using two origins with value of |server_info|.
|
|
// NetworkAnonymizationKey's constructor takes the state of the
|
|
// kAppendFrameOriginToNetworkAnonymizationKey feature into account, so
|
|
// need to make sure to call the constructor after setting up the feature
|
|
// above.
|
|
HttpServerProperties::ServerInfoMapKey server_info_key(
|
|
kServer, NetworkAnonymizationKey::CreateCrossSite(kSite1),
|
|
use_network_anonymization_key);
|
|
server_info_map.Put(server_info_key, server_info);
|
|
|
|
// Also add an etry with an opaque origin, if
|
|
// |use_network_anonymization_key| is true. This value should not be saved
|
|
// to disk, since opaque origins are only meaningful within a browsing
|
|
// session.
|
|
if (use_network_anonymization_key) {
|
|
HttpServerProperties::ServerInfoMapKey server_info_key2(
|
|
kServer2, NetworkAnonymizationKey::CreateSameSite(kOpaqueSite),
|
|
use_network_anonymization_key);
|
|
server_info_map.Put(server_info_key2, server_info);
|
|
}
|
|
|
|
saved_value = ServerInfoMapToDict(server_info_map);
|
|
}
|
|
|
|
for (auto load_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(load_network_anonymization_key_mode));
|
|
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(load_network_anonymization_key_mode);
|
|
std::unique_ptr<HttpServerProperties::ServerInfoMap> server_info_map2 =
|
|
DictToServerInfoMap(saved_value.Clone());
|
|
ASSERT_TRUE(server_info_map2);
|
|
if (save_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
// If NetworkAnonymizationKey was disabled when saving, it was saved
|
|
// with an empty NetworkAnonymizationKey, which should always be loaded
|
|
// successfully. This is needed to continue to support consumers that
|
|
// don't use NetworkAnonymizationKeys.
|
|
ASSERT_EQ(1u, server_info_map2->size());
|
|
const HttpServerProperties::ServerInfoMapKey& server_info_key2 =
|
|
server_info_map2->begin()->first;
|
|
const HttpServerProperties::ServerInfo& server_info2 =
|
|
server_info_map2->begin()->second;
|
|
EXPECT_EQ(kServer, server_info_key2.server);
|
|
EXPECT_EQ(NetworkAnonymizationKey(),
|
|
server_info_key2.network_anonymization_key);
|
|
EXPECT_EQ(server_info, server_info2);
|
|
} else if (save_network_anonymization_key_mode ==
|
|
load_network_anonymization_key_mode) {
|
|
// If the save and load modes are the same, the load should succeed, and
|
|
// the network anonymization keys should match.
|
|
ASSERT_EQ(1u, server_info_map2->size());
|
|
const HttpServerProperties::ServerInfoMapKey& server_info_key2 =
|
|
server_info_map2->begin()->first;
|
|
const HttpServerProperties::ServerInfo& server_info2 =
|
|
server_info_map2->begin()->second;
|
|
EXPECT_EQ(kServer, server_info_key2.server);
|
|
EXPECT_EQ(NetworkAnonymizationKey::CreateCrossSite(kSite1),
|
|
server_info_key2.network_anonymization_key);
|
|
EXPECT_EQ(server_info, server_info2);
|
|
} else {
|
|
// Otherwise, the NetworkAnonymizationKey doesn't make sense with the
|
|
// current feature values, so the ServerInfo should be discarded.
|
|
EXPECT_EQ(0u, server_info_map2->size());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tests a full round trip with a NetworkAnonymizationKey, using the
|
|
// HttpServerProperties interface.
|
|
TEST_F(HttpServerPropertiesManagerTest, NetworkAnonymizationKeyIntegration) {
|
|
const SchemefulSite kSite(GURL("https://foo.test/"));
|
|
const auto kNetworkAnonymizationKey =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite);
|
|
const url::SchemeHostPort kServer("https", "baz.test", 443);
|
|
|
|
const SchemefulSite kOpaqueSite(GURL("data:text/plain,Hello World"));
|
|
const auto kOpaqueSiteNetworkAnonymizationKey =
|
|
NetworkAnonymizationKey::CreateSameSite(kOpaqueSite);
|
|
const url::SchemeHostPort kServer2("https", "zab.test", 443);
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create and initialize an HttpServerProperties with no state.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set a values using kNetworkAnonymizationKey.
|
|
properties->SetSupportsSpdy(kServer, kNetworkAnonymizationKey, true);
|
|
EXPECT_TRUE(properties->GetSupportsSpdy(kServer, kNetworkAnonymizationKey));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer, kOpaqueSiteNetworkAnonymizationKey));
|
|
EXPECT_FALSE(properties->GetSupportsSpdy(kServer, NetworkAnonymizationKey()));
|
|
|
|
// Opaque origins should works with HttpServerProperties, but not be persisted
|
|
// to disk.
|
|
properties->SetSupportsSpdy(kServer2, kOpaqueSiteNetworkAnonymizationKey,
|
|
true);
|
|
EXPECT_FALSE(properties->GetSupportsSpdy(kServer2, kNetworkAnonymizationKey));
|
|
EXPECT_TRUE(properties->GetSupportsSpdy(kServer2,
|
|
kOpaqueSiteNetworkAnonymizationKey));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
|
|
// Wait until the data's been written to prefs, and then tear down the
|
|
// HttpServerProperties.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
base::Value::Dict saved_value =
|
|
unowned_pref_delegate->GetServerProperties().Clone();
|
|
properties.reset();
|
|
|
|
// Create a new HttpServerProperties using the value saved to prefs above.
|
|
pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
unowned_pref_delegate = pref_delegate.get();
|
|
properties = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(std::move(saved_value));
|
|
|
|
// The information set using kNetworkAnonymizationKey on the original
|
|
// HttpServerProperties should also be set on the restored
|
|
// HttpServerProperties.
|
|
EXPECT_TRUE(properties->GetSupportsSpdy(kServer, kNetworkAnonymizationKey));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer, kOpaqueSiteNetworkAnonymizationKey));
|
|
EXPECT_FALSE(properties->GetSupportsSpdy(kServer, NetworkAnonymizationKey()));
|
|
|
|
// The information set using kOpaqueSiteNetworkAnonymizationKey should not
|
|
// have been restored.
|
|
EXPECT_FALSE(properties->GetSupportsSpdy(kServer2, kNetworkAnonymizationKey));
|
|
EXPECT_FALSE(properties->GetSupportsSpdy(kServer2,
|
|
kOpaqueSiteNetworkAnonymizationKey));
|
|
EXPECT_FALSE(
|
|
properties->GetSupportsSpdy(kServer2, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
// Tests a full round trip to prefs and back in the canonical suffix case.
|
|
// Enable NetworkAnonymizationKeys, as they have some interactions with the
|
|
// canonical suffix logic.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
CanonicalSuffixRoundTripWithNetworkAnonymizationKey) {
|
|
const SchemefulSite kSite1(GURL("https://foo.test/"));
|
|
const SchemefulSite kSite2(GURL("https://bar.test/"));
|
|
const auto kNetworkAnonymizationKey1 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite1);
|
|
const auto kNetworkAnonymizationKey2 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite2);
|
|
// Three servers with the same canonical suffix (".c.youtube.com").
|
|
const url::SchemeHostPort kServer1("https", "foo.c.youtube.com", 443);
|
|
const url::SchemeHostPort kServer2("https", "bar.c.youtube.com", 443);
|
|
const url::SchemeHostPort kServer3("https", "baz.c.youtube.com", 443);
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create three alt service vectors of different lengths.
|
|
base::Time expiration = base::Time::Now() + base::Days(1);
|
|
AlternativeServiceInfo alt_service1 =
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
AlternativeService(kProtoQUIC, "foopy.c.youtube.com", 1234),
|
|
expiration, DefaultSupportedQuicVersions());
|
|
AlternativeServiceInfo alt_service2 =
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
AlternativeService(kProtoHTTP2, "foopy.c.youtube.com", 443),
|
|
expiration);
|
|
AlternativeServiceInfo alt_service3 =
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
AlternativeService(kProtoHTTP2, "foopy2.c.youtube.com", 443),
|
|
expiration);
|
|
AlternativeServiceInfoVector alt_service_vector1 = {alt_service1};
|
|
AlternativeServiceInfoVector alt_service_vector2 = {alt_service1,
|
|
alt_service2};
|
|
AlternativeServiceInfoVector alt_service_vector3 = {
|
|
alt_service1, alt_service2, alt_service3};
|
|
|
|
// Create and initialize an HttpServerProperties with no state.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set alternative services for kServer1 using kNetworkAnonymizationKey1. That
|
|
// information should be retrieved when fetching information for any server
|
|
// with the same canonical suffix, when using kNetworkAnonymizationKey1.
|
|
properties->SetAlternativeServices(kServer1, kNetworkAnonymizationKey1,
|
|
alt_service_vector1);
|
|
EXPECT_EQ(
|
|
1u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
1u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
1u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
0u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey2)
|
|
.size());
|
|
|
|
// Set different alternative services for kServer2 using
|
|
// kNetworkAnonymizationKey1. It should not affect information retrieved for
|
|
// kServer1, but should for kServer2 and kServer3.
|
|
properties->SetAlternativeServices(kServer2, kNetworkAnonymizationKey1,
|
|
alt_service_vector2);
|
|
EXPECT_EQ(
|
|
1u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
0u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey2)
|
|
.size());
|
|
|
|
// Set different information for kServer1 using kNetworkAnonymizationKey2. It
|
|
// should not affect information stored for kNetworkAnonymizationKey1.
|
|
properties->SetAlternativeServices(kServer1, kNetworkAnonymizationKey2,
|
|
alt_service_vector3);
|
|
EXPECT_EQ(
|
|
1u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey2)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey2)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey2)
|
|
.size());
|
|
|
|
// Wait until the data's been written to prefs, and then tear down the
|
|
// HttpServerProperties.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
base::Value::Dict saved_value =
|
|
unowned_pref_delegate->GetServerProperties().Clone();
|
|
properties.reset();
|
|
|
|
// Create a new HttpServerProperties using the value saved to prefs above.
|
|
pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
unowned_pref_delegate = pref_delegate.get();
|
|
properties = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(std::move(saved_value));
|
|
|
|
// Only the last of the values learned for kNetworkAnonymizationKey1 should
|
|
// have been saved, and the value for kNetworkAnonymizationKey2 as well. The
|
|
// canonical suffix logic should still be respected.
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
2u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey1)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer1, kNetworkAnonymizationKey2)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer2, kNetworkAnonymizationKey2)
|
|
.size());
|
|
EXPECT_EQ(
|
|
3u, properties
|
|
->GetAlternativeServiceInfos(kServer3, kNetworkAnonymizationKey2)
|
|
.size());
|
|
}
|
|
|
|
// Tests a full round trip with a NetworkAnonymizationKey, using the
|
|
// HttpServerProperties interface and setting alternative services as broken.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
NetworkAnonymizationKeyBrokenAltServiceRoundTrip) {
|
|
const SchemefulSite kSite1(GURL("https://foo1.test/"));
|
|
const SchemefulSite kSite2(GURL("https://foo2.test/"));
|
|
const auto kNetworkAnonymizationKey1 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite1);
|
|
const auto kNetworkAnonymizationKey2 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite2);
|
|
|
|
const AlternativeService kAlternativeService1(kProtoHTTP2,
|
|
"alt.service1.test", 443);
|
|
const AlternativeService kAlternativeService2(kProtoHTTP2,
|
|
"alt.service2.test", 443);
|
|
|
|
for (auto save_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(save_network_anonymization_key_mode));
|
|
|
|
// Save prefs using |save_network_anonymization_key_mode|.
|
|
base::Value::Dict saved_value;
|
|
{
|
|
// Configure the the feature.
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(save_network_anonymization_key_mode);
|
|
|
|
// Create and initialize an HttpServerProperties, must be done after
|
|
// setting the feature.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set kAlternativeService1 as broken in the context of
|
|
// kNetworkAnonymizationKey1, and kAlternativeService2 as broken in the
|
|
// context of the empty NetworkAnonymizationKey2, and recently broken in
|
|
// the context of the empty NetworkAnonymizationKey.
|
|
properties->MarkAlternativeServiceBroken(kAlternativeService1,
|
|
kNetworkAnonymizationKey1);
|
|
properties->MarkAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey());
|
|
properties->MarkAlternativeServiceBroken(kAlternativeService2,
|
|
kNetworkAnonymizationKey2);
|
|
|
|
// Verify values were set.
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
// When NetworkAnonymizationKeys are disabled, kAlternativeService2 is
|
|
// marked as broken regardless of the values passed to
|
|
// NetworkAnonymizationKey's constructor.
|
|
EXPECT_EQ(save_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled,
|
|
properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
|
|
// If NetworkAnonymizationKeys are enabled, there should be no
|
|
// cross-contamination of the NetworkAnonymizationKeys.
|
|
if (save_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
}
|
|
|
|
// Wait until the data's been written to prefs, and then create a copy of
|
|
// the prefs data.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
saved_value = unowned_pref_delegate->GetServerProperties().Clone();
|
|
}
|
|
|
|
// Now try and load the data in each of the feature modes.
|
|
for (auto load_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(load_network_anonymization_key_mode));
|
|
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(load_network_anonymization_key_mode);
|
|
|
|
// Create a new HttpServerProperties, loading the data from before.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(saved_value.Clone());
|
|
|
|
if (save_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
// If NetworkAnonymizationKey was disabled when saving, it was saved
|
|
// with an empty NetworkAnonymizationKey, which should always be loaded
|
|
// successfully. This is needed to continue to support consumers that
|
|
// don't use NetworkAnonymizationKeys.
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
} else if (save_network_anonymization_key_mode ==
|
|
load_network_anonymization_key_mode) {
|
|
// If the save and load modes are the same, the load should succeed, and
|
|
// the network anonymization keys should match.
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
// When NetworkAnonymizationKeys are disabled, kAlternativeService2 is
|
|
// marked as broken regardless of the values passed to
|
|
// NetworkAnonymizationKey's constructor.
|
|
EXPECT_EQ(save_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled,
|
|
properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
|
|
// If NetworkAnonymizationKeys are enabled, there should be no
|
|
// cross-contamination of the NetworkAnonymizationKeys.
|
|
if (save_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
}
|
|
} else {
|
|
// Otherwise, only the values set with an empty NetworkAnonymizationKey
|
|
// should have been loaded successfully.
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
// If the load mode is NetworkAnonymizationKeyMode::kDisabled,
|
|
// kNetworkAnonymizationKey2 is NetworkAnonymizationKey().
|
|
EXPECT_EQ(load_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled,
|
|
properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey2));
|
|
|
|
// There should be no cross-contamination of NetworkAnonymizationKeys,
|
|
// if NetworkAnonymizationKeys are enabled.
|
|
if (load_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService2, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, NetworkAnonymizationKey()));
|
|
EXPECT_FALSE(properties->IsAlternativeServiceBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
EXPECT_FALSE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService1, kNetworkAnonymizationKey2));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure broken alt services with opaque origins aren't saved.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
NetworkAnonymizationKeyBrokenAltServiceOpaqueOrigin) {
|
|
const SchemefulSite kOpaqueSite(GURL("data:text/plain,Hello World"));
|
|
const auto kNetworkAnonymizationKey =
|
|
NetworkAnonymizationKey::CreateSameSite(kOpaqueSite);
|
|
const AlternativeService kAlternativeService(kProtoHTTP2, "alt.service1.test",
|
|
443);
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create and initialize an HttpServerProperties, must be done after
|
|
// setting the feature.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
properties->MarkAlternativeServiceBroken(kAlternativeService,
|
|
kNetworkAnonymizationKey);
|
|
|
|
// Verify values were set.
|
|
EXPECT_TRUE(properties->IsAlternativeServiceBroken(kAlternativeService,
|
|
kNetworkAnonymizationKey));
|
|
EXPECT_TRUE(properties->WasAlternativeServiceRecentlyBroken(
|
|
kAlternativeService, kNetworkAnonymizationKey));
|
|
|
|
// Wait until the data's been written to prefs, and then create a copy of
|
|
// the prefs data.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
|
|
// No information should have been saved to prefs.
|
|
std::string preferences_json;
|
|
base::JSONWriter::Write(unowned_pref_delegate->GetServerProperties(),
|
|
&preferences_json);
|
|
EXPECT_EQ("{\"servers\":[],\"version\":5}", preferences_json);
|
|
}
|
|
|
|
// Tests a full round trip with a NetworkAnonymizationKey, using the
|
|
// HttpServerProperties interface and setting QuicServerInfo.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
NetworkAnonymizationKeyQuicServerInfoRoundTrip) {
|
|
const SchemefulSite kSite1(GURL("https://foo1.test/"));
|
|
const SchemefulSite kSite2(GURL("https://foo2.test/"));
|
|
const auto kNetworkAnonymizationKey1 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite1);
|
|
const auto kNetworkAnonymizationKey2 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite2);
|
|
|
|
const quic::QuicServerId kServer1("foo", 443,
|
|
false /* privacy_mode_enabled */);
|
|
const quic::QuicServerId kServer2("foo", 443,
|
|
true /* privacy_mode_enabled */);
|
|
|
|
const char kQuicServerInfo1[] = "info1";
|
|
const char kQuicServerInfo2[] = "info2";
|
|
const char kQuicServerInfo3[] = "info3";
|
|
|
|
for (auto save_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(save_network_anonymization_key_mode));
|
|
|
|
// Save prefs using |save_network_anonymization_key_mode|.
|
|
base::Value::Dict saved_value;
|
|
{
|
|
// Configure the the feature.
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(save_network_anonymization_key_mode);
|
|
|
|
// Create and initialize an HttpServerProperties, must be done after
|
|
// setting the feature.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set kServer1 to kQuicServerInfo1 in the context of
|
|
// kNetworkAnonymizationKey1, Set kServer2 to kQuicServerInfo2 in the
|
|
// context of kNetworkAnonymizationKey2, and kServer1 to kQuicServerInfo3
|
|
// in the context of NetworkAnonymizationKey().
|
|
properties->SetQuicServerInfo(kServer1, kNetworkAnonymizationKey1,
|
|
kQuicServerInfo1);
|
|
properties->SetQuicServerInfo(kServer2, kNetworkAnonymizationKey2,
|
|
kQuicServerInfo2);
|
|
properties->SetQuicServerInfo(kServer1, NetworkAnonymizationKey(),
|
|
kQuicServerInfo3);
|
|
|
|
// Verify values were set.
|
|
if (save_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, NetworkAnonymizationKey()));
|
|
} else {
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, NetworkAnonymizationKey()));
|
|
}
|
|
|
|
// Wait until the data's been written to prefs, and then create a copy of
|
|
// the prefs data.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
saved_value = unowned_pref_delegate->GetServerProperties().Clone();
|
|
}
|
|
|
|
// Now try and load the data in each of the feature modes.
|
|
for (auto load_network_anonymization_key_mode :
|
|
kNetworkAnonymizationKeyModes) {
|
|
SCOPED_TRACE(static_cast<int>(load_network_anonymization_key_mode));
|
|
|
|
std::unique_ptr<base::test::ScopedFeatureList> feature_list =
|
|
SetNetworkAnonymizationKeyMode(load_network_anonymization_key_mode);
|
|
|
|
// Create a new HttpServerProperties, loading the data from before.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(saved_value.Clone());
|
|
|
|
if (save_network_anonymization_key_mode ==
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
// If NetworkAnonymizationKey was disabled when saving, entries were
|
|
// saved with an empty NetworkAnonymizationKey, which should always be
|
|
// loaded successfully. This is needed to continue to support consumers
|
|
// that don't use NetworkAnonymizationKeys.
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, NetworkAnonymizationKey()));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, NetworkAnonymizationKey()));
|
|
if (load_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
}
|
|
} else if (save_network_anonymization_key_mode ==
|
|
load_network_anonymization_key_mode) {
|
|
// If the save and load modes are the same, the load should succeed, and
|
|
// the network anonymization keys should match.
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, NetworkAnonymizationKey()));
|
|
} else {
|
|
// Otherwise, only the value set with an empty NetworkAnonymizationKey
|
|
// should have been loaded successfully.
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, NetworkAnonymizationKey()));
|
|
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer2, NetworkAnonymizationKey()));
|
|
|
|
// There should be no cross-contamination of NetworkAnonymizationKeys,
|
|
// if NetworkAnonymizationKeys are enabled.
|
|
if (load_network_anonymization_key_mode !=
|
|
NetworkAnonymizationKeyMode::kDisabled) {
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(nullptr, properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tests a full round trip to prefs and back in the canonical suffix for
|
|
// QuicServerInfo case. Enable NetworkAnonymizationKeys, as they have some
|
|
// interactions with the canonical suffix logic.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
NetworkAnonymizationKeyQuicServerInfoCanonicalSuffixRoundTrip) {
|
|
const SchemefulSite kSite1(GURL("https://foo.test/"));
|
|
const SchemefulSite kSite2(GURL("https://bar.test/"));
|
|
const auto kNetworkAnonymizationKey1 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite1);
|
|
const auto kNetworkAnonymizationKey2 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite2);
|
|
|
|
// Three servers with the same canonical suffix (".c.youtube.com").
|
|
const quic::QuicServerId kServer1("foo.c.youtube.com", 443,
|
|
false /* privacy_mode_enabled */);
|
|
const quic::QuicServerId kServer2("bar.c.youtube.com", 443,
|
|
false /* privacy_mode_enabled */);
|
|
const quic::QuicServerId kServer3("baz.c.youtube.com", 443,
|
|
false /* privacy_mode_enabled */);
|
|
|
|
const char kQuicServerInfo1[] = "info1";
|
|
const char kQuicServerInfo2[] = "info2";
|
|
const char kQuicServerInfo3[] = "info3";
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create and initialize an HttpServerProperties with no state.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set kQuicServerInfo1 for kServer1 using kNetworkAnonymizationKey1. That
|
|
// information should be retrieved when fetching information for any server
|
|
// with the same canonical suffix, when using kNetworkAnonymizationKey1.
|
|
properties->SetQuicServerInfo(kServer1, kNetworkAnonymizationKey1,
|
|
kQuicServerInfo1);
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(
|
|
properties->GetQuicServerInfo(kServer1, kNetworkAnonymizationKey2));
|
|
|
|
// Set kQuicServerInfo2 for kServer2 using kNetworkAnonymizationKey1. It
|
|
// should not affect information retrieved for kServer1, but should for
|
|
// kServer2 and kServer3.
|
|
properties->SetQuicServerInfo(kServer2, kNetworkAnonymizationKey1,
|
|
kQuicServerInfo2);
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey1));
|
|
EXPECT_FALSE(
|
|
properties->GetQuicServerInfo(kServer1, kNetworkAnonymizationKey2));
|
|
|
|
// Set kQuicServerInfo3 for kServer1 using kNetworkAnonymizationKey2. It
|
|
// should not affect information stored for kNetworkAnonymizationKey1.
|
|
properties->SetQuicServerInfo(kServer1, kNetworkAnonymizationKey2,
|
|
kQuicServerInfo3);
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey2));
|
|
|
|
// Wait until the data's been written to prefs, and then tear down the
|
|
// HttpServerProperties.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
base::Value::Dict saved_value =
|
|
unowned_pref_delegate->GetServerProperties().Clone();
|
|
properties.reset();
|
|
|
|
// Create a new HttpServerProperties using the value saved to prefs above.
|
|
pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
unowned_pref_delegate = pref_delegate.get();
|
|
properties = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(std::move(saved_value));
|
|
|
|
// All values should have been saved and be retrievable by suffix-matching
|
|
// servers.
|
|
//
|
|
// TODO(mmenke): The rest of this test corresponds exactly to behavior in
|
|
// CanonicalSuffixRoundTripWithNetworkAnonymizationKey. It seems like these
|
|
// lines should correspond as well.
|
|
EXPECT_EQ(kQuicServerInfo1, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo2, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey1));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer1, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer2, kNetworkAnonymizationKey2));
|
|
EXPECT_EQ(kQuicServerInfo3, *properties->GetQuicServerInfo(
|
|
kServer3, kNetworkAnonymizationKey2));
|
|
}
|
|
|
|
// Make sure QuicServerInfo associated with NetworkAnonymizationKeys with opaque
|
|
// origins aren't saved.
|
|
TEST_F(HttpServerPropertiesManagerTest,
|
|
NetworkAnonymizationKeyQuicServerInfoOpaqueOrigin) {
|
|
const SchemefulSite kOpaqueSite(GURL("data:text/plain,Hello World"));
|
|
const auto kNetworkAnonymizationKey =
|
|
NetworkAnonymizationKey::CreateSameSite(kOpaqueSite);
|
|
const quic::QuicServerId kServer("foo", 443,
|
|
false /* privacy_mode_enabled */);
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create and initialize an HttpServerProperties, must be done after
|
|
// setting the feature.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
properties->SetQuicServerInfo(kServer, kNetworkAnonymizationKey,
|
|
"QuicServerInfo");
|
|
EXPECT_TRUE(properties->GetQuicServerInfo(kServer, kNetworkAnonymizationKey));
|
|
|
|
// Wait until the data's been written to prefs, and then create a copy of
|
|
// the prefs data.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
|
|
// No information should have been saved to prefs.
|
|
std::string preferences_json;
|
|
base::JSONWriter::Write(unowned_pref_delegate->GetServerProperties(),
|
|
&preferences_json);
|
|
EXPECT_EQ("{\"quic_servers\":[],\"servers\":[],\"version\":5}",
|
|
preferences_json);
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, AdvertisedVersionsRoundTrip) {
|
|
for (const quic::ParsedQuicVersion& version : AllSupportedQuicVersions()) {
|
|
if (version.AlpnDeferToRFCv1()) {
|
|
// These versions currently do not support Alt-Svc.
|
|
continue;
|
|
}
|
|
// Reset test infrastructure.
|
|
TearDown();
|
|
SetUp();
|
|
InitializePrefs();
|
|
// Create alternate version information.
|
|
const url::SchemeHostPort server("https", "quic.example.org", 443);
|
|
AlternativeServiceInfoVector alternative_service_info_vector_in;
|
|
AlternativeService quic_alternative_service(kProtoQUIC, "", 443);
|
|
base::Time expiration;
|
|
ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration));
|
|
quic::ParsedQuicVersionVector advertised_versions = {version};
|
|
alternative_service_info_vector_in.push_back(
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
quic_alternative_service, expiration, advertised_versions));
|
|
http_server_props_->SetAlternativeServices(
|
|
server, NetworkAnonymizationKey(), alternative_service_info_vector_in);
|
|
// Save to JSON.
|
|
EXPECT_EQ(0, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
EXPECT_NE(0u, GetPendingMainThreadTaskCount());
|
|
FastForwardUntilNoTasksRemain();
|
|
EXPECT_EQ(1, pref_delegate_->GetAndClearNumPrefUpdates());
|
|
const base::Value::Dict& http_server_properties =
|
|
pref_delegate_->GetServerProperties();
|
|
std::string preferences_json;
|
|
EXPECT_TRUE(
|
|
base::JSONWriter::Write(http_server_properties, &preferences_json));
|
|
// Reset test infrastructure.
|
|
TearDown();
|
|
SetUp();
|
|
InitializePrefs();
|
|
// Read from JSON.
|
|
base::Value::Dict preferences_dict =
|
|
base::test::ParseJsonDict(preferences_json);
|
|
ASSERT_FALSE(preferences_dict.empty());
|
|
const base::Value::List* servers_list =
|
|
preferences_dict.FindList("servers");
|
|
ASSERT_TRUE(servers_list);
|
|
ASSERT_EQ(servers_list->size(), 1u);
|
|
const base::Value& server_dict = (*servers_list)[0];
|
|
HttpServerProperties::ServerInfo server_info;
|
|
EXPECT_TRUE(HttpServerPropertiesManager::ParseAlternativeServiceInfo(
|
|
server, server_dict.GetDict(), &server_info));
|
|
ASSERT_TRUE(server_info.alternative_services.has_value());
|
|
AlternativeServiceInfoVector alternative_service_info_vector_out =
|
|
server_info.alternative_services.value();
|
|
ASSERT_EQ(1u, alternative_service_info_vector_out.size());
|
|
EXPECT_EQ(
|
|
kProtoQUIC,
|
|
alternative_service_info_vector_out[0].alternative_service().protocol);
|
|
// Ensure we correctly parsed the version.
|
|
EXPECT_EQ(advertised_versions,
|
|
alternative_service_info_vector_out[0].advertised_versions());
|
|
}
|
|
}
|
|
|
|
TEST_F(HttpServerPropertiesManagerTest, SameOrderAfterReload) {
|
|
const SchemefulSite kSite1(GURL("https://foo.test/"));
|
|
const SchemefulSite kSite2(GURL("https://bar.test/"));
|
|
const auto kNetworkAnonymizationKey1 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite1);
|
|
const auto kNetworkAnonymizationKey2 =
|
|
NetworkAnonymizationKey::CreateSameSite(kSite2);
|
|
|
|
base::test::ScopedFeatureList feature_list;
|
|
feature_list.InitAndEnableFeature(
|
|
features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
|
|
|
|
// Create and initialize an HttpServerProperties with no state.
|
|
std::unique_ptr<MockPrefDelegate> pref_delegate =
|
|
std::make_unique<MockPrefDelegate>();
|
|
MockPrefDelegate* unowned_pref_delegate = pref_delegate.get();
|
|
std::unique_ptr<HttpServerProperties> properties =
|
|
std::make_unique<HttpServerProperties>(std::move(pref_delegate),
|
|
/*net_log=*/nullptr,
|
|
GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(base::Value::Dict());
|
|
|
|
// Set alternative_service info.
|
|
base::Time expiration = base::Time::Now() + base::Days(1);
|
|
AlternativeServiceInfo alt_service1 =
|
|
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
|
|
AlternativeService(kProtoQUIC, "1.example", 1234), expiration,
|
|
DefaultSupportedQuicVersions());
|
|
AlternativeServiceInfo alt_service2 =
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
AlternativeService(kProtoHTTP2, "2.example", 443), expiration);
|
|
AlternativeServiceInfo alt_service3 =
|
|
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
|
|
AlternativeService(kProtoHTTP2, "3.example", 443), expiration);
|
|
const url::SchemeHostPort kServer1("https", "1.example", 443);
|
|
const url::SchemeHostPort kServer2("https", "2.example", 443);
|
|
const url::SchemeHostPort kServer3("https", "3.example", 443);
|
|
properties->SetAlternativeServices(kServer1, kNetworkAnonymizationKey1,
|
|
{alt_service1});
|
|
properties->SetAlternativeServices(kServer2, kNetworkAnonymizationKey1,
|
|
{alt_service2});
|
|
properties->SetAlternativeServices(kServer3, kNetworkAnonymizationKey2,
|
|
{alt_service3});
|
|
|
|
// Set quic_server_info.
|
|
quic::QuicServerId quic_server_id1("quic1.example", 80, false);
|
|
quic::QuicServerId quic_server_id2("quic2.example", 80, false);
|
|
quic::QuicServerId quic_server_id3("quic3.example", 80, false);
|
|
properties->SetQuicServerInfo(quic_server_id1, kNetworkAnonymizationKey1,
|
|
"quic_server_info1");
|
|
properties->SetQuicServerInfo(quic_server_id2, kNetworkAnonymizationKey1,
|
|
"quic_server_info2");
|
|
properties->SetQuicServerInfo(quic_server_id3, kNetworkAnonymizationKey2,
|
|
"quic_server_info3");
|
|
|
|
// Set broken_alternative_service info.
|
|
AlternativeService broken_service1(kProtoQUIC, "broken1.example", 443);
|
|
AlternativeService broken_service2(kProtoQUIC, "broken2.example", 443);
|
|
AlternativeService broken_service3(kProtoQUIC, "broken3.example", 443);
|
|
properties->MarkAlternativeServiceBroken(broken_service1,
|
|
kNetworkAnonymizationKey1);
|
|
FastForwardBy(base::Milliseconds(1));
|
|
properties->MarkAlternativeServiceBroken(broken_service2,
|
|
kNetworkAnonymizationKey1);
|
|
FastForwardBy(base::Milliseconds(1));
|
|
properties->MarkAlternativeServiceBroken(broken_service3,
|
|
kNetworkAnonymizationKey2);
|
|
|
|
// The first item of `server_info_map` must be the latest item.
|
|
EXPECT_EQ(3u, properties->server_info_map_for_testing().size());
|
|
EXPECT_EQ(
|
|
properties->server_info_map_for_testing().begin()->first.server.host(),
|
|
"3.example");
|
|
|
|
// The first item of `recently_broken_alternative_services` must be the latest
|
|
// item.
|
|
EXPECT_EQ(3u, properties->broken_alternative_services_for_testing()
|
|
.recently_broken_alternative_services()
|
|
.size());
|
|
EXPECT_EQ("broken3.example",
|
|
properties->broken_alternative_services_for_testing()
|
|
.recently_broken_alternative_services()
|
|
.begin()
|
|
->first.alternative_service.host);
|
|
|
|
// The first item of `quic_server_info_map` must be the latest item.
|
|
EXPECT_EQ(3u, properties->quic_server_info_map_for_testing().size());
|
|
EXPECT_EQ("quic3.example", properties->quic_server_info_map_for_testing()
|
|
.begin()
|
|
->first.server_id.host());
|
|
|
|
// The first item of `broken_alternative_service_list` must be the oldest
|
|
// item.
|
|
EXPECT_EQ(3u, properties->broken_alternative_services_for_testing()
|
|
.broken_alternative_service_list()
|
|
.size());
|
|
EXPECT_EQ("broken1.example",
|
|
properties->broken_alternative_services_for_testing()
|
|
.broken_alternative_service_list()
|
|
.begin()
|
|
->first.alternative_service.host);
|
|
|
|
// Wait until the data's been written to prefs, and then tear down the
|
|
// HttpServerProperties.
|
|
FastForwardBy(HttpServerProperties::GetUpdatePrefsDelayForTesting());
|
|
base::Value::Dict saved_value =
|
|
unowned_pref_delegate->GetServerProperties().Clone();
|
|
|
|
// Create a new HttpServerProperties using the value saved to prefs above.
|
|
pref_delegate = std::make_unique<MockPrefDelegate>();
|
|
unowned_pref_delegate = pref_delegate.get();
|
|
properties = std::make_unique<HttpServerProperties>(
|
|
std::move(pref_delegate), /*net_log=*/nullptr, GetMockTickClock());
|
|
unowned_pref_delegate->InitializePrefs(std::move(saved_value));
|
|
|
|
// The first item of `server_info_map` must be the latest item.
|
|
EXPECT_EQ(3u, properties->server_info_map_for_testing().size());
|
|
EXPECT_EQ(
|
|
properties->server_info_map_for_testing().begin()->first.server.host(),
|
|
"3.example");
|
|
|
|
// The first item of `recently_broken_alternative_services` must be the latest
|
|
// item.
|
|
EXPECT_EQ(3u, properties->broken_alternative_services_for_testing()
|
|
.recently_broken_alternative_services()
|
|
.size());
|
|
EXPECT_EQ("broken3.example",
|
|
properties->broken_alternative_services_for_testing()
|
|
.recently_broken_alternative_services()
|
|
.begin()
|
|
->first.alternative_service.host);
|
|
|
|
// The first item of `quic_server_info_map` must be the latest item.
|
|
EXPECT_EQ(3u, properties->quic_server_info_map_for_testing().size());
|
|
EXPECT_EQ("quic3.example", properties->quic_server_info_map_for_testing()
|
|
.begin()
|
|
->first.server_id.host());
|
|
|
|
// The first item of `broken_alternative_service_list` must be the oldest
|
|
// item.
|
|
EXPECT_EQ(3u, properties->broken_alternative_services_for_testing()
|
|
.broken_alternative_service_list()
|
|
.size());
|
|
EXPECT_EQ("broken1.example",
|
|
properties->broken_alternative_services_for_testing()
|
|
.broken_alternative_service_list()
|
|
.begin()
|
|
->first.alternative_service.host);
|
|
}
|
|
|
|
} // namespace net
|