blob: 8c69d6e680d08d3dc48f399aa5d3e6c27e6b6775 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/location.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.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/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/filename_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_options.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/ssl_config.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/gtest_util.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/cpp/resource_response_info.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "extensions/browser/browsertest_util.h"
#include "extensions/test/test_extension_dir.h"
#endif
namespace {
const char kCacheRandomPath[] = "/cacherandom";
// Path using a ControllableHttpResponse that's part of the test fixture.
const char kControllablePath[] = "/controllable";
enum class NetworkServiceState {
kDisabled,
kEnabled,
// Similar to |kEnabled|, but will simulate a crash and run tests again the
// restarted Network Service process.
kRestarted,
};
enum class NetworkContextType {
kSystem,
kSafeBrowsing,
kProfile,
kIncognitoProfile,
kOnDiskApp,
kInMemoryApp,
kOnDiskAppWithIncognitoProfile,
};
// This list should be kept in sync with the NetworkContextType enum.
const NetworkContextType kNetworkContextTypes[] = {
NetworkContextType::kSystem,
NetworkContextType::kSafeBrowsing,
NetworkContextType::kProfile,
NetworkContextType::kIncognitoProfile,
NetworkContextType::kOnDiskApp,
NetworkContextType::kInMemoryApp,
NetworkContextType::kOnDiskAppWithIncognitoProfile,
};
struct TestCase {
NetworkServiceState network_service_state;
NetworkContextType network_context_type;
};
network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams() {
return g_browser_process->system_network_context_manager()
->CreateDefaultNetworkContextParams();
}
// Tests the system, profile, and incognito profile NetworkContexts.
class NetworkContextConfigurationBrowserTest
: public InProcessBrowserTest,
public testing::WithParamInterface<TestCase> {
public:
// Backing storage types that can used for various things (HTTP cache,
// cookies, etc).
enum class StorageType {
kNone,
kMemory,
kDisk,
};
enum class CookieType {
kFirstParty,
kThirdParty,
};
enum class CookiePersistenceType {
kSession,
kPersistent,
};
NetworkContextConfigurationBrowserTest() {
// Have to get a port before setting up the command line, but can only set
// up the connection listener after there's a main thread, so can't start
// the test server here.
EXPECT_TRUE(embedded_test_server()->InitializeAndListen());
}
// Returns a cacheable response (10 hours) that is some random text.
static std::unique_ptr<net::test_server::HttpResponse> HandleCacheRandom(
const net::test_server::HttpRequest& request) {
if (request.relative_url != kCacheRandomPath)
return nullptr;
std::unique_ptr<net::test_server::BasicHttpResponse> response =
std::make_unique<net::test_server::BasicHttpResponse>();
response->set_content(base::GenerateGUID());
response->set_content_type("text/plain");
response->AddCustomHeader("Cache-Control", "max-age=60000");
return std::move(response);
}
~NetworkContextConfigurationBrowserTest() override {}
void SetUpInProcessBrowserTestFixture() override {
if (GetParam().network_service_state != NetworkServiceState::kDisabled)
feature_list_.InitAndEnableFeature(network::features::kNetworkService);
}
void SetUpOnMainThread() override {
// Used in a bunch of proxy tests. Should not resolve.
host_resolver()->AddSimulatedFailure("does.not.resolve.test");
controllable_http_response_ =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), kControllablePath);
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&NetworkContextConfigurationBrowserTest::HandleCacheRandom));
embedded_test_server()->StartAcceptingConnections();
if (is_incognito())
incognito_ = CreateIncognitoBrowser();
SimulateNetworkServiceCrashIfNecessary();
}
// Returns true if the NetworkContext being tested is associated with an
// incognito profile.
bool is_incognito() const {
return GetParam().network_context_type ==
NetworkContextType::kIncognitoProfile ||
GetParam().network_context_type ==
NetworkContextType::kOnDiskAppWithIncognitoProfile;
}
void TearDownOnMainThread() override {
// Have to destroy this before the main message loop is torn down. Need to
// leave the embedded test server up for tests that use
// |live_during_shutdown_simple_loader_|. It's safe to destroy the
// ControllableHttpResponse before the test server.
controllable_http_response_.reset();
}
// Returns, as a string, a PAC script that will use the EmbeddedTestServer as
// a proxy.
std::string GetPacScript() const {
return base::StringPrintf(
"function FindProxyForURL(url, host){ return 'PROXY %s;' }",
net::HostPortPair::FromURL(embedded_test_server()->base_url())
.ToString()
.c_str());
}
content::StoragePartition* GetStoragePartition() {
return GetStoragePartitionForContextType(GetParam().network_context_type);
}
content::StoragePartition* GetStoragePartitionForContextType(
NetworkContextType network_context_type) {
const GURL kOnDiskUrl("chrome-guest://foo/persist");
const GURL kInMemoryUrl("chrome-guest://foo/");
switch (network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kSafeBrowsing:
NOTREACHED() << "Network context has no storage partition";
return nullptr;
case NetworkContextType::kProfile:
return content::BrowserContext::GetDefaultStoragePartition(
browser()->profile());
case NetworkContextType::kIncognitoProfile:
DCHECK(incognito_);
return content::BrowserContext::GetDefaultStoragePartition(
incognito_->profile());
case NetworkContextType::kOnDiskApp:
return content::BrowserContext::GetStoragePartitionForSite(
browser()->profile(), kOnDiskUrl);
case NetworkContextType::kInMemoryApp:
return content::BrowserContext::GetStoragePartitionForSite(
browser()->profile(), kInMemoryUrl);
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
DCHECK(incognito_);
return content::BrowserContext::GetStoragePartitionForSite(
incognito_->profile(), kOnDiskUrl);
}
NOTREACHED();
return nullptr;
}
network::mojom::URLLoaderFactory* loader_factory() {
return GetLoaderFactoryForContextType(GetParam().network_context_type);
}
network::mojom::URLLoaderFactory* GetLoaderFactoryForContextType(
NetworkContextType network_context_type) {
switch (network_context_type) {
case NetworkContextType::kSystem:
return g_browser_process->system_network_context_manager()
->GetURLLoaderFactory();
case NetworkContextType::kSafeBrowsing:
return g_browser_process->safe_browsing_service()
->GetURLLoaderFactory()
.get();
case NetworkContextType::kProfile:
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kOnDiskApp:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
return GetStoragePartitionForContextType(network_context_type)
->GetURLLoaderFactoryForBrowserProcess()
.get();
}
NOTREACHED();
return nullptr;
}
network::mojom::NetworkContext* network_context() {
return GetNetworkContextForContextType(GetParam().network_context_type);
}
network::mojom::NetworkContext* GetNetworkContextForContextType(
NetworkContextType network_context_type) {
switch (network_context_type) {
case NetworkContextType::kSystem:
return g_browser_process->system_network_context_manager()
->GetContext();
case NetworkContextType::kSafeBrowsing:
return g_browser_process->safe_browsing_service()->GetNetworkContext();
case NetworkContextType::kProfile:
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kOnDiskApp:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
return GetStoragePartitionForContextType(network_context_type)
->GetNetworkContext();
}
NOTREACHED();
return nullptr;
}
StorageType GetHttpCacheType() const {
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kSafeBrowsing:
return StorageType::kNone;
case NetworkContextType::kProfile:
case NetworkContextType::kOnDiskApp:
return StorageType::kDisk;
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
return StorageType::kMemory;
}
NOTREACHED();
return StorageType::kNone;
}
StorageType GetCookieStorageType() const {
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
return StorageType::kMemory;
case NetworkContextType::kSafeBrowsing:
case NetworkContextType::kProfile:
case NetworkContextType::kOnDiskApp:
return StorageType::kDisk;
}
NOTREACHED();
return StorageType::kNone;
}
// Returns the pref service with most prefs related to the NetworkContext
// being tested.
PrefService* GetPrefService() {
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kSafeBrowsing:
return g_browser_process->local_state();
case NetworkContextType::kProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskApp:
return browser()->profile()->GetPrefs();
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
// Incognito actually uses the non-incognito prefs, so this should end
// up being the same pref store as in the KProfile case.
return browser()->profile()->GetOffTheRecordProfile()->GetPrefs();
}
}
// Sets the proxy preference on a PrefService based on the NetworkContextType,
// and waits for it to be applied.
void SetProxyPref(const net::HostPortPair& host_port_pair) {
GetPrefService()->Set(proxy_config::prefs::kProxy,
ProxyConfigDictionary::CreateFixedServers(
host_port_pair.ToString(), std::string()));
// Wait for the new ProxyConfig to be passed over the pipe. Needed because
// Mojo doesn't guarantee ordering of events on different Mojo pipes, and
// requests are sent on a separate pipe from ProxyConfigs.
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kSafeBrowsing:
g_browser_process->system_network_context_manager()
->FlushProxyConfigMonitorForTesting();
break;
case NetworkContextType::kProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskApp:
ProfileNetworkContextServiceFactory::GetForContext(browser()->profile())
->FlushProxyConfigMonitorForTesting();
break;
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
ProfileNetworkContextServiceFactory::GetForContext(
browser()->profile()->GetOffTheRecordProfile())
->FlushProxyConfigMonitorForTesting();
break;
}
}
// Sends a request and expects it to be handled by embedded_test_server()
// acting as a proxy;
void TestProxyConfigured(bool expect_success) {
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the test server because of the proxy.
request->url = GURL("http://does.not.resolve.test:1872/echo");
content::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();
if (expect_success) {
EXPECT_EQ(net::OK, simple_loader->NetError());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ(*simple_loader_helper.response_body(), "Echo");
} else {
EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, simple_loader->NetError());
ASSERT_FALSE(simple_loader_helper.response_body());
}
}
// Makes a request that hangs, and will live until browser shutdown.
void MakeLongLivedRequestThatHangsUntilShutdown() {
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL(kControllablePath);
live_during_shutdown_simple_loader_ = network::SimpleURLLoader::Create(
std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS);
live_during_shutdown_simple_loader_helper_ =
std::make_unique<content::SimpleURLLoaderTestHelper>();
live_during_shutdown_simple_loader_
->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory(),
live_during_shutdown_simple_loader_helper_->GetCallback());
// Don't actually care about controlling the response, just need to wait
// until it sees the request, to make sure that a URLRequest has been
// created to potentially leak. Since the |controllable_http_response_| is
// not used to send a response to the request, the request just hangs until
// the NetworkContext is destroyed (Or the test server is shut down, but the
// NetworkContext should be destroyed before that happens, in this test).
controllable_http_response_->WaitForRequest();
}
// Sends a request to the test server's echoheader URL and sets
// |header_value_out| to the value of the specified response header. Returns
// false if the request fails. If non-null, uses |request| to make the
// request, after setting its |url| value.
bool FetchHeaderEcho(const std::string& header_name,
std::string* header_value_out,
std::unique_ptr<network::ResourceRequest> request =
nullptr) WARN_UNUSED_RESULT {
if (!request)
request = std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL(
base::StrCat({"/echoheader?", header_name}));
content::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();
if (simple_loader_helper.response_body()) {
*header_value_out = *simple_loader_helper.response_body();
return true;
}
return false;
}
void SetCookie(CookieType cookie_type,
CookiePersistenceType cookie_expiration_type) {
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
std::string cookie_line = "cookie";
if (cookie_expiration_type == CookiePersistenceType::kPersistent)
cookie_line += ";max-age=3600";
request->url = embedded_test_server()->GetURL("/set-cookie?" + cookie_line);
if (cookie_type == CookieType::kThirdParty)
request->site_for_cookies = GURL("http://example.com");
else
request->site_for_cookies = embedded_test_server()->base_url();
content::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();
EXPECT_EQ(net::OK, simple_loader->NetError());
}
void FlushNetworkInterface() {
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
g_browser_process->system_network_context_manager()
->FlushNetworkInterfaceForTesting();
break;
case NetworkContextType::kSafeBrowsing:
g_browser_process->safe_browsing_service()
->FlushNetworkInterfaceForTesting();
break;
case NetworkContextType::kProfile:
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskApp:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
GetStoragePartition()->FlushNetworkInterfaceForTesting();
break;
}
}
Profile* GetProfile() {
switch (GetParam().network_context_type) {
case NetworkContextType::kSystem:
case NetworkContextType::kSafeBrowsing:
case NetworkContextType::kProfile:
case NetworkContextType::kInMemoryApp:
case NetworkContextType::kOnDiskApp:
return browser()->profile();
case NetworkContextType::kIncognitoProfile:
case NetworkContextType::kOnDiskAppWithIncognitoProfile:
DCHECK(incognito_);
return incognito_->profile();
}
}
// Gets all cookies for given URL, as a single string.
std::string GetCookies(const GURL& url) {
return GetCookiesForContextType(GetParam().network_context_type, url);
}
std::string GetCookiesForContextType(NetworkContextType network_context_type,
const GURL& url) {
std::string cookies;
base::RunLoop run_loop;
network::mojom::CookieManagerPtr cookie_manager;
GetNetworkContextForContextType(network_context_type)
->GetCookieManager(mojo::MakeRequest(&cookie_manager));
cookie_manager->GetCookieList(
url, net::CookieOptions(),
base::BindOnce(
[](std::string* cookies_out, base::RunLoop* run_loop,
const std::vector<net::CanonicalCookie>& cookies) {
*cookies_out = net::CanonicalCookie::BuildCookieLine(cookies);
run_loop->Quit();
},
&cookies, &run_loop));
run_loop.Run();
return cookies;
}
void ForEachOtherContext(
base::RepeatingCallback<void(NetworkContextType network_context_type)>
callback) {
// Create Incognito Profile if needed.
if (!incognito_)
incognito_ = CreateIncognitoBrowser();
// True if the |network_context_type| corresponding to GetParam() has been
// found. Used to verify that kNetworkContextTypes is kept up to date, and
// contains no duplicates.
bool found_matching_type = false;
for (const auto network_context_type : kNetworkContextTypes) {
if (network_context_type == GetParam().network_context_type) {
EXPECT_FALSE(found_matching_type);
found_matching_type = true;
continue;
}
callback.Run(network_context_type);
}
EXPECT_TRUE(found_matching_type);
}
bool IsRestartStateWithInProcessNetworkService() {
return GetParam().network_service_state ==
NetworkServiceState::kRestarted &&
content::IsNetworkServiceRunningInProcess();
}
private:
void SimulateNetworkServiceCrashIfNecessary() {
if (GetParam().network_service_state != NetworkServiceState::kRestarted ||
content::IsNetworkServiceRunningInProcess()) {
return;
}
// Make sure |network_context()| is working as expected. Use '/echoheader'
// instead of '/echo' to avoid a disk_cache bug.
// See https://crbug.com/792255.
int net_error = content::LoadBasicRequest(
network_context(), embedded_test_server()->GetURL("/echoheader"), 0, 0,
net::LOAD_BYPASS_PROXY);
EXPECT_THAT(net_error, net::test::IsOk());
// Crash the NetworkService process. Existing interfaces should receive
// error notifications at some point.
SimulateNetworkServiceCrash();
// Flush the interface to make sure the error notification was received.
FlushNetworkInterface();
}
Browser* incognito_ = nullptr;
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<net::test_server::ControllableHttpResponse>
controllable_http_response_;
// Used in tests that need a live request during browser shutdown.
std::unique_ptr<network::SimpleURLLoader> live_during_shutdown_simple_loader_;
std::unique_ptr<content::SimpleURLLoaderTestHelper>
live_during_shutdown_simple_loader_helper_;
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationBrowserTest);
};
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
SecureCookiesAllowedForChromeScheme) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Cookies are only allowed for chrome:// schemes requesting a secure origin,
// so create an HTTPS server.
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::test_server::RegisterDefaultHandlers(&https_server);
ASSERT_TRUE(https_server.Start());
if (GetPrefService()->FindPreference(prefs::kBlockThirdPartyCookies))
GetPrefService()->SetBoolean(prefs::kBlockThirdPartyCookies, true);
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent);
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = https_server.GetURL("/echoheader?Cookie");
request->site_for_cookies = GURL(chrome::kChromeUIPrintURL);
content::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();
EXPECT_EQ(200, simple_loader->ResponseInfo()->headers->response_code());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ("cookie", *simple_loader_helper.response_body());
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
std::unique_ptr<net::test_server::HttpResponse> EchoCookieHeader(
const net::test_server::HttpRequest& request) {
auto response = std::make_unique<net::test_server::BasicHttpResponse>();
auto it = request.headers.find("Cookie");
if (it != request.headers.end())
response->set_content(it->second);
response->AddCustomHeader("Access-Control-Allow-Origin", "*");
return response;
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ThirdPartyCookiesAllowedForExtensions) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Loading an extension only makes sense for profile contexts.
if (GetParam().network_context_type != NetworkContextType::kProfile &&
GetParam().network_context_type !=
NetworkContextType::kIncognitoProfile) {
return;
}
net::EmbeddedTestServer test_server;
net::test_server::RegisterDefaultHandlers(&test_server);
test_server.RegisterRequestHandler(base::BindRepeating(&EchoCookieHeader));
ASSERT_TRUE(test_server.Start());
GetPrefService()->SetBoolean(prefs::kBlockThirdPartyCookies, true);
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent);
extensions::TestExtensionDir extension_dir;
extension_dir.WriteManifest(R"({
"name": "Cookie Test",
"manifest_version": 2,
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"incognito": "split",
"permissions": ["<all_urls>"]
})");
extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
extensions::ChromeTestExtensionLoader loader(GetProfile());
loader.set_allow_incognito_access(true);
scoped_refptr<const extensions::Extension> extension =
loader.LoadExtension(extension_dir.UnpackedPath());
ASSERT_TRUE(extension);
GURL url = test_server.GetURL("/echocookieheader");
std::string script = R"((url => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = () => domAutomationController.send(xhr.responseText);
xhr.send();
}))";
std::string result =
extensions::browsertest_util::ExecuteScriptInBackgroundPage(
GetProfile(), extension->id(), script + "('" + url.spec() + "')");
EXPECT_EQ("cookie", result);
}
#endif
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, BasicRequest) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL("/echo");
content::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->ResponseInfo());
ASSERT_TRUE(simple_loader->ResponseInfo()->headers);
EXPECT_EQ(200, simple_loader->ResponseInfo()->headers->response_code());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ("Echo", *simple_loader_helper.response_body());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, DataURL) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = GURL("data:text/plain,foo");
content::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->ResponseInfo());
// Data URLs don't have headers.
EXPECT_FALSE(simple_loader->ResponseInfo()->headers);
EXPECT_EQ("text/plain", simple_loader->ResponseInfo()->mime_type);
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ("foo", *simple_loader_helper.response_body());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, FileURL) {
if (IsRestartStateWithInProcessNetworkService())
return;
// File URLs require a FileURLFactory that is not present in the default
// URLLoaderFactories.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
base::ScopedAllowBlockingForTesting allow_blocking;
base::ScopedTempDir temp_dir_;
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath file_path;
ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
const char kFileContents[] = "This file intentionally left empty.";
ASSERT_EQ(static_cast<int>(strlen(kFileContents)),
base::WriteFile(file_path, kFileContents, strlen(kFileContents)));
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = net::FilePathToFileURL(file_path);
content::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->ResponseInfo());
// File URLs don't have headers.
EXPECT_FALSE(simple_loader->ResponseInfo()->headers);
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ(kFileContents, *simple_loader_helper.response_body());
}
// Make sure a cache is used when expected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, Cache) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Crashing the network service may corrupt the disk cache, so skip this test
// in tests that crash the network service and use an on-disk cache.
if (GetParam().network_service_state == NetworkServiceState::kRestarted &&
GetHttpCacheType() == StorageType::kDisk) {
return;
}
// Make a request whose response should be cached.
GURL request_url = embedded_test_server()->GetURL("/cachetime");
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = request_url;
content::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());
EXPECT_GT(simple_loader_helper.response_body()->size(), 0u);
// Stop the server.
ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
// Make the request again, and make sure it's cached or not, according to
// expectations. Reuse the content::ResourceRequest, but nothing else.
std::unique_ptr<network::ResourceRequest> request2 =
std::make_unique<network::ResourceRequest>();
request2->url = request_url;
content::SimpleURLLoaderTestHelper simple_loader_helper2;
std::unique_ptr<network::SimpleURLLoader> simple_loader2 =
network::SimpleURLLoader::Create(std::move(request2),
TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader2->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory(), simple_loader_helper2.GetCallback());
simple_loader_helper2.WaitForCallback();
if (GetHttpCacheType() == StorageType::kNone) {
// If there's no cache, and no server running, the request should have
// failed.
EXPECT_FALSE(simple_loader_helper2.response_body());
EXPECT_EQ(net::ERR_CONNECTION_REFUSED, simple_loader2->NetError());
} else {
// Otherwise, the request should have succeeded, and returned the same
// result as before.
ASSERT_TRUE(simple_loader_helper2.response_body());
EXPECT_EQ(*simple_loader_helper.response_body(),
*simple_loader_helper2.response_body());
}
}
// Make sure that NetworkContexts can't access each other's disk caches.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, CacheIsolation) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Make a request whose response should be cached.
GURL request_url = embedded_test_server()->GetURL("/cachetime");
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = request_url;
content::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());
EXPECT_GT(simple_loader_helper.response_body()->size(), 0u);
// Stop the server.
ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
// Make the request again, for each other network context, and make sure the
// response is not cached.
ForEachOtherContext(
base::BindLambdaForTesting([&](NetworkContextType network_context_type) {
std::unique_ptr<network::ResourceRequest> request2 =
std::make_unique<network::ResourceRequest>();
request2->url = request_url;
content::SimpleURLLoaderTestHelper simple_loader_helper2;
std::unique_ptr<network::SimpleURLLoader> simple_loader2 =
network::SimpleURLLoader::Create(std::move(request2),
TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader2->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
GetLoaderFactoryForContextType(network_context_type),
simple_loader_helper2.GetCallback());
simple_loader_helper2.WaitForCallback();
EXPECT_FALSE(simple_loader_helper2.response_body());
EXPECT_EQ(net::ERR_CONNECTION_REFUSED, simple_loader2->NetError());
}));
}
// Make sure an on-disk cache is used when expected. PRE_DiskCache populates the
// cache. DiskCache then makes sure the cache entry is still there (Or not) as
// expected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, PRE_DiskCache) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Save test URL to disk, so it can be used in the next test (Test server uses
// a random port, so need to know the port to try and retrieve it from the
// cache in the next test). The profile directory is preserved between the
// PRE_DiskCache and DiskCache run, so can just keep a file there.
GURL test_url = embedded_test_server()->GetURL(kCacheRandomPath);
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath save_url_file_path = browser()->profile()->GetPath().Append(
FILE_PATH_LITERAL("url_for_test.txt"));
// Make a request whose response should be cached.
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = test_url;
content::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();
EXPECT_EQ(net::OK, simple_loader->NetError());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_FALSE(simple_loader_helper.response_body()->empty());
// Write the URL and expected response to a file.
std::string file_data =
test_url.spec() + "\n" + *simple_loader_helper.response_body();
ASSERT_EQ(
static_cast<int>(file_data.length()),
base::WriteFile(save_url_file_path, file_data.data(), file_data.size()));
EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
}
// Check if the URL loaded in PRE_DiskCache is still in the cache, across a
// browser restart.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, DiskCache) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Crashing the network service may corrupt the disk cache, so skip this phase
// in tests that crash the network service and use an on-disk cache.
if (GetParam().network_service_state == NetworkServiceState::kRestarted &&
GetHttpCacheType() == StorageType::kDisk) {
return;
}
// Load URL from the above test body to disk.
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath save_url_file_path = browser()->profile()->GetPath().Append(
FILE_PATH_LITERAL("url_for_test.txt"));
std::string file_data;
ASSERT_TRUE(ReadFileToString(save_url_file_path, &file_data));
size_t newline_pos = file_data.find('\n');
ASSERT_NE(newline_pos, std::string::npos);
GURL test_url = GURL(file_data.substr(0, newline_pos));
ASSERT_TRUE(test_url.is_valid()) << test_url.possibly_invalid_spec();
std::string original_response = file_data.substr(newline_pos + 1);
// Request the same test URL as may have been cached by PRE_DiskCache.
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = test_url;
content::SimpleURLLoaderTestHelper simple_loader_helper;
request->load_flags = net::LOAD_ONLY_FROM_CACHE;
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();
// The request should only succeed if there is an on-disk cache.
if (GetHttpCacheType() != StorageType::kDisk) {
EXPECT_FALSE(simple_loader_helper.response_body());
} else {
DCHECK_NE(GetParam().network_service_state,
NetworkServiceState::kRestarted);
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ(original_response, *simple_loader_helper.response_body());
}
}
// Visits a URL with an HSTS header, and makes sure it is respected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, PRE_Hsts) {
if (IsRestartStateWithInProcessNetworkService())
return;
net::test_server::EmbeddedTestServer ssl_server(
net::test_server::EmbeddedTestServer::TYPE_HTTPS);
ssl_server.SetSSLConfig(
net::test_server::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
ssl_server.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
ASSERT_TRUE(ssl_server.Start());
// Make a request whose response has an STS header.
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = ssl_server.GetURL(
"/set-header?Strict-Transport-Security: max-age%3D600000");
content::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();
EXPECT_EQ(net::OK, simple_loader->NetError());
ASSERT_TRUE(simple_loader->ResponseInfo()->headers);
EXPECT_TRUE(simple_loader->ResponseInfo()->headers->HasHeaderValue(
"Strict-Transport-Security", "max-age=600000"));
// Make a cache-only request to make sure the HSTS entry is respected. Using a
// cache-only request both prevents the result from being cached, and makes
// the check identical to the one in the next test, which is run after the
// test server has been shut down.
GURL exected_ssl_url = ssl_server.base_url();
GURL::Replacements replacements;
replacements.SetSchemeStr("http");
GURL start_url = exected_ssl_url.ReplaceComponents(replacements);
request = std::make_unique<network::ResourceRequest>();
request->url = start_url;
request->load_flags = net::LOAD_ONLY_FROM_CACHE;
content::SimpleURLLoaderTestHelper simple_loader_helper2;
simple_loader = network::SimpleURLLoader::Create(
std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory(), simple_loader_helper2.GetCallback());
simple_loader_helper2.WaitForCallback();
EXPECT_FALSE(simple_loader_helper2.response_body());
EXPECT_EQ(exected_ssl_url, simple_loader->GetFinalURL());
// Write the URL with HSTS information to a file, so it can be loaded in the
// next test. Have to use a file for this, since the server's port is random.
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath save_url_file_path = browser()->profile()->GetPath().Append(
FILE_PATH_LITERAL("url_for_test.txt"));
std::string file_data = start_url.spec();
ASSERT_EQ(
static_cast<int>(file_data.length()),
base::WriteFile(save_url_file_path, file_data.data(), file_data.size()));
}
// Checks if the HSTS information from the last test is still available after a
// restart.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, Hsts) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The network service must be cleanly shut down to guarantee HSTS information
// is flushed to disk, but that currently generally doesn't happen. See
// https://crbug.com/820996.
if (GetParam().network_service_state != NetworkServiceState::kDisabled &&
GetHttpCacheType() == StorageType::kDisk) {
return;
}
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath save_url_file_path = browser()->profile()->GetPath().Append(
FILE_PATH_LITERAL("url_for_test.txt"));
std::string file_data;
ASSERT_TRUE(ReadFileToString(save_url_file_path, &file_data));
GURL start_url = GURL(file_data);
// Unfortunately, loading HSTS information is loaded asynchronously from
// disk, so there's no way to guarantee it has loaded by the time a
// request is made. As a result, may have to try multiple times to verify that
// cached HSTS information has been loaded, when it's stored on disk.
while (true) {
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = start_url;
request->load_flags = net::LOAD_ONLY_FROM_CACHE;
content::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();
EXPECT_FALSE(simple_loader_helper.response_body());
// HSTS information is currently stored on disk if-and-only-if there's an
// on-disk HTTP cache.
if (GetHttpCacheType() == StorageType::kDisk) {
GURL::Replacements replacements;
replacements.SetSchemeStr("https");
GURL expected_https_url = start_url.ReplaceComponents(replacements);
// The file may not have been loaded yet, so if the cached HSTS
// information was not respected, try again.
if (expected_https_url != simple_loader->GetFinalURL())
continue;
EXPECT_EQ(expected_https_url, simple_loader->GetFinalURL());
break;
} else {
EXPECT_EQ(start_url, simple_loader->GetFinalURL());
break;
}
}
}
// Check that the SSLConfig is hooked up. PRE_SSLConfig checks that changing
// local_state() after start modifies the SSLConfig, SSLConfig makes sure the
// (now modified) initial value of local_state() is respected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, PRE_SSLConfig) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Start a TLS 1.0 server.
net::EmbeddedTestServer ssl_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1;
ssl_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1;
ssl_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
ssl_server.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
ASSERT_TRUE(ssl_server.Start());
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = ssl_server.GetURL("/echo");
content::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());
EXPECT_EQ(*simple_loader_helper.response_body(), "Echo");
// Disallow TLS 1.0 via prefs.
g_browser_process->local_state()->SetString(prefs::kSSLVersionMin,
switches::kSSLVersionTLSv11);
// Flush the changes to the network process, to avoid a race between updating
// the config and the next request.
g_browser_process->system_network_context_manager()
->FlushSSLConfigManagerForTesting();
// With the new prefs, requests to the server should be blocked.
request = std::make_unique<network::ResourceRequest>();
request->url = ssl_server.GetURL("/echo");
content::SimpleURLLoaderTestHelper simple_loader_helper2;
simple_loader = network::SimpleURLLoader::Create(
std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS);
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory(), simple_loader_helper2.GetCallback());
simple_loader_helper2.WaitForCallback();
EXPECT_FALSE(simple_loader_helper2.response_body());
EXPECT_EQ(net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH, simple_loader->NetError());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, SSLConfig) {
if (IsRestartStateWithInProcessNetworkService())
return;
// Start a TLS 1.0 server.
net::EmbeddedTestServer ssl_server(net::EmbeddedTestServer::TYPE_HTTPS);
net::SSLServerConfig ssl_config;
ssl_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1;
ssl_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1;
ssl_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
ASSERT_TRUE(ssl_server.Start());
// Making a request should fail, since PRE_SSLConfig saved a pref to disallow
// TLS 1.0.
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = ssl_server.GetURL("/echo");
content::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();
EXPECT_FALSE(simple_loader_helper.response_body());
EXPECT_EQ(net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH, simple_loader->NetError());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, ProxyConfig) {
if (IsRestartStateWithInProcessNetworkService())
return;
SetProxyPref(embedded_test_server()->host_port_pair());
TestProxyConfigured(/*expect_success=*/true);
}
// This test should not end in an AssertNoURLLRequests CHECK.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ShutdownWithLiveRequest) {
if (IsRestartStateWithInProcessNetworkService())
return;
MakeLongLivedRequestThatHangsUntilShutdown();
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
UserAgentAndLanguagePrefs) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The system and SafeBrowsing network contexts aren't associated with any
// profile, so changing the language settings for the profile's main network
// context won't affect what they send.
bool system =
(GetParam().network_context_type == NetworkContextType::kSystem ||
GetParam().network_context_type == NetworkContextType::kSafeBrowsing);
// echoheader returns "None" when the header isn't there in the first place.
const char kNoAcceptLanguage[] = "None";
std::string accept_language, user_agent;
// Check default.
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language));
EXPECT_EQ(system ? kNoAcceptLanguage : "en-US,en;q=0.9", accept_language);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent));
EXPECT_EQ(::GetUserAgent(), user_agent);
// Now change the profile a different language, and see if the headers
// get updated.
browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages, "uk");
FlushNetworkInterface();
std::string accept_language2, user_agent2;
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language2));
EXPECT_EQ(system ? kNoAcceptLanguage : "uk", accept_language2);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent2));
EXPECT_EQ(::GetUserAgent(), user_agent2);
// Try a more complicated one, with multiple languages.
browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages,
"uk, en_US");
FlushNetworkInterface();
std::string accept_language3, user_agent3;
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language3));
EXPECT_EQ(system ? kNoAcceptLanguage : "uk,en_US;q=0.9", accept_language3);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent3));
EXPECT_EQ(::GetUserAgent(), user_agent3);
}
// First part of testing enable referrers. Check that referrers are enabled by
// default at browser start, and referrers are indeed sent. Then disable
// referrers, and make sure that they aren't set.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
PRE_EnableReferrers) {
if (IsRestartStateWithInProcessNetworkService())
return;
const GURL kReferrer("http://referrer/");
// Referrers should be enabled by default.
EXPECT_TRUE(GetPrefService()->GetBoolean(prefs::kEnableReferrers));
// Send a request, make sure the referrer is sent.
std::string referrer;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->referrer = kReferrer;
ASSERT_TRUE(FetchHeaderEcho("referer", &referrer, std::move(request)));
// SafeBrowsing never sends the referrer when then network service is enabled,
// since it doesn't need to. When the network service is disabled, it matches
// the behavior of the system NetworkContext, since it shares internals.
if (GetParam().network_context_type == NetworkContextType::kSafeBrowsing &&
base::FeatureList::IsEnabled(network::features::kNetworkService)) {
EXPECT_EQ("None", referrer);
} else {
EXPECT_EQ(kReferrer.spec(), referrer);
}
// Disable referrers, and flush the NetworkContext mojo interface it's set on,
// to avoid any races with the URLLoaderFactory pipe.
GetPrefService()->SetBoolean(prefs::kEnableReferrers, false);
FlushNetworkInterface();
// Send a request and make sure its referer is not sent.
std::string referrer2;
std::unique_ptr<network::ResourceRequest> request2 =
std::make_unique<network::ResourceRequest>();
request2->referrer = kReferrer;
ASSERT_TRUE(FetchHeaderEcho("referer", &referrer2, std::move(request2)));
EXPECT_EQ("None", referrer2);
}
// Second part of enable referrer test. Referrer should still be disabled. Make
// sure that disable referrers option is respected after startup, as to just
// after changing it.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
EnableReferrers) {
if (IsRestartStateWithInProcessNetworkService())
return;
const GURL kReferrer("http://referrer/");
// The preference is expected to be reset in incognito mode.
if (is_incognito()) {
EXPECT_TRUE(GetPrefService()->GetBoolean(prefs::kEnableReferrers));
return;
}
// Referrers should still be disabled.
EXPECT_FALSE(GetPrefService()->GetBoolean(prefs::kEnableReferrers));
// Send a request and make sure its referer is not sent.
std::string referrer;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->referrer = kReferrer;
ASSERT_TRUE(FetchHeaderEcho("referer", &referrer, std::move(request)));
EXPECT_EQ("None", referrer);
}
// Make sure that sending referrers that violate the referrer policy results in
// errors.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
PolicyViolatingReferrers) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = embedded_test_server()->GetURL("/echoheader?Referer");
request->referrer = GURL("http://referrer/");
request->referrer_policy = net::URLRequest::NO_REFERRER;
content::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();
if (GetParam().network_context_type == NetworkContextType::kSafeBrowsing &&
base::FeatureList::IsEnabled(network::features::kNetworkService)) {
// Safebrowsing ignores referrers, when the network service is enabled, so
// the requests succeed.
EXPECT_EQ(net::OK, simple_loader->NetError());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ("None", *simple_loader_helper.response_body());
} else {
// In all other cases, the invalid referrer causes the request to fail.
EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT, simple_loader->NetError());
}
}
// Makes sure cookies are enabled by default, and saved to disk / not saved to
// disk as expected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
PRE_CookiesEnabled) {
if (IsRestartStateWithInProcessNetworkService())
return;
EXPECT_TRUE(GetCookies(embedded_test_server()->base_url()).empty());
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent);
EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, CookiesEnabled) {
if (IsRestartStateWithInProcessNetworkService())
return;
#if defined(OS_MACOSX)
// TODO(https://crbug.com/880496): Fix and reenable test.
if (base::mac::IsOS10_11())
return;
#endif
// Check that the cookie from the first stage of the test was / was not
// preserved between browser restarts, as expected.
bool has_cookies = !GetCookies(embedded_test_server()->base_url()).empty();
EXPECT_EQ(GetCookieStorageType() == StorageType::kDisk, has_cookies);
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
CookieIsolation) {
if (IsRestartStateWithInProcessNetworkService())
return;
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent);
EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty());
ForEachOtherContext(
base::BindLambdaForTesting([&](NetworkContextType network_context_type) {
EXPECT_TRUE(GetCookiesForContextType(network_context_type,
embedded_test_server()->base_url())
.empty());
}));
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
PRE_ThirdPartyCookiesBlocked) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The system and SafeBrowsing network contexts don't support the third party
// cookie blocking options, since they have no notion of third parties.
bool system =
GetParam().network_context_type == NetworkContextType::kSystem ||
GetParam().network_context_type == NetworkContextType::kSafeBrowsing;
if (system)
return;
GetPrefService()->SetBoolean(prefs::kBlockThirdPartyCookies, true);
SetCookie(CookieType::kThirdParty, CookiePersistenceType::kSession);
EXPECT_TRUE(GetCookies(embedded_test_server()->base_url()).empty());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ThirdPartyCookiesBlocked) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The system and SafeBrowsing network contexts don't support the third party
// cookie blocking options, since they have no notion of third parties.
bool system =
GetParam().network_context_type == NetworkContextType::kSystem ||
GetParam().network_context_type == NetworkContextType::kSafeBrowsing;
if (system)
return;
// The preference is expected to be reset in incognito mode.
if (is_incognito()) {
EXPECT_FALSE(GetPrefService()->GetBoolean(prefs::kBlockThirdPartyCookies));
return;
}
// The kBlockThirdPartyCookies pref should carry over to the next session.
EXPECT_TRUE(GetPrefService()->GetBoolean(prefs::kBlockThirdPartyCookies));
SetCookie(CookieType::kThirdParty, CookiePersistenceType::kSession);
EXPECT_TRUE(GetCookies(embedded_test_server()->base_url()).empty());
// Set pref to false, third party cookies should be allowed now.
GetPrefService()->SetBoolean(prefs::kBlockThirdPartyCookies, false);
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kSession);
EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
PRE_CookieSettings) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The system and SafeBrowsing network contexts don't respect cookie blocking
// options, which are per-profile.
bool system =
GetParam().network_context_type == NetworkContextType::kSystem ||
GetParam().network_context_type == NetworkContextType::kSafeBrowsing;
if (system)
return;
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
FlushNetworkInterface();
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kSession);
EXPECT_TRUE(GetCookies(embedded_test_server()->base_url()).empty());
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, CookieSettings) {
if (IsRestartStateWithInProcessNetworkService())
return;
// The system and SafeBrowsing network contexts don't respect cookie blocking
// options, which are per-profile.
bool system =
GetParam().network_context_type == NetworkContextType::kSystem ||
GetParam().network_context_type == NetworkContextType::kSafeBrowsing;
if (system)
return;
// The content settings should carry over to the next session.
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kSession);
EXPECT_TRUE(GetCookies(embedded_test_server()->base_url()).empty());
// Set default setting to allow, cookies should be set now.
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_ALLOW);
FlushNetworkInterface();
SetCookie(CookieType::kFirstParty, CookiePersistenceType::kSession);
EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty());
}
// Make sure file uploads work.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, UploadFile) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->method = "POST";
request->url = embedded_test_server()->GetURL("/echo");
content::SimpleURLLoaderTestHelper simple_loader_helper;
std::unique_ptr<network::SimpleURLLoader> simple_loader =
network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::FilePath dir_test_data;
base::PathService::Get(chrome::DIR_TEST_DATA, &dir_test_data);
base::FilePath path =
dir_test_data.Append(base::FilePath(FILE_PATH_LITERAL("simple.html")));
simple_loader->AttachFileForUpload(path, "text/html");
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
loader_factory(), simple_loader_helper.GetCallback());
simple_loader_helper.WaitForCallback();
ASSERT_TRUE(simple_loader->ResponseInfo());
ASSERT_TRUE(simple_loader->ResponseInfo()->headers);
EXPECT_EQ(200, simple_loader->ResponseInfo()->headers->response_code());
ASSERT_TRUE(simple_loader_helper.response_body());
base::ScopedAllowBlockingForTesting allow_blocking;
std::string expected_response;
base::ReadFileToString(path, &expected_response);
EXPECT_EQ(expected_response.c_str(), *simple_loader_helper.response_body());
}
class NetworkContextConfigurationFixedPortBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationFixedPortBrowserTest() {}
~NetworkContextConfigurationFixedPortBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(
switches::kTestingFixedHttpPort,
base::StringPrintf("%u", embedded_test_server()->port()));
LOG(WARNING) << base::StringPrintf("%u", embedded_test_server()->port());
}
};
// Test that the command line switch makes it to the network service and is
// respected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFixedPortBrowserTest,
TestingFixedPort) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL does not use the port the embedded test server is using. The
// command line switch should make it result in the request being directed to
// the test server anyways.
request->url = GURL("http://127.0.0.1/echo");
content::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();
EXPECT_EQ(net::OK, simple_loader->NetError());
ASSERT_TRUE(simple_loader_helper.response_body());
EXPECT_EQ(*simple_loader_helper.response_body(), "Echo");
}
class NetworkContextConfigurationProxyOnStartBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationProxyOnStartBrowserTest() {}
~NetworkContextConfigurationProxyOnStartBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(
switches::kProxyServer,
embedded_test_server()->host_port_pair().ToString());
}
private:
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationProxyOnStartBrowserTest);
};
// Test that when there's a proxy configuration at startup, the initial requests
// use that configuration.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationProxyOnStartBrowserTest,
TestInitialProxyConfig) {
if (IsRestartStateWithInProcessNetworkService())
return;
TestProxyConfigured(/*expect_success=*/true);
}
// Make sure the system URLRequestContext can handle fetching PAC scripts from
// http URLs.
class NetworkContextConfigurationHttpPacBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationHttpPacBrowserTest()
: pac_test_server_(net::test_server::EmbeddedTestServer::TYPE_HTTP) {}
~NetworkContextConfigurationHttpPacBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
pac_test_server_.RegisterRequestHandler(base::Bind(
&NetworkContextConfigurationHttpPacBrowserTest::HandlePacRequest,
GetPacScript()));
EXPECT_TRUE(pac_test_server_.Start());
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
pac_test_server_.base_url().spec().c_str());
}
static std::unique_ptr<net::test_server::HttpResponse> HandlePacRequest(
const std::string& pac_script,
const net::test_server::HttpRequest& request) {
std::unique_ptr<net::test_server::BasicHttpResponse> response =
std::make_unique<net::test_server::BasicHttpResponse>();
response->set_content(pac_script);
return response;
}
private:
net::test_server::EmbeddedTestServer pac_test_server_;
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationHttpPacBrowserTest);
};
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpPacBrowserTest, HttpPac) {
if (IsRestartStateWithInProcessNetworkService())
return;
TestProxyConfigured(/*expect_success=*/true);
}
// Make sure the system URLRequestContext can handle fetching PAC scripts from
// file URLs.
class NetworkContextConfigurationFilePacBrowserTest
: public NetworkContextConfigurationBrowserTest,
public network::NetworkConnectionTracker::NetworkConnectionObserver {
public:
NetworkContextConfigurationFilePacBrowserTest() {}
~NetworkContextConfigurationFilePacBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
const char kPacFileName[] = "foo.pac";
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath pac_file_path =
temp_dir_.GetPath().AppendASCII(kPacFileName);
std::string pac_script = GetPacScript();
ASSERT_EQ(
static_cast<int>(pac_script.size()),
base::WriteFile(pac_file_path, pac_script.c_str(), pac_script.size()));
command_line->AppendSwitchASCII(
switches::kProxyPacUrl, net::FilePathToFileURL(pac_file_path).spec());
}
void SetUpOnMainThread() override {
NetworkContextConfigurationBrowserTest::SetUpOnMainThread();
// The network service will have just been killed if network_service_state
// is kRestarted. Make sure it knows about the correct network state before
// continuing.
network::NetworkConnectionTracker* tracker =
content::GetNetworkConnectionTracker();
auto connection_type = network::mojom::ConnectionType::CONNECTION_NONE;
run_loop_.reset(new base::RunLoop());
tracker->AddNetworkConnectionObserver(this);
while (!tracker->GetConnectionType(
&connection_type,
base::BindOnce(&NetworkContextConfigurationFilePacBrowserTest::
OnConnectionChanged,
base::Unretained(this))) ||
connection_type == network::mojom::ConnectionType::CONNECTION_NONE) {
run_loop_->Run();
run_loop_.reset(new base::RunLoop());
}
tracker->RemoveNetworkConnectionObserver(this);
}
// network::NetworkConnectionTracker::NetworkConnectionObserver
void OnConnectionChanged(network::mojom::ConnectionType type) override {
run_loop_->Quit();
}
private:
base::ScopedTempDir temp_dir_;
std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFilePacBrowserTest);
};
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFilePacBrowserTest, FilePac) {
if (IsRestartStateWithInProcessNetworkService())
return;
bool network_service_disabled =
!base::FeatureList::IsEnabled(network::features::kNetworkService);
// PAC file URLs are not supported with the network service
TestProxyConfigured(/*expect_success=*/network_service_disabled);
}
// Make sure the system URLRequestContext can handle fetching PAC scripts from
// data URLs.
class NetworkContextConfigurationDataPacBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationDataPacBrowserTest() {}
~NetworkContextConfigurationDataPacBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
std::string contents;
// Read in kPACScript contents.
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
"data:," + GetPacScript());
}
private:
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationDataPacBrowserTest);
};
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationDataPacBrowserTest, DataPac) {
if (IsRestartStateWithInProcessNetworkService())
return;
TestProxyConfigured(/*expect_success=*/true);
}
// Make sure the system URLRequestContext can handle fetching PAC scripts from
// ftp URLs. Unlike the other PAC tests, this test uses a PAC script that
// results in an error, since the spawned test server is designed so that it can
// run remotely (So can't just write a script to a local file and have the
// server serve it).
class NetworkContextConfigurationFtpPacBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationFtpPacBrowserTest()
: ftp_server_(net::SpawnedTestServer::TYPE_FTP,
base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {
EXPECT_TRUE(ftp_server_.Start());
}
~NetworkContextConfigurationFtpPacBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(
switches::kProxyPacUrl,
ftp_server_.GetURL("bad_server.pac").spec().c_str());
}
private:
net::SpawnedTestServer ftp_server_;
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFtpPacBrowserTest);
};
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFtpPacBrowserTest, FtpPac) {
if (IsRestartStateWithInProcessNetworkService())
return;
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the test server because of the proxy.
request->url = GURL("http://does.not.resolve.test:1872/echo");
content::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();
EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError());
}
// Used to test that PAC HTTPS URL stripping works. A different test server is
// used as the "proxy" based on whether the PAC script sees the full path or
// not. The servers aren't correctly set up to mimic HTTP proxies that tunnel
// to an HTTPS test server, so the test fixture just watches for any incoming
// connection.
class NetworkContextConfigurationHttpsStrippingPacBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationHttpsStrippingPacBrowserTest() {}
~NetworkContextConfigurationHttpsStrippingPacBrowserTest() override {}
void SetUpCommandLine(base::CommandLine* command_line) override {
// Test server HostPortPair, as a string.
std::string test_server_host_port_pair =
net::HostPortPair::FromURL(embedded_test_server()->base_url())
.ToString();
// Set up a PAC file that directs to different servers based on the URL it
// sees.
std::string pac_script = base::StringPrintf(
"function FindProxyForURL(url, host) {"
// With the test URL stripped of the path, try to use the embedded test
// server to establish a an SSL tunnel over an HTTP proxy. The request
// will fail with ERR_TUNNEL_CONNECTION_FAILED.
" if (url == 'https://does.not.resolve.test:1872/')"
" return 'PROXY %s';"
// With the full test URL, try to use a domain that does not resolve as
// a proxy. Errors connecting to the proxy result in
// ERR_PROXY_CONNECTION_FAILED.
" if (url == 'https://does.not.resolve.test:1872/foo')"
" return 'PROXY does.not.resolve.test';"
// Otherwise, use direct. If a connection to "does.not.resolve.test"
// tries to use a direction connection, it will fail with
// ERR_NAME_NOT_RESOLVED. This path will also
// be used by the initial request in NetworkServiceState::kRestarted
// tests to make sure the network service process is fully started
// before it's crashed and restarted. Using direct in this case avoids
// that request failing with an unexpeced error when being directed to a
// bogus proxy.
" return 'DIRECT';"
"}",
test_server_host_port_pair.c_str());
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
"data:," + pac_script);
}
};
// Start Chrome and check that PAC HTTPS path stripping is enabled.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpsStrippingPacBrowserTest,
PRE_PacHttpsUrlStripping) {
if (IsRestartStateWithInProcessNetworkService())
return;
ASSERT_FALSE(CreateDefaultNetworkContextParams()
->dangerously_allow_pac_access_to_secure_urls);
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the proxy that fails with
// ERR_TUNNEL_CONNECTION_FAILED.
request->url = GURL("https://does.not.resolve.test:1872/foo");
content::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();
EXPECT_FALSE(simple_loader_helper.response_body());
EXPECT_EQ(net::ERR_TUNNEL_CONNECTION_FAILED, simple_loader->NetError());
// Disable stripping paths from HTTPS PAC URLs for the next test.
g_browser_process->local_state()->SetBoolean(
prefs::kPacHttpsUrlStrippingEnabled, false);
// Check that the changed setting is reflected in the network context params.
// The changes aren't applied to existing URLRequestContexts, however, so have
// to restart to see the setting change respected.
EXPECT_TRUE(CreateDefaultNetworkContextParams()
->dangerously_allow_pac_access_to_secure_urls);
}
// Restart Chrome and check the case where PAC HTTPS path stripping is disabled.
// Have to restart Chrome because the setting is only checked on NetworkContext
// creation.
// Flaky. See https://crbug.com/840127.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationHttpsStrippingPacBrowserTest,
DISABLED_PacHttpsUrlStripping) {
if (IsRestartStateWithInProcessNetworkService())
return;
ASSERT_TRUE(CreateDefaultNetworkContextParams()
->dangerously_allow_pac_access_to_secure_urls);
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
// This URL should be directed to the proxy that fails with
// ERR_PROXY_CONNECTION_FAILED.
request->url = GURL("https://does.not.resolve.test:1872/foo");
content::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();
EXPECT_FALSE(simple_loader_helper.response_body());
EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError());
}
// Instiates tests with a prefix indicating which NetworkContext is being
// tested, and a suffix of "/0" if the network service is disabled, "/1" if it's
// enabled, and "/2" if it's enabled and restarted.
#if BUILDFLAG(ENABLE_EXTENSIONS)
#define INSTANTIATE_EXTENSION_TESTS(TestFixture) \
INSTANTIATE_TEST_CASE_P( \
OnDiskApp, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kOnDiskApp}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kOnDiskApp}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kOnDiskApp}))); \
\
INSTANTIATE_TEST_CASE_P( \
InMemoryApp, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kInMemoryApp}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kInMemoryApp}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kInMemoryApp}))); \
\
INSTANTIATE_TEST_CASE_P( \
OnDiskAppWithIncognitoProfile, TestFixture, \
::testing::Values( \
TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kOnDiskAppWithIncognitoProfile}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kOnDiskAppWithIncognitoProfile}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kOnDiskAppWithIncognitoProfile})));
#else // !BUILDFLAG(ENABLE_EXTENSIONS)
#define INSTANTIATE_EXTENSION_TESTS(TestFixture)
#endif // !BUILDFLAG(ENABLE_EXTENSIONS)
#define INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(TestFixture) \
INSTANTIATE_EXTENSION_TESTS(TestFixture) \
INSTANTIATE_TEST_CASE_P( \
SystemNetworkContext, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kSystem}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kSystem}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kSystem}))); \
\
INSTANTIATE_TEST_CASE_P( \
SafeBrowsingNetworkContext, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kSafeBrowsing}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kSafeBrowsing}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kSafeBrowsing}))); \
\
INSTANTIATE_TEST_CASE_P( \
ProfileMainNetworkContext, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kProfile}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kProfile}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kProfile}))); \
\
INSTANTIATE_TEST_CASE_P( \
IncognitoProfileMainNetworkContext, TestFixture, \
::testing::Values(TestCase({NetworkServiceState::kDisabled, \
NetworkContextType::kIncognitoProfile}), \
TestCase({NetworkServiceState::kEnabled, \
NetworkContextType::kIncognitoProfile}), \
TestCase({NetworkServiceState::kRestarted, \
NetworkContextType::kIncognitoProfile})));
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(NetworkContextConfigurationBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationFixedPortBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationProxyOnStartBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationHttpPacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationFilePacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationDataPacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationFtpPacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationHttpsStrippingPacBrowserTest);
} // namespace