Commit 0f3fc0e0 authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

NetworkService: Add configuration for data, file, and ftp schemes.

Bug: 715695
Change-Id: I093262cfefeca6b70eb09c9d94764f4ed4f786c2
Reviewed-on: https://chromium-review.googlesource.com/583632
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: default avatarOliver Chang <ochang@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490706}
parent 70aec2ee
......@@ -2,7 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string.h>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.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"
......@@ -18,6 +23,7 @@
#include "content/public/common/url_loader_factory.mojom.h"
#include "content/public/test/test_url_loader_client.h"
#include "mojo/common/data_pipe_utils.h"
#include "net/base/filename_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
......@@ -117,6 +123,66 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, BasicRequest) {
EXPECT_EQ(net::OK, client.completion_status().error_code);
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, DataURL) {
content::mojom::URLLoaderPtr loader;
content::ResourceRequest request;
content::TestURLLoaderClient client;
request.url = GURL("data:text/plain,foo");
request.method = "GET";
request.request_initiator = url::Origin();
loader_factory()->CreateLoaderAndStart(
mojo::MakeRequest(&loader), 2, 1, content::mojom::kURLLoadOptionNone,
request, client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilResponseReceived();
// Data URLs don't have headers.
EXPECT_FALSE(client.response_head().headers);
EXPECT_EQ("text/plain", client.response_head().mime_type);
client.RunUntilResponseBodyArrived();
std::string response_body;
EXPECT_TRUE(mojo::common::BlockingCopyToString(client.response_body_release(),
&response_body));
EXPECT_EQ("foo", response_body);
client.RunUntilComplete();
EXPECT_EQ(net::OK, client.completion_status().error_code);
}
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, FileURL) {
base::ThreadRestrictions::ScopedAllowIO allow_io;
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)));
content::mojom::URLLoaderPtr loader;
content::ResourceRequest request;
content::TestURLLoaderClient client;
request.url = net::FilePathToFileURL(file_path);
request.method = "GET";
request.request_initiator = url::Origin();
loader_factory()->CreateLoaderAndStart(
mojo::MakeRequest(&loader), 2, 1, content::mojom::kURLLoadOptionNone,
request, client.CreateInterfacePtr(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
client.RunUntilResponseReceived();
// File URLs don't have headers.
EXPECT_FALSE(client.response_head().headers);
client.RunUntilResponseBodyArrived();
std::string response_body;
EXPECT_TRUE(mojo::common::BlockingCopyToString(client.response_body_release(),
&response_body));
EXPECT_EQ(kFileContents, response_body);
client.RunUntilComplete();
EXPECT_EQ(net::OK, client.completion_status().error_code);
}
INSTANTIATE_TEST_CASE_P(
SystemNetworkContext,
NetworkContextConfigurationBrowserTest,
......
......@@ -6,6 +6,7 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
......@@ -19,7 +20,20 @@ namespace {
content::mojom::NetworkContextParamsPtr CreateMainNetworkContextParams() {
// TODO(mmenke): Set up parameters here.
return content::mojom::NetworkContextParams::New();
content::mojom::NetworkContextParamsPtr network_context_params =
content::mojom::NetworkContextParams::New();
// NOTE(mmenke): Keep these protocol handlers and
// ProfileIOData::SetUpJobFactoryDefaultsForBuilder in sync with
// ProfileIOData::IsHandledProtocol().
// TODO(mmenke): Find a better way of handling tracking supported schemes.
network_context_params->enable_data_url_support = true;
network_context_params->enable_file_url_support = true;
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
network_context_params->enable_ftp_url_support = true;
#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT)
return network_context_params;
}
} // namespace
......
......@@ -6,6 +6,7 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_features.h"
......@@ -17,7 +18,17 @@ namespace {
content::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
// TODO(mmenke): Set up parameters here (No cache, in memory cookie store,
// etc).
return content::mojom::NetworkContextParams::New();
content::mojom::NetworkContextParamsPtr network_context_params =
content::mojom::NetworkContextParams::New();
// These are needed for PAC scripts that use file or data URLs (Or FTP URLs?).
network_context_params->enable_data_url_support = true;
network_context_params->enable_file_url_support = true;
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
network_context_params->enable_ftp_url_support = true;
#endif
return network_context_params;
}
} // namespace
......
......@@ -220,9 +220,7 @@ void OffTheRecordProfileIOData::InitializeInternal(
AddProtocolHandlersToBuilder(builder, protocol_handlers);
SetUpJobFactoryDefaultsForBuilder(
builder, std::move(request_interceptors),
std::move(profile_params->protocol_handler_interceptor),
profile_params->io_thread->globals()
->system_request_context->host_resolver());
std::move(profile_params->protocol_handler_interceptor));
}
void OffTheRecordProfileIOData::OnMainRequestContextCreated(
......
......@@ -555,8 +555,7 @@ void ProfileImplIOData::InitializeInternal(
io_thread_globals->data_use_ascriber.get());
SetUpJobFactoryDefaultsForBuilder(
builder, std::move(request_interceptors),
std::move(profile_params->protocol_handler_interceptor),
io_thread_globals->system_request_context->host_resolver());
std::move(profile_params->protocol_handler_interceptor));
builder->set_reporting_policy(MaybeCreateReportingPolicy());
}
......
......@@ -1320,17 +1320,9 @@ void ProfileIOData::SetUpJobFactoryDefaultsForBuilder(
net::URLRequestContextBuilder* builder,
content::URLRequestInterceptorScopedVector request_interceptors,
std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor,
net::HostResolver* host_resolver) const {
// NOTE(willchan): Keep these protocol handlers in sync with
// ProfileIOData::IsHandledProtocol().
builder->SetProtocolHandler(
url::kFileScheme,
base::MakeUnique<net::FileProtocolHandler>(
base::CreateTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
protocol_handler_interceptor) const {
// NOTE(willchan): Keep these protocol handlers in sync with
// ProfileIOData::IsHandledProtocol().
#if BUILDFLAG(ENABLE_EXTENSIONS)
DCHECK(extension_info_map_.get());
// Check only for incognito (and not Chrome OS guest mode GUEST_PROFILE).
......@@ -1339,8 +1331,6 @@ void ProfileIOData::SetUpJobFactoryDefaultsForBuilder(
extensions::CreateExtensionProtocolHandler(
is_incognito, extension_info_map_.get()));
#endif
builder->SetProtocolHandler(url::kDataScheme,
base::MakeUnique<net::DataProtocolHandler>());
#if defined(OS_CHROMEOS)
if (profile_params_) {
builder->SetProtocolHandler(
......@@ -1361,11 +1351,6 @@ void ProfileIOData::SetUpJobFactoryDefaultsForBuilder(
url::kAboutScheme,
base::MakeUnique<about_handler::AboutProtocolHandler>());
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
builder->SetProtocolHandler(url::kFtpScheme,
net::FtpProtocolHandler::Create(host_resolver));
#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT)
#if BUILDFLAG(DEBUG_DEVTOOLS)
request_interceptors.push_back(base::MakeUnique<DebugDevToolsInterceptor>());
#endif
......
......@@ -376,19 +376,20 @@ class ProfileIOData {
net::NetworkDelegate* network_delegate,
net::HostResolver* host_resolver) const;
// Does common setup of the URLRequestJobFactories. Adds default
// ProtocolHandlers to |builder|, and adds URLRequestInterceptors in front of
// them as needed.
// Does common setup of the URLRequestJobFactories. Adds
// |request_interceptors| and some default ProtocolHandlers to |builder|, adds
// URLRequestInterceptors in front of them as needed.
//
// Unlike SetUpJobFactoryDefaults, leaves configuring data, file, and ftp
// support to the ProfileNetworkContextService.
//
// |protocol_handler_interceptor| is configured to intercept URLRequests
// before all other URLRequestInterceptors, if non-null.
// |host_resolver| is needed to set up the FtpProtocolHandler.
void SetUpJobFactoryDefaultsForBuilder(
net::URLRequestContextBuilder* builder,
content::URLRequestInterceptorScopedVector request_interceptors,
std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor,
net::HostResolver* host_resolver) const;
protocol_handler_interceptor) const;
// Called when the Profile is destroyed. |context_getters| must include all
// URLRequestContextGetters that refer to the ProfileIOData's
......
......@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/network/cache_url_loader.h"
#include "content/network/network_service_impl.h"
......@@ -26,7 +27,24 @@ namespace content {
namespace {
std::unique_ptr<net::URLRequestContext> MakeURLRequestContext() {
void ApplyContextParamsToBuilder(
net::URLRequestContextBuilder* builder,
mojom::NetworkContextParams* network_context_params) {
builder->set_data_enabled(network_context_params->enable_data_url_support);
#if !BUILDFLAG(DISABLE_FILE_SUPPORT)
builder->set_file_enabled(network_context_params->enable_file_url_support);
#else // BUILDFLAG(DISABLE_FILE_SUPPORT)
DCHECK(!network_context_params->enable_file_url_support);
#endif
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
builder->set_ftp_enabled(network_context_params->enable_ftp_url_support);
#else // BUILDFLAG(DISABLE_FTP_SUPPORT)
DCHECK(!network_context_params->enable_ftp_url_support);
#endif
}
std::unique_ptr<net::URLRequestContext> MakeURLRequestContext(
mojom::NetworkContextParams* network_context_params) {
net::URLRequestContextBuilder builder;
net::HttpNetworkSession::Params params;
const base::CommandLine* command_line =
......@@ -68,8 +86,6 @@ std::unique_ptr<net::URLRequestContext> MakeURLRequestContext() {
cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY;
builder.EnableHttpCache(cache_params);
builder.set_file_enabled(true);
builder.set_data_enabled(true);
if (command_line->HasSwitch(switches::kProxyServer)) {
net::ProxyConfig config;
......@@ -82,6 +98,8 @@ std::unique_ptr<net::URLRequestContext> MakeURLRequestContext() {
builder.set_proxy_service(net::ProxyService::CreateDirect());
}
ApplyContextParamsToBuilder(&builder, network_context_params);
return builder.Build();
}
......@@ -91,7 +109,7 @@ NetworkContext::NetworkContext(NetworkServiceImpl* network_service,
mojom::NetworkContextRequest request,
mojom::NetworkContextParamsPtr params)
: network_service_(network_service),
url_request_context_(MakeURLRequestContext()),
url_request_context_(MakeURLRequestContext(params.get())),
params_(std::move(params)),
binding_(this, std::move(request)) {
network_service_->RegisterNetworkContext(this);
......@@ -107,9 +125,11 @@ NetworkContext::NetworkContext(
mojom::NetworkContextParamsPtr params,
std::unique_ptr<net::URLRequestContextBuilder> builder)
: network_service_(nullptr),
url_request_context_(builder->Build()),
params_(std::move(params)),
binding_(this, std::move(request)) {}
binding_(this, std::move(request)) {
ApplyContextParamsToBuilder(builder.get(), params_.get());
url_request_context_ = builder->Build();
}
NetworkContext::~NetworkContext() {
// Call each URLLoaderImpl and ask it to release its net::URLRequest, as the
......@@ -159,8 +179,10 @@ void NetworkContext::Cleanup() {
NetworkContext::NetworkContext()
: network_service_(nullptr),
url_request_context_(MakeURLRequestContext()),
binding_(this) {}
params_(mojom::NetworkContextParams::New()),
binding_(this) {
url_request_context_ = MakeURLRequestContext(params_.get());
}
void NetworkContext::OnConnectionError() {
// Don't delete |this| in response to connection errors when it was created by
......
......@@ -39,7 +39,7 @@ class URLLoaderImpl;
// URLRequestContext. When that happens, the consumer takes ownership of the
// NetworkContext directly, has direct access to its URLRequestContext, and is
// responsible for destroying it before the NetworkService.
class NetworkContext : public mojom::NetworkContext {
class CONTENT_EXPORT NetworkContext : public mojom::NetworkContext {
public:
NetworkContext(NetworkServiceImpl* network_service,
mojom::NetworkContextRequest request,
......@@ -53,7 +53,7 @@ class NetworkContext : public mojom::NetworkContext {
~NetworkContext() override;
CONTENT_EXPORT static std::unique_ptr<NetworkContext> CreateForTesting();
static std::unique_ptr<NetworkContext> CreateForTesting();
net::URLRequestContext* url_request_context() {
return url_request_context_.get();
......
// 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 <memory>
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/network/network_context.h"
#include "content/network/network_service_impl.h"
#include "content/public/common/network_service.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_constants.h"
namespace content {
namespace {
class NetworkContextTest : public testing::Test {
public:
NetworkContextTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::IO),
network_service_(NetworkServiceImpl::CreateForTesting()) {}
~NetworkContextTest() override {}
std::unique_ptr<NetworkContext> CreateContextWithParams(
mojom::NetworkContextParamsPtr context_params) {
return base::MakeUnique<NetworkContext>(
network_service_.get(), mojo::MakeRequest(&network_context_ptr_),
std::move(context_params));
}
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<NetworkServiceImpl> network_service_;
// Stores the NetworkContextPtr of the most recently created NetworkContext,
// since destroying this before the NetworkContext itself triggers deletion of
// the NetworkContext. These tests are probably fine anyways, since the
// message loop must be spun for that to happen.
mojom::NetworkContextPtr network_context_ptr_;
};
TEST_F(NetworkContextTest, DisableDataUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_data_url_support = false;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_FALSE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kDataScheme));
}
TEST_F(NetworkContextTest, EnableDataUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_data_url_support = true;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_TRUE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kDataScheme));
}
TEST_F(NetworkContextTest, DisableFileUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_file_url_support = false;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_FALSE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kFileScheme));
}
#if !BUILDFLAG(DISABLE_FILE_SUPPORT)
TEST_F(NetworkContextTest, EnableFileUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_file_url_support = true;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_TRUE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kFileScheme));
}
#endif // !BUILDFLAG(DISABLE_FILE_SUPPORT)
TEST_F(NetworkContextTest, DisableFtpUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_ftp_url_support = false;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_FALSE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kFtpScheme));
}
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
TEST_F(NetworkContextTest, EnableFtpUrlSupport) {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_ftp_url_support = true;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(context_params));
EXPECT_TRUE(
network_context->url_request_context()->job_factory()->IsHandledProtocol(
url::kFtpScheme));
}
#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT)
} // namespace
} // namespace content
......@@ -93,7 +93,7 @@ NetworkServiceImpl::CreateNetworkContextWithBuilder(
return network_context;
}
std::unique_ptr<NetworkService> NetworkServiceImpl::CreateForTesting() {
std::unique_ptr<NetworkServiceImpl> NetworkServiceImpl::CreateForTesting() {
return base::WrapUnique(new NetworkServiceImpl(nullptr));
}
......
......@@ -38,7 +38,7 @@ class CONTENT_EXPORT NetworkServiceImpl : public service_manager::Service,
std::unique_ptr<net::URLRequestContextBuilder> builder,
net::URLRequestContext** url_request_context) override;
static std::unique_ptr<NetworkService> CreateForTesting();
static std::unique_ptr<NetworkServiceImpl> CreateForTesting();
// These are called by NetworkContexts as they are being created and
// destroyed.
......
......@@ -496,6 +496,8 @@ mojom::NetworkContextPtr ContentBrowserClient::CreateNetworkContext(
mojom::NetworkContextPtr network_context;
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
context_params->enable_data_url_support = true;
context_params->enable_file_url_support = true;
GetNetworkService()->CreateNetworkContext(MakeRequest(&network_context),
std::move(context_params));
return network_context;
......
......@@ -11,10 +11,24 @@ import "url/mojo/url.mojom";
// Parameters for constructing a network context.
struct NetworkContextParams {
// Points to the cookie file. If null, an in-memory database is used.
// Points to the cookie file. Currently ignored. An in-memory cookie store is
// always used instead.
// TODO(mmenke): Respect this parameter.
mojo.common.mojom.FilePath? cookie_path;
// Points to the cache directory. If null, an in-memory database is used.
mojo.common.mojom.FilePath? cache_dir;
// Enabled protocols. Note that these apply to all fetches, including those
// used to fetch PAC scripts.
// True if data URLs should be supported.
bool enable_data_url_support = false;
// True if file URLs should be supported.
// Must be false if built without file support.
bool enable_file_url_support = false;
// True if ftp URLs should be supported.
// Must be false if built without FTP support.
bool enable_ftp_url_support = false;
};
// Represents a distinct context for making network requests, with its own
......
......@@ -1430,6 +1430,7 @@ test("content_unittests") {
"../common/service_worker/service_worker_utils_unittest.cc",
"../common/throttling_url_loader_unittest.cc",
"../common/webplugininfo_unittest.cc",
"../network/network_context_unittest.cc",
"../network/network_service_unittest.cc",
"../network/url_loader_unittest.cc",
"../public/test/referrer_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment