// Copyright (c) 2013 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 "google_apis/gaia/fake_gaia.h"

#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/linked_ptr.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"
#include "net/cookies/parsed_cookie.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "url/url_parse.h"

#define REGISTER_RESPONSE_HANDLER(url, method) \
  request_handlers_.insert(std::make_pair( \
        url.path(), base::Bind(&FakeGaia::method, base::Unretained(this))))

#define REGISTER_PATH_RESPONSE_HANDLER(path, method) \
  request_handlers_.insert(std::make_pair( \
        path, base::Bind(&FakeGaia::method, base::Unretained(this))))

using namespace net::test_server;

namespace {

const char kTestAuthCode[] = "fake-auth-code";
const char kTestGaiaUberToken[] = "fake-uber-token";
const char kTestAuthLoginAccessToken[] = "fake-access-token";
const char kTestRefreshToken[] = "fake-refresh-token";
const char kTestSessionSIDCookie[] = "fake-session-SID-cookie";
const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie";
const char kTestOAuthLoginSID[] = "fake-oauth-SID-cookie";
const char kTestOAuthLoginLSID[] = "fake-oauth-LSID-cookie";
const char kTestOAuthLoginAuthCode[] = "fake-oauth-auth-code";

const char kDefaultGaiaId[]  ="12345";

const base::FilePath::CharType kServiceLogin[] =
    FILE_PATH_LITERAL("google_apis/test/service_login.html");

// OAuth2 Authentication header value prefix.
const char kAuthHeaderBearer[] = "Bearer ";
const char kAuthHeaderOAuth[] = "OAuth ";

const char kListAccountsResponseFormat[] =
    "[\"gaia.l.a.r\",[[\"gaia.l.a\",1,\"\",\"%s\",\"\",1,1,0]]]";

typedef std::map<std::string, std::string> CookieMap;

// Parses cookie name-value map our of |request|.
CookieMap GetRequestCookies(const HttpRequest& request) {
  CookieMap result;
  std::map<std::string, std::string>::const_iterator iter =
           request.headers.find("Cookie");
  if (iter != request.headers.end()) {
    std::vector<std::string> cookie_nv_pairs;
    base::SplitString(iter->second, ' ', &cookie_nv_pairs);
    for(std::vector<std::string>::const_iterator cookie_line =
            cookie_nv_pairs.begin();
        cookie_line != cookie_nv_pairs.end();
        ++cookie_line) {
      std::vector<std::string> name_value;
      base::SplitString(*cookie_line, '=', &name_value);
      if (name_value.size() != 2)
        continue;

      std::string value = name_value[1];
      if (value.size() && value[value.size() - 1] == ';')
        value = value.substr(0, value.size() -1);

      result.insert(std::make_pair(name_value[0], value));
    }
  }
  return result;
}

// Extracts the |access_token| from authorization header of |request|.
bool GetAccessToken(const HttpRequest& request,
                    const char* auth_token_prefix,
                    std::string* access_token) {
  std::map<std::string, std::string>::const_iterator auth_header_entry =
      request.headers.find("Authorization");
  if (auth_header_entry != request.headers.end()) {
    if (StartsWithASCII(auth_header_entry->second, auth_token_prefix, true)) {
      *access_token = auth_header_entry->second.substr(
          strlen(auth_token_prefix));
      return true;
    }
  }

  return false;
}

void SetCookies(BasicHttpResponse* http_response,
                const std::string& sid_cookie,
                const std::string& lsid_cookie) {
  http_response->AddCustomHeader(
      "Set-Cookie",
      base::StringPrintf("SID=%s; Path=/; HttpOnly", sid_cookie.c_str()));
  http_response->AddCustomHeader(
      "Set-Cookie",
      base::StringPrintf("LSID=%s; Path=/; HttpOnly", lsid_cookie.c_str()));
}

}  // namespace

FakeGaia::AccessTokenInfo::AccessTokenInfo()
  : expires_in(3600) {}

FakeGaia::AccessTokenInfo::~AccessTokenInfo() {}

FakeGaia::MergeSessionParams::MergeSessionParams() {
}

FakeGaia::MergeSessionParams::~MergeSessionParams() {
}

FakeGaia::FakeGaia() {
  base::FilePath source_root_dir;
  PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir);
  CHECK(base::ReadFileToString(
      source_root_dir.Append(base::FilePath(kServiceLogin)),
      &service_login_response_));
}

FakeGaia::~FakeGaia() {}

void FakeGaia::SetFakeMergeSessionParams(
    const std::string& email,
    const std::string& auth_sid_cookie,
    const std::string& auth_lsid_cookie) {
  FakeGaia::MergeSessionParams params;
  params.auth_sid_cookie = auth_sid_cookie;
  params.auth_lsid_cookie = auth_lsid_cookie;
  params.auth_code = kTestAuthCode;
  params.refresh_token = kTestRefreshToken;
  params.access_token = kTestAuthLoginAccessToken;
  params.gaia_uber_token = kTestGaiaUberToken;
  params.session_sid_cookie = kTestSessionSIDCookie;
  params.session_lsid_cookie = kTestSessionLSIDCookie;
  params.email = email;
  SetMergeSessionParams(params);
}

void FakeGaia::SetMergeSessionParams(
    const MergeSessionParams& params) {
  merge_session_params_ = params;
}

void FakeGaia::MapEmailToGaiaId(const std::string& email,
                                const std::string& gaia_id) {
  DCHECK(!email.empty());
  DCHECK(!gaia_id.empty());
  email_to_gaia_id_map_[email] = gaia_id;
}

std::string FakeGaia::GetGaiaIdOfEmail(const std::string& email) const {
  DCHECK(!email.empty());
  auto it = email_to_gaia_id_map_.find(email);
  return it == email_to_gaia_id_map_.end() ? std::string(kDefaultGaiaId) :
      it->second;
}

void FakeGaia::AddGoogleAccountsSigninHeader(
    net::test_server::BasicHttpResponse* http_response,
    const std::string& email) const {
  DCHECK(!email.empty());
  http_response->AddCustomHeader("google-accounts-signin",
      base::StringPrintf(
          "email=\"%s\", obfuscatedid=\"%s\", sessionindex=0",
          email.c_str(), GetGaiaIdOfEmail(email).c_str()));
}

void FakeGaia::Initialize() {
  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
  // Handles /MergeSession GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->merge_session_url(), HandleMergeSession);

  // Handles /o/oauth2/programmatic_auth GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->client_login_to_oauth2_url(), HandleProgramaticAuth);

  // Handles /ServiceLogin GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->service_login_url(), HandleServiceLogin);

  // Handles /OAuthLogin GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->oauth1_login_url(), HandleOAuthLogin);

  // Handles /ServiceLoginAuth GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->service_login_auth_url(), HandleServiceLoginAuth);

  // Handles /SSO GAIA call (not GAIA, made up for SAML tests).
  REGISTER_PATH_RESPONSE_HANDLER("/SSO", HandleSSO);

  // Handles /o/oauth2/token GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->oauth2_token_url(), HandleAuthToken);

  // Handles /oauth2/v2/tokeninfo GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->oauth2_token_info_url(), HandleTokenInfo);

  // Handles /oauth2/v2/IssueToken GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->oauth2_issue_token_url(), HandleIssueToken);

  // Handles /ListAccounts GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->ListAccountsURLWithSource(std::string()), HandleListAccounts);

  // Handles /GetUserInfo GAIA call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->get_user_info_url(), HandleGetUserInfo);
}

scoped_ptr<HttpResponse> FakeGaia::HandleRequest(const HttpRequest& request) {
  // The scheme and host of the URL is actually not important but required to
  // get a valid GURL in order to parse |request.relative_url|.
  GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
  std::string request_path = request_url.path();
  scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse());
  RequestHandlerMap::iterator iter = request_handlers_.find(request_path);
  if (iter != request_handlers_.end()) {
    LOG(WARNING) << "Serving request " << request_path;
    iter->second.Run(request, http_response.get());
  } else {
    LOG(ERROR) << "Unhandled request " << request_path;
    return scoped_ptr<HttpResponse>();      // Request not understood.
  }

  return http_response.Pass();
}

void FakeGaia::IssueOAuthToken(const std::string& auth_token,
                               const AccessTokenInfo& token_info) {
  access_token_info_map_.insert(std::make_pair(auth_token, token_info));
}

void FakeGaia::RegisterSamlUser(const std::string& account_id,
                                const GURL& saml_idp) {
  saml_account_idp_map_[account_id] = saml_idp;
}

// static
bool FakeGaia::GetQueryParameter(const std::string& query,
                                 const std::string& key,
                                 std::string* value) {
  // Name and scheme actually don't matter, but are required to get a valid URL
  // for parsing.
  GURL query_url("http://localhost?" + query);
  return net::GetValueForKeyInQuery(query_url, key, value);
}

void FakeGaia::HandleMergeSession(const HttpRequest& request,
                                  BasicHttpResponse* http_response) {
  http_response->set_code(net::HTTP_UNAUTHORIZED);
  if (merge_session_params_.session_sid_cookie.empty() ||
      merge_session_params_.session_lsid_cookie.empty()) {
    http_response->set_code(net::HTTP_BAD_REQUEST);
    return;
  }

  std::string uber_token;
  if (!GetQueryParameter(request.content, "uberauth", &uber_token) ||
      uber_token != merge_session_params_.gaia_uber_token) {
    LOG(ERROR) << "Missing or invalid 'uberauth' param in /MergeSession call";
    return;
  }

  std::string continue_url;
  if (!GetQueryParameter(request.content, "continue", &continue_url)) {
    LOG(ERROR) << "Missing or invalid 'continue' param in /MergeSession call";
    return;
  }

  std::string source;
  if (!GetQueryParameter(request.content, "source", &source)) {
    LOG(ERROR) << "Missing or invalid 'source' param in /MergeSession call";
    return;
  }

  SetCookies(http_response,
             merge_session_params_.session_sid_cookie,
             merge_session_params_.session_lsid_cookie);
  // TODO(zelidrag): Not used now.
  http_response->set_content("OK");
  http_response->set_code(net::HTTP_OK);
}

void FakeGaia::HandleProgramaticAuth(
    const HttpRequest& request,
    BasicHttpResponse* http_response) {
  http_response->set_code(net::HTTP_UNAUTHORIZED);
  if (merge_session_params_.auth_code.empty()) {
    http_response->set_code(net::HTTP_BAD_REQUEST);
    return;
  }

  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
  std::string scope;
  if (!GetQueryParameter(request.content, "scope", &scope) ||
      GaiaConstants::kOAuth1LoginScope != scope) {
    return;
  }

  CookieMap cookies = GetRequestCookies(request);
  CookieMap::const_iterator sid_iter = cookies.find("SID");
  if (sid_iter == cookies.end() ||
      sid_iter->second != merge_session_params_.auth_sid_cookie) {
    LOG(ERROR) << "/o/oauth2/programmatic_auth missing SID cookie";
    return;
  }
  CookieMap::const_iterator lsid_iter = cookies.find("LSID");
  if (lsid_iter == cookies.end() ||
      lsid_iter->second != merge_session_params_.auth_lsid_cookie) {
    LOG(ERROR) << "/o/oauth2/programmatic_auth missing LSID cookie";
    return;
  }

  std::string client_id;
  if (!GetQueryParameter(request.content, "client_id", &client_id) ||
      gaia_urls->oauth2_chrome_client_id() != client_id) {
    return;
  }

  http_response->AddCustomHeader(
      "Set-Cookie",
      base::StringPrintf(
          "oauth_code=%s; Path=/o/GetOAuth2Token; Secure; HttpOnly;",
          merge_session_params_.auth_code.c_str()));
  http_response->set_code(net::HTTP_OK);
  http_response->set_content_type("text/html");
}

void FakeGaia::FormatJSONResponse(const base::DictionaryValue& response_dict,
                                  BasicHttpResponse* http_response) {
  std::string response_json;
  base::JSONWriter::Write(&response_dict, &response_json);
  http_response->set_content(response_json);
  http_response->set_code(net::HTTP_OK);
}

const FakeGaia::AccessTokenInfo* FakeGaia::FindAccessTokenInfo(
    const std::string& auth_token,
    const std::string& client_id,
    const std::string& scope_string) const {
  if (auth_token.empty() || client_id.empty())
    return NULL;

  std::vector<std::string> scope_list;
  base::SplitString(scope_string, ' ', &scope_list);
  ScopeSet scopes(scope_list.begin(), scope_list.end());

  for (AccessTokenInfoMap::const_iterator entry(
           access_token_info_map_.lower_bound(auth_token));
       entry != access_token_info_map_.upper_bound(auth_token);
       ++entry) {
    if (entry->second.audience == client_id &&
        (scope_string.empty() || entry->second.scopes == scopes)) {
      return &(entry->second);
    }
  }

  return NULL;
}

void FakeGaia::HandleServiceLogin(const HttpRequest& request,
                                  BasicHttpResponse* http_response) {
  http_response->set_code(net::HTTP_OK);
  http_response->set_content(service_login_response_);
  http_response->set_content_type("text/html");
}

void FakeGaia::HandleOAuthLogin(const HttpRequest& request,
                                BasicHttpResponse* http_response) {
  http_response->set_code(net::HTTP_UNAUTHORIZED);
  if (merge_session_params_.gaia_uber_token.empty()) {
    http_response->set_code(net::HTTP_FORBIDDEN);
    return;
  }

  std::string access_token;
  if (!GetAccessToken(request, kAuthHeaderBearer, &access_token) &&
      !GetAccessToken(request, kAuthHeaderOAuth, &access_token)) {
    LOG(ERROR) << "/OAuthLogin missing access token in the header";
    return;
  }

  GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
  std::string request_query = request_url.query();

  std::string source;
  if (!GetQueryParameter(request_query, "source", &source) &&
      !GetQueryParameter(request.content, "source", &source)) {
    LOG(ERROR) << "Missing 'source' param in /OAuthLogin call";
    return;
  }

  std::string issue_uberauth;
  if (GetQueryParameter(request_query, "issueuberauth", &issue_uberauth) &&
      issue_uberauth == "1") {
    http_response->set_content(merge_session_params_.gaia_uber_token);
    http_response->set_code(net::HTTP_OK);
    // Issue GAIA uber token.
  } else {
    http_response->set_content(base::StringPrintf(
        "SID=%s\nLSID=%s\nAuth=%s",
        kTestOAuthLoginSID, kTestOAuthLoginLSID, kTestOAuthLoginAuthCode));
    http_response->set_code(net::HTTP_OK);
  }
}

void FakeGaia::HandleServiceLoginAuth(const HttpRequest& request,
                                      BasicHttpResponse* http_response) {
  std::string continue_url =
      GaiaUrls::GetInstance()->service_login_url().spec();
  GetQueryParameter(request.content, "continue", &continue_url);

  std::string redirect_url = continue_url;

  std::string email;
  const bool is_saml =
      GetQueryParameter(request.content, "Email", &email) &&
      saml_account_idp_map_.find(email) != saml_account_idp_map_.end();

  if (is_saml) {
    GURL url(saml_account_idp_map_[email]);
    url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request");
    url = net::AppendQueryParameter(url, "RelayState", continue_url);
    redirect_url = url.spec();
    http_response->AddCustomHeader("Google-Accounts-SAML", "Start");
  } else if (!merge_session_params_.auth_sid_cookie.empty() &&
             !merge_session_params_.auth_lsid_cookie.empty()) {
    SetCookies(http_response,
               merge_session_params_.auth_sid_cookie,
               merge_session_params_.auth_lsid_cookie);
  }

  http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
  http_response->AddCustomHeader("Location", redirect_url);

  // SAML sign-ins complete in HandleSSO().
  if (is_saml)
    return;

  AddGoogleAccountsSigninHeader(http_response, email);
}

void FakeGaia::HandleSSO(const HttpRequest& request,
                         BasicHttpResponse* http_response) {
  if (!merge_session_params_.auth_sid_cookie.empty() &&
      !merge_session_params_.auth_lsid_cookie.empty()) {
    SetCookies(http_response,
               merge_session_params_.auth_sid_cookie,
               merge_session_params_.auth_lsid_cookie);
  }
  std::string relay_state;
  GetQueryParameter(request.content, "RelayState", &relay_state);
  std::string redirect_url = relay_state;
  http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
  http_response->AddCustomHeader("Location", redirect_url);
  http_response->AddCustomHeader("Google-Accounts-SAML", "End");

  if (!merge_session_params_.email.empty())
    AddGoogleAccountsSigninHeader(http_response, merge_session_params_.email);
}

