summaryrefslogtreecommitdiffstats
path: root/chrome/browser/services/gcm/gcm_account_tracker.h
blob: 39f357e34c6904765974d8f42a65d5f6aa870e29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_
#define CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_

#include <map>
#include <string>

#include "base/memory/scoped_vector.h"
#include "components/gcm_driver/gcm_client.h"
#include "components/gcm_driver/gcm_connection_observer.h"
#include "google_apis/gaia/account_tracker.h"
#include "google_apis/gaia/oauth2_token_service.h"

namespace base {
class Time;
}

namespace gcm {

class GCMDriver;

// Class for reporting back which accounts are signed into. It is only meant to
// be used when the user is signed into sync.
//
// This class makes a check for tokens periodically, to make sure the user is
// still logged into the profile, so that in the case that the user is not, we
// can immediately report that to the GCM and stop messages addressed to that
// user from ever reaching Chrome.
class GCMAccountTracker : public gaia::AccountTracker::Observer,
                          public OAuth2TokenService::Consumer,
                          public GCMConnectionObserver {
 public:
  // State of the account.
  // Allowed transitions:
  // TOKEN_NEEDED - account info was created.
  // TOKEN_NEEDED -> GETTING_TOKEN - access token was requested.
  // GETTING_TOKEN -> TOKEN_NEEDED - access token fetching failed.
  // GETTING_TOKEN -> TOKEN_PRESENT - access token fetching succeeded.
  // GETTING_TOKEN -> ACCOUNT_REMOVED - account was removed.
  // TOKEN_NEEDED -> ACCOUNT_REMOVED - account was removed.
  // TOKEN_PRESENT -> ACCOUNT_REMOVED - account was removed.
  enum AccountState {
    TOKEN_NEEDED,     // Needs a token (AccountInfo was recently created or
                      // token request failed).
    GETTING_TOKEN,    // There is a pending token request.
    TOKEN_PRESENT,    // We have a token for the account.
    ACCOUNT_REMOVED,  // Account was removed, and we didn't report it yet.
  };

  // Stores necessary account information and state of token fetching.
  struct AccountInfo {
    AccountInfo(const std::string& email, AccountState state);
    ~AccountInfo();

    // Email address of the tracked account.
    std::string email;
    // OAuth2 access token, when |state| is TOKEN_PRESENT.
    std::string access_token;
    // Expiration time of the access tokens.
    base::Time expiration_time;
    // Status of the token fetching.
    AccountState state;
  };

  // |account_tracker| is used to deliver information about the accounts present
  // in the browser context to |driver|.
  GCMAccountTracker(scoped_ptr<gaia::AccountTracker> account_tracker,
                    GCMDriver* driver);
  ~GCMAccountTracker() override;

  // Shuts down the tracker ensuring a proper clean up. After Shutdown() is
  // called Start() and Stop() should no longer be used. Must be called before
  // destruction.
  void Shutdown();

  // Starts tracking accounts.
  void Start();

  // Gets the number of pending token requests. Only used for testing.
  size_t get_pending_token_request_count() const {
    return pending_token_requests_.size();
  }

 private:
  friend class GCMAccountTrackerTest;

  // Maps account keys to account states. Keyed by account_ids as used by
  // OAuth2TokenService.
  typedef std::map<std::string, AccountInfo> AccountInfos;

  // AccountTracker::Observer overrides.
  void OnAccountAdded(const gaia::AccountIds& ids) override;
  void OnAccountRemoved(const gaia::AccountIds& ids) override;
  void OnAccountSignInChanged(const gaia::AccountIds& ids,
                              bool is_signed_in) override;

  // OAuth2TokenService::Consumer overrides.
  void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
                         const std::string& access_token,
                         const base::Time& expiration_time) override;
  void OnGetTokenFailure(const OAuth2TokenService::Request* request,
                         const GoogleServiceAuthError& error) override;

  // GCMConnectionObserver overrides.
  void OnConnected(const net::IPEndPoint& ip_endpoint) override;
  void OnDisconnected() override;

  // Schedules token reporting.
  void ScheduleReportTokens();
  // Report the list of accounts with OAuth2 tokens back using the |callback_|
  // function. If there are token requests in progress, do nothing.
  void ReportTokens();
  // Verify that all of the tokens are ready to be passed down to the GCM
  // Driver, e.g. none of them has expired or is missing. Returns true if not
  // all tokens are valid and a fetching yet more tokens is required.
  void SanitizeTokens();
  // Indicates whether token reporting is required, either because it is due, or
  // some of the accounts were removed.
  bool IsTokenReportingRequired() const;
  // Indicates whether there are tokens that still need fetching.
  bool IsTokenFetchingRequired() const;
  // Gets the time until next token reporting.
  base::TimeDelta GetTimeToNextTokenReporting() const;
  // Deletes a token request. Should be called from OnGetTokenSuccess(..) or
  // OnGetTokenFailure(..).
  void DeleteTokenRequest(const OAuth2TokenService::Request* request);
  // Checks on all known accounts, and calls GetToken(..) for those with
  // |state == TOKEN_NEEDED|.
  void GetAllNeededTokens();
  // Starts fetching the OAuth2 token for the GCM group scope.
  void GetToken(AccountInfos::iterator& account_iter);

  // Handling of actual sign in and sign out for accounts.
  void OnAccountSignedIn(const gaia::AccountIds& ids);
  void OnAccountSignedOut(const gaia::AccountIds& ids);

  OAuth2TokenService* GetTokenService();

  // Account tracker.
  scoped_ptr<gaia::AccountTracker> account_tracker_;

  // GCM Driver. Not owned.
  GCMDriver* driver_;

  // State of the account.
  AccountInfos account_infos_;

  // Indicates whether shutdown has been called.
  bool shutdown_called_;

  ScopedVector<OAuth2TokenService::Request> pending_token_requests_;

  // Creates weak pointers used to postpone reporting tokens. See
  // ScheduleReportTokens.
  base::WeakPtrFactory<GCMAccountTracker> reporting_weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(GCMAccountTracker);
};

}  // namespace gcm

#endif  // CHROME_BROWSER_SERVICES_GCM_GCM_ACCOUNT_TRACKER_H_