Commit 03608d8b authored by rogerta@chromium.org's avatar rogerta@chromium.org

Enable account reconcilor when --new-profile-management is used.

Move mergesession from SigninManager to reconcilor.
Implement ListAccounts.
Start implementing reconcile action, but still a noop for now.

This CL depends on https://codereview.chromium.org/57103002/

Alan: here is an implementation of the ListAccounts.  I also added lots of
DVLOG() to the code.  Let me know if you'd rather I took those out and put
in a separate CL.

Hui: please review.  This CL adds more functionality to the reconcilor but
its still not complete.  However, it enables AC behind the flag for merge
session so you don't need to do that manually.

BUG=305249

Review URL: https://codereview.chromium.org/57363003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233424 0039d316-1c4b-4281-b951-d872f2087c98
parent 4ecd01b1
......@@ -33,6 +33,7 @@
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/profiles/startup_task_runner_service.h"
#include "chrome/browser/profiles/startup_task_runner_service_factory.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser.h"
......@@ -818,6 +819,9 @@ void ProfileManager::DoFinalInitForServices(Profile* profile,
// Start the deferred task runners once the profile is loaded.
StartupTaskRunnerServiceFactory::GetForProfile(profile)->
StartDeferredTaskRunners();
if (profiles::IsNewProfileManagementEnabled())
AccountReconcilorFactory::GetForProfile(profile);
}
void ProfileManager::DoFinalInitLogging(Profile* profile) {
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
......@@ -16,21 +17,45 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_constants.h"
AccountReconcilor::AccountReconcilor(Profile* profile) : profile_(profile) {
AccountReconcilor::AccountReconcilor(Profile* profile)
: profile_(profile),
are_gaia_accounts_set_(false),
requests_(NULL) {
RegisterWithSigninManager();
RegisterWithCookieMonster();
// If this profile is not connected, the reconcilor should do nothing but
// wait for the connection.
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile_);
if (!signin_manager->GetAuthenticatedUsername().empty()) {
if (IsProfileConnected()) {
RegisterWithTokenService();
StartPeriodicReconciliation();
}
}
AccountReconcilor::~AccountReconcilor() {
// Make sure shutdown was called first.
DCHECK(registrar_.IsEmpty());
DCHECK(!reconciliation_timer_.IsRunning());
DCHECK(!requests_);
}
void AccountReconcilor::Shutdown() {
DVLOG(1) << "AccountReconcilor::Shutdown";
DeleteAccessTokenRequests();
UnregisterWithSigninManager();
UnregisterWithTokenService();
UnregisterWithCookieMonster();
StopPeriodicReconciliation();
}
void AccountReconcilor::DeleteAccessTokenRequests() {
delete[] requests_;
requests_ = NULL;
}
void AccountReconcilor::RegisterWithCookieMonster() {
content::Source<Profile> source(profile_);
registrar_.Add(this, chrome::NOTIFICATION_COOKIE_CHANGED, source);
......@@ -66,21 +91,29 @@ void AccountReconcilor::UnregisterWithTokenService() {
token_service->RemoveObserver(this);
}
bool AccountReconcilor::IsProfileConnected() {
return !SigninManagerFactory::GetForProfile(profile_)->
GetAuthenticatedUsername().empty();
}
void AccountReconcilor::StartPeriodicReconciliation() {
DVLOG(1) << "AccountReconcilor::StartPeriodicReconciliation";
// TODO(rogerta): pick appropriate thread and timeout value.
reconciliation_timer_.Start(
FROM_HERE,
base::TimeDelta::FromMinutes(5),
base::TimeDelta::FromSeconds(300),
this,
&AccountReconcilor::PeriodicReconciliation);
}
void AccountReconcilor::StopPeriodicReconciliation() {
DVLOG(1) << "AccountReconcilor::StopPeriodicReconciliation";
reconciliation_timer_.Stop();
}
void AccountReconcilor::PeriodicReconciliation() {
PerformReconcileAction();
DVLOG(1) << "AccountReconcilor::PeriodicReconciliation";
StartReconcileAction();
}
void AccountReconcilor::Observe(int type,
......@@ -88,10 +121,12 @@ void AccountReconcilor::Observe(int type,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL:
DVLOG(1) << "AccountReconcilor::Observe: signed in";
RegisterWithTokenService();
StartPeriodicReconciliation();
break;
case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
DVLOG(1) << "AccountReconcilor::Observe: signed out";
UnregisterWithTokenService();
StopPeriodicReconciliation();
break;
......@@ -106,14 +141,16 @@ void AccountReconcilor::Observe(int type,
void AccountReconcilor::OnCookieChanged(ChromeCookieDetails* details) {
// TODO(acleung): Filter out cookies by looking at the domain.
// PerformReconcileAction();
// StartReconcileAction();
}
void AccountReconcilor::OnRefreshTokenAvailable(const std::string& account_id) {
DVLOG(1) << "AccountReconcilor::OnRefreshTokenAvailable: " << account_id;
PerformMergeAction(account_id);
}
void AccountReconcilor::OnRefreshTokenRevoked(const std::string& account_id) {
DVLOG(1) << "AccountReconcilor::OnRefreshTokenRevoked: " << account_id;
PerformRemoveAction(account_id);
}
......@@ -129,18 +166,157 @@ void AccountReconcilor::PerformRemoveAction(const std::string& account_id) {
// TODO(acleung): Implement this:
}
void AccountReconcilor::PerformReconcileAction() {
// TODO(acleung): Implement this:
void AccountReconcilor::StartReconcileAction() {
if (!IsProfileConnected())
return;
// Reset state for validating gaia cookie.
are_gaia_accounts_set_ = false;
gaia_accounts_.clear();
GetAccountsFromCookie();
// Reset state for validating oauth2 tokens.
primary_account_.clear();
chrome_accounts_.clear();
DeleteAccessTokenRequests();
valid_chrome_accounts_.clear();
invalid_chrome_accounts_.clear();
ValidateAccountsFromTokenService();
}
AccountReconcilor::~AccountReconcilor() {
// Make sure shutdown was called first.
DCHECK(registrar_.IsEmpty());
void AccountReconcilor::GetAccountsFromCookie() {
gaia_fetcher_.reset(new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
profile_->GetRequestContext()));
gaia_fetcher_->StartListAccounts();
}
void AccountReconcilor::Shutdown() {
UnregisterWithSigninManager();
UnregisterWithTokenService();
UnregisterWithCookieMonster();
StopPeriodicReconciliation();
void AccountReconcilor::OnListAccountsSuccess(const std::string& data) {
gaia_fetcher_.reset();
// Get account information from response data.
gaia_accounts_ = ParseListAccountsData(data);
if (gaia_accounts_.size() > 0) {
DVLOG(1) << "AccountReconcilor::OnListAccountsSuccess: "
<< "Gaia " << gaia_accounts_.size() << " accounts, "
<< "Primary is '" << gaia_accounts_[0] << "'";
} else {
DVLOG(1) << "AccountReconcilor::OnListAccountsSuccess: No accounts";
}
are_gaia_accounts_set_ = true;
FinishReconcileAction();
}
// static
std::vector<std::string> AccountReconcilor::ParseListAccountsData(
const std::string& data) {
std::vector<std::string> account_ids;
// Parse returned data and make sure we have data.
scoped_ptr<base::Value> value(base::JSONReader::Read(data));
if (!value)
return account_ids;
base::ListValue* list;
if (!value->GetAsList(&list) || list->GetSize() < 2)
return account_ids;
// Get list of account info.
base::ListValue* accounts;
if (!list->GetList(1, &accounts) || accounts == NULL)
return account_ids;
// Build a vector of accounts from the cookie. Order is important: the first
// account in the list is the primary account.
for (size_t i = 0; i < accounts->GetSize(); ++i) {
base::ListValue* account;
if (accounts->GetList(i, &account) && account != NULL) {
std::string email;
if (account->GetString(3, &email) && !email.empty())
account_ids.push_back(email);
}
}
return account_ids;
}
void AccountReconcilor::OnListAccountsFailure(
const GoogleServiceAuthError& error) {
gaia_fetcher_.reset();
DVLOG(1) << "AccountReconcilor::OnListAccountsFailure: " << error.ToString();
are_gaia_accounts_set_ = true;
FinishReconcileAction();
}
void AccountReconcilor::ValidateAccountsFromTokenService() {
primary_account_ =
SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername();
DCHECK(!primary_account_.empty());
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
chrome_accounts_ = token_service->GetAccounts();
DCHECK(chrome_accounts_.size() > 0);
DVLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: "
<< "Chrome " << chrome_accounts_.size() << " accounts, "
<< "Primary is '" << primary_account_ << "'";
DCHECK(!requests_);
requests_ =
new scoped_ptr<OAuth2TokenService::Request>[chrome_accounts_.size()];
for (size_t i = 0; i < chrome_accounts_.size(); ++i) {
requests_[i] = token_service->StartRequest(chrome_accounts_[i],
OAuth2TokenService::ScopeSet(),
this);
}
}
void AccountReconcilor::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: valid "
<< request->GetAccountId();
valid_chrome_accounts_.insert(request->GetAccountId());
FinishReconcileAction();
}
void AccountReconcilor::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
DVLOG(1) << "AccountReconcilor::OnGetTokenSuccess: invalid "
<< request->GetAccountId();
invalid_chrome_accounts_.insert(request->GetAccountId());
FinishReconcileAction();
}
void AccountReconcilor::FinishReconcileAction() {
// Make sure that the process of validating the gaia cookie and the oauth2
// tokens individually is done before proceeding with reconciliation.
if (!are_gaia_accounts_set_ ||
(chrome_accounts_.size() != (valid_chrome_accounts_.size() +
invalid_chrome_accounts_.size()))) {
return;
}
DVLOG(1) << "AccountReconcilor::FinishReconcileAction";
bool are_primaries_equal =
gaia_accounts_.size() > 0 && primary_account_ == gaia_accounts_[0];
bool have_same_accounts = chrome_accounts_.size() == gaia_accounts_.size();
if (have_same_accounts) {
for (size_t i = 0; i < gaia_accounts_.size(); ++i) {
if (std::find(chrome_accounts_.begin(), chrome_accounts_.end(),
gaia_accounts_[i]) == chrome_accounts_.end()) {
have_same_accounts = false;
break;
}
}
}
if (!are_primaries_equal || !have_same_accounts) {
// TODO(rogerta): fix things up.
}
}
......@@ -6,16 +6,21 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/oauth2_token_service.h"
class GaiaAuthFetcher;
class Profile;
struct ChromeCookieDetails;
class AccountReconcilor : public BrowserContextKeyedService,
content::NotificationObserver,
GaiaAuthConsumer,
OAuth2TokenService::Consumer,
OAuth2TokenService::Observer {
public:
explicit AccountReconcilor(Profile* profile);
......@@ -31,6 +36,9 @@ class AccountReconcilor : public BrowserContextKeyedService,
}
private:
class AccountReconcilorTest;
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ParseListAccountsData);
// Register and unregister with dependent services.
void RegisterWithCookieMonster();
void UnregisterWithCookieMonster();
......@@ -39,32 +47,69 @@ class AccountReconcilor : public BrowserContextKeyedService,
void RegisterWithTokenService();
void UnregisterWithTokenService();
bool IsProfileConnected();
void DeleteAccessTokenRequests();
static std::vector<std::string> ParseListAccountsData(
const std::string& data);
// Start and stop the periodic reconciliation.
void StartPeriodicReconciliation();
void StopPeriodicReconciliation();
void PeriodicReconciliation();
// The profile that this reconcilor belongs to.
Profile* profile_;
content::NotificationRegistrar registrar_;
base::RepeatingTimer<AccountReconcilor> reconciliation_timer_;
void PerformMergeAction(const std::string& account_id);
void PerformRemoveAction(const std::string& account_id);
void PerformReconcileAction();
void StartReconcileAction();
void FinishReconcileAction();
void GetAccountsFromCookie();
void ValidateAccountsFromTokenService();
void OnCookieChanged(ChromeCookieDetails* details);
// Overriden from content::NotificationObserver
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
void OnCookieChanged(ChromeCookieDetails* details);
// Overriden from OAuth2TokenService::Consumer
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) OVERRIDE;
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
// Overriden from OAuth2TokenService::Observer
virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
virtual void OnRefreshTokensLoaded() OVERRIDE;
// Overriden from GaiaAuthConsumer
virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
virtual void OnListAccountsFailure(
const GoogleServiceAuthError& error) OVERRIDE;
// The profile that this reconcilor belongs to.
Profile* profile_;
content::NotificationRegistrar registrar_;
base::RepeatingTimer<AccountReconcilor> reconciliation_timer_;
// Used during reconcile action.
// These members are used used to validate the gaia cookie.
scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
bool are_gaia_accounts_set_;
std::vector<std::string> gaia_accounts_;
// Used during reconcile action.
// These members are used to validate the tokens in OAuth2TokenService.
std::string primary_account_;
std::vector<std::string> chrome_accounts_;
scoped_ptr<OAuth2TokenService::Request>* requests_;
std::set<std::string> valid_chrome_accounts_;
std::set<std::string> invalid_chrome_accounts_;
DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
};
......
......@@ -101,3 +101,37 @@ TEST_F(AccountReconcilorTest, ProfileAlreadyConnected) {
ASSERT_TRUE(NULL != reconcilor);
ASSERT_TRUE(reconcilor->IsPeriodicReconciliationRunning());
}
TEST_F(AccountReconcilorTest, ParseListAccountsData) {
std::vector<std::string> accounts;
accounts = AccountReconcilor::ParseListAccountsData("");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData("1");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData("[]");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData("[\"foo\", \"bar\"]");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData("[\"foo\", []]");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData(
"[\"foo\", [[\"bar\", 0, \"name\", 0, \"photo\", 0, 0, 0]]]");
ASSERT_EQ(0u, accounts.size());
accounts = AccountReconcilor::ParseListAccountsData(
"[\"foo\", [[\"bar\", 0, \"name\", \"email\", \"photo\", 0, 0, 0]]]");
ASSERT_EQ(1u, accounts.size());
ASSERT_EQ("email", accounts[0]);
accounts = AccountReconcilor::ParseListAccountsData(
"[\"foo\", [[\"bar1\", 0, \"name1\", \"email1\", \"photo1\", 0, 0, 0], "
"[\"bar2\", 0, \"name2\", \"email2\", \"photo2\", 0, 0, 0]]]");
ASSERT_EQ(2u, accounts.size());
ASSERT_EQ("email1", accounts[0]);
ASSERT_EQ("email2", accounts[1]);
}
......@@ -611,35 +611,6 @@ void SigninManager::OnSignedIn(const std::string& username) {
}
password_.clear(); // Don't need it anymore.
DisableOneClickSignIn(profile_); // Don't ever offer again.
if (type_ == SIGNIN_TYPE_WITH_OAUTH_CODE &&
!temp_oauth_login_tokens_.access_token.empty())
// Cookie jar may not be set up properly, need to first get an uber token
// and then merge sessions with the token.
client_login_->StartTokenFetchForUberAuthExchange(
temp_oauth_login_tokens_.access_token);
}
void SigninManager::OnUberAuthTokenSuccess(const std::string& token) {
DVLOG(1) << "SigninManager::OnUberAuthTokenSuccess";
NotifyDiagnosticsObservers(UBER_TOKEN_STATUS, "Successful");
client_login_->StartMergeSession(token);
}
void SigninManager::OnMergeSessionSuccess(const std::string& data) {
DVLOG(1) << "SigninManager::OnMergeSessionSuccess";
NotifyDiagnosticsObservers(MERGE_SESSION_STATUS, "Successful");
}
void SigninManager::OnMergeSessionFailure(const GoogleServiceAuthError& error) {
LOG(ERROR) << "Unable to mereg sessions. Login failed.";
NotifyDiagnosticsObservers(MERGE_SESSION_STATUS, error.ToString());
}
void SigninManager::OnUberAuthTokenFailure(
const GoogleServiceAuthError& error) {
LOG(ERROR) << "Unable to retreive the uber token. Login failed.";
NotifyDiagnosticsObservers(UBER_TOKEN_STATUS, error.ToString());
}
void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
......
......@@ -154,12 +154,6 @@ class SigninManager : public SigninManagerBase,
virtual void OnGetUserInfoSuccess(const UserInfoMap& data) OVERRIDE;
virtual void OnGetUserInfoFailure(
const GoogleServiceAuthError& error) OVERRIDE;
virtual void OnUberAuthTokenSuccess(const std::string& token) OVERRIDE;
virtual void OnUberAuthTokenFailure(
const GoogleServiceAuthError& error) OVERRIDE;
virtual void OnMergeSessionSuccess(const std::string& data) OVERRIDE;
virtual void OnMergeSessionFailure(
const GoogleServiceAuthError& error) OVERRIDE;
// content::NotificationObserver
virtual void Observe(int type,
......
......@@ -82,6 +82,9 @@ class GaiaAuthConsumer {
virtual void OnMergeSessionSuccess(const std::string& data) {}
virtual void OnMergeSessionFailure(const GoogleServiceAuthError& error) {}
virtual void OnListAccountsSuccess(const std::string& data) {}
virtual void OnListAccountsFailure(const GoogleServiceAuthError& error) {}
};
#endif // GOOGLE_APIS_GAIA_GAIA_AUTH_CONSUMER_H_
......@@ -182,6 +182,7 @@ GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer,
uberauth_token_gurl_(GaiaUrls::GetInstance()->oauth1_login_url().Resolve(
base::StringPrintf(kUberAuthTokenURLFormat, source.c_str()))),
oauth_login_gurl_(GaiaUrls::GetInstance()->oauth1_login_url()),
list_accounts_gurl_(GaiaUrls::GetInstance()->list_accounts_url()),
client_login_to_oauth2_gurl_(
GaiaUrls::GetInstance()->client_login_to_oauth2_url()),
fetch_pending_(false) {}
......@@ -659,6 +660,19 @@ void GaiaAuthFetcher::StartOAuthLogin(const std::string& access_token,
fetcher_->Start();
}
void GaiaAuthFetcher::StartListAccounts() {
DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
fetcher_.reset(CreateGaiaFetcher(getter_,
" ", // To force an HTTP POST.
"Origin: https://www.google.com",
list_accounts_gurl_,
net::LOAD_NORMAL,
this));
fetch_pending_ = true;
fetcher_->Start();
}
// static
GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError(
const std::string& data,
......@@ -844,6 +858,16 @@ void GaiaAuthFetcher::OnOAuth2RevokeTokenFetched(
consumer_->OnOAuth2RevokeTokenCompleted();
}
void GaiaAuthFetcher::OnListAccountsFetched(const std::string& data,
const net::URLRequestStatus& status,
int response_code) {
if (status.is_success() && response_code == net::HTTP_OK) {
consumer_->OnListAccountsSuccess(data);
} else {
consumer_->OnListAccountsFailure(GenerateAuthError(data, status));
}
}
void GaiaAuthFetcher::OnGetUserInfoFetched(
const std::string& data,
const net::URLRequestStatus& status,
......@@ -937,6 +961,8 @@ void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
OnOAuthLoginFetched(data, status, response_code);
} else if (url == oauth2_revoke_gurl_) {
OnOAuth2RevokeTokenFetched(data, status, response_code);
} else if (url == list_accounts_gurl_) {
OnListAccountsFetched(data, status, response_code);
} else {
NOTREACHED();
}
......
......@@ -158,6 +158,9 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
void StartOAuthLogin(const std::string& access_token,
const std::string& service);
// Starts a request to list the accounts in the GAIA cookie.
void StartListAccounts();
// Implementation of net::URLFetcherDelegate
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
......@@ -253,6 +256,10 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
const net::URLRequestStatus& status,
int response_code);
void OnListAccountsFetched(const std::string& data,
const net::URLRequestStatus& status,
int response_code);
void OnGetUserInfoFetched(const std::string& data,
const net::URLRequestStatus& status,
int response_code);
......@@ -359,6 +366,7 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
const GURL merge_session_gurl_;
const GURL uberauth_token_gurl_;
const GURL oauth_login_gurl_;
const GURL list_accounts_gurl_;
// While a fetch is going on:
scoped_ptr<net::URLFetcher> fetcher_;
......
......@@ -187,6 +187,7 @@ class MockGaiaConsumer : public GaiaAuthConsumer {
const GoogleServiceAuthError& error));
MOCK_METHOD1(OnUberAuthTokenFailure, void(
const GoogleServiceAuthError& error));
MOCK_METHOD1(OnListAccountsSuccess, void(const std::string& data));
};
#if defined(OS_WIN)
......@@ -789,3 +790,17 @@ TEST_F(GaiaAuthFetcherTest, StartOAuthLogin) {
net::URLFetcher::GET, &auth);
auth.OnURLFetchComplete(&mock_fetcher);
}
TEST_F(GaiaAuthFetcherTest, ListAccounts) {
std::string data("[\"gaia.l.a.r\", ["
"[\"gaia.l.a\", 1, \"First Last\", \"user@gmail.com\", "
"\"//googleusercontent.com/A/B/C/D/photo.jpg\", 1, 1, 0]]]");
MockGaiaConsumer consumer;
EXPECT_CALL(consumer, OnListAccountsSuccess(data)).Times(1);
GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext());
net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
MockFetcher mock_fetcher(GaiaUrls::GetInstance()->list_accounts_url(),
status, net::HTTP_OK, cookies_, data, net::URLFetcher::GET, &auth);
auth.OnURLFetchComplete(&mock_fetcher);
}
......@@ -28,6 +28,7 @@ const char kOAuthGetAccessTokenUrlSuffix[] = "OAuthGetAccessToken";
const char kOAuthWrapBridgeUrlSuffix[] = "OAuthWrapBridge";
const char kOAuth1LoginUrlSuffix[] = "OAuthLogin";
const char kOAuthRevokeTokenUrlSuffix[] = "AuthSubRevokeToken";
const char kListAccountsSuffix[] = "ListAccounts";
// OAuth scopes
const char kOAuth1LoginScope[] = "https://www.google.com/accounts/OAuthLogin";
......@@ -103,6 +104,7 @@ GaiaUrls::GaiaUrls() {
oauth_wrap_bridge_url_ = gaia_url_.Resolve(kOAuthWrapBridgeUrlSuffix);
oauth_revoke_token_url_ = gaia_url_.Resolve(kOAuthRevokeTokenUrlSuffix);
oauth1_login_url_ = gaia_url_.Resolve(kOAuth1LoginUrlSuffix);
list_accounts_url_ = gaia_url_.Resolve(kListAccountsSuffix);
// URLs from accounts.google.com (LSO).
get_oauth_token_url_ = lso_origin_url_.Resolve(kGetOAuthTokenUrlSuffix);
......@@ -198,6 +200,10 @@ const GURL& GaiaUrls::oauth1_login_url() const {
return oauth1_login_url_;
}
const GURL& GaiaUrls::list_accounts_url() const {
return list_accounts_url_;
}
const std::string& GaiaUrls::oauth1_login_scope() const {
return oauth1_login_scope_;
}
......
......@@ -32,6 +32,7 @@ class GaiaUrls {
const GURL& oauth_user_info_url() const;
const GURL& oauth_revoke_token_url() const;
const GURL& oauth1_login_url() const;
const GURL& list_accounts_url() const;
const std::string& oauth1_login_scope() const;
const std::string& oauth_wrap_bridge_user_info_scope() const;
......@@ -73,6 +74,7 @@ class GaiaUrls {
GURL oauth_user_info_url_;
GURL oauth_revoke_token_url_;
GURL oauth1_login_url_;
GURL list_accounts_url_;
std::string oauth1_login_scope_;
std::string oauth_wrap_bridge_user_info_scope_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment