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.
6 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params_test_utils.h"
15 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.h"
16 #include "net/base/auth.h"
17 #include "net/base/host_port_pair.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 const char kChromeProxyHeader[] = "chrome-proxy";
24 const char kOtherProxy[] = "testproxy:17";
27 #if defined(OS_ANDROID)
28 const char kClient[] = "android";
30 const char kClient[] = "ios";
32 const char kClient[] = "";
34 const char kVersion[] = "0.1.2.3";
35 const char kExpectedBuild[] = "2";
36 const char kExpectedPatch[] = "3";
37 const char kBogusVersion[] = "0.0";
38 const char kTestKey[] = "test-key";
39 const char kExpectedCredentials[] = "96bd72ec4a050ba60981743d41787768";
40 const char kExpectedSession[] = "0-1633771873-1633771873-1633771873";
42 const char kTestKey2[] = "test-key2";
43 const char kExpectedCredentials2[] = "c911fdb402f578787562cf7f00eda972";
44 const char kExpectedSession2[] = "0-1633771873-1633771873-1633771873";
45 #if defined(OS_ANDROID)
46 const char kExpectedHeader2[] =
47 "ps=0-1633771873-1633771873-1633771873, "
48 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3, c=android";
49 const char kExpectedHeader3[] =
50 "ps=86401-1633771873-1633771873-1633771873, "
51 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3, c=android";
52 const char kExpectedHeader4[] =
53 "ps=0-1633771873-1633771873-1633771873, "
54 "sid=c911fdb402f578787562cf7f00eda972, c=android";
56 const char kExpectedHeader2[] =
57 "ps=0-1633771873-1633771873-1633771873, "
58 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3, c=ios";
59 const char kExpectedHeader3[] =
60 "ps=86401-1633771873-1633771873-1633771873, "
61 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3, c=ios";
62 const char kExpectedHeader4[] =
63 "ps=0-1633771873-1633771873-1633771873, "
64 "sid=c911fdb402f578787562cf7f00eda972, c=ios";
66 const char kExpectedHeader2[] =
67 "ps=0-1633771873-1633771873-1633771873, "
68 "sid=c911fdb402f578787562cf7f00eda972, b=2, p=3";
69 const char kExpectedHeader3[] =
70 "ps=86401-1633771873-1633771873-1633771873, "
71 "sid=d7c1c34ef6b90303b01c48a6c1db6419, b=2, p=3";
72 const char kExpectedHeader4[] =
73 "ps=0-1633771873-1633771873-1633771873, "
74 "sid=c911fdb402f578787562cf7f00eda972";
77 const char kDataReductionProxyKey[] = "12345";
81 namespace data_reduction_proxy {
83 class TestDataReductionProxyAuthRequestHandler
84 : public DataReductionProxyAuthRequestHandler {
86 TestDataReductionProxyAuthRequestHandler(
87 const std::string& client,
88 const std::string& version,
89 DataReductionProxyParams* params,
90 base::MessageLoopProxy* loop_proxy)
91 : DataReductionProxyAuthRequestHandler(
92 client, version, params, loop_proxy) {}
94 virtual std::string GetDefaultKey() const OVERRIDE {
98 virtual base::Time Now() const OVERRIDE {
99 return base::Time::UnixEpoch() + now_offset_;
102 virtual void RandBytes(void* output, size_t length) OVERRIDE {
103 char* c = static_cast<char*>(output);
104 for (size_t i = 0; i < length; ++i) {
109 // Time after the unix epoch that Now() reports.
110 void set_offset(const base::TimeDelta& now_offset) {
111 now_offset_ = now_offset;
115 base::TimeDelta now_offset_;
120 class DataReductionProxyAuthRequestHandlerTest : public testing::Test {
122 DataReductionProxyAuthRequestHandlerTest()
123 : loop_proxy_(base::MessageLoopProxy::current().get()) {
125 // Required for MessageLoopProxy::current().
126 base::MessageLoopForUI loop_;
127 base::MessageLoopProxy* loop_proxy_;
130 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthorizationOnIO) {
131 scoped_ptr<TestDataReductionProxyParams> params;
133 new TestDataReductionProxyParams(
134 DataReductionProxyParams::kAllowed |
135 DataReductionProxyParams::kFallbackAllowed |
136 DataReductionProxyParams::kPromoAllowed,
137 TestDataReductionProxyParams::HAS_EVERYTHING &
138 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
139 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN));
140 // loop_proxy_ is just the current message loop. This means loop_proxy_
141 // is the network thread used by DataReductionProxyAuthRequestHandler.
142 TestDataReductionProxyAuthRequestHandler auth_handler(kClient,
147 base::RunLoop().RunUntilIdle();
148 EXPECT_EQ(auth_handler.client_, kClient);
149 EXPECT_EQ(kExpectedBuild, auth_handler.build_number_);
150 EXPECT_EQ(kExpectedPatch, auth_handler.patch_number_);
151 EXPECT_EQ(auth_handler.key_, kTestKey);
152 EXPECT_EQ(kExpectedCredentials, auth_handler.credentials_);
153 EXPECT_EQ(kExpectedSession, auth_handler.session_);
156 auth_handler.InitAuthentication(kTestKey2);
157 base::RunLoop().RunUntilIdle();
158 EXPECT_EQ(kTestKey2, auth_handler.key_);
159 EXPECT_EQ(kExpectedCredentials2, auth_handler.credentials_);
160 EXPECT_EQ(kExpectedSession2, auth_handler.session_);
162 // Don't write headers if the proxy is invalid.
163 net::HttpRequestHeaders headers;
164 auth_handler.MaybeAddRequestHeader(NULL, net::ProxyServer(), &headers);
165 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
167 // Don't write headers with a valid proxy, that's not a data reduction proxy.
168 auth_handler.MaybeAddRequestHeader(
170 net::ProxyServer::FromURI(kOtherProxy, net::ProxyServer::SCHEME_HTTP),
172 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
174 // Don't write headers with a valid data reduction ssl proxy.
175 auth_handler.MaybeAddRequestHeader(
177 net::ProxyServer::FromURI(
178 net::HostPortPair::FromURL(
179 GURL(params->DefaultSSLOrigin())).ToString(),
180 net::ProxyServer::SCHEME_HTTP),
182 EXPECT_FALSE(headers.HasHeader(kChromeProxyHeader));
184 // Write headers with a valid data reduction proxy.
185 auth_handler.MaybeAddRequestHeader(
187 net::ProxyServer::FromURI(
188 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
189 net::ProxyServer::SCHEME_HTTP),
191 EXPECT_TRUE(headers.HasHeader(kChromeProxyHeader));
192 std::string header_value;
193 headers.GetHeader(kChromeProxyHeader, &header_value);
194 EXPECT_EQ(kExpectedHeader2, header_value);
196 // Write headers with a valid data reduction ssl proxy when one is expected.
197 net::HttpRequestHeaders ssl_headers;
198 auth_handler.MaybeAddProxyTunnelRequestHandler(
199 net::HostPortPair::FromURL(GURL(params->DefaultSSLOrigin())),
201 EXPECT_TRUE(ssl_headers.HasHeader(kChromeProxyHeader));
202 std::string ssl_header_value;
203 ssl_headers.GetHeader(kChromeProxyHeader, &ssl_header_value);
204 EXPECT_EQ(kExpectedHeader2, ssl_header_value);
206 // Fast forward 24 hours. The header should be the same.
207 auth_handler.set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60));
208 net::HttpRequestHeaders headers2;
209 // Write headers with a valid data reduction proxy.
210 auth_handler.MaybeAddRequestHeader(
212 net::ProxyServer::FromURI(
213 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
214 net::ProxyServer::SCHEME_HTTP),
216 EXPECT_TRUE(headers2.HasHeader(kChromeProxyHeader));
217 std::string header_value2;
218 headers2.GetHeader(kChromeProxyHeader, &header_value2);
219 EXPECT_EQ(kExpectedHeader2, header_value2);
221 // Fast forward one more second. The header should be new.
222 auth_handler.set_offset(base::TimeDelta::FromSeconds(24 * 60 * 60 + 1));
223 net::HttpRequestHeaders headers3;
224 // Write headers with a valid data reduction proxy.
225 auth_handler.MaybeAddRequestHeader(
227 net::ProxyServer::FromURI(
228 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
229 net::ProxyServer::SCHEME_HTTP),
231 EXPECT_TRUE(headers3.HasHeader(kChromeProxyHeader));
232 std::string header_value3;
233 headers3.GetHeader(kChromeProxyHeader, &header_value3);
234 EXPECT_EQ(kExpectedHeader3, header_value3);
237 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthorizationIgnoresEmptyKey) {
238 scoped_ptr<TestDataReductionProxyParams> params;
240 new TestDataReductionProxyParams(
241 DataReductionProxyParams::kAllowed |
242 DataReductionProxyParams::kFallbackAllowed |
243 DataReductionProxyParams::kPromoAllowed,
244 TestDataReductionProxyParams::HAS_EVERYTHING &
245 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
246 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN));
247 // loop_proxy_ is just the current message loop. This means loop_proxy_
248 // is the network thread used by DataReductionProxyAuthRequestHandler.
249 TestDataReductionProxyAuthRequestHandler auth_handler(kClient,
254 base::RunLoop().RunUntilIdle();
255 EXPECT_EQ(auth_handler.client_, kClient);
256 EXPECT_EQ(kExpectedBuild, auth_handler.build_number_);
257 EXPECT_EQ(kExpectedPatch, auth_handler.patch_number_);
258 EXPECT_EQ(auth_handler.key_, kTestKey);
259 EXPECT_EQ(kExpectedCredentials, auth_handler.credentials_);
260 EXPECT_EQ(kExpectedSession, auth_handler.session_);
262 // Now set an empty key. The auth handler should ignore that, and the key
263 // remains |kTestKey|.
264 auth_handler.InitAuthentication("");
265 base::RunLoop().RunUntilIdle();
266 EXPECT_EQ(auth_handler.key_, kTestKey);
267 EXPECT_EQ(kExpectedCredentials, auth_handler.credentials_);
268 EXPECT_EQ(kExpectedSession, auth_handler.session_);
271 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthorizationBogusVersion) {
272 scoped_ptr<TestDataReductionProxyParams> params;
274 new TestDataReductionProxyParams(
275 DataReductionProxyParams::kAllowed |
276 DataReductionProxyParams::kFallbackAllowed |
277 DataReductionProxyParams::kPromoAllowed,
278 TestDataReductionProxyParams::HAS_EVERYTHING &
279 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
280 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN));
281 TestDataReductionProxyAuthRequestHandler auth_handler(kClient,
285 EXPECT_TRUE(auth_handler.build_number_.empty());
286 EXPECT_TRUE(auth_handler.patch_number_.empty());
289 auth_handler.InitAuthentication(kTestKey2);
290 base::RunLoop().RunUntilIdle();
291 EXPECT_EQ(kTestKey2, auth_handler.key_);
292 EXPECT_EQ(kExpectedCredentials2, auth_handler.credentials_);
293 EXPECT_EQ(kExpectedSession2, auth_handler.session_);
295 net::HttpRequestHeaders headers;
296 // Write headers with a valid data reduction proxy;
297 auth_handler.MaybeAddRequestHeader(
299 net::ProxyServer::FromURI(
300 net::HostPortPair::FromURL(GURL(params->DefaultOrigin())).ToString(),
301 net::ProxyServer::SCHEME_HTTP),
303 EXPECT_TRUE(headers.HasHeader(kChromeProxyHeader));
304 std::string header_value;
305 headers.GetHeader(kChromeProxyHeader, &header_value);
306 EXPECT_EQ(kExpectedHeader4, header_value);
309 TEST_F(DataReductionProxyAuthRequestHandlerTest, AuthHashForSalt) {
310 std::string salt = "8675309"; // Jenny's number to test the hash generator.
311 std::string salted_key = salt + kDataReductionProxyKey + salt;
312 base::string16 expected_hash = base::UTF8ToUTF16(base::MD5String(salted_key));
313 EXPECT_EQ(expected_hash,
314 DataReductionProxyAuthRequestHandler::AuthHashForSalt(
315 8675309, kDataReductionProxyKey));
318 } // namespace data_reduction_proxy