Download driver for components/download.

This CL introduces the glue layer between //components/download and
//content. The DownloadDriver interface will be the only place to access
content functionalities from download service.

Also provides a test support class for //components/download code. The
test support version of DownloadManager is not done in this CL.

The response/request headers pumping is not done in this CL, which
requires tweak on download network code.

BUG=717180

Review-Url: https://codereview.chromium.org/2880933002
Cr-Commit-Position: refs/heads/master@{#474191}
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc
index ec81704..fb47fa8 100644
--- a/chrome/browser/download/download_history.cc
+++ b/chrome/browser/download/download_history.cc
@@ -315,6 +315,7 @@
     ++history_size_;
   }
   notifier_.GetManager()->CheckForHistoryFilesRemoval();
+  notifier_.GetManager()->PostInitialization();
 
   initial_history_query_complete_ = true;
   for (Observer& observer : observers_)
diff --git a/chrome/browser/download/download_ui_controller_unittest.cc b/chrome/browser/download/download_ui_controller_unittest.cc
index 47308a7..87af5bd 100644
--- a/chrome/browser/download/download_ui_controller_unittest.cc
+++ b/chrome/browser/download/download_ui_controller_unittest.cc
@@ -329,6 +329,7 @@
 
   EXPECT_CALL(*item, GetOriginalMimeType());
   EXPECT_CALL(*manager(), CheckForHistoryFilesRemoval());
+  EXPECT_CALL(*manager(), PostInitialization());
 
   {
     testing::InSequence s;
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 0e5a648..0c176a8e 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -190,6 +190,7 @@
       "//components/discardable_memory/service:unit_tests",
       "//components/dom_distiller/content/browser:unit_tests",
       "//components/domain_reliability:unit_tests",
+      "//components/download/content:unit_tests",
       "//components/error_page/renderer:unit_tests",
       "//components/favicon/content:unit_tests",
       "//components/gcm_driver/instance_id:unit_tests",
diff --git a/components/download/content/BUILD.gn b/components/download/content/BUILD.gn
new file mode 100644
index 0000000..7ca79f6
--- /dev/null
+++ b/components/download/content/BUILD.gn
@@ -0,0 +1,42 @@
+# 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("content") {
+  sources = [
+    "download_driver_impl.cc",
+    "download_driver_impl.h",
+  ]
+
+  public_deps = [
+    "//components/download/internal",
+    "//components/download/public",
+  ]
+
+  deps = [
+    "//base",
+    "//content/public/browser",
+    "//net",
+    "//url",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "download_driver_impl_unittest.cc",
+  ]
+
+  deps = [
+    ":content",
+    "//content/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/download/content/DEPS b/components/download/content/DEPS
new file mode 100644
index 0000000..ea159c83
--- /dev/null
+++ b/components/download/content/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+content/public/browser",
+  "+content/public/test",
+  "+base",
+  "+net",
+]
diff --git a/components/download/content/download_driver_impl.cc b/components/download/content/download_driver_impl.cc
new file mode 100644
index 0000000..0d1d281
--- /dev/null
+++ b/components/download/content/download_driver_impl.cc
@@ -0,0 +1,188 @@
+// 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/content/download_driver_impl.h"
+
+#include "components/download/internal/driver_entry.h"
+#include "content/public/browser/download_interrupt_reasons.h"
+#include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/storage_partition.h"
+#include "net/http/http_response_headers.h"
+
+namespace download {
+
+namespace {
+
+// Converts a content::DownloadItem::DownloadState to DriverEntry::State.
+DriverEntry::State ToDriverEntryState(
+    content::DownloadItem::DownloadState state) {
+  switch (state) {
+    case content::DownloadItem::IN_PROGRESS:
+      return DriverEntry::State::IN_PROGRESS;
+    case content::DownloadItem::COMPLETE:
+      return DriverEntry::State::COMPLETE;
+    case content::DownloadItem::CANCELLED:
+      return DriverEntry::State::CANCELLED;
+    case content::DownloadItem::INTERRUPTED:
+      return DriverEntry::State::INTERRUPTED;
+    case content::DownloadItem::MAX_DOWNLOAD_STATE:
+      return DriverEntry::State::UNKNOWN;
+    default:
+      NOTREACHED();
+      return DriverEntry::State::UNKNOWN;
+  }
+}
+
+}  // namespace
+
+// static
+DriverEntry DownloadDriverImpl::CreateDriverEntry(
+    const content::DownloadItem* item) {
+  DCHECK(item);
+  DriverEntry entry;
+  entry.guid = item->GetGuid();
+  entry.state = ToDriverEntryState(item->GetState());
+  entry.paused = item->IsPaused();
+  entry.bytes_downloaded = item->GetReceivedBytes();
+  entry.expected_total_size = item->GetTotalBytes();
+  entry.response_headers = item->GetResponseHeaders();
+  return entry;
+}
+
+DownloadDriverImpl::DownloadDriverImpl(content::DownloadManager* manager,
+                                       const base::FilePath& dir)
+    : download_manager_(manager), file_dir_(dir), client_(nullptr) {
+  DCHECK(download_manager_);
+}
+
+DownloadDriverImpl::~DownloadDriverImpl() {
+  if (download_manager_)
+    download_manager_->RemoveObserver(this);
+}
+
+void DownloadDriverImpl::Initialize(DownloadDriver::Client* client) {
+  DCHECK(!client_);
+  client_ = client;
+  DCHECK(client_);
+
+  // |download_manager_| may be shut down. Informs the client.
+  if (!download_manager_) {
+    client_->OnDriverReady(false);
+    return;
+  }
+
+  download_manager_->AddObserver(this);
+  if (download_manager_->IsManagerInitialized())
+    client_->OnDriverReady(true);
+}
+
+bool DownloadDriverImpl::IsReady() const {
+  return client_ && download_manager_;
+}
+
+void DownloadDriverImpl::Start(const DownloadParams& params) {
+  DCHECK(!params.request_params.url.is_empty());
+  DCHECK(!params.guid.empty());
+  if (!download_manager_)
+    return;
+
+  content::StoragePartition* storage_partition =
+      content::BrowserContext::GetStoragePartitionForSite(
+          download_manager_->GetBrowserContext(), params.request_params.url);
+  DCHECK(storage_partition);
+
+  std::unique_ptr<content::DownloadUrlParameters> download_url_params(
+      new content::DownloadUrlParameters(
+          params.request_params.url,
+          storage_partition->GetURLRequestContext()));
+
+  // TODO(xingliu): Handle the request headers from |params|, need to tweak
+  // download network stack.
+  // Make content::DownloadManager handle potential guid collision and return
+  // an error to fail the download cleanly.
+  download_url_params->set_guid(params.guid);
+  download_url_params->set_transient(true);
+  download_url_params->set_method(params.request_params.method);
+  download_url_params->set_file_path(file_dir_.AppendASCII(params.guid));
+
+  download_manager_->DownloadUrl(std::move(download_url_params));
+}
+
+void DownloadDriverImpl::Cancel(const std::string& guid) {
+  if (!download_manager_)
+    return;
+  content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+  // Cancels the download and removes the persisted records in content layer.
+  if (item) {
+    item->RemoveObserver(this);
+    item->Remove();
+  }
+}
+
+void DownloadDriverImpl::Pause(const std::string& guid) {
+  if (!download_manager_)
+    return;
+  content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+  if (item)
+    item->Pause();
+}
+
+void DownloadDriverImpl::Resume(const std::string& guid) {
+  if (!download_manager_)
+    return;
+  content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+  if (item)
+    item->Resume();
+}
+
+base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
+  if (!download_manager_)
+    return base::nullopt;
+  content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+  if (item)
+    return CreateDriverEntry(item);
+  return base::nullopt;
+}
+
+void DownloadDriverImpl::OnDownloadUpdated(content::DownloadItem* item) {
+  DCHECK(client_);
+
+  using DownloadState = content::DownloadItem::DownloadState;
+  DownloadState state = item->GetState();
+  content::DownloadInterruptReason reason = item->GetLastReason();
+  DriverEntry entry = CreateDriverEntry(item);
+
+  if (state == DownloadState::COMPLETE) {
+    client_->OnDownloadSucceeded(entry, item->GetTargetFilePath());
+    item->RemoveObserver(this);
+  } else if (state == DownloadState::IN_PROGRESS) {
+    client_->OnDownloadUpdated(entry);
+  } else if (reason !=
+             content::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE) {
+    client_->OnDownloadFailed(entry, static_cast<int>(reason));
+    item->RemoveObserver(this);
+  }
+}
+
+void DownloadDriverImpl::OnDownloadCreated(content::DownloadManager* manager,
+                                           content::DownloadItem* item) {
+  // Listens to all downloads.
+  item->AddObserver(this);
+  DCHECK(client_);
+  DriverEntry entry = CreateDriverEntry(item);
+  client_->OnDownloadCreated(entry);
+}
+
+void DownloadDriverImpl::OnManagerInitialized() {
+  DCHECK(client_);
+  DCHECK(download_manager_);
+  client_->OnDriverReady(true);
+}
+
+void DownloadDriverImpl::ManagerGoingDown(content::DownloadManager* manager) {
+  DCHECK_EQ(download_manager_, manager);
+  download_manager_ = nullptr;
+}
+
+}  // namespace download
diff --git a/components/download/content/download_driver_impl.h b/components/download/content/download_driver_impl.h
new file mode 100644
index 0000000..c7c5b1c
--- /dev/null
+++ b/components/download/content/download_driver_impl.h
@@ -0,0 +1,67 @@
+// 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_CONTENT_DOWNLOAD_DRIVER_IMPL_H_
+#define COMPONENTS_DOWNLOAD_CONTENT_DOWNLOAD_DRIVER_IMPL_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "components/download/internal/download_driver.h"
+#include "components/download/public/download_params.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/download_manager.h"
+
+namespace download {
+
+struct DriverEntry;
+
+// Aggregates and handles all interaction between download service and content
+// download logic.
+class DownloadDriverImpl : public DownloadDriver,
+                           public content::DownloadManager::Observer,
+                           public content::DownloadItem::Observer {
+ public:
+  // Creates a driver entry based on a download item.
+  static DriverEntry CreateDriverEntry(const content::DownloadItem* item);
+
+  // Create the driver. All files downloaded will be saved to |dir|.
+  DownloadDriverImpl(content::DownloadManager* manager,
+                     const base::FilePath& dir);
+  ~DownloadDriverImpl() override;
+
+  // DownloadDriver implementation.
+  void Initialize(DownloadDriver::Client* client) override;
+  bool IsReady() const override;
+  void Start(const DownloadParams& params) override;
+  void Cancel(const std::string& guid) override;
+  void Pause(const std::string& guid) override;
+  void Resume(const std::string& guid) override;
+  base::Optional<DriverEntry> Find(const std::string& guid) override;
+
+ private:
+  // content::DownloadItem::Observer implementation.
+  void OnDownloadUpdated(content::DownloadItem* item) override;
+
+  // content::DownloadManager::Observer implementation.
+  void OnDownloadCreated(content::DownloadManager* manager,
+                         content::DownloadItem* item) override;
+  void OnManagerInitialized() override;
+  void ManagerGoingDown(content::DownloadManager* manager) override;
+
+  // Low level download handle.
+  content::DownloadManager* download_manager_;
+
+  // Target directory of download files.
+  base::FilePath file_dir_;
+
+  // The client that receives updates from low level download logic.
+  DownloadDriver::Client* client_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadDriverImpl);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_CONTENT_DOWNLOAD_DRIVER_IMPL_H_
diff --git a/components/download/content/download_driver_impl_unittest.cc b/components/download/content/download_driver_impl_unittest.cc
new file mode 100644
index 0000000..c53b490f
--- /dev/null
+++ b/components/download/content/download_driver_impl_unittest.cc
@@ -0,0 +1,129 @@
+// 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/content/download_driver_impl.h"
+
+#include <memory>
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "content/public/test/fake_download_item.h"
+#include "content/public/test/mock_download_manager.h"
+#include "net/http/http_response_headers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+
+namespace download {
+
+namespace {
+
+const char kFakeGuid[] = "fake_guid";
+
+// Matcher to compare driver entries. Not all the memeber fields are compared.
+// Currently no comparison in non test code, so no operator== override for
+// driver entry.
+MATCHER_P(DriverEntryEuqual, entry, "") {
+  return entry.guid == arg.guid && entry.state == arg.state &&
+         entry.bytes_downloaded == arg.bytes_downloaded;
+}
+
+}  // namespace
+
+class MockDriverClient : public DownloadDriver::Client {
+ public:
+  MOCK_METHOD1(OnDriverReady, void(bool));
+  MOCK_METHOD1(OnDownloadCreated, void(const DriverEntry&));
+  MOCK_METHOD2(OnDownloadFailed, void(const DriverEntry&, int));
+  MOCK_METHOD2(OnDownloadSucceeded,
+               void(const DriverEntry&, const base::FilePath&));
+  MOCK_METHOD1(OnDownloadUpdated, void(const DriverEntry&));
+};
+
+class DownloadDriverImplTest : public testing::Test {
+ public:
+  DownloadDriverImplTest() = default;
+  ~DownloadDriverImplTest() override = default;
+
+  void SetUp() override {
+    driver_ =
+        base::MakeUnique<DownloadDriverImpl>(&mock_manager_, base::FilePath());
+  }
+
+  // TODO(xingliu): implements test download manager for embedders to test.
+  NiceMock<content::MockDownloadManager> mock_manager_;
+  MockDriverClient mock_client_;
+  std::unique_ptr<DownloadDriverImpl> driver_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DownloadDriverImplTest);
+};
+
+// Ensure the download manager can be initialized after the download driver.
+TEST_F(DownloadDriverImplTest, ManagerLateInitialization) {
+  EXPECT_CALL(mock_manager_, IsManagerInitialized())
+      .Times(1)
+      .WillOnce(Return(false));
+  driver_->Initialize(&mock_client_);
+
+  EXPECT_CALL(mock_client_, OnDriverReady(true));
+  static_cast<content::DownloadManager::Observer*>(driver_.get())
+      ->OnManagerInitialized();
+}
+
+// Ensures download updates from download items are propagated correctly.
+TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
+  using DownloadState = content::DownloadItem::DownloadState;
+  using DownloadInterruptReason = content::DownloadInterruptReason;
+
+  EXPECT_CALL(mock_manager_, IsManagerInitialized())
+      .Times(1)
+      .WillOnce(Return(true));
+  EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(1);
+  driver_->Initialize(&mock_client_);
+
+  content::FakeDownloadItem fake_item;
+  fake_item.SetState(DownloadState::IN_PROGRESS);
+  fake_item.SetGuid(kFakeGuid);
+  fake_item.SetReceivedBytes(0);
+  fake_item.SetTotalBytes(1024);
+  DriverEntry entry = DownloadDriverImpl::CreateDriverEntry(&fake_item);
+
+  EXPECT_CALL(mock_client_, OnDownloadUpdated(DriverEntryEuqual(entry)))
+      .Times(1)
+      .RetiresOnSaturation();
+  static_cast<content::DownloadItem::Observer*>(driver_.get())
+      ->OnDownloadUpdated(&fake_item);
+
+  // Nothing happens for cancelled state.
+  fake_item.SetState(DownloadState::CANCELLED);
+  static_cast<content::DownloadItem::Observer*>(driver_.get())
+      ->OnDownloadUpdated(&fake_item);
+
+  fake_item.SetReceivedBytes(1024);
+  fake_item.SetState(DownloadState::COMPLETE);
+  entry = DownloadDriverImpl::CreateDriverEntry(&fake_item);
+  EXPECT_CALL(mock_client_, OnDownloadSucceeded(DriverEntryEuqual(entry), _))
+      .Times(1)
+      .RetiresOnSaturation();
+  static_cast<content::DownloadItem::Observer*>(driver_.get())
+      ->OnDownloadUpdated(&fake_item);
+
+  fake_item.SetState(DownloadState::INTERRUPTED);
+  fake_item.SetLastReason(
+      DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT);
+  entry = DownloadDriverImpl::CreateDriverEntry(&fake_item);
+  int reason = static_cast<int>(
+      DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT);
+  EXPECT_CALL(mock_client_, OnDownloadFailed(DriverEntryEuqual(entry), reason))
+      .Times(1)
+      .RetiresOnSaturation();
+  static_cast<content::DownloadItem::Observer*>(driver_.get())
+      ->OnDownloadUpdated(&fake_item);
+}
+
+}  // namespace download
diff --git a/components/download/internal/BUILD.gn b/components/download/internal/BUILD.gn
index 7e35171..d1e1e43 100644
--- a/components/download/internal/BUILD.gn
+++ b/components/download/internal/BUILD.gn
@@ -11,14 +11,18 @@
   visibility = [
     ":*",
     "//components/download",
+    "//components/download/content",
     "//components/download/internal/test:test_support",
   ]
 
   sources = [
     "config.cc",
     "config.h",
+    "download_driver.h",
     "download_service_impl.cc",
     "download_service_impl.h",
+    "driver_entry.cc",
+    "driver_entry.h",
     "entry.cc",
     "entry.h",
     "model.h",
diff --git a/components/download/internal/DEPS b/components/download/internal/DEPS
index a348cdf..4ca86d9b 100644
--- a/components/download/internal/DEPS
+++ b/components/download/internal/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "-components/download/content",
   "-content",
   "+base",
   "+net",
diff --git a/components/download/internal/download_driver.h b/components/download/internal/download_driver.h
new file mode 100644
index 0000000..88247d1
--- /dev/null
+++ b/components/download/internal/download_driver.h
@@ -0,0 +1,76 @@
+// 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_DRIVER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "components/download/internal/driver_entry.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace download {
+
+struct DownloadParams;
+
+// The interface that includes all the operations to interact with low level
+// download library functionalities.
+class DownloadDriver {
+ public:
+  // The client to receive updates from content download library.
+  // The update events for all downloads will pass through, so it's the
+  // client's responsibility to filter the events it needs to handle.
+  class Client {
+   public:
+    // Called when the low level download library is ready. |success| is true
+    // when the low level download library is ready.
+    virtual void OnDriverReady(bool success) = 0;
+
+    // Called when any download is created.
+    virtual void OnDownloadCreated(const DriverEntry& download) = 0;
+
+    // Called when any download is failed. |reason| is propagated from low level
+    // download library.
+    virtual void OnDownloadFailed(const DriverEntry& download, int reason) = 0;
+
+    // Called when any download is successfully completed.
+    virtual void OnDownloadSucceeded(const DriverEntry& download,
+                                     const base::FilePath& path) = 0;
+
+    // Called when any download is updated.
+    virtual void OnDownloadUpdated(const DriverEntry& download) = 0;
+  };
+
+  // Initialize the driver to receive download updates.
+  virtual void Initialize(Client* client) = 0;
+
+  // Returns if the driver is ready. Returns false when the driver is not
+  // initialized by the client, or low level download library has been shut
+  // down.
+  virtual bool IsReady() const = 0;
+
+  // Starts a new download.
+  virtual void Start(const DownloadParams& params) = 0;
+
+  // Cancels an existing download, all data associated with this download should
+  // be removed.
+  virtual void Cancel(const std::string& guid) = 0;
+
+  // Pauses the download.
+  virtual void Pause(const std::string& guid) = 0;
+
+  // Resumes the download
+  virtual void Resume(const std::string& guid) = 0;
+
+  // Find a download record from low level download library.
+  virtual base::Optional<DriverEntry> Find(const std::string& guid) = 0;
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_DOWNLOAD_DRIVER_H_
diff --git a/components/download/internal/driver_entry.cc b/components/download/internal/driver_entry.cc
new file mode 100644
index 0000000..88ab03df2
--- /dev/null
+++ b/components/download/internal/driver_entry.cc
@@ -0,0 +1,21 @@
+// 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/driver_entry.h"
+
+#include "net/http/http_response_headers.h"
+
+namespace download {
+
+DriverEntry::DriverEntry()
+    : state(State::UNKNOWN),
+      paused(false),
+      bytes_downloaded(0u),
+      expected_total_size(0u) {}
+
+DriverEntry::DriverEntry(const DriverEntry& other) = default;
+
+DriverEntry::~DriverEntry() = default;
+
+}  // namespace download
diff --git a/components/download/internal/driver_entry.h b/components/download/internal/driver_entry.h
new file mode 100644
index 0000000..a21a431
--- /dev/null
+++ b/components/download/internal/driver_entry.h
@@ -0,0 +1,61 @@
+// 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_DRIVER_ENTRY_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+
+namespace net {
+class HttpResponseHeaders;
+}  // namespace net
+
+namespace content {
+class DownloadItem;
+}  // namespace content
+
+namespace download {
+
+// A snapshot of the states of a download. It's preferred to use the data on the
+// fly and query new ones from download driver, instead of caching the states.
+struct DriverEntry {
+  // States of the download. Mostly maps to
+  // content::DownloadItem::DownloadState.
+  enum class State {
+    IN_PROGRESS = 0,
+    COMPLETE = 1,
+    CANCELLED = 2,
+    INTERRUPTED = 3,
+    UNKNOWN = 4, /* Not created from a download item object. */
+  };
+
+  DriverEntry();
+  DriverEntry(const DriverEntry& other);
+  ~DriverEntry();
+
+  // The unique identifier of the download.
+  std::string guid;
+
+  // The current state of the download.
+  State state;
+
+  // If the download is paused.
+  bool paused;
+
+  // The number of bytes downloaded.
+  uint64_t bytes_downloaded;
+
+  // The expected total size of the download, set to 0 if the Content-Length
+  // http header is not presented.
+  uint64_t expected_total_size;
+
+  // The response headers for the most recent download request.
+  scoped_refptr<const net::HttpResponseHeaders> response_headers;
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_
diff --git a/components/download/internal/test/BUILD.gn b/components/download/internal/test/BUILD.gn
index cabd4ee..87032dc 100644
--- a/components/download/internal/test/BUILD.gn
+++ b/components/download/internal/test/BUILD.gn
@@ -12,6 +12,8 @@
     "entry_utils.h",
     "mock_model_client.cc",
     "mock_model_client.h",
+    "test_download_driver.cc",
+    "test_download_driver.h",
     "test_store.cc",
     "test_store.h",
   ]
@@ -19,6 +21,7 @@
   public_deps = [
     "//base",
     "//components/download/internal",
+    "//components/download/public",
     "//testing/gmock",
   ]
 }
diff --git a/components/download/internal/test/test_download_driver.cc b/components/download/internal/test/test_download_driver.cc
new file mode 100644
index 0000000..78de8d77
--- /dev/null
+++ b/components/download/internal/test/test_download_driver.cc
@@ -0,0 +1,84 @@
+// 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/test/test_download_driver.h"
+
+#include "base/files/file_path.h"
+#include "components/download/public/download_params.h"
+#include "net/http/http_response_headers.h"
+
+namespace download {
+
+TestDownloadDriver::TestDownloadDriver() : is_ready_(false), client_(nullptr) {}
+
+TestDownloadDriver::~TestDownloadDriver() = default;
+
+void TestDownloadDriver::MakeReady() {
+  is_ready_ = true;
+  DCHECK(client_);
+  if (client_)
+    client_->OnDriverReady(is_ready_);
+}
+
+void TestDownloadDriver::NotifyDownloadUpdate(const DriverEntry& entry) {
+  if (client_) {
+    entries_[entry.guid] = entry;
+    client_->OnDownloadUpdated(entry);
+  }
+}
+
+void TestDownloadDriver::NotifyDownloadFailed(const DriverEntry& entry,
+                                              int reason) {
+  if (client_) {
+    entries_[entry.guid] = entry;
+    client_->OnDownloadFailed(entry, reason);
+  }
+}
+
+void TestDownloadDriver::NotifyDownloadSucceeded(const DriverEntry& entry,
+                                                 const base::FilePath& path) {
+  if (client_) {
+    entries_[entry.guid] = entry;
+    client_->OnDownloadSucceeded(entry, path);
+  }
+}
+
+void TestDownloadDriver::Initialize(DownloadDriver::Client* client) {
+  DCHECK(!client_);
+  client_ = client;
+}
+
+bool TestDownloadDriver::IsReady() const {
+  return is_ready_;
+}
+
+void TestDownloadDriver::Start(const DownloadParams& params) {
+  DriverEntry entry;
+  entry.guid = params.guid;
+  entry.state = DriverEntry::State::IN_PROGRESS;
+  entry.paused = false;
+  entry.bytes_downloaded = 0;
+  entry.expected_total_size = 0;
+  entry.response_headers =
+      base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200");
+  entries_[params.guid] = entry;
+
+  if (client_)
+    client_->OnDownloadCreated(entry);
+}
+
+void TestDownloadDriver::Cancel(const std::string& guid) {}
+
+void TestDownloadDriver::Pause(const std::string& guid) {}
+
+void TestDownloadDriver::Resume(const std::string& guid) {}
+
+base::Optional<DriverEntry> TestDownloadDriver::Find(const std::string& guid) {
+  auto it = entries_.find(guid);
+  if (it == entries_.end())
+    return base::nullopt;
+  return it->second;
+}
+
+}  // namespace downloads
diff --git a/components/download/internal/test/test_download_driver.h b/components/download/internal/test/test_download_driver.h
new file mode 100644
index 0000000..0ee9f3d
--- /dev/null
+++ b/components/download/internal/test/test_download_driver.h
@@ -0,0 +1,53 @@
+// 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_TEST_TEST_DOWNLOAD_DRIVER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_TEST_DOWNLOAD_DRIVER_H_
+
+#include <map>
+#include <memory>
+
+#include "base/macros.h"
+#include "components/download/internal/download_driver.h"
+
+namespace download {
+
+// Download driver that simulates content layer download logic.
+class TestDownloadDriver : public DownloadDriver {
+ public:
+  TestDownloadDriver();
+  ~TestDownloadDriver();
+
+  // Marks download driver as ready, used to test logic that depends on
+  // data initialization.
+  void MakeReady();
+
+  // Simulates download events from content layer.
+  void NotifyDownloadUpdate(const DriverEntry& entry);
+  void NotifyDownloadFailed(const DriverEntry& entry, int reason);
+  void NotifyDownloadSucceeded(const DriverEntry& entry,
+                               const base::FilePath& path);
+
+  // DownloadDriver implementation.
+  void Initialize(DownloadDriver::Client* client) override;
+  bool IsReady() const override;
+  void Start(const DownloadParams& params) override;
+  void Cancel(const std::string& guid) override;
+  void Pause(const std::string& guid) override;
+  void Resume(const std::string& guid) override;
+  base::Optional<DriverEntry> Find(const std::string& guid) override;
+
+ private:
+  bool is_ready_;
+  DownloadDriver::Client* client_;
+
+  // Map of guid --> DriverEntry.
+  std::map<std::string, DriverEntry> entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestDownloadDriver);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_CONTENT_TEST_TEST_DOWNLOAD_DRIVER_H_
diff --git a/content/browser/download/download_create_info.h b/content/browser/download/download_create_info.h
index 1f6c773..3ebcaf2 100644
--- a/content/browser/download/download_create_info.h
+++ b/content/browser/download/download_create_info.h
@@ -44,9 +44,12 @@
   // redirection by the server for |url_chain|.
   const GURL& url() const;
 
-  // The ID of the download.
+  // The ID of the download. (Deprecated)
   uint32_t download_id;
 
+  // The unique identifier for the download.
+  std::string guid;
+
   // The chain of redirects that leading up to and including the final URL.
   std::vector<GURL> url_chain;
 
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index 1132560..dccaf11c 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -203,7 +203,8 @@
                                    uint32_t download_id,
                                    const DownloadCreateInfo& info,
                                    const net::NetLogWithSource& net_log)
-    : guid_(base::ToUpperASCII(base::GenerateGUID())),
+    : guid_(info.guid.empty() ? base::ToUpperASCII(base::GenerateGUID())
+                              : info.guid),
       download_id_(download_id),
       target_disposition_((info.save_info->prompt_for_save_location)
                               ? TARGET_DISPOSITION_PROMPT
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 44ac7f5..ecd6d88 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -181,6 +181,7 @@
     : item_factory_(new DownloadItemFactoryImpl()),
       file_factory_(new DownloadFileFactory()),
       shutdown_needed_(true),
+      initialized_(false),
       browser_context_(browser_context),
       delegate_(nullptr),
       net_log_(net_log),
@@ -674,6 +675,17 @@
   return item;
 }
 
+void DownloadManagerImpl::PostInitialization() {
+  DCHECK(!initialized_);
+  initialized_ = true;
+  for (auto& observer : observers_)
+    observer.OnManagerInitialized();
+}
+
+bool DownloadManagerImpl::IsManagerInitialized() const {
+  return initialized_;
+}
+
 int DownloadManagerImpl::InProgressCount() const {
   int count = 0;
   for (const auto& it : downloads_) {
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 0128c28..e9b13f6 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -108,6 +108,8 @@
       base::Time last_access_time,
       bool transient,
       const std::vector<DownloadItem::ReceivedSlice>& received_slices) override;
+  void PostInitialization() override;
+  bool IsManagerInitialized() const override;
   int InProgressCount() const override;
   int NonMaliciousInProgressCount() const override;
   BrowserContext* GetBrowserContext() const override;
@@ -227,6 +229,9 @@
   // True if the download manager has been initialized and requires a shutdown.
   bool shutdown_needed_;
 
+  // True if the download manager has been initialized and loaded all the data.
+  bool initialized_;
+
   // Observers that want to be notified of changes to the set of downloads.
   base::ObserverList<Observer> observers_;
 
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc
index 7c55b93..6dd961b0 100644
--- a/content/browser/download/download_request_core.cc
+++ b/content/browser/download/download_request_core.cc
@@ -65,6 +65,7 @@
     return std::move(save_info_);
   }
   uint32_t download_id() const { return download_id_; }
+  std::string guid() const { return guid_; }
   bool is_transient() const { return transient_; }
   const DownloadUrlParameters::OnStartedCallback& callback() const {
     return on_started_callback_;
@@ -75,6 +76,7 @@
 
   std::unique_ptr<DownloadSaveInfo> save_info_;
   uint32_t download_id_ = DownloadItem::kInvalidId;
+  std::string guid_;
   bool transient_ = false;
   DownloadUrlParameters::OnStartedCallback on_started_callback_;
 };
@@ -90,6 +92,7 @@
   request_data->save_info_.reset(
       new DownloadSaveInfo(parameters->GetSaveInfo()));
   request_data->download_id_ = download_id;
+  request_data->guid_ = parameters->guid();
   request_data->transient_ = parameters->is_transient();
   request_data->on_started_callback_ = parameters->callback();
   request->SetUserData(&kKey, std::move(request_data));
@@ -221,6 +224,7 @@
   if (request_data) {
     save_info_ = request_data->TakeSaveInfo();
     download_id_ = request_data->download_id();
+    guid_ = request_data->guid();
     transient_ = request_data->is_transient();
     on_started_callback_ = request_data->callback();
     DownloadRequestData::Detach(request_);
@@ -251,6 +255,7 @@
   create_info->referrer_url = GURL(request()->referrer());
   create_info->result = result;
   create_info->download_id = download_id_;
+  create_info->guid = guid_;
   create_info->transient = transient_;
   create_info->response_headers = request()->response_headers();
   create_info->offset = create_info->save_info->offset;
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h
index dae93986..fc2ccd2 100644
--- a/content/browser/download/download_request_core.h
+++ b/content/browser/download/download_request_core.h
@@ -135,6 +135,7 @@
   // populate the DownloadCreateInfo when the time comes.
   std::unique_ptr<DownloadSaveInfo> save_info_;
   uint32_t download_id_;
+  std::string guid_;
   bool transient_;
   DownloadUrlParameters::OnStartedCallback on_started_callback_;
 
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 9e38db2..f6080fe5 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -84,6 +84,9 @@
     virtual void OnSavePackageSuccessfullyFinished(
         DownloadManager* manager, DownloadItem* item) {}
 
+    // Called when the download manager has finished loading the data.
+    virtual void OnManagerInitialized() {}
+
     // Called when the DownloadManager is being destroyed to prevent Observers
     // from calling back to a stale pointer.
     virtual void ManagerGoingDown(DownloadManager* manager) {}
@@ -155,6 +158,12 @@
       bool transient,
       const std::vector<DownloadItem::ReceivedSlice>& received_slices) = 0;
 
+  // Called when download manager has loaded all the data.
+  virtual void PostInitialization() = 0;
+
+  // Returns if the manager has been initialized and loaded all the data.
+  virtual bool IsManagerInitialized() const = 0;
+
   // The number of in progress (including paused) downloads.
   // Performance note: this loops over all items. If profiling finds that this
   // is too slow, use an AllDownloadItemNotifier to count in-progress items.
diff --git a/content/public/browser/download_url_parameters.h b/content/public/browser/download_url_parameters.h
index b1a8bce..a88be116 100644
--- a/content/public/browser/download_url_parameters.h
+++ b/content/public/browser/download_url_parameters.h
@@ -209,6 +209,11 @@
   // download is short-lived and is not shown in the UI.
   void set_transient(bool transient) { transient_ = transient; }
 
+  // Sets the optional guid for the download, the guid serves as the unique
+  // identitfier for the download item. If no guid is provided, download
+  // system will automatically generate one.
+  void set_guid(const std::string& guid) { guid_ = guid; }
+
   // For downloads of blob URLs, the caller can store a BlobDataHandle in the
   // DownloadUrlParameters object so that the blob will remain valid until
   // the download starts. The BlobDataHandle will be attached to the associated
@@ -262,6 +267,7 @@
   const GURL& url() const { return url_; }
   bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; }
   bool is_transient() const { return transient_; }
+  std::string guid() const { return guid_; }
 
   // STATE_CHANGING: Return the BlobDataHandle.
   std::unique_ptr<storage::BlobDataHandle> GetBlobDataHandle() {
@@ -294,6 +300,7 @@
   GURL url_;
   bool do_not_prompt_for_login_;
   bool transient_;
+  std::string guid_;
   std::unique_ptr<storage::BlobDataHandle> blob_data_handle_;
 
   DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters);
diff --git a/content/public/test/fake_download_item.cc b/content/public/test/fake_download_item.cc
index ccc2188..4ae0a1b 100644
--- a/content/public/test/fake_download_item.cc
+++ b/content/public/test/fake_download_item.cc
@@ -157,6 +157,10 @@
   received_bytes_ = received_bytes;
 }
 
