1// Copyright (c) 2011 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#include "net/http/http_auth_handler_mock.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/strings/string_util.h"
10#include "net/base/net_errors.h"
11#include "net/http/http_auth_challenge_tokenizer.h"
12#include "net/http/http_request_info.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace net {
16
17HttpAuthHandlerMock::HttpAuthHandlerMock()
18  : resolve_(RESOLVE_INIT),
19    generate_async_(false),
20    generate_rv_(OK),
21    auth_token_(NULL),
22    first_round_(true),
23    connection_based_(false),
24    allows_default_credentials_(false),
25    allows_explicit_credentials_(true),
26    weak_factory_(this) {
27}
28
29HttpAuthHandlerMock::~HttpAuthHandlerMock() {
30}
31
32void HttpAuthHandlerMock::SetResolveExpectation(Resolve resolve) {
33  EXPECT_EQ(RESOLVE_INIT, resolve_);
34  resolve_ = resolve;
35}
36
37bool HttpAuthHandlerMock::NeedsCanonicalName() {
38  switch (resolve_) {
39    case RESOLVE_SYNC:
40    case RESOLVE_ASYNC:
41      return true;
42    case RESOLVE_SKIP:
43      resolve_ = RESOLVE_TESTED;
44      return false;
45    default:
46      NOTREACHED();
47      return false;
48  }
49}
50
51int HttpAuthHandlerMock::ResolveCanonicalName(
52    HostResolver* host_resolver, const CompletionCallback& callback) {
53  EXPECT_NE(RESOLVE_TESTED, resolve_);
54  int rv = OK;
55  switch (resolve_) {
56    case RESOLVE_SYNC:
57      resolve_ = RESOLVE_TESTED;
58      break;
59    case RESOLVE_ASYNC:
60      EXPECT_TRUE(callback_.is_null());
61      rv = ERR_IO_PENDING;
62      callback_ = callback;
63      base::MessageLoop::current()->PostTask(
64          FROM_HERE,
65          base::Bind(&HttpAuthHandlerMock::OnResolveCanonicalName,
66                     weak_factory_.GetWeakPtr()));
67      break;
68    default:
69      NOTREACHED();
70      break;
71  }
72  return rv;
73}
74
75void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
76  generate_async_ = async;
77  generate_rv_ = rv;
78}
79
80HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
81    HttpAuthChallengeTokenizer* challenge) {
82  // If we receive an empty challenge for a connection based scheme, or a second
83  // challenge for a non connection based scheme, assume it's a rejection.
84  if (!is_connection_based() || challenge->base64_param().empty())
85    return HttpAuth::AUTHORIZATION_RESULT_REJECT;
86  if (!LowerCaseEqualsASCII(challenge->scheme(), "mock"))
87    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
88  return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
89}
90
91bool HttpAuthHandlerMock::NeedsIdentity() {
92  return first_round_;
93}
94
95bool HttpAuthHandlerMock::AllowsDefaultCredentials() {
96  return allows_default_credentials_;
97}
98
99bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
100  return allows_explicit_credentials_;
101}
102
103bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge) {
104  auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
105  score_ = 1;
106  properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
107  return true;
108}
109
110int HttpAuthHandlerMock::GenerateAuthTokenImpl(
111    const AuthCredentials* credentials,
112    const HttpRequestInfo* request,
113    const CompletionCallback& callback,
114    std::string* auth_token) {
115  first_round_ = false;
116  request_url_ = request->url;
117  if (generate_async_) {
118    EXPECT_TRUE(callback_.is_null());
119    EXPECT_TRUE(auth_token_ == NULL);
120    callback_ = callback;
121    auth_token_ = auth_token;
122    base::MessageLoop::current()->PostTask(
123        FROM_HERE,
124        base::Bind(&HttpAuthHandlerMock::OnGenerateAuthToken,
125                   weak_factory_.GetWeakPtr()));
126    return ERR_IO_PENDING;
127  } else {
128    if (generate_rv_ == OK)
129      *auth_token = "auth_token";
130    return generate_rv_;
131  }
132}
133
134void HttpAuthHandlerMock::OnResolveCanonicalName() {
135  EXPECT_EQ(RESOLVE_ASYNC, resolve_);
136  EXPECT_TRUE(!callback_.is_null());
137  resolve_ = RESOLVE_TESTED;
138  CompletionCallback callback = callback_;
139  callback_.Reset();
140  callback.Run(OK);
141}
142
143void HttpAuthHandlerMock::OnGenerateAuthToken() {
144  EXPECT_TRUE(generate_async_);
145  EXPECT_TRUE(!callback_.is_null());
146  if (generate_rv_ == OK)
147    *auth_token_ = "auth_token";
148  auth_token_ = NULL;
149  CompletionCallback callback = callback_;
150  callback_.Reset();
151  callback.Run(generate_rv_);
152}
153
154HttpAuthHandlerMock::Factory::Factory()
155    : do_init_from_challenge_(false) {
156  // TODO(cbentzel): Default do_init_from_challenge_ to true.
157}
158
159HttpAuthHandlerMock::Factory::~Factory() {
160}
161
162void HttpAuthHandlerMock::Factory::AddMockHandler(
163    HttpAuthHandler* handler, HttpAuth::Target target) {
164  handlers_[target].push_back(handler);
165}
166
167int HttpAuthHandlerMock::Factory::CreateAuthHandler(
168    HttpAuthChallengeTokenizer* challenge,
169    HttpAuth::Target target,
170    const GURL& origin,
171    CreateReason reason,
172    int nonce_count,
173    const BoundNetLog& net_log,
174    scoped_ptr<HttpAuthHandler>* handler) {
175  if (handlers_[target].empty())
176    return ERR_UNEXPECTED;
177  scoped_ptr<HttpAuthHandler> tmp_handler(handlers_[target][0]);
178  std::vector<HttpAuthHandler*>& handlers = handlers_[target].get();
179  handlers.erase(handlers.begin());
180  if (do_init_from_challenge_ &&
181      !tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
182    return ERR_INVALID_RESPONSE;
183  handler->swap(tmp_handler);
184  return OK;
185}
186
187}  // namespace net
188