// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_auth_handler_mock.h"

#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_request_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

void PrintTo(const HttpAuthHandlerMock::State& state, ::std::ostream* os) {
  switch (state) {
    case HttpAuthHandlerMock::State::WAIT_FOR_INIT:
      *os << "WAIT_FOR_INIT";
      break;
    case HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE:
      *os << "WAIT_FOR_CHALLENGE";
      break;
    case HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN:
      *os << "WAIT_FOR_GENERATE_AUTH_TOKEN";
      break;
    case HttpAuthHandlerMock::State::TOKEN_PENDING:
      *os << "TOKEN_PENDING";
      break;
    case HttpAuthHandlerMock::State::DONE:
      *os << "DONE";
      break;
  }
}

HttpAuthHandlerMock::HttpAuthHandlerMock()
    : state_(State::WAIT_FOR_INIT),
      generate_async_(false),
      generate_rv_(OK),
      auth_token_(NULL),
      first_round_(true),
      connection_based_(false),
      allows_default_credentials_(false),
      allows_explicit_credentials_(true),
      weak_factory_(this) {}

HttpAuthHandlerMock::~HttpAuthHandlerMock() = default;

void HttpAuthHandlerMock::SetGenerateExpectation(bool async, int rv) {
  generate_async_ = async;
  generate_rv_ = rv;
}

HttpAuth::AuthorizationResult HttpAuthHandlerMock::HandleAnotherChallenge(
    HttpAuthChallengeTokenizer* challenge) {
  EXPECT_THAT(state_, ::testing::AnyOf(State::WAIT_FOR_CHALLENGE,
                                       State::WAIT_FOR_GENERATE_AUTH_TOKEN));
  // If we receive an empty challenge for a connection based scheme, or a second
  // challenge for a non connection based scheme, assume it's a rejection.
  if (!is_connection_based() || challenge->base64_param().empty()) {
    state_ = State::DONE;
    return HttpAuth::AUTHORIZATION_RESULT_REJECT;
  }

  if (!base::LowerCaseEqualsASCII(challenge->scheme(), "mock")) {
    state_ = State::DONE;
    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
  }

  state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
  return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
}

bool HttpAuthHandlerMock::NeedsIdentity() {
  return first_round_;
}

bool HttpAuthHandlerMock::AllowsDefaultCredentials() {
  return allows_default_credentials_;
}

bool HttpAuthHandlerMock::AllowsExplicitCredentials() {
  return allows_explicit_credentials_;
}

bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge,
                               const SSLInfo& ssl_info) {
  EXPECT_EQ(State::WAIT_FOR_INIT, state_);
  state_ = State::WAIT_FOR_GENERATE_AUTH_TOKEN;
  auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK;
  score_ = 1;
  properties_ = connection_based_ ? IS_CONNECTION_BASED : 0;
  return true;
}

int HttpAuthHandlerMock::GenerateAuthTokenImpl(
    const AuthCredentials* credentials,
    const HttpRequestInfo* request,
    CompletionOnceCallback callback,
    std::string* auth_token) {
  EXPECT_EQ(State::WAIT_FOR_GENERATE_AUTH_TOKEN, state_);
  first_round_ = false;
  request_url_ = request->url;
  if (generate_async_) {
    EXPECT_TRUE(callback_.is_null());
    EXPECT_TRUE(auth_token_ == NULL);
    callback_ = std::move(callback);
    auth_token_ = auth_token;
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&HttpAuthHandlerMock::OnGenerateAuthToken,
                              weak_factory_.GetWeakPtr()));
    state_ = State::TOKEN_PENDING;
    return ERR_IO_PENDING;
  } else {
    if (generate_rv_ == OK) {
      *auth_token = "auth_token";
      state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
                                     : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
    } else {
      state_ = State::DONE;
    }
    return generate_rv_;
  }
}

void HttpAuthHandlerMock::OnGenerateAuthToken() {
  EXPECT_TRUE(generate_async_);
  EXPECT_TRUE(!callback_.is_null());
  EXPECT_EQ(State::TOKEN_PENDING, state_);
  if (generate_rv_ == OK) {
    *auth_token_ = "auth_token";
    state_ = is_connection_based() ? State::WAIT_FOR_CHALLENGE
                                   : State::WAIT_FOR_GENERATE_AUTH_TOKEN;
  } else {
    state_ = State::DONE;
  }
  auth_token_ = NULL;
  base::ResetAndReturn(&callback_).Run(generate_rv_);
}

HttpAuthHandlerMock::Factory::Factory()
    : do_init_from_challenge_(false) {
  // TODO(cbentzel): Default do_init_from_challenge_ to true.
}

HttpAuthHandlerMock::Factory::~Factory() = default;

void HttpAuthHandlerMock::Factory::AddMockHandler(
    HttpAuthHandler* handler, HttpAuth::Target target) {
  handlers_[target].push_back(base::WrapUnique(handler));
}

int HttpAuthHandlerMock::Factory::CreateAuthHandler(
    HttpAuthChallengeTokenizer* challenge,
    HttpAuth::Target target,
    const SSLInfo& ssl_info,
    const GURL& origin,
    CreateReason reason,
    int nonce_count,
    const NetLogWithSource& net_log,
    std::unique_ptr<HttpAuthHandler>* handler) {
  if (handlers_[target].empty())
    return ERR_UNEXPECTED;
  std::unique_ptr<HttpAuthHandler> tmp_handler =
      std::move(handlers_[target][0]);
  std::vector<std::unique_ptr<HttpAuthHandler>>& handlers = handlers_[target];
  handlers.erase(handlers.begin());
  if (do_init_from_challenge_ &&
      !tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
                                      net_log))
    return ERR_INVALID_RESPONSE;
  handler->swap(tmp_handler);
  return OK;
}

}  // namespace net
