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. 4 5 6 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h" 7 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string16.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/time/time.h" 12 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings_test_utils.h" 13 #include "net/base/auth.h" 14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace data_reduction_proxy { 18 19 namespace { 20 21 const char kInvalidTestRealm[] = "invalid-test-realm"; 22 const char kTestChallenger[] = "https://test-challenger.com:443"; 23 const char kTestRealm[] = "test-realm"; 24 const char kTestToken[] = "test-token"; 25 const char kTestUser[] = "fw-cookie"; 26 27 } // namespace 28 29 // Test class that overrides underlying calls to see if an auth challenge is 30 // acceptible for the data reduction proxy, and to get a valid token if so. 31 class TestDataReductionProxyAuthRequestHandler 32 : public DataReductionProxyAuthRequestHandler { 33 public: 34 TestDataReductionProxyAuthRequestHandler(int time_step_ms, 35 int64 initial_time_ms, 36 DataReductionProxySettings* settings) 37 : DataReductionProxyAuthRequestHandler(settings), 38 time_step_ms_(time_step_ms), 39 now_(base::TimeTicks() + 40 base::TimeDelta::FromMilliseconds(initial_time_ms)) {} 41 protected: 42 // Test implementation. 43 virtual bool IsAcceptableAuthChallenge( 44 net::AuthChallengeInfo* auth_info) OVERRIDE { 45 if (net::HostPortPair::FromString( 46 kTestChallenger).Equals(auth_info->challenger) && 47 auth_info->realm == kTestRealm) { 48 return true; 49 } 50 return false; 51 } 52 53 // Test implementation. 54 virtual base::string16 GetTokenForAuthChallenge( 55 net::AuthChallengeInfo* auth_info) OVERRIDE { 56 return base::ASCIIToUTF16(kTestToken); 57 } 58 59 virtual base::TimeTicks Now() OVERRIDE { 60 now_ += base::TimeDelta::FromMilliseconds(time_step_ms_); 61 return now_; 62 } 63 int time_step_ms_; 64 base::TimeTicks now_; 65 }; 66 67 class DataReductionProxyAuthRequestHandlerTest : public testing::Test { 68 public: 69 70 virtual void SetUp() OVERRIDE { 71 DataReductionProxySettingsTestBase::AddTestProxyToCommandLine(); 72 settings_.reset( 73 new MockDataReductionProxySettings<DataReductionProxySettings>( 74 DataReductionProxyParams::kAllowed | 75 DataReductionProxyParams::kFallbackAllowed | 76 DataReductionProxyParams::kPromoAllowed)); 77 } 78 79 // Checks that |PROCEED| was returned with expected user and password. 80 void ExpectProceed( 81 DataReductionProxyAuthRequestHandler::TryHandleResult result, 82 const base::string16& user, 83 const base::string16& password) { 84 base::string16 expected_user = base::ASCIIToUTF16(kTestUser); 85 base::string16 expected_password = base::ASCIIToUTF16(kTestToken); 86 EXPECT_EQ(DataReductionProxyAuthRequestHandler::TRY_HANDLE_RESULT_PROCEED, 87 result); 88 EXPECT_EQ(expected_user, user); 89 EXPECT_EQ(expected_password, password); 90 } 91 92 // Checks that |CANCEL| was returned. 93 void ExpectCancel( 94 DataReductionProxyAuthRequestHandler::TryHandleResult result, 95 const base::string16& user, 96 const base::string16& password) { 97 EXPECT_EQ(DataReductionProxyAuthRequestHandler::TRY_HANDLE_RESULT_CANCEL, 98 result); 99 EXPECT_EQ(base::string16(), user); 100 EXPECT_EQ(base::string16(), password); 101 } 102 103 // Checks that |IGNORE| was returned. 104 void ExpectIgnore( 105 DataReductionProxyAuthRequestHandler::TryHandleResult result, 106 const base::string16& user, 107 const base::string16& password) { 108 EXPECT_EQ(DataReductionProxyAuthRequestHandler::TRY_HANDLE_RESULT_IGNORE, 109 result); 110 EXPECT_EQ(base::string16(), user); 111 EXPECT_EQ(base::string16(), password); 112 } 113 114 scoped_ptr<DataReductionProxySettings> settings_; 115 }; 116 117 TEST_F(DataReductionProxyAuthRequestHandlerTest, 118 CancelAfterSuccessiveAuthAttempts) { 119 DataReductionProxyAuthRequestHandler::auth_request_timestamp_ = 0; 120 DataReductionProxyAuthRequestHandler::back_to_back_failure_count_ = 0; 121 DataReductionProxyAuthRequestHandler::auth_token_invalidation_timestamp_ = 0; 122 scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo); 123 auth_info->realm = kTestRealm; 124 auth_info->challenger = net::HostPortPair::FromString(kTestChallenger); 125 TestDataReductionProxyAuthRequestHandler handler( 126 499, 3600001, settings_.get()); 127 base::string16 user, password; 128 DataReductionProxyAuthRequestHandler::TryHandleResult result = 129 handler.TryHandleAuthentication(auth_info.get(), &user, &password); 130 ExpectProceed(result, user, password); 131 132 // Successive retries should also succeed up to a maximum count. 133 for (int i = 0; i < 5; ++i) { 134 user = base::string16(); 135 password = base::string16(); 136 result = handler.TryHandleAuthentication(auth_info.get(), &user, &password); 137 ExpectProceed(result, user, password); 138 } 139 140 // Then another retry should fail. 141 user = base::string16(); 142 password = base::string16(); 143 result = handler.TryHandleAuthentication(auth_info.get(), &user, &password); 144 ExpectCancel(result, user, password); 145 146 // After canceling, the next one should proceed. 147 user = base::string16(); 148 password = base::string16(); 149 result = handler.TryHandleAuthentication(auth_info.get(), &user, &password); 150 ExpectProceed(result, user, password); 151 } 152 153 TEST_F(DataReductionProxyAuthRequestHandlerTest, Ignore) { 154 scoped_refptr<net::AuthChallengeInfo> auth_info(new net::AuthChallengeInfo); 155 auth_info->realm = kInvalidTestRealm; 156 auth_info->challenger = net::HostPortPair::FromString(kTestChallenger); 157 TestDataReductionProxyAuthRequestHandler handler( 158 100, 3600001, settings_.get()); 159 base::string16 user, password; 160 DataReductionProxyAuthRequestHandler::TryHandleResult result = 161 handler.TryHandleAuthentication(auth_info.get(), &user, &password); 162 ExpectIgnore(result, user, password); 163 } 164 165 } // namespace data_reduction_proxy 166