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#ifndef CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_
6#define CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_
7
8#include <map>
9#include <string>
10
11#include "base/memory/scoped_vector.h"
12#include "google_apis/gaia/account_tracker.h"
13#include "google_apis/gaia/oauth2_token_service.h"
14
15namespace gcm {
16
17// Class for reporting back which accounts are signed into. It is only meant to
18// be used when the user is signed into sync.
19class GCMAccountTracker : public gaia::AccountTracker::Observer,
20                          public OAuth2TokenService::Consumer {
21 public:
22  // State of the account.
23  // Allowed transitions:
24  // TOKEN_NEEDED - account info was created.
25  // TOKEN_NEEDED -> GETTING_TOKEN - access token was requested.
26  // GETTING_TOKEN -> TOKEN_NEEDED - access token fetching failed.
27  // GETTING_TOKEN -> TOKEN_PRESENT - access token fetching succeeded.
28  // GETTING_TOKEN -> ACCOUNT_REMOVED - account was removed.
29  // TOKEN_NEEDED -> ACCOUNT_REMOVED - account was removed.
30  // TOKEN_PRESENT -> ACCOUNT_REMOVED - account was removed.
31  enum AccountState {
32    TOKEN_NEEDED,     // Needs a token (AccountInfo was recently created or
33                      // token request failed).
34    GETTING_TOKEN,    // There is a pending token request.
35    TOKEN_PRESENT,    // We have a token for the account.
36    ACCOUNT_REMOVED,  // Account was removed, and we didn't report it yet.
37  };
38
39  // Stores necessary account information and state of token fetching.
40  struct AccountInfo {
41    AccountInfo(const std::string& email, AccountState state);
42    ~AccountInfo();
43
44    // Email address of the tracked account.
45    std::string email;
46    // OAuth2 access token, when |state| is TOKEN_PRESENT.
47    std::string access_token;
48    // Status of the token fetching.
49    AccountState state;
50  };
51
52  // Callback for the GetAccountsForCheckin call. |account_tokens| maps email
53  // addresses to OAuth2 access tokens.
54  typedef base::Callback<void(const std::map<std::string, std::string>&
55                                  account_tokens)> UpdateAccountsCallback;
56
57  // Creates an instance of GCMAccountTracker. |account_tracker| is used to
58  // deliver information about the account, while |callback| will be called
59  // once all of the accounts have been fetched a necessary OAuth2 token, as
60  // many times as the list of accounts is stable, meaning that all accounts
61  // are known and there is no related activity in progress for them, like
62  // fetching OAuth2 tokens.
63  GCMAccountTracker(scoped_ptr<gaia::AccountTracker> account_tracker,
64                    const UpdateAccountsCallback& callback);
65  virtual ~GCMAccountTracker();
66
67  // Shuts down the tracker ensuring a proper clean up. After Shutdown() is
68  // called Start() and Stop() should no longer be used. Must be called before
69  // destruction.
70  void Shutdown();
71
72  // Starts tracking accounts.
73  void Start();
74  // Stops tracking accounts. Cancels all of the pending token requests.
75  void Stop();
76
77 private:
78  // Maps account keys to account states. Keyed by account_ids as used by
79  // OAuth2TokenService.
80  typedef std::map<std::string, AccountInfo> AccountInfos;
81
82  // AccountTracker::Observer overrides.
83  virtual void OnAccountAdded(const gaia::AccountIds& ids) OVERRIDE;
84  virtual void OnAccountRemoved(const gaia::AccountIds& ids) OVERRIDE;
85  virtual void OnAccountSignInChanged(const gaia::AccountIds& ids,
86                                      bool is_signed_in) OVERRIDE;
87
88  // OAuth2TokenService::Consumer overrides.
89  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
90                                 const std::string& access_token,
91                                 const base::Time& expiration_time) OVERRIDE;
92  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
93                                 const GoogleServiceAuthError& error) OVERRIDE;
94
95  // Report the list of accounts with OAuth2 tokens back using the |callback_|
96  // function. If there are token requests in progress, do nothing.
97  void CompleteCollectingTokens();
98  // Deletes a token request. Should be called from OnGetTokenSuccess(..) or
99  // OnGetTokenFailure(..).
100  void DeleteTokenRequest(const OAuth2TokenService::Request* request);
101  // Checks on all known accounts, and calls GetToken(..) for those with
102  // |state == TOKEN_NEEDED|.
103  void GetAllNeededTokens();
104  // Starts fetching the OAuth2 token for the GCM group scope.
105  void GetToken(AccountInfos::iterator& account_iter);
106
107  // Handling of actual sign in and sign out for accounts.
108  void OnAccountSignedIn(const gaia::AccountIds& ids);
109  void OnAccountSignedOut(const gaia::AccountIds& ids);
110
111  OAuth2TokenService* GetTokenService();
112
113  // Account tracker.
114  scoped_ptr<gaia::AccountTracker> account_tracker_;
115
116  // Callback to be called after all of the account and OAuth2 tokens are
117  // collected.
118  UpdateAccountsCallback callback_;
119
120  // State of the account.
121  AccountInfos account_infos_;
122
123  // Indicates whether shutdown has been called.
124  bool shutdown_called_;
125
126  ScopedVector<OAuth2TokenService::Request> pending_token_requests_;
127
128  DISALLOW_COPY_AND_ASSIGN(GCMAccountTracker);
129};
130
131}  // namespace gcm
132
133#endif  // CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_
134