blob: 0d82024001c0ba1691d386696878720ab071aed7 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_
#define COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_
#include <string>
#include "base/callback.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/previews/content/hint_cache_store.h"
namespace previews {
using HintLoadedCallback =
base::OnceCallback<void(const optimization_guide::proto::Hint*)>;
// Contains a set of optimization hints received from the Cacao service. This
// may include hints received from the ComponentUpdater and hints fetched from a
// Cacao Optimization Guide Service API. The availability of hints is queryable
// via host name. The cache itself consists of a backing store, which allows for
// asynchronous loading of any available hint, and an MRU memory cache, which
// can be used to synchronously retrieve recently loaded hints.
class HintCache {
public:
// Construct the HintCache with a backing store and an optional max memory
// cache size. While |hint_store| is required, |max_memory_cache_hints| is
// optional and the default max size will be used if it is not provided.
explicit HintCache(
std::unique_ptr<HintCacheStore> hint_store,
base::Optional<int> max_memory_cache_hints = base::Optional<int>());
~HintCache();
// Initializes the backing store contained within the hint cache and
// asynchronously runs the callback after initialization is complete.
// If |purge_existing_data| is set to true, then the cache will purge any
// pre-existing data and begin in a clean state.
void Initialize(bool purge_existing_data, base::OnceClosure callback);
// Returns a ComponentUpdateData created by the store, based upon the provided
// component version. During component processing, hints from the component
// are moved into the component update data. After component processing
// completes, the component update data is provided to the backing store in
// UpdateComponentData() and used to update its component hints. In the case
// the provided component version is not newer than the store's version,
// nullptr will be returned by the call.
std::unique_ptr<HintCacheStore::ComponentUpdateData>
MaybeCreateComponentUpdateData(const base::Version& version) const;
// Updates the store's component data using the provided ComponentUpdateData
// and asynchronously runs the provided callback after the update finishes.
void UpdateComponentData(
std::unique_ptr<HintCacheStore::ComponentUpdateData> component_data,
base::OnceClosure callback);
// Returns whether the cache has a hint data for |host| locally (whether
// in memory or persisted on disk).
bool HasHint(const std::string& host) const;
// Requests that hint data for |host| be loaded asynchronously and passed to
// |callback| if/when loaded.
void LoadHint(const std::string& host, HintLoadedCallback callback);
// Returns the hint data for |host| if found in memory, otherwise nullptr.
const optimization_guide::proto::Hint* GetHintIfLoaded(
const std::string& host);
private:
using StoreHintMemoryCache =
base::HashingMRUCache<HintCacheStore::EntryKey,
std::unique_ptr<optimization_guide::proto::Hint>>;
// The callback run after the store finishes initialization. This then runs
// the callback initially provided by the Initialize() call.
void OnStoreInitialized(base::OnceClosure callback);
// The callback run after the store finishes loading a hint. This adds the
// loaded hint to |memory_cache_|, potentially purging the least recently
// used element, and then runs the callback initially provided by the
// LoadHint() call.
void OnLoadStoreHint(HintLoadedCallback callback,
const HintCacheStore::EntryKey& store_hint_entry_key,
std::unique_ptr<optimization_guide::proto::Hint> hint);
// Finds the most specific host suffix of the host name for which the store
// has a hint and populates |out_hint_entry_key| with the hint's corresponding
// entry key. Returns true if a hint was successfully found.
bool FindHintEntryKey(const std::string& host,
HintCacheStore::EntryKey* out_hint_entry_key) const;
// The backing store used with this hint cache. Set during construction.
const std::unique_ptr<HintCacheStore> hint_store_;
// The in-memory cache of hints loaded from the store. Maps store EntryKey to
// Hint proto. This servers two purposes:
// 1. Allows hints to be requested on navigation and retained in memory until
// commit, when they can be synchronously retrieved from the cache.
// 2. Reduces churn of needing to reload hints from frequently visited sites
// multiple times during a session.
StoreHintMemoryCache memory_cache_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(HintCache);
};
} // namespace previews
#endif // COMPONENTS_PREVIEWS_CONTENT_HINT_CACHE_H_