File: per_user_state_manager_chromeos.h

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (300 lines) | stat: -rw-r--r-- 12,210 bytes parent folder | download | duplicates (4)
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_METRICS_PER_USER_STATE_MANAGER_CHROMEOS_H_
#define CHROME_BROWSER_METRICS_PER_USER_STATE_MANAGER_CHROMEOS_H_

#include <optional>
#include <string>

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/ash/settings/device_settings_service.h"
#include "chrome/browser/metrics/profile_pref_names.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/login/session/session_termination_manager.h"
#include "components/account_id/account_id.h"
#include "components/metrics/metrics_log_store.h"
#include "components/metrics/metrics_provider.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"

namespace metrics {

// State manager for per-user metrics collection. Listens to user
// creation/deletion and manages user prefs accordingly.
//
// When a particular user is created (login), all metrics collected so far
// will be flushed to local state. Before a user is destroyed (logout), all
// metrics will be flushed to the user dir.
//
// It is assumed that there can only be at most one user logged in at once. This
// assumption is only true in Ash Chrome.
//
// This class integrates into the MetricsService in order to separately handle
// UMA reporting consent for unmanaged secondary users. Profile prefs are
// used to handle the consent for each user. These profile settings interact
// with the local state pref that controls the overall device reporting
// consent, and UMA uploading logic.
//
// Ownership status needs to be asynchronously retrieved first in order to know
// whether the device has no ownership yet, or whether the device is owned and
// we are controlling consent for a secondary user.
//
// This class does not manage the device owner reporting consent.
// Device owner consent is handled separately by
// |ash::StatsReportingController|. In the future, we may want to consider
// simplifying the code by using a single class to manage both device owner
// consent and secondary user consent.
class PerUserStateManagerChromeOS
    : public user_manager::UserManager::UserSessionStateObserver,
      public user_manager::UserManager::Observer,
      public ash::SessionTerminationManager::Observer {
 public:
  // Callback to handle changes in user metrics consent.
  using MetricsConsentHandler = base::RepeatingCallback<void(bool)>;

  // Does not own params passed by pointer. Caller should ensure that the
  // lifetimes of the weak pointers exceed that of |this|.
  PerUserStateManagerChromeOS(
      MetricsServiceClient* metrics_service_client,
      user_manager::UserManager* user_manager,
      PrefService* local_state,
      const MetricsLogStore::StorageLimits& storage_limits,
      const std::string& signing_key);

  // Does not own |metrics_service_client| and |local_state|. Lifetime of
  // these raw pointers should be handled by the caller.
  PerUserStateManagerChromeOS(MetricsServiceClient* metrics_service_client,
                              PrefService* local_state);

  PerUserStateManagerChromeOS(const PerUserStateManagerChromeOS& other) =
      delete;
  PerUserStateManagerChromeOS& operator=(
      const PerUserStateManagerChromeOS& other) = delete;
  ~PerUserStateManagerChromeOS() override;

  static void RegisterPrefs(PrefRegistrySimple* registry);
  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);

  // Returns the user_id of the current logged in user. If no user is logged in,
  // returns std::nullopt. If a user has logged in and has opted-out, will
  // return std::nullopt.
  //
  // If the user has opted-into metrics collection and is not ephemeral, then
  // this will return the pseudo-anonymous identifier associated with the user.
  std::optional<std::string> GetCurrentUserId() const;

  // Returns the consent of the current logged in user only if current user's
  // consent should be applied to metrics reporting.
  //
  // The cases in which this occurs are:
  //
  //    1) Regular non-owner users on non-managed devices.
  //    2) Guest users.
  //
  // If no user is logged in, returns std::nullopt. True means that the user
  // has opted-into metrics collection during the session and False means that
  // the user has opted-out.
  std::optional<bool> GetCurrentUserReportingConsentIfApplicable() const;

  // Sets the metric consent for the current logged in user. If no user is
  // logged in, no-ops.
  //
  // This method will reset the client id if a user toggles from a non-consent
  // to consent state AND the user had consented to metrics collection in the
  // past. This is to preserve the pseudo-anonymity of <user_id, client_id>
  // identifier.
  //
  // This call should be used to toggle consent from the UI or during OOBE flow
  // for the current user.
  void SetCurrentUserMetricsConsent(bool metrics_consent);

  // Returns true if |user| should have the ability to toggle user metrics
  // collection for themselves.
  //
  // This will return false for managed device users as well as guest users.
  bool IsUserAllowedToChangeConsent(user_manager::User* user) const;

  // Adds an observer |callback| to be called when a user consent should be
  // applied. This happens either when an applicable user logs in or an
  // applicable user changes metrics consent.
  base::CallbackListSubscription AddObserver(
      const MetricsConsentHandler& callback);

  // Sets behavior of IsReportingPolicyManaged() for testing.
  //
  // TODO(crbug/1269950): Investigate why ash::LoginManagerTest does not work
  // with ash::ScopedStubInstallAttributes. Remove this function once resolved
  // as it is hack to force PerUserStateManagerChromeOS to return a fixed value.
  static void SetIsManagedForTesting(bool is_managed);

  // Resets the logged in user state for testing.
  void ResetStateForTesting();

 protected:
  // These methods are marked virtual to stub out for testing.

  // Sets the user log store to use |log_store|. Default uses
  // |metrics_service_client_| implementation.
  virtual void SetUserLogStore(std::unique_ptr<UnsentLogStore> log_store);

