1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_auth_handler_mock.h"
6
7 #include <utility>
8
9 #include "base/functional/bind.h"
10 #include "base/location.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/task/single_thread_task_runner.h"
14 #include "net/base/net_errors.h"
15 #include "net/dns/host_resolver.h"
16 #include "net/http/http_auth_challenge_tokenizer.h"
17 #include "net/http/http_request_info.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace net {
22
PrintTo(const HttpAuthHandlerMock::State & state,::std::ostream * os)23 void PrintTo(const HttpAuthHandlerMock::State& state, ::std::ostream* os) {
24 switch (state) {
25 case HttpAuthHandlerMock::State::WAIT_FOR_INIT:
26 *os << "WAIT_FOR_INIT";
27 break;
28 case HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE:
29 *os << "WAIT_FOR_CHALLENGE";
30 break;
31 case HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN:
32 *os << "WAIT_FOR_GENERATE_AUTH_TOKEN";
33 break;
34 case HttpAuthHandlerMock::State::TOKEN_PENDING:
35 *os << "TOKEN_PENDING";
36 break;
37 case HttpAuthHandlerMock::State::DONE:
38 *os << "DONE";
39 break;
40 }
41 }
42
43 HttpAuthHandlerMock::HttpAuthHandlerMock() = default;
44
45 HttpAuthHandlerMock::~HttpAuthHandlerMock() = default;
46
SetGenerateExpectation(bool async,int rv)47 void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
48 generate_async_ = async;
49 generate_rv_ = rv;
50 }
51
NeedsIdentity()52 bool HttpAuthHandlerMock::NeedsIdentity() {
53 return first_round_;
54 }
55
AllowsDefaultCredentials()56 bool HttpAuthHandlerMock::AllowsDefaultCredentials() {
57 return allows_default_credentials_;
58 }
59
AllowsExplicitCredentials()60 bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
61 return allows_explicit_credentials_;
62 }
63
Init(HttpAuthChallengeTokenizer * challenge,const SSLInfo & ssl_info,const NetworkAnonymizationKey & network_anonymization_key)64 bool HttpAuthHandlerMock::Init(
65 HttpAuthChallengeTokenizer* challenge,
66 const SSLInfo& ssl_info,
67 const NetworkAnonymizationKey& network_anonymization_key) {
68 EXPECT_EQ(State::WAIT_FOR_INIT, state_);
69 state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
70 auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
71 score_ = 1;
72 properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
73 return true;
74 }
75
GenerateAuthTokenImpl(const AuthCredentials * credentials,const HttpRequestInfo * request,CompletionOnceCallback callback,std::string * auth_token)76 int HttpAuthHandlerMock::GenerateAuthTokenImpl(
77 const AuthCredentials* credentials,
78 const HttpRequestInfo* request,
79 CompletionOnceCallback callback,
80 std::string* auth_token) {
81 EXPECT_EQ(State::WAIT_FOR_GENERATE_AUTH_TOKEN, state_);
82 first_round_ = false;
83 request_url_ = request->url;
84 if (generate_async_) {
85 EXPECT_TRUE(callback_.is_null());
86 EXPECT_TRUE(auth_token_ == nullptr);
87 callback_ = std::move(callback);
88 auth_token_ = auth_token;
89 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
90 FROM_HERE, base::BindOnce(&HttpAuthHandlerMock::OnGenerateAuthToken,
91 weak_factory_.GetWeakPtr()));
92 state_ = State::TOKEN_PENDING;
93 return ERR_IO_PENDING;
94 } else {
95 if (generate_rv_ == OK) {
96 *auth_token = "auth_token";
97 state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
98 : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
99 } else {
100 state_ = State::DONE;
101 }
102 return generate_rv_;
103 }
104 }
105
HandleAnotherChallengeImpl(HttpAuthChallengeTokenizer * challenge)106 HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallengeImpl(
107 HttpAuthChallengeTokenizer* challenge) {
108 EXPECT_THAT(state_, ::testing::AnyOf(State::WAIT_FOR_CHALLENGE,
109 State::WAIT_FOR_GENERATE_AUTH_TOKEN));
110 // If we receive an empty challenge for a connection based scheme, or a second
111 // challenge for a non connection based scheme, assume it's a rejection.
112 if (!is_connection_based() || challenge->base64_param().empty()) {
113 state_ = State::DONE;
114 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
115 }
116
117 if (challenge->auth_scheme() != "mock") {
118 state_ = State::DONE;
119 return HttpAuth::AUTHORIZATION_RESULT_INVALID;
120 }
121
122 state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
123 return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
124 }
125
OnGenerateAuthToken()126 void HttpAuthHandlerMock::OnGenerateAuthToken() {
127 EXPECT_TRUE(generate_async_);
128 EXPECT_TRUE(!callback_.is_null());
129 EXPECT_EQ(State::TOKEN_PENDING, state_);
130 if (generate_rv_ == OK) {
131 *auth_token_ = "auth_token";
132 state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
133 : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
134 } else {
135 state_ = State::DONE;
136 }
137 auth_token_ = nullptr;
138 std::move(callback_).Run(generate_rv_);
139 }
140
Factory()141 HttpAuthHandlerMock::Factory::Factory() {
142 // TODO(cbentzel): Default do_init_from_challenge_ to true.
143 }
144
145 HttpAuthHandlerMock::Factory::~Factory() = default;
146
AddMockHandler(std::unique_ptr<HttpAuthHandler> handler,HttpAuth::Target target)147 void HttpAuthHandlerMock::Factory::AddMockHandler(
148 std::unique_ptr<HttpAuthHandler> handler,
149 HttpAuth::Target target) {
150 handlers_[target].push_back(std::move(handler));
151 }
152
CreateAuthHandler(HttpAuthChallengeTokenizer * challenge,HttpAuth::Target target,const SSLInfo & ssl_info,const NetworkAnonymizationKey & network_anonymization_key,const url::SchemeHostPort & scheme_host_port,CreateReason reason,int nonce_count,const NetLogWithSource & net_log,HostResolver * host_resolver,std::unique_ptr<HttpAuthHandler> * handler)153 int HttpAuthHandlerMock::Factory::CreateAuthHandler(
154 HttpAuthChallengeTokenizer* challenge,
155 HttpAuth::Target target,
156 const SSLInfo& ssl_info,
157 const NetworkAnonymizationKey& network_anonymization_key,
158 const url::SchemeHostPort& scheme_host_port,
159 CreateReason reason,
160 int nonce_count,
161 const NetLogWithSource& net_log,
162 HostResolver* host_resolver,
163 std::unique_ptr<HttpAuthHandler>* handler) {
164 if (handlers_[target].empty())
165 return ERR_UNEXPECTED;
166 std::unique_ptr<HttpAuthHandler> tmp_handler =
167 std::move(handlers_[target][0]);
168 std::vector<std::unique_ptr<HttpAuthHandler>>& handlers = handlers_[target];
169 handlers.erase(handlers.begin());
170 if (do_init_from_challenge_ &&
171 !tmp_handler->InitFromChallenge(challenge, target, ssl_info,
172 network_anonymization_key,
173 scheme_host_port, net_log)) {
174 return ERR_INVALID_RESPONSE;
175 }
176 handler->swap(tmp_handler);
177 return OK;
178 }
179
180 } // namespace net
181