blob: 87271618db68dff6fd3d11461b09464dfb97a807 [file] [log] [blame]
// Copyright 2021 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.
#include "weblayer/browser/download_service_factory.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "components/background_fetch/download_client.h"
#include "components/download/content/factory/download_service_factory_helper.h"
#include "components/download/content/factory/navigation_monitor_factory.h"
#include "components/download/public/background_service/basic_task_scheduler.h"
#include "components/download/public/background_service/blob_context_getter_factory.h"
#include "components/download/public/background_service/clients.h"
#include "components/download/public/background_service/download_service.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "weblayer/browser/browser_context_impl.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/system_network_context_manager.h"
namespace weblayer {
namespace {
// Like DownloadServiceFactory, this is a BrowserContextKeyedServiceFactory
// although the Chrome version is a SimpleKeyedServiceFactory.
class SimpleDownloadManagerCoordinatorFactory
: public BrowserContextKeyedServiceFactory {
public:
// Returns singleton instance of SimpleDownloadManagerCoordinatorFactory.
static SimpleDownloadManagerCoordinatorFactory* GetInstance() {
static base::NoDestructor<SimpleDownloadManagerCoordinatorFactory> instance;
return instance.get();
}
static download::SimpleDownloadManagerCoordinator* GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<download::SimpleDownloadManagerCoordinator*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
SimpleDownloadManagerCoordinatorFactory(
const SimpleDownloadManagerCoordinatorFactory& other) = delete;
SimpleDownloadManagerCoordinatorFactory& operator=(
const SimpleDownloadManagerCoordinatorFactory& other) = delete;
private:
friend class base::NoDestructor<SimpleDownloadManagerCoordinatorFactory>;
SimpleDownloadManagerCoordinatorFactory()
: BrowserContextKeyedServiceFactory(
"SimpleDownloadManagerCoordinator",
BrowserContextDependencyManager::GetInstance()) {}
~SimpleDownloadManagerCoordinatorFactory() override = default;
// BrowserContextKeyedService:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override {
auto* service_instance = new download::SimpleDownloadManagerCoordinator(
{}, !context->IsOffTheRecord());
service_instance->SetSimpleDownloadManager(
content::BrowserContext::GetDownloadManager(context), true);
return service_instance;
}
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override {
return context;
}
};
// An implementation of BlobContextGetterFactory that returns the
// BlobStorageContext without delay (since WebLayer must be in "full browser"
// mode).
class DownloadBlobContextGetterFactory
: public download::BlobContextGetterFactory {
public:
explicit DownloadBlobContextGetterFactory(
content::BrowserContext* browser_context)
: browser_context_(browser_context) {}
DownloadBlobContextGetterFactory(const DownloadBlobContextGetterFactory&) =
delete;
DownloadBlobContextGetterFactory& operator=(
const DownloadBlobContextGetterFactory&) = delete;
~DownloadBlobContextGetterFactory() override = default;
private:
// download::BlobContextGetterFactory:
void RetrieveBlobContextGetter(
download::BlobContextGetterCallback callback) override {
std::move(callback).Run(
content::BrowserContext::GetBlobStorageContext(browser_context_));
}
content::BrowserContext* browser_context_;
};
} // namespace
// static
download::DownloadService* DownloadServiceFactory::GetForBrowserContext(
content::BrowserContext* browser_context) {
return static_cast<download::DownloadService*>(
GetInstance()->GetServiceForBrowserContext(browser_context,
/*create=*/true));
}
// static
DownloadServiceFactory* DownloadServiceFactory::GetInstance() {
static base::NoDestructor<DownloadServiceFactory> factory;
return factory.get();
}
DownloadServiceFactory::DownloadServiceFactory()
: BrowserContextKeyedServiceFactory(
"DownloadServiceFactory",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(SimpleDownloadManagerCoordinatorFactory::GetInstance());
DependsOn(download::NavigationMonitorFactory::GetInstance());
}
KeyedService* DownloadServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
SimpleFactoryKey* key = ProfileImpl::FromBrowserContext(context)
->GetBrowserContext()
->simple_factory_key();
auto clients = std::make_unique<download::DownloadClientMap>();
clients->insert(std::make_pair(
download::DownloadClient::BACKGROUND_FETCH,
std::make_unique<background_fetch::DownloadClient>(context)));
// Build in memory download service for an off the record context.
if (context->IsOffTheRecord()) {
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
content::GetIOThreadTaskRunner({});
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
SystemNetworkContextManager::GetInstance()->GetSharedURLLoaderFactory();
return download::BuildInMemoryDownloadService(
key, std::move(clients), content::GetNetworkConnectionTracker(),
base::FilePath(),
std::make_unique<DownloadBlobContextGetterFactory>(context),
io_task_runner, url_loader_factory)
.release();
}
// Build download service for a regular browsing context.
base::FilePath storage_dir;
if (!context->IsOffTheRecord() && !context->GetPath().empty()) {
const base::FilePath::CharType kDownloadServiceStorageDirname[] =
FILE_PATH_LITERAL("Download Service");
storage_dir = context->GetPath().Append(kDownloadServiceStorageDirname);
}
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT});
leveldb_proto::ProtoDatabaseProvider* proto_db_provider =
content::BrowserContext::GetDefaultStoragePartition(context)
->GetProtoDatabaseProvider();
return download::BuildDownloadService(
key, std::move(clients), content::GetNetworkConnectionTracker(),
storage_dir,
SimpleDownloadManagerCoordinatorFactory::GetForBrowserContext(
context),
proto_db_provider, background_task_runner,
std::make_unique<download::BasicTaskScheduler>(base::BindRepeating(
[](content::BrowserContext* context) {
return DownloadServiceFactory::GetForBrowserContext(context);
},
context)))
.release();
}
content::BrowserContext* DownloadServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return context;
}
} // namespace weblayer