chromium/ios/chrome/browser/download/model/background_service/background_download_service_factory.cc

// 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.

#include "ios/chrome/browser/download/model/background_service/background_download_service_factory.h"

#include <utility>

#include "base/no_destructor.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/default_clock.h"
#include "components/download/internal/background_service/client_set.h"
#include "components/download/internal/background_service/download_store.h"
#include "components/download/internal/background_service/file_monitor_impl.h"
#include "components/download/internal/background_service/init_aware_background_download_service.h"
#include "components/download/internal/background_service/ios/background_download_service_impl.h"
#include "components/download/internal/background_service/ios/background_download_task_helper.h"
#include "components/download/internal/background_service/logger_impl.h"
#include "components/download/internal/background_service/model_impl.h"
#include "components/download/internal/background_service/proto/entry.pb.h"
#include "components/download/public/background_service/background_download_service.h"
#include "components/download/public/background_service/clients.h"
#include "components/keyed_service/ios/browser_state_dependency_manager.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
#include "ios/chrome/browser/optimization_guide/model/prediction_model_download_client.h"
#include "ios/chrome/browser/shared/model/profile/profile_ios.h"

// The root directory for background download system, under browser state
// directory.
const base::FilePath::CharType kDownloadServiceStorageDir[] =
    FILE_PATH_LITERAL("Download Service");

// The directory for background download database.
const base::FilePath::CharType kEntryDBStorageDir[] =
    FILE_PATH_LITERAL("EntryDB");

// The directory for downloaded files.
const base::FilePath::CharType kFilesStorageDir[] = FILE_PATH_LITERAL("Files");

// static
download::BackgroundDownloadService*
BackgroundDownloadServiceFactory::GetForBrowserState(
    ChromeBrowserState* browser_state) {
  return static_cast<download::BackgroundDownloadService*>(
      GetInstance()->GetServiceForBrowserState(browser_state, true));
}

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

BackgroundDownloadServiceFactory::BackgroundDownloadServiceFactory()
    : BrowserStateKeyedServiceFactory(
          "BackgroundDownloadService",
          BrowserStateDependencyManager::GetInstance()) {}

BackgroundDownloadServiceFactory::~BackgroundDownloadServiceFactory() = default;

std::unique_ptr<KeyedService>
BackgroundDownloadServiceFactory::BuildServiceInstanceFor(
    web::BrowserState* context) const {
  DCHECK(!context->IsOffTheRecord());
  auto clients = std::make_unique<download::DownloadClientMap>();
  // Clients should be registered here.
  if (optimization_guide::features::IsModelDownloadingEnabled()) {
    auto prediction_model_download_client =
        std::make_unique<optimization_guide::PredictionModelDownloadClient>(
            ChromeBrowserState::FromBrowserState(context));
    clients->insert(std::make_pair(
        download::DownloadClient::OPTIMIZATION_GUIDE_PREDICTION_MODELS,
        std::move(prediction_model_download_client)));
  }
  return BuildServiceWithClients(context, std::move(clients));
}

std::unique_ptr<KeyedService>
BackgroundDownloadServiceFactory::BuildServiceWithClients(
    web::BrowserState* context,
    std::unique_ptr<download::DownloadClientMap> clients) const {
  auto client_set = std::make_unique<download::ClientSet>(std::move(clients));
  base::FilePath storage_dir =
      context->GetStatePath().Append(kDownloadServiceStorageDir);
  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
  auto entry_db = context->GetProtoDatabaseProvider()->GetDB<protodb::Entry>(
      leveldb_proto::ProtoDbType::DOWNLOAD_STORE,
      storage_dir.Append(kEntryDBStorageDir), background_task_runner);
  auto store = std::make_unique<download::DownloadStore>(std::move(entry_db));
  auto model = std::make_unique<download::ModelImpl>(std::move(store));
  base::FilePath files_storage_dir = storage_dir.Append(kFilesStorageDir);
  auto file_monitor = std::make_unique<download::FileMonitorImpl>(
      files_storage_dir, background_task_runner);
  auto logger = std::make_unique<download::LoggerImpl>();
  auto* logger_ptr = logger.get();
  auto service = std::make_unique<download::BackgroundDownloadServiceImpl>(
      std::move(client_set), std::move(model),
      download::BackgroundDownloadTaskHelper::Create(), std::move(file_monitor),
      files_storage_dir, std::move(logger), logger_ptr,
      base::DefaultClock::GetInstance());
  logger_ptr->SetLogSource(service.get());
  auto init_aware_service =
      std::make_unique<download::InitAwareBackgroundDownloadService>(
          std::move(service));
  return init_aware_service;
}