// 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.
#import "ios/chrome/browser/optimization_guide/model/optimization_guide_service_factory.h"
#import "base/feature_list.h"
#import "base/path_service.h"
#import "components/keyed_service/ios/browser_state_dependency_manager.h"
#import "components/optimization_guide/core/optimization_guide_constants.h"
#import "components/optimization_guide/core/optimization_guide_features.h"
#import "components/optimization_guide/core/optimization_guide_store.h"
#import "components/optimization_guide/core/prediction_manager.h"
#import "ios/chrome/browser/optimization_guide/model/ios_chrome_hints_manager.h"
#import "ios/chrome/browser/optimization_guide/model/ios_chrome_prediction_model_store.h"
#import "ios/chrome/browser/optimization_guide/model/optimization_guide_service.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
#import "ios/chrome/browser/shared/model/paths/paths.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/signin/model/identity_manager_factory.h"
#import "services/network/public/cpp/shared_url_loader_factory.h"
namespace {
std::unique_ptr<KeyedService> BuildOptimizationGuideService(
web::BrowserState* context) {
ChromeBrowserState* chrome_browser_state =
ChromeBrowserState::FromBrowserState(context);
ChromeBrowserState* original_browser_state =
chrome_browser_state->GetOriginalChromeBrowserState();
DCHECK(chrome_browser_state);
// Regardless of whether the profile is off the record or not, initialize the
// Optimization Guide with the database associated with the original profile.
auto* proto_db_provider = original_browser_state->GetProtoDatabaseProvider();
base::FilePath profile_path = original_browser_state->GetStatePath();
base::WeakPtr<optimization_guide::OptimizationGuideStore> hint_store;
if (chrome_browser_state->IsOffTheRecord()) {
OptimizationGuideService* original_ogs =
OptimizationGuideServiceFactory::GetForBrowserState(
original_browser_state);
DCHECK(original_ogs);
hint_store = original_ogs->GetHintsManager()->hint_store();
}
return std::make_unique<OptimizationGuideService>(
proto_db_provider, profile_path, chrome_browser_state->IsOffTheRecord(),
GetApplicationContext()->GetApplicationLocale(), hint_store,
chrome_browser_state->GetPrefs(),
BrowserListFactory::GetForBrowserState(chrome_browser_state),
chrome_browser_state->GetSharedURLLoaderFactory(),
base::BindOnce(
[](ChromeBrowserState* browser_state) {
return BackgroundDownloadServiceFactory::GetForBrowserState(
browser_state);
},
// base::Unretained is safe here because the callback is owned
// by PredictionManager which is a transitively owned by
// OptimizationGuideService (a keyed service that is
// killed before ChromeBrowserState is deallocated).
base::Unretained(chrome_browser_state)),
IdentityManagerFactory::GetForBrowserState(chrome_browser_state));
}
}
// static
OptimizationGuideService* OptimizationGuideServiceFactory::GetForBrowserState(
ChromeBrowserState* context) {
if (!optimization_guide::features::IsOptimizationHintsEnabled())
return nullptr;
return static_cast<OptimizationGuideService*>(
GetInstance()->GetServiceForBrowserState(context, /*create=*/true));
}
// static
OptimizationGuideServiceFactory*
OptimizationGuideServiceFactory::GetInstance() {
static base::NoDestructor<OptimizationGuideServiceFactory> instance;
return instance.get();
}
// static
void OptimizationGuideServiceFactory::InitializePredictionModelStore() {
base::FilePath model_downloads_dir;
base::PathService::Get(ios::DIR_USER_DATA, &model_downloads_dir);
model_downloads_dir = model_downloads_dir.Append(
optimization_guide::kOptimizationGuideModelStoreDirPrefix);
optimization_guide::IOSChromePredictionModelStore::GetInstance()->Initialize(
model_downloads_dir);
}
OptimizationGuideServiceFactory::OptimizationGuideServiceFactory()
: BrowserStateKeyedServiceFactory(
"OptimizationGuideService",
BrowserStateDependencyManager::GetInstance()) {
DependsOn(BackgroundDownloadServiceFactory::GetInstance());
DependsOn(BrowserListFactory::GetInstance());
DependsOn(IdentityManagerFactory::GetInstance());
}
OptimizationGuideServiceFactory::~OptimizationGuideServiceFactory() = default;
// static
BrowserStateKeyedServiceFactory::TestingFactory
OptimizationGuideServiceFactory::GetDefaultFactory() {
return base::BindRepeating(&BuildOptimizationGuideService);
}
std::unique_ptr<KeyedService>
OptimizationGuideServiceFactory::BuildServiceInstanceFor(
web::BrowserState* context) const {
return BuildOptimizationGuideService(context);
}
bool OptimizationGuideServiceFactory::ServiceIsCreatedWithBrowserState() const {
return optimization_guide::features::IsOptimizationHintsEnabled();
}
web::BrowserState* OptimizationGuideServiceFactory::GetBrowserStateToUse(
web::BrowserState* context) const {
return GetBrowserStateOwnInstanceInIncognito(context);
}
bool OptimizationGuideServiceFactory::ServiceIsNULLWhileTesting() const {
return true;
}