void FakeGaia::HandleAuthToken(const HttpRequest& request,
                               BasicHttpResponse* http_response) {
  std::string scope;
  GetQueryParameter(request.content, "scope", &scope);

  std::string grant_type;
  if (!GetQueryParameter(request.content, "grant_type", &grant_type)) {
    http_response->set_code(net::HTTP_BAD_REQUEST);
    LOG(ERROR) << "No 'grant_type' param in /o/oauth2/token";
    return;
  }

  if (grant_type == "authorization_code") {
    std::string auth_code;
    if (!GetQueryParameter(request.content, "code", &auth_code) ||
        auth_code != merge_session_params_.auth_code) {
      http_response->set_code(net::HTTP_BAD_REQUEST);
      LOG(ERROR) << "No 'code' param in /o/oauth2/token";
      return;
    }

    if (GaiaConstants::kOAuth1LoginScope != scope) {
      http_response->set_code(net::HTTP_BAD_REQUEST);
      LOG(ERROR) << "Invalid scope for /o/oauth2/token - " << scope;
      return;
    }

    base::DictionaryValue response_dict;
    response_dict.SetString("refresh_token",
                            merge_session_params_.refresh_token);
    response_dict.SetString("access_token",
                            merge_session_params_.access_token);
    response_dict.SetInteger("expires_in", 3600);
    FormatJSONResponse(response_dict, http_response);
    return;
  }

  std::string refresh_token;
  std::string client_id;
  if (GetQueryParameter(request.content, "refresh_token", &refresh_token) &&
      GetQueryParameter(request.content, "client_id", &client_id)) {
    const AccessTokenInfo* token_info =
        FindAccessTokenInfo(refresh_token, client_id, scope);
    if (token_info) {
      base::DictionaryValue response_dict;
      response_dict.SetString("access_token", token_info->token);
      response_dict.SetInteger("expires_in", 3600);
      FormatJSONResponse(response_dict, http_response);
      return;
    }
  }

  LOG(ERROR) << "Bad request for /o/oauth2/token - "
              << "refresh_token = " << refresh_token
              << ", scope = " << scope
              << ", client_id = " << client_id;
  http_response->set_code(net::HTTP_BAD_REQUEST);
}

void FakeGaia::HandleTokenInfo(const HttpRequest& request,
                               BasicHttpResponse* http_response) {
  const AccessTokenInfo* token_info = NULL;
  std::string access_token;
  if (GetQueryParameter(request.content, "access_token", &access_token)) {
    for (AccessTokenInfoMap::const_iterator entry(
             access_token_info_map_.begin());
         entry != access_token_info_map_.end();
         ++entry) {
      if (entry->second.token == access_token) {
        token_info = &(entry->second);
        break;
      }
    }
  }

  if (token_info) {
    base::DictionaryValue response_dict;
    response_dict.SetString("issued_to", token_info->issued_to);
    response_dict.SetString("audience", token_info->audience);
    response_dict.SetString("user_id", token_info->user_id);
    std::vector<std::string> scope_vector(token_info->scopes.begin(),
                                          token_info->scopes.end());
    response_dict.SetString("scope", JoinString(scope_vector, " "));
    response_dict.SetInteger("expires_in", token_info->expires_in);
    response_dict.SetString("email", token_info->email);
    FormatJSONResponse(response_dict, http_response);
  } else {
    http_response->set_code(net::HTTP_BAD_REQUEST);
  }
}

void FakeGaia::HandleIssueToken(const HttpRequest& request,
                                BasicHttpResponse* http_response) {
  std::string access_token;
  std::string scope;
  std::string client_id;
  if (GetAccessToken(request, kAuthHeaderBearer, &access_token) &&
      GetQueryParameter(request.content, "scope", &scope) &&
      GetQueryParameter(request.content, "client_id", &client_id)) {
    const AccessTokenInfo* token_info =
        FindAccessTokenInfo(access_token, client_id, scope);
    if (token_info) {
      base::DictionaryValue response_dict;
      response_dict.SetString("issueAdvice", "auto");
      response_dict.SetString("expiresIn",
                              base::IntToString(token_info->expires_in));
      response_dict.SetString("token", token_info->token);
      FormatJSONResponse(response_dict, http_response);
      return;
    }
  }
  http_response->set_code(net::HTTP_BAD_REQUEST);
}

void FakeGaia::HandleListAccounts(const HttpRequest& request,
                                  BasicHttpResponse* http_response) {
  http_response->set_content(base::StringPrintf(
      kListAccountsResponseFormat, merge_session_params_.email.c_str()));
  http_response->set_code(net::HTTP_OK);
}

void FakeGaia::HandleGetUserInfo(const HttpRequest& request,
                                 BasicHttpResponse* http_response) {
  http_response->set_content(base::StringPrintf(
      "email=%s\ndisplayEmail=%s",
      merge_session_params_.email.c_str(),
      merge_session_params_.email.c_str()));
  http_response->set_code(net::HTTP_OK);
}

