// 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 <utility>
#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/third_party/mozilla/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");

const base::FilePath::CharType kEmbeddedSetupChromeos[] =
    FILE_PATH_LITERAL("google_apis/test/embedded_setup_chromeos.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,0,1,\"12345\"]]]";

const char kDummySAMLContinuePath[] = "DummySAMLContinue";

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

// Parses cookie name-value map our of |request|.
CookieMap GetRequestCookies(const HttpRequest& request) {
  CookieMap result;
  auto iter = request.headers.find("Cookie");
  if (iter != request.headers.end()) {
    for (const std::string& cookie_line :
         base::SplitString(iter->second, " ", base::TRIM_WHITESPACE,
                           base::SPLIT_WANT_ALL)) {
      std::vector<std::string> name_value = base::SplitString(
          cookie_line, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
      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) {
  auto auth_header_entry = request.headers.find("Authorization");
  if (auth_header_entry != request.headers.end()) {
    if (base::StartsWith(auth_header_entry->second, auth_token_prefix,
                         base::CompareCase::SENSITIVE)) {
      *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(const AccessTokenInfo& other) =
    default;

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

FakeGaia::MergeSessionParams::MergeSessionParams() {
}

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

void FakeGaia::MergeSessionParams::Update(const MergeSessionParams& update) {
  // This lambda uses a pointer to data member to merge attributes.
  auto maybe_update_field =
      [this, &update](std::string MergeSessionParams::* field_ptr) {
        if (!(update.*field_ptr).empty())
          this->*field_ptr = update.*field_ptr;
      };

  maybe_update_field(&MergeSessionParams::auth_sid_cookie);
  maybe_update_field(&MergeSessionParams::auth_lsid_cookie);
  maybe_update_field(&MergeSessionParams::auth_code);
  maybe_update_field(&MergeSessionParams::refresh_token);
  maybe_update_field(&MergeSessionParams::access_token);
  maybe_update_field(&MergeSessionParams::gaia_uber_token);
  maybe_update_field(&MergeSessionParams::session_sid_cookie);
  maybe_update_field(&MergeSessionParams::session_lsid_cookie);
  maybe_update_field(&MergeSessionParams::email);
}

FakeGaia::FakeGaia() : issue_oauth_code_cookie_(false) {
  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_));
  CHECK(base::ReadFileToString(
      source_root_dir.Append(base::FilePath(kEmbeddedSetupChromeos)),
      &embedded_setup_chromeos_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::UpdateMergeSessionParams(const MergeSessionParams& params) {
  merge_session_params_.Update(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());
  const 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::SetOAuthCodeCookie(
    net::test_server::BasicHttpResponse* http_response) const {
  http_response->AddCustomHeader(
      "Set-Cookie",
      base::StringPrintf(
          "oauth_code=%s; Path=/o/GetOAuth2Token; Secure; HttpOnly;",
          merge_session_params_.auth_code.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 /embedded/setup/chromeos GAIA call.
  REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(),
                            HandleEmbeddedSetupChromeos);

  // 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 /_/embedded/lookup/accountlookup for /embedded/setup/chromeos
  // authentication request.
  REGISTER_PATH_RESPONSE_HANDLER("/_/embedded/lookup/accountlookup",
                                 HandleEmbeddedLookupAccountLookup);

  // Handles /_/embedded/signin/challenge for /embedded/setup/chromeos
  // authentication request.
  REGISTER_PATH_RESPONSE_HANDLER("/_/embedded/signin/challenge",
                                 HandleEmbeddedSigninChallenge);

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

  // Handles the /samlredirect requests for tests.
  REGISTER_PATH_RESPONSE_HANDLER("/samlredirect", HandleSAMLRedirect);

  REGISTER_RESPONSE_HANDLER(
      gaia_urls->gaia_url().Resolve(kDummySAMLContinuePath),
      HandleDummySAMLContinue);

  // Handles /oauth2/v4/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);

  // Handles /oauth2/v1/userinfo call.
  REGISTER_RESPONSE_HANDLER(
      gaia_urls->oauth_user_info_url(), HandleOAuthUserInfo);
}

std::unique_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();
  std::unique_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 std::unique_ptr<HttpResponse>();  // Request not understood.
  }

  return std::move(http_response);
}

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;
}

void FakeGaia::RegisterSamlDomainRedirectUrl(const std::string& domain,
                                             const GURL& saml_redirect_url) {
  saml_domain_url_map_[domain] = saml_redirect_url;
}

// 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);
}

std::string FakeGaia::GetDeviceIdByRefreshToken(
    const std::string& refresh_token) const {
  auto it = refresh_token_to_device_id_map_.find(refresh_token);
  return it != refresh_token_to_device_id_map_.end() ? it->second
                                                     : std::string();
}

void FakeGaia::SetRefreshTokenToDeviceIdMap(
    const RefreshTokenToDeviceIdMap& refresh_token_to_device_id_map) {
  refresh_token_to_device_id_map_ = refresh_token_to_device_id_map;
}

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;
  }

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

  std::string uber_token;
  if (!GetQueryParameter(request_query, "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_query, "continue", &continue_url)) {
    LOG(ERROR) << "Missing or invalid 'continue' param in /MergeSession call";
    return;
  }

  std::string source;
  if (!GetQueryParameter(request_query, "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;
  }

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

  GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
  std::string scope;
  if (!GetQueryParameter(request_query, "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_query, "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, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  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;
}

const FakeGaia::AccessTokenInfo* FakeGaia::GetAccessTokenInfo(
    const std::string& access_token) const {
  for (AccessTokenInfoMap::const_iterator entry(
           access_token_info_map_.begin());
       entry != access_token_info_map_.end();
       ++entry) {
    if (entry->second.token == access_token)
      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::HandleEmbeddedSetupChromeos(const HttpRequest& request,
                                           BasicHttpResponse* http_response) {
  GURL request_url = GURL("http://localhost").Resolve(request.relative_url);

  std::string client_id;
  if (!GetQueryParameter(request_url.query(), "client_id", &client_id) ||
      GaiaUrls::GetInstance()->oauth2_chrome_client_id() != client_id) {
    LOG(ERROR) << "Missing or invalid param 'client_id' in "
                  "/embedded/setup/chromeos call";
    return;
  }

  GetQueryParameter(request_url.query(), "Email", &prefilled_email_);

  http_response->set_code(net::HTTP_OK);
  http_response->set_content(embedded_setup_chromeos_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);
  if (issue_oauth_code_cookie_)
    SetOAuthCodeCookie(http_response);
}

void FakeGaia::HandleEmbeddedLookupAccountLookup(
    const net::test_server::HttpRequest& request,
    net::test_server::BasicHttpResponse* http_response) {
  std::string email;
  const bool is_saml =
      GetQueryParameter(request.content, "identifier", &email) &&
      saml_account_idp_map_.find(email) != saml_account_idp_map_.end();

  if (!is_saml)
    return;

  GURL url(saml_account_idp_map_[email]);
  url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request");
  url = net::AppendQueryParameter(url, "RelayState",
                                  GaiaUrls::GetInstance()
                                      ->gaia_url()
                                      .Resolve(kDummySAMLContinuePath)
                                      .spec());
  std::string redirect_url = url.spec();
  http_response->AddCustomHeader("Google-Accounts-SAML", "Start");

  http_response->AddCustomHeader("continue", redirect_url);
}

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

  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);
  }

  AddGoogleAccountsSigninHeader(http_response, email);

  if (issue_oauth_code_cookie_)
    SetOAuthCodeCookie(http_response);
}

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);

  if (issue_oauth_code_cookie_)
    SetOAuthCodeCookie(http_response);
}

void FakeGaia::HandleDummySAMLContinue(const HttpRequest& request,
                                       BasicHttpResponse* http_response) {
  http_response->set_content("");
  http_response->set_code(net::HTTP_OK);
}

void FakeGaia::HandleAuthToken(const HttpRequest& request,
                               BasicHttpResponse* http_response) {
  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 /oauth2/v4/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 /oauth2/v4/token";
      return;
    }

    std::string device_id;
    if (GetQueryParameter(request.content, "device_id", &device_id)) {
      std::string device_type;
      if (!GetQueryParameter(request.content, "device_type", &device_type)) {
        http_response->set_code(net::HTTP_BAD_REQUEST);
        LOG(ERROR) << "'device_type' should be set if 'device_id' is set.";
        return;
      }
      if (device_type != "chrome") {
        http_response->set_code(net::HTTP_BAD_REQUEST);
        LOG(ERROR) << "'device_type' is not 'chrome'.";
        return;
      }
    }

    base::DictionaryValue response_dict;
    response_dict.SetString("refresh_token",
                            merge_session_params_.refresh_token);
    if (!device_id.empty())
      refresh_token_to_device_id_map_[merge_session_params_.refresh_token] =
          device_id;
    response_dict.SetString("access_token",
                            merge_session_params_.access_token);
    response_dict.SetInteger("expires_in", 3600);
    FormatJSONResponse(response_dict, http_response);
    return;
  }

  std::string scope;
  GetQueryParameter(request.content, "scope", &scope);

  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 /oauth2/v4/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))
    token_info = GetAccessTokenInfo(access_token);

  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", base::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);
}

void FakeGaia::HandleOAuthUserInfo(
    const net::test_server::HttpRequest& request,
    net::test_server::BasicHttpResponse* http_response) {
  const AccessTokenInfo* token_info = NULL;
  std::string access_token;
  if (GetAccessToken(request, kAuthHeaderBearer, &access_token) ||
      GetAccessToken(request, kAuthHeaderOAuth, &access_token)) {
    token_info = GetAccessTokenInfo(access_token);
  }

  if (token_info) {
    base::DictionaryValue response_dict;
    response_dict.SetString("id", GetGaiaIdOfEmail(token_info->email));
    response_dict.SetString("email", token_info->email);
    response_dict.SetString("verified_email", token_info->email);
    FormatJSONResponse(response_dict, http_response);
  } else {
    http_response->set_code(net::HTTP_BAD_REQUEST);
  }
}

void FakeGaia::HandleSAMLRedirect(
    const net::test_server::HttpRequest& request,
    net::test_server::BasicHttpResponse* http_response) {
  GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
  std::string domain;
  GetQueryParameter(request_url.query(), "domain", &domain);

  // Get the redirect url.
  auto itr = saml_domain_url_map_.find(domain);
  if (itr == saml_domain_url_map_.end()) {
    http_response->set_code(net::HTTP_BAD_REQUEST);
    return;
  }

  GURL url = itr->second;
  url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request");
  url = net::AppendQueryParameter(url, "RelayState",
                                  GaiaUrls::GetInstance()
                                      ->gaia_url()
                                      .Resolve(kDummySAMLContinuePath)
                                      .spec());
  std::string redirect_url = url.spec();
  http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
  http_response->AddCustomHeader("Google-Accounts-SAML", "Start");
  http_response->AddCustomHeader("Location", redirect_url);
}
