summaryrefslogtreecommitdiff
path: root/chromium/components/cryptauth/cryptauth_device_manager.h
blob: a728f247abf31cd0c0919712d7f8dcf04f654da8 (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2015 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 COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_H_
#define COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_H_

#include <memory>

#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/cryptauth/cryptauth_gcm_manager.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/sync_scheduler.h"

class PrefService;
class PrefRegistrySimple;

namespace cryptauth {

class CryptAuthClient;
class CryptAuthClientFactory;

// This class manages syncing and storing the user's phones that are registered
// with CryptAuth and are capable of unlocking the user's other devices. These
// phones are called "unlock keys".
// The manager periodically syncs the user's devices from CryptAuth to keep the
// list of unlock keys fresh. If a sync attempts fails, the manager will
// schedule the next sync more aggressively to recover.
class CryptAuthDeviceManager : public SyncScheduler::Delegate,
                               public CryptAuthGCMManager::Observer {
 public:
  // Respresents the success result of a sync attempt.
  enum class SyncResult { SUCCESS, FAILURE };

  // Represents whether the list of unlock keys has changed after a sync
  // attempt completes.
  enum class DeviceChangeResult {
    UNCHANGED,
    CHANGED,
  };

  class Observer {
   public:
    // Called when a sync attempt is started.
    virtual void OnSyncStarted() {}

    // Called when a sync attempt finishes with the |success| of the request.
    // |devices_changed| specifies if the sync caused the stored unlock keys to
    // change.
    virtual void OnSyncFinished(SyncResult sync_result,
                                DeviceChangeResult device_change_result) {}

    virtual ~Observer() {}
  };

  // Creates the manager:
  // |clock|: Used to determine the time between sync attempts.
  // |client_factory|: Creates CryptAuthClient instances to perform each sync.
  // |gcm_manager|: Notifies when GCM push messages trigger device syncs.
  //                Not owned and must outlive this instance.
  // |pref_service|: Stores syncing metadata and unlock key information to
  //                 persist across browser restarts. Must already be registered
  //                 with RegisterPrefs().
  CryptAuthDeviceManager(std::unique_ptr<base::Clock> clock,
                         std::unique_ptr<CryptAuthClientFactory> client_factory,
                         CryptAuthGCMManager* gcm_manager,
                         PrefService* pref_service);

  ~CryptAuthDeviceManager() override;

  // Registers the prefs used by this class to the given |registry|.
  static void RegisterPrefs(PrefRegistrySimple* registry);

  // Starts device manager to begin syncing devices.
  void Start();

  // Adds an observer.
  void AddObserver(Observer* observer);

  // Removes an observer.
  void RemoveObserver(Observer* observer);

  // Skips the waiting period and forces a sync immediately. If a
  // sync attempt is already in progress, this function does nothing.
  // |invocation_reason| specifies the reason that the sync was triggered,
  // which is upload to the server.
  void ForceSyncNow(InvocationReason invocation_reason);

  // Returns the timestamp of the last successful sync. If no sync
  // has ever been made, then returns a null base::Time object.
  base::Time GetLastSyncTime() const;

  // Returns the time to the next sync attempt.
  base::TimeDelta GetTimeToNextAttempt() const;

  // Returns true if a device sync attempt is currently in progress.
  bool IsSyncInProgress() const;

  // Returns true if the last device sync failed and the manager is now
  // scheduling sync attempts more aggressively to recover. If no enrollment
  // has ever been recorded, then this function will also return true.
  bool IsRecoveringFromFailure() const;

  // Returns a list of all remote devices that have been synced.
  virtual std::vector<ExternalDeviceInfo> GetSyncedDevices() const;

  // Returns a list of remote devices that can unlock the user's other devices.
  virtual std::vector<ExternalDeviceInfo> GetUnlockKeys() const;

  // Returns a list of remote devices that can host tether hotspots.
  virtual std::vector<ExternalDeviceInfo> GetTetherHosts() const;

 protected:
  // Empty constructor, to be used by tests to mock the device manager. Do not
  // use this constructor outside of tests.
  CryptAuthDeviceManager();

  // Creates a new SyncScheduler instance. Exposed for testing.
  virtual std::unique_ptr<SyncScheduler> CreateSyncScheduler();

 private:
  // CryptAuthGCMManager::Observer:
  void OnResyncMessage() override;

  // Updates |unlock_keys_| by fetching the list stored in |pref_service_|.
  void UpdateUnlockKeysFromPrefs();

  // SyncScheduler::Delegate:
  void OnSyncRequested(
      std::unique_ptr<SyncScheduler::SyncRequest> sync_request) override;

  // Callback when |cryptauth_client_| completes with the response.
  void OnGetMyDevicesSuccess(const GetMyDevicesResponse& response);
  void OnGetMyDevicesFailure(const std::string& error);

  // Used to determine the time.
  std::unique_ptr<base::Clock> clock_;

  // Creates CryptAuthClient instances for each sync attempt.
  std::unique_ptr<CryptAuthClientFactory> client_factory_;

  // Notifies when GCM push messages trigger device sync. Not owned and must
  // outlive this instance.
  CryptAuthGCMManager* gcm_manager_;

  // Contains preferences that outlive the lifetime of this object and across
  // process restarts. |pref_service_| must outlive the lifetime of this
  // instance.
  PrefService* const pref_service_;

  // All devices currently synced from CryptAuth.
  std::vector<ExternalDeviceInfo> synced_devices_;

  // Schedules the time between device sync attempts.
  std::unique_ptr<SyncScheduler> scheduler_;

  // Contains the SyncRequest that |scheduler_| requests when a device sync
  // attempt is made.
  std::unique_ptr<SyncScheduler::SyncRequest> sync_request_;

  // The CryptAuthEnroller instance for the current sync attempt. A new
  // instance will be created for each individual attempt.
  std::unique_ptr<CryptAuthClient> cryptauth_client_;

  // List of observers.
  base::ObserverList<Observer> observers_;

  base::WeakPtrFactory<CryptAuthDeviceManager> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceManager);
};

}  // namespace cryptauth

#endif  // COMPONENTS_CRYPTAUTH_CRYPTAUTH_DEVICE_MANAGER_H_