File: verdict_cache_manager.h

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 (327 lines) | stat: -rw-r--r-- 14,465 bytes parent folder | download | duplicates (3)
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
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
// Copyright 2019 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_SAFE_BROWSING_CORE_BROWSER_VERDICT_CACHE_MANAGER_H_
#define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_VERDICT_CACHE_MANAGER_H_

#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_cache.h"
#include "components/safe_browsing/core/browser/safe_browsing_sync_observer.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"
#include "components/safe_browsing/core/common/proto/realtimeapi.pb.h"
#include "components/safe_browsing/core/common/proto/safebrowsingv5.pb.h"
#include "url/gurl.h"

class HostContentSettingsMap;
class SafeBrowsingServiceTest;

namespace safe_browsing {

using ReusedPasswordAccountType =
    LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType;

// Structure: http://screen/YaNfDRYrcnk.png.
class VerdictCacheManager : public history::HistoryServiceObserver,
                            public KeyedService {
 public:
  VerdictCacheManager(history::HistoryService* history_service,
                      scoped_refptr<HostContentSettingsMap> content_settings,
                      PrefService* pref_service,
                      std::unique_ptr<SafeBrowsingSyncObserver> sync_observer);
  VerdictCacheManager(const VerdictCacheManager&) = delete;
  VerdictCacheManager& operator=(const VerdictCacheManager&) = delete;
  VerdictCacheManager(VerdictCacheManager&&) = delete;
  VerdictCacheManager& operator=(const VerdictCacheManager&&) = delete;

  ~VerdictCacheManager() override;

  struct DictionaryCounts {
    // The number of entries in a dictionary before removal due to expiry.
    size_t num_entries = 0;
    // The number of entries removed from the dictionary due to expiry.
    size_t num_removed_expired_entries = 0;
  };

  base::WeakPtr<VerdictCacheManager> GetWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

  // KeyedService:
  // Called before the actual deletion of the object.
  void Shutdown() override;

  // Stores |verdict| in |content_settings_| based on its |trigger_type|, |url|,
  // reused |password_type|, |verdict| and |receive_time|.
  void CachePhishGuardVerdict(
      LoginReputationClientRequest::TriggerType trigger_type,
      ReusedPasswordAccountType password_type,
      const LoginReputationClientResponse& verdict,
      const base::Time& receive_time);

  // Looks up |content_settings_| to find the cached verdict response. If
  // verdict is not available or is expired, return VERDICT_TYPE_UNSPECIFIED.
  // Can be called on any thread.
  LoginReputationClientResponse::VerdictType GetCachedPhishGuardVerdict(
      const GURL& url,
      LoginReputationClientRequest::TriggerType trigger_type,
      ReusedPasswordAccountType password_type,
      LoginReputationClientResponse* out_response);

  // Gets the total number of verdicts of the specified |trigger_type| we cached
  // for this profile. This counts both expired and active verdicts.
  size_t GetStoredPhishGuardVerdictCount(
      LoginReputationClientRequest::TriggerType trigger_type);

  // Stores |verdict| in |content_settings_| based on its |verdict| and
  // |receive_time|.
  void CacheRealTimeUrlVerdict(const RTLookupResponse& verdict,
                               const base::Time& receive_time);

  // Looks up |content_settings_| to find the cached verdict response. If
  // verdict is not available or is expired, return VERDICT_TYPE_UNSPECIFIED.
  // Otherwise, the most matching theat info will be copied to out_threat_info.
  // Can be called on any thread.
  RTLookupResponse::ThreatInfo::VerdictType GetCachedRealTimeUrlVerdict(
      const GURL& url,
      RTLookupResponse::ThreatInfo* out_threat_info);

  safe_browsing::ClientSideDetectionType
  GetCachedRealTimeUrlClientSideDetectionType(const GURL& url);

  // Returns true if the most matching verdict to the provided url contains a
  // LlamaForcedTriggerInfo. |out_llama_forced_trigger_info| will hold the cache
  // result.
  bool GetCachedRealTimeLlamaForcedTriggerInfo(
      const GURL& url,
      safe_browsing::LlamaForcedTriggerInfo* out_llama_forced_trigger_info);

  // Creates a page load token that is tied with the hostname of the |url|.
  // The token is stored in memory.
  ChromeUserPopulation::PageLoadToken CreatePageLoadToken(const GURL& url);

  // Gets the page load token for the hostname of the |url|. Returns an empty
  // token if the token is not found.
  ChromeUserPopulation::PageLoadToken GetPageLoadToken(const GURL& url);

  // Stores the results of a hash-prefix real-time lookup into a cache object.
  void CacheHashPrefixRealTimeLookupResults(
      const std::vector<std::string>& requested_hash_prefixes,
      const std::vector<V5::FullHash>& response_full_hashes,
      const V5::Duration& cache_duration);

  // Searches the hash-prefix real-time cache object for the requested
  // |hash_prefixes|.
  std::unordered_map<std::string, std::vector<V5::FullHash>>
  GetCachedHashPrefixRealTimeLookupResults(
      const std::set<std::string>& hash_prefixes);

  // Overridden from history::HistoryServiceObserver.
  void OnHistoryDeletions(history::HistoryService* history_service,
                          const history::DeletionInfo& deletion_info) override;

  void HistoryServiceBeingDeleted(
      history::HistoryService* history_service) override;

  // Called by browsing data remover.
  void OnCookiesDeleted();

  // Returns true if an artificial URL has been provided either using
  // command-line flags or through a test.
  static bool has_artificial_cached_url();

  void StopCleanUpTimerForTesting();
  void SetPageLoadTokenForTesting(const GURL& url,
                                  ChromeUserPopulation::PageLoadToken token);

 private:
  friend class ::SafeBrowsingServiceTest;
  friend class SafeBrowsingBlockingPageAsyncChecksTestBase;
  friend class SafeBrowsingBlockingPageRealTimeUrlCheckTest;
  friend class SafeBrowsingBlockingPageHashRealTimeCheckTest;
  friend class VerdictCacheManagerTest;
  friend class ArtificialHashRealTimeVerdictCacheManagerTest;
  friend class ArtificialEnterpriseVerdictCacheManagerTest;
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest, TestCleanUpExpiredVerdict);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestCleanUpExpiredVerdictWithInvalidEntry);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestRemoveCachedVerdictOnURLsDeleted);
  FRIEND_TEST_ALL_PREFIXES(
      VerdictCacheManagerTest,
      TestRemoveRealTimeUrlCheckCachedVerdictOnURLsDeleted);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestCleanUpExpiredVerdictInBackground);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestCleanUpVerdictOlderThanUpperBound);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestCleanUpTooManyExpiredRealTimeUrlEntries);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestCleanupWithInvalidRealTimeUrlCacheDictionary);
  FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
                           TestSkipRealTimeUrlCleanupOptimization);
  FRIEND_TEST_ALL_PREFIXES(ArtificialHashRealTimeVerdictCacheManagerTest,
                           TestCachePopulated);
  FRIEND_TEST_ALL_PREFIXES(ArtificialEnterpriseVerdictCacheManagerTest,
                           TestArtificialEnterpriseBlockCache);
  FRIEND_TEST_ALL_PREFIXES(ArtificialEnterpriseVerdictCacheManagerTest,
                           TestArtificialEnterpriseWarnCache);

  // Enum representing the reason why page load tokens are cleared. Used to log
  // histograms. Entries must not be removed or reordered.
  enum class ClearReason {
    kSafeBrowsingStateChanged = 0,
    kCookiesDeleted = 1,
    kSyncStateChanged = 2,

    kMaxValue = kSyncStateChanged
  };

  void ScheduleNextCleanUpAfterInterval(base::TimeDelta interval);

  // Removes all the expired verdicts from cache.
  void CleanUpExpiredVerdicts();
  void CleanUpExpiredPhishGuardVerdicts();
  void CleanUpExpiredRealTimeUrlCheckVerdicts();
  void CleanUpExpiredPageLoadTokens();
  void CleanUpAllPageLoadTokens(ClearReason reason);
  void CleanUpExpiredHashPrefixRealTimeLookupResults();

  // Returns the default max entries that can be removed in a cleanup task.
  // The maximum can be modified by tests.
  int GetMaxRemovedEntriesCount();

  // Helper method to remove content settings when URLs are deleted. If
  // |all_history| is true, removes all cached verdicts. Otherwise it removes
  // all verdicts associated with the deleted URLs in |deleted_rows|.
  void RemoveContentSettingsOnURLsDeleted(bool all_history,
                                          const history::URLRows& deleted_rows);
  bool RemoveExpiredPhishGuardVerdicts(
      LoginReputationClientRequest::TriggerType trigger_type,
      base::Value::Dict& cache_dictionary);
  // Computes the number of entries in `cache_dictionary`. If
  // `remove_expired_verdicts` is true, it will also remove any expired entries
  // from `cache_dictionary` and return the number of removed entries.
  DictionaryCounts ComputeCountsAndMaybeRemoveExpiredRealTimeUrlCheckVerdicts(
      base::Value::Dict& cache_dictionary,
      bool remove_expired_verdicts);

  size_t GetPhishGuardVerdictCountForURL(
      const GURL& url,
      LoginReputationClientRequest::TriggerType trigger_type);

  // This adds a cached verdict for a URL that has artificially been marked as
  // unsafe using the command line flag "mark_as_real_time_phishing". This
  // applies to URL real-time lookups.
  void CacheArtificialUnsafeRealTimeUrlVerdictFromSwitch();

  // This adds a cached verdict for a URL that has artificially been marked as
  // safe or unsafe (depending on |verdict_type| and |threat_type|). This
  // applies to URL real-time lookups.
  void CacheArtificialRealTimeUrlVerdict(
      const std::string& url_string,
      RTLookupResponse::ThreatInfo::VerdictType verdict_type,
      std::optional<RTLookupResponse::ThreatInfo::ThreatType> threat_type);

  // This adds a cached verdict for a URL that has artificially been marked as
  // unsafe using the command line flag "mark_as_phish_guard_phishing". This
  // applies to Phishguard pings.
  void CacheArtificialUnsafePhishGuardVerdictFromSwitch();

  // This adds a cached verdict for a URL that has artificially been marked as
  // unsafe using the command line flag
  // "mark_as_hash_prefix_real_time_phishing". This applies to hash-prefix
  // real-time lookups.
  void CacheArtificialUnsafeHashRealTimeLookupVerdictFromSwitch();

  // This adds a cached verdict for a URL that has artificially been marked as
  // safe or unsafe (depending on |is_unsafe|). This applies to hash-prefix
  // real-time lookups.
  void CacheArtificialHashRealTimeLookupVerdict(const std::string& url_spec,
                                                bool is_unsafe);

  // This adds a cached verdict for a URL that has artificially been marked as
  // blocked for Enterprise Url Filtering by using the command line flag
  // "mark_as_enterprise_blocked".
  void CacheArtificialEnterpriseBlockedVerdictFromSwitch();

  // This adds a cached verdict for a URL that has artificially been marked as
  // flagged for Enterprise Url Filtering by using the command line flag
  // "mark_as_enterprise_warned".
  void CacheArtificialEnterpriseWarnedVerdictFromSwitch();

  // Resets the value of |has_artificial_cached_url_| back to false. If a unit
  // test sets an artificial URL, it is responsible for resetting the value
  // when the test completes so that it's not still true when later unit tests
  // run.
  static void ResetHasArtificialCachedUrlForTesting();

  // Number of verdict stored for this profile for password on focus pings.
  std::optional<size_t> stored_verdict_count_password_on_focus_;

  // Number of verdict stored for this profile for protected password entry
  // pings.
  std::optional<size_t> stored_verdict_count_password_entry_;

  // Whether there might be any verdicts stored for this profile for real time
  // url check pings. This property is an optimization to avoid unneeded
  // cleanups if nothing is stored. There are cases where this value can be true
  // but there are no stored verdicts (e.g. if a verdict was cached, but the
  // specific URL's history gets wiped).
  bool has_stored_verdicts_real_time_url_check_;

  // Used only for tests. Defaults to false. Can be set to true to simulate
  // that the real-time URL verdict `cache_dictionary` has corrupt data.
  bool corrupt_real_time_cache_dictionary_override_;

  // A map of page load tokens, keyed by the hostname.
  base::flat_map<std::string, ChromeUserPopulation::PageLoadToken>
      page_load_token_map_;

  base::ScopedObservation<history::HistoryService,
                          history::HistoryServiceObserver>
      history_service_observation_{this};

  // Content settings maps associated with this instance.
  scoped_refptr<HostContentSettingsMap> content_settings_;

  base::OneShotTimer cleanup_timer_;

  PrefChangeRegistrar pref_change_registrar_;

  std::unique_ptr<SafeBrowsingSyncObserver> sync_observer_;

  // The local cache object for hash-prefix real-time lookups.
  std::unique_ptr<HashRealTimeCache> hash_realtime_cache_ =
      std::make_unique<HashRealTimeCache>();

  bool is_shut_down_ = false;

  std::optional<int> max_removed_entries_count_override_;

  base::WeakPtrFactory<VerdictCacheManager> weak_factory_{this};

  static bool has_artificial_cached_url_;
};

}  // namespace safe_browsing

#endif  // COMPONENTS_SAFE_BROWSING_CORE_BROWSER_VERDICT_CACHE_MANAGER_H_