15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Authenticate a user against the Google Accounts ClientLogin API 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with various capabilities and return results to a GaiaAuthConsumer. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the future, we will also issue auth tokens from this class. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class should be used on a single thread, but it can be whichever thread 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that you like. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class can handle one request at a time on any thread. To parallelize 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requests, create multiple GaiaAuthFetcher's. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GaiaAuthFetcherTest; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLFetcher; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLRequestContextGetter; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLRequestStatus; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GaiaAuthFetcher : public net::URLFetcherDelegate { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum HostedAccountsSetting { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsAllowed, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsNotAllowed 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Magic string indicating that, while a second factor is still 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // needed to complete authentication, the user provided the right password. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kSecondFactor[]; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will later be hidden behind an auth service which caches 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tokens. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthFetcher(GaiaAuthConsumer* consumer, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GaiaAuthFetcher(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to obtain the SID and LSID cookies for the the account 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // identified by |username| and |password|. If |service| is not null or 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // empty, then also obtains a service token for specified service. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a second call because of captcha challenge, then the 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |login_token| and |login_captcha| arugment should correspond to the 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // solution of the challenge. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnClientLoginSuccess or OnClientLoginFailure will be 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartClientLogin(const std::string& username, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to obtain service token for the the account identified by 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |sid| and |lsid| and the |service|. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartIssueAuthToken(const std::string& sid, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start a request to obtain |service| token for the the account identified by 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |uber_token|. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // called on the consumer on the original thread. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StartTokenAuth(const std::string& uber_token, 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* const service); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start a request to obtain service token for the the account identified by 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |oauth2_access_token| and the |service|. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Either OnIssueAuthTokenSuccess or OnIssueAuthTokenFailure will be 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // called on the consumer on the original thread. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StartIssueAuthTokenForOAuth2(const std::string& oauth2_access_token, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* const service); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to exchange an "lso" service token given by |auth_token| 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for an OAuthLogin-scoped oauth2 token. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnClientOAuthSuccess or OnClientOAuthFailure will be 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartLsoForOAuthLoginTokenExchange(const std::string& auth_token); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start a request to revoke |auth_token|. 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 105558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // OnOAuth2RevokeTokenCompleted will be called on the consumer on the original 106558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // thread. 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void StartRevokeOAuth2Token(const std::string& auth_token); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to exchange the cookies of a signed-in user session 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for an OAuthLogin-scoped oauth2 token. In the case of a session with 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // multiple accounts signed in, |session_index| indicate the which of accounts 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // within the session. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnClientOAuthSuccess or OnClientOAuthFailure will be 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartCookieForOAuthLoginTokenExchange(const std::string& session_index); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Start a request to exchange the authorization code for an OAuthLogin-scoped 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // oauth2 token. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Either OnClientOAuthSuccess or OnClientOAuthFailure will be 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // called on the consumer on the original thread. 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StartAuthCodeForOAuth2TokenExchange(const std::string& auth_code); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to get user info for the account identified by |lsid|. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnGetUserInfoSuccess or OnGetUserInfoFailure will be 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartGetUserInfo(const std::string& lsid); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a MergeSession request to pre-login the user with the given 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // credentials. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a MergeSession request to fill the browsing cookie jar with 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // credentials represented by the account whose uber-auth token is 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |uber_token|. This method will modify the cookies of the current profile. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnMergeSessionSuccess or OnMergeSessionFailure will be 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartMergeSession(const std::string& uber_token); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to exchange an OAuthLogin-scoped oauth2 access token for an 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // uber-auth token. The returned token can be used with the method 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // StartMergeSession(). 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnUberAuthTokenSuccess or OnUberAuthTokenFailure will be 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called on the consumer on the original thread. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartTokenFetchForUberAuthExchange(const std::string& access_token); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a request to exchange an OAuthLogin-scoped oauth2 access token for a 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClientLogin-style service tokens. The response to this request is the 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same as the response to a ClientLogin request, except that captcha 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // challenges are never issued. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either OnClientLoginSuccess or OnClientLoginFailure will be 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // called on the consumer on the original thread. If |service| is empty, 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the call will attempt to fetch uber auth token. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartOAuthLogin(const std::string& access_token, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Starts a request to list the accounts in the GAIA cookie. 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void StartListAccounts(); 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implementation of net::URLFetcherDelegate 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // StartClientLogin been called && results not back yet? 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasPendingFetch(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop any URL fetches in progress. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CancelRequest(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From a URLFetcher result, generate an appropriate error. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From the API documentation, both IssueAuthToken and ClientLogin have 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same error returns. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static GoogleServiceAuthError GenerateOAuthLoginError( 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClientLogin body constants that don't change 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCookiePersistence[]; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountTypeHostedOrGoogle[]; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountTypeGoogle[]; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body for ClientLogin. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginFormat[]; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of said POST body when CAPTCHA token & answer are specified. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginCaptchaFormat[]; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body for IssueAuthToken. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kIssueAuthTokenFormat[]; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body to get OAuth2 auth code from auth token. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginToOAuth2BodyFormat[]; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body to get OAuth2 token pair from auth code. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kOAuth2CodeToTokenPairBodyFormat[]; 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The format of the POST body to revoke an OAuth2 token. 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static const char kOAuth2RevokeTokenBodyFormat[]; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body for GetUserInfo. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kGetUserInfoFormat[]; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the POST body for MergeSession. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kMergeSessionFormat[]; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the URL for UberAuthToken. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kUberAuthTokenURLFormat[]; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of the body for OAuthLogin. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kOAuthLoginFormat[]; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constants for parsing ClientLogin errors. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountDeletedError[]; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountDeletedErrorCode[]; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountDisabledError[]; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAccountDisabledErrorCode[]; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kBadAuthenticationError[]; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kBadAuthenticationErrorCode[]; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCaptchaError[]; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCaptchaErrorCode[]; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kServiceUnavailableError[]; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kServiceUnavailableErrorCode[]; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kErrorParam[]; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kErrorUrlParam[]; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCaptchaUrlParam[]; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCaptchaTokenParam[]; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constants for parsing ClientOAuth errors. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kNeedsAdditional[]; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kCaptcha[]; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kTwoFactor[]; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constants for request/response for OAuth2 requests. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAuthHeaderFormat[]; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kOAuthHeaderFormat[]; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const char kOAuth2BearerHeaderFormat[]; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginToOAuth2CookiePartSecure[]; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginToOAuth2CookiePartHttpOnly[]; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kClientLoginToOAuth2CookiePartCodePrefix[]; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kClientLoginToOAuth2CookiePartCodePrefixLength; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process the results of a ClientLogin fetch. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnClientLoginFetched(const std::string& data, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnIssueAuthTokenFetched(const std::string& data, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnClientLoginToOAuth2Fetched(const std::string& data, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnOAuth2TokenPairFetched(const std::string& data, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void OnOAuth2RevokeTokenFetched(const std::string& data, 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const net::URLRequestStatus& status, 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int response_code); 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void OnListAccountsFetched(const std::string& data, 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const net::URLRequestStatus& status, 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int response_code); 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnGetUserInfoFetched(const std::string& data, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnMergeSessionFetched(const std::string& data, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnUberAuthTokenFetch(const std::string& data, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnOAuthLoginFetched(const std::string& data, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tokenize the results of a ClientLogin fetch. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void ParseClientLoginResponse(const std::string& data, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* sid, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* lsid, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* token); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void ParseClientLoginFailure(const std::string& data, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error_url, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_url, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* captcha_token); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse ClientLogin to OAuth2 response. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool ParseClientLoginToOAuth2Response( 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool ParseClientLoginToOAuth2Cookie(const std::string& cookie, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_code); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Is this a special case Gaia error for TwoFactor auth? 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsSecondFactorSuccess(const std::string& alleged_error); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given parameters, create a ClientLogin request body. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeClientLoginBody( 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& username, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_token, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& login_captcha, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostedAccountsSetting allow_hosted_accounts); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Supply the sid / lsid returned from ClientLogin in order to 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request a long lived auth token for a service. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeIssueAuthTokenBody(const std::string& sid, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& lsid, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const service); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create body to get OAuth2 auth code. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeGetAuthCodeBody(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given auth code, create body to get OAuth2 token pair. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeGetTokenPairBody(const std::string& auth_code); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Given an OAuth2 token, create body to revoke the token. 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string MakeRevokeTokenBody(const std::string& auth_token); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Supply the lsid returned from ClientLogin in order to fetch 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // user information. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeGetUserInfoBody(const std::string& lsid); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Supply the authentication token returned from StartIssueAuthToken. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeMergeSessionBody(const std::string& auth_token, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& continue_url, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeGetAuthCodeHeader(const std::string& auth_token); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string MakeOAuthLoginBody(const std::string& service, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a fetcher usable for making any Gaia request. |body| is used 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as the body of the POST request sent to GAIA. Any strings listed in 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |headers| are added as extra HTTP headers in the request. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |load_flags| are passed to directly to net::URLFetcher::Create() when 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // creating the URL fetcher. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static net::URLFetcher* CreateGaiaFetcher( 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& body, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& headers, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& gaia_gurl, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int load_flags, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcherDelegate* delegate); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From a URLFetcher result, generate an appropriate error. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From the API documentation, both IssueAuthToken and ClientLogin have 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same error returns. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static GoogleServiceAuthError GenerateAuthError( 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These fields are common to GaiaAuthFetcher, same every request 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GaiaAuthConsumer* const consumer_; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* const getter_; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string source_; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL client_login_gurl_; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL issue_auth_token_gurl_; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL oauth2_token_gurl_; 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL oauth2_revoke_gurl_; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL get_user_info_gurl_; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL merge_session_gurl_; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL uberauth_token_gurl_; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL oauth_login_gurl_; 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const GURL list_accounts_gurl_; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // While a fetch is going on: 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::URLFetcher> fetcher_; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL client_login_to_oauth2_gurl_; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string request_body_; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string requested_service_; // Currently tracked for IssueAuthToken only. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fetch_pending_; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class GaiaAuthFetcherTest; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CaptchaParse); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDeletedError); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDisabledError); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationError); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, IncomprehensibleError); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ServiceUnavailableError); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckNormalErrorCode); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CheckTwoFactorResponse); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, LoginNetFailure); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseClientLoginToOAuth2Response); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ParseOAuth2TokenPairResponse); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthSuccess); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthWithQuote); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeSuccess); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, ClientOAuthChallengeQuote); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcher); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // GOOGLE_APIS_GAIA_GAIA_AUTH_FETCHER_H_ 400