  // Unsets the user log store. Default uses |metrics_service_client_|
  // implementation.
  virtual void UnsetUserLogStore();

  // Resets the client ID. Should be called when user consent is turned off->on
  // and the user has opted-in metrics consent in the past. Default uses
  // |metrics_service_client_| implementation.
  virtual void ForceClientIdReset();

  // Returns true if the reporting policy is managed.
  virtual bool IsReportingPolicyManaged() const;

  // Returns true if user log store has been set to be used to persist metric
  // logs.
  virtual bool HasUserLogStore() const;

  // Returns true if the device is owned either by a policy or a local owner.
  //
  // Does not guarantee that the ownership status is known and will return false
  // if the status is unknown.
  //
  // See //chrome/browser/ash/settings/device_settings_service.h for more
  // details as to when a device is considered owned and how a device becomes
  // owned.
  virtual bool IsDeviceOwned() const;

  // Returns true if the device status is known.
  virtual bool IsDeviceStatusKnown() const;

  // These methods are protected to avoid dependency on DeviceSettingsService
  // during testing.

  // Ensures that ownership status is known before proceeding with using
  // profile prefs.
  virtual void WaitForOwnershipStatus();

  // Returns true if a user log store in the user cryptohome should be used for
  // the current logged in user.
  // Certain users (ie demo mode sessions with metrics consent on) should not
  // use a user log store since the user log store will be stored on the
  // temporary cryptohome and will be deleted at the end of the session.
  // Demo mode sessions with metric consent on should be stored in local state
  // to be persistent.
  bool ShouldUseUserLogStore() const;

  // Loads appropriate prefs from |current_user_| and creates new log storage
  // using profile prefs.
  //
  // Will only be called when OwnershipStatus is known. This guarantees that
  // we avoid race conditions where the ownership status is still unknown due
  // to policy fetch on browser restart.
  // The status will either be kOwnershipNone, or kOwnershipTaken.
  void InitializeProfileMetricsState(
      ash::DeviceSettingsService::OwnershipStatus status);

 private:
  // Possible states for |this|.
  enum class State {
    // Right after construction.
    CONSTRUCTED = 0,

    // ActiveUserChanged on non-trivial user. The profile for the user is not
    // immediately created.
    USER_LOGIN = 1,

    // User profile has been created and ready to use.
    USER_PROFILE_READY = 2,

    // User log store has been initialized, if applicable. Per-user consent
    // now can be changed if the user has permissions to change consent.
    //
    // Terminal state.
    USER_LOG_STORE_HANDLED = 3,
  };

  // UserManager::UserSessionStateObserver:
  void ActiveUserChanged(user_manager::User* active_user) override;

  // UserManager::Observer:
  void OnUserToBeRemoved(const AccountId& account_id) override;

  // ash::SessionTerminationManager::Observer:
  void OnSessionWillBeTerminated() override;

  // Updates the current user ID to |new_user_id|. Updates both the profile pref
  // as well as local state pref.
  void UpdateCurrentUserId(const std::string& new_user_id);

  // Resets the state of |this| to that of no logged in user.
  void ResetState();

  // Returns the prefs for the current logged in user.
  PrefService* GetCurrentUserPrefs() const;

  // Builds a unsent log store for |current_user_| and assigns it to be used as
  // the primary log store for ongoing logs.
  void AssignUserLogStore();

  // Sets the reporting state for metrics collection. Notifies observers that
  // user metrics consent has changed to |metrics_consent|.
  void SetReportingState(bool metrics_consent);

  // Notifies observers of the per-user state change |metrics_consent|.
  void NotifyObservers(bool metrics_consent);

  // Updates local state prefs based on |metrics_enabled|. If |metrics_enabled|
  // is true,
  //
  //    1) Client ID will be reset if the user has ever had metrics reporting
  //       enabled. This is to preserve the pseudo-anonymous identifier
  //       <client_id, user_id>.
  void UpdateLocalStatePrefs(bool metrics_enabled);

  SEQUENCE_CHECKER(sequence_checker_);

  base::RepeatingCallbackList<void(bool)> callback_list_;

  // Raw pointer to Metrics service client that should own |this|.
  const raw_ptr<MetricsServiceClient> metrics_service_client_;

  // Raw pointer to user manager. User manager is used to listen to login/logout
  // events as well as retrieve metadata about users. |user_manager_| should
  // outlive |this|.
  const raw_ptr<user_manager::UserManager> user_manager_;

  // Raw pointer to local state prefs store.
  const raw_ptr<PrefService> local_state_;

  // Logs parameters that control log storage requirements and restrictions.
  const MetricsLogStore::StorageLimits storage_limits_;

  // Signing key to encrypt logs.
  const std::string signing_key_;

  // Pointer to the current logged-in user.
  raw_ptr<user_manager::User> current_user_ = nullptr;

  // Current state for |this|.
  State state_ = State::CONSTRUCTED;

  // Task runner. Used to persist state to daemon-store.
  scoped_refptr<base::SequencedTaskRunner> task_runner_ = nullptr;

  base::WeakPtrFactory<PerUserStateManagerChromeOS> weak_ptr_factory_{this};
};

}  // namespace metrics

#endif  // CHROME_BROWSER_METRICS_PER_USER_STATE_MANAGER_CHROMEOS_H_