123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- // Copyright 2021 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_OPTIMIZATION_GUIDE_CORE_HINTS_MANAGER_H_
- #define COMPONENTS_OPTIMIZATION_GUIDE_CORE_HINTS_MANAGER_H_
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/callback_forward.h"
- #include "base/containers/flat_map.h"
- #include "base/containers/flat_set.h"
- #include "base/containers/lru_cache.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/memory/weak_ptr.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/time/clock.h"
- #include "base/timer/timer.h"
- #include "components/optimization_guide/core/hints_component_info.h"
- #include "components/optimization_guide/core/hints_fetcher.h"
- #include "components/optimization_guide/core/optimization_guide_decision.h"
- #include "components/optimization_guide/core/optimization_hints_component_observer.h"
- #include "components/optimization_guide/core/push_notification_manager.h"
- #include "components/optimization_guide/proto/hints.pb.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- class OptimizationGuideLogger;
- class OptimizationGuideNavigationData;
- class OptimizationGuideTestAppInterfaceWrapper;
- class PrefService;
- namespace network {
- class SharedURLLoaderFactory;
- } // namespace network
- namespace optimization_guide {
- class HintCache;
- class HintsFetcherFactory;
- class OptimizationFilter;
- class OptimizationGuideStore;
- class OptimizationMetadata;
- enum class OptimizationTypeDecision;
- class StoreUpdateData;
- class TabUrlProvider;
- class TopHostProvider;
- class HintsManager : public OptimizationHintsComponentObserver,
- public PushNotificationManager::Delegate {
- public:
- HintsManager(
- bool is_off_the_record,
- const std::string& application_locale,
- PrefService* pref_service,
- base::WeakPtr<OptimizationGuideStore> hint_store,
- TopHostProvider* top_host_provider,
- TabUrlProvider* tab_url_provider,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- std::unique_ptr<PushNotificationManager> push_notification_manager,
- OptimizationGuideLogger* optimization_guide_logger);
- ~HintsManager() override;
- HintsManager(const HintsManager&) = delete;
- HintsManager& operator=(const HintsManager&) = delete;
- // Unhooks the observer to |optimization_guide_service_|.
- void Shutdown();
- // Returns the OptimizationGuideDecision from |optimization_type_decision|.
- static OptimizationGuideDecision
- GetOptimizationGuideDecisionFromOptimizationTypeDecision(
- OptimizationTypeDecision optimization_type_decision);
- // OptimizationHintsComponentObserver implementation:
- void OnHintsComponentAvailable(const HintsComponentInfo& info) override;
- // |next_update_closure| is called the next time OnHintsComponentAvailable()
- // is called and the corresponding hints have been updated.
- void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure);
- // Registers the optimization types that have the potential for hints to be
- // called by consumers of the Optimization Guide.
- void RegisterOptimizationTypes(
- const std::vector<proto::OptimizationType>& optimization_types);
- // Returns the optimization types that are registered.
- base::flat_set<proto::OptimizationType> registered_optimization_types()
- const {
- return registered_optimization_types_;
- }
- // Returns whether there is an optimization allowlist loaded for
- // |optimization_type|.
- bool HasLoadedOptimizationAllowlist(
- proto::OptimizationType optimization_type);
- // Returns whether there is an optimization blocklist loaded for
- // |optimization_type|.
- bool HasLoadedOptimizationBlocklist(
- proto::OptimizationType optimization_type);
- // Returns the OptimizationTypeDecision based on the given parameters.
- // |optimization_metadata| will be populated, if applicable.
- OptimizationTypeDecision CanApplyOptimization(
- const GURL& navigation_url,
- proto::OptimizationType optimization_type,
- OptimizationMetadata* optimization_metadata);
- // Invokes |callback| with the decision for the URL contained in |url| and
- // |optimization_type|, when sufficient information has been collected to
- // make the decision.
- virtual void CanApplyOptimization(
- const GURL& url,
- optimization_guide::proto::OptimizationType optimization_type,
- optimization_guide::OptimizationGuideDecisionCallback callback);
- // Invokes |callback| with the decision for |navigation_url| and
- // |optimization_type|, when sufficient information has been collected by
- // |this| to make the decision. Virtual for testing.
- virtual void CanApplyOptimizationAsync(
- const GURL& navigation_url,
- proto::OptimizationType optimization_type,
- OptimizationGuideDecisionCallback callback);
- // Invokes |callback| with the decision for all types contained in
- // |optimization_types| for each URL contained in |urls|, when sufficient
- // information has been collected to make decisions. If information is not
- // available for all URLs, the remote Optimization Guide Service will be
- // contacted to fetch information for those URLs using |request_context|.
- void CanApplyOptimizationOnDemand(
- const std::vector<GURL>& urls,
- const base::flat_set<proto::OptimizationType>& optimization_types,
- proto::RequestContext request_context,
- OnDemandOptimizationGuideDecisionRepeatingCallback callback);
- // Clears all fetched hints from |hint_cache_|.
- void ClearFetchedHints();
- // Clears the host-keyed fetched hints from |hint_cache_|, both the persisted
- // and in memory ones.
- void ClearHostKeyedHints();
- // Overrides |hints_fetcher_factory| for testing.
- void SetHintsFetcherFactoryForTesting(
- std::unique_ptr<HintsFetcherFactory> hints_fetcher_factory);
- // Overrides |clock_| for testing.
- void SetClockForTesting(const base::Clock* clock);
- // Notifies |this| that a navigation with |navigation_data| started.
- // |callback| is run when the request has finished regardless of whether there
- // was actually a hint for that load or not. The callback can be used as a
- // signal for tests.
- void OnNavigationStartOrRedirect(
- OptimizationGuideNavigationData* navigation_data,
- base::OnceClosure callback);
- // Notifies |this| that a navigation with redirect chain
- // |navigation_redirect_chain| has finished.
- void OnNavigationFinish(const std::vector<GURL>& navigation_redirect_chain);
- // Notifies |this| that deferred startup has occurred. This enables |this|
- // to execute background tasks while minimizing the risk of regressing
- // metrics such as jank.
- void OnDeferredStartup();
- // Fetch the hints for the given URLs with the provided |request_context|.
- void FetchHintsForURLs(const std::vector<GURL>& target_urls,
- proto::RequestContext request_context);
- // PushNotificationManager::Delegate:
- void RemoveFetchedEntriesByHintKeys(
- base::OnceClosure on_success,
- proto::KeyRepresentation key_representation,
- const base::flat_set<std::string>& hint_keys) override;
- // Returns true if |this| is allowed to fetch hints at the navigation time for
- // |url|.
- bool IsAllowedToFetchNavigationHints(const GURL& url);
- // Returns the hint cache for |this|.
- HintCache* hint_cache();
- // Returns the persistent store for |this|.
- base::WeakPtr<OptimizationGuideStore> hint_store();
- // Returns the push notification manager for |this|. May be nullptr;
- PushNotificationManager* push_notification_manager();
- // Add hints to the cache with the provided metadata. For testing only.
- void AddHintForTesting(const GURL& url,
- proto::OptimizationType optimization_type,
- const absl::optional<OptimizationMetadata>& metadata);
- private:
- friend class ::OptimizationGuideTestAppInterfaceWrapper;
- friend class HintsManagerTest;
- // Processes the optimization filters contained in the hints component.
- void ProcessOptimizationFilters(
- const google::protobuf::RepeatedPtrField<proto::OptimizationFilter>&
- allowlist_optimization_filters,
- const google::protobuf::RepeatedPtrField<proto::OptimizationFilter>&
- blocklist_optimization_filters);
- // Process a set of optimization filters.
- //
- // |is_allowlist| will be used to ensure that the filters are either uses as
- // allowlists or blocklists.
- void ProcessOptimizationFilterSet(const google::protobuf::RepeatedPtrField<
- proto::OptimizationFilter>& filters,
- bool is_allowlist);
- // Callback run after the hint cache is fully initialized. At this point,
- // the HintsManager is ready to process hints.
- void OnHintCacheInitialized();
- // Updates the cache with the latest hints sent by the Component Updater.
- void UpdateComponentHints(base::OnceClosure update_closure,
- std::unique_ptr<StoreUpdateData> update_data,
- std::unique_ptr<proto::Configuration> config);
- // Called when the hints have been fully updated with the latest hints from
- // the Component Updater. This is used as a signal during tests.
- void OnComponentHintsUpdated(base::OnceClosure update_closure,
- bool hints_updated);
- // Initiates fetching of hints - either immediately over via a timer.
- void InitiateHintsFetchScheduling();
- // Returns the URLs that are currently in the active tab model that do not
- // have a hint available in |hint_cache_|.
- const std::vector<GURL> GetActiveTabURLsToRefresh();
- // Schedules |active_tabs_hints_fetch_timer_| to fire based on the last time a
- // fetch attempt was made.
- void ScheduleActiveTabsHintsFetch();
- // Called to make a request to fetch hints from the remote Optimization Guide
- // Service. Used to fetch hints for origins frequently visited by the user and
- // URLs open in the active tab model.
- void FetchHintsForActiveTabs();
- // Called when the hints for active tabs have been fetched from the remote
- // Optimization Guide Service and are ready for parsing. This is used when
- // fetching hints in batch mode.
- void OnHintsForActiveTabsFetched(
- const base::flat_set<std::string>& hosts_fetched,
- const base::flat_set<GURL>& urls_fetched,
- absl::optional<std::unique_ptr<proto::GetHintsResponse>>
- get_hints_response);
- // Called when the batch update hints have been fetched from the remote
- // Optimization Guide Service and are ready for parsing. This is used when
- // fetching hints on demand or from SRP.
- void OnBatchUpdateHintsFetched(
- int32_t request_id,
- proto::RequestContext request_context,
- const base::flat_set<std::string>& hosts_fetched,
- const base::flat_set<GURL>& urls_fetched,
- const base::flat_set<GURL>& urls_for_callback,
- const base::flat_set<proto::OptimizationType>& optimization_types,
- OnDemandOptimizationGuideDecisionRepeatingCallback callback,
- absl::optional<std::unique_ptr<proto::GetHintsResponse>>
- get_hints_response);
- // Called when information is ready such that we can invoke any callbacks that
- // require returning decisions to consumer features.
- //
- // TODO(crbug/1279536): Clean this up when we clean up some of the existing
- // interfaces.
- void OnBatchUpdateHintsStored(
- const base::flat_set<GURL>& urls_fetched,
- const base::flat_set<proto::OptimizationType>& optimization_types,
- OnDemandOptimizationGuideDecisionRepeatingCallback callback);
- // Creates a hints fetcher and stores it in |batch_update_hints_fetchers_| and
- // returns the request ID associated with the fetch. It is expected to call
- // `CleanUpBatchUpdateHintsFetcher` with the returned request ID once the
- // fetch has finished.
- std::pair<int32_t, HintsFetcher*> CreateAndTrackBatchUpdateHintsFetcher();
- // Called to inform |this| that the batch fetcher with |request_id| is no
- // longer needed removes the request from |batch_update_hints_fetchers_|
- void CleanUpBatchUpdateHintsFetcher(int32_t request_id);
- // Returns decisions for |url| and |optimization_types| based on what's cached
- // locally.
- base::flat_map<proto::OptimizationType, OptimizationGuideDecisionWithMetadata>
- GetDecisionsWithCachedInformationForURLAndOptimizationTypes(
- const GURL& url,
- const base::flat_set<proto::OptimizationType>& optimization_types);
- // Invokes |callback| for |url| and |optimization_types| based on what is
- // cached on device.
- void InvokeOnDemandHintsCallbackForURL(
- const GURL& url,
- const base::flat_set<proto::OptimizationType>& optimization_types,
- OnDemandOptimizationGuideDecisionRepeatingCallback callback);
- // Called when the hints for a navigation have been fetched from the remote
- // Optimization Guide Service and are ready for parsing. This is used when
- // fetching hints in real-time. |navigation_url| is the URL associated with
- // the navigation handle that initiated the fetch.
- // |page_navigation_urls_requested| contains the URLs that were requested by
- // |this| to be fetched. |page_navigation_hosts_requested| contains the hosts
- // that were requested by |this| to be fetched.
- void OnPageNavigationHintsFetched(
- base::WeakPtr<OptimizationGuideNavigationData> navigation_data_weak_ptr,
- const absl::optional<GURL>& navigation_url,
- const base::flat_set<GURL>& page_navigation_urls_requested,
- const base::flat_set<std::string>& page_navigation_hosts_requested,
- absl::optional<std::unique_ptr<proto::GetHintsResponse>>
- get_hints_response);
- // Called when the fetched hints have been stored in |hint_cache| and are
- // ready to be used. This is used when hints were fetched in batch mode.
- void OnFetchedActiveTabsHintsStored();
- // Called when the fetched hints have been stored in |hint_cache| and are
- // ready to be used. This is used when hints were fetched in real-time.
- // |navigation_url| is the URL associated with the navigation handle that
- // initiated the fetch. |page_navigation_hosts_requested| contains the hosts
- // whose hints should be loaded into memory when invoked.
- void OnFetchedPageNavigationHintsStored(
- base::WeakPtr<OptimizationGuideNavigationData> navigation_data_weak_ptr,
- const absl::optional<GURL>& navigation_url,
- const base::flat_set<std::string>& page_navigation_hosts_requested);
- // Returns true if there is a fetch currently in-flight for |navigation_url|.
- bool IsHintBeingFetchedForNavigation(const GURL& navigation_url);
- // Cleans up the hints fetcher for |navigation_url|, if applicable.
- void CleanUpFetcherForNavigation(const GURL& navigation_url);
- // Returns the time when a hints fetch request was last attempted.
- base::Time GetLastHintsFetchAttemptTime() const;
- // Sets the time when a hints fetch was last attempted to |last_attempt_time|.
- void SetLastHintsFetchAttemptTime(base::Time last_attempt_time);
- // Called when the request to load a hint has completed.
- void OnHintLoaded(base::OnceClosure callback,
- const proto::Hint* loaded_hint) const;
- // Loads the hint if available for navigation to |url|.
- // |callback| is run when the request has finished regardless of whether there
- // was actually a hint for that load or not. The callback can be used as a
- // signal for tests.
- void LoadHintForURL(const GURL& url, base::OnceClosure callback);
- // Loads the hint for |host| if available.
- // |callback| is run when the request has finished regardless of whether there
- // was actually a hint for that |host| or not. The callback can be used as a
- // signal for tests.
- void LoadHintForHost(const std::string& host, base::OnceClosure callback);
- // Returns whether there is an optimization type to fetch for. Will return
- // false if no optimization types are registered or if all registered
- // optimization types are covered by optimization filters.
- bool HasOptimizationTypeToFetchFor();
- // Creates a hints fetch for navigation represented by |navigation_data|, if
- // it is allowed. The fetch will include the host and URL of the
- // |navigation_data| if the associated hints for each are not already in the
- // cache.
- void MaybeFetchHintsForNavigation(
- OptimizationGuideNavigationData* navigation_data);
- // If an entry for |navigation_url| is contained in |registered_callbacks_|,
- // it will load the hint for |navigation_url|'s host and upon completion, will
- // invoke the registered callbacks for |navigation_url|.
- void PrepareToInvokeRegisteredCallbacks(const GURL& navigation_url);
- // Invokes the registered callbacks for |navigation_url|, if applicable.
- void OnReadyToInvokeRegisteredCallbacks(const GURL& navigation_url);
- // Whether all information was available to make a decision for
- // |navigation_url| and |optimization type}.
- bool HasAllInformationForDecisionAvailable(
- const GURL& navigation_url,
- proto::OptimizationType optimization_type);
- HintsFetcherFactory* GetHintsFetcherFactory();
- // Returns the number of batch update hints fetches initiated.
- //
- // Exposed here for testing.
- int32_t num_batch_update_hints_fetches_initiated() const {
- return batch_update_hints_fetcher_request_id_;
- }
- // Returns the current active tabs batch update hints fetcher.
- //
- // Exposed here for testing.
- HintsFetcher* active_tabs_batch_update_hints_fetcher() const {
- return active_tabs_batch_update_hints_fetcher_.get();
- }
- // The information of the latest component delivered by
- // |optimization_guide_service_|.
- absl::optional<HintsComponentInfo> hints_component_info_;
- // The component version that failed to process in the last session, if
- // applicable.
- const absl::optional<base::Version> failed_component_version_;
- // The version of the component that is currently being processed.
- absl::optional<base::Version> currently_processing_component_version_;
- // The set of optimization types that have been registered with the hints
- // manager.
- //
- // Should only be read and modified on the UI thread.
- base::flat_set<proto::OptimizationType> registered_optimization_types_;
- // The set of optimization types that the component specified by
- // |component_info_| has optimization filters for.
- base::flat_set<proto::OptimizationType> optimization_types_with_filter_;
- // A map from optimization type to the host filter that holds the allowlist
- // for that type.
- base::flat_map<proto::OptimizationType, std::unique_ptr<OptimizationFilter>>
- allowlist_optimization_filters_;
- // A map from optimization type to the host filter that holds the blocklist
- // for that type.
- base::flat_map<proto::OptimizationType, std::unique_ptr<OptimizationFilter>>
- blocklist_optimization_filters_;
- // A map from URL to a map of callbacks keyed by their optimization type.
- base::flat_map<GURL,
- base::flat_map<proto::OptimizationType,
- std::vector<OptimizationGuideDecisionCallback>>>
- registered_callbacks_;
- // Whether |this| was created for an off the record profile.
- const bool is_off_the_record_;
- // The current applcation locale of Chrome.
- const std::string application_locale_;
- // A reference to the PrefService for this profile. Not owned.
- raw_ptr<PrefService> pref_service_ = nullptr;
- // The hint cache that holds both hints received from the component and
- // fetched from the remote Optimization Guide Service.
- std::unique_ptr<HintCache> hint_cache_;
- // The fetcher that handles making requests for hints for active tabs from
- // the remote Optimization Guide Service.
- std::unique_ptr<HintsFetcher> active_tabs_batch_update_hints_fetcher_;
- // A map from request ID to the fetcher that handles making requests for hints
- // for multiple hosts from the remote Optimization Guide Service.
- base::LRUCache<int32_t, std::unique_ptr<HintsFetcher>>
- batch_update_hints_fetchers_;
- int32_t batch_update_hints_fetcher_request_id_ = 0;
- // A cache keyed by navigation URL to the fetcher making a request for a hint
- // for that URL and/or host to the remote Optimization Guide Service that
- // keeps track of when an entry has been placed in the cache.
- base::LRUCache<GURL, std::unique_ptr<HintsFetcher>>
- page_navigation_hints_fetchers_;
- // The factory used to create hints fetchers. It is mostly used to create
- // new fetchers for use under the page navigation context, but will also be
- // used to create the initial fetcher for the batch update context.
- std::unique_ptr<HintsFetcherFactory> hints_fetcher_factory_;
- // The top host provider that can be queried. Not owned.
- raw_ptr<TopHostProvider> top_host_provider_ = nullptr;
- // The tab URL provider that can be queried. Not owned.
- raw_ptr<TabUrlProvider> tab_url_provider_ = nullptr;
- // The timer used to schedule fetching hints from the remote Optimization
- // Guide Service.
- base::OneShotTimer active_tabs_hints_fetch_timer_;
- // The class that handles push notification processing and informs |this| of
- // what to do through the implemented Delegate above.
- std::unique_ptr<PushNotificationManager> push_notification_manager_;
- // The logger that plumbs the debug logs to the optimization guide
- // internals page. Not owned. Guaranteed to outlive |this|, since the logger
- // and |this| are owned by the optimization guide keyed service.
- raw_ptr<OptimizationGuideLogger> optimization_guide_logger_;
- // The clock used to schedule fetching from the remote Optimization Guide
- // Service.
- raw_ptr<const base::Clock> clock_;
- // Whether fetched hints should be cleared when the store is initialized
- // because a new optimization type was registered.
- bool should_clear_hints_for_new_type_ = false;
- // Used in testing to subscribe to an update event in this class.
- base::OnceClosure next_update_closure_;
- // Background thread where hints processing should be performed.
- //
- // Warning: This must be the last object, so it is destroyed (and flushed)
- // first. This will prevent use-after-free issues where the background thread
- // would access other member variables after they have been destroyed.
- scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
- SEQUENCE_CHECKER(sequence_checker_);
- // Used to get |weak_ptr_| to self.
- base::WeakPtrFactory<HintsManager> weak_ptr_factory_{this};
- };
- } // namespace optimization_guide
- #endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_HINTS_MANAGER_H_
|