Use componentized background fetch download service for Chrome.

Bug: 1057770
Change-Id: Ic04d2031c9cd43eb54614b8ec76e873f90d5d62c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2773674
Commit-Queue: Evan Stade <[email protected]>
Reviewed-by: Rayan Kanso <[email protected]>
Reviewed-by: Shakti Sahu <[email protected]>
Reviewed-by: Lei Zhang <[email protected]>
Reviewed-by: Mugdha Lakhani <[email protected]>
Cr-Commit-Position: refs/heads/master@{#867316}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index aabd5dc..e769acf 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -184,8 +184,6 @@
     "background_fetch/background_fetch_delegate_factory.h",
     "background_fetch/background_fetch_delegate_impl.cc",
     "background_fetch/background_fetch_delegate_impl.h",
-    "background_fetch/background_fetch_download_client.cc",
-    "background_fetch/background_fetch_download_client.h",
     "background_fetch/background_fetch_permission_context.cc",
     "background_fetch/background_fetch_permission_context.h",
     "background_sync/background_sync_controller_factory.cc",
@@ -1988,6 +1986,7 @@
     "//components/autofill/content/browser",
     "//components/autofill/core/browser",
     "//components/autofill_assistant/browser/public:public",
+    "//components/background_fetch",
     "//components/background_sync",
     "//components/background_task_scheduler",
     "//components/blocked_content",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index ecf8b55..c572c13 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -45,8 +45,9 @@
   "+components/autofill/content/common",
   "+components/autofill/core/browser",
   "+components/autofill/core/common",
-  "+components/background_task_scheduler",
+  "+components/background_fetch",
   "+components/background_sync",
+  "+components/background_task_scheduler",
   "+components/base32",
   "+components/blocked_content",
   "+components/blocklist/opt_out_blocklist",
diff --git a/chrome/browser/background_fetch/background_fetch_browsertest.cc b/chrome/browser/background_fetch/background_fetch_browsertest.cc
index 0a3db2c..1a3bba3 100644
--- a/chrome/browser/background_fetch/background_fetch_browsertest.cc
+++ b/chrome/browser/background_fetch/background_fetch_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/background_fetch/job_details.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/download/public/background_service/download_service.h"
@@ -766,19 +767,27 @@
 
   base::RunLoop().RunUntilIdle();  // Give updates a chance to propagate.
 
-  ASSERT_EQ(delegate_->job_details_map_.size(), 1u);
-  auto& job_details = delegate_->job_details_map_.begin()->second;
-  EXPECT_EQ(job_details.job_state,
-            BackgroundFetchDelegateImpl::JobDetails::State::kJobComplete);
+  ASSERT_EQ(delegate_->ui_state_map_.size(), 1u);
+  auto entry = delegate_->ui_state_map_.begin();
+  std::string job_id = entry->first;
+  auto& offline_item = entry->second.offline_item;
+  EXPECT_EQ(offline_items_collection::OfflineItemState::COMPLETE,
+            offline_item.state);
+  background_fetch::JobDetails* job_details =
+      delegate_->GetJobDetails(job_id, /*allow_null=*/true);
+  ASSERT_TRUE(!!job_details);
+  EXPECT_EQ(job_details->job_state,
+            background_fetch::JobDetails::State::kJobComplete);
 
   // Simulate notification click.
   delegate_->OpenItem(
       offline_items_collection::OpenParams(
           offline_items_collection::LaunchLocation::NOTIFICATION),
-      job_details.offline_item.id);
+      offline_item.id);
 
-  // Job Details should be deleted at this point.
-  EXPECT_TRUE(delegate_->job_details_map_.empty());
+  // The offline item and JobDetails should both be deleted at this point.
+  EXPECT_TRUE(delegate_->ui_state_map_.empty());
+  EXPECT_FALSE(delegate_->GetJobDetails(job_id, /*allow_null=*/true));
 
   // Wait for click event.
   {
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_factory.cc b/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
index e94afaa..200c97f 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/background_fetch/background_fetch_delegate_factory.h"
 
 #include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/download/download_service_factory.h"
@@ -13,78 +12,8 @@
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_key.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/offline_items_collection/core/offline_content_aggregator.h"
-#include "components/offline_items_collection/core/offline_item.h"
 #include "content/public/browser/background_fetch_delegate.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
-
-namespace {
-
-// Provider for Chrome-specific services and functionality.
-class ChromeBackgroundFetchDelegateHelper
-    : public BackgroundFetchDelegateImpl::Embedder {
- public:
-  explicit ChromeBackgroundFetchDelegateHelper(Profile* profile)
-      : profile_(profile) {}
-  ChromeBackgroundFetchDelegateHelper(
-      const ChromeBackgroundFetchDelegateHelper&) = delete;
-  ChromeBackgroundFetchDelegateHelper& operator=(
-      const ChromeBackgroundFetchDelegateHelper&) = delete;
-  ~ChromeBackgroundFetchDelegateHelper() override = default;
-
-  // BackgroundFetchDelegateImpl::Delegate:
-  offline_items_collection::OfflineContentAggregator*
-  GetOfflineContentAggregator() override {
-    return OfflineContentAggregatorFactory::GetForKey(
-        profile_->GetProfileKey());
-  }
-
-  download::DownloadService* GetDownloadService() override {
-    return DownloadServiceFactory::GetInstance()->GetForKey(
-        profile_->GetProfileKey());
-  }
-
-  HostContentSettingsMap* GetHostContentSettingsMap() override {
-    return HostContentSettingsMapFactory::GetForProfile(profile_);
-  }
-
-  void UpdateOfflineItem(
-      offline_items_collection::OfflineItem* offline_item) override {
-#if defined(OS_ANDROID)
-    if (profile_->IsOffTheRecord())
-      offline_item->otr_profile_id = profile_->GetOTRProfileID().Serialize();
-#endif
-  }
-
-  void OnJobCompleted(const url::Origin& origin,
-                      bool user_initiated_abort) override {
-    auto* ukm_background_service =
-        ukm::UkmBackgroundRecorderFactory::GetForProfile(profile_);
-    ukm_background_service->GetBackgroundSourceIdIfAllowed(
-        origin,
-        base::BindOnce(&DidGetBackgroundSourceId, user_initiated_abort));
-  }
-
- private:
-  static void DidGetBackgroundSourceId(
-      bool user_initiated_abort,
-      base::Optional<ukm::SourceId> source_id) {
-    // This background event did not meet the requirements for the UKM service.
-    if (!source_id)
-      return;
-
-    ukm::builders::BackgroundFetchDeletingRegistration(*source_id)
-        .SetUserInitiatedAbort(user_initiated_abort)
-        .Record(ukm::UkmRecorder::Get());
-  }
-
-  Profile* profile_;
-};
-
-}  // namespace
 
 // static
 BackgroundFetchDelegateImpl* BackgroundFetchDelegateFactory::GetForProfile(
@@ -112,9 +41,7 @@
 
 KeyedService* BackgroundFetchDelegateFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  return new BackgroundFetchDelegateImpl(
-      context, std::make_unique<ChromeBackgroundFetchDelegateHelper>(
-                   Profile::FromBrowserContext(context)));
+  return new BackgroundFetchDelegateImpl(Profile::FromBrowserContext(context));
 }
 
 content::BrowserContext* BackgroundFetchDelegateFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
index 2331754..e595a32 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -7,434 +7,102 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/callback_helpers.h"
 #include "base/check_op.h"
+#include "base/containers/contains.h"
 #include "base/feature_list.h"
-#include "base/guid.h"
 #include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/download/download_service_factory.h"
+#include "chrome/browser/metrics/ukm_background_recorder_service.h"
+#include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
+#include "components/background_fetch/job_details.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
-#include "components/download/public/background_service/download_params.h"
 #include "components/download/public/background_service/download_service.h"
 #include "components/download/public/common/download_features.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 #include "components/offline_items_collection/core/offline_item.h"
-#include "components/permissions/permissions_client.h"
 #include "content/public/browser/background_fetch_description.h"
-#include "content/public/browser/background_fetch_response.h"
-#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_manager.h"
-#include "content/public/browser/download_manager_delegate.h"
-#include "content/public/browser/web_contents.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/network/public/mojom/data_pipe_getter.mojom.h"
-#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/image/image_skia.h"
 #include "url/origin.h"
 
 namespace {
 constexpr char kBackgroundFetchNamespacePrefix[] = "background_fetch";
 }  // namespace
 
-BackgroundFetchDelegateImpl::BackgroundFetchDelegateImpl(
-    content::BrowserContext* context,
-    std::unique_ptr<Embedder> embedder)
-    : context_(context),
-      embedder_(std::move(embedder)),
+BackgroundFetchDelegateImpl::BackgroundFetchDelegateImpl(Profile* profile)
+    : background_fetch::BackgroundFetchDelegateBase(profile),
+      profile_(profile),
       provider_namespace_(
           offline_items_collection::OfflineContentAggregator::
               CreateUniqueNameSpace(kBackgroundFetchNamespacePrefix,
-                                    context->IsOffTheRecord())) {
-  DCHECK(context_);
-  embedder_->GetOfflineContentAggregator()->RegisterProvider(
-      provider_namespace_, this);
+                                    profile->IsOffTheRecord())),
+      offline_content_aggregator_(OfflineContentAggregatorFactory::GetForKey(
+          profile->GetProfileKey())) {
+  DCHECK(profile_);
+  DCHECK(!provider_namespace_.empty());
+  offline_content_aggregator_->RegisterProvider(provider_namespace_, this);
 
   // Ensure that downloads UI components are initialized to handle the UI
   // updates.
   if (!base::FeatureList::IsEnabled(
           download::features::
               kUseInProgressDownloadManagerForDownloadService)) {
-    content::BrowserContext::GetDownloadManager(context_);
+    content::BrowserContext::GetDownloadManager(profile_);
   }
 }
 
-BackgroundFetchDelegateImpl::~BackgroundFetchDelegateImpl() = default;
-
-download::DownloadService* BackgroundFetchDelegateImpl::GetDownloadService() {
-  return embedder_->GetDownloadService();
+BackgroundFetchDelegateImpl::~BackgroundFetchDelegateImpl() {
+  offline_content_aggregator_->UnregisterProvider(provider_namespace_);
 }
 
-void BackgroundFetchDelegateImpl::Shutdown() {
+void BackgroundFetchDelegateImpl::MarkJobComplete(const std::string& job_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  embedder_->GetOfflineContentAggregator()->UnregisterProvider(
-      provider_namespace_);
-}
+  background_fetch::JobDetails* job_details = GetJobDetails(job_id);
+  RecordBackgroundFetchDeletingRegistrationUkmEvent(
+      job_details->fetch_description->origin, job_details->cancelled_from_ui);
 
-BackgroundFetchDelegateImpl::JobDetails::RequestData::RequestData(
-    bool has_upload_data) {
-  if (has_upload_data)
-    status = Status::kIncluded;
-  else
-    status = Status::kAbsent;
-}
-
-BackgroundFetchDelegateImpl::JobDetails::RequestData::~RequestData() = default;
-
-BackgroundFetchDelegateImpl::JobDetails::JobDetails(JobDetails&&) = default;
-
-BackgroundFetchDelegateImpl::JobDetails::JobDetails() = default;
-
-BackgroundFetchDelegateImpl::JobDetails::~JobDetails() = default;
-
-void BackgroundFetchDelegateImpl::JobDetails::MarkJobAsStarted() {
-  if (job_state == State::kPendingWillStartDownloading)
-    job_state = State::kStartedAndDownloading;
-  else if (job_state == State::kPendingWillStartPaused)
-    job_state = State::kStartedButPaused;
-}
-
-void BackgroundFetchDelegateImpl::JobDetails::UpdateJobOnDownloadComplete(
-    const std::string& download_guid) {
-  fetch_description->completed_requests++;
-  if (fetch_description->completed_requests ==
-      fetch_description->total_requests) {
-    job_state = State::kDownloadsComplete;
-  }
-
-  current_fetch_guids.erase(download_guid);
-}
-
-void BackgroundFetchDelegateImpl::JobDetails::UpdateOfflineItem() {
-  DCHECK_GT(fetch_description->total_requests, 0);
-
-  if (ShouldReportProgressBySize()) {
-    offline_item.progress.value = GetProcessedBytes();
-    // If we have completed all downloads, update progress max to the processed
-    // bytes in case the provided totals were set too high. This avoids
-    // unnecessary jumping in the progress bar.
-    uint64_t completed_bytes =
-        fetch_description->downloaded_bytes + fetch_description->uploaded_bytes;
-    uint64_t total_bytes = fetch_description->download_total_bytes +
-                           fetch_description->upload_total_bytes;
-    offline_item.progress.max =
-        job_state == State::kDownloadsComplete ? completed_bytes : total_bytes;
-  } else {
-    offline_item.progress.value = fetch_description->completed_requests;
-    offline_item.progress.max = fetch_description->total_requests;
-  }
-
-  offline_item.progress.unit =
-      offline_items_collection::OfflineItemProgressUnit::PERCENTAGE;
-
-  offline_item.title = fetch_description->title;
-  offline_item.promote_origin = true;
-  offline_item.is_transient = true;
-  offline_item.is_resumable = true;
-
-  using OfflineItemState = offline_items_collection::OfflineItemState;
-  switch (job_state) {
-    case State::kCancelled:
-      offline_item.state = OfflineItemState::CANCELLED;
-      break;
-    case State::kDownloadsComplete:
-      // This includes cases when the download failed, or completed but the
-      // response was an HTTP error, e.g. 404.
-      offline_item.state = OfflineItemState::COMPLETE;
-      offline_item.is_openable = true;
-      break;
-    case State::kPendingWillStartPaused:
-    case State::kStartedButPaused:
-      offline_item.state = OfflineItemState::PAUSED;
-      break;
-    case State::kJobComplete:
-      // There shouldn't be any updates at this point.
-      NOTREACHED();
-      break;
-    default:
-      offline_item.state = OfflineItemState::IN_PROGRESS;
-  }
-}
-
-uint64_t BackgroundFetchDelegateImpl::JobDetails::GetProcessedBytes() const {
-  return fetch_description->downloaded_bytes +
-         fetch_description->uploaded_bytes + GetInProgressBytes();
-}
-
-uint64_t BackgroundFetchDelegateImpl::JobDetails::GetDownloadedBytes() const {
-  uint64_t bytes = fetch_description->downloaded_bytes;
-  for (const auto& current_fetch : current_fetch_guids)
-    bytes += current_fetch.second.in_progress_downloaded_bytes;
-  return bytes;
-}
-
-uint64_t BackgroundFetchDelegateImpl::JobDetails::GetInProgressBytes() const {
-  uint64_t bytes = 0u;
-  for (const auto& current_fetch : current_fetch_guids) {
-    bytes += current_fetch.second.in_progress_downloaded_bytes +
-             current_fetch.second.in_progress_uploaded_bytes;
-  }
-  return bytes;
-}
-
-void BackgroundFetchDelegateImpl::JobDetails::UpdateInProgressBytes(
-    const std::string& download_guid,
-    uint64_t bytes_uploaded,
-    uint64_t bytes_downloaded) {
-  DCHECK(current_fetch_guids.count(download_guid));
-  auto& request_data = current_fetch_guids.find(download_guid)->second;
-
-  // If we started receiving download bytes then the upload was complete and is
-  // accounted for in |uploaded_bytes|.
-  if (bytes_downloaded > 0u)
-    request_data.in_progress_uploaded_bytes = 0u;
-  else
-    request_data.in_progress_uploaded_bytes = bytes_uploaded;
-
-  request_data.in_progress_downloaded_bytes = bytes_downloaded;
-}
-
-bool BackgroundFetchDelegateImpl::JobDetails::ShouldReportProgressBySize() {
-  if (!fetch_description->download_total_bytes) {
-    // |download_total_bytes| was not set. Cannot report by size.
-    return false;
-  }
-
-  if (fetch_description->completed_requests <
-          fetch_description->total_requests &&
-      GetDownloadedBytes() > fetch_description->download_total_bytes) {
-    // |download_total_bytes| was set too low.
-    return false;
-  }
-
-  return true;
-}
-
-void BackgroundFetchDelegateImpl::GetIconDisplaySize(
-    BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // If Android, return 192x192, else return 0x0. 0x0 means not loading an
-  // icon at all, which is returned for all non-Android platforms as the
-  // icons can't be displayed on the UI yet.
-  // TODO(nator): Move this logic to OfflineItemsCollection, and return icon
-  // size based on display.
-  gfx::Size display_size;
-#if defined(OS_ANDROID)
-  display_size = gfx::Size(192, 192);
-#endif
-  std::move(callback).Run(display_size);
-}
-
-void BackgroundFetchDelegateImpl::GetPermissionForOrigin(
-    const url::Origin& origin,
-    const content::WebContents::Getter& wc_getter,
-    GetPermissionForOriginCallback callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  if (wc_getter) {
-    // The fetch should be thought of as one download. So the origin will be
-    // used as the URL, and the |request_method| is set to GET.
-    content::BrowserContext::GetDownloadManager(context_)
-        ->GetDelegate()
-        ->CheckDownloadAllowed(
-            wc_getter, origin.GetURL(), "GET", base::nullopt,
-            false /* from_download_cross_origin_redirect */,
-            true /* content_initiated */,
-            base::BindOnce(&BackgroundFetchDelegateImpl::
-                               DidGetPermissionFromDownloadRequestLimiter,
-                           weak_ptr_factory_.GetWeakPtr(),
-                           std::move(callback)));
-    return;
-  }
-
-  auto* host_content_settings_map = embedder_->GetHostContentSettingsMap();
-  DCHECK(host_content_settings_map);
-
-  // This is running from a non-top level frame, use the Automatic Downloads
-  // content setting.
-  ContentSetting content_setting = host_content_settings_map->GetContentSetting(
-      origin.GetURL(), origin.GetURL(),
-      ContentSettingsType::AUTOMATIC_DOWNLOADS);
-
-  // The set of valid settings for automatic downloads is set to
-  // {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK}.
-  switch (content_setting) {
-    case CONTENT_SETTING_ALLOW:
-    case CONTENT_SETTING_ASK:
-      std::move(callback).Run(content::BackgroundFetchPermission::ASK);
-      return;
-    case CONTENT_SETTING_BLOCK:
-      std::move(callback).Run(content::BackgroundFetchPermission::BLOCKED);
-      return;
-    case CONTENT_SETTING_DEFAULT:
-    case CONTENT_SETTING_SESSION_ONLY:
-    case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
-    case CONTENT_SETTING_NUM_SETTINGS:
-      NOTREACHED();
-  }
-}
-
-void BackgroundFetchDelegateImpl::DidGetPermissionFromDownloadRequestLimiter(
-    GetPermissionForOriginCallback callback,
-    bool has_permission) {
-  std::move(callback).Run(has_permission
-                              ? content::BackgroundFetchPermission::ALLOWED
-                              : content::BackgroundFetchPermission::BLOCKED);
-}
-
-void BackgroundFetchDelegateImpl::CreateDownloadJob(
-    base::WeakPtr<Client> client,
-    std::unique_ptr<content::BackgroundFetchDescription> fetch_description) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  std::string job_unique_id = fetch_description->job_unique_id;
-  DCHECK(!job_details_map_.count(job_unique_id));
-
-  JobDetails job_details;
-  job_details.client = std::move(client);
-
-  job_details.offline_item =
-      offline_items_collection::OfflineItem(offline_items_collection::ContentId(
-          provider_namespace_, fetch_description->job_unique_id));
-  job_details.offline_item.is_off_the_record = context_->IsOffTheRecord();
-  job_details.offline_item.original_url = fetch_description->origin.GetURL();
-  embedder_->UpdateOfflineItem(&job_details.offline_item);
-
-  job_details.job_state = fetch_description->start_paused
-                              ? JobDetails::State::kPendingWillStartPaused
-                              : JobDetails::State::kPendingWillStartDownloading;
-
-  job_details.fetch_description = std::move(fetch_description);
-
-  job_details.UpdateOfflineItem();
-
-  job_details_map_.emplace(job_unique_id, std::move(job_details));
-}
-
-void BackgroundFetchDelegateImpl::DownloadUrl(
-    const std::string& job_unique_id,
-    const std::string& download_guid,
-    const std::string& method,
-    const GURL& url,
-    const net::NetworkTrafficAnnotationTag& traffic_annotation,
-    const net::HttpRequestHeaders& headers,
-    bool has_request_body) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(job_details_map_.count(job_unique_id));
-  DCHECK(!download_job_unique_id_map_.count(download_guid));
-
-  download_job_unique_id_map_.emplace(download_guid, job_unique_id);
-
-  download::DownloadParams params;
-  params.guid = download_guid;
-  params.client = download::DownloadClient::BACKGROUND_FETCH;
-  params.request_params.method = method;
-  params.request_params.url = url;
-  params.request_params.request_headers = headers;
-  params.callback =
-      base::BindRepeating(&BackgroundFetchDelegateImpl::OnDownloadReceived,
-                          weak_ptr_factory_.GetWeakPtr());
-  params.traffic_annotation =
-      net::MutableNetworkTrafficAnnotationTag(traffic_annotation);
-
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-
-  if (job_details.job_state == JobDetails::State::kPendingWillStartPaused ||
-      job_details.job_state ==
-          JobDetails::State::kPendingWillStartDownloading) {
-    NotifyItemsAdded({job_details.offline_item});
-    job_details.MarkJobAsStarted();
-  }
-
-  if (job_details.job_state == JobDetails::State::kStartedButPaused) {
-    job_details.on_resume =
-        base::BindOnce(&BackgroundFetchDelegateImpl::StartDownload,
-                       GetWeakPtr(), job_unique_id, params, has_request_body);
-  } else {
-    StartDownload(job_unique_id, params, has_request_body);
-  }
-
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-}
-
-void BackgroundFetchDelegateImpl::StartDownload(
-    const std::string& job_unique_id,
-    const download::DownloadParams& params,
-    bool has_request_body) {
-  DCHECK(job_details_map_.count(job_unique_id));
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-
-  job_details.current_fetch_guids.emplace(params.guid, has_request_body);
-  GetDownloadService()->StartDownload(params);
-}
-
-void BackgroundFetchDelegateImpl::Abort(const std::string& job_unique_id) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
-
-  JobDetails& job_details = job_details_iter->second;
-  job_details.job_state = JobDetails::State::kCancelled;
-
-  for (const auto& download_guid_pair : job_details.current_fetch_guids) {
-    GetDownloadService()->CancelDownload(download_guid_pair.first);
-    download_job_unique_id_map_.erase(download_guid_pair.first);
-  }
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-}
-
-void BackgroundFetchDelegateImpl::MarkJobComplete(
-    const std::string& job_unique_id) {
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  DCHECK(job_details_iter != job_details_map_.end());
-
-  JobDetails& job_details = job_details_iter->second;
-  job_details.job_state = JobDetails::State::kJobComplete;
-
-  embedder_->OnJobCompleted(job_details.fetch_description->origin,
-                            job_details.cancelled_from_ui);
-
-  // Clear the |job_details| internals that are no longer needed.
-  job_details.current_fetch_guids.clear();
-  job_details.fetch_description.reset();
+  BackgroundFetchDelegateBase::MarkJobComplete(job_id);
 }
 
 void BackgroundFetchDelegateImpl::UpdateUI(
-    const std::string& job_unique_id,
+    const std::string& job_id,
     const base::Optional<std::string>& title,
     const base::Optional<SkBitmap>& icon) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(title || icon);             // One of the UI options must be updatable.
   DCHECK(!icon || !icon->isNull());  // The |icon|, if provided, is not null.
 
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
+  background_fetch::JobDetails* job_details =
+      GetJobDetails(job_id, /*allow_null=*/true);
+  if (!job_details)
     return;
 
-  JobDetails& job_details = job_details_iter->second;
   // Update the title, if it's different.
-  if (title && job_details.fetch_description->title != *title)
-    job_details.fetch_description->title = *title;
+  if (title && job_details->fetch_description->title != *title)
+    job_details->fetch_description->title = *title;
+
+  DCHECK(base::Contains(ui_state_map_, job_id));
+  UiState& ui_state = ui_state_map_[job_id];
 
   if (icon) {
-    job_details.fetch_description->icon = *icon;
+    job_details->fetch_description->icon = *icon;
     offline_items_collection::UpdateDelta update_delta;
     update_delta.visuals_changed = true;
-    job_details.update_delta = update_delta;
+    ui_state.update_delta = update_delta;
   }
 
-  bool should_update_visuals = job_details.update_delta.has_value()
-                                   ? job_details.update_delta->visuals_changed
+  bool should_update_visuals = ui_state.update_delta.has_value()
+                                   ? ui_state.update_delta->visuals_changed
                                    : false;
 #if !defined(OS_ANDROID)
   should_update_visuals = false;
@@ -442,198 +110,17 @@
 
   if (!should_update_visuals) {
     // Notify the client that the UI updates have been handed over.
-    if (job_details.client)
-      job_details.client->OnUIUpdated(job_unique_id);
+    if (job_details->client)
+      job_details->client->OnUIUpdated(job_id);
   }
 
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-}
-
-void BackgroundFetchDelegateImpl::OnDownloadStarted(
-    const std::string& download_guid,
-    std::unique_ptr<content::BackgroundFetchResponse> response) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  auto download_job_unique_id_iter =
-      download_job_unique_id_map_.find(download_guid);
-  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
-  // OnDownload* methods, then this can be a DCHECK.
-  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
-    return;
-
-  const std::string& job_unique_id = download_job_unique_id_iter->second;
-  auto& job_details = job_details_map_.find(job_unique_id)->second;
-  if (job_details.client) {
-    job_details.client->OnDownloadStarted(job_unique_id, download_guid,
-                                          std::move(response));
-  }
-
-  // Update the upload progress.
-  auto it = job_details.current_fetch_guids.find(download_guid);
-  DCHECK(it != job_details.current_fetch_guids.end());
-  job_details.fetch_description->uploaded_bytes += it->second.body_size_bytes;
-}
-
-void BackgroundFetchDelegateImpl::OnDownloadUpdated(
-    const std::string& download_guid,
-    uint64_t bytes_uploaded,
-    uint64_t bytes_downloaded) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  auto download_job_unique_id_iter =
-      download_job_unique_id_map_.find(download_guid);
-  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
-  // OnDownload* methods, then this can be a DCHECK.
-  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
-    return;
-
-  const std::string& job_unique_id = download_job_unique_id_iter->second;
-
-  DCHECK(job_details_map_.count(job_unique_id));
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-
-  job_details.UpdateInProgressBytes(download_guid, bytes_uploaded,
-                                    bytes_downloaded);
-  if (job_details.fetch_description->download_total_bytes &&
-      job_details.fetch_description->download_total_bytes <
-          job_details.GetDownloadedBytes()) {
-    // Fail the fetch if total download size was set too low.
-    // We only do this if total download size is specified. If not specified,
-    // this check is skipped. This is to allow for situations when the
-    // total download size cannot be known when invoking fetch.
-    FailFetch(job_unique_id);
-    return;
-  }
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-
-  if (job_details.client) {
-    job_details.client->OnDownloadUpdated(job_unique_id, download_guid,
-                                          bytes_uploaded, bytes_downloaded);
-  }
-}
-
-void BackgroundFetchDelegateImpl::OnDownloadFailed(
-    const std::string& download_guid,
-    std::unique_ptr<content::BackgroundFetchResult> result) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  auto download_job_unique_id_iter =
-      download_job_unique_id_map_.find(download_guid);
-  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs
-  // potentially calling OnDownloadFailed with a reason other than
-  // CANCELLED/ABORTED, we should add a DCHECK here.
-  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
-    return;
-
-  const std::string& job_unique_id = download_job_unique_id_iter->second;
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-
-  job_details.UpdateJobOnDownloadComplete(download_guid);
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-
-  // The client cancelled or aborted the download so no need to notify it.
-  if (result->failure_reason ==
-      content::BackgroundFetchResult::FailureReason::CANCELLED) {
-    return;
-  }
-
-  if (job_details.client) {
-    job_details.client->OnDownloadComplete(job_unique_id, download_guid,
-                                           std::move(result));
-  }
-
-  download_job_unique_id_map_.erase(download_guid);
-}
-
-void BackgroundFetchDelegateImpl::OnDownloadSucceeded(
-    const std::string& download_guid,
-    std::unique_ptr<content::BackgroundFetchResult> result) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  auto download_job_unique_id_iter =
-      download_job_unique_id_map_.find(download_guid);
-  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
-  // OnDownload* methods, then this can be a DCHECK.
-  if (download_job_unique_id_iter == download_job_unique_id_map_.end())
-    return;
-
-  const std::string& job_unique_id = download_job_unique_id_iter->second;
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-  job_details.UpdateJobOnDownloadComplete(download_guid);
-
-  job_details.fetch_description->downloaded_bytes +=
-      context_->IsOffTheRecord() ? result->blob_handle->size()
-                                 : result->file_size;
-
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-
-  if (job_details.client) {
-    job_details.client->OnDownloadComplete(job_unique_id, download_guid,
-                                           std::move(result));
-  }
-
-  download_job_unique_id_map_.erase(download_guid);
-}
-
-void BackgroundFetchDelegateImpl::OnDownloadReceived(
-    const std::string& download_guid,
-    download::DownloadParams::StartResult result) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  using StartResult = download::DownloadParams::StartResult;
-  switch (result) {
-    case StartResult::ACCEPTED:
-      // Nothing to do.
-      break;
-    case StartResult::UNEXPECTED_GUID:
-      // The download started in a previous session. Nothing to do.
-      break;
-    case StartResult::BACKOFF:
-      // TODO(delphick): try again later?
-      NOTREACHED();
-      break;
-    case StartResult::UNEXPECTED_CLIENT:
-      // This really should never happen since we're supplying the
-      // DownloadClient.
-      NOTREACHED();
-      break;
-    case StartResult::CLIENT_CANCELLED:
-      // TODO(delphick): do we need to do anything here, since we will have
-      // cancelled it?
-      break;
-    case StartResult::INTERNAL_ERROR:
-      // TODO(delphick): We need to handle this gracefully.
-      NOTREACHED();
-      break;
-    case StartResult::COUNT:
-      NOTREACHED();
-      break;
-  }
-}
-
-// Much of the code in offline_item_collection is not re-entrant, so this should
-// not be called from any of the OfflineContentProvider-inherited methods.
-void BackgroundFetchDelegateImpl::UpdateOfflineItemAndUpdateObservers(
-    JobDetails* job_details) {
-  job_details->UpdateOfflineItem();
-
-  auto update_delta = std::move(job_details->update_delta);
-  NotifyItemUpdated(job_details->offline_item, update_delta);
+  DoUpdateUi(job_id);
 }
 
 void BackgroundFetchDelegateImpl::OpenItem(
     const offline_items_collection::OpenParams& open_params,
     const offline_items_collection::ContentId& id) {
-  auto job_details_iter = job_details_map_.find(id.id);
-  if (job_details_iter == job_details_map_.end())
-    return;
-
-  JobDetails& job_details = job_details_iter->second;
-  if (job_details.client)
-    job_details.client->OnUIActivated(id.id);
-
-  // No point in keeping the job details around anymore.
-  if (job_details.job_state == JobDetails::State::kJobComplete)
-    job_details_map_.erase(job_details_iter);
+  OnUiFinished(id.id, /*activated=*/true);
 }
 
 void BackgroundFetchDelegateImpl::RemoveItem(
@@ -643,93 +130,38 @@
   NOTIMPLEMENTED();
 }
 
-void BackgroundFetchDelegateImpl::FailFetch(const std::string& job_unique_id) {
-  // Save a copy before Abort() deletes the reference.
-  const std::string unique_id = job_unique_id;
-  Abort(job_unique_id);
-
-  if (auto client = GetClient(unique_id)) {
-    client->OnJobCancelled(
-        unique_id,
-        blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);
-  }
-}
-
 void BackgroundFetchDelegateImpl::CancelDownload(
     const offline_items_collection::ContentId& id) {
-  // Save a copy before Abort() deletes the reference.
-  const std::string unique_id = id.id;
-
-  auto job_details_iter = job_details_map_.find(unique_id);
-  DCHECK(job_details_iter != job_details_map_.end());
-
-  auto& job_details = job_details_iter->second;
-  if (job_details.job_state == JobDetails::State::kDownloadsComplete ||
-      job_details.job_state == JobDetails::State::kJobComplete) {
-    // The cancel event arrived after the fetch was complete; ignore it.
-    return;
-  }
-
-  job_details.cancelled_from_ui = true;
-  Abort(unique_id);
-
-  if (auto client = GetClient(unique_id)) {
-    client->OnJobCancelled(
-        unique_id,
-        blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI);
-  }
+  BackgroundFetchDelegateBase::CancelDownload(id.id);
 }
 
 void BackgroundFetchDelegateImpl::PauseDownload(
     const offline_items_collection::ContentId& id) {
-  auto job_details_iter = job_details_map_.find(id.id);
-  if (job_details_iter == job_details_map_.end())
-    return;
-
-  JobDetails& job_details = job_details_iter->second;
-  if (job_details.job_state == JobDetails::State::kDownloadsComplete ||
-      job_details.job_state == JobDetails::State::kJobComplete) {
-    // The pause event arrived after the fetch was complete; ignore it.
-    return;
-  }
-
-  job_details.job_state = JobDetails::State::kStartedButPaused;
-  job_details.UpdateOfflineItem();
-  for (auto& download_guid_pair : job_details.current_fetch_guids)
-    GetDownloadService()->PauseDownload(download_guid_pair.first);
+  UpdateOfflineItem(id.id);
+  BackgroundFetchDelegateBase::PauseDownload(id.id);
 }
 
 void BackgroundFetchDelegateImpl::ResumeDownload(
     const offline_items_collection::ContentId& id,
     bool has_user_gesture) {
-  auto job_details_iter = job_details_map_.find(id.id);
-  if (job_details_iter == job_details_map_.end())
-    return;
-
-  JobDetails& job_details = job_details_iter->second;
-  job_details.job_state = JobDetails::State::kStartedAndDownloading;
-  job_details.UpdateOfflineItem();
-  for (auto& download_guid_pair : job_details.current_fetch_guids)
-    GetDownloadService()->ResumeDownload(download_guid_pair.first);
-
-  if (job_details.on_resume)
-    std::move(job_details.on_resume).Run();
+  UpdateOfflineItem(id.id);
+  BackgroundFetchDelegateBase::ResumeDownload(id.id);
 }
 
 void BackgroundFetchDelegateImpl::GetItemById(
     const offline_items_collection::ContentId& id,
     SingleItemCallback callback) {
-  auto it = job_details_map_.find(id.id);
+  auto iter = ui_state_map_.find(id.id);
   base::Optional<offline_items_collection::OfflineItem> offline_item;
-  if (it != job_details_map_.end())
-    offline_item = it->second.offline_item;
+  if (iter != ui_state_map_.end())
+    offline_item = iter->second.offline_item;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), offline_item));
 }
 
 void BackgroundFetchDelegateImpl::GetAllItems(MultipleItemCallback callback) {
   OfflineItemList item_list;
-  for (auto& entry : job_details_map_)
+  for (auto& entry : ui_state_map_)
     item_list.push_back(entry.second.offline_item);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), item_list));
@@ -748,14 +180,15 @@
   // is not re-entrant and it must be called even if there are no visuals.
   auto visuals =
       std::make_unique<offline_items_collection::OfflineItemVisuals>();
-  auto it = job_details_map_.find(id.id);
-  if (it != job_details_map_.end()) {
-    auto& job_details = it->second;
+  background_fetch::JobDetails* job_details =
+      GetJobDetails(id.id, /*allow_null=*/true);
+  if (job_details) {
     visuals->icon =
-        gfx::Image::CreateFrom1xBitmap(job_details.fetch_description->icon);
-    if (job_details.client &&
-        job_details.job_state == JobDetails::State::kDownloadsComplete) {
-      job_details.client->OnUIUpdated(id.id);
+        gfx::Image::CreateFrom1xBitmap(job_details->fetch_description->icon);
+    if (job_details->client &&
+        job_details->job_state ==
+            background_fetch::JobDetails::State::kDownloadsComplete) {
+      job_details->client->OnUIUpdated(id.id);
     }
   }
 
@@ -785,123 +218,169 @@
   NOTIMPLEMENTED();
 }
 
-bool BackgroundFetchDelegateImpl::IsGuidOutstanding(
-    const std::string& guid) const {
-  auto unique_id_it = download_job_unique_id_map_.find(guid);
-  if (unique_id_it == download_job_unique_id_map_.end())
-    return false;
+void BackgroundFetchDelegateImpl::GetPermissionForOriginWithoutWebContents(
+    const url::Origin& origin,
+    GetPermissionForOriginCallback callback) {
+  auto* host_content_settings_map =
+      HostContentSettingsMapFactory::GetForProfile(profile_);
+  DCHECK(host_content_settings_map);
 
-  auto job_details_it = job_details_map_.find(unique_id_it->second);
-  if (job_details_it == job_details_map_.end())
-    return false;
+  // This is running from a non-top level frame, use the Automatic Downloads
+  // content setting.
+  ContentSetting content_setting = host_content_settings_map->GetContentSetting(
+      origin.GetURL(), origin.GetURL(),
+      ContentSettingsType::AUTOMATIC_DOWNLOADS);
 
-  std::vector<std::string>& outstanding_guids =
-      job_details_it->second.fetch_description->outstanding_guids;
-  return std::find(outstanding_guids.begin(), outstanding_guids.end(), guid) !=
-         outstanding_guids.end();
+  // The set of valid settings for automatic downloads is set to
+  // {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK}.
+  switch (content_setting) {
+    case CONTENT_SETTING_ALLOW:
+    case CONTENT_SETTING_ASK:
+      std::move(callback).Run(content::BackgroundFetchPermission::ASK);
+      return;
+    case CONTENT_SETTING_BLOCK:
+      std::move(callback).Run(content::BackgroundFetchPermission::BLOCKED);
+      return;
+    case CONTENT_SETTING_DEFAULT:
+    case CONTENT_SETTING_SESSION_ONLY:
+    case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT:
+    case CONTENT_SETTING_NUM_SETTINGS:
+      NOTREACHED();
+  }
 }
 
-void BackgroundFetchDelegateImpl::RestartPausedDownload(
-    const std::string& download_guid) {
-  auto job_it = download_job_unique_id_map_.find(download_guid);
+download::DownloadService* BackgroundFetchDelegateImpl::GetDownloadService() {
+  return DownloadServiceFactory::GetInstance()->GetForKey(
+      profile_->GetProfileKey());
+}
 
-  if (job_it == download_job_unique_id_map_.end())
+void BackgroundFetchDelegateImpl::OnJobDetailsCreated(
+    const std::string& job_id) {
+  DCHECK(!base::Contains(ui_state_map_, job_id));
+  UiState& ui_state = ui_state_map_[job_id];
+  offline_items_collection::OfflineItem offline_item(
+      offline_items_collection::ContentId(provider_namespace_, job_id));
+  offline_item.is_off_the_record = profile_->IsOffTheRecord();
+#if defined(OS_ANDROID)
+  if (profile_->IsOffTheRecord())
+    offline_item.otr_profile_id = profile_->GetOTRProfileID().Serialize();
+#endif
+  offline_item.original_url =
+      GetJobDetails(job_id)->fetch_description->origin.GetURL();
+  ui_state.offline_item = offline_item;
+  UpdateOfflineItem(job_id);
+}
+
+void BackgroundFetchDelegateImpl::DoShowUi(const std::string& job_id) {
+  NotifyItemsAdded({ui_state_map_[job_id].offline_item});
+}
+
+// Much of the code in offline_item_collection is not re-entrant, so this should
+// not be called from any of the OfflineContentProvider-inherited methods.
+void BackgroundFetchDelegateImpl::DoUpdateUi(const std::string& job_id) {
+  // Update the OfflineItem that controls the contents of download
+  // notifications and notify any OfflineContentProvider::Observer that was
+  // registered with this instance.
+  UpdateOfflineItem(job_id);
+
+  UiState& ui_state = ui_state_map_[job_id];
+  auto update_delta = std::move(ui_state.update_delta);
+  NotifyItemUpdated(ui_state.offline_item, update_delta);
+}
+
+void BackgroundFetchDelegateImpl::DoCleanUpUi(const std::string& job_id) {
+  ui_state_map_.erase(job_id);
+  // Note that the entry in `ui_state_map_` will leak if OnUiFinished is never
+  // called, and it's not called when the notification is dismissed without
+  // being clicked. See crbug.com/1190390
+}
+
+void BackgroundFetchDelegateImpl::UpdateOfflineItem(const std::string& job_id) {
+  background_fetch::JobDetails* job_details =
+      GetJobDetails(job_id, /*allow_null=*/true);
+  if (!job_details)
     return;
 
-  const std::string& unique_id = job_it->second;
+  content::BackgroundFetchDescription* fetch_description =
+      job_details->fetch_description.get();
+  DCHECK_GT(fetch_description->total_requests, 0);
 
-  DCHECK(job_details_map_.find(unique_id) != job_details_map_.end());
-  JobDetails& job_details = job_details_map_.find(unique_id)->second;
-  job_details.job_state = JobDetails::State::kStartedButPaused;
+  offline_items_collection::OfflineItem* offline_item =
+      &ui_state_map_[job_id].offline_item;
 
-  UpdateOfflineItemAndUpdateObservers(&job_details);
-}
-
-std::set<std::string> BackgroundFetchDelegateImpl::TakeOutstandingGuids() {
-  std::set<std::string> outstanding_guids;
-  for (auto& job_id_details : job_details_map_) {
-    auto& job_details = job_id_details.second;
-
-    // If the job is loaded at this point, then it already started
-    // in a previous session.
-    job_details.MarkJobAsStarted();
-
-    std::vector<std::string>& job_outstanding_guids =
-        job_details.fetch_description->outstanding_guids;
-    for (std::string& outstanding_guid : job_outstanding_guids)
-      outstanding_guids.insert(std::move(outstanding_guid));
-    job_outstanding_guids.clear();
+  using JobState = background_fetch::JobDetails::State;
+  if (job_details->ShouldReportProgressBySize()) {
+    offline_item->progress.value = job_details->GetProcessedBytes();
+    // If we have completed all downloads, update progress max to the processed
+    // bytes in case the provided totals were set too high. This avoids
+    // unnecessary jumping in the progress bar.
+    uint64_t completed_bytes =
+        fetch_description->downloaded_bytes + fetch_description->uploaded_bytes;
+    uint64_t total_bytes = fetch_description->download_total_bytes +
+                           fetch_description->upload_total_bytes;
+    offline_item->progress.max =
+        job_details->job_state == JobState::kDownloadsComplete ? completed_bytes
+                                                               : total_bytes;
+  } else {
+    offline_item->progress.value = fetch_description->completed_requests;
+    offline_item->progress.max = fetch_description->total_requests;
   }
-  return outstanding_guids;
+
+  offline_item->progress.unit =
+      offline_items_collection::OfflineItemProgressUnit::PERCENTAGE;
+
+  offline_item->title = fetch_description->title;
+  offline_item->promote_origin = true;
+  offline_item->is_transient = true;
+  offline_item->is_resumable = true;
+
+  using OfflineItemState = offline_items_collection::OfflineItemState;
+  switch (job_details->job_state) {
+    case JobState::kCancelled:
+      offline_item->state = OfflineItemState::CANCELLED;
+      break;
+    case JobState::kDownloadsComplete:
+      // This includes cases when the download failed, or completed but the
+      // response was an HTTP error, e.g. 404.
+      offline_item->state = OfflineItemState::COMPLETE;
+      offline_item->is_openable = true;
+      break;
+    case JobState::kPendingWillStartPaused:
+    case JobState::kStartedButPaused:
+      offline_item->state = OfflineItemState::PAUSED;
+      break;
+    case JobState::kJobComplete:
+      // There shouldn't be any updates at this point.
+      NOTREACHED();
+      break;
+    default:
+      offline_item->state = OfflineItemState::IN_PROGRESS;
+  }
 }
 
-void BackgroundFetchDelegateImpl::GetUploadData(
-    const std::string& download_guid,
-    download::GetUploadDataCallback callback) {
-  auto job_it = download_job_unique_id_map_.find(download_guid);
-  // TODO(crbug.com/779012): When DownloadService fixes cancelled jobs calling
-  // client methods, then this can be a DCHECK.
-  if (job_it == download_job_unique_id_map_.end()) {
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(callback), /* request_body= */ nullptr));
+void BackgroundFetchDelegateImpl::
+    RecordBackgroundFetchDeletingRegistrationUkmEvent(
+        const url::Origin& origin,
+        bool user_initiated_abort) {
+  auto* ukm_background_service =
+      ukm::UkmBackgroundRecorderFactory::GetForProfile(profile_);
+  ukm_background_service->GetBackgroundSourceIdIfAllowed(
+      origin,
+      base::BindOnce(&BackgroundFetchDelegateImpl::DidGetBackgroundSourceId,
+                     weak_ptr_factory_.GetWeakPtr(), user_initiated_abort));
+}
+
+void BackgroundFetchDelegateImpl::DidGetBackgroundSourceId(
+    bool user_initiated_abort,
+    base::Optional<ukm::SourceId> source_id) {
+  // This background event did not meet the requirements for the UKM service.
+  if (!source_id)
     return;
-  }
 
-  JobDetails& job_details = job_details_map_.find(job_it->second)->second;
-  if (job_details.current_fetch_guids.at(download_guid).status ==
-      JobDetails::RequestData::Status::kAbsent) {
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(callback), /* request_body= */ nullptr));
-    return;
-  }
-
-  if (job_details.client) {
-    job_details.client->GetUploadData(
-        job_it->second, download_guid,
-        base::BindOnce(&BackgroundFetchDelegateImpl::DidGetUploadData,
-                       weak_ptr_factory_.GetWeakPtr(), job_it->second,
-                       download_guid, std::move(callback)));
-  }
+  ukm::builders::BackgroundFetchDeletingRegistration(*source_id)
+      .SetUserInitiatedAbort(user_initiated_abort)
+      .Record(ukm::UkmRecorder::Get());
 }
 
-void BackgroundFetchDelegateImpl::DidGetUploadData(
-    const std::string& unique_id,
-    const std::string& download_guid,
-    download::GetUploadDataCallback callback,
-    blink::mojom::SerializedBlobPtr blob) {
-  if (!blob || blob->uuid.empty()) {
-    std::move(callback).Run(/* request_body= */ nullptr);
-    return;
-  }
-
-  auto job_it = job_details_map_.find(unique_id);
-  if (job_it == job_details_map_.end()) {
-    std::move(callback).Run(/* request_body= */ nullptr);
-    return;
-  }
-
-  auto& job_details = job_it->second;
-  DCHECK(job_details.current_fetch_guids.count(download_guid));
-  auto& request_data = job_details.current_fetch_guids.at(download_guid);
-  request_data.body_size_bytes = blob->size;
-
-  // Use a Data Pipe to transfer the blob.
-  mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter_remote;
-  mojo::Remote<blink::mojom::Blob> blob_remote(std::move(blob->blob));
-  blob_remote->AsDataPipeGetter(
-      data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
-  auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
-  request_body->AppendDataPipe(std::move(data_pipe_getter_remote));
-
-  std::move(callback).Run(request_body);
-}
-
-base::WeakPtr<content::BackgroundFetchDelegate::Client>
-BackgroundFetchDelegateImpl::GetClient(const std::string& job_unique_id) {
-  auto it = job_details_map_.find(job_unique_id);
-  if (it == job_details_map_.end())
-    return nullptr;
-  return it->second.client;
-}
+BackgroundFetchDelegateImpl::UiState::UiState() = default;
+BackgroundFetchDelegateImpl::UiState::~UiState() = default;
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
index 16629fb..05426e82 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -12,119 +12,41 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
+#include "components/background_fetch/background_fetch_delegate_base.h"
 #include "components/download/public/background_service/download_params.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/offline_items_collection/core/offline_content_provider.h"
 #include "components/offline_items_collection/core/offline_item.h"
 #include "components/offline_items_collection/core/update_delta.h"
-#include "content/public/browser/background_fetch_delegate.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
 #include "ui/gfx/image/image.h"
 #include "url/origin.h"
 
-class HostContentSettingsMap;
-
-namespace content {
-class BrowserContext;
-}
-
-namespace download {
-class DownloadService;
-}  // namespace download
+class Profile;
 
 namespace offline_items_collection {
 class OfflineContentAggregator;
 }  // namespace offline_items_collection
 
-// Implementation of BackgroundFetchDelegate using the DownloadService. This
-// also implements OfflineContentProvider which allows it to show notifications
-// for its downloads.
+// Implementation of BackgroundFetchDelegateBase which makes use of offline
+// items collection to show UI.
 class BackgroundFetchDelegateImpl
-    : public content::BackgroundFetchDelegate,
+    : public background_fetch::BackgroundFetchDelegateBase,
       public offline_items_collection::OfflineContentProvider,
       public KeyedService {
  public:
-  // Provides embedder-specific KeyedServices and functionality to
-  // BackgroundFetchDelegateImpl.
-  class Embedder {
-   public:
-    virtual ~Embedder() = default;
-
-    // Gets the OfflineContentAggregator associated with |context_|. Should not
-    // return null.
-    virtual offline_items_collection::OfflineContentAggregator*
-    GetOfflineContentAggregator() = 0;
-
-    // Gets the download service associated with |context_|. Should not return
-    // null.
-    virtual download::DownloadService* GetDownloadService() = 0;
-
-    // Gets the content settings map associated with |context_|. Should not
-    // return null.
-    virtual HostContentSettingsMap* GetHostContentSettingsMap() = 0;
-
-    // Called to give the embedder a chance to do any extra setup necessary for
-    // |offline_item|, which is associated with a download job.
-    virtual void UpdateOfflineItem(
-        offline_items_collection::OfflineItem* offline_item) = 0;
-
-    // Called when the job is done; used by Chrome to record UKM.
-    virtual void OnJobCompleted(const url::Origin& origin,
-                                bool user_initiated_abort) = 0;
-  };
-
-  BackgroundFetchDelegateImpl(content::BrowserContext* context,
-                              std::unique_ptr<Embedder> embedder);
+  explicit BackgroundFetchDelegateImpl(Profile* profile);
   BackgroundFetchDelegateImpl(const BackgroundFetchDelegateImpl&) = delete;
   BackgroundFetchDelegateImpl& operator=(const BackgroundFetchDelegateImpl&) =
       delete;
   ~BackgroundFetchDelegateImpl() override;
 
-  // Lazily initializes and returns the DownloadService.
-  download::DownloadService* GetDownloadService();
-
-  // KeyedService implementation:
-  void Shutdown() override;
-
   // BackgroundFetchDelegate implementation:
-  void GetIconDisplaySize(GetIconDisplaySizeCallback callback) override;
-  void GetPermissionForOrigin(const url::Origin& origin,
-                              const content::WebContents::Getter& wc_getter,
-                              GetPermissionForOriginCallback callback) override;
-  void CreateDownloadJob(base::WeakPtr<Client> client,
-                         std::unique_ptr<content::BackgroundFetchDescription>
-                             fetch_description) override;
-  void DownloadUrl(const std::string& job_unique_id,
-                   const std::string& guid,
-                   const std::string& method,
-                   const GURL& url,
-                   const net::NetworkTrafficAnnotationTag& traffic_annotation,
-                   const net::HttpRequestHeaders& headers,
-                   bool has_request_body) override;
-  void Abort(const std::string& job_unique_id) override;
-  void MarkJobComplete(const std::string& job_unique_id) override;
+  void MarkJobComplete(const std::string& job_id) override;
   void UpdateUI(const std::string& job_unique_id,
                 const base::Optional<std::string>& title,
                 const base::Optional<SkBitmap>& icon) override;
 
-  // Abort all ongoing downloads and fail the fetch. Currently only used when
-  // the bytes downloaded exceed the total download size, if specified.
-  void FailFetch(const std::string& job_unique_id);
-
-  void OnDownloadStarted(
-      const std::string& guid,
-      std::unique_ptr<content::BackgroundFetchResponse> response);
-
-  void OnDownloadUpdated(const std::string& guid,
-                         uint64_t bytes_uploaded,
-                         uint64_t bytes_downloaded);
-
-  void OnDownloadFailed(const std::string& guid,
-                        std::unique_ptr<content::BackgroundFetchResult> result);
-
-  void OnDownloadSucceeded(
-      const std::string& guid,
-      std::unique_ptr<content::BackgroundFetchResult> result);
-
   // OfflineContentProvider implementation:
   void OpenItem(const offline_items_collection::OpenParams& open_params,
                 const offline_items_collection::ContentId& id) override;
@@ -149,155 +71,57 @@
       base::Optional<offline_items_collection::OfflineItemSchedule> schedule)
       override;
 
-  // Whether the provided GUID is resuming from the perspective of Background
-  // Fetch.
-  bool IsGuidOutstanding(const std::string& guid) const;
-
-  // Notifies the OfflineContentAggregator of an interrupted download that is
-  // in a paused state.
-  void RestartPausedDownload(const std::string& download_guid);
-
-  // Returns the set of download GUIDs that have started but did not finish
-  // according to Background Fetch. Clears out all references to outstanding
-  // GUIDs.
-  std::set<std::string> TakeOutstandingGuids();
-
-  // Gets the upload data, if any, associated with the |download_guid|.
-  void GetUploadData(const std::string& download_guid,
-                     download::GetUploadDataCallback callback);
-
-  base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr() {
-    return weak_ptr_factory_.GetWeakPtr();
-  }
+ protected:
+  // BackgroundFetchDelegateBase:
+  void GetPermissionForOriginWithoutWebContents(
+      const url::Origin& origin,
+      GetPermissionForOriginCallback callback) override;
+  download::DownloadService* GetDownloadService() override;
+  void OnJobDetailsCreated(const std::string& job_id) override;
+  void DoShowUi(const std::string& job_id) override;
+  void DoUpdateUi(const std::string& job_id) override;
+  void DoCleanUpUi(const std::string& job_id) override;
 
  private:
   FRIEND_TEST_ALL_PREFIXES(BackgroundFetchBrowserTest, ClickEventIsDispatched);
   FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDelegateImplTest, RecordUkmEvent);
+  FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDelegateImplTest,
+                           HistoryServiceIntegration);
+  FRIEND_TEST_ALL_PREFIXES(BackgroundFetchDelegateImplTest,
+                           HistoryServiceIntegrationUrlVsOrigin);
 
-  struct JobDetails {
-    // If a job is part of the |job_details_map_|, it will have one of these
-    // states.
-    enum class State {
-      kPendingWillStartPaused,
-      kPendingWillStartDownloading,
-      kStartedButPaused,
-      kStartedAndDownloading,
-      // The job was aborted.
-      kCancelled,
-      // All requests were processed (either succeeded or failed).
-      kDownloadsComplete,
-      // The appropriate completion event (success, fail, abort) has been
-      // dispatched.
-      kJobComplete,
-    };
-
-    JobDetails(JobDetails&&);
-    JobDetails();
-    ~JobDetails();
-
-    void UpdateOfflineItem();
-    void MarkJobAsStarted();
-    void UpdateJobOnDownloadComplete(const std::string& download_guid);
-
-    // Returns how many bytes have been processed by the Download Service so
-    // far.
-    uint64_t GetProcessedBytes() const;
-
-    // Returns the number of downloaded bytes, including for the in progress
-    // requests.
-    uint64_t GetDownloadedBytes() const;
-
-    void UpdateInProgressBytes(const std::string& download_guid,
-                               uint64_t bytes_uploaded,
-                               uint64_t bytes_downloaded);
-
-    struct RequestData {
-      enum class Status {
-        kAbsent,
-        kIncluded,
-      };
-
-      explicit RequestData(bool has_upload_data);
-      ~RequestData();
-
-      Status status = Status::kAbsent;
-
-      uint64_t body_size_bytes = 0u;
-      uint64_t in_progress_uploaded_bytes = 0u;
-      uint64_t in_progress_downloaded_bytes = 0u;
-    };
-
-    // The client to report the Background Fetch updates to.
-    base::WeakPtr<Client> client;
-
-    // Set of DownloadService GUIDs that are currently processed. They are
-    // added by DownloadUrl and are removed when the fetch completes, fails,
-    // or is cancelled.
-    std::map<std::string, RequestData> current_fetch_guids;
+  // Represents the data which is associated with a particular BGF job and is
+  // relevant to the UI.
+  struct UiState {
+    UiState();
+    ~UiState();
 
     offline_items_collection::OfflineItem offline_item;
     base::Optional<offline_items_collection::UpdateDelta> update_delta;
-    State job_state;
-    std::unique_ptr<content::BackgroundFetchDescription> fetch_description;
-    bool cancelled_from_ui = false;
-
-    base::OnceClosure on_resume;
-
-   private:
-    // Whether we should report progress of the job in terms of size of
-    // downloads or in terms of the number of files being downloaded.
-    bool ShouldReportProgressBySize();
-
-    // Returns the number of bytes processed by in-progress requests.
-    uint64_t GetInProgressBytes() const;
-
-    DISALLOW_COPY_AND_ASSIGN(JobDetails);
   };
 
-  // Starts a download according to |params| belonging to |job_unique_id|.
-  void StartDownload(const std::string& job_unique_id,
-                     const download::DownloadParams& params,
-                     bool has_request_body);
+  // Updates the entry in |ui_state_map_| based on the corresponding JobDetails
+  // object.
+  void UpdateOfflineItem(const std::string& job_id);
 
-  // Updates the OfflineItem that controls the contents of download
-  // notifications and notifies any OfflineContentProvider::Observer that was
-  // registered with this instance.
-  void UpdateOfflineItemAndUpdateObservers(JobDetails* job_details);
+  // Helper methods for recording BackgroundFetchDeletingRegistration UKM event.
+  // We check with UkmBackgroundRecorderService whether this event for |origin|
+  // can be recorded.
+  void RecordBackgroundFetchDeletingRegistrationUkmEvent(
+      const url::Origin& origin,
+      bool user_initiated_abort);
+  void DidGetBackgroundSourceId(bool user_initiated_abort,
+                                base::Optional<ukm::SourceId> source_id);
 
-  void OnDownloadReceived(const std::string& guid,
-                          download::DownloadParams::StartResult result);
-
-  // The callback passed to DownloadRequestLimiter::CanDownload().
-  void DidGetPermissionFromDownloadRequestLimiter(
-      GetPermissionForOriginCallback callback,
-      bool has_permission);
-
-  void DidGetUploadData(const std::string& unique_id,
-                        const std::string& download_guid,
-                        download::GetUploadDataCallback callback,
-                        blink::mojom::SerializedBlobPtr blob);
-
-  // Returns the client for a given |job_unique_id|.
-  base::WeakPtr<Client> GetClient(const std::string& job_unique_id);
-
-  // The browser context this service is being created for.
-  content::BrowserContext* context_;
-
-  std::unique_ptr<Embedder> embedder_;
+  // The profile this service is being created for.
+  Profile* profile_;
 
   // The namespace provided to the |offline_content_aggregator_| and used when
   // creating Content IDs.
   std::string provider_namespace_;
 
-  // The BackgroundFetchDelegateImplFactory depends on the
-  // DownloadServiceFactory, so |download_service_| should outlive |this|.
-  download::DownloadService* download_service_ = nullptr;
-
-  // Map from individual download GUIDs to job unique ids.
-  std::map<std::string, std::string> download_job_unique_id_map_;
-
-  // Map from job unique ids to the details of the job.
-  std::map<std::string, JobDetails> job_details_map_;
+  // A map from job id to associated UI state.
+  std::map<std::string, UiState> ui_state_map_;
 
   offline_items_collection::OfflineContentAggregator*
       offline_content_aggregator_;
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc
index 73e502d..3528a3d80 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl_unittest.cc
@@ -69,8 +69,8 @@
   recorder_->SetOnAddEntryCallback(
       ukm::builders::BackgroundFetchDeletingRegistration::kEntryName,
       run_loop.QuitClosure());
-  delegate_->embedder_->OnJobCompleted(origin,
-                                       /* user_initiated_abort= */ true);
+  delegate_->RecordBackgroundFetchDeletingRegistrationUkmEvent(
+      origin, /* user_initiated_abort= */ true);
   run_loop.Run();
 
   {
diff --git a/chrome/browser/background_fetch/background_fetch_download_client.cc b/chrome/browser/background_fetch/background_fetch_download_client.cc
deleted file mode 100644
index 9ad97ef7..0000000
--- a/chrome/browser/background_fetch/background_fetch_download_client.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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/background_fetch/background_fetch_download_client.h"
-
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "chrome/browser/background_fetch/background_fetch_delegate_impl.h"
-#include "components/download/public/background_service/download_metadata.h"
-#include "components/download/public/background_service/download_service.h"
-#include "content/public/browser/background_fetch_response.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "services/network/public/cpp/resource_request_body.h"
-#include "url/origin.h"
-
-namespace {
-
-using BackgroundFetchFailureReason =
-    content::BackgroundFetchResult::FailureReason;
-BackgroundFetchFailureReason ToBackgroundFetchFailureReason(
-    download::Client::FailureReason reason) {
-  switch (reason) {
-    case download::Client::FailureReason::NETWORK:
-      return BackgroundFetchFailureReason::NETWORK;
-    case download::Client::FailureReason::UPLOAD_TIMEDOUT:
-    case download::Client::FailureReason::TIMEDOUT:
-      return BackgroundFetchFailureReason::TIMEDOUT;
-    case download::Client::FailureReason::UNKNOWN:
-      return BackgroundFetchFailureReason::FETCH_ERROR;
-    case download::Client::FailureReason::ABORTED:
-    case download::Client::FailureReason::CANCELLED:
-      return BackgroundFetchFailureReason::CANCELLED;
-  }
-}
-
-}  // namespace
-
-BackgroundFetchDownloadClient::BackgroundFetchDownloadClient(
-    content::BrowserContext* context)
-    : browser_context_(context), delegate_(nullptr) {}
-
-BackgroundFetchDownloadClient::~BackgroundFetchDownloadClient() = default;
-
-void BackgroundFetchDownloadClient::OnServiceInitialized(
-    bool state_lost,
-    const std::vector<download::DownloadMetaData>& downloads) {
-  std::set<std::string> outstanding_guids =
-      GetDelegate()->TakeOutstandingGuids();
-  for (const auto& download : downloads) {
-    if (!outstanding_guids.count(download.guid)) {
-      // Background Fetch is not aware of this GUID, so it successfully
-      // completed but the information is still around.
-      continue;
-    }
-
-    if (download.completion_info) {
-      // The download finished but was not persisted.
-      OnDownloadSucceeded(download.guid, *download.completion_info);
-      return;
-    }
-
-    // The download is active, and will call the appropriate functions.
-
-    if (download.paused) {
-      // We need to resurface the notification in a paused state.
-      content::BrowserThread::PostBestEffortTask(
-          FROM_HERE, base::SequencedTaskRunnerHandle::Get(),
-          base::BindOnce(&BackgroundFetchDelegateImpl::RestartPausedDownload,
-                         GetDelegate()->GetWeakPtr(), download.guid));
-    }
-  }
-
-  // There is also the case that the Download Service is not aware of the GUID.
-  // i.e. there is a guid in |outstanding_guids| not in |downloads|.
-  // This can be due to:
-  // 1. The browser crashing before the download started.
-  // 2. The download failing before persisting the state.
-  // 3. The browser was forced to clean-up the the download.
-  // In either case the download should be allowed to restart, so there is
-  // nothing to do here.
-}
-
-void BackgroundFetchDownloadClient::OnServiceUnavailable() {}
-
-void BackgroundFetchDownloadClient::OnDownloadStarted(
-    const std::string& guid,
-    const std::vector<GURL>& url_chain,
-    const scoped_refptr<const net::HttpResponseHeaders>& headers) {
-  // TODO(crbug.com/884672): Validate the chain/headers and cancel the download
-  // if invalid.
-  auto response =
-      std::make_unique<content::BackgroundFetchResponse>(url_chain, headers);
-  GetDelegate()->OnDownloadStarted(guid, std::move(response));
-}
-
-void BackgroundFetchDownloadClient::OnDownloadUpdated(
-    const std::string& guid,
-    uint64_t bytes_uploaded,
-    uint64_t bytes_downloaded) {
-  GetDelegate()->OnDownloadUpdated(guid, bytes_uploaded, bytes_downloaded);
-}
-
-void BackgroundFetchDownloadClient::OnDownloadFailed(
-    const std::string& guid,
-    const download::CompletionInfo& info,
-    download::Client::FailureReason reason) {
-  auto response = std::make_unique<content::BackgroundFetchResponse>(
-      info.url_chain, info.response_headers);
-  auto result = std::make_unique<content::BackgroundFetchResult>(
-      std::move(response), base::Time::Now(),
-      ToBackgroundFetchFailureReason(reason));
-  GetDelegate()->OnDownloadFailed(guid, std::move(result));
-}
-
-void BackgroundFetchDownloadClient::OnDownloadSucceeded(
-    const std::string& guid,
-    const download::CompletionInfo& info) {
-  if (browser_context_->IsOffTheRecord())
-    DCHECK(info.blob_handle);
-  else
-    DCHECK(!info.path.empty());
-
-  auto response = std::make_unique<content::BackgroundFetchResponse>(
-      info.url_chain, info.response_headers);
-  auto result = std::make_unique<content::BackgroundFetchResult>(
-      std::move(response), base::Time::Now(), info.path, info.blob_handle,
-      info.bytes_downloaded);
-
-  GetDelegate()->OnDownloadSucceeded(guid, std::move(result));
-}
-
-bool BackgroundFetchDownloadClient::CanServiceRemoveDownloadedFile(
-    const std::string& guid,
-    bool force_delete) {
-  // If |force_delete| is true the file will be removed anyway.
-  // TODO(rayankans): Add UMA to see how often this happens.
-  return force_delete || GetDelegate()->IsGuidOutstanding(guid);
-}
-
-void BackgroundFetchDownloadClient::GetUploadData(
-    const std::string& guid,
-    download::GetUploadDataCallback callback) {
-  GetDelegate()->GetUploadData(guid, std::move(callback));
-}
-
-BackgroundFetchDelegateImpl* BackgroundFetchDownloadClient::GetDelegate() {
-  if (delegate_)
-    return delegate_.get();
-
-  content::BackgroundFetchDelegate* delegate =
-      browser_context_->GetBackgroundFetchDelegate();
-
-  delegate_ = static_cast<BackgroundFetchDelegateImpl*>(delegate)->GetWeakPtr();
-  DCHECK(delegate_);
-  return delegate_.get();
-}
diff --git a/chrome/browser/background_fetch/background_fetch_download_client.h b/chrome/browser/background_fetch/background_fetch_download_client.h
deleted file mode 100644
index 8ca9bff..0000000
--- a/chrome/browser/background_fetch/background_fetch_download_client.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
-#define CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/download/public/background_service/client.h"
-
-class BackgroundFetchDelegateImpl;
-
-namespace content {
-class BrowserContext;
-}  // namespace content
-
-// A DownloadService client used by BackgroundFetch. Mostly this just forwards
-// calls to BackgroundFetchDelegateImpl.
-class BackgroundFetchDownloadClient : public download::Client {
- public:
-  explicit BackgroundFetchDownloadClient(content::BrowserContext* context);
-  ~BackgroundFetchDownloadClient() override;
-
- private:
-  // Lazily initializes and returns |delegate_| as a raw pointer.
-  BackgroundFetchDelegateImpl* GetDelegate();
-
-  // download::Client implementation
-  void OnServiceInitialized(
-      bool state_lost,
-      const std::vector<download::DownloadMetaData>& downloads) override;
-  void OnServiceUnavailable() override;
-  void OnDownloadStarted(
-      const std::string& guid,
-      const std::vector<GURL>& url_chain,
-      const scoped_refptr<const net::HttpResponseHeaders>& headers) override;
-  void OnDownloadUpdated(const std::string& guid,
-                         uint64_t bytes_uploaded,
-                         uint64_t bytes_downloaded) override;
-  void OnDownloadFailed(const std::string& guid,
-                        const download::CompletionInfo& info,
-                        download::Client::FailureReason reason) override;
-  void OnDownloadSucceeded(const std::string& guid,
-                           const download::CompletionInfo& info) override;
-  bool CanServiceRemoveDownloadedFile(const std::string& guid,
-                                      bool force_delete) override;
-  void GetUploadData(const std::string& guid,
-                     download::GetUploadDataCallback callback) override;
-
-  content::BrowserContext* browser_context_;
-  base::WeakPtr<BackgroundFetchDelegateImpl> delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDownloadClient);
-};
-
-#endif  // CHROME_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DOWNLOAD_CLIENT_H_
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index 034cfcf..416cb68 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -16,7 +16,6 @@
 #include "base/task/thread_pool.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_image_download_client.h"
-#include "chrome/browser/background_fetch/background_fetch_download_client.h"
 #include "chrome/browser/download/deferred_client_wrapper.h"
 #include "chrome/browser/download/download_manager_utils.h"
 #include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
@@ -27,6 +26,7 @@
 #include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/transition_manager/full_browser_transition_manager.h"
 #include "chrome/common/chrome_constants.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"
@@ -58,7 +58,7 @@
 
 std::unique_ptr<download::Client> CreateBackgroundFetchDownloadClient(
     Profile* profile) {
-  return std::make_unique<BackgroundFetchDownloadClient>(profile);
+  return std::make_unique<background_fetch::DownloadClient>(profile);
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)