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.
5 #include "google_apis/gaia/merge_session_helper.h"
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"
14 MergeSessionHelper::MergeSessionHelper(
15 OAuth2TokenService* token_service,
16 net::URLRequestContextGetter* request_context,
18 : token_service_(token_service),
19 request_context_(request_context) {
21 AddObserver(observer);
24 MergeSessionHelper::~MergeSessionHelper() {
25 DCHECK(accounts_.empty());
28 void MergeSessionHelper::LogIn(const std::string& account_id) {
29 DCHECK(!account_id.empty());
30 accounts_.push_back(account_id);
31 if (accounts_.size() == 1)
35 void MergeSessionHelper::AddObserver(Observer* observer) {
36 observer_list_.AddObserver(observer);
39 void MergeSessionHelper::RemoveObserver(Observer* observer) {
40 observer_list_.RemoveObserver(observer);
43 void MergeSessionHelper::CancelAll() {
44 gaia_auth_fetcher_.reset();
45 uber_token_fetcher_.reset();
49 void 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);
56 void MergeSessionHelper::LogOutInternal(
57 const std::string& account_id,
58 const std::vector<std::string>& accounts) {
59 bool pending = !accounts_.empty();
62 for (std::deque<std::string>::const_iterator it = accounts_.begin() + 1;
63 it != accounts_.end(); it++) {
65 (std::find(accounts.begin(), accounts.end(), *it) == accounts.end() ||
67 // We have a pending log in request for an account followed by
69 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
70 SignalComplete(*it, error);
74 // Remove every thing in the work list besides the one that is running.
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("");
83 for (std::vector<std::string>::const_iterator it = accounts.begin();
84 it != accounts.end(); it++) {
85 if (*it != account_id) {
87 accounts_.push_back(*it);
92 StartLogOutUrlFetch();
95 void MergeSessionHelper::LogOutAllAccounts() {
96 LogOutInternal("", std::vector<std::string>());
99 void 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));
109 void 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_);
118 void 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,
124 gaia_auth_fetcher_->StartMergeSession(uber_token);
127 void 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();
134 SignalComplete(account_id, error);
137 void MergeSessionHelper::OnMergeSessionSuccess(const std::string& data) {
138 DVLOG(1) << "MergeSession successful account=" << accounts_.front();
139 const std::string account_id = accounts_.front();
141 SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone());
144 void 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();
151 SignalComplete(account_id, error);
154 void MergeSessionHelper::StartFetching() {
155 uber_token_fetcher_.reset(new UbertokenFetcher(token_service_,
158 uber_token_fetcher_->StartFetchingToken(accounts_.front());
161 void MergeSessionHelper::OnURLFetchComplete(const net::URLFetcher* source) {
162 DCHECK(accounts_.front().empty());
166 void MergeSessionHelper::HandleNextAccount() {
167 accounts_.pop_front();
168 gaia_auth_fetcher_.reset();
169 if (accounts_.empty()) {
170 uber_token_fetcher_.reset();
172 if (accounts_.front().empty()) {
173 StartLogOutUrlFetch();