fake_gaia.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2013 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 "google_apis/gaia/fake_gaia.h" 6 7#include "base/base_paths.h" 8#include "base/file_util.h" 9#include "base/files/file_path.h" 10#include "base/json/json_writer.h" 11#include "base/logging.h" 12#include "base/path_service.h" 13#include "base/strings/string_util.h" 14#include "base/values.h" 15#include "google_apis/gaia/gaia_urls.h" 16#include "net/base/url_util.h" 17#include "net/http/http_status_code.h" 18#include "net/test/embedded_test_server/http_request.h" 19#include "net/test/embedded_test_server/http_response.h" 20#include "url/url_parse.h" 21 22using namespace net::test_server; 23 24namespace { 25const base::FilePath::CharType kServiceLogin[] = 26 FILE_PATH_LITERAL("google_apis/test/service_login.html"); 27} 28 29FakeGaia::AccessTokenInfo::AccessTokenInfo() 30 : expires_in(3600) {} 31 32FakeGaia::AccessTokenInfo::~AccessTokenInfo() {} 33 34FakeGaia::FakeGaia() { 35 base::FilePath source_root_dir; 36 PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir); 37 CHECK(base::ReadFileToString( 38 source_root_dir.Append(base::FilePath(kServiceLogin)), 39 &service_login_response_)); 40} 41 42FakeGaia::~FakeGaia() {} 43 44scoped_ptr<HttpResponse> FakeGaia::HandleRequest(const HttpRequest& request) { 45 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); 46 47 // The scheme and host of the URL is actually not important but required to 48 // get a valid GURL in order to parse |request.relative_url|. 49 GURL request_url = GURL("http://localhost").Resolve(request.relative_url); 50 std::string request_path = request_url.path(); 51 52 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse()); 53 if (request_path == gaia_urls->service_login_url().path()) { 54 http_response->set_code(net::HTTP_OK); 55 http_response->set_content(service_login_response_); 56 http_response->set_content_type("text/html"); 57 } else if (request_path == gaia_urls->service_login_auth_url().path()) { 58 std::string continue_url = gaia_urls->service_login_url().spec(); 59 GetQueryParameter(request.content, "continue", &continue_url); 60 http_response->set_code(net::HTTP_OK); 61 const std::string redirect_js = 62 "document.location.href = '" + continue_url + "'"; 63 http_response->set_content( 64 "<HTML><HEAD><SCRIPT>\n" + redirect_js + "\n</SCRIPT></HEAD></HTML>"); 65 http_response->set_content_type("text/html"); 66 } else if (request_path == gaia_urls->oauth2_token_url().path()) { 67 std::string refresh_token; 68 const AccessTokenInfo* token_info = NULL; 69 if (GetQueryParameter(request.content, "refresh_token", &refresh_token) && 70 (token_info = GetAccessTokenInfo(refresh_token))) { 71 base::DictionaryValue response_dict; 72 response_dict.SetString("access_token", token_info->token); 73 response_dict.SetInteger("expires_in", 3600); 74 FormatJSONResponse(response_dict, http_response.get()); 75 } else { 76 http_response->set_code(net::HTTP_BAD_REQUEST); 77 } 78 } else if (request_path == gaia_urls->oauth2_token_info_url().path()) { 79 const AccessTokenInfo* token_info = NULL; 80 std::string access_token; 81 if (GetQueryParameter(request.content, "access_token", &access_token)) { 82 for (AccessTokenInfoMap::const_iterator entry( 83 access_token_info_map_.begin()); 84 entry != access_token_info_map_.end(); 85 ++entry) { 86 if (entry->second.token == access_token) { 87 token_info = &(entry->second); 88 break; 89 } 90 } 91 } 92 93 if (token_info) { 94 base::DictionaryValue response_dict; 95 response_dict.SetString("issued_to", token_info->issued_to); 96 response_dict.SetString("audience", token_info->audience); 97 response_dict.SetString("user_id", token_info->user_id); 98 std::vector<std::string> scope_vector(token_info->scopes.begin(), 99 token_info->scopes.end()); 100 response_dict.SetString("scope", JoinString(scope_vector, " ")); 101 response_dict.SetInteger("expires_in", token_info->expires_in); 102 response_dict.SetString("email", token_info->email); 103 FormatJSONResponse(response_dict, http_response.get()); 104 } else { 105 http_response->set_code(net::HTTP_BAD_REQUEST); 106 } 107 } else { 108 // Request not understood. 109 return scoped_ptr<HttpResponse>(); 110 } 111 112 return http_response.PassAs<HttpResponse>(); 113} 114 115void FakeGaia::IssueOAuthToken(const std::string& refresh_token, 116 const AccessTokenInfo& token_info) { 117 access_token_info_map_[refresh_token] = token_info; 118} 119 120void FakeGaia::FormatJSONResponse(const base::DictionaryValue& response_dict, 121 BasicHttpResponse* http_response) { 122 std::string response_json; 123 base::JSONWriter::Write(&response_dict, &response_json); 124 http_response->set_content(response_json); 125 http_response->set_code(net::HTTP_OK); 126} 127 128const FakeGaia::AccessTokenInfo* FakeGaia::GetAccessTokenInfo( 129 const std::string& refresh_token) const { 130 AccessTokenInfoMap::const_iterator entry = 131 access_token_info_map_.find(refresh_token); 132 return entry == access_token_info_map_.end() ? NULL : &entry->second; 133} 134 135// static 136bool FakeGaia::GetQueryParameter(const std::string& query, 137 const std::string& key, 138 std::string* value) { 139 // Name and scheme actually don't matter, but are required to get a valid URL 140 // for parsing. 141 GURL query_url("http://localhost?" + query); 142 return net::GetValueForKeyInQuery(query_url, key, value); 143} 144