File: privacy_metrics_service.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (179 lines) | stat: -rw-r--r-- 7,577 bytes parent folder | download | duplicates (7)
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 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/privacy/privacy_metrics_service.h"

#include "base/metrics/histogram_functions.h"
#include "chrome/browser/preloading/preloading_prefs.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/prefs/pref_service.h"
#include "components/privacy_sandbox/tracking_protection_prefs.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/sync/service/sync_service.h"

PrivacyMetricsService::PrivacyMetricsService(
    PrefService* pref_service,
    HostContentSettingsMap* host_content_settings_map,
    syncer::SyncService* sync_service,
    signin::IdentityManager* identity_manager)
    : pref_service_(pref_service),
      host_content_settings_map_(host_content_settings_map),
      sync_service_(sync_service),
      identity_manager_(identity_manager) {
  DCHECK(pref_service_);
  DCHECK(host_content_settings_map_);

  RecordStartupMetrics();

  // Avoid registering any observers if COE is disabled. Events which change
  // COE state will still be caught on shutdown.
  if (!IsClearOnExitEnabled())
    return;

  // Observe the identity manager regardless of sync state to catch changes to
  // sync level consent (e.g. a user enabling sync).
  if (identity_manager_)
    identity_manager_observer_.Observe(identity_manager_.get());

  // Avoid observing the sync service if sync-the-feature is disabled, events
  // this service is interested in will still be caught by the identity manager
  // observer. This service is not interested in sync-the-transport, as for the
  // user visible sync-paused state to occur, sync-the-feature must be enabled.
  if (!sync_service_ || !sync_service_->IsSyncFeatureEnabled()) {
    RecordClearOnExitSyncEvent(ClearOnExitSyncEvent::kStartupSyncDisabled);
    return;
  }

  sync_service_observer_.Observe(sync_service_.get());

  // While this service is brought up with the profile, and thus practically
  // should capture all sync state changes as the sync service starts up,
  // firing the observer here ensures that no state changes are missed.
  OnStateChanged(sync_service_);
}

PrivacyMetricsService::~PrivacyMetricsService() = default;

void PrivacyMetricsService::Shutdown() {
  UnregisterObservers();

  if (!sync_service_ || !IsClearOnExitEnabled()) {
    return;
  }

  if (sync_service_->IsSyncFeatureActive()) {
    ClearOnExitSyncEvent event;
    if (sync_started_paused_ && primary_account_consent_changed_) {
      event =
          ClearOnExitSyncEvent::kShutdownSyncActiveStartedPausedConsentChange;
    } else if (sync_started_paused_ && !primary_account_consent_changed_) {
      event =
          ClearOnExitSyncEvent::kShutdownSyncActiveStartedPausedNoConsentChange;
    } else if (!sync_started_paused_ && primary_account_consent_changed_) {
      event =
          ClearOnExitSyncEvent::kShutdownSyncActiveStartedActiveConsentChange;
    } else {
      DCHECK(!sync_started_paused_ && !primary_account_consent_changed_);
      event =
          ClearOnExitSyncEvent::kShutdownSyncActiveStartedActiveNoConsentChange;
    }
    RecordClearOnExitSyncEvent(event);
  } else if (sync_service_->GetTransportState() ==
             syncer::SyncService::TransportState::PAUSED) {
    RecordClearOnExitSyncEvent(ClearOnExitSyncEvent::kShutdownSyncPaused);
  }
}

void PrivacyMetricsService::OnStateChanged(syncer::SyncService* sync) {
  // This function will be called in response to all sync service state changes
  // until sync reaches the active state and the observer is unregistered below.
  // This may be soon after startup, or delayed if sync first enters the sync
  // paused state (or experiences another uninteresting sync issue). This
  // includes the initial state sync is in when this service is created, which
  // as this service is created along with the profile is early enough that the
  // user cannot have rectified a sync paused state.

  if (sync->GetTransportState() ==
          syncer::SyncService::TransportState::PAUSED &&
      IsClearOnExitEnabled() && !sync_started_paused_) {
    // Sync has started up directly into a paused state, very likely because of
    // the users COE setting. Sync has not previously reached the active state,
    // because when it does this observer is unregistered.
    RecordClearOnExitSyncEvent(ClearOnExitSyncEvent::kStartupSyncPaused);

    // Continue to observe the sync service, as if the user rectifies the
    // sync paused error by signing directly back in, the account change
    // observer wont trigger, but sync will eventually reach an active state.
    sync_started_paused_ = true;
  } else if (sync->GetTransportState() ==
             syncer::SyncService::TransportState::ACTIVE) {
    // Getting into the sync active state by changing primary account is handled
    // by the identity manager observer.
    if (!primary_account_consent_changed_ && IsClearOnExitEnabled()) {
      if (sync_started_paused_) {
        RecordClearOnExitSyncEvent(

            ClearOnExitSyncEvent::kReloginToPausedAccount);
      } else {
        // User managed to avoid the sync paused state while having CoE enabled.
        RecordClearOnExitSyncEvent(ClearOnExitSyncEvent::kStartupSyncActive);
      }
    }
    // No further sync or identity updates are interesting. The final state of
    // sync and COE will however be checked on Shutdown().
    UnregisterObservers();
  }
}

void PrivacyMetricsService::OnPrimaryAccountChanged(
    const signin::PrimaryAccountChangeEvent& event_details) {
  auto previous_consent_level = event_details.GetPreviousState().consent_level;
  auto current_consent_level = event_details.GetCurrentState().consent_level;

  if (current_consent_level != previous_consent_level) {
    primary_account_consent_changed_ = true;
    if (current_consent_level == signin::ConsentLevel::kSignin &&
        IsClearOnExitEnabled() && sync_started_paused_) {
      DCHECK(previous_consent_level == signin::ConsentLevel::kSync);
      // The only way for a user to downgrade the consent level in the UI is
      // by logging out of the account.
      RecordClearOnExitSyncEvent(ClearOnExitSyncEvent::kLogoutOfPausedAccount);
      identity_manager_observer_.Reset();
    }
  }
}

void PrivacyMetricsService::RecordStartupMetrics() {
  base::UmaHistogramBoolean(
      "Privacy.DoNotTrackSetting2",
      pref_service_->GetBoolean(prefs::kEnableDoNotTrack));

  base::UmaHistogramEnumeration("Settings.PreloadStatus.OnStartup3",
                                prefetch::GetPreloadPagesState(*pref_service_));
  base::UmaHistogramBoolean(
      "Settings.AutocompleteSearches.OnStartup2",
      pref_service_->GetBoolean(::prefs::kSearchSuggestEnabled));

  base::UmaHistogramBoolean(
      "Settings.AdvancedSpellcheck.OnStartup2",
      pref_service_->GetBoolean(
          ::spellcheck::prefs::kSpellCheckUseSpellingService));
}

void PrivacyMetricsService::UnregisterObservers() {
  sync_service_observer_.Reset();
  identity_manager_observer_.Reset();
}

bool PrivacyMetricsService::IsClearOnExitEnabled() {
  return host_content_settings_map_->GetDefaultContentSetting(
             ContentSettingsType::COOKIES) ==
         ContentSetting::CONTENT_SETTING_SESSION_ONLY;
}

void PrivacyMetricsService::RecordClearOnExitSyncEvent(
    ClearOnExitSyncEvent event) const {
  base::UmaHistogramEnumeration("Privacy.ClearOnExitSyncEvent", event);
}