blob: ad8b47cc9f64f475c7f317720f3b3f01671598e1 [file] [log] [blame]
// Copyright 2019 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 CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MANAGER_H_
#define CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MANAGER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "base/timer/timer.h"
#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h"
#include "components/optimization_guide/optimization_guide_enums.h"
#include "components/optimization_guide/proto/models.pb.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "url/origin.h"
namespace base {
class FilePath;
} // namespace base
namespace content {
class NavigationHandle;
} // namespace content
namespace leveldb_proto {
class ProtoDatabaseProvider;
} // namespace leveldb_proto
namespace network {
class SharedURLLoaderFactory;
} // namespace network
class PrefService;
class Profile;
namespace optimization_guide {
enum class OptimizationGuideDecision;
class OptimizationGuideStore;
class PredictionModel;
class PredictionModelFetcher;
class TopHostProvider;
using HostModelFeaturesMRUCache =
base::HashingMRUCache<std::string, base::flat_map<std::string, float>>;
// A PredictionManager supported by the optimization guide that makes an
// OptimizationTargetDecision by evaluating the corresponding prediction model
// for an OptimizationTarget.
class PredictionManager
: public network::NetworkQualityTracker::EffectiveConnectionTypeObserver {
public:
PredictionManager(
const std::vector<optimization_guide::proto::OptimizationTarget>&
optimization_targets_at_initialization,
const base::FilePath& profile_path,
leveldb_proto::ProtoDatabaseProvider* database_provider,
TopHostProvider* top_host_provider,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
PrefService* pref_service,
Profile* profile);
PredictionManager(
const std::vector<optimization_guide::proto::OptimizationTarget>&
optimization_targets_at_initialization,
std::unique_ptr<OptimizationGuideStore> model_and_features_store,
TopHostProvider* top_host_provider,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
PrefService* pref_service,
Profile* profile);
~PredictionManager() override;
// Register the optimization targets that may have ShouldTargetNavigtation
// requested by consumers of the Optimization Guide.
void RegisterOptimizationTargets(
const std::vector<proto::OptimizationTarget>& optimization_targets);
// Determine if the navigation matches the critieria for
// |optimization_target|. Return kUnknown if a PredictionModel for the
// optimization target is not registered and kModelNotAvailableOnClient if the
// if model for the optimization target is not currently on the client.
OptimizationTargetDecision ShouldTargetNavigation(
content::NavigationHandle* navigation_handle,
proto::OptimizationTarget optimization_target);
// Update |session_fcp_| and |previous_fcp_| with |fcp|.
void UpdateFCPSessionStatistics(base::TimeDelta fcp);
OptimizationGuideSessionStatistic* GetFCPSessionStatisticsForTesting() const {
return const_cast<OptimizationGuideSessionStatistic*>(&session_fcp_);
}
// network::NetworkQualityTracker::EffectiveConnectionTypeObserver
// implementation:
void OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType type) override;
// Set the prediction model fetcher for testing.
void SetPredictionModelFetcherForTesting(
std::unique_ptr<PredictionModelFetcher> prediction_model_fetcher);
PredictionModelFetcher* prediction_model_fetcher() const {
return prediction_model_fetcher_.get();
}
OptimizationGuideStore* model_and_features_store() const {
return model_and_features_store_.get();
}
// Return the optimization targets that are registered.
base::flat_set<optimization_guide::proto::OptimizationTarget>
registered_optimization_targets() const {
return registered_optimization_targets_;
}
// Override |clock_| for testing.
void SetClockForTesting(const base::Clock* clock);
// Clear host model features from the in memory host model features map and
// from the models and features store.
void ClearHostModelFeatures();
protected:
// Return the prediction model for the optimization target used by this
// PredictionManager for testing.
PredictionModel* GetPredictionModelForTesting(
proto::OptimizationTarget optimization_target) const;
// Return the host model features for all hosts used by this
// PredictionManager for testing.
const HostModelFeaturesMRUCache* GetHostModelFeaturesForTesting() const;
// Returns the host model features for a host if available.
base::Optional<base::flat_map<std::string, float>>
GetHostModelFeaturesForHost(const std::string& host) const;
// Return the set of features that each host in |host_model_features_map_|
// contains for testing.
base::flat_set<std::string> GetSupportedHostModelFeaturesForTesting() const;
// Create a PredictionModel, virtual for testing.
virtual std::unique_ptr<PredictionModel> CreatePredictionModel(
const proto::PredictionModel& model) const;
// Process |host_model_features| to be stored in memory in the host model
// features map for immediate use and asynchronously write them to the model
// and features store to be persisted.
void UpdateHostModelFeatures(
const google::protobuf::RepeatedPtrField<proto::HostModelFeatures>&
host_model_features);
// Process |prediction_models| to be stored in the in memory optimization
// target prediction model map for immediate use and asynchronously write the
// models to the model and features store to be persisted.
void UpdatePredictionModels(
const google::protobuf::RepeatedPtrField<proto::PredictionModel>&
prediction_models);
private:
// Called on construction to register optimization targets, initialize the
// prediction model and host model features store, and register as an observer
// to the network quality tracker.
void Initialize(const std::vector<proto::OptimizationTarget>&
optimization_targets_at_intialization);
// Construct and return a map containing the current feature values for the
// requested set of model features. The host model features cache is updated
// based on if host model features were used.
base::flat_map<std::string, float> BuildFeatureMap(
content::NavigationHandle* navigation_handle,
const base::flat_set<std::string>& model_features);
// Calculate and return the current value for the client feature specified
// by |model_feature|. Return nullopt if the client does not support the
// model feature.
base::Optional<float> GetValueForClientFeature(
const std::string& model_feature,
content::NavigationHandle* navigation_handle) const;
// Called to make a request to fetch models and host model features from the
// remote Optimization Guide Service. Used to fetch models for the registered
// optimization targets as well as the host model features for top hosts
// needed to evaluate these models.
void FetchModelsAndHostModelFeatures();
// Callback when the models and host model features have been fetched from the
// remote Optimization Guide Service and are ready for parsing. Processes the
// prediction models and the host model features in the response and stores
// them for use. The metadata entry containing the time that updates should be
// fetched from the remote Optimization Guide Service is updated, even when
// the response is empty.
void OnModelsAndHostFeaturesFetched(
base::Optional<std::unique_ptr<proto::GetModelsResponse>>
get_models_response_data);
// Callback run after the model and host model features store is fully
// initialized. The prediction manager can load models from
// the store for registered optimization targets. |store_is_ready_| is set to
// true.
void OnStoreInitialized();
// Callback run after prediction models are stored in
// |model_and_features_store_|.
void OnPredictionModelsStored();
// Callback run after host model features are stored in
// |model_and_features_store_|. |fetch_timer_| is stopped and the timer is
// rescheduled based on when models and host model features should be fetched
// again.
void OnHostModelFeaturesStored();
// Request the store to load all the host model features it contains. This
// must be completed before any prediction models can be loaded from the
// store.
void LoadHostModelFeatures();
// Callback run after host model features are loaded from the store and are
// ready to be processed and placed in |host_model_features_map_|.
// |host_model_features_loaded_| is set to true when called. Prediction models
// for all registered optimization targets that are not already loaded are
// requested to be loaded.
void OnLoadHostModelFeatures(
std::unique_ptr<std::vector<proto::HostModelFeatures>>
all_host_model_features);
// Load models for every target in |optimization_targets| that have not yet
// been loaded from the store.
void LoadPredictionModels(
const base::flat_set<proto::OptimizationTarget>& optimization_targets);
// Callback run after a prediction model is loaded from the store.
// |prediction_model| is used to construct a PredictionModel capable of making
// prediction for the appropriate optimization target.
void OnLoadPredictionModel(
std::unique_ptr<proto::PredictionModel> prediction_model);
// Process |model| into a PredictionModel object and store it in the
// |optimization_target_prediction_model_map_|. Return true if a prediction
// model object was created and successfully stored, otherwise false.
bool ProcessAndStorePredictionModel(const proto::PredictionModel& model);
// Process |host_model_features| from the into host model features
// usable by the PredictionManager. The processed host model features are
// stored in |host_model_features_map_|. Return true if host model features
// can be constructed and successfully stored, otherwise, return false.
bool ProcessAndStoreHostModelFeatures(
const proto::HostModelFeatures& host_model_features);
// Return the time when a prediction model and host model features fetch was
// last attempted.
base::Time GetLastFetchAttemptTime() const;
// Set the last time when a prediction model and host model features fetch
// was last attempted to |last_attempt_time|.
void SetLastModelAndFeaturesFetchAttemptTime(base::Time last_attempt_time);
// Determine whether to schedule fetching new prediction models and host model
// features or fetch immediately due to override.
void MaybeScheduleModelAndHostModelFeaturesFetch();
// Schedule |fetch_timer_| to fire based on:
// 1. The update time for host model features in the store and
// 2. The last time a fetch attempt was made.
void ScheduleModelsAndHostModelFeaturesFetch();
// A map of optimization target to the prediction model capable of making
// an optimization target decision for it.
base::flat_map<proto::OptimizationTarget, std::unique_ptr<PredictionModel>>
optimization_target_prediction_model_map_;
// The set of optimization targets that have been registered with the
// prediction manager.
base::flat_set<proto::OptimizationTarget> registered_optimization_targets_;
// A MRU cache of host to host model features known to the prediction manager.
HostModelFeaturesMRUCache host_model_features_cache_;
// The current session's FCP statistics for HTTP/HTTPS navigations.
OptimizationGuideSessionStatistic session_fcp_;
// A float representation of the time to FCP of the previous HTTP/HTTPS page
// load. This is nullopt when no previous page load exists (the first page
// load of a session).
base::Optional<float> previous_load_fcp_ms_;
// The fetcher than handles making requests to update the models and host
// model features from the remote Optimization Guide Service.
std::unique_ptr<PredictionModelFetcher> prediction_model_fetcher_;
// The top host provider that can be queried. Not owned.
TopHostProvider* top_host_provider_ = nullptr;
// The optimization guide store that contains prediction models and host
// model features from the remote Optimization Guide Service.
std::unique_ptr<OptimizationGuideStore> model_and_features_store_;
// A stored response from a model and host model features fetch used to hold
// models to be stored once host model features are processed and stored.
std::unique_ptr<proto::GetModelsResponse> get_models_response_data_to_store_;
// The URL loader factory used for fetching model and host feature updates
// from the remote Optimization Guide Service.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// The current estimate of the EffectiveConnectionType.
net::EffectiveConnectionType current_effective_connection_type_ =
net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
// A reference to the PrefService for this profile. Not owned.
PrefService* pref_service_ = nullptr;
// A reference to the profile. Not owned.
Profile* profile_ = nullptr;
// The timer used to schedule fetching prediction models and host model
// features from the remote Optimization Guide Service.
base::OneShotTimer fetch_timer_;
// The clock used to schedule fetching from the remote Optimization Guide
// Service.
const base::Clock* clock_;
// Whether the |model_and_features_store_| is initialized and ready for use.
bool store_is_ready_ = false;
// Whether host model features have been loaded from the store and are ready
// for use.
bool host_model_features_loaded_ = false;
SEQUENCE_CHECKER(sequence_checker_);
// Used to get |weak_ptr_| to self on the UI thread.
base::WeakPtrFactory<PredictionManager> ui_weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PredictionManager);
};
} // namespace optimization_guide
#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MANAGER_H_