merge_session_helper.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright 2014 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/merge_session_helper.h" 6 7#include "google_apis/gaia/gaia_auth_fetcher.h" 8#include "google_apis/gaia/gaia_constants.h" 9#include "google_apis/gaia/gaia_urls.h" 10#include "google_apis/gaia/oauth2_token_service.h" 11#include "net/url_request/url_fetcher.h" 12#include "net/url_request/url_fetcher_delegate.h" 13 14MergeSessionHelper::MergeSessionHelper( 15 OAuth2TokenService* token_service, 16 net::URLRequestContextGetter* request_context, 17 Observer* observer) 18 : token_service_(token_service), 19 request_context_(request_context) { 20 if (observer) 21 AddObserver(observer); 22} 23 24MergeSessionHelper::~MergeSessionHelper() { 25 DCHECK(accounts_.empty()); 26} 27 28void MergeSessionHelper::LogIn(const std::string& account_id) { 29 DCHECK(!account_id.empty()); 30 VLOG(1) << "MergeSessionHelper::LogIn: " << account_id; 31 accounts_.push_back(account_id); 32 if (accounts_.size() == 1) 33 StartFetching(); 34} 35 36void MergeSessionHelper::AddObserver(Observer* observer) { 37 observer_list_.AddObserver(observer); 38} 39 40void MergeSessionHelper::RemoveObserver(Observer* observer) { 41 observer_list_.RemoveObserver(observer); 42} 43 44void MergeSessionHelper::CancelAll() { 45 VLOG(1) << "MergeSessionHelper::CancelAll"; 46 gaia_auth_fetcher_.reset(); 47 uber_token_fetcher_.reset(); 48 accounts_.clear(); 49} 50 51void MergeSessionHelper::LogOut( 52 const std::string& account_id, 53 const std::vector<std::string>& accounts) { 54 DCHECK(!account_id.empty()); 55 VLOG(1) << "MergeSessionHelper::LogOut: " << account_id 56 << " accounts=" << accounts.size(); 57 LogOutInternal(account_id, accounts); 58} 59 60void MergeSessionHelper::LogOutInternal( 61 const std::string& account_id, 62 const std::vector<std::string>& accounts) { 63 bool pending = !accounts_.empty(); 64 65 if (pending) { 66 for (std::deque<std::string>::const_iterator it = accounts_.begin() + 1; 67 it != accounts_.end(); it++) { 68 if (!it->empty() && 69 (std::find(accounts.begin(), accounts.end(), *it) == accounts.end() || 70 *it == account_id)) { 71 // We have a pending log in request for an account followed by 72 // a signout. 73 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); 74 SignalComplete(*it, error); 75 } 76 } 77 78 // Remove every thing in the work list besides the one that is running. 79 accounts_.resize(1); 80 } 81 82 // Signal a logout to be the next thing to do unless the pending 83 // action is already a logout. 84 if (!pending || !accounts_.front().empty()) 85 accounts_.push_back(""); 86 87 for (std::vector<std::string>::const_iterator it = accounts.begin(); 88 it != accounts.end(); it++) { 89 if (*it != account_id) { 90 DCHECK(!it->empty()); 91 accounts_.push_back(*it); 92 } 93 } 94 95 if (!pending) 96 StartLogOutUrlFetch(); 97} 98 99void MergeSessionHelper::LogOutAllAccounts() { 100 VLOG(1) << "MergeSessionHelper::LogOutAllAccounts"; 101 LogOutInternal("", std::vector<std::string>()); 102} 103 104void MergeSessionHelper::SignalComplete( 105 const std::string& account_id, 106 const GoogleServiceAuthError& error) { 107 // Its possible for the observer to delete |this| object. Don't access 108 // access any members after this calling the observer. This method should 109 // be the last call in any other method. 110 FOR_EACH_OBSERVER(Observer, observer_list_, 111 MergeSessionCompleted(account_id, error)); 112} 113 114void MergeSessionHelper::StartLogOutUrlFetch() { 115 DCHECK(accounts_.front().empty()); 116 VLOG(1) << "MergeSessionHelper::StartLogOutUrlFetch"; 117 GURL logout_url(GaiaUrls::GetInstance()->service_logout_url()); 118 net::URLFetcher* fetcher = 119 net::URLFetcher::Create(logout_url, net::URLFetcher::GET, this); 120 fetcher->SetRequestContext(request_context_); 121 fetcher->Start(); 122} 123 124void MergeSessionHelper::OnUbertokenSuccess(const std::string& uber_token) { 125 VLOG(1) << "MergeSessionHelper::OnUbertokenSuccess" 126 << " account=" << accounts_.front(); 127 gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this, 128 GaiaConstants::kChromeSource, 129 request_context_)); 130 gaia_auth_fetcher_->StartMergeSession(uber_token); 131} 132 133void MergeSessionHelper::OnUbertokenFailure( 134 const GoogleServiceAuthError& error) { 135 VLOG(1) << "Failed to retrieve ubertoken" 136 << " account=" << accounts_.front() 137 << " error=" << error.ToString(); 138 const std::string account_id = accounts_.front(); 139 HandleNextAccount(); 140 SignalComplete(account_id, error); 141} 142 143void MergeSessionHelper::OnMergeSessionSuccess(const std::string& data) { 144 VLOG(1) << "MergeSession successful account=" << accounts_.front(); 145 const std::string account_id = accounts_.front(); 146 HandleNextAccount(); 147 SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); 148} 149 150void MergeSessionHelper::OnMergeSessionFailure( 151 const GoogleServiceAuthError& error) { 152 VLOG(1) << "Failed MergeSession" 153 << " account=" << accounts_.front() 154 << " error=" << error.ToString(); 155 const std::string account_id = accounts_.front(); 156 HandleNextAccount(); 157 SignalComplete(account_id, error); 158} 159 160void MergeSessionHelper::StartFetching() { 161 VLOG(1) << "MergeSessionHelper::StartFetching account_id=" 162 << accounts_.front(); 163 uber_token_fetcher_.reset(new UbertokenFetcher(token_service_, 164 this, 165 request_context_)); 166 uber_token_fetcher_->StartFetchingToken(accounts_.front()); 167} 168 169void MergeSessionHelper::OnURLFetchComplete(const net::URLFetcher* source) { 170 DCHECK(accounts_.front().empty()); 171 VLOG(1) << "MergeSessionHelper::OnURLFetchComplete"; 172 HandleNextAccount(); 173} 174 175void MergeSessionHelper::HandleNextAccount() { 176 VLOG(1) << "MergeSessionHelper::HandleNextAccount"; 177 accounts_.pop_front(); 178 gaia_auth_fetcher_.reset(); 179 if (accounts_.empty()) { 180 VLOG(1) << "MergeSessionHelper::HandleNextAccount: no more"; 181 uber_token_fetcher_.reset(); 182 } else { 183 if (accounts_.front().empty()) { 184 StartLogOutUrlFetch(); 185 } else { 186 StartFetching(); 187 } 188 } 189} 190