#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/json/values_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_controller_factory.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "net/base/features.h"
#include "net/cookies/cookie_util.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/gtest_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
#include "services/network/test/udp_socket_test_util.h"
#include "sql/database.h"
#include "sql/sql_features.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/application_status_listener.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "sandbox/policy/features.h"
#endif
namespace content {
namespace {
class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
public:
std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
WebUI* web_ui,
const GURL& url) override {
std::string foo(url.path());
if (url.path() == "/nobinding/")
web_ui->SetBindings(BINDINGS_POLICY_NONE);
return HasWebUIScheme(url) ? std::make_unique<WebUIController>(web_ui)
: nullptr;
}
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) override {
return HasWebUIScheme(url) ? reinterpret_cast<WebUI::TypeID>(1) : nullptr;
}
bool UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) override {
return HasWebUIScheme(url);
}
};
class TestWebUIDataSource : public URLDataSource {
public:
TestWebUIDataSource() {}
TestWebUIDataSource(const TestWebUIDataSource&) = delete;
TestWebUIDataSource& operator=(const TestWebUIDataSource&) = delete;
~TestWebUIDataSource() override {}
std::string GetSource() override { return "webui"; }
void StartDataRequest(const GURL& url,
const WebContents::Getter& wc_getter,
URLDataSource::GotDataCallback callback) override {
std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>(
std::string("<html><body>Foo</body></html>")));
}
std::string GetMimeType(const GURL& url) override { return "text/html"; }
};
class NetworkServiceBrowserTest : public ContentBrowserTest {
public:
NetworkServiceBrowserTest() {
EXPECT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
WebUIControllerFactory::RegisterFactory(&factory_);
}
NetworkServiceBrowserTest(const NetworkServiceBrowserTest&) = delete;
NetworkServiceBrowserTest& operator=(const NetworkServiceBrowserTest&) =
delete;
bool FetchResource(const GURL& url,
bool synchronous = false,
bool expect_disallowed = false) {
if (!url.is_valid())
return false;
std::string script = JsReplace(
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', $1, $2);"
"new Promise(resolve => {"
" xhr.onload = function (e) {"
" if (xhr.readyState === 4) {"
" resolve(xhr.status === 200);"
" }"
" };"
" xhr.onerror = function () {"
" resolve(false);"
" };"
" try {"
" xhr.send(null);"
" } catch (error) {"
" resolve(false);"
" }"
"});",
url, !synchronous);
return expect_disallowed ? ExecJs(shell(), script)
: EvalJs(shell(), script).ExtractBool();
}
bool CheckCanLoadHttp(bool expect_disallowed = false) {
return FetchResource(embedded_test_server()->GetURL("/echo"),
false, expect_disallowed);
}
void SetUpOnMainThread() override {
URLDataSource::Add(shell()->web_contents()->GetBrowserContext(),
std::make_unique<TestWebUIDataSource>());
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kDisableWebSecurity);
IsolateAllSitesForTesting(command_line);
}
base::FilePath GetCacheDirectory() { return temp_dir_.GetPath(); }
base::FilePath GetCacheIndexDirectory() {
return GetCacheDirectory()
.AppendASCII("Cache_Data")
.AppendASCII("index-dir");
}
void LoadURL(const GURL& url,
network::mojom::URLLoaderFactory* loader_factory) {
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = url;
url::Origin origin = url::Origin::Create(url);
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->isolation_info =
net::IsolationInfo::CreateForInternalRequest(origin);
request->site_for_cookies =
request->trusted_params->isolation_info.site_for_cookies();
SimpleURLLoaderTestHelper simple_loader_helper;
std::unique_ptr<network::SimpleURLLoader> simple_loader =
network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory, simple_loader_helper.GetCallback());
simple_loader_helper.WaitForCallback();
ASSERT_TRUE(simple_loader_helper.response_body());
}
private:
WebUITestWebUIControllerFactory factory_;
base::ScopedTempDir temp_dir_;
};
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_WebUIBindingsNoHttp DISABLED_WebUIBindingsNoHttp
#else
#define MAYBE_WebUIBindingsNoHttp WebUIBindingsNoHttp
#endif
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, MAYBE_WebUIBindingsNoHttp) {
GURL test_url(GetWebUIURL("webui/"));
EXPECT_TRUE(NavigateToURL(shell(), test_url));
RenderProcessHostBadIpcMessageWaiter kill_waiter(
shell()->web_contents()->GetPrimaryMainFrame()->GetProcess());
ASSERT_FALSE(CheckCanLoadHttp(true));
EXPECT_EQ(bad_message::RPH_MOJO_PROCESS_ERROR, kill_waiter.Wait());
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, NoWebUIBindingsHttp) {
GURL test_url(GetWebUIURL("webui/nobinding/"));
EXPECT_TRUE(NavigateToURL(shell(), test_url));
ASSERT_TRUE(CheckCanLoadHttp());
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
FileSystemBindingsCorrectOrigin) {
GURL test_url(GetWebUIURL("webui/nobinding/"));
EXPECT_TRUE(NavigateToURL(shell(), test_url));
GURL file_url("filesystem:file:///etc/passwd");
EXPECT_FALSE(FetchResource(file_url));
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
SimpleUrlLoader_NoAuthWhenNoWebContents) {
auto request = std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL("/auth-basic?password=");
auto loader = network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
auto loader_factory = shell()
->web_contents()
->GetBrowserContext()
->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess();
scoped_refptr<net::HttpResponseHeaders> headers;
base::RunLoop loop;
loader->DownloadHeadersOnly(
loader_factory.get(),
base::BindOnce(
[](base::OnceClosure quit_closure,
scoped_refptr<net::HttpResponseHeaders>* rh_out,
scoped_refptr<net::HttpResponseHeaders> rh_in) {
*rh_out = rh_in;
std::move(quit_closure).Run();
},
loop.QuitClosure(), &headers));
loop.Run();
ASSERT_TRUE(headers.get());
ASSERT_EQ(headers->response_code(), 401);
}
#if BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
HttpCacheWrittenToDiskOnApplicationStateChange) {
base::ScopedAllowBlockingForTesting allow_blocking;
mojo::Remote<network::mojom::NetworkContext> network_context;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params = GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
context_params->http_cache_directory = GetCacheDirectory();
CreateNetworkContextInNetworkService(
network_context.BindNewPipeAndPassReceiver(), std::move(context_params));
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
params->process_id = network::mojom::kBrowserProcessId;
params->automatically_assign_isolation_info = true;
params->is_corb_enabled = false;
params->is_trusted = true;
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
network_context->CreateURLLoaderFactory(
loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
LoadURL(embedded_test_server()->GetURL("/cachetime"), loader_factory.get());
int64_t directory_size = base::ComputeDirectorySize(GetCacheIndexDirectory());
LoadURL(embedded_test_server()->GetURL("/cachetime?foo"),
loader_factory.get());
EXPECT_EQ(directory_size,
base::ComputeDirectorySize(GetCacheIndexDirectory()));
base::android::ApplicationStatusListener::NotifyApplicationStateChange(
base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES);
base::RunLoop().RunUntilIdle();
FlushNetworkServiceInstanceForTesting();
disk_cache::FlushCacheThreadForTesting();
EXPECT_GT(base::ComputeDirectorySize(GetCacheIndexDirectory()),
directory_size);
}
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
class NetworkConnectionObserver
: public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
NetworkConnectionObserver() {
content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this);
content::GetNetworkConnectionTracker()->GetConnectionType(
&last_connection_type_,
base::BindOnce(&NetworkConnectionObserver::OnConnectionChanged,
base::Unretained(this)));
}
~NetworkConnectionObserver() override {
content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(
this);
}
void WaitForConnectionType(network::mojom::ConnectionType type) {
type_to_wait_for_ = type;
if (last_connection_type_ == type_to_wait_for_)
return;
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
void OnConnectionChanged(network::mojom::ConnectionType type) override {
last_connection_type_ = type;
if (run_loop_ && type_to_wait_for_ == type)
run_loop_->Quit();
}
private:
network::mojom::ConnectionType type_to_wait_for_ =
network::mojom::ConnectionType::CONNECTION_UNKNOWN;
network::mojom::ConnectionType last_connection_type_ =
network::mojom::ConnectionType::CONNECTION_UNKNOWN;
std::unique_ptr<base::RunLoop> run_loop_;
};
class NetworkServiceConnectionTypeSyncedBrowserTest
: public NetworkServiceBrowserTest {
public:
NetworkServiceConnectionTypeSyncedBrowserTest() {
scoped_feature_list_.InitWithFeatures(
#if BUILDFLAG(IS_LINUX)
{net::features::kAddressTrackerLinuxIsProxied},
#else
{},
#endif
{features::kNetworkServiceInProcess});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(NetworkServiceConnectionTypeSyncedBrowserTest,
ConnectionTypeChangeSyncedToNetworkProcess) {
NetworkConnectionObserver observer;
net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
net::NetworkChangeNotifier::CONNECTION_WIFI);
observer.WaitForConnectionType(
network::mojom::ConnectionType::CONNECTION_WIFI);
net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
net::NetworkChangeNotifier::CONNECTION_ETHERNET);
observer.WaitForConnectionType(
network::mojom::ConnectionType::CONNECTION_ETHERNET);
}
#endif
class NetworkServiceOutOfProcessBrowserTest : public NetworkServiceBrowserTest {
public:
NetworkServiceOutOfProcessBrowserTest() {
scoped_feature_list_.InitAndDisableFeature(
features::kNetworkServiceInProcess);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(NetworkServiceOutOfProcessBrowserTest,
MemoryPressureSentToNetworkProcess) {
mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
GetNetworkService()->BindTestInterfaceForTesting(
network_service_test.BindNewPipeAndPassReceiver());
network_service_test.FlushForTesting();
mojo::ScopedAllowSyncCallForTesting allow_sync_call;
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level =
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
network_service_test->GetLatestMemoryPressureLevel(&memory_pressure_level);
EXPECT_EQ(memory_pressure_level,
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE);
base::MemoryPressureListener::NotifyMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
base::RunLoop().RunUntilIdle();
FlushNetworkServiceInstanceForTesting();
network_service_test->GetLatestMemoryPressureLevel(&memory_pressure_level);
EXPECT_EQ(memory_pressure_level,
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
}
IN_PROC_BROWSER_TEST_F(NetworkServiceOutOfProcessBrowserTest, SyncXHROnCrash) {
net::EmbeddedTestServer http_server;
http_server.AddDefaultHandlers(GetTestDataFilePath());
http_server.RegisterRequestMonitor(base::BindLambdaForTesting(
[&](const net::test_server::HttpRequest& request) {
if (request.relative_url == "/hung") {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&BrowserTestBase::SimulateNetworkServiceCrash,
base::Unretained(this)));
}
}));
EXPECT_TRUE(http_server.Start());
EXPECT_TRUE(NavigateToURL(shell(), http_server.GetURL("/empty.html")));
FetchResource(http_server.GetURL("/hung"), true);
}
IN_PROC_BROWSER_TEST_F(NetworkServiceOutOfProcessBrowserTest,
SyncCookieGetOnCrash) {
mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
GetNetworkService()->BindTestInterfaceForTesting(
network_service_test.BindNewPipeAndPassReceiver());
network_service_test->CrashOnGetCookieList();
EXPECT_TRUE(
NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html")));
ASSERT_TRUE(
content::ExecuteScript(shell()->web_contents(), "document.cookie"));
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest, FactoryOverride) {
class TestURLLoaderFactory final : public network::mojom::URLLoaderFactory {
public:
void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
mojo::PendingRemote<network::mojom::URLLoaderClient> pending_client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
override {
mojo::Remote<network::mojom::URLLoaderClient> client(
std::move(pending_client));
EXPECT_EQ(resource_request.url,
GURL("https://www.example.com/hello.txt"));
if (resource_request.method == "OPTIONS") {
has_received_preflight_ = true;
auto response = network::mojom::URLResponseHead::New();
response->headers =
base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
response->headers->SetHeader("access-control-allow-origin",
"https://www2.example.com");
response->headers->SetHeader("access-control-allow-methods", "*");
client->OnReceiveResponse(std::move(response),
mojo::ScopedDataPipeConsumerHandle(),
absl::nullopt);
} else if (resource_request.method == "custom-method") {
has_received_request_ = true;
auto response = network::mojom::URLResponseHead::New();
response->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
"HTTP/1.1 202 Accepted");
response->headers->SetHeader("access-control-allow-origin",
"https://www2.example.com");
client->OnReceiveResponse(std::move(response),
mojo::ScopedDataPipeConsumerHandle(),
absl::nullopt);
client->OnComplete(network::URLLoaderCompletionStatus(net::OK));
} else {
client->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
}
}
void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
override {
NOTREACHED();
}
bool has_received_preflight() const { return has_received_preflight_; }
bool has_received_request() const { return has_received_request_; }
private:
bool has_received_preflight_ = false;
bool has_received_request_ = false;
};
auto request = std::make_unique<network::ResourceRequest>();
request->url = GURL("https://www.example.com/hello.txt");
request->mode = network::mojom::RequestMode::kCors;
request->credentials_mode = network::mojom::CredentialsMode::kSameOrigin;
request->method = "custom-method";
request->request_initiator =
url::Origin::Create(GURL("https://www2.example.com/"));
auto test_loader_factory = std::make_unique<TestURLLoaderFactory>();
mojo::Receiver<network::mojom::URLLoaderFactory> test_loader_factory_receiver(
test_loader_factory.get());
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory_remote;
auto loader = network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
auto params = network::mojom::URLLoaderFactoryParams::New();
params->process_id = 0;
params->factory_override = network::mojom::URLLoaderFactoryOverride::New();
params->factory_override->overriding_factory =
test_loader_factory_receiver.BindNewPipeAndPassRemote();
shell()
->web_contents()
->GetBrowserContext()
->GetDefaultStoragePartition()
->GetNetworkContext()
->CreateURLLoaderFactory(
loader_factory_remote.BindNewPipeAndPassReceiver(),
std::move(params));
scoped_refptr<net::HttpResponseHeaders> headers;
base::RunLoop loop;
loader->DownloadHeadersOnly(
loader_factory_remote.get(),
base::BindLambdaForTesting(
[&](scoped_refptr<net::HttpResponseHeaders> passed_headers) {
headers = passed_headers;
loop.Quit();
}));
loop.Run();
ASSERT_TRUE(headers.get());
EXPECT_EQ(headers->response_code(), 202);
EXPECT_TRUE(test_loader_factory->has_received_preflight());
EXPECT_TRUE(test_loader_factory->has_received_request());
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_FUCHSIA)
class NetworkServiceBrowserCacheResetTest : public NetworkServiceBrowserTest {
public:
NetworkServiceBrowserCacheResetTest() = default;
protected:
void StoreUrl(const GURL& url) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath data_file =
shell()->web_contents()->GetBrowserContext()->GetPath().Append(
FILE_PATH_LITERAL("TestData"));
std::string data;
base::JSONWriter::Write(base::Value(url.spec()), &data);
EXPECT_TRUE(base::WriteFile(data_file, data));
}
void RetrieveUrl(GURL& url) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath data_file =
shell()->web_contents()->GetBrowserContext()->GetPath().Append(
FILE_PATH_LITERAL("TestData"));
std::string data;
EXPECT_TRUE(base::ReadFileToString(data_file, &data));
auto json_data = base::JSONReader::Read(data);
ASSERT_TRUE(json_data.has_value());
url = GURL(json_data->GetString());
EXPECT_TRUE(url.is_valid());
}
base::FilePath GetNetworkContextPath() {
return shell()->web_contents()->GetBrowserContext()->GetPath().Append(
FILE_PATH_LITERAL("TestContext"));
}
base::FilePath GetNetworkContextCachePath() {
return GetNetworkContextPath().Append(FILE_PATH_LITERAL("Cache"));
}
int MakeNetworkContentAndLoadUrl(bool reset_cache,
bool load_only_from_cache,
const GURL& url) {
auto file_paths = network::mojom::NetworkContextFilePaths::New();
base::FilePath context_path = GetNetworkContextPath();
file_paths->data_directory = context_path.Append(FILE_PATH_LITERAL("Data"));
file_paths->unsandboxed_data_path = context_path;
file_paths->trigger_migration = true;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->file_paths = std::move(file_paths);
context_params->cert_verifier_params = GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
context_params->reset_http_cache_backend = reset_cache;
context_params->http_cache_enabled = true;
context_params->http_cache_directory = GetNetworkContextCachePath();
mojo::Remote<network::mojom::NetworkContext> network_context;
content::CreateNetworkContextInNetworkService(
network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
network::mojom::URLLoaderFactoryParamsPtr url_loader_params =
network::mojom::URLLoaderFactoryParams::New();
url_loader_params->process_id = network::mojom::kBrowserProcessId;
url_loader_params->is_trusted = true;
mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory;
network_context->CreateURLLoaderFactory(
url_loader_factory.BindNewPipeAndPassReceiver(),
std::move(url_loader_params));
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = url;
url::Origin origin = url::Origin::Create(url);
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->isolation_info =
net::IsolationInfo::CreateForInternalRequest(origin);
request->site_for_cookies =
request->trusted_params->isolation_info.site_for_cookies();
if (load_only_from_cache)
request->load_flags |= net::LOAD_ONLY_FROM_CACHE;
auto loader = network::SimpleURLLoader::Create(
std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS);
scoped_refptr<net::HttpResponseHeaders> headers;
base::RunLoop loop;
loader->DownloadHeadersOnly(
url_loader_factory.get(),
base::BindLambdaForTesting(
[&](scoped_refptr<net::HttpResponseHeaders> passed_headers) {
headers = passed_headers;
loop.Quit();
}));
loop.Run();
return loader->NetError();
}
void GetCacheFileInfo(base::File::Info& info) {
base::FilePath ceontxt_path = GetNetworkContextPath();
base::FileEnumerator cache_files(GetNetworkContextCachePath(), true,
base::FileEnumerator::FILES);
auto file_path = cache_files.Next();
ASSERT_FALSE(file_path.empty());
ASSERT_TRUE(base::GetFileInfo(file_path, &info));
}
};
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserCacheResetTest,
PRE_PRE_CacheResetTest) {
GURL url = embedded_test_server()->GetURL("/echoheadercache");
ASSERT_NO_FATAL_FAILURE(StoreUrl(url));
EXPECT_THAT(MakeNetworkContentAndLoadUrl(
false, false, url),
net::test::IsOk());
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserCacheResetTest,
PRE_CacheResetTest) {
GURL url;
ASSERT_NO_FATAL_FAILURE(RetrieveUrl(url));
EXPECT_THAT(MakeNetworkContentAndLoadUrl(false,
true, url),
net::test::IsOk());
}
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserCacheResetTest, CacheResetTest) {
GURL url;
ASSERT_NO_FATAL_FAILURE(RetrieveUrl(url));
EXPECT_THAT(MakeNetworkContentAndLoadUrl(true,
true, url),
net::test::IsError(net::ERR_CACHE_MISS));
}
#if BUILDFLAG(IS_POSIX)
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserCacheResetTest, CacheResetFailure) {
base::ScopedAllowBlockingForTesting allow_blocking;
const base::FilePath path = GetNetworkContextCachePath();
GURL url = embedded_test_server()->GetURL("/echoheadercache");
ASSERT_TRUE(base::CreateDirectory(path));
ASSERT_TRUE(base::SetPosixFilePermissions(path, 0));
EXPECT_THAT(MakeNetworkContentAndLoadUrl(true,
true, url),
net::test::IsError(net::ERR_CACHE_MISS));
}
#endif
#endif
#if !BUILDFLAG(IS_FUCHSIA)
const base::FilePath::CharType kCheckpointFileName[] =
FILE_PATH_LITERAL("NetworkDataMigrated");
constexpr char kCookieName[] = "Name";
constexpr char kCookieValue[] = "Value";
net::CookieList GetCookies(
const mojo::Remote<network::mojom::CookieManager>& cookie_manager) {
base::RunLoop run_loop;
net::CookieList cookies_out;
cookie_manager->GetAllCookies(
base::BindLambdaForTesting([&](const net::CookieList& cookies) {
cookies_out = cookies;
run_loop.Quit();
}));
run_loop.Run();
return cookies_out;
}
void SetCookie(
const mojo::Remote<network::mojom::CookieManager>& cookie_manager) {
base::Time t = base::Time::Now();
auto cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting(
kCookieName, kCookieValue, "example.test", "/", t, t + base::Days(1),
base::Time(), base::Time(), true, false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_DEFAULT,
false);
base::RunLoop run_loop;
cookie_manager->SetCanonicalCookie(
*cookie, net::cookie_util::SimulatedCookieSource(*cookie, "https"),
net::CookieOptions(),
base::BindLambdaForTesting(
[&](net::CookieAccessResult result) { run_loop.Quit(); }));
run_loop.Run();
}
void FlushCookies(
const mojo::Remote<network::mojom::CookieManager>& cookie_manager) {
base::RunLoop run_loop;
cookie_manager->FlushCookieStore(
base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
run_loop.Run();
}
mojo::PendingRemote<network::mojom::NetworkContext>
CreateNetworkContextForPaths(network::mojom::NetworkContextFilePathsPtr paths,
const base::FilePath& cache_path) {
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->file_paths = std::move(paths);
context_params->cert_verifier_params = GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
context_params->enable_encrypted_cookies = false;
context_params->http_cache_enabled = true;
context_params->http_cache_directory = cache_path;
mojo::PendingRemote<network::mojom::NetworkContext> network_context;
content::CreateNetworkContextInNetworkService(
network_context.InitWithNewPipeAndPassReceiver(),
std::move(context_params));
return network_context;
}
enum class FailureType {
kNoFailures = 0,
kDirIsAFile = 1,
kDirAlreadyThere = 2,
kCookieFileAlreadyThere = 3,
#if BUILDFLAG(IS_WIN)
kDestCookieFileIsLocked = 4,
kSourceCookieFileIsLocked = 5,
#endif
kCacheDirIsAFile = 6,
};
static const FailureType kFailureTypes[] = {
FailureType::kNoFailures,
FailureType::kDirIsAFile,
FailureType::kDirAlreadyThere,
FailureType::kCookieFileAlreadyThere,
#if BUILDFLAG(IS_WIN)
FailureType::kDestCookieFileIsLocked,
FailureType::kSourceCookieFileIsLocked,
#endif
FailureType::kCacheDirIsAFile};
static const base::FilePath::CharType kCookieDatabaseName[] =
FILE_PATH_LITERAL("TestCookies");
static const base::FilePath::CharType kNetworkSubpath[] =
FILE_PATH_LITERAL("Network");
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_NetworkServiceDataMigrationBrowserTest \
DISABLED_NetworkServiceDataMigrationBrowserTest
#define MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures \
DISABLED_NetworkServiceDataMigrationBrowserTestWithFailures
#else
#define MAYBE_NetworkServiceDataMigrationBrowserTest \
NetworkServiceDataMigrationBrowserTest
#define MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures \
NetworkServiceDataMigrationBrowserTestWithFailures
#endif
class MAYBE_NetworkServiceDataMigrationBrowserTest : public ContentBrowserTest {
public:
MAYBE_NetworkServiceDataMigrationBrowserTest() {
EXPECT_FALSE(
base::FeatureList::IsEnabled(sql::features::kEnableWALModeByDefault));
#if BUILDFLAG(IS_WIN)
win_network_sandbox_feature_.InitAndDisableFeature(
sandbox::policy::features::kNetworkServiceSandbox);
#endif
}
#if BUILDFLAG(IS_WIN)
private:
base::test::ScopedFeatureList win_network_sandbox_feature_;
#endif
};
class MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures
: public MAYBE_NetworkServiceDataMigrationBrowserTest,
public ::testing::WithParamInterface<std::tuple<bool, FailureType>> {
public:
MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures() {
if (IsNetworkServiceRunningInProcess())
network_service_in_process_feature_.InitAndEnableFeature(
features::kNetworkServiceInProcess);
}
protected:
bool IsNetworkServiceRunningInProcess() { return std::get<0>(GetParam()); }
FailureType GetFailureType() { return std::get<1>(GetParam()); }
private:
base::test::ScopedFeatureList network_service_in_process_feature_;
};
void MigrationTestInternal(const base::FilePath& tempdir_one,
const base::FilePath& tempdir_two_parent,
FailureType failure_type) {
EXPECT_FALSE(base::PathExists(tempdir_one.Append(kCookieDatabaseName)));
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = tempdir_one;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
mojo::Remote<network::mojom::NetworkContext> network_context_one(
CreateNetworkContextForPaths(
std::move(file_paths),
tempdir_one.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager_one;
network_context_one->GetCookieManager(
cookie_manager_one.BindNewPipeAndPassReceiver());
SetCookie(cookie_manager_one);
FlushCookies(cookie_manager_one);
EXPECT_TRUE(base::PathExists(tempdir_one.Append(kCookieDatabaseName)));
EXPECT_TRUE(base::CopyDirectory(tempdir_one, tempdir_two_parent, true));
base::FilePath tempdir_two =
tempdir_two_parent.Append(tempdir_one.BaseName());
EXPECT_TRUE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
#if BUILDFLAG(IS_WIN)
base::File longer_lived_file;
#endif
switch (failure_type) {
case FailureType::kNoFailures:
break;
case FailureType::kDirIsAFile: {
base::File scoped_file(
tempdir_two.Append(kNetworkSubpath),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
EXPECT_TRUE(scoped_file.IsValid());
} break;
case FailureType::kDirAlreadyThere:
EXPECT_TRUE(base::CreateDirectory(tempdir_two.Append(kNetworkSubpath)));
break;
case FailureType::kCookieFileAlreadyThere: {
EXPECT_TRUE(base::CreateDirectory(tempdir_two.Append(kNetworkSubpath)));
base::File scoped_file(
tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
EXPECT_TRUE(scoped_file.IsValid());
} break;
#if BUILDFLAG(IS_WIN)
case FailureType::kDestCookieFileIsLocked:
EXPECT_TRUE(base::CreateDirectory(tempdir_two.Append(kNetworkSubpath)));
longer_lived_file = base::File(
tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_WIN_EXCLUSIVE_WRITE |
base::File::FLAG_WIN_EXCLUSIVE_READ);
EXPECT_TRUE(longer_lived_file.IsValid());
break;
case FailureType::kSourceCookieFileIsLocked:
longer_lived_file =
base::File(tempdir_two.Append(kCookieDatabaseName),
base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_WIN_EXCLUSIVE_WRITE |
base::File::FLAG_WIN_EXCLUSIVE_READ);
EXPECT_TRUE(longer_lived_file.IsValid());
break;
#endif
case FailureType::kCacheDirIsAFile: {
base::DeletePathRecursively(
tempdir_two.Append(FILE_PATH_LITERAL("Cache")));
base::File scoped_file(
tempdir_two.Append(FILE_PATH_LITERAL("Cache")),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
EXPECT_TRUE(scoped_file.IsValid());
} break;
}
auto new_file_paths = network::mojom::NetworkContextFilePaths::New();
new_file_paths->data_directory = tempdir_two.Append(kNetworkSubpath);
new_file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
new_file_paths->unsandboxed_data_path = tempdir_two;
new_file_paths->trigger_migration = true;
base::HistogramTester histogram_tester;
mojo::Remote<network::mojom::NetworkContext> network_context_two(
CreateNetworkContextForPaths(
std::move(new_file_paths),
tempdir_two.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager_two;
network_context_two->GetCookieManager(
cookie_manager_two.BindNewPipeAndPassReceiver());
net::CookieList cookies = GetCookies(cookie_manager_two);
bool cookies_should_work = true;
switch (failure_type) {
case FailureType::kNoFailures:
case FailureType::kDirAlreadyThere:
case FailureType::kCookieFileAlreadyThere:
EXPECT_FALSE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
EXPECT_TRUE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
if (base::PathExists(tempdir_one.Append(sql::Database::JournalPath(
base::FilePath(kCookieDatabaseName))))) {
EXPECT_FALSE(base::PathExists(tempdir_two.Append(
sql::Database::JournalPath(base::FilePath(kCookieDatabaseName)))));
EXPECT_TRUE(
base::PathExists(tempdir_two.Append(kNetworkSubpath)
.Append(sql::Database::JournalPath(
base::FilePath(kCookieDatabaseName)))));
}
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
0,
1);
EXPECT_TRUE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCheckpointFileName)));
break;
case FailureType::kDirIsAFile:
EXPECT_TRUE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCheckpointFileName)));
histogram_tester.ExpectUniqueSample(
"NetworkService.GrantSandboxResult",
2,
1);
break;
#if BUILDFLAG(IS_WIN)
case FailureType::kDestCookieFileIsLocked:
EXPECT_TRUE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
EXPECT_TRUE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
EXPECT_TRUE(
base::PathExists(tempdir_two.Append(FILE_PATH_LITERAL("Network"))
.Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCheckpointFileName)));
{
base::File attempt_to_open_locked_file(
tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName),
base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
EXPECT_FALSE(attempt_to_open_locked_file.IsValid());
}
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
3,
1);
break;
case FailureType::kSourceCookieFileIsLocked:
EXPECT_TRUE(base::PathExists(tempdir_two.Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(
tempdir_two.Append(kNetworkSubpath).Append(kCheckpointFileName)));
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
3,
1);
cookies_should_work = false;
break;
#endif
case FailureType::kCacheDirIsAFile:
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
0,
1);
break;
}
if (!cookies_should_work)
return;
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
}
IN_PROC_BROWSER_TEST_P(MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures,
MigrateDataTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir_one;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("one"), &tempdir_one));
base::FilePath tempdir_two;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("two"), &tempdir_two));
MigrationTestInternal(tempdir_one, tempdir_two, GetFailureType());
}
IN_PROC_BROWSER_TEST_F(MAYBE_NetworkServiceDataMigrationBrowserTest,
MigrateThenNoMigrate) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir_one;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("one"), &tempdir_one));
base::FilePath tempdir_two;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("two"), &tempdir_two));
MigrationTestInternal(tempdir_one, tempdir_two, FailureType::kNoFailures);
base::FilePath real_tempdir_two = tempdir_two.Append(tempdir_one.BaseName());
EXPECT_TRUE(base::PathExists(
real_tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
base::FilePath tempdir_three;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("three"), &tempdir_three));
EXPECT_TRUE(base::CopyDirectory(real_tempdir_two, tempdir_three, true));
base::FilePath real_tempdir_three =
tempdir_three.Append(real_tempdir_two.BaseName());
EXPECT_TRUE(base::PathExists(
real_tempdir_three.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
EXPECT_FALSE(
base::PathExists(real_tempdir_three.Append(kCookieDatabaseName)));
base::HistogramTester histogram_tester;
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = real_tempdir_three.Append(kNetworkSubpath);
file_paths->unsandboxed_data_path = real_tempdir_three;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
DCHECK_EQ(file_paths->trigger_migration, false);
mojo::Remote<network::mojom::NetworkContext> network_context(
CreateNetworkContextForPaths(
std::move(file_paths),
real_tempdir_three.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager;
network_context->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
net::CookieList cookies = GetCookies(cookie_manager);
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
10,
1);
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
}
IN_PROC_BROWSER_TEST_F(MAYBE_NetworkServiceDataMigrationBrowserTest,
NewDataDirWithMigrationTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL(""), &tempdir));
EXPECT_FALSE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = tempdir.Append(FILE_PATH_LITERAL("Network"));
file_paths->unsandboxed_data_path = tempdir;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
file_paths->trigger_migration = true;
base::HistogramTester histogram_tester;
mojo::Remote<network::mojom::NetworkContext> network_context(
CreateNetworkContextForPaths(std::move(file_paths),
tempdir.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager;
network_context->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
SetCookie(cookie_manager);
FlushCookies(cookie_manager);
EXPECT_FALSE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
EXPECT_TRUE(base::PathExists(tempdir.Append(FILE_PATH_LITERAL("Network"))
.Append(kCookieDatabaseName)));
net::CookieList cookies = GetCookies(cookie_manager);
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
0,
1);
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
}
IN_PROC_BROWSER_TEST_F(MAYBE_NetworkServiceDataMigrationBrowserTest,
NewDataDirWithNoMigrationTest) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL(""), &tempdir));
EXPECT_FALSE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = tempdir.Append(FILE_PATH_LITERAL("Network"));
file_paths->unsandboxed_data_path = tempdir;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
file_paths->trigger_migration = false;
base::HistogramTester histogram_tester;
mojo::Remote<network::mojom::NetworkContext> network_context(
CreateNetworkContextForPaths(std::move(file_paths),
tempdir.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager;
network_context->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
SetCookie(cookie_manager);
FlushCookies(cookie_manager);
EXPECT_TRUE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(tempdir.Append(FILE_PATH_LITERAL("Network"))
.Append(kCookieDatabaseName)));
EXPECT_FALSE(base::PathExists(tempdir.Append(FILE_PATH_LITERAL("Network"))
.Append(kCheckpointFileName)));
net::CookieList cookies = GetCookies(cookie_manager);
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
9,
1);
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
}
IN_PROC_BROWSER_TEST_F(MAYBE_NetworkServiceDataMigrationBrowserTest,
LegacyDataDir) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL(""), &tempdir));
EXPECT_FALSE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = tempdir;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
base::HistogramTester histogram_tester;
mojo::Remote<network::mojom::NetworkContext> network_context(
CreateNetworkContextForPaths(std::move(file_paths),
tempdir.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager;
network_context->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
SetCookie(cookie_manager);
FlushCookies(cookie_manager);
EXPECT_TRUE(base::PathExists(tempdir.Append(kCookieDatabaseName)));
net::CookieList cookies = GetCookies(cookie_manager);
histogram_tester.ExpectUniqueSample(
"NetworkService.GrantSandboxResult",
7,
1);
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
}
IN_PROC_BROWSER_TEST_F(MAYBE_NetworkServiceDataMigrationBrowserTest,
MigratedPreviouslyAndMigrateAgain) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath tempdir_one;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("one"), &tempdir_one));
base::FilePath tempdir_two;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("two"), &tempdir_two));
MigrationTestInternal(tempdir_one, tempdir_two, FailureType::kNoFailures);
base::FilePath real_tempdir_two = tempdir_two.Append(tempdir_one.BaseName());
EXPECT_TRUE(base::PathExists(
real_tempdir_two.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
base::FilePath tempdir_three;
EXPECT_TRUE(base::CreateTemporaryDirInDir(
shell()->web_contents()->GetBrowserContext()->GetPath(),
FILE_PATH_LITERAL("three"), &tempdir_three));
EXPECT_TRUE(base::CopyDirectory(real_tempdir_two, tempdir_three, true));
base::FilePath real_tempdir_three =
tempdir_three.Append(real_tempdir_two.BaseName());
EXPECT_TRUE(base::PathExists(
real_tempdir_three.Append(kNetworkSubpath).Append(kCookieDatabaseName)));
EXPECT_FALSE(
base::PathExists(real_tempdir_three.Append(kCookieDatabaseName)));
base::FilePath checkpoint_file =
real_tempdir_three.Append(kNetworkSubpath).Append(kCheckpointFileName);
EXPECT_TRUE(base::PathExists(checkpoint_file));
EXPECT_TRUE(base::DeleteFile(checkpoint_file));
EXPECT_FALSE(base::PathExists(checkpoint_file));
base::HistogramTester histogram_tester;
auto file_paths = network::mojom::NetworkContextFilePaths::New();
file_paths->data_directory = real_tempdir_three.Append(kNetworkSubpath);
file_paths->unsandboxed_data_path = real_tempdir_three;
file_paths->cookie_database_name = base::FilePath(kCookieDatabaseName);
file_paths->trigger_migration = true;
mojo::Remote<network::mojom::NetworkContext> network_context(
CreateNetworkContextForPaths(
std::move(file_paths),
real_tempdir_three.Append(FILE_PATH_LITERAL("Cache"))));
mojo::Remote<network::mojom::CookieManager> cookie_manager;
network_context->GetCookieManager(
cookie_manager.BindNewPipeAndPassReceiver());
net::CookieList cookies = GetCookies(cookie_manager);
histogram_tester.ExpectUniqueSample("NetworkService.GrantSandboxResult",
0,
1);
ASSERT_EQ(1u, cookies.size());
EXPECT_EQ(kCookieName, cookies[0].Name());
EXPECT_EQ(kCookieValue, cookies[0].Value());
EXPECT_TRUE(base::PathExists(checkpoint_file));
}
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_InProcess DISABLED_InProcess
#define MAYBE_OutOfProcess DISABLED_OutOfProcess
#else
#define MAYBE_InProcess InProcess
#define MAYBE_OutOfProcess OutOfProcess
#endif
INSTANTIATE_TEST_SUITE_P(
MAYBE_InProcess,
MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures,
::testing::Combine(::testing::Values(true),
::testing::ValuesIn(kFailureTypes)));
INSTANTIATE_TEST_SUITE_P(
MAYBE_OutOfProcess,
MAYBE_NetworkServiceDataMigrationBrowserTestWithFailures,
::testing::Combine(::testing::Values(false),
::testing::ValuesIn(kFailureTypes)));
#endif
class NetworkServiceInProcessBrowserTest : public ContentBrowserTest {
public:
NetworkServiceInProcessBrowserTest() {
std::vector<base::test::FeatureRef> features;
features.push_back(features::kNetworkServiceInProcess);
scoped_feature_list_.InitWithFeatures(
features, std::vector<base::test::FeatureRef>());
}
NetworkServiceInProcessBrowserTest(
const NetworkServiceInProcessBrowserTest&) = delete;
NetworkServiceInProcessBrowserTest& operator=(
const NetworkServiceInProcessBrowserTest&) = delete;
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
EXPECT_TRUE(embedded_test_server()->Start());
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(NetworkServiceInProcessBrowserTest, Basic) {
GURL test_url = embedded_test_server()->GetURL("foo.com", "/echo");
StoragePartitionImpl* partition =
static_cast<StoragePartitionImpl*>(shell()
->web_contents()
->GetBrowserContext()
->GetDefaultStoragePartition());
EXPECT_TRUE(NavigateToURL(shell(), test_url));
ASSERT_EQ(net::OK,
LoadBasicRequest(partition->GetNetworkContext(), test_url));
}
class NetworkServiceInvalidLogBrowserTest : public ContentBrowserTest {
public:
NetworkServiceInvalidLogBrowserTest() = default;
NetworkServiceInvalidLogBrowserTest(
const NetworkServiceInvalidLogBrowserTest&) = delete;
NetworkServiceInvalidLogBrowserTest& operator=(
const NetworkServiceInvalidLogBrowserTest&) = delete;
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(network::switches::kLogNetLog, "/abc/def");
}
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
EXPECT_TRUE(embedded_test_server()->Start());
}
};
IN_PROC_BROWSER_TEST_F(NetworkServiceInvalidLogBrowserTest, Basic) {
GURL test_url = embedded_test_server()->GetURL("foo.com", "/echo");
StoragePartitionImpl* partition =
static_cast<StoragePartitionImpl*>(shell()
->web_contents()
->GetBrowserContext()
->GetDefaultStoragePartition());
EXPECT_TRUE(NavigateToURL(shell(), test_url));
ASSERT_EQ(net::OK,
LoadBasicRequest(partition->GetNetworkContext(), test_url));
}
class NetworkServiceWithUDPSocketLimit : public NetworkServiceBrowserTest {
public:
NetworkServiceWithUDPSocketLimit() {
base::FieldTrialParams params;
params[net::features::kLimitOpenUDPSocketsMax.name] =
base::NumberToString(kMaxUDPSockets);
scoped_feature_list_.InitAndEnableFeatureWithParameters(
net::features::kLimitOpenUDPSockets, params);
}
protected:
static constexpr int kMaxUDPSockets = 4;
int ConnectUDPSocketSync(
mojo::Remote<network::mojom::NetworkContext>* network_context,
mojo::Remote<network::mojom::UDPSocket>* socket) {
network_context->get()->CreateUDPSocket(
socket->BindNewPipeAndPassReceiver(), mojo::NullRemote());
net::IPEndPoint remote_addr(net::IPAddress(127, 0, 0, 1), 8080);
network::mojom::UDPSocketOptionsPtr options =
network::mojom::UDPSocketOptions::New();
net::IPEndPoint local_addr;
network::test::UDPSocketTestHelper helper(socket);
return helper.ConnectSync(remote_addr, std::move(options), &local_addr);
}
mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext() {
mojo::Remote<network::mojom::NetworkContext> network_context;
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
context_params->cert_verifier_params = GetCertVerifierParams(
cert_verifier::mojom::CertVerifierCreationParams::New());
CreateNetworkContextInNetworkService(
network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
return network_context;
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(NetworkServiceWithUDPSocketLimit,
UDPSocketBoundEnforced) {
constexpr size_t kNumContexts = 2;
mojo::Remote<network::mojom::NetworkContext> network_contexts[kNumContexts] =
{CreateNetworkContext(), CreateNetworkContext()};
mojo::Remote<network::mojom::UDPSocket> sockets[kMaxUDPSockets];
for (size_t i = 0; i < kMaxUDPSockets; ++i) {
auto* network_context = &network_contexts[i % kNumContexts];
EXPECT_EQ(net::OK, ConnectUDPSocketSync(network_context, &sockets[i]));
}
for (size_t i = 0; i < 4; ++i) {
auto* network_context = &network_contexts[i % kNumContexts];
mojo::Remote<network::mojom::UDPSocket> socket;
EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
ConnectUDPSocketSync(network_context, &socket));
}
}
}
}