Skip to content

Commit

Permalink
Background Download: Incognito mode support.
Browse files Browse the repository at this point in the history
This CL implements more functionality for background download to support
incognito mode, the feature is behind a flag and disabled.

Major changes includes:

1. InMemoryDownloadDriver and tests, similar to
content::DownloadManagerImpl and download::DownloadDriverImpl. Extract
InMemoryDownload to a virtual base class for test.

2. A series of classes that don't do any db IO or file IO, and hook up
the pipeline to Chrome layer in DownloadServiceFactory.

3. Expose storage::BlobStorageContext in content/public, since download
now needs to use this API to save data to blob.

Bug: 795809
Change-Id: Ib7f388fe7e86f9697625dfbb0da3689afbd824f6
Reviewed-on: https://chromium-review.googlesource.com/903372
Reviewed-by: Peter Beverloo <peter@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: David Trainor <dtrainor@chromium.org>
Commit-Queue: Xing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#535791}
  • Loading branch information
Xing Liu authored and Commit Bot committed Feb 9, 2018
1 parent 5a06e5c commit 8986047
Show file tree
Hide file tree
Showing 30 changed files with 948 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ BackgroundFetchDownloadClient::~BackgroundFetchDownloadClient() = default;
void BackgroundFetchDownloadClient::OnServiceInitialized(
bool state_lost,
const std::vector<download::DownloadMetaData>& downloads) {
content::BackgroundFetchDelegate* delegate =
browser_context_->GetBackgroundFetchDelegate();

// TODO(crbug.com/766082): Support incognito mode in
// BackgroundFetchDelegateFactory, currently |delegate| will be nullptr in
// incognito mode.
if (!delegate)
return;

delegate_ = static_cast<BackgroundFetchDelegateImpl*>(
browser_context_->GetBackgroundFetchDelegate())
->GetWeakPtr();
Expand Down
69 changes: 47 additions & 22 deletions chrome/browser/download/download_service_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <memory>
#include <utility>

#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
Expand All @@ -21,10 +22,14 @@
#include "components/download/content/factory/download_service_factory.h"
#include "components/download/public/background_service/clients.h"
#include "components/download/public/background_service/download_service.h"
#include "components/download/public/background_service/features.h"
#include "components/download/public/background_service/task_scheduler.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/offline_pages/features/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "net/url_request/url_request_context_getter.h"

#if defined(OS_ANDROID)
#include "chrome/browser/android/download/service/download_task_scheduler.h"
Expand Down Expand Up @@ -58,38 +63,58 @@ KeyedService* DownloadServiceFactory::BuildServiceInstanceFor(
auto clients = base::MakeUnique<download::DownloadClientMap>();

#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
clients->insert(std::make_pair(
download::DownloadClient::OFFLINE_PAGE_PREFETCH,
base::MakeUnique<offline_pages::OfflinePrefetchDownloadClient>(context)));
// Offline prefetch doesn't support incognito.
if (!context->IsOffTheRecord()) {
clients->insert(std::make_pair(
download::DownloadClient::OFFLINE_PAGE_PREFETCH,
base::MakeUnique<offline_pages::OfflinePrefetchDownloadClient>(
context)));
}
#endif // BUILDFLAG(ENABLE_OFFLINE_PAGES)

clients->insert(
std::make_pair(download::DownloadClient::BACKGROUND_FETCH,
base::MakeUnique<BackgroundFetchDownloadClient>(context)));

auto* download_manager = content::BrowserContext::GetDownloadManager(context);

base::FilePath storage_dir;
if (!context->IsOffTheRecord() && !context->GetPath().empty()) {
storage_dir =
context->GetPath().Append(chrome::kDownloadServiceStorageDirname);
}

scoped_refptr<base::SequencedTaskRunner> background_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND});

std::unique_ptr<download::TaskScheduler> task_scheduler;

// Build in memory download service for incognito profile.
if (context->IsOffTheRecord() &&
base::FeatureList::IsEnabled(download::kDownloadServiceIncognito)) {
scoped_refptr<net::URLRequestContextGetter> url_request_context =
content::BrowserContext::GetDefaultStoragePartition(
Profile::FromBrowserContext(context))
->GetURLRequestContext();
content::BrowserContext::BlobContextGetter blob_context_getter =
content::BrowserContext::GetBlobStorageContext(context);
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::IO);

return download::BuildInMemoryDownloadService(
context, std::move(clients), base::FilePath(), url_request_context,
blob_context_getter, io_task_runner);
} else {
// Build download service for normal profile.
base::FilePath storage_dir;
if (!context->IsOffTheRecord() && !context->GetPath().empty()) {
storage_dir =
context->GetPath().Append(chrome::kDownloadServiceStorageDirname);
}
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND});

std::unique_ptr<download::TaskScheduler> task_scheduler;
#if defined(OS_ANDROID)
task_scheduler = base::MakeUnique<download::android::DownloadTaskScheduler>();
task_scheduler =
base::MakeUnique<download::android::DownloadTaskScheduler>();
#else
task_scheduler = base::MakeUnique<DownloadTaskSchedulerImpl>(context);
task_scheduler = base::MakeUnique<DownloadTaskSchedulerImpl>(context);
#endif

return download::CreateDownloadService(std::move(clients), download_manager,
storage_dir, background_task_runner,
std::move(task_scheduler));
return download::BuildDownloadService(context, std::move(clients),
storage_dir, background_task_runner,
std::move(task_scheduler));
}
}

content::BrowserContext* DownloadServiceFactory::GetBrowserContextToUse(
Expand Down
1 change: 1 addition & 0 deletions components/download/components_unittests.filter
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ DownloadServiceModelImplTest.*
DownloadStoreTest.*
FileMonitorTest.*
InProgressConversionsTest.*
InMemoryDownloadDriverTest.*
InMemoryDownloadTest.*
NavigationMonitorImplTest.*
NetworkListenerTest.*
Expand Down
94 changes: 74 additions & 20 deletions components/download/content/factory/download_service_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/download/content/factory/download_service_factory.h"

#include "base/files/file_path.h"
#include "build/build_config.h"
#include "components/download/content/factory/navigation_monitor_factory.h"
Expand All @@ -11,12 +13,17 @@
#include "components/download/internal/background_service/controller_impl.h"
#include "components/download/internal/background_service/download_service_impl.h"
#include "components/download/internal/background_service/download_store.h"
#include "components/download/internal/background_service/empty_file_monitor.h"
#include "components/download/internal/background_service/empty_task_scheduler.h"
#include "components/download/internal/background_service/file_monitor_impl.h"
#include "components/download/internal/background_service/in_memory_download_driver.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/noop_store.h"
#include "components/download/internal/background_service/proto/entry.pb.h"
#include "components/download/internal/background_service/scheduler/scheduler_impl.h"
#include "components/leveldb_proto/proto_database_impl.h"
#include "net/url_request/url_request_context_getter.h"

#if defined(OS_ANDROID)
#include "components/download/internal/background_service/android/battery_status_listener_android.h"
Expand All @@ -29,24 +36,18 @@ const base::FilePath::CharType kEntryDBStorageDir[] =
const base::FilePath::CharType kFilesStorageDir[] = FILE_PATH_LITERAL("Files");
} // namespace

