chromium/ios/chrome/browser/visited_url_ranking/model/visited_url_ranking_service_factory.mm

// Copyright 2024 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/visited_url_ranking/model/visited_url_ranking_service_factory.h"

#import "components/history_clusters/core/config.h"
#import "components/keyed_service/core/service_access_type.h"
#import "components/keyed_service/ios/browser_state_dependency_manager.h"
#import "components/visited_url_ranking/internal/history_url_visit_data_fetcher.h"
#import "components/visited_url_ranking/internal/session_url_visit_data_fetcher.h"
#import "components/visited_url_ranking/internal/transformer/bookmarks_url_visit_aggregates_transformer.h"
#import "components/visited_url_ranking/internal/transformer/history_url_visit_aggregates_categories_transformer.h"
#import "components/visited_url_ranking/internal/transformer/history_url_visit_aggregates_visibility_score_transformer.h"
#import "components/visited_url_ranking/internal/transformer/recency_filter_transformer.h"
#import "components/visited_url_ranking/internal/transformer/url_visit_aggregates_segmentation_metrics_transformer.h"
#import "components/visited_url_ranking/internal/visited_url_ranking_service_impl.h"
#import "components/visited_url_ranking/public/url_visit_util.h"
#import "components/visited_url_ranking/public/visited_url_ranking_service.h"
#import "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h"
#import "ios/chrome/browser/history/model/history_service_factory.h"
#import "ios/chrome/browser/segmentation_platform/model/segmentation_platform_service_factory.h"
#import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/sync/model/session_sync_service_factory.h"
#import "ios/chrome/browser/visited_url_ranking/model/ios_tab_model_url_visit_data_fetcher.h"

// static
visited_url_ranking::VisitedURLRankingService*
VisitedURLRankingServiceFactory::GetForBrowserState(ChromeBrowserState* state) {
  return static_cast<visited_url_ranking::VisitedURLRankingService*>(
      GetInstance()->GetServiceForBrowserState(state, true));
}

VisitedURLRankingServiceFactory::VisitedURLRankingServiceFactory()
    : BrowserStateKeyedServiceFactory(
          "VisitedURLRanking",
          BrowserStateDependencyManager::GetInstance()) {
  DependsOn(SessionSyncServiceFactory::GetInstance());
  DependsOn(ios::HistoryServiceFactory::GetInstance());
  DependsOn(ios::BookmarkModelFactory::GetInstance());
  DependsOn(
      segmentation_platform::SegmentationPlatformServiceFactory::GetInstance());
}

// static
VisitedURLRankingServiceFactory*
VisitedURLRankingServiceFactory::GetInstance() {
  static base::NoDestructor<VisitedURLRankingServiceFactory> instance;
  return instance.get();
}

VisitedURLRankingServiceFactory::~VisitedURLRankingServiceFactory() {}

std::unique_ptr<KeyedService>
VisitedURLRankingServiceFactory::BuildServiceInstanceFor(
    web::BrowserState* context) const {
  ChromeBrowserState* browser_state =
      ChromeBrowserState::FromBrowserState(context);
  std::map<visited_url_ranking::Fetcher,
           std::unique_ptr<visited_url_ranking::URLVisitDataFetcher>>
      data_fetchers;

  data_fetchers.emplace(
      visited_url_ranking::Fetcher::kTabModel,
      std::make_unique<visited_url_ranking::IOSTabModelURLVisitDataFetcher>(
          browser_state));

  sync_sessions::SessionSyncService* session_sync_service =
      SessionSyncServiceFactory::GetForBrowserState(browser_state);
  if (session_sync_service) {
    data_fetchers.emplace(
        visited_url_ranking::Fetcher::kSession,
        std::make_unique<visited_url_ranking::SessionURLVisitDataFetcher>(
            session_sync_service));
  }
  auto* history_service = ios::HistoryServiceFactory::GetForBrowserState(
      browser_state, ServiceAccessType::IMPLICIT_ACCESS);
  if (history_service) {
    data_fetchers.emplace(
        visited_url_ranking::Fetcher::kHistory,
        std::make_unique<visited_url_ranking::HistoryURLVisitDataFetcher>(
            history_service));
  }

  std::map<visited_url_ranking::URLVisitAggregatesTransformType,
           std::unique_ptr<visited_url_ranking::URLVisitAggregatesTransformer>>
      transformers = {};

  auto* segmentation_platform_service = segmentation_platform::
      SegmentationPlatformServiceFactory::GetForBrowserState(browser_state);
  transformers.emplace(
      visited_url_ranking::URLVisitAggregatesTransformType::
          kSegmentationMetricsData,
      std::make_unique<visited_url_ranking::
                           URLVisitAggregatesSegmentationMetricsTransformer>(
          segmentation_platform_service));

  // TODO(crbug.com/329242209): Add various aggregate transformers (e.g,
  // shopping) to the service's map of supported transformers.
  auto* bookmark_model =
      ios::BookmarkModelFactory::GetForBrowserState(browser_state);
  if (bookmark_model) {
    auto bookmarks_transformer = std::make_unique<
        visited_url_ranking::BookmarksURLVisitAggregatesTransformer>(
        bookmark_model);
    transformers.emplace(
        visited_url_ranking::URLVisitAggregatesTransformType::kBookmarkData,
        std::move(bookmarks_transformer));
  }

  transformers.emplace(
      visited_url_ranking::URLVisitAggregatesTransformType::
          kHistoryVisibilityScoreFilter,
      std::make_unique<visited_url_ranking::
                           HistoryURLVisitAggregatesVisibilityScoreTransformer>(
          history_clusters::Config().content_visibility_threshold));
  transformers.emplace(
      visited_url_ranking::URLVisitAggregatesTransformType::
          kHistoryCategoriesFilter,
      std::make_unique<
          visited_url_ranking::HistoryURLVisitAggregatesCategoriesTransformer>(
          base::flat_set<std::string>(
              visited_url_ranking::kBlocklistedCategories.begin(),
              visited_url_ranking::kBlocklistedCategories.end())));

  transformers.emplace(
      visited_url_ranking::URLVisitAggregatesTransformType::kRecencyFilter,
      std::make_unique<visited_url_ranking::RecencyFilterTransformer>());

  return std::make_unique<visited_url_ranking::VisitedURLRankingServiceImpl>(
      segmentation_platform_service, std::move(data_fetchers),
      std::move(transformers));
}