blob: 7b65f96443a77c83f0bbc8206601a2d9914aa1d1 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/network_service_test_helper.h"
#include <optional>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/environment.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/current_thread.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_host_resolver.h"
#include "content/utility/services.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/address_map_linux.h"
#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/host_resolver_system_task.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/dns_over_https_server_config.h"
#include "net/http/transport_security_state.h"
#include "net/http/transport_security_state_test_util.h"
#include "net/log/net_log.h"
#include "net/nqe/network_quality_estimator.h"
#include "net/test/test_data_directory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "sandbox/policy/sandbox_type.h"
#include "services/network/cookie_manager.h"
#include "services/network/disk_cache/mojo_backend_file_operations_factory.h"
#include "services/network/host_resolver.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_service_buildflags.h"
#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#if BUILDFLAG(IS_CT_SUPPORTED)
#include "services/network/sct_auditing/sct_auditing_cache.h"
#include "services/network/sct_auditing/sct_auditing_reporter.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/test/android/url_utils.h"
#endif
namespace content {
namespace {
#ifndef STATIC_ASSERT_ENUM
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enums: " #a)
#endif
STATIC_ASSERT_ENUM(network::mojom::ResolverType::kResolverTypeFail,
net::RuleBasedHostResolverProc::Rule::kResolverTypeFail);
STATIC_ASSERT_ENUM(network::mojom::ResolverType::kResolverTypeSystem,
net::RuleBasedHostResolverProc::Rule::kResolverTypeSystem);
STATIC_ASSERT_ENUM(
network::mojom::ResolverType::kResolverTypeIPLiteral,
net::RuleBasedHostResolverProc::Rule::kResolverTypeIPLiteral);
void CrashResolveHost(const std::string& host_to_crash,
const std::string& host) {
if (host_to_crash == host)
base::Process::TerminateCurrentProcessImmediately(1);
}
class SimpleCacheEntry : public network::mojom::SimpleCacheEntry {
public:
explicit SimpleCacheEntry(disk_cache::ScopedEntryPtr entry)
: entry_(std::move(entry)) {}
~SimpleCacheEntry() override = default;
void WriteData(int32_t index,
int32_t offset,
const std::vector<uint8_t>& data,
bool truncate,
WriteDataCallback callback) override {
if (!entry_) {
std::move(callback).Run(net::ERR_FAILED);
return;
}
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<WriteDataCallback>>();
callback_holder->data = std::move(callback);
auto data_to_pass =
base::MakeRefCounted<net::IOBufferWithSize>(data.size());
UNSAFE_TODO(memcpy(data_to_pass->data(), data.data(), data.size()));
int rv = entry_->WriteData(index, offset, data_to_pass.get(), data.size(),
base::BindOnce(&SimpleCacheEntry::OnDataWritten,
weak_factory_.GetWeakPtr(),
data_to_pass, callback_holder),
truncate);
if (rv == net::ERR_IO_PENDING) {
return;
}
OnDataWritten(std::move(data_to_pass), std::move(callback_holder), rv);
}
void ReadData(int32_t index,
int32_t offset,
uint32_t length,
ReadDataCallback callback) override {
if (!entry_) {
std::move(callback).Run(/*data=*/{}, net::ERR_FAILED);
return;
}
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<ReadDataCallback>>();
callback_holder->data = std::move(callback);
auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(length);
int rv = entry_->ReadData(
index, offset, buffer.get(), length,
base::BindOnce(&SimpleCacheEntry::OnDataRead,
weak_factory_.GetWeakPtr(), buffer, callback_holder));
if (rv == net::ERR_IO_PENDING) {
return;
}
OnDataRead(std::move(buffer), std::move(callback_holder), rv);
}
void WriteSparseData(int32_t offset,
const std::vector<uint8_t>& data,
WriteDataCallback callback) override {
if (!entry_) {
std::move(callback).Run(net::ERR_FAILED);
return;
}
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<WriteDataCallback>>();
callback_holder->data = std::move(callback);
auto data_to_pass =
base::MakeRefCounted<net::IOBufferWithSize>(data.size());
UNSAFE_TODO(memcpy(data_to_pass->data(), data.data(), data.size()));
int rv =
entry_->WriteSparseData(offset, data_to_pass.get(), data.size(),
base::BindOnce(&SimpleCacheEntry::OnDataWritten,
weak_factory_.GetWeakPtr(),
data_to_pass, callback_holder));
if (rv == net::ERR_IO_PENDING) {
return;
}
OnDataWritten(std::move(data_to_pass), std::move(callback_holder), rv);
}
void ReadSparseData(int32_t offset,
uint32_t length,
ReadDataCallback callback) override {
if (!entry_) {
std::move(callback).Run(/*data=*/{}, net::ERR_FAILED);
return;
}
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<ReadDataCallback>>();
callback_holder->data = std::move(callback);
auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(length);
int rv = entry_->ReadSparseData(
offset, buffer.get(), length,
base::BindOnce(&SimpleCacheEntry::OnDataRead,
weak_factory_.GetWeakPtr(), buffer, callback_holder));
if (rv == net::ERR_IO_PENDING) {
return;
}
OnDataRead(std::move(buffer), std::move(callback_holder), rv);
}
void Close(CloseCallback callback) override {
entry_.reset();
std::move(callback).Run();
}
private:
void OnDataWritten(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedData<WriteDataCallback>> callback_holder,
int result) {
WriteDataCallback callback = std::move(callback_holder->data);
std::move(callback).Run(result);
}
void OnDataRead(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedData<ReadDataCallback>> callback_holder,
int result) {
ReadDataCallback callback = std::move(callback_holder->data);
if (result < 0) {
std::move(callback).Run(/*data=*/{}, result);
return;
}
std::vector<uint8_t> data(result);
UNSAFE_TODO(memcpy(data.data(), buffer->data(), result));
std::move(callback).Run(data, result);
}
disk_cache::ScopedEntryPtr entry_;
base::WeakPtrFactory<SimpleCacheEntry> weak_factory_{this};
};
class SimpleCacheEntryEnumerator final
: public network::mojom::SimpleCacheEntryEnumerator {
public:
using GetNextCallbackHolder = base::RefCountedData<GetNextCallback>;
explicit SimpleCacheEntryEnumerator(
std::unique_ptr<disk_cache::Backend::Iterator> iter)
: iter_(std::move(iter)) {}
~SimpleCacheEntryEnumerator() override = default;
void GetNext(GetNextCallback callback) override {
DCHECK(!processing_);
processing_ = true;
auto callback_holder =
base::MakeRefCounted<GetNextCallbackHolder>(std::move(callback));
disk_cache::EntryResult result = iter_->OpenNextEntry(
base::BindOnce(&SimpleCacheEntryEnumerator::OnEntryOpened,
weak_factory_.GetWeakPtr(), callback_holder));
if (result.net_error() == net::ERR_IO_PENDING) {
return;
}
OnEntryOpened(std::move(callback_holder), std::move(result));
}
private:
void OnEntryOpened(scoped_refptr<GetNextCallbackHolder> callback_holder,
disk_cache::EntryResult result) {
DCHECK(processing_);
processing_ = false;
auto result_to_pass = network::mojom::SimpleCacheOpenEntryResult::New();
result_to_pass->error = result.net_error();
auto callback = std::move(callback_holder->data);
DCHECK(callback);
if (result.net_error() != net::OK) {
std::move(callback).Run(std::move(result_to_pass));
return;
}
disk_cache::ScopedEntryPtr entry(result.ReleaseEntry());
result_to_pass->key = entry->GetKey();
mojo::PendingRemote<network::mojom::SimpleCacheEntry> remote;
mojo::MakeSelfOwnedReceiver(
std::make_unique<SimpleCacheEntry>(std::move(entry)),
result_to_pass->entry.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(result_to_pass));
}
std::unique_ptr<disk_cache::Backend::Iterator> iter_;
bool processing_ = false;
base::WeakPtrFactory<SimpleCacheEntryEnumerator> weak_factory_{this};
};
class SimpleCache : public network::mojom::SimpleCache {
public:
explicit SimpleCache(std::unique_ptr<disk_cache::Backend> backend)
: backend_(std::move(backend)) {
DCHECK(backend_);
}
~SimpleCache() override = default;
void CreateEntry(const std::string& key,
CreateEntryCallback callback) override {
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<CreateEntryCallback>>();
callback_holder->data = std::move(callback);
disk_cache::EntryResult result = backend_->CreateEntry(
key, net::DEFAULT_PRIORITY,
base::BindOnce(&SimpleCache::OnEntryCreated, weak_factory_.GetWeakPtr(),
callback_holder));
if (result.net_error() == net::ERR_IO_PENDING) {
return;
}
OnEntryCreated(std::move(callback_holder), std::move(result));
}
void OpenEntry(const std::string& key, OpenEntryCallback callback) override {
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<OpenEntryCallback>>();
callback_holder->data = std::move(callback);
disk_cache::EntryResult result = backend_->OpenEntry(
key, net::DEFAULT_PRIORITY,
base::BindOnce(&SimpleCache::OnEntryOpend, weak_factory_.GetWeakPtr(),
callback_holder));
if (result.net_error() == net::ERR_IO_PENDING) {
return;
}
OnEntryOpend(std::move(callback_holder), std::move(result));
}
void DoomEntry(const std::string& key, DoomEntryCallback callback) override {
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<DoomEntryCallback>>();
callback_holder->data = std::move(callback);
int rv = backend_->DoomEntry(
key, net::IDLE,
base::BindOnce(&SimpleCache::OnEntryDoomed, weak_factory_.GetWeakPtr(),
callback_holder));
if (rv == net::ERR_IO_PENDING) {
return;
}
OnEntryDoomed(std::move(callback_holder), rv);
}
void DoomAllEntries(DoomAllEntriesCallback callback) override {
auto callback_holder =
base::MakeRefCounted<base::RefCountedData<DoomAllEntriesCallback>>(
std::move(callback));
int rv = backend_->DoomAllEntries(
base::BindOnce(&SimpleCache::OnAllEntriesDoomed,
weak_factory_.GetWeakPtr(), callback_holder));
if (rv == net::ERR_IO_PENDING) {
return;
}
OnAllEntriesDoomed(std::move(callback_holder), rv);
}
void EnumerateEntries(
mojo::PendingReceiver<network::mojom::SimpleCacheEntryEnumerator>
pending_receiver) override {
mojo::MakeSelfOwnedReceiver(std::make_unique<SimpleCacheEntryEnumerator>(
backend_->CreateIterator()),
std::move(pending_receiver));
}
void Detach(DetachCallback callback) override {
backend_ = nullptr;
disk_cache::FlushCacheThreadAsynchronouslyForTesting(std::move(callback));
}
private:
void OnEntryCreated(
scoped_refptr<base::RefCountedData<CreateEntryCallback>> callback_holder,
disk_cache::EntryResult result) {
CreateEntryCallback callback = std::move(callback_holder->data);
if (result.net_error() != net::OK) {
std::move(callback).Run(mojo::NullRemote(), result.net_error());
return;
}
disk_cache::ScopedEntryPtr entry(result.ReleaseEntry());
mojo::PendingRemote<network::mojom::SimpleCacheEntry> remote;
mojo::MakeSelfOwnedReceiver(
std::make_unique<SimpleCacheEntry>(std::move(entry)),
remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(remote), net::OK);
}
void OnEntryOpend(
scoped_refptr<base::RefCountedData<OpenEntryCallback>> callback_holder,
disk_cache::EntryResult result) {
OpenEntryCallback callback = std::move(callback_holder->data);
if (result.net_error() != net::OK) {
std::move(callback).Run(mojo::NullRemote(), result.net_error());
return;
}
disk_cache::ScopedEntryPtr entry(result.ReleaseEntry());
mojo::PendingRemote<network::mojom::SimpleCacheEntry> remote;
mojo::MakeSelfOwnedReceiver(
std::make_unique<SimpleCacheEntry>(std::move(entry)),
remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(remote), net::OK);
}
void OnEntryDoomed(
scoped_refptr<base::RefCountedData<DoomEntryCallback>> callback_holder,
int result) {
DoomEntryCallback callback = std::move(callback_holder->data);
std::move(callback).Run(result);
}
void OnAllEntriesDoomed(
scoped_refptr<base::RefCountedData<DoomAllEntriesCallback>>
callback_holder,
int result) {
DoomAllEntriesCallback callback = std::move(callback_holder->data);
std::move(callback).Run(result);
}
std::unique_ptr<disk_cache::Backend> backend_;
base::WeakPtrFactory<SimpleCache> weak_factory_{this};
};
} // namespace
class NetworkServiceTestHelper::NetworkServiceTestImpl
: public network::mojom::NetworkServiceTest,
public base::CurrentThread::DestructionObserver,
public base::MemoryPressureListener {
public:
NetworkServiceTestImpl() : test_host_resolver_(new TestHostResolver()) {
memory_pressure_listener_registration_.emplace(
base::MemoryPressureListenerTag::kTest, this);
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMockCertVerifierForTesting)) {
mock_cert_verifier_ = std::make_unique<net::MockCertVerifier>();
network::NetworkContext::SetCertVerifierForTesting(
mock_cert_verifier_.get());
// The default result may be set using a command line flag.
std::string default_result =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kMockCertVerifierDefaultResultForTesting);
int default_result_int = 0;
if (!default_result.empty() &&
base::StringToInt(default_result, &default_result_int)) {
mock_cert_verifier_->set_default_result(default_result_int);
}
}
}
NetworkServiceTestImpl(const NetworkServiceTestImpl&) = delete;
NetworkServiceTestImpl& operator=(const NetworkServiceTestImpl&) = delete;
~NetworkServiceTestImpl() override {
network::NetworkContext::SetCertVerifierForTesting(nullptr);
}
// network::mojom::NetworkServiceTest:
void AddRules(std::vector<network::mojom::RulePtr> rules,
AddRulesCallback callback) override {
// test_host_resolver_ may be empty if
// SetAllowNetworkAccessToHostResolutions was invoked.
DCHECK(test_host_resolver_);
auto* host_resolver = test_host_resolver_->host_resolver();
for (const auto& rule : rules) {
switch (rule->resolver_type) {
case network::mojom::ResolverType::kResolverTypeFail:
host_resolver->AddSimulatedFailure(rule->host_pattern);
break;
case network::mojom::ResolverType::kResolverTypeFailTimeout:
host_resolver->AddSimulatedTimeoutFailure(rule->host_pattern);
break;
case network::mojom::ResolverType::kResolverTypeIPLiteral: {
net::IPAddress ip_address;
DCHECK(ip_address.AssignFromIPLiteral(rule->replacement));
host_resolver->AddRuleWithFlags(rule->host_pattern, rule->replacement,
rule->host_resolver_flags,
rule->dns_aliases);
break;
}
case network::mojom::ResolverType::kResolverTypeDirectLookup:
host_resolver->AllowDirectLookup(rule->host_pattern);
break;
default:
host_resolver->AddRuleWithFlags(rule->host_pattern, rule->replacement,
rule->host_resolver_flags,
rule->dns_aliases);
break;
}
}
std::move(callback).Run();
}
void SimulateNetworkChange(network::mojom::ConnectionType type,
SimulateNetworkChangeCallback callback) override {
DCHECK(!net::NetworkChangeNotifier::CreateIfNeeded());
net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
net::NetworkChangeNotifier::ConnectionType(type));
std::move(callback).Run();
}
void SimulateNetworkQualityChange(
net::EffectiveConnectionType type,
SimulateNetworkChangeCallback callback) override {
network::NetworkService::GetNetworkServiceForTesting()
->network_quality_estimator()
->SimulateNetworkQualityChangeForTesting(type);
std::move(callback).Run();
}
void ForceNetworkQualityEstimatorReportWifiAsSlow2G(
SimulateNetworkChangeCallback callback) override {
network::NetworkService::GetNetworkServiceForTesting()
->network_quality_estimator()
->ForceReportWifiAsSlow2GForTesting();
std::move(callback).Run();
}
void SimulateCrash() override {
LOG(ERROR) << "Intentionally terminating current process to simulate"
" NetworkService crash for testing.";
// Use |TerminateCurrentProcessImmediately()| instead of |CHECK()| to avoid
// 'Fatal error' dialog on Windows debug.
base::Process::TerminateCurrentProcessImmediately(1);
}
void MockCertVerifierSetDefaultResult(
int32_t default_result,
MockCertVerifierSetDefaultResultCallback callback) override {
// TODO(crbug.com/40243688): Since testing/variations/
// fieldtrial_testing_config.json changes the command line flags after
// ContentBrowserTest::SetUpCommandLine() and NetworkServiceTest
// instantiation, MockCertVerifierSetDefaultResult can be called without
// `mock_cert_verifier_` initialization.
// Actually since all mock cert verification tests call this function first,
// we should remove the set up using the command line flags.
if (!mock_cert_verifier_) {
mock_cert_verifier_ = std::make_unique<net::MockCertVerifier>();
network::NetworkContext::SetCertVerifierForTesting(
mock_cert_verifier_.get());
}
mock_cert_verifier_->set_default_result(default_result);
std::move(callback).Run();
}
void MockCertVerifierAddResultForCertAndHost(
const scoped_refptr<net::X509Certificate>& cert,
const std::string& host_pattern,
const net::CertVerifyResult& verify_result,
int32_t rv,
MockCertVerifierAddResultForCertAndHostCallback callback) override {
mock_cert_verifier_->AddResultForCertAndHost(cert, host_pattern,
verify_result, rv);
std::move(callback).Run();
}
void SetTransportSecurityStateTestSource(
bool enable_unittest_source,
SetTransportSecurityStateTestSourceCallback callback) override {
if (enable_unittest_source) {
transport_security_state_source_ =
std::make_unique<net::ScopedTransportSecurityStateSource>();
} else {
transport_security_state_source_.reset();
}
std::move(callback).Run();
}
void SetAllowNetworkAccessToHostResolutions(
SetAllowNetworkAccessToHostResolutionsCallback callback) override {
DCHECK(!have_test_doh_servers_)
<< "Cannot allow network access when test DoH servers have been set.";
test_host_resolver_.reset();
std::move(callback).Run();
}
void ReplaceSystemDnsConfig(
ReplaceSystemDnsConfigCallback callback) override {
network::NetworkService::GetNetworkServiceForTesting()
->ReplaceSystemDnsConfigForTesting(std::move(callback));
}
void SetTestDohConfig(net::SecureDnsMode secure_dns_mode,
const net::DnsOverHttpsConfig& doh_config,
SetTestDohConfigCallback callback) override {
DCHECK(test_host_resolver_)
<< "Network access for host resolutions must be disabled.";
have_test_doh_servers_ = true;
network::NetworkService::GetNetworkServiceForTesting()
->SetTestDohConfigForTesting(secure_dns_mode, doh_config);
std::move(callback).Run();
}
void CrashOnResolveHost(const std::string& host) override {
network::HostResolver::SetResolveHostCallbackForTesting(
base::BindRepeating(CrashResolveHost, host));
}
void CrashOnGetCookieList() override {
network::CookieManager::CrashOnGetCookieList();
}
void GetLatestMemoryPressureLevel(
GetLatestMemoryPressureLevelCallback callback) override {
std::move(callback).Run(latest_memory_pressure_level_);
}
void GetPeerToPeerConnectionsCountChange(
GetPeerToPeerConnectionsCountChangeCallback callback) override {
uint32_t count = network::NetworkService::GetNetworkServiceForTesting()
->network_quality_estimator()
->GetPeerToPeerConnectionsCountChange();
std::move(callback).Run(count);
}
void SetSCTAuditingRetryDelay(
std::optional<base::TimeDelta> delay,
SetSCTAuditingRetryDelayCallback callback) override {
#if BUILDFLAG(IS_CT_SUPPORTED)
network::SCTAuditingReporter::SetRetryDelayForTesting(delay);
#endif
std::move(callback).Run();
}
void GetEnvironmentVariableValue(
const std::string& name,
GetEnvironmentVariableValueCallback callback) override {
std::move(callback).Run(
base::Environment::Create()->GetVar(name).value_or(std::string()));
}
void Log(const std::string& message, LogCallback callback) override {
LOG(ERROR) << message;
std::move(callback).Run();
}
void ActivateFieldTrial(const std::string& field_trial_name) override {
base::FieldTrialList::FindFullName(field_trial_name);
}
void BindReceiver(
mojo::PendingReceiver<network::mojom::NetworkServiceTest> receiver) {
receivers_.Add(this, std::move(receiver));
if (!registered_as_destruction_observer_) {
base::CurrentIOThread::Get()->AddDestructionObserver(this);
registered_as_destruction_observer_ = true;
}
}
// base::CurrentThread::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
// Needs to be called on the IO thread.
receivers_.Clear();
}
void OpenFile(const base::FilePath& path,
base::OnceCallback<void(bool)> callback) override {
base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
std::move(callback).Run(file.IsValid());
}
void EnumerateFiles(
const base::FilePath& path,
mojo::PendingRemote<network::mojom::HttpCacheBackendFileOperationsFactory>
factory_remote,
EnumerateFilesCallback callback) override {
auto task_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
auto factory =
base::MakeRefCounted<network::MojoBackendFileOperationsFactory>(
std::move(factory_remote));
auto ops = factory->Create(task_runner);
using Entry = disk_cache::BackendFileOperations::FileEnumerationEntry;
task_runner->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(
[](const base::FilePath& path,
std::unique_ptr<disk_cache::BackendFileOperations> ops) {
base::ScopedAllowBaseSyncPrimitivesForTesting scope;
auto enumerator = ops->EnumerateFiles(path);
std::vector<Entry> entries;
while (auto entry = enumerator->Next()) {
entries.push_back(std::move(*entry));
}
return std::make_pair(entries, enumerator->HasError());
},
path, std::move(ops)),
base::BindOnce(
[](EnumerateFilesCallback callback,
std::pair<std::vector<Entry>, bool> arg) {
std::move(callback).Run(arg.first, arg.second);
},
std::move(callback)));
}
void CreateSimpleCache(
mojo::PendingRemote<network::mojom::HttpCacheBackendFileOperationsFactory>
factory,
const base::FilePath& path,
bool reset,
CreateSimpleCacheCallback callback) override {
const auto reset_mode = reset ? disk_cache::ResetHandling::kReset
: disk_cache::ResetHandling::kResetOnError;
disk_cache::BackendResult result = disk_cache::CreateCacheBackend(
net::DISK_CACHE, net::CACHE_BACKEND_SIMPLE,
base::MakeRefCounted<network::MojoBackendFileOperationsFactory>(
std::move(factory)),
path, 64 * 1024 * 1024, reset_mode, net::NetLog::Get(),
base::BindOnce(&NetworkServiceTestImpl::OnCacheCreated,
weak_factory_.GetWeakPtr(), std::move(callback)));
DCHECK_EQ(result.net_error, net::ERR_IO_PENDING);
}
void MakeRequestToServer(network::TransferableSocket transferred,
const net::IPEndPoint& endpoint,
MakeRequestToServerCallback callback) override {
std::unique_ptr<net::TCPSocket> socket =
net::TCPSocket::Create(nullptr, nullptr, net::NetLogSource());
socket->AdoptConnectedSocket(transferred.TakeSocket(), endpoint);
const std::string kRequest("GET / HTTP/1.0\r\n\r\n");
auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kRequest);
int rv = socket->Write(io_buffer.get(), io_buffer->size(),
base::DoNothing(), TRAFFIC_ANNOTATION_FOR_TESTS);
// For purposes of tests, this IPC only supports sync Write calls.
DCHECK_NE(net::ERR_IO_PENDING, rv);
std::move(callback).Run(rv == static_cast<int>(kRequest.size()));
}
void ResolveOwnHostnameWithSystemDns(
ResolveOwnHostnameWithSystemDnsCallback callback) override {
std::unique_ptr<net::HostResolverSystemTask> system_task =
net::HostResolverSystemTask::CreateForOwnHostname(
net::AddressFamily::ADDRESS_FAMILY_UNSPECIFIED, 0);
net::HostResolverSystemTask* system_task_ptr = system_task.get();
auto forward_system_dns_results =
[](std::unique_ptr<net::HostResolverSystemTask>,
net::SystemDnsResultsCallback callback,
const net::AddressList& addr_list, int os_error, int net_error) {
std::move(callback).Run(addr_list, os_error, net_error);
};
auto results_cb = base::BindOnce(
std::move(forward_system_dns_results), std::move(system_task),
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
std::move(callback), net::AddressList(), 0, net::ERR_ABORTED));
system_task_ptr->Start(std::move(results_cb));
}
void SetIPv6ProbeResult(bool success,
SetIPv6ProbeResultCallback callback) override {
network::NetworkService::GetNetworkServiceForTesting()
->host_resolver_manager()
->SetLastIPv6ProbeResultForTesting(success);
std::move(callback).Run();
}
#if BUILDFLAG(IS_LINUX)
void GetAddressMapCacheLinux(
GetAddressMapCacheLinuxCallback callback) override {
const net::AddressMapOwnerLinux* address_map_owner =
net::NetworkChangeNotifier::GetAddressMapOwner();
std::move(callback).Run(address_map_owner->GetAddressMap(),
address_map_owner->GetOnlineLinks());
}
#endif // BUILDFLAG(IS_LINUX)
void AllowsGSSAPILibraryLoad(
AllowsGSSAPILibraryLoadCallback callback) override {
bool allow_gssapi_library_load;
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
allow_gssapi_library_load =
network::NetworkService::GetNetworkServiceForTesting()
->http_auth_dynamic_network_service_params_for_testing()
->allow_gssapi_library_load;
#else
allow_gssapi_library_load = true;
#endif
std::move(callback).Run(allow_gssapi_library_load);
}
#if BUILDFLAG(IS_WIN)
void DisableExclusiveCookieDatabaseLockingForTesting(
DisableExclusiveCookieDatabaseLockingForTestingCallback callback)
override {
network::NetworkService::GetNetworkServiceForTesting()
->disable_exclusive_cookie_database_locking_for_testing();
std::move(callback).Run();
}
#endif // BUILDFLAG(IS_WIN)
void IsHappyEyeballsV3Enabled(
IsHappyEyeballsV3EnabledCallback callback) override {
const bool enabled = network::NetworkService::GetNetworkServiceForTesting()
->host_resolver_manager()
->IsHappyEyeballsV3Enabled();
std::move(callback).Run(enabled);
}
private:
void OnMemoryPressure(
base::MemoryPressureLevel memory_pressure_level) override {
latest_memory_pressure_level_ = memory_pressure_level;
}
void OnCacheCreated(CreateSimpleCacheCallback callback,
disk_cache::BackendResult result) {
std::unique_ptr<disk_cache::Backend> backend = std::move(result.backend);
if (result.net_error != net::OK) {
DCHECK(!backend);
std::move(callback).Run(mojo::NullRemote());
return;
}
DCHECK(backend);
mojo::PendingRemote<network::mojom::SimpleCache> remote;
mojo::MakeSelfOwnedReceiver(
std::make_unique<SimpleCache>(std::move(backend)),
remote.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(remote));
}
void OnNetworkDataWritten(int rv) { write_result_ = rv; }
bool registered_as_destruction_observer_ = false;
bool have_test_doh_servers_ = false;
mojo::ReceiverSet<network::mojom::NetworkServiceTest> receivers_;
std::unique_ptr<TestHostResolver> test_host_resolver_;
std::unique_ptr<net::MockCertVerifier> mock_cert_verifier_;
std::unique_ptr<net::ScopedTransportSecurityStateSource>
transport_security_state_source_;
std::optional<base::SyncMemoryPressureListenerRegistration>
memory_pressure_listener_registration_;
base::MemoryPressureLevel latest_memory_pressure_level_ =
base::MEMORY_PRESSURE_LEVEL_NONE;
int write_result_;
std::unique_ptr<disk_cache::Backend> disk_cache_backend_;
base::WeakPtrFactory<NetworkServiceTestImpl> weak_factory_{this};
};
NetworkServiceTestHelper::NetworkServiceTestHelper()
: network_service_test_impl_(new NetworkServiceTestImpl) {
static bool is_created = false;
DCHECK(!is_created) << "NetworkServiceTestHelper shouldn't be created twice.";
is_created = true;
}
NetworkServiceTestHelper::~NetworkServiceTestHelper() = default;
std::unique_ptr<NetworkServiceTestHelper> NetworkServiceTestHelper::Create() {
if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kUtilitySubType) == network::mojom::NetworkService::Name_) {
std::unique_ptr<NetworkServiceTestHelper> helper(
new NetworkServiceTestHelper());
SetNetworkBinderCreationCallbackForTesting(
base::BindOnce(&NetworkServiceTestHelper::RegisterNetworkBinders,
base::Unretained(helper.get())));
return helper;
}
return nullptr;
}
void NetworkServiceTestHelper::RegisterNetworkBinders(
service_manager::BinderRegistry* registry) {
registry->AddInterface(base::BindRepeating(
[](NetworkServiceTestHelper* helper,
mojo::PendingReceiver<network::mojom::NetworkServiceTest> receiver) {
helper->network_service_test_impl_->BindReceiver(std::move(receiver));
},
base::Unretained(this)));
}
} // namespace content