File: breadcrumbs_status.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; 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 (157 lines) | stat: -rw-r--r-- 5,785 bytes parent folder | download | duplicates (6)
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
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/breadcrumbs/core/breadcrumbs_status.h"

#include <atomic>
#include <optional>

#include "base/command_line.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/variations/variations_switches.h"
#include "components/version_info/channel.h"

namespace breadcrumbs {

namespace {

// Represents whether breadcrumbs is enabled/disabled from local prefs (the
// default and most common case) or forced to enabled/disabled.
enum class BreadcrumbsEnabledMode {
  kFromLocalPrefs,
  kForceEnabled,
  kForceDisabled
};

// If set to `kFromLocalPrefs`, breadcrumbs is enabled or disabled based on
// Local State prefs like usual. Otherwise, breadcrumbs has been forced either
// on (e.g., for testing) or off (e.g., for Chrome on Android's minimal mode).
std::atomic<BreadcrumbsEnabledMode> breadcrumbs_enabled_mode =
    BreadcrumbsEnabledMode::kFromLocalPrefs;

// The percentage at which breadcrumbs is enabled per channel.
// Enable on most pre-Stable clients to ensure crashes with only a few reports
// have enough breadcrumbs to be useful.
constexpr int kCanaryPercent = 99;
constexpr int kDevPercent = 80;
constexpr int kBetaPercent = 80;
// Enable on a small portion of Stable. This rate is expected to provide enough
// breadcrumbs data while not logging on more clients than necessary.
constexpr int kStablePercent = 5;

// How long logging should be enabled on a client before re-randomizing.
constexpr auto kEnabledDuration = base::Days(30);

// Returns a random boolean representing whether breadcrumbs should be enabled
// for `channel`. For example, if logging is enabled at 5% on `channel`, this
// has a 5% chance of returning true.
bool GetRandomIsEnabled(version_info::Channel channel) {
  int enabled_percent = 0;
  switch (channel) {
    case version_info::Channel::CANARY:
      enabled_percent = kCanaryPercent;
      break;
    case version_info::Channel::DEV:
      enabled_percent = kDevPercent;
      break;
    case version_info::Channel::BETA:
      enabled_percent = kBetaPercent;
      break;
    case version_info::Channel::STABLE:
      enabled_percent = kStablePercent;
      break;
    case version_info::Channel::UNKNOWN:
      break;
  }
  return base::RandInt(1, 100) <= enabled_percent;
}

// Returns true if `prefs` contains both breadcrumbs prefs, and the timestamp is
// valid and newer than `kEnabledDuration`.
bool HasRecentBreadcrumbsPrefs(PrefService* prefs) {
  if (!prefs->HasPrefPath(kEnabledPref) ||
      !prefs->HasPrefPath(kEnabledTimePref)) {
    // Breadcrumbs prefs have never been set.
    return false;
  }
  const auto enabled_time = prefs->GetTime(kEnabledTimePref);
  const auto now = base::Time::Now();
  if (enabled_time > now) {
    // Timestamp is in the future, so consider it invalid.
    return false;
  }
  const auto oldest_valid_time = now - kEnabledDuration;
  return enabled_time > oldest_valid_time;
}

bool IsEnabled(PrefService* prefs,
               std::optional<version_info::Channel> set_for_channel) {
  switch (breadcrumbs_enabled_mode) {
    case BreadcrumbsEnabledMode::kForceEnabled:
      return true;
    case BreadcrumbsEnabledMode::kForceDisabled:
      return false;
    case BreadcrumbsEnabledMode::kFromLocalPrefs:
      // `prefs` can be null or unregistered in tests, and can be null in Chrome
      // for Android's minimal mode. In these cases, breadcrumbs should be
      // disabled for the entire session. Also, breadcrumbs should be disabled
      // while benchmarking, to reflect the typical client experience.
      if (!prefs || !prefs->FindPreference(kEnabledPref) ||
          !prefs->FindPreference(kEnabledTimePref) ||
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              variations::switches::kEnableBenchmarking)) {
        breadcrumbs_enabled_mode = BreadcrumbsEnabledMode::kForceDisabled;
        return false;
      }

      if (set_for_channel.has_value()) {
        // Keep breadcrumbs consistently enabled/disabled on a given client for
        // `kEnabledDuration`. If breadcrumbs has been enabled/disabled in prefs
        // more recently than `kEnabledDuration`, use the existing setting.
        if (HasRecentBreadcrumbsPrefs(prefs)) {
          return prefs->GetBoolean(kEnabledPref);
        }

        // Re-randomize if breadcrumbs was enabled/disabled too long ago. This
        // either enables or disables breadcrumbs for `kEnabledDuration`.
        const bool is_enabled = GetRandomIsEnabled(set_for_channel.value());
        prefs->SetBoolean(kEnabledPref, is_enabled);
        prefs->SetTime(kEnabledTimePref, base::Time::Now());
      }

      return prefs->GetBoolean(kEnabledPref);
  }
}

}  // namespace

constexpr char kEnabledPref[] = "breadcrumbs.enabled";
constexpr char kEnabledTimePref[] = "breadcrumbs.enabled_time";

bool IsEnabled(PrefService* prefs) {
  return IsEnabled(prefs, std::nullopt);
}

bool MaybeEnableBasedOnChannel(PrefService* prefs,
                               version_info::Channel channel) {
  return IsEnabled(prefs, channel);
}

void RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(kEnabledPref, false);
  registry->RegisterTimePref(kEnabledTimePref, base::Time());
}

ScopedEnableBreadcrumbsForTesting::ScopedEnableBreadcrumbsForTesting() {
  breadcrumbs_enabled_mode = BreadcrumbsEnabledMode::kForceEnabled;
}

ScopedEnableBreadcrumbsForTesting::~ScopedEnableBreadcrumbsForTesting() {
  breadcrumbs_enabled_mode = BreadcrumbsEnabledMode::kFromLocalPrefs;
}

}  // namespace breadcrumbs