1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h"
15 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
16 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
17 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
18 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
19 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
20 #include "net/base/capturing_net_log.h"
21 #include "net/base/request_priority.h"
22 #include "net/http/http_response_headers.h"
23 #include "net/proxy/proxy_server.h"
24 #include "net/test/embedded_test_server/embedded_test_server.h"
25 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_intercepting_job_factory.h"
27 #include "net/url_request/url_request_interceptor.h"
28 #include "net/url_request/url_request_job.h"
29 #include "net/url_request/url_request_job_factory.h"
30 #include "net/url_request/url_request_job_factory_impl.h"
31 #include "net/url_request/url_request_test_util.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 namespace data_reduction_proxy
{
36 class CountingURLRequestInterceptor
: public net::URLRequestInterceptor
{
38 CountingURLRequestInterceptor()
39 : request_count_(0), redirect_count_(0), response_count_(0) {
42 // URLRequestInterceptor implementation:
43 net::URLRequestJob
* MaybeInterceptRequest(
44 net::URLRequest
* request
,
45 net::NetworkDelegate
* network_delegate
) const override
{
50 net::URLRequestJob
* MaybeInterceptRedirect(
51 net::URLRequest
* request
,
52 net::NetworkDelegate
* network_delegate
,
53 const GURL
& location
) const override
{
58 net::URLRequestJob
* MaybeInterceptResponse(
59 net::URLRequest
* request
,
60 net::NetworkDelegate
* network_delegate
) const override
{
65 int request_count() const {
66 return request_count_
;
69 int redirect_count() const {
70 return redirect_count_
;
73 int response_count() const {
74 return response_count_
;
78 mutable int request_count_
;
79 mutable int redirect_count_
;
80 mutable int response_count_
;
83 class TestURLRequestContextWithDataReductionProxy
84 : public net::TestURLRequestContext
{
86 TestURLRequestContextWithDataReductionProxy(DataReductionProxyParams
* params
,
87 net::NetworkDelegate
* delegate
)
88 : net::TestURLRequestContext(true) {
89 std::string proxy
= params
->origin().ToURI();
90 context_storage_
.set_proxy_service(net::ProxyService::CreateFixed(proxy
));
91 set_network_delegate(delegate
);
94 ~TestURLRequestContextWithDataReductionProxy() override
{}
97 class DataReductionProxyInterceptorTest
: public testing::Test
{
99 DataReductionProxyInterceptorTest()
100 : params_(DataReductionProxyParams::kAllowed
) {
101 default_context_
.reset(
102 new TestURLRequestContextWithDataReductionProxy(
103 ¶ms_
, &default_network_delegate_
));
104 default_context_
->set_network_delegate(&default_network_delegate_
);
105 default_context_
->set_net_log(&net_log_
);
108 ~DataReductionProxyInterceptorTest() override
{
109 // URLRequestJobs may post clean-up tasks on destruction.
110 base::RunLoop().RunUntilIdle();
113 void Init(scoped_ptr
<net::URLRequestJobFactory
> factory
) {
114 job_factory_
= factory
.Pass();
115 default_context_
->set_job_factory(job_factory_
.get());
116 default_context_
->Init();
119 DataReductionProxyParams params_
;
120 net::CapturingNetLog net_log_
;
121 net::TestNetworkDelegate default_network_delegate_
;
122 scoped_ptr
<net::URLRequestJobFactory
> job_factory_
;
123 scoped_ptr
<net::TestURLRequestContext
> default_context_
;
124 base::MessageLoopForIO loop_
;
127 TEST_F(DataReductionProxyInterceptorTest
, TestJobFactoryChaining
) {
128 // Verifies that job factories can be chained.
129 scoped_ptr
<net::URLRequestJobFactory
> impl(
130 new net::URLRequestJobFactoryImpl());
132 CountingURLRequestInterceptor
* interceptor2
=
133 new CountingURLRequestInterceptor();
134 scoped_ptr
<net::URLRequestJobFactory
> factory2(
135 new net::URLRequestInterceptingJobFactory(
136 impl
.Pass(), make_scoped_ptr(interceptor2
)));
138 CountingURLRequestInterceptor
* interceptor1
=
139 new CountingURLRequestInterceptor();
140 scoped_ptr
<net::URLRequestJobFactory
> factory1(
141 new net::URLRequestInterceptingJobFactory(
142 factory2
.Pass(), make_scoped_ptr(interceptor1
)));
144 Init(factory1
.Pass());
147 scoped_ptr
<net::URLRequest
> req(default_context_
->CreateRequest(
148 GURL("http://foo"), net::DEFAULT_PRIORITY
, &d
, nullptr));
151 base::RunLoop().Run();
152 EXPECT_EQ(1, interceptor1
->request_count());
153 EXPECT_EQ(0, interceptor1
->redirect_count());
154 EXPECT_EQ(1, interceptor1
->response_count());
155 EXPECT_EQ(1, interceptor2
->request_count());
156 EXPECT_EQ(0, interceptor2
->redirect_count());
157 EXPECT_EQ(1, interceptor2
->response_count());
160 class DataReductionProxyInterceptorWithServerTest
: public testing::Test
{
162 DataReductionProxyInterceptorWithServerTest()
164 context_
.set_network_delegate(&network_delegate_
);
165 context_
.set_net_log(&net_log_
);
168 ~DataReductionProxyInterceptorWithServerTest() override
{
169 io_data_
->ShutdownOnUIThread();
170 // URLRequestJobs may post clean-up tasks on destruction.
171 base::RunLoop().RunUntilIdle();
174 void SetUp() override
{
175 base::FilePath root_path
, proxy_file_path
, direct_file_path
;
176 PathService::Get(base::DIR_SOURCE_ROOT
, &root_path
);
177 proxy_file_path
= root_path
.AppendASCII(
178 "components/test/data/data_reduction_proxy/proxy");
179 direct_file_path
= root_path
.AppendASCII(
180 "components/test/data/data_reduction_proxy/direct");
181 proxy_
.ServeFilesFromDirectory(proxy_file_path
);
182 direct_
.ServeFilesFromDirectory(direct_file_path
);
183 ASSERT_TRUE(proxy_
.InitializeAndWaitUntilReady());
184 ASSERT_TRUE(direct_
.InitializeAndWaitUntilReady());
186 // Owned by settings_.
187 scoped_ptr
<TestDataReductionProxyParams
> params
;
188 params
.reset(new TestDataReductionProxyParams(
189 DataReductionProxyParams::kAllowed
,
190 TestDataReductionProxyParams::HAS_EVERYTHING
&
191 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN
&
192 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN
));
194 base::TrimString(proxy_
.GetURL("/").spec(), "/", &spec
);
195 params
->set_origin(net::ProxyServer::FromURI(
196 spec
, net::ProxyServer::SCHEME_HTTP
));
197 std::string proxy_name
= params
->origin().ToURI();
198 proxy_service_
.reset(
199 net::ProxyService::CreateFixedFromPacResult(
200 "PROXY " + proxy_name
+ "; DIRECT"));
202 context_
.set_proxy_service(proxy_service_
.get());
204 settings_
.reset(new DataReductionProxySettings(params
.Pass()));
206 new DataReductionProxyIOData(
207 data_reduction_proxy::Client::UNKNOWN
,
209 data_reduction_proxy::DataReductionProxyStatisticsPrefs
>(),
212 loop_
.message_loop_proxy(),
213 loop_
.message_loop_proxy()));
215 scoped_ptr
<net::URLRequestJobFactoryImpl
> job_factory_impl(
216 new net::URLRequestJobFactoryImpl());
218 new net::URLRequestInterceptingJobFactory(
219 job_factory_impl
.Pass(),
220 io_data_
->CreateInterceptor()));
221 context_
.set_job_factory(job_factory_
.get());
225 const net::TestURLRequestContext
& context() {
229 const net::test_server::EmbeddedTestServer
& direct() {
234 base::MessageLoopForIO loop_
;
235 net::CapturingNetLog net_log_
;
236 net::TestNetworkDelegate network_delegate_
;
237 net::TestURLRequestContext context_
;
238 net::test_server::EmbeddedTestServer proxy_
;
239 net::test_server::EmbeddedTestServer direct_
;
240 scoped_ptr
<net::ProxyService
> proxy_service_
;
241 scoped_ptr
<net::URLRequestJobFactory
> job_factory_
;
242 scoped_ptr
<DataReductionProxySettings
> settings_
;
243 scoped_ptr
<DataReductionProxyIOData
> io_data_
;
246 TEST_F(DataReductionProxyInterceptorWithServerTest
, TestBypass
) {
247 // Tests the mechanics of proxy bypass work with a "real" server. For tests
248 // that cover every imaginable response that could trigger a bypass, see:
249 // DataReductionProxyProtocolTest.
250 net::TestDelegate delegate
;
251 scoped_ptr
<net::URLRequest
> request(
252 context().CreateRequest(direct().GetURL("/block10.html"),
253 net::DEFAULT_PRIORITY
, &delegate
, NULL
));
255 EXPECT_TRUE(request
->is_pending());
256 base::RunLoop().Run();
258 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request
->status().status());
259 EXPECT_EQ(net::OK
, request
->status().error());
260 EXPECT_EQ("hello", delegate
.data_received());
263 TEST_F(DataReductionProxyInterceptorWithServerTest
, TestNoBypass
) {
264 net::TestDelegate delegate
;
265 scoped_ptr
<net::URLRequest
> request(
266 context().CreateRequest(direct().GetURL("/noblock.html"),
267 net::DEFAULT_PRIORITY
, &delegate
, NULL
));
269 EXPECT_TRUE(request
->is_pending());
270 base::RunLoop().Run();
272 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request
->status().status());
273 EXPECT_EQ(net::OK
, request
->status().error());
274 EXPECT_EQ("hello", delegate
.data_received());
277 } // namespace data_reduction_proxy