Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / fake_gaia.cc
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 <vector>
8
9 #include "base/base_paths.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/json/json_writer.h"
15 #include "base/logging.h"
16 #include "base/memory/linked_ptr.h"
17 #include "base/path_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/values.h"
23 #include "google_apis/gaia/gaia_constants.h"
24 #include "google_apis/gaia/gaia_urls.h"
25 #include "net/base/url_util.h"
26 #include "net/cookies/parsed_cookie.h"
27 #include "net/http/http_status_code.h"
28 #include "net/test/embedded_test_server/http_request.h"
29 #include "net/test/embedded_test_server/http_response.h"
30 #include "url/url_parse.h"
31
32 #define REGISTER_RESPONSE_HANDLER(url, method) \
33   request_handlers_.insert(std::make_pair( \
34         url.path(), base::Bind(&FakeGaia::method, base::Unretained(this))))
35
36 #define REGISTER_PATH_RESPONSE_HANDLER(path, method) \
37   request_handlers_.insert(std::make_pair( \
38         path, base::Bind(&FakeGaia::method, base::Unretained(this))))
39
40 using namespace net::test_server;
41
42 namespace {
43
44 const char kTestAuthCode[] = "fake-auth-code";
45 const char kTestGaiaUberToken[] = "fake-uber-token";
46 const char kTestAuthLoginAccessToken[] = "fake-access-token";
47 const char kTestRefreshToken[] = "fake-refresh-token";
48 const char kTestSessionSIDCookie[] = "fake-session-SID-cookie";
49 const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie";
50 const char kTestOAuthLoginSID[] = "fake-oauth-SID-cookie";
51 const char kTestOAuthLoginLSID[] = "fake-oauth-LSID-cookie";
52 const char kTestOAuthLoginAuthCode[] = "fake-oauth-auth-code";
53
54 const char kDefaultGaiaId[]  ="12345";
55
56 const base::FilePath::CharType kServiceLogin[] =
57     FILE_PATH_LITERAL("google_apis/test/service_login.html");
58
59 // OAuth2 Authentication header value prefix.
60 const char kAuthHeaderBearer[] = "Bearer ";
61 const char kAuthHeaderOAuth[] = "OAuth ";
62
63 const char kListAccountsResponseFormat[] =
64     "[\"gaia.l.a.r\",[[\"gaia.l.a\",1,\"\",\"%s\",\"\",1,1,0]]]";
65
66 typedef std::map<std::string, std::string> CookieMap;
67
68 // Parses cookie name-value map our of |request|.
69 CookieMap GetRequestCookies(const HttpRequest& request) {
70   CookieMap result;
71   std::map<std::string, std::string>::const_iterator iter =
72            request.headers.find("Cookie");
73   if (iter != request.headers.end()) {
74     std::vector<std::string> cookie_nv_pairs;
75     base::SplitString(iter->second, ' ', &cookie_nv_pairs);
76     for(std::vector<std::string>::const_iterator cookie_line =
77             cookie_nv_pairs.begin();
78         cookie_line != cookie_nv_pairs.end();
79         ++cookie_line) {
80       std::vector<std::string> name_value;
81       base::SplitString(*cookie_line, '=', &name_value);
82       if (name_value.size() != 2)
83         continue;
84
85       std::string value = name_value[1];
86       if (value.size() && value[value.size() - 1] == ';')
87         value = value.substr(0, value.size() -1);
88
89       result.insert(std::make_pair(name_value[0], value));
90     }
91   }
92   return result;
93 }
94
95 // Extracts the |access_token| from authorization header of |request|.
96 bool GetAccessToken(const HttpRequest& request,
97                     const char* auth_token_prefix,
98                     std::string* access_token) {
99   std::map<std::string, std::string>::const_iterator auth_header_entry =
100       request.headers.find("Authorization");
101   if (auth_header_entry != request.headers.end()) {
102     if (StartsWithASCII(auth_header_entry->second, auth_token_prefix, true)) {
103       *access_token = auth_header_entry->second.substr(
104           strlen(auth_token_prefix));
105       return true;
106     }
107   }
108
109   return false;
110 }
111
112 void SetCookies(BasicHttpResponse* http_response,
113                 const std::string& sid_cookie,
114                 const std::string& lsid_cookie) {
115   http_response->AddCustomHeader(
116       "Set-Cookie",
117       base::StringPrintf("SID=%s; Path=/; HttpOnly", sid_cookie.c_str()));
118   http_response->AddCustomHeader(
119       "Set-Cookie",
120       base::StringPrintf("LSID=%s; Path=/; HttpOnly", lsid_cookie.c_str()));
121 }
122
123 }  // namespace
124
125 FakeGaia::AccessTokenInfo::AccessTokenInfo()
126   : expires_in(3600) {}
127
128 FakeGaia::AccessTokenInfo::~AccessTokenInfo() {}
129
130 FakeGaia::MergeSessionParams::MergeSessionParams() {
131 }
132
133 FakeGaia::MergeSessionParams::~MergeSessionParams() {
134 }
135
136 FakeGaia::FakeGaia() {
137   base::FilePath source_root_dir;
138   PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir);
139   CHECK(base::ReadFileToString(
140       source_root_dir.Append(base::FilePath(kServiceLogin)),
141       &service_login_response_));
142 }
143
144 FakeGaia::~FakeGaia() {}
145
146 void FakeGaia::SetFakeMergeSessionParams(
147     const std::string& email,
148     const std::string& auth_sid_cookie,
149     const std::string& auth_lsid_cookie) {
150   FakeGaia::MergeSessionParams params;
151   params.auth_sid_cookie = auth_sid_cookie;
152   params.auth_lsid_cookie = auth_lsid_cookie;
153   params.auth_code = kTestAuthCode;
154   params.refresh_token = kTestRefreshToken;
155   params.access_token = kTestAuthLoginAccessToken;
156   params.gaia_uber_token = kTestGaiaUberToken;
157   params.session_sid_cookie = kTestSessionSIDCookie;
158   params.session_lsid_cookie = kTestSessionLSIDCookie;
159   params.email = email;
160   SetMergeSessionParams(params);
161 }
162
163 void FakeGaia::SetMergeSessionParams(
164     const MergeSessionParams& params) {
165   merge_session_params_ = params;
166 }
167
168 void FakeGaia::MapEmailToGaiaId(const std::string& email,
169                                 const std::string& gaia_id) {
170   DCHECK(!email.empty());
171   DCHECK(!gaia_id.empty());
172   email_to_gaia_id_map_[email] = gaia_id;
173 }
174
175 std::string FakeGaia::GetGaiaIdOfEmail(const std::string& email) const {
176   DCHECK(!email.empty());
177   auto it = email_to_gaia_id_map_.find(email);
178   return it == email_to_gaia_id_map_.end() ? std::string(kDefaultGaiaId) :
179       it->second;
180 }
181
182 void FakeGaia::AddGoogleAccountsSigninHeader(
183     net::test_server::BasicHttpResponse* http_response,
184     const std::string& email) const {
185   DCHECK(!email.empty());
186   http_response->AddCustomHeader("google-accounts-signin",
187       base::StringPrintf(
188           "email=\"%s\", obfuscatedid=\"%s\", sessionindex=0",
189           email.c_str(), GetGaiaIdOfEmail(email).c_str()));
190 }
191
192 void FakeGaia::Initialize() {
193   GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
194   // Handles /MergeSession GAIA call.
195   REGISTER_RESPONSE_HANDLER(
196       gaia_urls->merge_session_url(), HandleMergeSession);
197
198   // Handles /o/oauth2/programmatic_auth GAIA call.
199   REGISTER_RESPONSE_HANDLER(
200       gaia_urls->client_login_to_oauth2_url(), HandleProgramaticAuth);
201
202   // Handles /ServiceLogin GAIA call.
203   REGISTER_RESPONSE_HANDLER(
204       gaia_urls->service_login_url(), HandleServiceLogin);
205
206   // Handles /OAuthLogin GAIA call.
207   REGISTER_RESPONSE_HANDLER(
208       gaia_urls->oauth1_login_url(), HandleOAuthLogin);
209
210   // Handles /ServiceLoginAuth GAIA call.
211   REGISTER_RESPONSE_HANDLER(
212       gaia_urls->service_login_auth_url(), HandleServiceLoginAuth);
213
214   // Handles /SSO GAIA call (not GAIA, made up for SAML tests).
215   REGISTER_PATH_RESPONSE_HANDLER("/SSO", HandleSSO);
216
217   // Handles /o/oauth2/token GAIA call.
218   REGISTER_RESPONSE_HANDLER(
219       gaia_urls->oauth2_token_url(), HandleAuthToken);
220
221   // Handles /oauth2/v2/tokeninfo GAIA call.
222   REGISTER_RESPONSE_HANDLER(
223       gaia_urls->oauth2_token_info_url(), HandleTokenInfo);
224
225   // Handles /oauth2/v2/IssueToken GAIA call.
226   REGISTER_RESPONSE_HANDLER(
227       gaia_urls->oauth2_issue_token_url(), HandleIssueToken);
228
229   // Handles /ListAccounts GAIA call.
230   REGISTER_RESPONSE_HANDLER(
231       gaia_urls->ListAccountsURLWithSource(std::string()), HandleListAccounts);
232
233   // Handles /GetUserInfo GAIA call.
234   REGISTER_RESPONSE_HANDLER(
235       gaia_urls->get_user_info_url(), HandleGetUserInfo);
236 }
237
238 scoped_ptr<HttpResponse> FakeGaia::HandleRequest(const HttpRequest& request) {
239   // The scheme and host of the URL is actually not important but required to
240   // get a valid GURL in order to parse |request.relative_url|.
241   GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
242   std::string request_path = request_url.path();
243   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse());
244   RequestHandlerMap::iterator iter = request_handlers_.find(request_path);
245   if (iter != request_handlers_.end()) {
246     LOG(WARNING) << "Serving request " << request_path;
247     iter->second.Run(request, http_response.get());
248   } else {
249     LOG(ERROR) << "Unhandled request " << request_path;
250     return scoped_ptr<HttpResponse>();      // Request not understood.
251   }
252
253   return http_response.Pass();
254 }
255
256 void FakeGaia::IssueOAuthToken(const std::string& auth_token,
257                                const AccessTokenInfo& token_info) {
258   access_token_info_map_.insert(std::make_pair(auth_token, token_info));
259 }
260
261 void FakeGaia::RegisterSamlUser(const std::string& account_id,
262                                 const GURL& saml_idp) {
263   saml_account_idp_map_[account_id] = saml_idp;
264 }
265
266 // static
267 bool FakeGaia::GetQueryParameter(const std::string& query,
268                                  const std::string& key,
269                                  std::string* value) {
270   // Name and scheme actually don't matter, but are required to get a valid URL
271   // for parsing.
272   GURL query_url("http://localhost?" + query);
273   return net::GetValueForKeyInQuery(query_url, key, value);
274 }
275
276 void FakeGaia::HandleMergeSession(const HttpRequest& request,
277                                   BasicHttpResponse* http_response) {
278   http_response->set_code(net::HTTP_UNAUTHORIZED);
279   if (merge_session_params_.session_sid_cookie.empty() ||
280       merge_session_params_.session_lsid_cookie.empty()) {
281     http_response->set_code(net::HTTP_BAD_REQUEST);
282     return;
283   }
284
285   std::string uber_token;
286   if (!GetQueryParameter(request.content, "uberauth", &uber_token) ||
287       uber_token != merge_session_params_.gaia_uber_token) {
288     LOG(ERROR) << "Missing or invalid 'uberauth' param in /MergeSession call";
289     return;
290   }
291
292   std::string continue_url;
293   if (!GetQueryParameter(request.content, "continue", &continue_url)) {
294     LOG(ERROR) << "Missing or invalid 'continue' param in /MergeSession call";
295     return;
296   }
297
298   std::string source;
299   if (!GetQueryParameter(request.content, "source", &source)) {
300     LOG(ERROR) << "Missing or invalid 'source' param in /MergeSession call";
301     return;
302   }
303
304   SetCookies(http_response,
305              merge_session_params_.session_sid_cookie,
306              merge_session_params_.session_lsid_cookie);
307   // TODO(zelidrag): Not used now.
308   http_response->set_content("OK");
309   http_response->set_code(net::HTTP_OK);
310 }
311
312 void FakeGaia::HandleProgramaticAuth(
313     const HttpRequest& request,
314     BasicHttpResponse* http_response) {
315   http_response->set_code(net::HTTP_UNAUTHORIZED);
316   if (merge_session_params_.auth_code.empty()) {
317     http_response->set_code(net::HTTP_BAD_REQUEST);
318     return;
319   }
320
321   GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
322   std::string scope;
323   if (!GetQueryParameter(request.content, "scope", &scope) ||
324       GaiaConstants::kOAuth1LoginScope != scope) {
325     return;
326   }
327
328   CookieMap cookies = GetRequestCookies(request);
329   CookieMap::const_iterator sid_iter = cookies.find("SID");
330   if (sid_iter == cookies.end() ||
331       sid_iter->second != merge_session_params_.auth_sid_cookie) {
332     LOG(ERROR) << "/o/oauth2/programmatic_auth missing SID cookie";
333     return;
334   }
335   CookieMap::const_iterator lsid_iter = cookies.find("LSID");
336   if (lsid_iter == cookies.end() ||
337       lsid_iter->second != merge_session_params_.auth_lsid_cookie) {
338     LOG(ERROR) << "/o/oauth2/programmatic_auth missing LSID cookie";
339     return;
340   }
341
342   std::string client_id;
343   if (!GetQueryParameter(request.content, "client_id", &client_id) ||
344       gaia_urls->oauth2_chrome_client_id() != client_id) {
345     return;
346   }
347
348   http_response->AddCustomHeader(
349       "Set-Cookie",
350       base::StringPrintf(
351           "oauth_code=%s; Path=/o/GetOAuth2Token; Secure; HttpOnly;",
352           merge_session_params_.auth_code.c_str()));
353   http_response->set_code(net::HTTP_OK);
354   http_response->set_content_type("text/html");
355 }
356
357 void FakeGaia::FormatJSONResponse(const base::DictionaryValue& response_dict,
358                                   BasicHttpResponse* http_response) {
359   std::string response_json;
360   base::JSONWriter::Write(&response_dict, &response_json);
361   http_response->set_content(response_json);
362   http_response->set_code(net::HTTP_OK);
363 }
364
365 const FakeGaia::AccessTokenInfo* FakeGaia::FindAccessTokenInfo(
366     const std::string& auth_token,
367     const std::string& client_id,
368     const std::string& scope_string) const {
369   if (auth_token.empty() || client_id.empty())
370     return NULL;
371
372   std::vector<std::string> scope_list;
373   base::SplitString(scope_string, ' ', &scope_list);
374   ScopeSet scopes(scope_list.begin(), scope_list.end());
375
376   for (AccessTokenInfoMap::const_iterator entry(
377            access_token_info_map_.lower_bound(auth_token));
378        entry != access_token_info_map_.upper_bound(auth_token);
379        ++entry) {
380     if (entry->second.audience == client_id &&
381         (scope_string.empty() || entry->second.scopes == scopes)) {
382       return &(entry->second);
383     }
384   }
385
386   return NULL;
387 }
388
389 void FakeGaia::HandleServiceLogin(const HttpRequest& request,
390                                   BasicHttpResponse* http_response) {
391   http_response->set_code(net::HTTP_OK);
392   http_response->set_content(service_login_response_);
393   http_response->set_content_type("text/html");
394 }
395
396 void FakeGaia::HandleOAuthLogin(const HttpRequest& request,
397                                 BasicHttpResponse* http_response) {
398   http_response->set_code(net::HTTP_UNAUTHORIZED);
399   if (merge_session_params_.gaia_uber_token.empty()) {
400     http_response->set_code(net::HTTP_FORBIDDEN);
401     return;
402   }
403
404   std::string access_token;
405   if (!GetAccessToken(request, kAuthHeaderBearer, &access_token) &&
406       !GetAccessToken(request, kAuthHeaderOAuth, &access_token)) {
407     LOG(ERROR) << "/OAuthLogin missing access token in the header";
408     return;
409   }
410
411   GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
412   std::string request_query = request_url.query();
413
414   std::string source;
415   if (!GetQueryParameter(request_query, "source", &source) &&
416       !GetQueryParameter(request.content, "source", &source)) {
417     LOG(ERROR) << "Missing 'source' param in /OAuthLogin call";
418     return;
419   }
420
421   std::string issue_uberauth;
422   if (GetQueryParameter(request_query, "issueuberauth", &issue_uberauth) &&
423       issue_uberauth == "1") {
424     http_response->set_content(merge_session_params_.gaia_uber_token);
425     http_response->set_code(net::HTTP_OK);
426     // Issue GAIA uber token.
427   } else {
428     http_response->set_content(base::StringPrintf(
429         "SID=%s\nLSID=%s\nAuth=%s",
430         kTestOAuthLoginSID, kTestOAuthLoginLSID, kTestOAuthLoginAuthCode));
431     http_response->set_code(net::HTTP_OK);
432   }
433 }
434
435 void FakeGaia::HandleServiceLoginAuth(const HttpRequest& request,
436                                       BasicHttpResponse* http_response) {
437   std::string continue_url =
438       GaiaUrls::GetInstance()->service_login_url().spec();
439   GetQueryParameter(request.content, "continue", &continue_url);
440
441   std::string redirect_url = continue_url;
442
443   std::string email;
444   const bool is_saml =
445       GetQueryParameter(request.content, "Email", &email) &&
446       saml_account_idp_map_.find(email) != saml_account_idp_map_.end();
447
448   if (is_saml) {
449     GURL url(saml_account_idp_map_[email]);
450     url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request");
451     url = net::AppendQueryParameter(url, "RelayState", continue_url);
452     redirect_url = url.spec();
453     http_response->AddCustomHeader("Google-Accounts-SAML", "Start");
454   } else if (!merge_session_params_.auth_sid_cookie.empty() &&
455              !merge_session_params_.auth_lsid_cookie.empty()) {
456     SetCookies(http_response,
457                merge_session_params_.auth_sid_cookie,
458                merge_session_params_.auth_lsid_cookie);
459   }
460
461   http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
462   http_response->AddCustomHeader("Location", redirect_url);
463
464   // SAML sign-ins complete in HandleSSO().
465   if (is_saml)
466     return;
467
468   AddGoogleAccountsSigninHeader(http_response, email);
469 }
470
471 void FakeGaia::HandleSSO(const HttpRequest& request,
472                          BasicHttpResponse* http_response) {
473   if (!merge_session_params_.auth_sid_cookie.empty() &&
474       !merge_session_params_.auth_lsid_cookie.empty()) {
475     SetCookies(http_response,
476                merge_session_params_.auth_sid_cookie,
477                merge_session_params_.auth_lsid_cookie);
478   }
479   std::string relay_state;
480   GetQueryParameter(request.content, "RelayState", &relay_state);
481   std::string redirect_url = relay_state;
482   http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
483   http_response->AddCustomHeader("Location", redirect_url);
484   http_response->AddCustomHeader("Google-Accounts-SAML", "End");
485
486   if (!merge_session_params_.email.empty())
487     AddGoogleAccountsSigninHeader(http_response, merge_session_params_.email);
488 }
489
490 void FakeGaia::HandleAuthToken(const HttpRequest& request,
491                                BasicHttpResponse* http_response) {
492   std::string scope;
493   GetQueryParameter(request.content, "scope", &scope);
494
495   std::string grant_type;
496   if (!GetQueryParameter(request.content, "grant_type", &grant_type)) {
497     http_response->set_code(net::HTTP_BAD_REQUEST);
498     LOG(ERROR) << "No 'grant_type' param in /o/oauth2/token";
499     return;
500   }
501
502   if (grant_type == "authorization_code") {
503     std::string auth_code;
504     if (!GetQueryParameter(request.content, "code", &auth_code) ||
505         auth_code != merge_session_params_.auth_code) {
506       http_response->set_code(net::HTTP_BAD_REQUEST);
507       LOG(ERROR) << "No 'code' param in /o/oauth2/token";
508       return;
509     }
510
511     if (GaiaConstants::kOAuth1LoginScope != scope) {
512       http_response->set_code(net::HTTP_BAD_REQUEST);
513       LOG(ERROR) << "Invalid scope for /o/oauth2/token - " << scope;
514       return;
515     }
516
517     base::DictionaryValue response_dict;
518     response_dict.SetString("refresh_token",
519                             merge_session_params_.refresh_token);
520     response_dict.SetString("access_token",
521                             merge_session_params_.access_token);
522     response_dict.SetInteger("expires_in", 3600);
523     FormatJSONResponse(response_dict, http_response);
524     return;
525   }
526
527   std::string refresh_token;
528   std::string client_id;
529   if (GetQueryParameter(request.content, "refresh_token", &refresh_token) &&
530       GetQueryParameter(request.content, "client_id", &client_id)) {
531     const AccessTokenInfo* token_info =
532         FindAccessTokenInfo(refresh_token, client_id, scope);
533     if (token_info) {
534       base::DictionaryValue response_dict;
535       response_dict.SetString("access_token", token_info->token);
536       response_dict.SetInteger("expires_in", 3600);
537       FormatJSONResponse(response_dict, http_response);
538       return;
539     }
540   }
541
542   LOG(ERROR) << "Bad request for /o/oauth2/token - "
543               << "refresh_token = " << refresh_token
544               << ", scope = " << scope
545               << ", client_id = " << client_id;
546   http_response->set_code(net::HTTP_BAD_REQUEST);
547 }
548
549 void FakeGaia::HandleTokenInfo(const HttpRequest& request,
550                                BasicHttpResponse* http_response) {
551   const AccessTokenInfo* token_info = NULL;
552   std::string access_token;
553   if (GetQueryParameter(request.content, "access_token", &access_token)) {
554     for (AccessTokenInfoMap::const_iterator entry(
555              access_token_info_map_.begin());
556          entry != access_token_info_map_.end();
557          ++entry) {
558       if (entry->second.token == access_token) {
559         token_info = &(entry->second);
560         break;
561       }
562     }
563   }
564
565   if (token_info) {
566     base::DictionaryValue response_dict;
567     response_dict.SetString("issued_to", token_info->issued_to);
568     response_dict.SetString("audience", token_info->audience);
569     response_dict.SetString("user_id", token_info->user_id);
570     std::vector<std::string> scope_vector(token_info->scopes.begin(),
571                                           token_info->scopes.end());
572     response_dict.SetString("scope", JoinString(scope_vector, " "));
573     response_dict.SetInteger("expires_in", token_info->expires_in);
574     response_dict.SetString("email", token_info->email);
575     FormatJSONResponse(response_dict, http_response);
576   } else {
577     http_response->set_code(net::HTTP_BAD_REQUEST);
578   }
579 }
580
581 void FakeGaia::HandleIssueToken(const HttpRequest& request,
582                                 BasicHttpResponse* http_response) {
583   std::string access_token;
584   std::string scope;
585   std::string client_id;
586   if (GetAccessToken(request, kAuthHeaderBearer, &access_token) &&
587       GetQueryParameter(request.content, "scope", &scope) &&
588       GetQueryParameter(request.content, "client_id", &client_id)) {
589     const AccessTokenInfo* token_info =
590         FindAccessTokenInfo(access_token, client_id, scope);
591     if (token_info) {
592       base::DictionaryValue response_dict;
593       response_dict.SetString("issueAdvice", "auto");
594       response_dict.SetString("expiresIn",
595                               base::IntToString(token_info->expires_in));
596       response_dict.SetString("token", token_info->token);
597       FormatJSONResponse(response_dict, http_response);
598       return;
599     }
600   }
601   http_response->set_code(net::HTTP_BAD_REQUEST);
602 }
603
604 void FakeGaia::HandleListAccounts(const HttpRequest& request,
605                                   BasicHttpResponse* http_response) {
606   http_response->set_content(base::StringPrintf(
607       kListAccountsResponseFormat, merge_session_params_.email.c_str()));
608   http_response->set_code(net::HTTP_OK);
609 }
610
611 void FakeGaia::HandleGetUserInfo(const HttpRequest& request,
612                                  BasicHttpResponse* http_response) {
613   http_response->set_content(base::StringPrintf(
614       "email=%s\ndisplayEmail=%s",
615       merge_session_params_.email.c_str(),
616       merge_session_params_.email.c_str()));
617   http_response->set_code(net::HTTP_OK);
618 }
619