DownloadService* CreateDownloadService(
// Helper function to create download service with different implementation
// details.
DownloadService* CreateDownloadServiceInternal(
content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
content::DownloadManager* download_manager,
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler) {
std::unique_ptr<Configuration> config,
std::unique_ptr<DownloadDriver> driver,
std::unique_ptr<Store> store,
std::unique_ptr<TaskScheduler> task_scheduler,
std::unique_ptr<FileMonitor> file_monitor,
const base::FilePath& files_storage_dir) {
auto client_set = std::make_unique<ClientSet>(std::move(clients));
auto config = Configuration::CreateFromFinch();

auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
auto driver = std::make_unique<DownloadDriverImpl>(download_manager);

auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
auto entry_db =
std::make_unique<leveldb_proto::ProtoDatabaseImpl<protodb::Entry>>(
background_task_runner);
auto store = std::make_unique<DownloadStore>(entry_db_storage_dir,
std::move(entry_db));
auto model = std::make_unique<ModelImpl>(std::move(store));

#if defined(OS_ANDROID)
Expand All @@ -61,12 +62,9 @@ DownloadService* CreateDownloadService(
config->network_startup_delay, config->network_change_delay,
std::move(battery_listener));
NavigationMonitor* navigation_monitor =
NavigationMonitorFactory::GetForBrowserContext(
download_manager->GetBrowserContext());
NavigationMonitorFactory::GetForBrowserContext(browser_context);
auto scheduler = std::make_unique<SchedulerImpl>(
task_scheduler.get(), config.get(), client_set.get());
auto file_monitor = std::make_unique<FileMonitorImpl>(
files_storage_dir, background_task_runner, config->file_keep_alive_time);
auto logger = std::make_unique<LoggerImpl>();
auto controller = std::make_unique<ControllerImpl>(
config.get(), logger.get(), std::move(client_set), std::move(driver),
Expand All @@ -79,4 +77,60 @@ DownloadService* CreateDownloadService(
std::move(controller));
}

// Create download service for normal profile.
DownloadService* BuildDownloadService(
content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler) {
auto config = Configuration::CreateFromFinch();

auto driver = std::make_unique<DownloadDriverImpl>(
content::BrowserContext::GetDownloadManager(browser_context));

auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
auto entry_db =
std::make_unique<leveldb_proto::ProtoDatabaseImpl<protodb::Entry>>(
background_task_runner);
auto store = std::make_unique<DownloadStore>(entry_db_storage_dir,
std::move(entry_db));

auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
auto file_monitor = std::make_unique<FileMonitorImpl>(
files_storage_dir, background_task_runner, config->file_keep_alive_time);

return CreateDownloadServiceInternal(
browser_context, std::move(clients), std::move(config), std::move(driver),
std::move(store), std::move(task_scheduler), std::move(file_monitor),
files_storage_dir);
}

// Create download service for incognito mode without any database or file IO.
DownloadService* BuildInMemoryDownloadService(
content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
const base::FilePath& storage_dir,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
auto config = Configuration::CreateFromFinch();
auto download_factory = std::make_unique<InMemoryDownloadFactory>(
request_context_getter, blob_context_getter, io_task_runner);
auto driver =
std::make_unique<InMemoryDownloadDriver>(std::move(download_factory));
auto store = std::make_unique<NoopStore>();
auto task_scheduler = std::make_unique<EmptyTaskScheduler>();

// TODO(xingliu): Remove |files_storage_dir| and |storage_dir| for incognito
// mode. See https://crbug.com/810202.
auto files_storage_dir = storage_dir.Append(kFilesStorageDir);
auto file_monitor = std::make_unique<EmptyFileMonitor>();

return CreateDownloadServiceInternal(
browser_context, std::move(clients), std::move(config), std::move(driver),
std::move(store), std::move(task_scheduler), std::move(file_monitor),
files_storage_dir);
}

} // namespace download
21 changes: 18 additions & 3 deletions components/download/content/factory/download_service_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "components/download/internal/background_service/blob_task_proxy.h"
#include "components/download/public/background_service/clients.h"

namespace content {
class DownloadManager;
class BrowserContext;
} // namespace content

namespace net {
class URLRequestContextGetter;
} // namespace net

namespace download {

class DownloadService;
Expand All @@ -31,13 +36,23 @@ class TaskScheduler;
// will act as an in-memory only service (this means no auto-retries after
// restarts, no files written on completion, etc.).
// |background_task_runner| will be used for all disk reads and writes.
DownloadService* CreateDownloadService(
DownloadService* BuildDownloadService(
content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
content::DownloadManager* download_manager,
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler);

// Create download service used in incognito mode, without any database or
// download file IO.
DownloadService* BuildInMemoryDownloadService(
content::BrowserContext* browser_context,
std::unique_ptr<DownloadClientMap> clients,
const base::FilePath& storage_dir,
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);

} // namespace download

#endif // COMPONENTS_DOWNLOAD_CONTENT_FACTORY_DOWNLOAD_SERVICE_FACTORY_H_
1 change: 1 addition & 0 deletions components/download/content/internal/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ source_set("unit_tests") {
":internal",
"//base/test:test_support",
"//components/download/content/public",
"//components/download/internal/background_service/test:test_support",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/download/internal/background_service/test/mock_download_driver_client.h"
#include "content/public/test/fake_download_item.h"
#include "content/public/test/mock_download_manager.h"
#include "net/http/http_response_headers.h"
Expand Down Expand Up @@ -45,17 +46,6 @@ MATCHER_P(DriverEntryEqual, entry, "") {

} // namespace

class MockDriverClient : public DownloadDriver::Client {
public:
MOCK_METHOD1(OnDriverReady, void(bool));
MOCK_METHOD1(OnDriverHardRecoverComplete, void(bool));
MOCK_METHOD1(OnDownloadCreated, void(const DriverEntry&));
MOCK_METHOD2(OnDownloadFailed, void(const DriverEntry&, FailureType));
MOCK_METHOD1(OnDownloadSucceeded, void(const DriverEntry&));
MOCK_METHOD1(OnDownloadUpdated, void(const DriverEntry&));
MOCK_CONST_METHOD1(IsTrackingDownload, bool(const std::string&));
};

class DownloadDriverImplTest : public testing::Test {
public:
DownloadDriverImplTest()
Expand Down
9 changes: 9 additions & 0 deletions components/download/internal/background_service/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ static_library("internal") {
"download_store.h",
"driver_entry.cc",
"driver_entry.h",
"empty_file_monitor.cc",
"empty_file_monitor.h",
"empty_task_scheduler.cc",
"empty_task_scheduler.h",
"entry.cc",
"entry.h",
"entry_utils.cc",
Expand All @@ -43,6 +47,8 @@ static_library("internal") {
"file_monitor_impl.h",
"in_memory_download.cc",
"in_memory_download.h",
"in_memory_download_driver.cc",
"in_memory_download_driver.h",
"log_sink.h",
"log_source.h",
"logger_impl.cc",
Expand All @@ -53,6 +59,8 @@ static_library("internal") {
"model_impl.h",
"navigation_monitor_impl.cc",
"navigation_monitor_impl.h",
"noop_store.cc",
"noop_store.h",
"proto_conversions.cc",
"proto_conversions.h",
"scheduler/device_status.cc",
Expand Down Expand Up @@ -127,6 +135,7 @@ source_set("unit_tests") {
"download_store_unittest.cc",
"entry_utils_unittest.cc",
"file_monitor_unittest.cc",
"in_memory_download_driver_unittest.cc",
"in_memory_download_unittest.cc",
"model_impl_unittest.cc",
"navigation_monitor_impl_unittests.cc",
Expand Down
Loading

0 comments on commit 8986047

Please sign in to comment.