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 #ifndef COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H
6 #define COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H
10 #include "base/observer_list.h"
11 #include "base/timer/timer.h"
12 #include "components/signin/core/browser/signin_client.h"
13 #include "google_apis/gaia/gaia_auth_consumer.h"
14 #include "google_apis/gaia/gaia_auth_util.h"
15 #include "google_apis/gaia/ubertoken_fetcher.h"
16 #include "net/base/backoff_entry.h"
17 #include "net/url_request/url_fetcher_delegate.h"
19 class GaiaAuthFetcher
;
20 class GaiaCookieRequest
;
21 class GoogleServiceAuthError
;
22 class OAuth2TokenService
;
28 // Merges a Google account known to Chrome into the cookie jar. When merging
29 // multiple accounts, one instance of the helper is better than multiple
30 // instances if there is the possibility that they run concurrently, since
31 // changes to the cookie must be serialized.
33 // Also checks the External CC result to ensure no services that consume the
34 // GAIA cookie are blocked (such as youtube). This is executed once for the
35 // lifetime of this object, when the first call is made to AddAccountToCookie.
36 class GaiaCookieManagerService
: public KeyedService
,
37 public GaiaAuthConsumer
,
38 public UbertokenConsumer
{
40 enum GaiaCookieRequestType
{
46 // Contains the information and parameters for any request.
47 class GaiaCookieRequest
{
51 GaiaCookieRequestType
request_type() const { return request_type_
; }
52 const std::string
& account_id() const {return account_id_
; }
54 static GaiaCookieRequest
CreateAddAccountRequest(
55 const std::string
& account_id
);
56 static GaiaCookieRequest
CreateLogOutRequest();
57 static GaiaCookieRequest
CreateListAccountsRequest();
61 GaiaCookieRequestType request_type
,
62 const std::string
& account_id
);
64 GaiaCookieRequestType request_type_
;
65 std::string account_id_
;
70 // Called whenever a merge session is completed. The account that was
71 // merged is given by |account_id|. If |error| is equal to
72 // GoogleServiceAuthError::AuthErrorNone() then the merge succeeeded.
73 virtual void OnAddAccountToCookieCompleted(
74 const std::string
& account_id
,
75 const GoogleServiceAuthError
& error
) {}
77 // Called whenever the GaiaCookieManagerService's list of GAIA accounts is
78 // updated. The GCMS monitors the APISID cookie and triggers a /ListAccounts
79 // call on change. The GCMS will also call ListAccounts upon the first call
80 // to ListAccounts(). The GCMS will delay calling ListAccounts if other
81 // requests are in queue that would modify the APISID cookie.
82 // If the ListAccounts call fails and the GCMS cannot recover, the reason
83 // is passed in |error|.
84 virtual void OnGaiaAccountsInCookieUpdated(
85 const std::vector
<gaia::ListedAccount
>& accounts
,
86 const GoogleServiceAuthError
& error
) {}
89 virtual ~Observer() {}
92 // Class to retrieve the external connection check results from gaia.
93 // Declared publicly for unit tests.
94 class ExternalCcResultFetcher
: public GaiaAuthConsumer
,
95 public net::URLFetcherDelegate
{
97 // Maps connection URLs, as returned by StartGetCheckConnectionInfo() to
98 // token and URLFetcher used to fetch the URL.
99 typedef std::map
<GURL
, std::pair
<std::string
, net::URLFetcher
*>>
100 URLToTokenAndFetcher
;
102 // Maps tokens to the fetched result for that token.
103 typedef std::map
<std::string
, std::string
> ResultMap
;
105 ExternalCcResultFetcher(GaiaCookieManagerService
* helper
);
106 ~ExternalCcResultFetcher() override
;
108 // Gets the current value of the external connection check result string.
109 std::string
GetExternalCcResult();
111 // Start fetching the external CC result. If a fetch is already in progress
115 // Are external URLs still being checked?
118 // Returns a copy of the internal token to fetcher map.
119 URLToTokenAndFetcher
get_fetcher_map_for_testing() { return fetchers_
; }
121 // Simulate a timeout for tests.
122 void TimeoutForTests();
125 // Overridden from GaiaAuthConsumer.
126 void OnGetCheckConnectionInfoSuccess(const std::string
& data
) override
;
127 void OnGetCheckConnectionInfoError(
128 const GoogleServiceAuthError
& error
) override
;
130 // Creates and initializes a URL fetcher for doing a connection check.
131 scoped_ptr
<net::URLFetcher
> CreateFetcher(const GURL
& url
);
133 // Overridden from URLFetcherDelgate.
134 void OnURLFetchComplete(const net::URLFetcher
* source
) override
;
136 // Any fetches still ongoing after this call are considered timed out.
139 void CleanupTransientState();
141 void GetCheckConnectionInfoCompleted(bool succeeded
);
143 GaiaCookieManagerService
* helper_
;
144 base::OneShotTimer
<ExternalCcResultFetcher
> timer_
;
145 URLToTokenAndFetcher fetchers_
;
147 base::Time m_external_cc_result_start_time_
;
149 base::OneShotTimer
<ExternalCcResultFetcher
> gaia_auth_fetcher_timer_
;
151 DISALLOW_COPY_AND_ASSIGN(ExternalCcResultFetcher
);
154 GaiaCookieManagerService(OAuth2TokenService
* token_service
,
155 const std::string
& source
,
156 SigninClient
* signin_client
);
157 ~GaiaCookieManagerService() override
;
160 void Shutdown() override
;
162 void AddAccountToCookie(const std::string
& account_id
);
163 void AddAccountToCookieWithToken(const std::string
& account_id
,
164 const std::string
& access_token
);
166 // Returns if the listed accounts are up to date or not (ignore the out
167 // parameter if return is false). The parameter will be assigned the current
168 // cached accounts. If the accounts are not up to date, a ListAccounts fetch
169 // is sent GAIA and Observer::OnGaiaAccountsInCookieUpdated will be called.
170 bool ListAccounts(std::vector
<gaia::ListedAccount
>* accounts
);
172 // Add or remove observers of this helper.
173 void AddObserver(Observer
* observer
);
174 void RemoveObserver(Observer
* observer
);
176 // Cancel all login requests.
179 // Signout all accounts.
180 void LogOutAllAccounts();
182 // Call observers when merge session completes. This public so that callers
183 // that know that a given account is already in the cookie jar can simply
184 // inform the observers.
185 void SignalComplete(const std::string
& account_id
,
186 const GoogleServiceAuthError
& error
);
188 // Returns true of there are pending log ins or outs.
189 bool is_running() const { return requests_
.size() > 0; }
191 // Access the internal object during tests.
192 ExternalCcResultFetcher
* external_cc_result_fetcher_for_testing() {
193 return &external_cc_result_fetcher_
;
196 void set_list_accounts_fetched_once_for_testing(bool fetched
) {
197 list_accounts_fetched_once_
= fetched
;
201 net::URLRequestContextGetter
* request_context() {
202 return signin_client_
->GetURLRequestContext();
205 // Called when a cookie changes. If the cookie relates to a GAIA APISID
206 // cookie, then we call ListAccounts and fire OnGaiaAccountsInCookieUpdated.
207 void OnCookieChanged(const net::CanonicalCookie
& cookie
, bool removed
);
209 // Overridden from UbertokenConsumer.
210 void OnUbertokenSuccess(const std::string
& token
) override
;
211 void OnUbertokenFailure(const GoogleServiceAuthError
& error
) override
;
213 // Overridden from GaiaAuthConsumer.
214 void OnMergeSessionSuccess(const std::string
& data
) override
;
215 void OnMergeSessionFailure(const GoogleServiceAuthError
& error
) override
;
216 void OnListAccountsSuccess(const std::string
& data
) override
;
217 void OnListAccountsFailure(const GoogleServiceAuthError
& error
) override
;
218 void OnLogOutSuccess() override
;
219 void OnLogOutFailure(const GoogleServiceAuthError
& error
) override
;
221 // Helper method for AddAccountToCookie* methods.
222 void AddAccountToCookieInternal(const std::string
& account_id
);
224 // Starts the proess of fetching the uber token and performing a merge session
225 // for the next account. Virtual so that it can be overriden in tests.
226 virtual void StartFetchingUbertoken();
228 // Virtual for testing purposes.
229 virtual void StartFetchingMergeSession();
231 // Virtual for testing purposes.
232 virtual void StartFetchingListAccounts();
234 // Virtual for testing purpose.
235 virtual void StartFetchingLogOut();
237 // Start the next request, if needed.
238 void HandleNextRequest();
240 OAuth2TokenService
* token_service_
;
241 SigninClient
* signin_client_
;
242 scoped_ptr
<GaiaAuthFetcher
> gaia_auth_fetcher_
;
243 scoped_ptr
<UbertokenFetcher
> uber_token_fetcher_
;
244 ExternalCcResultFetcher external_cc_result_fetcher_
;
246 // If the GaiaAuthFetcher or URLFetcher fails, retry with exponential backoff
247 // and network delay.
248 net::BackoffEntry fetcher_backoff_
;
249 // We can safely depend on the SigninClient here because there is an explicit
250 // dependency, as noted in the GaiaCookieManagerServiceFactory.
251 base::OneShotTimer
<SigninClient
> fetcher_timer_
;
252 int fetcher_retries_
;
254 // The last fetched ubertoken, for use in MergeSession retries.
255 std::string uber_token_
;
257 // The access token that can be used to prime the UberToken fetch.
258 std::string access_token_
;
260 // Subscription to be called whenever the GAIA cookies change.
261 scoped_ptr
<SigninClient::CookieChangedSubscription
>
262 cookie_changed_subscription_
;
264 // A worklist for this class. Stores any pending requests that couldn't be
265 // executed right away, since this class only permits one request to be
266 // executed at a time.
267 std::deque
<GaiaCookieRequest
> requests_
;
269 // List of observers to notify when merge session completes.
270 // Makes sure list is empty on destruction.
271 base::ObserverList
<Observer
, true> observer_list_
;
273 // Source to use with GAIA endpoints for accounting.
276 // True once the ExternalCCResultFetcher has completed once.
277 bool external_cc_result_fetched_
;
279 std::vector
<gaia::ListedAccount
> listed_accounts_
;
281 bool list_accounts_fetched_once_
;
283 DISALLOW_COPY_AND_ASSIGN(GaiaCookieManagerService
);
286 #endif // COMPONENTS_SIGNIN_CORE_BROWSER_GAIA_COOKIE_MANAGER_SERVICE_H