// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_MODEL_OPTIMIZATION_GUIDE_SERVICE_H_
#define IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_MODEL_OPTIMIZATION_GUIDE_SERVICE_H_
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#import "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/optimization_guide/core/optimization_guide_decider.h"
#include "components/optimization_guide/core/optimization_guide_decision.h"
#include "components/optimization_guide/core/optimization_guide_model_provider.h"
#include "components/optimization_guide/core/optimization_metadata.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "ios/chrome/browser/download/model/background_service/background_download_service_factory.h"
#include "url/gurl.h"
namespace leveldb_proto {
class ProtoDatabaseProvider;
} // namespace leveldb_proto
namespace network {
class SharedURLLoaderFactory;
} // namespace network
namespace optimization_guide {
class TabUrlProvider;
class TopHostProvider;
class OptimizationGuideStore;
class OptimizationTargetModelObserver;
class PredictionManager;
class HintsManager;
} // namespace optimization_guide
namespace signin {
class IdentityManager;
} // namespace signin
class BrowserList;
class OptimizationGuideLogger;
class OptimizationGuideNavigationData;
class PrefService;
// A BrowserState keyed service that is used to own the underlying Optimization
// Guide components. This is a rough copy of the OptimizationGuideKeyedService
// in //chrome/browser that is used for non-iOS. It cannot be directly used due
// to the platform differences of the common data structures -
// NavigationContext vs NavigationHandle, BrowserState vs Profile, etc.
// TODO(crbug.com/40785700): Add support for clearing the hints when browsing
// data is cleared.
class OptimizationGuideService
: public KeyedService,
public optimization_guide::OptimizationGuideDecider,
public optimization_guide::OptimizationGuideModelProvider {
public:
// BackgroundDownloadService is only available once the profile is fully
// initialized and that cannot be done as part of `Initialize`. Get a provider
// to retrieve the service when it is needed.
using BackgroundDownloadServiceProvider =
base::OnceCallback<download::BackgroundDownloadService*(void)>;
OptimizationGuideService(
leveldb_proto::ProtoDatabaseProvider* proto_db_provider,
const base::FilePath& profile_path,
bool off_the_record,
const std::string& application_locale,
base::WeakPtr<optimization_guide::OptimizationGuideStore> hint_store,
PrefService* pref_service,
BrowserList* browser_list,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
BackgroundDownloadServiceProvider background_download_service_provider,
signin::IdentityManager* identity_manager);
~OptimizationGuideService() override;
OptimizationGuideService(const OptimizationGuideService&) = delete;
OptimizationGuideService& operator=(const OptimizationGuideService&) = delete;
// Some initialization parts must be done once the browser_state is fully
// initialized.
void DoFinalInit(download::BackgroundDownloadService*
background_download_service = nullptr);
// optimization_guide::OptimizationGuideDecider implementation:
void RegisterOptimizationTypes(
const std::vector<optimization_guide::proto::OptimizationType>&
optimization_types) override;
void CanApplyOptimization(
const GURL& url,
optimization_guide::proto::OptimizationType optimization_type,
optimization_guide::OptimizationGuideDecisionCallback callback) override;
optimization_guide::OptimizationGuideDecision CanApplyOptimization(
const GURL& url,
optimization_guide::proto::OptimizationType optimization_type,
optimization_guide::OptimizationMetadata* optimization_metadata) override;
// optimization_guide::OptimizationGuideModelProvider implementation:
void AddObserverForOptimizationTargetModel(
optimization_guide::proto::OptimizationTarget optimization_target,
const std::optional<optimization_guide::proto::Any>& model_metadata,
optimization_guide::OptimizationTargetModelObserver* observer) override;
void RemoveObserverForOptimizationTargetModel(
optimization_guide::proto::OptimizationTarget optimization_target,
optimization_guide::OptimizationTargetModelObserver* observer) override;
// These functions are not private but are for optimization_guide component
// internal use only.
// Called when browsing data is cleared for the user.
void OnBrowsingDataRemoved();
// Getter for the hint manager.
optimization_guide::HintsManager* GetHintsManager();
// Getter for the prediction manager.
optimization_guide::PredictionManager* GetPredictionManager();
// Getter for the optimization guide logger.
OptimizationGuideLogger* GetOptimizationGuideLogger() {
return optimization_guide_logger_.get();
}
// Adds hints for a URL with provided metadata to the optimization guide. For
// testing purposes only. This will flush any callbacks for `url` that were
// registered via `CanApplyOptimization`. If no applicable callbacks were
// registered, this will just add the hint for later use.
void AddHintForTesting(
const GURL& url,
optimization_guide::proto::OptimizationType optimization_type,
const std::optional<optimization_guide::OptimizationMetadata>& metadata);
private:
friend class OptimizationGuideServiceTest;
friend class OptimizationGuideTabHelper;
friend class OptimizationGuideTestAppInterfaceWrapper;
// Notifies `hints_manager_` that the navigation associated with
// `navigation_data` has started or redirected.
void OnNavigationStartOrRedirect(
OptimizationGuideNavigationData* navigation_data);
// Notifies `hints_manager_` that the navigation associated with
// `navigation_redirect_chain` has finished.
void OnNavigationFinish(const std::vector<GURL>& navigation_redirect_chain);
// KeyedService implementation:
void Shutdown() override;
// optimization_guide::OptimizationGuideDecider implementation:
void CanApplyOptimizationOnDemand(
const std::vector<GURL>& urls,
const base::flat_set<optimization_guide::proto::OptimizationType>&
optimization_types,
optimization_guide::proto::RequestContext request_context,
optimization_guide::OnDemandOptimizationGuideDecisionRepeatingCallback
callback,
std::optional<optimization_guide::proto::RequestContextMetadata>
request_context_metadata) override;
// The store of hints.
std::unique_ptr<optimization_guide::OptimizationGuideStore> hint_store_;
// Manages the storing, loading, and fetching of hints.
std::unique_ptr<optimization_guide::HintsManager> hints_manager_;
// The top host provider to use for fetching information for the user's top
// hosts. Will be null if the user has not consented to this type of browser
// behavior.
std::unique_ptr<optimization_guide::TopHostProvider> top_host_provider_;
// The tab URL provider to use for fetching information for the user's active
// tabs. Will be null if the user is off the record.
std::unique_ptr<optimization_guide::TabUrlProvider> tab_url_provider_;
raw_ptr<OptimizationGuideLogger> optimization_guide_logger_;
// Manages the storing, loading, and evaluating of optimization target
// prediction models.
std::unique_ptr<optimization_guide::PredictionManager> prediction_manager_;
// The PrefService of the browser state this service is linked to.
const raw_ptr<PrefService> pref_service_ = nullptr;
// Whether the service is linked to an incognito browser state.
const bool off_the_record_ = false;
SEQUENCE_CHECKER(sequence_checker_);
};
#endif // IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_MODEL_OPTIMIZATION_GUIDE_SERVICE_H_