+void FakeDownloadItem::SetTotalBytes(int64_t total_bytes) {
+  total_bytes_ = total_bytes;
+}
+
 int64_t FakeDownloadItem::GetReceivedBytes() const {
   return received_bytes_;
 }
@@ -206,7 +210,6 @@
 }
 
 bool FakeDownloadItem::IsPaused() const {
-  NOTREACHED();
   return false;
 }
 
@@ -351,8 +354,7 @@
 }
 
 int64_t FakeDownloadItem::GetTotalBytes() const {
-  NOTREACHED();
-  return 1;
+  return total_bytes_;
 }
 
 const std::vector<DownloadItem::ReceivedSlice>&
diff --git a/content/public/test/fake_download_item.h b/content/public/test/fake_download_item.h
index f2e23057..504477c 100644
--- a/content/public/test/fake_download_item.h
+++ b/content/public/test/fake_download_item.h
@@ -80,6 +80,9 @@
   void SetReceivedBytes(int64_t received_bytes);
   int64_t GetReceivedBytes() const override;
 
+  void SetTotalBytes(int64_t total_bytes);
+  int64_t GetTotalBytes() const override;
+
   void SetLastAccessTime(base::Time time) override;
   base::Time GetLastAccessTime() const override;
 
@@ -122,7 +125,6 @@
   int64_t CurrentSpeed() const override;
   int PercentComplete() const override;
   bool AllDataSaved() const override;
-  int64_t GetTotalBytes() const override;
   const std::vector<DownloadItem::ReceivedSlice>& GetReceivedSlices()
       const override;
   bool CanShowInFolder() override;
@@ -160,6 +162,7 @@
   DownloadInterruptReason last_reason_ =
       DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_NONE;
   int64_t received_bytes_ = 0;
+  int64_t total_bytes_ = 0;
 
   // The members below are to be returned by methods, which return by reference.
   std::string dummy_string;
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h
index 41ca921..f462fa1 100644
--- a/content/public/test/mock_download_manager.h
+++ b/content/public/test/mock_download_manager.h
@@ -148,7 +148,8 @@
 
   MOCK_METHOD1(MockCreateDownloadItem,
                DownloadItem*(CreateDownloadItemAdapter adapter));
-
+  MOCK_METHOD0(PostInitialization, void());
+  MOCK_CONST_METHOD0(IsManagerInitialized, bool());
   MOCK_CONST_METHOD0(InProgressCount, int());
   MOCK_CONST_METHOD0(NonMaliciousInProgressCount, int());
   MOCK_CONST_METHOD0(GetBrowserContext, BrowserContext*());