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