1 // Copyright 2019 The Chromium Authors. All rights reserved.
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_SAFE_BROWSING_CORE_VERDICT_CACHE_MANAGER_H_
6 #define COMPONENTS_SAFE_BROWSING_CORE_VERDICT_CACHE_MANAGER_H_
7 
8 #include "base/gtest_prod_util.h"
9 #include "base/memory/scoped_refptr.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/scoped_observation.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "base/values.h"
15 #include "components/content_settings/core/browser/host_content_settings_map.h"
16 #include "components/history/core/browser/history_service.h"
17 #include "components/history/core/browser/history_service_observer.h"
18 #include "components/keyed_service/core/keyed_service.h"
19 #include "components/safe_browsing/core/proto/csd.pb.h"
20 #include "components/safe_browsing/core/proto/realtimeapi.pb.h"
21 #include "url/gurl.h"
22 
23 class HostContentSettingsMap;
24 
25 namespace safe_browsing {
26 
27 using ReusedPasswordAccountType =
28     LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType;
29 
30 // Structure: http://screen/YaNfDRYrcnk.png.
31 class VerdictCacheManager : public history::HistoryServiceObserver,
32                             public KeyedService {
33  public:
34   explicit VerdictCacheManager(
35       history::HistoryService* history_service,
36       scoped_refptr<HostContentSettingsMap> content_settings);
37   VerdictCacheManager(const VerdictCacheManager&) = delete;
38   VerdictCacheManager& operator=(const VerdictCacheManager&) = delete;
39   VerdictCacheManager(VerdictCacheManager&&) = delete;
40   VerdictCacheManager& operator=(const VerdictCacheManager&&) = delete;
41 
42   ~VerdictCacheManager() override;
43 
GetWeakPtr()44   base::WeakPtr<VerdictCacheManager> GetWeakPtr() {
45     return weak_factory_.GetWeakPtr();
46   }
47 
48   // KeyedService:
49   // Called before the actual deletion of the object.
50   void Shutdown() override;
51 
52   // Stores |verdict| in |content_settings_| based on its |trigger_type|, |url|,
53   // reused |password_type|, |verdict| and |receive_time|.
54   void CachePhishGuardVerdict(
55       LoginReputationClientRequest::TriggerType trigger_type,
56       ReusedPasswordAccountType password_type,
57       const LoginReputationClientResponse& verdict,
58       const base::Time& receive_time);
59 
60   // Looks up |content_settings_| to find the cached verdict response. If
61   // verdict is not available or is expired, return VERDICT_TYPE_UNSPECIFIED.
62   // Can be called on any thread.
63   LoginReputationClientResponse::VerdictType GetCachedPhishGuardVerdict(
64       const GURL& url,
65       LoginReputationClientRequest::TriggerType trigger_type,
66       ReusedPasswordAccountType password_type,
67       LoginReputationClientResponse* out_response);
68 
69   // Gets the total number of verdicts of the specified |trigger_type| we cached
70   // for this profile. This counts both expired and active verdicts.
71   size_t GetStoredPhishGuardVerdictCount(
72       LoginReputationClientRequest::TriggerType trigger_type);
73 
74   // Stores |verdict| in |content_settings_| based on its |url|, |verdict| and
75   // |receive_time|.
76   // |store_old_cache| is used for compatibility test. It is set to true only
77   // when we need to store an old cache for testing.
78   // TODO(crbug.com/1049376): |store_old_cache| should be removed once
79   // |cache_expression| field is deprecated.
80   void CacheRealTimeUrlVerdict(const GURL& url,
81                                const RTLookupResponse& verdict,
82                                const base::Time& receive_time,
83                                bool store_old_cache);
84 
85   // Looks up |content_settings_| to find the cached verdict response. If
86   // verdict is not available or is expired, return VERDICT_TYPE_UNSPECIFIED.
87   // Otherwise, the most matching theat info will be copied to out_threat_info.
88   // Can be called on any thread.
89   RTLookupResponse::ThreatInfo::VerdictType GetCachedRealTimeUrlVerdict(
90       const GURL& url,
91       RTLookupResponse::ThreatInfo* out_threat_info);
92 
93   // Overridden from history::HistoryServiceObserver.
94   void OnURLsDeleted(history::HistoryService* history_service,
95                      const history::DeletionInfo& deletion_info) override;
96 
97   void HistoryServiceBeingDeleted(
98       history::HistoryService* history_service) override;
99 
100   // Returns true if an artificial unsafe URL has been provided using the
101   // command-line flag "mark_as_real_time_phishing".
102   static bool has_artificial_unsafe_url();
103 
104   void StopCleanUpTimerForTesting();
105 
106  private:
107   friend class SafeBrowsingBlockingPageRealTimeUrlCheckTest;
108   FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest, TestCleanUpExpiredVerdict);
109   FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
110                            TestCleanUpExpiredVerdictWithInvalidEntry);
111   FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
112                            TestRemoveCachedVerdictOnURLsDeleted);
113   FRIEND_TEST_ALL_PREFIXES(
114       VerdictCacheManagerTest,
115       TestRemoveRealTimeUrlCheckCachedVerdictOnURLsDeleted);
116   FRIEND_TEST_ALL_PREFIXES(VerdictCacheManagerTest,
117                            TestCleanUpExpiredVerdictInBackground);
118 
119   void ScheduleNextCleanUpAfterInterval(base::TimeDelta interval);
120 
121   // Removes all the expired verdicts from cache.
122   void CleanUpExpiredVerdicts();
123   void CleanUpExpiredPhishGuardVerdicts();
124   void CleanUpExpiredRealTimeUrlCheckVerdicts();
125 
126   // Helper method to remove content settings when URLs are deleted. If
127   // |all_history| is true, removes all cached verdicts. Otherwise it removes
128   // all verdicts associated with the deleted URLs in |deleted_rows|.
129   void RemoveContentSettingsOnURLsDeleted(bool all_history,
130                                           const history::URLRows& deleted_rows);
131   bool RemoveExpiredPhishGuardVerdicts(
132       LoginReputationClientRequest::TriggerType trigger_type,
133       base::Value* cache_dictionary);
134   bool RemoveExpiredRealTimeUrlCheckVerdicts(base::Value* cache_dictionary);
135 
136   size_t GetPhishGuardVerdictCountForURL(
137       const GURL& url,
138       LoginReputationClientRequest::TriggerType trigger_type);
139   // This method is only used for testing.
140   size_t GetRealTimeUrlCheckVerdictCountForURL(const GURL& url);
141   // Gets the total number of RealTimeUrlCheck verdicts we cached
142   // for this profile. This counts both expired and active verdicts.
143   size_t GetStoredRealTimeUrlCheckVerdictCount();
144 
145   // This adds a cached verdict for a URL that has artificially been marked as
146   // unsafe using the command line flag "mark_as_real_time_phishing".
147   void CacheArtificialVerdict();
148 
149   // Number of verdict stored for this profile for password on focus pings.
150   base::Optional<size_t> stored_verdict_count_password_on_focus_;
151 
152   // Number of verdict stored for this profile for protected password entry
153   // pings.
154   base::Optional<size_t> stored_verdict_count_password_entry_;
155 
156   // Number of verdict stored for this profile for real time url check pings.
157   base::Optional<size_t> stored_verdict_count_real_time_url_check_;
158 
159   base::ScopedObservation<history::HistoryService,
160                           history::HistoryServiceObserver>
161       history_service_observation_{this};
162 
163   // Content settings maps associated with this instance.
164   scoped_refptr<HostContentSettingsMap> content_settings_;
165 
166   base::OneShotTimer cleanup_timer_;
167 
168   base::WeakPtrFactory<VerdictCacheManager> weak_factory_{this};
169 
170   static bool has_artificial_unsafe_url_;
171 };
172 
173 }  // namespace safe_browsing
174 
175 #endif  // COMPONENTS_SAFE_BROWSING_CORE_VERDICT_CACHE_MANAGER_H_
176