hint_cache.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2018 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. #ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_HINT_CACHE_H_
  5. #define COMPONENTS_OPTIMIZATION_GUIDE_CORE_HINT_CACHE_H_
  6. #include <string>
  7. #include "base/callback.h"
  8. #include "base/containers/lru_cache.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/weak_ptr.h"
  11. #include "base/sequence_checker.h"
  12. #include "base/time/clock.h"
  13. #include "components/optimization_guide/core/memory_hint.h"
  14. #include "components/optimization_guide/core/optimization_guide_store.h"
  15. #include "components/optimization_guide/proto/hints.pb.h"
  16. class GURL;
  17. namespace optimization_guide {
  18. class StoreUpdateData;
  19. using HintLoadedCallback = base::OnceCallback<void(const proto::Hint*)>;
  20. // Contains a set of optimization hints received from the Cacao service. This
  21. // may include hints received from the ComponentUpdater and hints fetched from a
  22. // Cacao Optimization Guide Service API. The availability of hints is queryable
  23. // via host name and full URL. The cache itself consists of a backing store,
  24. // which allows for asynchronous loading of any available host-keyed hint, and
  25. // an MRU host-keyed cache and a url-keyed cache, which can be used to
  26. // synchronously retrieve recently loaded hints keyed by URL or host.
  27. class HintCache {
  28. public:
  29. // Construct the HintCache with an optional backing store and max host-keyed
  30. // cache size. If a backing store is not provided, all hints will only be
  31. // stored in-memory.
  32. explicit HintCache(
  33. base::WeakPtr<OptimizationGuideStore> optimization_guide_store,
  34. int max_host_keyed_memory_cache_size);
  35. HintCache(const HintCache&) = delete;
  36. HintCache& operator=(const HintCache&) = delete;
  37. ~HintCache();
  38. // Initializes the backing store contained within the hint cache, if provided,
  39. // and asynchronously runs the callback after initialization is complete. If
  40. // |purge_existing_data| is set to true, then the cache will purge any
  41. // pre-existing data and begin in a clean state.
  42. void Initialize(bool purge_existing_data, base::OnceClosure callback);
  43. // Returns a StoreUpdateData. During component processing, hints from the
  44. // component are moved into the StoreUpdateData. After component
  45. // processing completes, the component update data is provided to the backing
  46. // store in UpdateComponentHints() and used to update its component hints. In
  47. // the case the provided component version is not newer than the store's
  48. // version, nullptr will be returned by the call.
  49. std::unique_ptr<StoreUpdateData> MaybeCreateUpdateDataForComponentHints(
  50. const base::Version& version) const;
  51. // Returns an UpdateData created by the store to hold updates for fetched
  52. // hints. No version is needed nor applicable for fetched hints. During
  53. // processing of the GetHintsResponse, hints are moved into the update data.
  54. // After processing is complete, the update data is provided to the backing
  55. // store to update hints. |update_time| specifies when the hints within the
  56. // created update data will be scheduled to be updated.
  57. std::unique_ptr<StoreUpdateData> CreateUpdateDataForFetchedHints(
  58. base::Time update_time) const;
  59. // Updates the store's component data using the provided StoreUpdateData
  60. // and asynchronously runs the provided callback after the update finishes.
  61. void UpdateComponentHints(std::unique_ptr<StoreUpdateData> component_data,
  62. base::OnceClosure callback);
  63. // Process |get_hints_response| to be stored in the hint cache store.
  64. // |callback| is asynchronously run when the hints are successfully stored or
  65. // if the store is not available. |update_time| specifies when the hints
  66. // within |get_hints_response| will need to be updated next. |hosts_fetched|
  67. // and |urls_fetched| specifies the hosts and URLs for which specific hints
  68. // were requested to be fetched. It is expected for |this| to keep track of
  69. // the result, even if a hint was not returned for the URL.
  70. void UpdateFetchedHints(
  71. std::unique_ptr<proto::GetHintsResponse> get_hints_response,
  72. base::Time update_time,
  73. const base::flat_set<std::string>& hosts_fetched,
  74. const base::flat_set<GURL>& urls_fetched,
  75. base::OnceClosure callback);
  76. // Purges fetched hints from the owned |optimization_guide_store| that have
  77. // expired.
  78. void PurgeExpiredFetchedHints();
  79. // Purges fetched hints from the owned |optimization_guide_store_| and resets
  80. // both in-memory hint caches.
  81. void ClearFetchedHints();
  82. // Purges fetched hints from the owned |optimization_guide_store_| and resets
  83. // the host-keyed cache.
  84. void ClearHostKeyedHints();
  85. // Returns whether the cache has a hint data for |host| locally (whether
  86. // in the host-keyed cache or persisted on disk).
  87. bool HasHint(const std::string& host);
  88. // Requests that hint data for |host| be loaded asynchronously and passed to
  89. // |callback| if/when loaded.
  90. void LoadHint(const std::string& host, HintLoadedCallback callback);
  91. // Returns the update time provided by |hint_store_|, which specifies when the
  92. // fetched hints within the store are ready to be updated. If |hint_store_| is
  93. // not initialized, base::Time() is returned.
  94. base::Time GetFetchedHintsUpdateTime() const;
  95. // Returns the hint data for |host| if found in the host-keyed cache,
  96. // otherwise nullptr.
  97. const proto::Hint* GetHostKeyedHintIfLoaded(const std::string& host);
  98. // Returns an unepxired hint data for |url| if found in the url-keyed cache,
  99. // otherwise nullptr. If the hint is expired, it is removed from the URL-keyed
  100. // cache. Only HTTP/HTTPS URLs without username and password are supported by
  101. // the URL-keyed cache, if |url| does not meet this criteria, nullptr is
  102. // returned. The returned hint is not guaranteed to remain valid and will
  103. // become invalid if any additional URL-keyed hints are added to the cache
  104. // that evicts the returned hint.
  105. proto::Hint* GetURLKeyedHint(const GURL& url);
  106. // Returns true if the url-keyed cache contains an entry for |url|, even if
  107. // the entry is empty. If a hint exists but is expired, it returns false.
  108. bool HasURLKeyedEntryForURL(const GURL& url);
  109. // Removes any URL-keyed hints that are in |urls|.
  110. void RemoveHintsForURLs(const base::flat_set<GURL>& urls);
  111. // Removes any host-keyed hints that are in |hosts|. Note that this will also
  112. // remove any persisted hints from |hint_store()|. |on_success| will be called
  113. // when the operation completes successfully. If the operation does not
  114. // complete successfully, the callback will not be run so calling code must
  115. // not expect it be called in every circumstance.
  116. void RemoveHintsForHosts(base::OnceClosure on_success,
  117. const base::flat_set<std::string>& hosts);
  118. // Verifies and processes |hints| and moves the ones it supports into
  119. // |update_data| and caches any valid URL keyed hints.
  120. //
  121. // Returns true if there was at least one hint is moved into |update_data|.
  122. bool ProcessAndCacheHints(
  123. google::protobuf::RepeatedPtrField<proto::Hint>* hints,
  124. StoreUpdateData* update_data);
  125. // Returns whether the persistent hint store owned by this is available.
  126. bool IsHintStoreAvailable() const;
  127. // Returns the persistent store for |this|.
  128. base::WeakPtr<optimization_guide::OptimizationGuideStore> hint_store() {
  129. return optimization_guide_store_;
  130. }
  131. // Override |clock_| for testing.
  132. void SetClockForTesting(const base::Clock* clock);
  133. // Add hint to the URL-keyed cache. For testing only.
  134. void AddHintForTesting(const GURL& gurl, std::unique_ptr<proto::Hint> hint);
  135. private:
  136. using HostKeyedHintCache =
  137. base::HashingLRUCache<std::string, std::unique_ptr<MemoryHint>>;
  138. using URLKeyedHintCache =
  139. base::HashingLRUCache<std::string, std::unique_ptr<MemoryHint>>;
  140. // The callback run after the store finishes initialization. This then runs
  141. // the callback initially provided by the Initialize() call.
  142. void OnStoreInitialized(base::OnceClosure callback);
  143. // The callback run after the store finishes loading a hint. This adds the
  144. // loaded hint to |host_keyed_cache_|, potentially purging the least recently
  145. // used element, and then runs the callback initially provided by the
  146. // LoadHint() call.
  147. void OnLoadStoreHint(
  148. const std::string& host,
  149. HintLoadedCallback callback,
  150. const OptimizationGuideStore::EntryKey& store_hint_entry_key,
  151. std::unique_ptr<MemoryHint> hint);
  152. // The backing store used with this hint cache. Set during construction. Not
  153. // owned.
  154. base::WeakPtr<OptimizationGuideStore> optimization_guide_store_;
  155. // The cache of host-keyed hints loaded from the store. Maps store
  156. // EntryKey to Hint proto. This serves two purposes:
  157. // 1. Allows hints to be requested on navigation and retained in memory until
  158. // commit, when they can be synchronously retrieved from the cache.
  159. // 2. Reduces churn of needing to reload hints from frequently visited sites
  160. // multiple times during a session.
  161. HostKeyedHintCache host_keyed_cache_;
  162. // The in-memory cache of URL-keyed hints fetched from the remote optimization
  163. // guide. Maps a full URL to Hint proto. All available URL-keyed hints are
  164. // maintained within the cache and are not persisted to disk.
  165. URLKeyedHintCache url_keyed_hint_cache_;
  166. // The clock used to determine if hints have expired.
  167. raw_ptr<const base::Clock> clock_;
  168. SEQUENCE_CHECKER(sequence_checker_);
  169. // Weak ptr factory to get weak pointer of |this|.
  170. base::WeakPtrFactory<HintCache> weak_ptr_factory_{this};
  171. };
  172. } // namespace optimization_guide
  173. #endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_HINT_CACHE_H_