Commit 620a4a88 authored by dtrainor's avatar dtrainor Committed by Commit bot

Add the download component and initial setup

- Add the BackgroundDownloadService interface and associated files.  Set
up the test hooks and tie it into the proper Chrome and
component_unittest targets.

BUG=717180

Review-Url: https://codereview.chromium.org/2851303003
Cr-Commit-Position: refs/heads/master@{#469371}
parent f240cb6e
......@@ -350,6 +350,8 @@ split_static_library("browser") {
"download/download_request_limiter.h",
"download/download_resource_throttle.cc",
"download/download_resource_throttle.h",
"download/download_service_factory.cc",
"download/download_service_factory.h",
"download/download_started_animation.h",
"download/download_stats.cc",
"download/download_stats.h",
......@@ -1481,6 +1483,7 @@ split_static_library("browser") {
"//components/dom_distiller/content/browser",
"//components/domain_reliability",
"//components/doodle",
"//components/download",
"//components/error_page/common",
"//components/favicon/content",
"//components/favicon/core",
......
// Copyright 2017 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 "chrome/browser/download/download_service_factory.h"
#include "base/files/file_path.h"
#include "base/memory/singleton.h"
#include "base/sequenced_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_constants.h"
#include "components/download/public/download_service.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
// static
DownloadServiceFactory* DownloadServiceFactory::GetInstance() {
return base::Singleton<DownloadServiceFactory>::get();
}
// static
download::DownloadService* DownloadServiceFactory::GetForBrowserContext(
content::BrowserContext* context) {
return static_cast<download::DownloadService*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
DownloadServiceFactory::DownloadServiceFactory()
: BrowserContextKeyedServiceFactory(
"download::DownloadService",
BrowserContextDependencyManager::GetInstance()) {}
DownloadServiceFactory::~DownloadServiceFactory() = default;
KeyedService* DownloadServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND});
base::FilePath storage_dir;
if (!profile->IsOffTheRecord() && !profile->GetPath().empty()) {
storage_dir =
profile->GetPath().Append(chrome::kDownloadServiceStorageDirname);
}
download::DownloadService* service =
download::DownloadService::Create(storage_dir, background_task_runner);
// TODO(dtrainor): Register all clients here.
return service;
}
content::BrowserContext* DownloadServiceFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextOwnInstanceInIncognito(context);
}
// Copyright 2017 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.
#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SERVICE_FACTORY_H_
#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SERVICE_FACTORY_H_
#include "base/macros.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace base {
template <typename T>
struct DefaultSingletonTraits;
} // namespace base
namespace content {
class BrowserContext;
} // namespace content
namespace download {
class DownloadService;
} // namespace download
// DownloadServiceFactory is the main client class for interaction with the
// download component.
class DownloadServiceFactory : public BrowserContextKeyedServiceFactory {
public:
// Returns singleton instance of DownloadServiceFactory.
static DownloadServiceFactory* GetInstance();
// Returns the DownloadService associated with |context|.
static download::DownloadService* GetForBrowserContext(
content::BrowserContext* context);
private:
friend struct base::DefaultSingletonTraits<DownloadServiceFactory>;
DownloadServiceFactory();
~DownloadServiceFactory() override;
// BrowserContextKeyedServiceFactory overrides:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(DownloadServiceFactory);
};
#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SERVICE_FACTORY_H_
......@@ -140,6 +140,8 @@ const base::FilePath::CharType kCRLSetFilename[] =
FPL("Certificate Revocation Lists");
const base::FilePath::CharType kCustomDictionaryFileName[] =
FPL("Custom Dictionary.txt");
const base::FilePath::CharType kDownloadServiceStorageDirname[] =
FPL("Download Service");
const base::FilePath::CharType kExtensionActivityLogFilename[] =
FPL("Extension Activity");
const base::FilePath::CharType kExtensionsCookieFilename[] =
......
......@@ -48,6 +48,7 @@ extern const base::FilePath::CharType kChannelIDFilename[];
extern const base::FilePath::CharType kCookieFilename[];
extern const base::FilePath::CharType kCRLSetFilename[];
extern const base::FilePath::CharType kCustomDictionaryFileName[];
extern const base::FilePath::CharType kDownloadServiceStorageDirname[];
extern const base::FilePath::CharType kExtensionActivityLogFilename[];
extern const base::FilePath::CharType kExtensionsCookieFilename[];
extern const base::FilePath::CharType kFeatureEngagementTrackerStorageDirname[];
......
......@@ -82,6 +82,7 @@ test("components_unittests") {
"//components/device_event_log:unit_tests",
"//components/dom_distiller/core:unit_tests",
"//components/doodle:unit_tests",
"//components/download:unit_tests",
"//components/favicon/core:unit_tests",
"//components/favicon_base:unit_tests",
"//components/flags_ui:unit_tests",
......
# Copyright 2017 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.
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
}
group("download") {
public_deps = [
"//components/download/public",
]
deps = [
"//components/download/internal",
]
}
group("unit_tests") {
testonly = true
deps = [
"//components/download/internal:unit_tests",
]
}
dtrainor@chromium.org
qinmin@chromium.org
shaktisahu@chromium.org
xingliu@chromium.org
# COMPONENT: UI>Browser>Downloads
\ No newline at end of file
# Copyright 2017 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.
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
}
static_library("internal") {
visibility = [
":*",
"//components/download",
]
sources = [
"download_service_impl.cc",
"download_service_impl.h",
]
deps = [
"//base",
"//components/download/public",
]
}
source_set("unit_tests") {
testonly = true
visibility = [ "//components/download:unit_tests" ]
sources = [
"download_service_impl_unittest.cc",
]
deps = [
":internal",
"//base/test:test_support",
"//testing/gtest",
]
}
include_rules = [
"-content",
"+base",
]
// Copyright 2017 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 "components/download/internal/download_service_impl.h"
namespace download {
// static
DownloadService* DownloadService::Create(
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
return new DownloadServiceImpl();
}
DownloadServiceImpl::DownloadServiceImpl() = default;
DownloadServiceImpl::~DownloadServiceImpl() = default;
void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
}
void DownloadServiceImpl::PauseDownload(const std::string& guid) {}
void DownloadServiceImpl::ResumeDownload(const std::string& guid) {}
void DownloadServiceImpl::CancelDownload(const std::string& guid) {}
void DownloadServiceImpl::ChangeDownloadCriteria(
const std::string& guid,
const SchedulingParams& params) {}
} // namespace download
// Copyright 2017 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.
#ifndef COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
#define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
#include <string>
#include "base/macros.h"
#include "components/download/public/download_service.h"
namespace download {
struct DownloadParams;
struct SchedulingParams;
// The internal implementation of the DownloadService.
class DownloadServiceImpl : public DownloadService {
public:
DownloadServiceImpl();
~DownloadServiceImpl() override;
// DownloadService implementation.
void StartDownload(const DownloadParams& download_params) override;
void PauseDownload(const std::string& guid) override;
void ResumeDownload(const std::string& guid) override;
void CancelDownload(const std::string& guid) override;
void ChangeDownloadCriteria(const std::string& guid,
const SchedulingParams& params) override;
private:
DISALLOW_COPY_AND_ASSIGN(DownloadServiceImpl);
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_SERVICE_IMPL_H_
// Copyright 2017 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 "components/download/internal/download_service_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
TEST(DownloadServiceImplTest, DummyTest) {
EXPECT_TRUE(true);
}
# Copyright 2017 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.
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
}
source_set("public") {
sources = [
"client.h",
"clients.h",
"download_params.cc",
"download_params.h",
"download_service.h",
]
deps = [
"//components/keyed_service/core",
]
public_deps = [
"//base",
"//net",
"//url",
]
}
include_rules = [
"-content",
"+base",
"+components/keyed_service",
"+net/http",
"+url",
]
// Copyright 2017 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.
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_CLIENT_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_CLIENT_H_
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "net/http/http_response_headers.h"
#include "url/gurl.h"
namespace download {
// The Client interface required by any feature that wants to start a download
// through the DownloadService. Should be registered immediately at startup
// when the DownloadService is created (see the factory).
class Client {
public:
// Used by OnDownloadStarted to determine whether or not the DownloadService
// should continue downloading the file or abort the attempt.
enum class ShouldDownload {
CONTINUE,
ABORT,
};
virtual ~Client() = default;
// Called when the DownloadService is initialized and ready to be interacted
// with. |outstanding_download_guids| is a list of all downloads the
// DownloadService is aware of that are associated with this Client.
virtual void OnServiceInitialized(
const std::vector<std::string>& outstanding_download_guids) = 0;
// Return whether or not the download should be aborted (potentially in
// response to |headers|). The download will be downloading at the time this
// call is made.
virtual ShouldDownload OnDownloadStarted(
const std::string& guid,
const std::vector<GURL>& url_chain,
const scoped_refptr<const net::HttpResponseHeaders>& headers) = 0;
// Will be called when there is an update to the current progress state of the
// underlying download. Note that |bytes_downloaded| may go backwards if the
// download had to be started over from the beginning due to an interruption.
// This will be called frequently if the download is actively downloading,
// with byte updates coming in as they are processed by the internal download
// driver.
virtual void OnDownloadUpdated(const std::string& guid,
uint64_t bytes_downloaded) = 0;
// TODO(dtrainor): Expose a useful error message with the failed download.
virtual void OnDownloadFailed(const std::string& guid) = 0;
// Called when the download was not completed before the
// DownloadParams::cancel_after timeout.
virtual void OnDownloadTimedOut(const std::string& guid) = 0;
// Called when the download has been aborted after reaching a treshold where
// we decide it is not worth attempting to start again. This could be either
// due to a specific number of failed retry attempts or a specific number of
// wasted bytes due to the download restarting.
virtual void OnDownloadAborted(const std::string& guid) = 0;
// Called when a download has been successfully completed. After this call
// the download entry will be purged from the database. The file will be
// automatically removed if it is not renamed or deleted after a window of
// time (12 hours, but finch configurable). The timeout is meant to be a
// failsafe to ensure that we clean up properly.
// TODO(dtrainor): Investigate alternate output formats.
// TODO(dtrainor): Point to finch configurable timeout when it is added.
virtual void OnDownloadSucceeded(const std::string& guid,
const base::FilePath& path,
uint64_t size) = 0;
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_CLIENT_H_
// Copyright 2017 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.
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
namespace download {
// A list of all clients that are able to make download requests through the
// DownloadService.
// To add a new client, update the metric DownloadService.DownloadClients in
// histograms.xml and make sure to keep this list in sync. Additions should be
// treated as APPEND ONLY to make sure to keep both UMA metric semantics correct
// but also to make sure the underlying database properly associates each
// download with the right client.
enum class DownloadClient {
// Represents an uninitialized DownloadClient variable.
DOWNLOAD_CLIENT_INVALID = 0,
DOWNLOAD_CLIENT_OFFLINE_PAGE_PREFETCH = 1,
DOWNLOAD_CLIENT_BOUNDARY = 2,
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_CLIENTS_H_
// Copyright 2017 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 "components/download/public/download_params.h"
#include "components/download/public/clients.h"
namespace download {
SchedulingParams::SchedulingParams()
: priority(Priority::DEFAULT),
network_requirements(NetworkRequirements::NONE),
battery_requirements(BatteryRequirements::BATTERY_INSENSITIVE) {}
RequestParams::RequestParams() : method("GET") {}
DownloadParams::DownloadParams()
: client(DownloadClient::DOWNLOAD_CLIENT_INVALID) {}
DownloadParams::DownloadParams(const DownloadParams& other) = default;
DownloadParams::~DownloadParams() = default;
} // namespace download
// Copyright 2017 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.
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
#include "base/callback.h"
#include "base/time/time.h"
#include "components/download/public/clients.h"
#include "net/http/http_request_headers.h"
#include "url/gurl.h"
namespace download {
// The parameters describing when to run a download. This allows the caller to
// specify restrictions on what impact this download will have on the device
// (battery, network conditions, priority, etc.).
struct SchedulingParams {
public:
enum class NetworkRequirements {
// The download can occur under all network conditions.
NONE = 0,
// The download should occur when the network isn't metered. However if the
// device does not provide that opportunity over a long period of time, the
// DownloadService may start allowing these downloads to run on metered
// networks as well.
OPTIMISTIC = 1,
// The download can occur only if the network isn't metered.
UNMETERED = 2,
};
enum class BatteryRequirements {
// The download can occur under all battery scenarios. Note that the
// DownloadService may still not run this download under extremely low
// battery conditions.
BATTERY_INSENSITIVE = 0,
// The download can only occur when charging or in optimal battery
// conditions.
BATTERY_SENSITIVE = 1,
};
enum class Priority {
// The lowest priority. Requires that the device is idle or Chrome is
// running.
LOW = 0,
// The normal priority. Requires that the device is idle or Chrome is
// running.
NORMAL = 1,
// The highest background priority. Does not require the device to be idle.
HIGH = 2,
// The highest priority. This will act (scheduling requirements aside) as a
// user-initiated download.
UI = 3,
// The default priority for all tasks unless overridden.
DEFAULT = NORMAL,
};
SchedulingParams();
SchedulingParams(const SchedulingParams& other) = default;
~SchedulingParams() = default;
// Cancel the download after this delay. Will cancel in-progress downloads.
base::TimeDelta cancel_after;
// The suggested priority. Non-UI priorities may not be honored by the
// DownloadService based on internal criteria and settings.
Priority priority;
NetworkRequirements network_requirements;
BatteryRequirements battery_requirements;
};
// The parameters describing how to build the request when starting a download.
struct RequestParams {
public:
RequestParams();
RequestParams(const RequestParams& other) = default;
~RequestParams() = default;
GURL url;
// The request method ("GET" is the default value).
std::string method;
net::HttpRequestHeaders request_headers;
};
// The parameters that describe a download request made to the DownloadService.
// The |client| needs to be properly created and registered for this service for
// the download to be accepted.
struct DownloadParams {
enum StartResult {
// The download is accepted and persisted.
ACCEPTED,
// The DownloadService has too many downloads. Backoff and retry.
BACKOFF,
// Failed to create the download. Invalid input parameters.
BAD_PARAMETERS,
// TODO(dtrainor): Add more error codes.
};
DownloadParams();
DownloadParams(const DownloadParams& other);
~DownloadParams();
// The feature that is requesting this download.
DownloadClient client;
// A unique GUID that represents this download. See |base::GenerateGUID()|.
std::string guid;
// A callback that will be notified if this download has been accepted and
// persisted by the DownloadService.
base::Callback<void(const DownloadParams&, StartResult)> callback;
// The parameters that determine under what device conditions this download
// will occur.
SchedulingParams scheduling_params;
// The parameters that define the actual download request to make.
RequestParams request_params;
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_PARAMS_H_
// Copyright 2017 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.
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "components/keyed_service/core/keyed_service.h"
namespace download {
struct DownloadParams;
struct SchedulingParams;
// A service responsible for helping facilitate the scheduling and downloading
// of file content from the web. See |DownloadParams| for more details on the
// types of scheduling that can be achieved and the required input parameters
// for starting a download. Note that DownloadServices with a valid storage
// directory will persist the requests across restarts. This means that any
// feature requesting a download will have to implement a download::Client
// interface so this class knows who to contact when a download completes after
// a process restart.
class DownloadService : public KeyedService {
public:
// |storage_dir| is a path to where all the local storage will be. This will
// hold the internal database as well as any temporary files on disk. If this
// is an empty path, the service will not persist any information to disk and
// 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.
static DownloadService* Create(
const base::FilePath& storage_dir,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
// Sends the download to the service. A callback to
// |DownloadParams::callback| will be triggered once the download has been
// persisted and saved in the service
virtual void StartDownload(const DownloadParams& download_params) = 0;
// Allows any feature to pause or resume downloads at will. Paused downloads
// will not start or stop based on scheduling criteria. They will be
// effectively frozen.
virtual void PauseDownload(const std::string& guid) = 0;
virtual void ResumeDownload(const std::string& guid) = 0;
// Cancels a download in this service. The canceled download will be
// interrupted if it is running.
virtual void CancelDownload(const std::string& guid) = 0;
// Changes the current scheduling criteria for a download. This is useful if
// a user action might constrain or loosen the device state during which this
// download can run.
virtual void ChangeDownloadCriteria(const std::string& guid,
const SchedulingParams& params) = 0;
protected:
DownloadService() = default;
private:
DISALLOW_COPY_AND_ASSIGN(DownloadService);
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_SERVICE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment