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
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_STRIKE_DATABASE_STRIKE_DATABASE_INTEGRATOR_BASE_H_
#define COMPONENTS_STRIKE_DATABASE_STRIKE_DATABASE_INTEGRATOR_BASE_H_
#include <stdint.h>
#include <map>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <vector>
#include "base/check.h"
#include "base/functional/function_ref.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "components/strike_database/strike_database_base.h"
namespace autofill {
// Contains virtual functions for per-project implementations of StrikeDatabase
// to interface from, as well as a pointer to StrikeDatabase. This class is
// seperated from StrikeDatabase since we only want StrikeDatabase's cache to
// be loaded once per browser session.
class StrikeDatabaseIntegratorBase {
public:
// The StrikeDatabase's decision on whether the feature should be blocked or
// not, and if so, why.
enum StrikeDatabaseDecision {
// The feature should not be blocked.
kDoNotBlock = 0,
// Block feature: The maximum strike limit has been reached.
kMaxStrikeLimitReached = 1,
// Block feature: Not enough time has passed since the last strike.
kRequiredDelayNotPassed = 2,
};
static constexpr std::string_view kSharedId = "shared_id";
explicit StrikeDatabaseIntegratorBase(StrikeDatabaseBase* strike_database);
virtual ~StrikeDatabaseIntegratorBase();
// Returns the StrikeDatabase's decision on whether a particular feature
// should be blocked (not offered) for the given `id`.
StrikeDatabaseDecision GetStrikeDatabaseDecision(std::string_view id) const;
// Returns the StrikeDatabase's decision on whether a particular feature
// should be blocked (not offered).
StrikeDatabaseDecision GetStrikeDatabaseDecision() const;
// Returns whether a particular feature should be blocked (not offered) for
// the given `id`. Same as calling `GetStrikeDatabaseDecision`, where a result
// of `kDoNotBlock` returns false.
bool ShouldBlockFeature(std::string_view id) const;
// Returns whether a particular feature should be blocked (not offered). Same
// as calling `GetStrikeDatabaseDecision`, where a result of `kDoNotBlock`
// returns false.
bool ShouldBlockFeature() const;
// Increments in-memory cache and updates underlying ProtoDatabase.
int AddStrike(std::string_view id = kSharedId);
// Increases in-memory cache by `strikes_increase` and updates underlying
// ProtoDatabase.
int AddStrikes(int strikes_increase, std::string_view id = kSharedId);
// Removes an in-memory cache strike, updates last_update_timestamp, and
// updates underlying ProtoDatabase.
int RemoveStrike(std::string_view id = kSharedId);
// Removes `strikes_decrease` in-memory cache strikes, updates
// `last_update_timestamp`, and updates underlying ProtoDatabase.
int RemoveStrikes(int strikes_decrease, std::string_view id = kSharedId);
// Returns strike count from in-memory cache.
int GetStrikes(std::string_view id = kSharedId) const;
// Removes all database entries from in-memory cache and underlying
// ProtoDatabase.
void ClearStrikes(std::string_view id = kSharedId);
// Removes all database entries from in-memory cache and underlying
// ProtoDatabase for the whole project.
void ClearAllStrikes();
// Count strike entries for this project.
size_t CountEntries() const;
protected:
// Runs a cleanup routine to remove the stored strike elements with the oldest
// update timestamps when `NumberOfEntriesExceedsLimits()`. The number of
// elements should be reduced to `GetMaximumEntriesAfterCleanup()`.
void LimitNumberOfStoredEntries();
// Returns true if the number of stored entries exceeds the limit.
bool NumberOfEntriesExceedsLimits() const;
// Removes one strike for each key where it has been longer than
// GetExpiryTimeMicros() since `last_update_timestamp`.
void RemoveExpiredStrikes();
// Removes all database entries for which `id_map(ID)` is in `ids_to_delete`.
void ClearStrikesByIdMatching(
const std::set<std::string>& ids_to_delete,
base::FunctionRef<std::string(const std::string&)> id_map);
// Removes all database entries from in-memory for which `id_map(ID)` is in
// `ids_to_delete` and were added between `delete_begin` and `delete_end`.
void ClearStrikesByIdMatchingAndTime(
const std::set<std::string>& ids_to_delete,
base::Time delete_begin,
base::Time delete_end,
base::FunctionRef<std::string(const std::string&)> id_map);
// Removes all database entries from in-memory cache and underlying
// ProtoDatabase for keys in `keys`.
void ClearStrikesForKeys(const std::vector<std::string>& keys);
// Get a readonly reference to the cache.
const std::map<std::string, StrikeData>& GetStrikeCache() const {
return strike_database_->GetStrikeCache();
}
// Returns the id the key was built from with `GetKey(id)`.
std::string_view GetIdFromKey(std::string_view key) const;
// Returns the age of a strike entry.
static base::TimeDelta GetEntryAge(const StrikeData& strike_data);
private:
FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest,
StrikeDatabaseEmptyOnAutofillRemoveEverything);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
ClearStrikesForKeys);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
GetKeyForStrikeDatabaseIntegratorUniqueIdTest);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
IdFromKey);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
NonExpiringStrikesDoNotExpire);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesOnlyConsidersCurrentIntegrator);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesTest);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesTestLogsUMA);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesUniqueIdTest);
friend class FakeCreditCardServer;
friend class StrikeDatabaseTest;
friend class StrikeDatabaseTester;
const raw_ptr<StrikeDatabaseBase> strike_database_;
// For projects in which strikes don't have unique identifiers, the
// id suffix is set to `kSharedId`. This makes sure that projects requiring
// unique IDs always specify `id` instead of relying on the default shared
// value, while projects where unique IDs are unnecessary always fall back to
// the default shared value.
void CheckIdUniqueness(std::string_view id) const {
DCHECK(UniqueIdsRequired() == (id != kSharedId));
}
// Generates key based on project-specific string identifier.
std::string GetKey(std::string_view id) const;
// Returns the maximum number of entries that should be stored for this
// project prefix. std::nullopt means that there is no limit.
virtual std::optional<size_t> GetMaximumEntries() const;
// Returns the maximum number of entries that should remain after a cleanup.
// This number should be smaller then `GetMaximumEntries()` to create some
// headroom. std::nullopt means that `GetMaximumEntries()` should be used.
virtual std::optional<size_t> GetMaximumEntriesAfterCleanup() const;
// Returns a prefix unique to each project, which will be used to create
// database key.
virtual std::string GetProjectPrefix() const = 0;
// Returns the maximum number of strikes after which the project's Autofill
// opportunity stops being offered.
virtual int GetMaxStrikesLimit() const = 0;
// Returns the time delta after which the most recent strike should expire.
// If the Optional is empty, then strikes don't expire.
virtual std::optional<base::TimeDelta> GetExpiryTimeDelta() const = 0;
// Returns whether or not a unique string identifier is required for every
// strike in this project.
virtual bool UniqueIdsRequired() const = 0;
// Returns the time delta to wait for before prompting the feature again. If
// the Optional is empty, then there is no required delay during which the
// feature is blocked.
virtual std::optional<base::TimeDelta> GetRequiredDelaySinceLastStrike()
const;
};
} // namespace autofill
#endif // COMPONENTS_STRIKE_DATABASE_STRIKE_DATABASE_INTEGRATOR_BASE_H_
|