1 // Copyright 2019 The Chromium Authors 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 COMPONENTS_METRICS_DEMOGRAPHICS_USER_DEMOGRAPHICS_H_ 6 #define COMPONENTS_METRICS_DEMOGRAPHICS_USER_DEMOGRAPHICS_H_ 7 8 #include "base/time/time.h" 9 #include "build/build_config.h" 10 #include "third_party/metrics_proto/user_demographics.pb.h" 11 12 class PrefService; 13 class PrefRegistrySimple; 14 15 namespace metrics { 16 17 // Default value for user gender when no value has been set. 18 constexpr int kUserDemographicsGenderDefaultValue = -1; 19 20 // Default value for user gender enum when no value has been set. 21 constexpr UserDemographicsProto_Gender kUserDemographicGenderDefaultEnumValue = 22 UserDemographicsProto_Gender_Gender_MIN; 23 24 // Default value for user birth year when no value has been set. 25 constexpr int kUserDemographicsBirthYearDefaultValue = -1; 26 27 // Default value for birth year offset when no value has been set. Set to a 28 // really high value that |kUserDemographicsBirthYearNoiseOffsetRange| will 29 // never go over. 30 constexpr int kUserDemographicsBirthYearNoiseOffsetDefaultValue = 100; 31 32 // Boundary of the +/- range in years within witch to randomly pick an offset to 33 // add to the user birth year. This adds noise to the birth year to not allow 34 // someone to accurately know a user's age. Possible offsets range from -2 to 2. 35 constexpr int kUserDemographicsBirthYearNoiseOffsetRange = 2; 36 37 // Minimal user age in years to provide demographics for. 38 constexpr int kUserDemographicsMinAgeInYears = 20; 39 40 // Max user age to provide demopgrahics for. 41 constexpr int kUserDemographicsMaxAgeInYears = 85; 42 43 // Root dictionary pref to store the user's birth year and gender that are 44 // provided by the sync server. This is a read-only syncable priority pref on 45 // all platforms except ChromeOS Ash, where it is a syncable OS-level priority 46 // pref. 47 #if !BUILDFLAG(IS_CHROMEOS_ASH) 48 inline constexpr char kSyncDemographicsPrefName[] = "sync.demographics"; 49 #else 50 inline constexpr char kSyncOsDemographicsPrefName[] = "sync.os_demographics"; 51 // TODO(crbug/1367338): Make this non-syncable (on Ash only) after full rollout 52 // of the syncable os priority pref; then delete it locally from Ash devices. 53 inline constexpr char kSyncDemographicsPrefName[] = "sync.demographics"; 54 #endif 55 56 // Stores a "secret" offset that is used to randomize the birth year for metrics 57 // reporting. This value should not be logged to UMA directly; instead, it 58 // should be summed with the kSyncDemographicsBirthYear. This value is generated 59 // locally on the client the first time a user begins to merge birth year data 60 // into their UMA reports. 61 inline constexpr char kUserDemographicsBirthYearOffsetPrefName[] = 62 "demographics_birth_year_offset"; 63 // TODO(crbug/1367338): Delete after 2023/09 64 inline constexpr char kDeprecatedDemographicsBirthYearOffsetPrefName[] = 65 "sync.demographics_birth_year_offset"; 66 67 // These are not prefs, they are paths inside of kSyncDemographics. 68 69 // This pref value is subordinate to the kSyncDemographics dictionary pref and 70 // is synced to the client. It stores the self-reported birth year of the 71 // syncing user. as provided by the sync server. This value should not be logged 72 // to UMA directly; instead, it should be summed with the 73 // kSyncDemographicsBirthYearNoiseOffset. 74 inline constexpr char kSyncDemographicsBirthYearPath[] = "birth_year"; 75 76 // This pref value is subordinate to the kSyncDemographics dictionary pref and 77 // is synced to the client. It stores the self-reported gender of the syncing 78 // user, as provided by the sync server. The gender is encoded using the Gender 79 // enum defined in UserDemographicsProto 80 // (see third_party/metrics_proto/user_demographics.proto). 81 inline constexpr char kSyncDemographicsGenderPath[] = "gender"; 82 83 // Container of user demographics. 84 struct UserDemographics { 85 int birth_year = 0; 86 UserDemographicsProto_Gender gender = UserDemographicsProto::Gender_MIN; 87 }; 88 89 // Represents the status of providing user demographics (noised birth year and 90 // gender) that are logged to UMA. Entries of the enum should not be renumbered 91 // and numeric values should never be reused. Please keep in sync with 92 // "UserDemographicsStatus" in src/tools/metrics/histograms/enums.xml. There 93 // should only be one entry representing demographic data that is ineligible to 94 // be provided. A finer grained division of kIneligibleDemographicsData (e.g., 95 // INVALID_BIRTH_YEAR) might help inferring categories of demographics that 96 // should not be exposed to protect privacy. 97 enum class UserDemographicsStatus { 98 // Could get the user's noised birth year and gender. 99 kSuccess = 0, 100 // Sync is not enabled. 101 kSyncNotEnabled = 1, 102 // User's birth year and gender are ineligible to be provided either because 103 // some of them don't exist (missing data) or some of them are not eligible to 104 // be provided. 105 kIneligibleDemographicsData = 2, 106 // Could not get the time needed to compute the user's age. 107 kCannotGetTime = 3, 108 // There is more than one Profile for the Chrome browser. This entry is used 109 // by the DemographicMetricsProvider client. 110 kMoreThanOneProfile = 4, 111 // There is no sync service available for the loaded Profile. This entry is 112 // used by the DemographicMetricsProvider client. 113 kNoSyncService = 5, 114 // Upper boundary of the enum that is needed for the histogram. 115 kMaxValue = kNoSyncService 116 }; 117 118 // Container and handler for data related to the retrieval of user demographics. 119 // Holds either valid demographics data or an error code. 120 class UserDemographicsResult { 121 public: 122 // Builds a UserDemographicsResult that contains user demographics and has a 123 // UserDemographicsStatus::kSuccess status. 124 static UserDemographicsResult ForValue(UserDemographics value); 125 126 // Builds a UserDemographicsResult that does not have user demographics (only 127 // default values) and has a status other than 128 // UserDemographicsStatus::kSuccess. 129 static UserDemographicsResult ForStatus(UserDemographicsStatus status); 130 131 // Determines whether demographics could be successfully retrieved. 132 bool IsSuccess() const; 133 134 // Gets the status of the result. 135 UserDemographicsStatus status() const; 136 137 // Gets the value of the result which will contain data when status() is 138 // UserDemographicsStatus::kSuccess. 139 const UserDemographics& value() const; 140 141 private: 142 UserDemographicsResult(UserDemographics value, UserDemographicsStatus status); 143 144 UserDemographics value_; 145 UserDemographicsStatus status_ = UserDemographicsStatus::kMaxValue; 146 }; 147 148 // Registers the local state preferences that are needed to persist demographics 149 // information exposed via GetUserNoisedBirthYearAndGenderFromPrefs(). 150 void RegisterDemographicsLocalStatePrefs(PrefRegistrySimple* registry); 151 152 // Registers the profile preferences that are needed to persist demographics 153 // information exposed via GetUserNoisedBirthYearAndGenderFromPrefs(). 154 void RegisterDemographicsProfilePrefs(PrefRegistrySimple* registry); 155 156 // Clears the profile's demographics-related preferences containing user data. 157 // This excludes the internal birth year offset. 158 void ClearDemographicsPrefs(PrefService* profile_prefs); 159 160 // Gets the synced user’s birth year and gender from |profile_prefs|, and noise 161 // from |local_state|. See docs for metrics::DemographicMetricsProvider in 162 // components/metrics/demographic_metrics_provider.h for more details. Returns 163 // an error status with an empty value when the user's birth year or gender 164 // cannot be provided. You need to provide an accurate |now| time that 165 // represents the current time. 166 UserDemographicsResult GetUserNoisedBirthYearAndGenderFromPrefs( 167 base::Time now, 168 PrefService* local_state, 169 PrefService* profile_prefs); 170 171 } // namespace metrics 172 173 #endif // COMPONENTS_METRICS_DEMOGRAPHICS_USER_DEMOGRAPHICS_H_ 174