This split will facilitate testing DownloadQuery and other users of DownloadItems.

Review URL: http://codereview.chromium.org/8503018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110984 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/download/download_id_unittest.cc b/content/browser/download/download_id_unittest.cc
index 17d944b..dd23003 100644
--- a/content/browser/download/download_id_unittest.cc
+++ b/content/browser/download/download_id_unittest.cc
@@ -9,6 +9,7 @@
 #include <set>
 #include <vector>
 
+#include "base/memory/scoped_ptr.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/download/mock_download_manager.h"
 #include "content/browser/download/mock_download_manager_delegate.h"
diff --git a/content/browser/download/download_item.cc b/content/browser/download/download_item.cc
index 3318a07..16261cc 100644
--- a/content/browser/download/download_item.cc
+++ b/content/browser/download/download_item.cc
@@ -4,121 +4,6 @@
 
 #include "content/browser/download/download_item.h"
 
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/format_macros.h"
-#include "base/i18n/case_conversion.h"
-#include "base/i18n/string_search.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/stringprintf.h"
-#include "base/utf_string_conversions.h"
-#include "content/browser/download/download_create_info.h"
-#include "content/browser/download/download_file.h"
-#include "content/browser/download/download_file_manager.h"
-#include "content/browser/download/download_id.h"
-#include "content/browser/download/download_manager.h"
-#include "content/browser/download/download_persistent_store_info.h"
-#include "content/browser/download/download_request_handle.h"
-#include "content/browser/download/download_stats.h"
-#include "content/browser/download/interrupt_reasons.h"
-#include "content/browser/tab_contents/tab_contents.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/download_manager_delegate.h"
-#include "net/base/net_util.h"
-
-using content::BrowserThread;
-
-// A DownloadItem normally goes through the following states:
-//      * Created (when download starts)
-//      * Made visible to consumers (e.g. Javascript) after the
-//        destination file has been determined.
-//      * Entered into the history database.
-//      * Made visible in the download shelf.
-//      * All data is saved.  Note that the actual data download occurs
-//        in parallel with the above steps, but until those steps are
-//        complete, completion of the data download will be ignored.
-//      * Download file is renamed to its final name, and possibly
-//        auto-opened.
-// TODO(rdsmith): This progress should be reflected in
-// DownloadItem::DownloadState and a state transition table/state diagram.
-//
-// TODO(rdsmith): This description should be updated to reflect the cancel
-// pathways.
-
-namespace {
-
-static void DeleteDownloadedFile(const FilePath& path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
-  // Make sure we only delete files.
-  if (!file_util::DirectoryExists(path))
-    file_util::Delete(path, false);
-}
-
-const char* DebugSafetyStateString(DownloadItem::SafetyState state) {
-  switch (state) {
-    case DownloadItem::SAFE:
-      return "SAFE";
-    case DownloadItem::DANGEROUS:
-      return "DANGEROUS";
-    case DownloadItem::DANGEROUS_BUT_VALIDATED:
-      return "DANGEROUS_BUT_VALIDATED";
-    default:
-      NOTREACHED() << "Unknown safety state " << state;
-      return "unknown";
-  };
-}
-
-const char* DebugDownloadStateString(DownloadItem::DownloadState state) {
-  switch (state) {
-    case DownloadItem::IN_PROGRESS:
-      return "IN_PROGRESS";
-    case DownloadItem::COMPLETE:
-      return "COMPLETE";
-    case DownloadItem::CANCELLED:
-      return "CANCELLED";
-    case DownloadItem::REMOVING:
-      return "REMOVING";
-    case DownloadItem::INTERRUPTED:
-      return "INTERRUPTED";
-    default:
-      NOTREACHED() << "Unknown download state " << state;
-      return "unknown";
-  };
-}
-
-// Classes to null out request handle calls (for SavePage DownloadItems, which
-// may have, e.g., Cancel() called on them without it doing anything)
-// and to DCHECK on them (for history DownloadItems, which should never have
-// any operation that implies an off-thread component, since they don't
-// have any).
-class NullDownloadRequestHandle : public DownloadRequestHandleInterface {
- public:
-  NullDownloadRequestHandle() {}
-
-  // DownloadRequestHandleInterface calls
-  virtual TabContents* GetTabContents() const OVERRIDE {
-    return NULL;
-  }
-  virtual DownloadManager* GetDownloadManager() const OVERRIDE {
-    return NULL;
-  }
-  virtual void PauseRequest() const OVERRIDE {}
-  virtual void ResumeRequest() const OVERRIDE {}
-  virtual void CancelRequest() const OVERRIDE {}
-  virtual std::string DebugString() const OVERRIDE {
-    return "Null DownloadRequestHandle";
-  }
-};
-
-
-}  // namespace
-
 // Our download table ID starts at 1, so we use 0 to represent a download that
 // has started, but has not yet had its data persisted in the table. We use fake
 // database handles in incognito mode starting at -1 and progressively getting
@@ -128,696 +13,5 @@
 
 const char DownloadItem::kEmptyFileHash[] = "";
 
-// Constructor for reading from the history service.
-DownloadItem::DownloadItem(DownloadManager* download_manager,
-                           const DownloadPersistentStoreInfo& info)
-    : download_id_(download_manager->GetNextId()),
-      full_path_(info.path),
-      url_chain_(1, info.url),
-      referrer_url_(info.referrer_url),
-      total_bytes_(info.total_bytes),
-      received_bytes_(info.received_bytes),
-      start_tick_(base::TimeTicks()),
-      state_(static_cast<DownloadState>(info.state)),
-      start_time_(info.start_time),
-      end_time_(info.end_time),
-      db_handle_(info.db_handle),
-      download_manager_(download_manager),
-      is_paused_(false),
-      open_when_complete_(false),
-      file_externally_removed_(false),
-      safety_state_(SAFE),
-      auto_opened_(false),
-      is_otr_(false),
-      is_temporary_(false),
-      all_data_saved_(false),
-      opened_(info.opened),
-      open_enabled_(true),
-      delegate_delayed_complete_(false) {
-  if (IsInProgress())
-    state_ = CANCELLED;
-  if (IsComplete())
-    all_data_saved_ = true;
-  Init(false /* not actively downloading */);
-}
-
-// Constructing for a regular download:
-DownloadItem::DownloadItem(DownloadManager* download_manager,
-                           const DownloadCreateInfo& info,
-                           DownloadRequestHandleInterface* request_handle,
-                           bool is_otr)
-    : state_info_(info.original_name, info.save_info.file_path,
-                  info.has_user_gesture, info.transition_type,
-                  info.prompt_user_for_save_location, info.path_uniquifier,
-                  DownloadStateInfo::NOT_DANGEROUS),
-      request_handle_(request_handle),
-      download_id_(info.download_id),
-      full_path_(info.path),
-      url_chain_(info.url_chain),
-      referrer_url_(info.referrer_url),
-      suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
-      content_disposition_(info.content_disposition),
-      mime_type_(info.mime_type),
-      original_mime_type_(info.original_mime_type),
-      referrer_charset_(info.referrer_charset),
-      total_bytes_(info.total_bytes),
-      received_bytes_(0),
-      last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
-      start_tick_(base::TimeTicks::Now()),
-      state_(IN_PROGRESS),
-      start_time_(info.start_time),
-      db_handle_(DownloadItem::kUninitializedHandle),
-      download_manager_(download_manager),
-      is_paused_(false),
-      open_when_complete_(false),
-      file_externally_removed_(false),
-      safety_state_(SAFE),
-      auto_opened_(false),
-      is_otr_(is_otr),
-      is_temporary_(!info.save_info.file_path.empty()),
-      all_data_saved_(false),
-      opened_(false),
-      open_enabled_(true),
-      delegate_delayed_complete_(false) {
-  Init(true /* actively downloading */);
-}
-
-// Constructing for the "Save Page As..." feature:
-DownloadItem::DownloadItem(DownloadManager* download_manager,
-                           const FilePath& path,
-                           const GURL& url,
-                           bool is_otr,
-                           DownloadId download_id)
-    : request_handle_(new NullDownloadRequestHandle()),
-      download_id_(download_id),
-      full_path_(path),
-      url_chain_(1, url),
-      referrer_url_(GURL()),
-      total_bytes_(0),
-      received_bytes_(0),
-      last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
-      start_tick_(base::TimeTicks::Now()),
-      state_(IN_PROGRESS),
-      start_time_(base::Time::Now()),
-      db_handle_(DownloadItem::kUninitializedHandle),
-      download_manager_(download_manager),
-      is_paused_(false),
-      open_when_complete_(false),
-      file_externally_removed_(false),
-      safety_state_(SAFE),
-      auto_opened_(false),
-      is_otr_(is_otr),
-      is_temporary_(false),
-      all_data_saved_(false),
-      opened_(false),
-      open_enabled_(true),
-      delegate_delayed_complete_(false) {
-  Init(true /* actively downloading */);
-}
-
 DownloadItem::~DownloadItem() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  TransitionTo(REMOVING);
-  download_manager_->AssertQueueStateConsistent(this);
-}
-
-void DownloadItem::AddObserver(Observer* observer) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  observers_.AddObserver(observer);
-}
-
-void DownloadItem::RemoveObserver(Observer* observer) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  observers_.RemoveObserver(observer);
-}
-
-void DownloadItem::UpdateObservers() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
-}
-
-bool DownloadItem::CanShowInFolder() {
-  return !IsCancelled() && !file_externally_removed_;
-}
-
-bool DownloadItem::CanOpenDownload() {
-  return !file_externally_removed_;
-}
-
-bool DownloadItem::ShouldOpenFileBasedOnExtension() {
-  return download_manager_->delegate()->ShouldOpenFileBasedOnExtension(
-      GetUserVerifiedFilePath());
-}
-
-void DownloadItem::OpenDownload() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (IsPartialDownload()) {
-    open_when_complete_ = !open_when_complete_;
-    return;
-  }
-
-  if (!IsComplete() || file_externally_removed_)
-    return;
-
-  // Ideally, we want to detect errors in opening and report them, but we
-  // don't generally have the proper interface for that to the external
-  // program that opens the file.  So instead we spawn a check to update
-  // the UI if the file has been deleted in parallel with the open.
-  download_manager_->CheckForFileRemoval(this);
-  download_stats::RecordOpen(end_time(), !opened());
-  opened_ = true;
-  FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
-  download_manager_->MarkDownloadOpened(this);
-
-  // For testing: If download opening is disabled on this item,
-  // make the rest of the routine a no-op.
-  if (!open_enabled_)
-    return;
-
-  content::GetContentClient()->browser()->OpenItem(full_path());
-}
-
-void DownloadItem::ShowDownloadInShell() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  content::GetContentClient()->browser()->ShowItemInFolder(full_path());
-}
-
-void DownloadItem::DangerousDownloadValidated() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK_EQ(DANGEROUS, safety_state());
-
-  UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
-                            GetDangerType(),
-                            DownloadStateInfo::DANGEROUS_TYPE_MAX);
-
-  safety_state_ = DANGEROUS_BUT_VALIDATED;
-  UpdateObservers();
-
-  download_manager_->MaybeCompleteDownload(this);
-}
-
-void DownloadItem::UpdateSize(int64 bytes_so_far) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  received_bytes_ = bytes_so_far;
-
-  // If we've received more data than we were expecting (bad server info?),
-  // revert to 'unknown size mode'.
-  if (received_bytes_ > total_bytes_)
-    total_bytes_ = 0;
-}
-
-// Updates from the download thread may have been posted while this download
-// was being cancelled in the UI thread, so we'll accept them unless we're
-// complete.
-void DownloadItem::Update(int64 bytes_so_far) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (!IsInProgress()) {
-    NOTREACHED();
-    return;
-  }
-  UpdateSize(bytes_so_far);
-  UpdateObservers();
-}
-
-// Triggered by a user action.
-void DownloadItem::Cancel(bool user_cancel) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  last_reason_ = user_cancel ?
-      DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
-      DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
-
-  VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
-  if (!IsPartialDownload()) {
-    // Small downloads might be complete before this method has
-    // a chance to run.
-    return;
-  }
-
-  download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
-
-  TransitionTo(CANCELLED);
-  if (user_cancel)
-    download_manager_->DownloadCancelledInternal(this);
-}
-
-void DownloadItem::MarkAsComplete() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  DCHECK(all_data_saved_);
-  end_time_ = base::Time::Now();
-  TransitionTo(COMPLETE);
-}
-
-void DownloadItem::DelayedDownloadOpened() {
-  auto_opened_ = true;
-  Completed();
-}
-
-void DownloadItem::OnAllDataSaved(int64 size, const std::string& final_hash) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  DCHECK(!all_data_saved_);
-  all_data_saved_ = true;
-  UpdateSize(size);
-  hash_ = final_hash;
-}
-
-void DownloadItem::OnDownloadedFileRemoved() {
-  file_externally_removed_ = true;
-  UpdateObservers();
-}
-
-void DownloadItem::Completed() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
-
-  DCHECK(all_data_saved_);
-  end_time_ = base::Time::Now();
-  TransitionTo(COMPLETE);
-  download_manager_->DownloadCompleted(id());
-  download_stats::RecordDownloadCompleted(start_tick_, received_bytes_);
-
-  if (auto_opened_) {
-    // If it was already handled by the delegate, do nothing.
-  } else if (open_when_complete() ||
-             ShouldOpenFileBasedOnExtension() ||
-             is_temporary()) {
-    // If the download is temporary, like in drag-and-drop, do not open it but
-    // we still need to set it auto-opened so that it can be removed from the
-    // download shelf.
-    if (!is_temporary())
-      OpenDownload();
-
-    auto_opened_ = true;
-    UpdateObservers();
-  }
-}
-
-void DownloadItem::TransitionTo(DownloadState new_state) {
-  if (state_ == new_state)
-    return;
-
-  state_ = new_state;
-  UpdateObservers();
-}
-
-void DownloadItem::UpdateSafetyState() {
-  SafetyState updated_value = state_info_.IsDangerous() ?
-      DownloadItem::DANGEROUS : DownloadItem::SAFE;
-  if (updated_value != safety_state_) {
-    safety_state_ = updated_value;
-    UpdateObservers();
-  }
-}
-
-void DownloadItem::UpdateTarget() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (state_info_.target_name.value().empty())
-    state_info_.target_name = full_path_.BaseName();
-}
-
-void DownloadItem::Interrupted(int64 size, InterruptReason reason) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (!IsInProgress())
-    return;
-
-  last_reason_ = reason;
-  UpdateSize(size);
-  download_stats::RecordDownloadInterrupted(reason,
-                                            received_bytes_,
-                                            total_bytes_);
-  TransitionTo(INTERRUPTED);
-}
-
-void DownloadItem::Delete(DeleteReason reason) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  switch (reason) {
-    case DELETE_DUE_TO_USER_DISCARD:
-      UMA_HISTOGRAM_ENUMERATION("Download.UserDiscard", GetDangerType(),
-                                DownloadStateInfo::DANGEROUS_TYPE_MAX);
-      break;
-    case DELETE_DUE_TO_BROWSER_SHUTDOWN:
-      UMA_HISTOGRAM_ENUMERATION("Download.Discard", GetDangerType(),
-                                DownloadStateInfo::DANGEROUS_TYPE_MAX);
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&DeleteDownloadedFile, full_path_));
-  Remove();
-  // We have now been deleted.
-}
-
-void DownloadItem::Remove() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  download_manager_->AssertQueueStateConsistent(this);
-  Cancel(true);
-  download_manager_->AssertQueueStateConsistent(this);
-
-  TransitionTo(REMOVING);
-  download_manager_->RemoveDownload(db_handle_);
-  // We have now been deleted.
-}
-
-bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const {
-  if (total_bytes_ <= 0)
-    return false;  // We never received the content_length for this download.
-
-  int64 speed = CurrentSpeed();
-  if (speed == 0)
-    return false;
-
-  *remaining = base::TimeDelta::FromSeconds(
-      (total_bytes_ - received_bytes_) / speed);
-  return true;
-}
-
-int64 DownloadItem::CurrentSpeed() const {
-  if (is_paused_)
-    return 0;
-  base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
-  int64 diff_ms = diff.InMilliseconds();
-  return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms;
-}
-
-int DownloadItem::PercentComplete() const {
-  // If the delegate is delaying completion of the download, then we have no
-  // idea how long it will take.
-  if (delegate_delayed_complete_ || total_bytes_ <= 0)
-    return -1;
-
-  return static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
-}
-
-void DownloadItem::OnPathDetermined(const FilePath& path) {
-  full_path_ = path;
-  UpdateTarget();
-}
-
-void DownloadItem::Rename(const FilePath& full_path) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  VLOG(20) << __FUNCTION__ << "()"
-           << " full_path = \"" << full_path.value() << "\""
-           << " " << DebugString(true);
-  DCHECK(!full_path.empty());
-  full_path_ = full_path;
-}
-
-void DownloadItem::TogglePause() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  DCHECK(IsInProgress());
-  if (is_paused_)
-    request_handle_->ResumeRequest();
-  else
-    request_handle_->PauseRequest();
-  is_paused_ = !is_paused_;
-  UpdateObservers();
-}
-
-void DownloadItem::OnDownloadCompleting(DownloadFileManager* file_manager) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  VLOG(20) << __FUNCTION__ << "()"
-           << " needs rename = " << NeedsRename()
-           << " " << DebugString(true);
-  DCHECK_NE(DANGEROUS, safety_state());
-  DCHECK(file_manager);
-
-  if (NeedsRename()) {
-    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-        base::Bind(&DownloadFileManager::RenameCompletingDownloadFile,
-                   file_manager, global_id(),
-                   GetTargetFilePath(), safety_state() == SAFE));
-    return;
-  }
-
-  Completed();
-
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&DownloadFileManager::CompleteDownload,
-                                     file_manager, global_id()));
-}
-
-void DownloadItem::OnDownloadRenamedToFinalName(const FilePath& full_path) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  VLOG(20) << __FUNCTION__ << "()"
-           << " full_path = \"" << full_path.value() << "\""
-           << " needed rename = " << NeedsRename()
-           << " " << DebugString(false);
-  DCHECK(NeedsRename());
-
-  Rename(full_path);
-
-  if (download_manager_->delegate()->ShouldOpenDownload(this)) {
-    Completed();
-  } else {
-    delegate_delayed_complete_ = true;
-  }
-}
-
-bool DownloadItem::MatchesQuery(const string16& query) const {
-  if (query.empty())
-    return true;
-
-  DCHECK_EQ(query, base::i18n::ToLower(query));
-
-  string16 url_raw(UTF8ToUTF16(GetURL().spec()));
-  if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_raw))
-    return true;
-
-  // TODO(phajdan.jr): write a test case for the following code.
-  // A good test case would be:
-  //   "/\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd",
-  //   L"/\x4f60\x597d\x4f60\x597d",
-  //   "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD"
-  std::string languages;
-  TabContents* tab = GetTabContents();
-  if (tab) {
-    languages = content::GetContentClient()->browser()->GetAcceptLangs(
-        tab->browser_context());
-  }
-  string16 url_formatted(net::FormatUrl(GetURL(), languages));
-  if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_formatted))
-    return true;
-
-  string16 path(full_path().LossyDisplayName());
-  return base::i18n::StringSearchIgnoringCaseAndAccents(query, path);
-}
-
-void DownloadItem::SetFileCheckResults(const DownloadStateInfo& state) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
-  state_info_ = state;
-  VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
-
-  UpdateSafetyState();
-}
-
-DownloadStateInfo::DangerType DownloadItem::GetDangerType() const {
-  return state_info_.danger;
-}
-
-bool DownloadItem::IsDangerous() const {
-  return state_info_.IsDangerous();
-}
-
-void DownloadItem::MarkFileDangerous() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  state_info_.danger = DownloadStateInfo::DANGEROUS_FILE;
-  UpdateSafetyState();
-}
-
-void DownloadItem::MarkUrlDangerous() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  state_info_.danger = DownloadStateInfo::DANGEROUS_URL;
-  UpdateSafetyState();
-}
-
-void DownloadItem::MarkContentDangerous() {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  state_info_.danger = DownloadStateInfo::DANGEROUS_CONTENT;
-  UpdateSafetyState();
-}
-
-DownloadPersistentStoreInfo DownloadItem::GetPersistentStoreInfo() const {
-  return DownloadPersistentStoreInfo(full_path(),
-                                     GetURL(),
-                                     referrer_url(),
-                                     start_time(),
-                                     end_time(),
-                                     received_bytes(),
-                                     total_bytes(),
-                                     state(),
-                                     db_handle(),
-                                     opened());
-}
-
-TabContents* DownloadItem::GetTabContents() const {
-  // TODO(rdsmith): Remove null check after removing GetTabContents() from
-  // paths that might be used by DownloadItems created from history import.
-  // Currently such items have null request_handle_s, where other items
-  // (regular and SavePackage downloads) have actual objects off the pointer.
-  if (request_handle_.get())
-    return request_handle_->GetTabContents();
-  return NULL;
-}
-
-FilePath DownloadItem::GetTargetFilePath() const {
-  return full_path_.DirName().Append(state_info_.target_name);
-}
-
-FilePath DownloadItem::GetFileNameToReportUser() const {
-  if (state_info_.path_uniquifier > 0) {
-    FilePath name(state_info_.target_name);
-    DownloadFile::AppendNumberToPath(&name, state_info_.path_uniquifier);
-    return name;
-  }
-  return state_info_.target_name;
-}
-
-FilePath DownloadItem::GetUserVerifiedFilePath() const {
-  return (safety_state_ == DownloadItem::SAFE) ?
-      GetTargetFilePath() : full_path_;
-}
-
-void DownloadItem::OffThreadCancel(DownloadFileManager* file_manager) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  request_handle_->CancelRequest();
-
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&DownloadFileManager::CancelDownload,
-                                     file_manager, global_id()));
-}
-
-void DownloadItem::Init(bool active) {
-  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  UpdateTarget();
-  if (active) {
-    download_stats::RecordDownloadCount(download_stats::START_COUNT);
-  }
-  VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
-}
-
-// TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
-// |IsPartialDownload()|, when resuming interrupted downloads is implemented.
-bool DownloadItem::IsPartialDownload() const {
-  return (state_ == IN_PROGRESS);
-}
-
-bool DownloadItem::IsInProgress() const {
-  return (state_ == IN_PROGRESS);
-}
-
-bool DownloadItem::IsCancelled() const {
-  return (state_ == CANCELLED) ||
-         (state_ == INTERRUPTED);
-}
-
-bool DownloadItem::IsInterrupted() const {
-  return (state_ == INTERRUPTED);
-}
-
-bool DownloadItem::IsComplete() const {
-  return (state_ == COMPLETE);
-}
-
-const GURL& DownloadItem::GetURL() const {
-  return url_chain_.empty() ?
-             GURL::EmptyGURL() : url_chain_.back();
-}
-
-std::string DownloadItem::DebugString(bool verbose) const {
-  std::string description =
-      base::StringPrintf("{ id = %d"
-                         " state = %s",
-                         download_id_.local(),
-                         DebugDownloadStateString(state()));
-
-  // Construct a string of the URL chain.
-  std::string url_list("<none>");
-  if (!url_chain_.empty()) {
-    std::vector<GURL>::const_iterator iter = url_chain_.begin();
-    std::vector<GURL>::const_iterator last = url_chain_.end();
-    url_list = (*iter).spec();
-    ++iter;
-    for ( ; verbose && (iter != last); ++iter) {
-      url_list += " ->\n\t";
-      const GURL& next_url = *iter;
-      url_list += next_url.spec();
-    }
-  }
-
-  if (verbose) {
-    description += base::StringPrintf(
-        " db_handle = %" PRId64
-        " total_bytes = %" PRId64
-        " received_bytes = %" PRId64
-        " is_paused = %c"
-        " is_otr = %c"
-        " safety_state = %s"
-        " url_chain = \n\t\"%s\"\n\t"
-        " target_name = \"%" PRFilePath "\""
-        " full_path = \"%" PRFilePath "\"",
-        db_handle(),
-        total_bytes(),
-        received_bytes(),
-        is_paused() ? 'T' : 'F',
-        is_otr() ? 'T' : 'F',
-        DebugSafetyStateString(safety_state()),
-        url_list.c_str(),
-        state_info_.target_name.value().c_str(),
-        full_path().value().c_str());
-  } else {
-    description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
-  }
-
-  description += " }";
-
-  return description;
 }
diff --git a/content/browser/download/download_item.h b/content/browser/download/download_item.h
index 0e53e8d..3592d52 100644
--- a/content/browser/download/download_item.h
+++ b/content/browser/download/download_item.h
@@ -20,26 +20,22 @@
 
 #include <string>
 
-#include "base/basictypes.h"
-#include "base/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "base/time.h"
-#include "content/browser/download/download_id.h"
-#include "content/browser/download/download_request_handle.h"
+#include "base/string16.h"
 #include "content/browser/download/download_state_info.h"
 #include "content/browser/download/interrupt_reasons.h"
-#include "content/common/content_export.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/net_errors.h"
 
 class DownloadFileManager;
 class DownloadId;
 class DownloadManager;
+class FilePath;
+class GURL;
 class TabContents;
-
 struct DownloadCreateInfo;
 struct DownloadPersistentStoreInfo;
+namespace base {
+class Time;
+class TimeDelta;
+}
 
 // One DownloadItem per download. This is the model class that stores all the
 // state for a download. Multiple views, such as a tab's download shelf and the
@@ -100,54 +96,36 @@
     virtual ~Observer() {}
   };
 
-  // Constructing from persistent store:
-  DownloadItem(DownloadManager* download_manager,
-               const DownloadPersistentStoreInfo& info);
-
-  // Constructing for a regular download.
-  // Takes ownership of the object pointed to by |request_handle|.
-  DownloadItem(DownloadManager* download_manager,
-               const DownloadCreateInfo& info,
-               DownloadRequestHandleInterface* request_handle,
-               bool is_otr);
-
-  // Constructing for the "Save Page As..." feature:
-  DownloadItem(DownloadManager* download_manager,
-               const FilePath& path,
-               const GURL& url,
-               bool is_otr,
-               DownloadId download_id);
-
   virtual ~DownloadItem();
 
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
+  virtual void AddObserver(DownloadItem::Observer* observer) = 0;
+  virtual void RemoveObserver(DownloadItem::Observer* observer) = 0;
 
   // Notifies our observers periodically.
-  void UpdateObservers();
+  virtual void UpdateObservers() = 0;
 
   // Returns true if it is OK to open a folder which this file is inside.
-  bool CanShowInFolder();
+  virtual bool CanShowInFolder() = 0;
 
   // Returns true if it is OK to register the type of this file so that
   // it opens automatically.
-  bool CanOpenDownload();
+  virtual bool CanOpenDownload() = 0;
 
   // Tests if a file type should be opened automatically.
-  bool ShouldOpenFileBasedOnExtension();
+  virtual bool ShouldOpenFileBasedOnExtension() = 0;
 
   // Open the file associated with this download (wait for the download to
   // complete if it is in progress).
-  void OpenDownload();
+  virtual void OpenDownload() = 0;
 
   // Show the download via the OS shell.
-  void ShowDownloadInShell();
+  virtual void ShowDownloadInShell() = 0;
 
   // Called when the user has validated the download of a dangerous file.
-  void DangerousDownloadValidated();
+  virtual void DangerousDownloadValidated() = 0;
 
   // Received a new chunk of data
-  void Update(int64 bytes_so_far);
+  virtual void Update(int64 bytes_so_far) = 0;
 
   // Cancel the download operation. We need to distinguish between cancels at
   // exit (DownloadManager destructor) from user interface initiated cancels
@@ -158,168 +136,157 @@
   // downloaded file's size on disk, and what the history system's last record
   // of it is. At worst, we'll end up re-downloading a small portion of the file
   // when resuming a download (assuming the server supports byte ranges).
-  void Cancel(bool user_cancel);
+  virtual void Cancel(bool user_cancel) = 0;
 
   // Called by external code (SavePackage) using the DownloadItem interface
   // to display progress when the DownloadItem should be considered complete.
-  void MarkAsComplete();
+  virtual void MarkAsComplete() = 0;
 
   // Called by the delegate after it delayed opening the download in
   // DownloadManagerDelegate::ShouldOpenDownload.
-  void DelayedDownloadOpened();
+  virtual void DelayedDownloadOpened() = 0;
 
-  // Called when all data has been saved.
-  void OnAllDataSaved(int64 size, const std::string& final_hash);
+  // Called when all data has been saved. Only has display effects.
+  virtual void OnAllDataSaved(int64 size, const std::string& final_hash) = 0;
 
   // Called when the downloaded file is removed.
-  void OnDownloadedFileRemoved();
+  virtual void OnDownloadedFileRemoved() = 0;
 
   // Download operation had an error.
   // |size| is the amount of data received at interruption.
   // |reason| is the download interrupt reason code that the operation received.
-  void Interrupted(int64 size, InterruptReason reason);
+  virtual void Interrupted(int64 size, InterruptReason reason) = 0;
 
   // Deletes the file from disk and removes the download from the views and
   // history.  |user| should be true if this is the result of the user clicking
   // the discard button, and false if it is being deleted for other reasons like
   // browser shutdown.
-  void Delete(DeleteReason reason);
+  virtual void Delete(DeleteReason reason) = 0;
 
   // Removes the download from the views and history.
-  void Remove();
+  virtual void Remove() = 0;
 
   // Simple calculation of the amount of time remaining to completion. Fills
   // |*remaining| with the amount of time remaining if successful. Fails and
   // returns false if we do not have the number of bytes or the speed so can
   // not estimate.
-  bool TimeRemaining(base::TimeDelta* remaining) const;
+  virtual bool TimeRemaining(base::TimeDelta* remaining) const = 0;
 
   // Simple speed estimate in bytes/s
-  int64 CurrentSpeed() const;
+  virtual int64 CurrentSpeed() const = 0;
 
   // Rough percent complete, -1 means we don't know (since we didn't receive a
   // total size).
-  int PercentComplete() const;
+  virtual int PercentComplete() const = 0;
 
   // Called when the final path has been determined.
-  void OnPathDetermined(const FilePath& path);
+  virtual void OnPathDetermined(const FilePath& path) = 0;
 
   // Returns true if this download has saved all of its data.
-  bool all_data_saved() const { return all_data_saved_; }
+  virtual bool AllDataSaved() const = 0;
 
   // Update the fields that may have changed in DownloadStateInfo as a
   // result of analyzing the file and figuring out its type, location, etc.
   // May only be called once.
-  void SetFileCheckResults(const DownloadStateInfo& state);
+  virtual void SetFileCheckResults(const DownloadStateInfo& state) = 0;
 
   // Update the download's path, the actual file is renamed on the download
   // thread.
-  void Rename(const FilePath& full_path);
+  virtual void Rename(const FilePath& full_path) = 0;
 
   // Allow the user to temporarily pause a download or resume a paused download.
-  void TogglePause();
+  virtual void TogglePause() = 0;
 
   // Called when the download is ready to complete.
   // This may perform final rename if necessary and will eventually call
   // DownloadItem::Completed().
-  void OnDownloadCompleting(DownloadFileManager* file_manager);
+  virtual void OnDownloadCompleting(DownloadFileManager* file_manager) = 0;
 
   // Called when the file name for the download is renamed to its final name.
-  void OnDownloadRenamedToFinalName(const FilePath& full_path);
+  virtual void OnDownloadRenamedToFinalName(const FilePath& full_path) = 0;
 
   // Returns true if this item matches |query|. |query| must be lower-cased.
-  bool MatchesQuery(const string16& query) const;
+  virtual bool MatchesQuery(const string16& query) const = 0;
 
   // Returns true if the download needs more data.
-  bool IsPartialDownload() const;
+  virtual bool IsPartialDownload() const = 0;
 
   // Returns true if the download is still receiving data.
-  bool IsInProgress() const;
+  virtual bool IsInProgress() const = 0;
 
   // Returns true if the download has been cancelled or was interrupted.
-  bool IsCancelled() const;
+  virtual bool IsCancelled() const = 0;
 
   // Returns true if the download was interrupted.
-  bool IsInterrupted() const;
+  virtual bool IsInterrupted() const = 0;
 
   // Returns true if we have all the data and know the final file name.
-  bool IsComplete() const;
+  virtual bool IsComplete() const = 0;
 
   // Accessors
-  DownloadState state() const { return state_; }
-  const FilePath& full_path() const { return full_path_; }
-  void set_path_uniquifier(int uniquifier) {
-    state_info_.path_uniquifier = uniquifier;
-  }
-  const GURL& GetURL() const;
-
-  const std::vector<GURL>& url_chain() const { return url_chain_; }
-  const GURL& original_url() const { return url_chain_.front(); }
-  const GURL& referrer_url() const { return referrer_url_; }
-  std::string suggested_filename() const { return suggested_filename_; }
-  std::string content_disposition() const { return content_disposition_; }
-  std::string mime_type() const { return mime_type_; }
-  std::string original_mime_type() const { return original_mime_type_; }
-  std::string referrer_charset() const { return referrer_charset_; }
-  int64 total_bytes() const { return total_bytes_; }
-  void set_total_bytes(int64 total_bytes) {
-    total_bytes_ = total_bytes;
-  }
-  int64 received_bytes() const { return received_bytes_; }
-  const std::string& hash() const { return hash_; }
-  int32 id() const { return download_id_.local(); }
-  DownloadId global_id() const { return download_id_; }
-  base::Time start_time() const { return start_time_; }
-  base::Time end_time() const { return end_time_; }
-  void set_db_handle(int64 handle) { db_handle_ = handle; }
-  int64 db_handle() const { return db_handle_; }
-  DownloadManager* download_manager() { return download_manager_; }
-  bool is_paused() const { return is_paused_; }
-  bool open_when_complete() const { return open_when_complete_; }
-  void set_open_when_complete(bool open) { open_when_complete_ = open; }
-  bool file_externally_removed() const { return file_externally_removed_; }
-  SafetyState safety_state() const { return safety_state_; }
+  virtual const std::string& GetHash() const = 0;
+  virtual DownloadState GetState() const = 0;
+  virtual const FilePath& GetFullPath() const = 0;
+  virtual void SetPathUniquifier(int uniquifier) = 0;
+  virtual const GURL& GetURL() const = 0;
+  virtual const std::vector<GURL>& GetUrlChain() const = 0;
+  virtual const GURL& GetOriginalUrl() const = 0;
+  virtual const GURL& GetReferrerUrl() const = 0;
+  virtual std::string GetSuggestedFilename() const = 0;
+  virtual std::string GetContentDisposition() const = 0;
+  virtual std::string GetMimeType() const = 0;
+  virtual std::string GetOriginalMimeType() const = 0;
+  virtual std::string GetReferrerCharset() const = 0;
+  virtual int64 GetTotalBytes() const = 0;
+  virtual void SetTotalBytes(int64 total_bytes) = 0;
+  virtual int64 GetReceivedBytes() const = 0;
+  virtual int32 GetId() const = 0;
+  virtual DownloadId GetGlobalId() const = 0;
+  virtual base::Time GetStartTime() const = 0;
+  virtual base::Time GetEndTime() const = 0;
+  virtual void SetDbHandle(int64 handle) = 0;
+  virtual int64 GetDbHandle() const = 0;
+  virtual DownloadManager* GetDownloadManager() = 0;
+  virtual bool IsPaused() const = 0;
+  virtual bool GetOpenWhenComplete() const = 0;
+  virtual void SetOpenWhenComplete(bool open) = 0;
+  virtual bool GetFileExternallyRemoved() const = 0;
+  virtual SafetyState GetSafetyState() const = 0;
   // Why |safety_state_| is not SAFE.
-  DownloadStateInfo::DangerType GetDangerType() const;
-  bool IsDangerous() const;
-  void MarkFileDangerous();
-  void MarkUrlDangerous();
-  void MarkContentDangerous();
+  virtual DownloadStateInfo::DangerType GetDangerType() const = 0;
+  virtual bool IsDangerous() const = 0;
+  virtual void MarkContentDangerous() = 0;
+  virtual void MarkFileDangerous() = 0;
+  virtual void MarkUrlDangerous() = 0;
 
-  bool auto_opened() { return auto_opened_; }
-  const FilePath& target_name() const { return state_info_.target_name; }
-  bool prompt_user_for_save_location() const {
-    return state_info_.prompt_user_for_save_location;
-  }
-  bool is_otr() const { return is_otr_; }
-  const FilePath& suggested_path() const { return state_info_.suggested_path; }
-  bool is_temporary() const { return is_temporary_; }
-  void set_opened(bool opened) { opened_ = opened; }
-  bool opened() const { return opened_; }
+  virtual bool GetAutoOpened() = 0;
+  virtual const FilePath& GetTargetName() const = 0;
+  virtual bool PromptUserForSaveLocation() const = 0;
+  virtual bool IsOtr() const = 0;
+  virtual const FilePath& GetSuggestedPath() const = 0;
+  virtual bool IsTemporary() const = 0;
+  virtual void SetOpened(bool opened) = 0;
+  virtual bool GetOpened() const = 0;
 
-  InterruptReason last_reason() const { return last_reason_; }
-
-  DownloadPersistentStoreInfo GetPersistentStoreInfo() const;
-  DownloadStateInfo state_info() const { return state_info_; }
-
-  TabContents* GetTabContents() const;
+  virtual InterruptReason GetLastReason() const = 0;
+  virtual DownloadPersistentStoreInfo GetPersistentStoreInfo() const = 0;
+  virtual DownloadStateInfo GetStateInfo() const = 0;
+  virtual TabContents* GetTabContents() const = 0;
 
   // Returns the final target file path for the download.
-  FilePath GetTargetFilePath() const;
+  virtual FilePath GetTargetFilePath() const = 0;
 
   // Returns the file-name that should be reported to the user, which is
   // target_name possibly with the uniquifier number.
-  FilePath GetFileNameToReportUser() const;
+  virtual FilePath GetFileNameToReportUser() const = 0;
 
   // Returns the user-verified target file path for the download.
   // This returns the same path as GetTargetFilePath() for safe downloads
   // but does not for dangerous downloads until the name is verified.
-  FilePath GetUserVerifiedFilePath() const;
+  virtual FilePath GetUserVerifiedFilePath() const = 0;
 
   // Returns true if the current file name is not the final target name yet.
-  bool NeedsRename() const {
-    return state_info_.target_name != full_path_.BaseName();
-  }
+  virtual bool NeedsRename() const = 0;
 
   // Cancels the off-thread aspects of the download.
   // TODO(rdsmith): This should be private and only called from
@@ -327,156 +294,11 @@
   // call those functions from
   // DownloadManager::FileSelectionCancelled() without doing some
   // rewrites of the DownloadManager queues.
-  void OffThreadCancel(DownloadFileManager* file_manager);
+  virtual void OffThreadCancel(DownloadFileManager* file_manager) = 0;
 
-  std::string DebugString(bool verbose) const;
+  virtual std::string DebugString(bool verbose) const = 0;
 
-  void MockDownloadOpenForTesting() { open_enabled_ = false; }
-
- private:
-  // Construction common to all constructors. |active| should be true for new
-  // downloads and false for downloads from the history.
-  void Init(bool active);
-
-  // Internal helper for maintaining consistent received and total sizes.
-  void UpdateSize(int64 size);
-
-  // Called when the entire download operation (including renaming etc)
-  // is completed.
-  void Completed();
-
-  // Call to transition state; all state transitions should go through this.
-  void TransitionTo(DownloadState new_state);
-
-  // Called when safety_state_ should be recomputed from the DangerType of the
-  // state info.
-  void UpdateSafetyState();
-
-  // Helper function to recompute |state_info_.target_name| when
-  // it may have changed.  (If it's non-null it should be left alone,
-  // otherwise updated from |full_path_|.)
-  void UpdateTarget();
-
-  // State information used by the download manager.
-  DownloadStateInfo state_info_;
-
-  // The handle to the request information.  Used for operations outside the
-  // download system.  May be null if the download item isn't associated
-  // with a request (e.g. created from persistent store).
-  scoped_ptr<DownloadRequestHandleInterface> request_handle_;
-
-  // Download ID assigned by DownloadResourceHandler.
-  DownloadId download_id_;
-
-  // Full path to the downloaded or downloading file.
-  FilePath full_path_;
-
-  // A number that should be appended to the path to make it unique, or 0 if the
-  // path should be used as is.
-  int path_uniquifier_;
-
-  // The chain of redirects that leading up to and including the final URL.
-  std::vector<GURL> url_chain_;
-
-  // The URL of the page that initiated the download.
-  GURL referrer_url_;
-
-  // Suggested filename in 'download' attribute of an anchor. Details:
-  // http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks
-  std::string suggested_filename_;
-
-  // Information from the request.
-  // Content-disposition field from the header.
-  std::string content_disposition_;
-
-  // Mime-type from the header.  Subject to change.
-  std::string mime_type_;
-
-  // The value of the content type header sent with the downloaded item.  It
-  // may be different from |mime_type_|, which may be set based on heuristics
-  // which may look at the file extension and first few bytes of the file.
-  std::string original_mime_type_;
-
-  // The charset of the referring page where the download request comes from.
-  // It's used to construct a suggested filename.
-  std::string referrer_charset_;
-
-  // Total bytes expected
-  int64 total_bytes_;
-
-  // Current received bytes
-  int64 received_bytes_;
-
-  // Sha256 hash of the content.  This might be empty either because
-  // the download isn't done yet or because the hash isn't needed
-  // (ChromeDownloadManagerDelegate::GenerateFileHash() returned false).
-  std::string hash_;
-
-  // Last reason.
-  InterruptReason last_reason_;
-
-  // Start time for calculating remaining time
-  base::TimeTicks start_tick_;
-
-  // The current state of this download
-  DownloadState state_;
-
-  // The views of this item in the download shelf and download tab
-  ObserverList<Observer> observers_;
-
-  // Time the download was started
-  base::Time start_time_;
-
-  // Time the download completed
-  base::Time end_time_;
-
-  // Our persistent store handle
-  int64 db_handle_;
-
-  // Our owning object
-  DownloadManager* download_manager_;
-
-  // In progress downloads may be paused by the user, we note it here
-  bool is_paused_;
-
-  // A flag for indicating if the download should be opened at completion.
-  bool open_when_complete_;
-
-  // A flag for indicating if the downloaded file is externally removed.
-  bool file_externally_removed_;
-
-  // Indicates if the download is considered potentially safe or dangerous
-  // (executable files are typically considered dangerous).
-  SafetyState safety_state_;
-
-  // True if the download was auto-opened. We set this rather than using
-  // an observer as it's frequently possible for the download to be auto opened
-  // before the observer is added.
-  bool auto_opened_;
-
-  // True if the download was initiated in an incognito window.
-  bool is_otr_;
-
-  // True if the item was downloaded temporarily.
-  bool is_temporary_;
-
-  // True if we've saved all the data for the download.
-  bool all_data_saved_;
-
-  // Did the user open the item either directly or indirectly (such as by
-  // setting always open files of this type)? The shelf also sets this field
-  // when the user closes the shelf before the item has been opened but should
-  // be treated as though the user opened it.
-  bool opened_;
-
-  // Do we actual open downloads when requested?  For testing purposes
-  // only.
-  bool open_enabled_;
-
-  // Did the delegate delay calling Complete on this download?
-  bool delegate_delayed_complete_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadItem);
+  virtual void MockDownloadOpenForTesting() = 0;
 };
 
 #endif  // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_H_
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
new file mode 100644
index 0000000..0a76e98
--- /dev/null
+++ b/content/browser/download/download_item_impl.cc
@@ -0,0 +1,899 @@
+// Copyright (c) 2011 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 "content/browser/download/download_item_impl.h"
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/format_macros.h"
+#include "base/i18n/case_conversion.h"
+#include "base/i18n/string_search.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
+#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_file.h"
+#include "content/browser/download/download_file_manager.h"
+#include "content/browser/download/download_id.h"
+#include "content/browser/download/download_manager.h"
+#include "content/browser/download/download_persistent_store_info.h"
+#include "content/browser/download/download_request_handle.h"
+#include "content/browser/download/download_stats.h"
+#include "content/browser/download/interrupt_reasons.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/download_manager_delegate.h"
+#include "net/base/net_util.h"
+
+using content::BrowserThread;
+
+// A DownloadItem normally goes through the following states:
+//      * Created (when download starts)
+//      * Made visible to consumers (e.g. Javascript) after the
+//        destination file has been determined.
+//      * Entered into the history database.
+//      * Made visible in the download shelf.
+//      * All data is saved.  Note that the actual data download occurs
+//        in parallel with the above steps, but until those steps are
+//        complete, completion of the data download will be ignored.
+//      * Download file is renamed to its final name, and possibly
+//        auto-opened.
+// TODO(rdsmith): This progress should be reflected in
+// DownloadItem::DownloadState and a state transition table/state diagram.
+//
+// TODO(rdsmith): This description should be updated to reflect the cancel
+// pathways.
+
+namespace {
+
+static void DeleteDownloadedFile(const FilePath& path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+  // Make sure we only delete files.
+  if (!file_util::DirectoryExists(path))
+    file_util::Delete(path, false);
+}
+
+const char* DebugSafetyStateString(DownloadItem::SafetyState state) {
+  switch (state) {
+    case DownloadItem::SAFE:
+      return "SAFE";
+    case DownloadItem::DANGEROUS:
+      return "DANGEROUS";
+    case DownloadItem::DANGEROUS_BUT_VALIDATED:
+      return "DANGEROUS_BUT_VALIDATED";
+    default:
+      NOTREACHED() << "Unknown safety state " << state;
+      return "unknown";
+  };
+}
+
+const char* DebugDownloadStateString(DownloadItem::DownloadState state) {
+  switch (state) {
+    case DownloadItem::IN_PROGRESS:
+      return "IN_PROGRESS";
+    case DownloadItem::COMPLETE:
+      return "COMPLETE";
+    case DownloadItem::CANCELLED:
+      return "CANCELLED";
+    case DownloadItem::REMOVING:
+      return "REMOVING";
+    case DownloadItem::INTERRUPTED:
+      return "INTERRUPTED";
+    default:
+      NOTREACHED() << "Unknown download state " << state;
+      return "unknown";
+  };
+}
+
+// Classes to null out request handle calls (for SavePage DownloadItems, which
+// may have, e.g., Cancel() called on them without it doing anything)
+// and to DCHECK on them (for history DownloadItems, which should never have
+// any operation that implies an off-thread component, since they don't
+// have any).
+class NullDownloadRequestHandle : public DownloadRequestHandleInterface {
+ public:
+  NullDownloadRequestHandle() {}
+
+  // DownloadRequestHandleInterface calls
+  virtual TabContents* GetTabContents() const OVERRIDE {
+    return NULL;
+  }
+  virtual DownloadManager* GetDownloadManager() const OVERRIDE {
+    return NULL;
+  }
+  virtual void PauseRequest() const OVERRIDE {}
+  virtual void ResumeRequest() const OVERRIDE {}
+  virtual void CancelRequest() const OVERRIDE {}
+  virtual std::string DebugString() const OVERRIDE {
+    return "Null DownloadRequestHandle";
+  }
+};
+
+}  // namespace
+
+// Our download table ID starts at 1, so we use 0 to represent a download that
+// has started, but has not yet had its data persisted in the table. We use fake
+// database handles in incognito mode starting at -1 and progressively getting
+// more negative.
+
+// Constructor for reading from the history service.
+DownloadItemImpl::DownloadItemImpl(DownloadManager* download_manager,
+                                   const DownloadPersistentStoreInfo& info)
+    : download_id_(download_manager->GetNextId()),
+      full_path_(info.path),
+      url_chain_(1, info.url),
+      referrer_url_(info.referrer_url),
+      total_bytes_(info.total_bytes),
+      received_bytes_(info.received_bytes),
+      start_tick_(base::TimeTicks()),
+      state_(static_cast<DownloadState>(info.state)),
+      start_time_(info.start_time),
+      end_time_(info.end_time),
+      db_handle_(info.db_handle),
+      download_manager_(download_manager),
+      is_paused_(false),
+      open_when_complete_(false),
+      file_externally_removed_(false),
+      safety_state_(SAFE),
+      auto_opened_(false),
+      is_otr_(false),
+      is_temporary_(false),
+      all_data_saved_(false),
+      opened_(info.opened),
+      open_enabled_(true),
+      delegate_delayed_complete_(false) {
+  if (IsInProgress())
+    state_ = CANCELLED;
+  if (IsComplete())
+    all_data_saved_ = true;
+  Init(false /* not actively downloading */);
+}
+
+// Constructing for a regular download:
+DownloadItemImpl::DownloadItemImpl(
+    DownloadManager* download_manager,
+    const DownloadCreateInfo& info,
+    DownloadRequestHandleInterface* request_handle,
+    bool is_otr)
+    : state_info_(info.original_name, info.save_info.file_path,
+                  info.has_user_gesture, info.transition_type,
+                  info.prompt_user_for_save_location, info.path_uniquifier,
+                  DownloadStateInfo::NOT_DANGEROUS),
+      request_handle_(request_handle),
+      download_id_(info.download_id),
+      full_path_(info.path),
+      url_chain_(info.url_chain),
+      referrer_url_(info.referrer_url),
+      suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
+      content_disposition_(info.content_disposition),
+      mime_type_(info.mime_type),
+      original_mime_type_(info.original_mime_type),
+      referrer_charset_(info.referrer_charset),
+      total_bytes_(info.total_bytes),
+      received_bytes_(0),
+      last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
+      start_tick_(base::TimeTicks::Now()),
+      state_(IN_PROGRESS),
+      start_time_(info.start_time),
+      db_handle_(DownloadItem::kUninitializedHandle),
+      download_manager_(download_manager),
+      is_paused_(false),
+      open_when_complete_(false),
+      file_externally_removed_(false),
+      safety_state_(SAFE),
+      auto_opened_(false),
+      is_otr_(is_otr),
+      is_temporary_(!info.save_info.file_path.empty()),
+      all_data_saved_(false),
+      opened_(false),
+      open_enabled_(true),
+      delegate_delayed_complete_(false) {
+  Init(true /* actively downloading */);
+}
+
+// Constructing for the "Save Page As..." feature:
+DownloadItemImpl::DownloadItemImpl(DownloadManager* download_manager,
+                                   const FilePath& path,
+                                   const GURL& url,
+                                   bool is_otr,
+                                   DownloadId download_id)
+    : request_handle_(new NullDownloadRequestHandle()),
+      download_id_(download_id),
+      full_path_(path),
+      url_chain_(1, url),
+      referrer_url_(GURL()),
+      total_bytes_(0),
+      received_bytes_(0),
+      last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
+      start_tick_(base::TimeTicks::Now()),
+      state_(IN_PROGRESS),
+      start_time_(base::Time::Now()),
+      db_handle_(DownloadItem::kUninitializedHandle),
+      download_manager_(download_manager),
+      is_paused_(false),
+      open_when_complete_(false),
+      file_externally_removed_(false),
+      safety_state_(SAFE),
+      auto_opened_(false),
+      is_otr_(is_otr),
+      is_temporary_(false),
+      all_data_saved_(false),
+      opened_(false),
+      open_enabled_(true),
+      delegate_delayed_complete_(false) {
+  Init(true /* actively downloading */);
+}
+
+DownloadItemImpl::~DownloadItemImpl() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  TransitionTo(REMOVING);
+  download_manager_->AssertQueueStateConsistent(this);
+}
+
+void DownloadItemImpl::AddObserver(Observer* observer) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  observers_.AddObserver(observer);
+}
+
+void DownloadItemImpl::RemoveObserver(Observer* observer) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  observers_.RemoveObserver(observer);
+}
+
+void DownloadItemImpl::UpdateObservers() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
+}
+
+bool DownloadItemImpl::CanShowInFolder() {
+  return !IsCancelled() && !file_externally_removed_;
+}
+
+bool DownloadItemImpl::CanOpenDownload() {
+  return !file_externally_removed_;
+}
+
+bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
+  return download_manager_->delegate()->ShouldOpenFileBasedOnExtension(
+      GetUserVerifiedFilePath());
+}
+
+void DownloadItemImpl::OpenDownload() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (IsPartialDownload()) {
+    open_when_complete_ = !open_when_complete_;
+    return;
+  }
+
+  if (!IsComplete() || file_externally_removed_)
+    return;
+
+  // Ideally, we want to detect errors in opening and report them, but we
+  // don't generally have the proper interface for that to the external
+  // program that opens the file.  So instead we spawn a check to update
+  // the UI if the file has been deleted in parallel with the open.
+  download_manager_->CheckForFileRemoval(this);
+  download_stats::RecordOpen(GetEndTime(), !GetOpened());
+  opened_ = true;
+  FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
+  download_manager_->MarkDownloadOpened(this);
+
+  // For testing: If download opening is disabled on this item,
+  // make the rest of the routine a no-op.
+  if (!open_enabled_)
+    return;
+
+  content::GetContentClient()->browser()->OpenItem(GetFullPath());
+}
+
+void DownloadItemImpl::ShowDownloadInShell() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  content::GetContentClient()->browser()->ShowItemInFolder(GetFullPath());
+}
+
+void DownloadItemImpl::DangerousDownloadValidated() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_EQ(DANGEROUS, GetSafetyState());
+
+  UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated",
+                            GetDangerType(),
+                            DownloadStateInfo::DANGEROUS_TYPE_MAX);
+
+  safety_state_ = DANGEROUS_BUT_VALIDATED;
+  UpdateObservers();
+
+  download_manager_->MaybeCompleteDownload(this);
+}
+
+void DownloadItemImpl::UpdateSize(int64 bytes_so_far) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  received_bytes_ = bytes_so_far;
+
+  // If we've received more data than we were expecting (bad server info?),
+  // revert to 'unknown size mode'.
+  if (received_bytes_ > total_bytes_)
+    total_bytes_ = 0;
+}
+
+// Updates from the download thread may have been posted while this download
+// was being cancelled in the UI thread, so we'll accept them unless we're
+// complete.
+void DownloadItemImpl::Update(int64 bytes_so_far) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (!IsInProgress()) {
+    NOTREACHED();
+    return;
+  }
+  UpdateSize(bytes_so_far);
+  UpdateObservers();
+}
+
+// Triggered by a user action.
+void DownloadItemImpl::Cancel(bool user_cancel) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  last_reason_ = user_cancel ?
+      DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
+      DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
+
+  VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
+  if (!IsPartialDownload()) {
+    // Small downloads might be complete before this method has
+    // a chance to run.
+    return;
+  }
+
+  download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
+
+  TransitionTo(CANCELLED);
+  if (user_cancel)
+    download_manager_->DownloadCancelledInternal(this);
+}
+
+void DownloadItemImpl::MarkAsComplete() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  DCHECK(all_data_saved_);
+  end_time_ = base::Time::Now();
+  TransitionTo(COMPLETE);
+}
+
+void DownloadItemImpl::DelayedDownloadOpened() {
+  auto_opened_ = true;
+  Completed();
+}
+
+void DownloadItemImpl::OnAllDataSaved(
+    int64 size, const std::string& final_hash) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  DCHECK(!all_data_saved_);
+  all_data_saved_ = true;
+  UpdateSize(size);
+  hash_ = final_hash;
+}
+
+void DownloadItemImpl::OnDownloadedFileRemoved() {
+  file_externally_removed_ = true;
+  UpdateObservers();
+}
+
+void DownloadItemImpl::Completed() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
+
+  DCHECK(all_data_saved_);
+  end_time_ = base::Time::Now();
+  TransitionTo(COMPLETE);
+  download_manager_->DownloadCompleted(GetId());
+  download_stats::RecordDownloadCompleted(start_tick_, received_bytes_);
+
+  if (auto_opened_) {
+    // If it was already handled by the delegate, do nothing.
+  } else if (GetOpenWhenComplete() ||
+             ShouldOpenFileBasedOnExtension() ||
+             IsTemporary()) {
+    // If the download is temporary, like in drag-and-drop, do not open it but
+    // we still need to set it auto-opened so that it can be removed from the
+    // download shelf.
+    if (!IsTemporary())
+      OpenDownload();
+
+    auto_opened_ = true;
+    UpdateObservers();
+  }
+}
+
+void DownloadItemImpl::TransitionTo(DownloadState new_state) {
+  if (state_ == new_state)
+    return;
+
+  state_ = new_state;
+  UpdateObservers();
+}
+
+void DownloadItemImpl::UpdateSafetyState() {
+  SafetyState updated_value = state_info_.IsDangerous() ?
+    DownloadItem::DANGEROUS : DownloadItem::SAFE;
+  if (updated_value != safety_state_) {
+    safety_state_ = updated_value;
+    UpdateObservers();
+  }
+}
+
+void DownloadItemImpl::UpdateTarget() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (state_info_.target_name.value().empty())
+    state_info_.target_name = full_path_.BaseName();
+}
+
+void DownloadItemImpl::Interrupted(int64 size, InterruptReason reason) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (!IsInProgress())
+    return;
+
+  last_reason_ = reason;
+  UpdateSize(size);
+  download_stats::RecordDownloadInterrupted(reason,
+                                            received_bytes_,
+                                            total_bytes_);
+  TransitionTo(INTERRUPTED);
+}
+
+void DownloadItemImpl::Delete(DeleteReason reason) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  switch (reason) {
+    case DELETE_DUE_TO_USER_DISCARD:
+      UMA_HISTOGRAM_ENUMERATION("Download.UserDiscard", GetDangerType(),
+                                DownloadStateInfo::DANGEROUS_TYPE_MAX);
+      break;
+    case DELETE_DUE_TO_BROWSER_SHUTDOWN:
+      UMA_HISTOGRAM_ENUMERATION("Download.Discard", GetDangerType(),
+                                DownloadStateInfo::DANGEROUS_TYPE_MAX);
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::Bind(&DeleteDownloadedFile, full_path_));
+  Remove();
+  // We have now been deleted.
+}
+
+void DownloadItemImpl::Remove() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  download_manager_->AssertQueueStateConsistent(this);
+  Cancel(true);
+  download_manager_->AssertQueueStateConsistent(this);
+
+  TransitionTo(REMOVING);
+  download_manager_->RemoveDownload(db_handle_);
+  // We have now been deleted.
+}
+
+bool DownloadItemImpl::TimeRemaining(base::TimeDelta* remaining) const {
+  if (total_bytes_ <= 0)
+    return false;  // We never received the content_length for this download.
+
+  int64 speed = CurrentSpeed();
+  if (speed == 0)
+    return false;
+
+  *remaining = base::TimeDelta::FromSeconds(
+      (total_bytes_ - received_bytes_) / speed);
+  return true;
+}
+
+int64 DownloadItemImpl::CurrentSpeed() const {
+  if (is_paused_)
+    return 0;
+  base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
+  int64 diff_ms = diff.InMilliseconds();
+  return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms;
+}
+
+int DownloadItemImpl::PercentComplete() const {
+  // If the delegate is delaying completion of the download, then we have no
+  // idea how long it will take.
+  if (delegate_delayed_complete_ || total_bytes_ <= 0)
+    return -1;
+
+  return static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
+}
+
+void DownloadItemImpl::OnPathDetermined(const FilePath& path) {
+  full_path_ = path;
+  UpdateTarget();
+}
+
+void DownloadItemImpl::Rename(const FilePath& full_path) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  VLOG(20) << __FUNCTION__ << "()"
+           << " full_path = \"" << full_path.value() << "\""
+           << " " << DebugString(true);
+  DCHECK(!full_path.empty());
+  full_path_ = full_path;
+}
+
+void DownloadItemImpl::TogglePause() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  DCHECK(IsInProgress());
+  if (is_paused_)
+    request_handle_->ResumeRequest();
+  else
+    request_handle_->PauseRequest();
+  is_paused_ = !is_paused_;
+  UpdateObservers();
+}
+
+void DownloadItemImpl::OnDownloadCompleting(DownloadFileManager* file_manager) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  VLOG(20) << __FUNCTION__ << "()"
+           << " needs rename = " << NeedsRename()
+           << " " << DebugString(true);
+  DCHECK_NE(DANGEROUS, GetSafetyState());
+  DCHECK(file_manager);
+
+  if (NeedsRename()) {
+    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+        base::Bind(&DownloadFileManager::RenameCompletingDownloadFile,
+                   file_manager, GetGlobalId(),
+                   GetTargetFilePath(), GetSafetyState() == SAFE));
+    return;
+  }
+
+  Completed();
+
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::Bind(&DownloadFileManager::CompleteDownload,
+                                     file_manager, GetGlobalId()));
+}
+
+void DownloadItemImpl::OnDownloadRenamedToFinalName(const FilePath& full_path) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  VLOG(20) << __FUNCTION__ << "()"
+           << " full_path = \"" << full_path.value() << "\""
+           << " needed rename = " << NeedsRename()
+           << " " << DebugString(false);
+  DCHECK(NeedsRename());
+
+  Rename(full_path);
+
+  if (download_manager_->delegate()->ShouldOpenDownload(this)) {
+    Completed();
+  } else {
+    delegate_delayed_complete_ = true;
+  }
+}
+
+bool DownloadItemImpl::MatchesQuery(const string16& query) const {
+  if (query.empty())
+    return true;
+
+  DCHECK_EQ(query, base::i18n::ToLower(query));
+
+  string16 url_raw(UTF8ToUTF16(GetURL().spec()));
+  if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_raw))
+    return true;
+
+  // TODO(phajdan.jr): write a test case for the following code.
+  // A good test case would be:
+  //   "/\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd",
+  //   L"/\x4f60\x597d\x4f60\x597d",
+  //   "/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD"
+  std::string languages;
+  TabContents* tab = GetTabContents();
+  if (tab) {
+    languages = content::GetContentClient()->browser()->GetAcceptLangs(
+        tab->browser_context());
+  }
+  string16 url_formatted(net::FormatUrl(GetURL(), languages));
+  if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_formatted))
+    return true;
+
+  string16 path(GetFullPath().LossyDisplayName());
+  return base::i18n::StringSearchIgnoringCaseAndAccents(query, path);
+}
+
+void DownloadItemImpl::SetFileCheckResults(const DownloadStateInfo& state) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
+  state_info_ = state;
+  VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
+
+  UpdateSafetyState();
+}
+
+DownloadStateInfo::DangerType DownloadItemImpl::GetDangerType() const {
+  return state_info_.danger;
+}
+
+bool DownloadItemImpl::IsDangerous() const {
+  return state_info_.IsDangerous();
+}
+
+void DownloadItemImpl::MarkFileDangerous() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  state_info_.danger = DownloadStateInfo::DANGEROUS_FILE;
+  UpdateSafetyState();
+}
+
+void DownloadItemImpl::MarkUrlDangerous() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  state_info_.danger = DownloadStateInfo::DANGEROUS_URL;
+  UpdateSafetyState();
+}
+
+void DownloadItemImpl::MarkContentDangerous() {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  state_info_.danger = DownloadStateInfo::DANGEROUS_CONTENT;
+  UpdateSafetyState();
+}
+
+DownloadPersistentStoreInfo DownloadItemImpl::GetPersistentStoreInfo() const {
+  return DownloadPersistentStoreInfo(GetFullPath(),
+                                     GetURL(),
+                                     GetReferrerUrl(),
+                                     GetStartTime(),
+                                     GetEndTime(),
+                                     GetReceivedBytes(),
+                                     GetTotalBytes(),
+                                     GetState(),
+                                     GetDbHandle(),
+                                     GetOpened());
+}
+
+TabContents* DownloadItemImpl::GetTabContents() const {
+  // TODO(rdsmith): Remove null check after removing GetTabContents() from
+  // paths that might be used by DownloadItems created from history import.
+  // Currently such items have null request_handle_s, where other items
+  // (regular and SavePackage downloads) have actual objects off the pointer.
+  if (request_handle_.get())
+    return request_handle_->GetTabContents();
+  return NULL;
+}
+
+FilePath DownloadItemImpl::GetTargetFilePath() const {
+  return full_path_.DirName().Append(state_info_.target_name);
+}
+
+FilePath DownloadItemImpl::GetFileNameToReportUser() const {
+  if (state_info_.path_uniquifier > 0) {
+    FilePath name(state_info_.target_name);
+    DownloadFile::AppendNumberToPath(&name, state_info_.path_uniquifier);
+    return name;
+  }
+  return state_info_.target_name;
+}
+
+FilePath DownloadItemImpl::GetUserVerifiedFilePath() const {
+  return (safety_state_ == DownloadItem::SAFE) ?
+      GetTargetFilePath() : full_path_;
+}
+
+void DownloadItemImpl::OffThreadCancel(DownloadFileManager* file_manager) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  request_handle_->CancelRequest();
+
+  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+                          base::Bind(&DownloadFileManager::CancelDownload,
+                                     file_manager, GetGlobalId()));
+}
+
+void DownloadItemImpl::Init(bool active) {
+  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  UpdateTarget();
+  if (active) {
+    download_stats::RecordDownloadCount(download_stats::START_COUNT);
+  }
+  VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
+}
+
+// TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
+// |IsPartialDownload()|, when resuming interrupted downloads is implemented.
+bool DownloadItemImpl::IsPartialDownload() const {
+  return (state_ == IN_PROGRESS);
+}
+
+bool DownloadItemImpl::IsInProgress() const {
+  return (state_ == IN_PROGRESS);
+}
+
+bool DownloadItemImpl::IsCancelled() const {
+  return (state_ == CANCELLED) ||
+         (state_ == INTERRUPTED);
+}
+
+bool DownloadItemImpl::IsInterrupted() const {
+  return (state_ == INTERRUPTED);
+}
+
+bool DownloadItemImpl::IsComplete() const {
+  return (state_ == COMPLETE);
+}
+
+const GURL& DownloadItemImpl::GetURL() const {
+  return url_chain_.empty() ?
+             GURL::EmptyGURL() : url_chain_.back();
+}
+
+std::string DownloadItemImpl::DebugString(bool verbose) const {
+  std::string description =
+      base::StringPrintf("{ id = %d"
+                         " state = %s",
+                         download_id_.local(),
+                         DebugDownloadStateString(GetState()));
+
+  // Construct a string of the URL chain.
+  std::string url_list("<none>");
+  if (!url_chain_.empty()) {
+    std::vector<GURL>::const_iterator iter = url_chain_.begin();
+    std::vector<GURL>::const_iterator last = url_chain_.end();
+    url_list = (*iter).spec();
+    ++iter;
+    for ( ; verbose && (iter != last); ++iter) {
+      url_list += " ->\n\t";
+      const GURL& next_url = *iter;
+      url_list += next_url.spec();
+    }
+  }
+
+  if (verbose) {
+    description += base::StringPrintf(
+        " db_handle = %" PRId64
+        " total_bytes = %" PRId64
+        " received_bytes = %" PRId64
+        " is_paused = %c"
+        " is_otr = %c"
+        " safety_state = %s"
+        " url_chain = \n\t\"%s\"\n\t"
+        " target_name = \"%" PRFilePath "\""
+        " full_path = \"%" PRFilePath "\"",
+        GetDbHandle(),
+        GetTotalBytes(),
+        GetReceivedBytes(),
+        IsPaused() ? 'T' : 'F',
+        IsOtr() ? 'T' : 'F',
+        DebugSafetyStateString(GetSafetyState()),
+        url_list.c_str(),
+        state_info_.target_name.value().c_str(),
+        GetFullPath().value().c_str());
+  } else {
+    description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
+  }
+
+  description += " }";
+
+  return description;
+}
+
+bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; }
+DownloadItem::DownloadState DownloadItemImpl::GetState() const {
+  return state_;
+}
+const FilePath& DownloadItemImpl::GetFullPath() const { return full_path_; }
+void DownloadItemImpl::SetPathUniquifier(int uniquifier) {
+  state_info_.path_uniquifier = uniquifier;
+}
+const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const {
+  return url_chain_;
+}
+const GURL& DownloadItemImpl::GetOriginalUrl() const {
+  return url_chain_.front();
+}
+const GURL& DownloadItemImpl::GetReferrerUrl() const { return referrer_url_; }
+std::string DownloadItemImpl::GetSuggestedFilename() const {
+  return suggested_filename_;
+}
+std::string DownloadItemImpl::GetContentDisposition() const {
+  return content_disposition_;
+}
+std::string DownloadItemImpl::GetMimeType() const { return mime_type_; }
+std::string DownloadItemImpl::GetOriginalMimeType() const {
+  return original_mime_type_;
+}
+std::string DownloadItemImpl::GetReferrerCharset() const {
+  return referrer_charset_;
+}
+int64 DownloadItemImpl::GetTotalBytes() const { return total_bytes_; }
+void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
+  total_bytes_ = total_bytes;
+}
+const std::string& DownloadItemImpl::GetHash() const { return hash_; }
+int64 DownloadItemImpl::GetReceivedBytes() const { return received_bytes_; }
+int32 DownloadItemImpl::GetId() const { return download_id_.local(); }
+DownloadId DownloadItemImpl::GetGlobalId() const { return download_id_; }
+base::Time DownloadItemImpl::GetStartTime() const { return start_time_; }
+base::Time DownloadItemImpl::GetEndTime() const { return end_time_; }
+void DownloadItemImpl::SetDbHandle(int64 handle) { db_handle_ = handle; }
+int64 DownloadItemImpl::GetDbHandle() const { return db_handle_; }
+DownloadManager* DownloadItemImpl::GetDownloadManager() {
+  return download_manager_;
+}
+bool DownloadItemImpl::IsPaused() const { return is_paused_; }
+bool DownloadItemImpl::GetOpenWhenComplete() const {
+  return open_when_complete_;
+}
+void DownloadItemImpl::SetOpenWhenComplete(bool open) {
+  open_when_complete_ = open;
+}
+bool DownloadItemImpl::GetFileExternallyRemoved() const {
+  return file_externally_removed_;
+}
+DownloadItem::SafetyState DownloadItemImpl::GetSafetyState() const {
+  return safety_state_;
+}
+bool DownloadItemImpl::IsOtr() const { return is_otr_; }
+bool DownloadItemImpl::GetAutoOpened() { return auto_opened_; }
+const FilePath& DownloadItemImpl::GetTargetName() const {
+  return state_info_.target_name;
+}
+bool DownloadItemImpl::PromptUserForSaveLocation() const {
+  return state_info_.prompt_user_for_save_location;
+}
+const FilePath& DownloadItemImpl::GetSuggestedPath() const {
+  return state_info_.suggested_path;
+}
+bool DownloadItemImpl::IsTemporary() const { return is_temporary_; }
+void DownloadItemImpl::SetOpened(bool opened) { opened_ = opened; }
+bool DownloadItemImpl::GetOpened() const { return opened_; }
+InterruptReason DownloadItemImpl::GetLastReason() const {
+  return last_reason_;
+}
+DownloadStateInfo DownloadItemImpl::GetStateInfo() const { return state_info_; }
+bool DownloadItemImpl::NeedsRename() const {
+  return state_info_.target_name != full_path_.BaseName();
+}
+void DownloadItemImpl::MockDownloadOpenForTesting() { open_enabled_ = false; }
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
new file mode 100644
index 0000000..e1908017
--- /dev/null
+++ b/content/browser/download/download_item_impl.h
@@ -0,0 +1,291 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_
+#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "content/browser/download/download_item.h"
+#include "content/browser/download/download_id.h"
+#include "content/browser/download/download_request_handle.h"
+#include "content/browser/download/download_state_info.h"
+#include "content/browser/download/interrupt_reasons.h"
+#include "content/common/content_export.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_errors.h"
+
+class DownloadFileManager;
+class DownloadId;
+class DownloadManager;
+class TabContents;
+
+struct DownloadCreateInfo;
+struct DownloadPersistentStoreInfo;
+
+// See download_item.h for usage.
+class CONTENT_EXPORT DownloadItemImpl : public DownloadItem {
+ public:
+  // Constructing from persistent store:
+  DownloadItemImpl(DownloadManager* download_manager,
+                   const DownloadPersistentStoreInfo& info);
+
+  // Constructing for a regular download.
+  // Takes ownership of the object pointed to by |request_handle|.
+  DownloadItemImpl(DownloadManager* download_manager,
+                   const DownloadCreateInfo& info,
+                   DownloadRequestHandleInterface* request_handle,
+                   bool is_otr);
+
+  // Constructing for the "Save Page As..." feature:
+  DownloadItemImpl(DownloadManager* download_manager,
+                   const FilePath& path,
+                   const GURL& url,
+                   bool is_otr,
+                   DownloadId download_id);
+
+  virtual ~DownloadItemImpl();
+
+  // Overridden from DownloadItem.
+  virtual void AddObserver(DownloadItem::Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(DownloadItem::Observer* observer) OVERRIDE;
+  virtual void UpdateObservers() OVERRIDE;
+  virtual bool CanShowInFolder() OVERRIDE;
+  virtual bool CanOpenDownload() OVERRIDE;
+  virtual bool ShouldOpenFileBasedOnExtension() OVERRIDE;
+  virtual void OpenDownload() OVERRIDE;
+  virtual void ShowDownloadInShell() OVERRIDE;
+  virtual void DangerousDownloadValidated() OVERRIDE;
+  virtual void Update(int64 bytes_so_far) OVERRIDE;
+  virtual void Cancel(bool user_cancel) OVERRIDE;
+  virtual void MarkAsComplete() OVERRIDE;
+  virtual void DelayedDownloadOpened() OVERRIDE;
+  virtual void OnAllDataSaved(
+      int64 size, const std::string& final_hash) OVERRIDE;
+  virtual void OnDownloadedFileRemoved() OVERRIDE;
+  virtual void Interrupted(int64 size, InterruptReason reason) OVERRIDE;
+  virtual void Delete(DeleteReason reason) OVERRIDE;
+  virtual void Remove() OVERRIDE;
+  virtual bool TimeRemaining(base::TimeDelta* remaining) const OVERRIDE;
+  virtual int64 CurrentSpeed() const OVERRIDE;
+  virtual int PercentComplete() const OVERRIDE;
+  virtual void OnPathDetermined(const FilePath& path) OVERRIDE;
+  virtual bool AllDataSaved() const OVERRIDE;
+  virtual void SetFileCheckResults(const DownloadStateInfo& state) OVERRIDE;
+  virtual void Rename(const FilePath& full_path) OVERRIDE;
+  virtual void TogglePause() OVERRIDE;
+  virtual void OnDownloadCompleting(DownloadFileManager* file_manager) OVERRIDE;
+  virtual void OnDownloadRenamedToFinalName(const FilePath& full_path) OVERRIDE;
+  virtual bool MatchesQuery(const string16& query) const OVERRIDE;
+  virtual bool IsPartialDownload() const OVERRIDE;
+  virtual bool IsInProgress() const OVERRIDE;
+  virtual bool IsCancelled() const OVERRIDE;
+  virtual bool IsInterrupted() const OVERRIDE;
+  virtual bool IsComplete() const OVERRIDE;
+  virtual DownloadState GetState() const OVERRIDE;
+  virtual const FilePath& GetFullPath() const OVERRIDE;
+  virtual void SetPathUniquifier(int uniquifier) OVERRIDE;
+  virtual const GURL& GetURL() const OVERRIDE;
+  virtual const std::vector<GURL>& GetUrlChain() const OVERRIDE;
+  virtual const GURL& GetOriginalUrl() const OVERRIDE;
+  virtual const GURL& GetReferrerUrl() const OVERRIDE;
+  virtual std::string GetSuggestedFilename() const OVERRIDE;
+  virtual std::string GetContentDisposition() const OVERRIDE;
+  virtual std::string GetMimeType() const OVERRIDE;
+  virtual std::string GetOriginalMimeType() const OVERRIDE;
+  virtual std::string GetReferrerCharset() const OVERRIDE;
+  virtual int64 GetTotalBytes() const OVERRIDE;
+  virtual void SetTotalBytes(int64 total_bytes) OVERRIDE;
+  virtual const std::string& GetHash() const OVERRIDE;
+  virtual int64 GetReceivedBytes() const OVERRIDE;
+  virtual int32 GetId() const OVERRIDE;
+  virtual DownloadId GetGlobalId() const OVERRIDE;
+  virtual base::Time GetStartTime() const OVERRIDE;
+  virtual base::Time GetEndTime() const OVERRIDE;
+  virtual void SetDbHandle(int64 handle) OVERRIDE;
+  virtual int64 GetDbHandle() const OVERRIDE;
+  virtual DownloadManager* GetDownloadManager() OVERRIDE;
+  virtual bool IsPaused() const OVERRIDE;
+  virtual bool GetOpenWhenComplete() const OVERRIDE;
+  virtual void SetOpenWhenComplete(bool open) OVERRIDE;
+  virtual bool GetFileExternallyRemoved() const OVERRIDE;
+  virtual SafetyState GetSafetyState() const OVERRIDE;
+  virtual DownloadStateInfo::DangerType GetDangerType() const OVERRIDE;
+  virtual bool IsDangerous() const OVERRIDE;
+  virtual void MarkFileDangerous() OVERRIDE;
+  virtual void MarkUrlDangerous() OVERRIDE;
+  virtual void MarkContentDangerous() OVERRIDE;
+  virtual bool GetAutoOpened() OVERRIDE;
+  virtual const FilePath& GetTargetName() const OVERRIDE;
+  virtual bool PromptUserForSaveLocation() const OVERRIDE;
+  virtual bool IsOtr() const OVERRIDE;
+  virtual const FilePath& GetSuggestedPath() const OVERRIDE;
+  virtual bool IsTemporary() const OVERRIDE;
+  virtual void SetOpened(bool opened) OVERRIDE;
+  virtual bool GetOpened() const OVERRIDE;
+  virtual InterruptReason GetLastReason() const OVERRIDE;
+  virtual DownloadPersistentStoreInfo GetPersistentStoreInfo() const OVERRIDE;
+  virtual DownloadStateInfo GetStateInfo() const OVERRIDE;
+  virtual TabContents* GetTabContents() const OVERRIDE;
+  virtual FilePath GetTargetFilePath() const OVERRIDE;
+  virtual FilePath GetFileNameToReportUser() const OVERRIDE;
+  virtual FilePath GetUserVerifiedFilePath() const OVERRIDE;
+  virtual bool NeedsRename() const OVERRIDE;
+  virtual void OffThreadCancel(DownloadFileManager* file_manager) OVERRIDE;
+  virtual std::string DebugString(bool verbose) const OVERRIDE;
+  virtual void MockDownloadOpenForTesting() OVERRIDE;
+
+ private:
+  // Construction common to all constructors. |active| should be true for new
+  // downloads and false for downloads from the history.
+  void Init(bool active);
+
+  // Internal helper for maintaining consistent received and total sizes.
+  void UpdateSize(int64 size);
+
+  // Called when the entire download operation (including renaming etc)
+  // is completed.
+  void Completed();
+
+  // Call to transition state; all state transitions should go through this.
+  void TransitionTo(DownloadState new_state);
+
+  // Called when safety_state_ should be recomputed from is_dangerous_file
+  // and is_dangerous_url.
+  void UpdateSafetyState();
+
+  // Helper function to recompute |state_info_.target_name| when
+  // it may have changed.  (If it's non-null it should be left alone,
+  // otherwise updated from |full_path_|.)
+  void UpdateTarget();
+
+  // State information used by the download manager.
+  DownloadStateInfo state_info_;
+
+  // The handle to the request information.  Used for operations outside the
+  // download system.
+  scoped_ptr<DownloadRequestHandleInterface> request_handle_;
+
+  // Download ID assigned by DownloadResourceHandler.
+  DownloadId download_id_;
+
+  // Full path to the downloaded or downloading file.
+  FilePath full_path_;
+
+  // A number that should be appended to the path to make it unique, or 0 if the
+  // path should be used as is.
+  int path_uniquifier_;
+
+  // The chain of redirects that leading up to and including the final URL.
+  std::vector<GURL> url_chain_;
+
+  // The URL of the page that initiated the download.
+  GURL referrer_url_;
+
+  // Suggested filename in 'download' attribute of an anchor. Details:
+  // http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks
+  std::string suggested_filename_;
+
+  // Information from the request.
+  // Content-disposition field from the header.
+  std::string content_disposition_;
+
+  // Mime-type from the header.  Subject to change.
+  std::string mime_type_;
+
+  // The value of the content type header sent with the downloaded item.  It
+  // may be different from |mime_type_|, which may be set based on heuristics
+  // which may look at the file extension and first few bytes of the file.
+  std::string original_mime_type_;
+
+  // The charset of the referring page where the download request comes from.
+  // It's used to construct a suggested filename.
+  std::string referrer_charset_;
+
+  // Total bytes expected
+  int64 total_bytes_;
+
+  // Current received bytes
+  int64 received_bytes_;
+
+  // Sha256 hash of the content.  This might be empty either because
+  // the download isn't done yet or because the hash isn't needed
+  // (ChromeDownloadManagerDelegate::GenerateFileHash() returned false).
+  std::string hash_;
+
+  // Last reason.
+  InterruptReason last_reason_;
+
+  // Start time for calculating remaining time
+  base::TimeTicks start_tick_;
+
+  // The current state of this download
+  DownloadState state_;
+
+  // The views of this item in the download shelf and download tab
+  ObserverList<Observer> observers_;
+
+  // Time the download was started
+  base::Time start_time_;
+
+  // Time the download completed
+  base::Time end_time_;
+
+  // Our persistent store handle
+  int64 db_handle_;
+
+  // Our owning object
+  DownloadManager* download_manager_;
+
+  // In progress downloads may be paused by the user, we note it here
+  bool is_paused_;
+
+  // A flag for indicating if the download should be opened at completion.
+  bool open_when_complete_;
+
+  // A flag for indicating if the downloaded file is externally removed.
+  bool file_externally_removed_;
+
+  // Indicates if the download is considered potentially safe or dangerous
+  // (executable files are typically considered dangerous).
+  SafetyState safety_state_;
+
+  // True if the download was auto-opened. We set this rather than using
+  // an observer as it's frequently possible for the download to be auto opened
+  // before the observer is added.
+  bool auto_opened_;
+
+  // True if the download was initiated in an incognito window.
+  bool is_otr_;
+
+  // True if the item was downloaded temporarily.
+  bool is_temporary_;
+
+  // True if we've saved all the data for the download.
+  bool all_data_saved_;
+
+  // Did the user open the item either directly or indirectly (such as by
+  // setting always open files of this type)? The shelf also sets this field
+  // when the user closes the shelf before the item has been opened but should
+  // be treated as though the user opened it.
+  bool opened_;
+
+  // Do we actual open downloads when requested?  For testing purposes
+  // only.
+  bool open_enabled_;
+
+  // Did the delegate delay calling Complete on this download?
+  bool delegate_delayed_complete_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl);
+};
+
+#endif  // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_IMPL_H_
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index f1a73092..af74eba 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -20,7 +20,7 @@
 #include "content/browser/download/download_create_info.h"
 #include "content/browser/download/download_file_manager.h"
 #include "content/browser/download/download_id_factory.h"
-#include "content/browser/download/download_item.h"
+#include "content/browser/download/download_item_impl.h"
 #include "content/browser/download/download_persistent_store_info.h"
 #include "content/browser/download/download_stats.h"
 #include "content/browser/download/download_status_updater.h"
@@ -129,7 +129,7 @@
     // associative containers such as sets.
     it++;
 
-    if (download->safety_state() == DownloadItem::DANGEROUS &&
+    if (download->GetSafetyState() == DownloadItem::DANGEROUS &&
         download->IsPartialDownload()) {
       // The user hasn't accepted it, so we need to remove it
       // from the disk.  This may or may not result in it being
@@ -174,8 +174,8 @@
 
   for (DownloadMap::iterator it = history_downloads_.begin();
        it != history_downloads_.end(); ++it) {
-    if (it->second->is_temporary() &&
-        it->second->full_path().DirName() == dir_path)
+    if (it->second->IsTemporary() &&
+        it->second->GetFullPath().DirName() == dir_path)
       result->push_back(it->second);
   }
 }
@@ -186,8 +186,8 @@
 
   for (DownloadMap::iterator it = history_downloads_.begin();
        it != history_downloads_.end(); ++it) {
-    if (!it->second->is_temporary() &&
-        (dir_path.empty() || it->second->full_path().DirName() == dir_path))
+    if (!it->second->IsTemporary() &&
+        (dir_path.empty() || it->second->GetFullPath().DirName() == dir_path))
       result->push_back(it->second);
   }
 }
@@ -200,13 +200,13 @@
        it != history_downloads_.end(); ++it) {
     DownloadItem* download_item = it->second;
 
-    if (download_item->is_temporary())
+    if (download_item->IsTemporary())
       continue;
 
     // Display Incognito downloads only in Incognito window, and vice versa.
     // The Incognito Downloads page will get the list of non-Incognito downloads
     // from its parent profile.
-    if (browser_context_->IsOffTheRecord() != download_item->is_otr())
+    if (browser_context_->IsOffTheRecord() != download_item->IsOtr())
       continue;
 
     if (download_item->MatchesQuery(query_lower))
@@ -254,11 +254,11 @@
 void DownloadManagerImpl::CheckForFileRemoval(DownloadItem* download_item) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (download_item->IsComplete() &&
-      !download_item->file_externally_removed()) {
+      !download_item->GetFileExternallyRemoved()) {
     BrowserThread::PostTask(
         BrowserThread::FILE, FROM_HERE,
         base::Bind(&DownloadManagerImpl::CheckForFileRemovalOnFileThread,
-                   this, download_item->db_handle(),
+                   this, download_item->GetDbHandle(),
                    download_item->GetTargetFilePath()));
   }
 }
@@ -295,9 +295,9 @@
   VLOG(20) << __FUNCTION__ << "()"
            << " download = " << download->DebugString(true);
 
-  FilePath suggested_path = download->suggested_path();
+  FilePath suggested_path = download->GetSuggestedPath();
 
-  if (download->prompt_user_for_save_location()) {
+  if (download->PromptUserForSaveLocation()) {
     // We must ask the user for the place to put the download.
     TabContents* contents = download->GetTabContents();
 
@@ -329,7 +329,7 @@
     DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  DownloadItem* download = new DownloadItem(
+  DownloadItem* download = new DownloadItemImpl(
       this, *info, new DownloadRequestHandle(request_handle),
       browser_context_->IsOffTheRecord());
   int32 download_id = info->download_id.local();
@@ -346,7 +346,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(download);
 
-  int32 download_id = download->id();
+  int32 download_id = download->GetId();
 
   // NOTE(ahendrickson) Eventually |active_downloads_| will replace
   // |in_progress_|, but we don't want to change the semantics yet.
@@ -366,12 +366,12 @@
   // Rename to intermediate name.
   FilePath download_path;
   if (!delegate_->OverrideIntermediatePath(download, &download_path))
-    download_path = download->full_path();
+    download_path = download->GetFullPath();
 
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       base::Bind(&DownloadFileManager::RenameInProgressDownloadFile,
-                 file_manager_, download->global_id(), download_path));
+                 file_manager_, download->GetGlobalId(), download_path));
 
   download->Rename(download_path);
 
@@ -413,11 +413,11 @@
 
 void DownloadManagerImpl::AssertQueueStateConsistent(DownloadItem* download) {
   // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
-  if (download->state() == DownloadItem::REMOVING) {
+  if (download->GetState() == DownloadItem::REMOVING) {
     CHECK(!ContainsKey(downloads_, download));
-    CHECK(!ContainsKey(active_downloads_, download->id()));
-    CHECK(!ContainsKey(in_progress_, download->id()));
-    CHECK(!ContainsKey(history_downloads_, download->db_handle()));
+    CHECK(!ContainsKey(active_downloads_, download->GetId()));
+    CHECK(!ContainsKey(in_progress_, download->GetId()));
+    CHECK(!ContainsKey(history_downloads_, download->GetDbHandle()));
     return;
   }
 
@@ -425,8 +425,8 @@
   CHECK(ContainsKey(downloads_, download));
 
   // Check history_downloads_ consistency.
-  if (download->db_handle() != DownloadItem::kUninitializedHandle) {
-    CHECK(ContainsKey(history_downloads_, download->db_handle()));
+  if (download->GetDbHandle() != DownloadItem::kUninitializedHandle) {
+    CHECK(ContainsKey(history_downloads_, download->GetDbHandle()));
   } else {
     // TODO(rdsmith): Somewhat painful; make sure to disable in
     // release builds after resolution of http://crbug.com/85408.
@@ -436,38 +436,38 @@
     }
   }
 
-  int64 state = download->state();
+  int64 state = download->GetState();
   base::debug::Alias(&state);
-  if (ContainsKey(active_downloads_, download->id())) {
-    if (download->db_handle() != DownloadItem::kUninitializedHandle)
-      CHECK_EQ(DownloadItem::IN_PROGRESS, download->state());
-    if (DownloadItem::IN_PROGRESS != download->state())
-      CHECK_EQ(DownloadItem::kUninitializedHandle, download->db_handle());
+  if (ContainsKey(active_downloads_, download->GetId())) {
+    if (download->GetDbHandle() != DownloadItem::kUninitializedHandle)
+      CHECK_EQ(DownloadItem::IN_PROGRESS, download->GetState());
+    if (DownloadItem::IN_PROGRESS != download->GetState())
+      CHECK_EQ(DownloadItem::kUninitializedHandle, download->GetDbHandle());
   }
-  if (DownloadItem::IN_PROGRESS == download->state())
-    CHECK(ContainsKey(active_downloads_, download->id()));
+  if (DownloadItem::IN_PROGRESS == download->GetState())
+    CHECK(ContainsKey(active_downloads_, download->GetId()));
 }
 
 bool DownloadManagerImpl::IsDownloadReadyForCompletion(DownloadItem* download) {
   // If we don't have all the data, the download is not ready for
   // completion.
-  if (!download->all_data_saved())
+  if (!download->AllDataSaved())
     return false;
 
   // If the download is dangerous, but not yet validated, it's not ready for
   // completion.
-  if (download->safety_state() == DownloadItem::DANGEROUS)
+  if (download->GetSafetyState() == DownloadItem::DANGEROUS)
     return false;
 
   // If the download isn't active (e.g. has been cancelled) it's not
   // ready for completion.
-  if (active_downloads_.count(download->id()) == 0)
+  if (active_downloads_.count(download->GetId()) == 0)
     return false;
 
   // If the download hasn't been inserted into the history system
   // (which occurs strictly after file name determination, intermediate
   // file rename, and UI display) then it's not ready for completion.
-  if (download->db_handle() == DownloadItem::kUninitializedHandle)
+  if (download->GetDbHandle() == DownloadItem::kUninitializedHandle)
     return false;
 
   return true;
@@ -487,11 +487,11 @@
 
   // Confirm we're in the proper set of states to be here;
   // in in_progress_, have all data, have a history handle, (validated or safe).
-  DCHECK_NE(DownloadItem::DANGEROUS, download->safety_state());
-  DCHECK_EQ(1u, in_progress_.count(download->id()));
-  DCHECK(download->all_data_saved());
-  DCHECK(download->db_handle() != DownloadItem::kUninitializedHandle);
-  DCHECK_EQ(1u, history_downloads_.count(download->db_handle()));
+  DCHECK_NE(DownloadItem::DANGEROUS, download->GetSafetyState());
+  DCHECK_EQ(1u, in_progress_.count(download->GetId()));
+  DCHECK(download->AllDataSaved());
+  DCHECK(download->GetDbHandle() != DownloadItem::kUninitializedHandle);
+  DCHECK_EQ(1u, history_downloads_.count(download->GetDbHandle()));
 
   // Give the delegate a chance to override.
   if (!delegate_->ShouldCompleteDownload(download))
@@ -501,7 +501,7 @@
            << download->DebugString(false);
 
   // Remove the id from in_progress
-  in_progress_.erase(download->id());
+  in_progress_.erase(download->GetId());
   UpdateDownloadProgress();  // Reflect removal from in_progress_.
 
   delegate_->UpdateItemInPersistentStore(download);
@@ -532,17 +532,17 @@
   if (!item)
     return;
 
-  if (item->safety_state() == DownloadItem::SAFE) {
+  if (item->GetSafetyState() == DownloadItem::SAFE) {
     DCHECK_EQ(0, uniquifier) << "We should not uniquify SAFE downloads twice";
   }
 
   BrowserThread::PostTask(
       BrowserThread::FILE, FROM_HERE,
       base::Bind(&DownloadFileManager::CompleteDownload,
-                 file_manager_, item->global_id()));
+                 file_manager_, item->GetGlobalId()));
 
   if (uniquifier)
-    item->set_path_uniquifier(uniquifier);
+    item->SetPathUniquifier(uniquifier);
 
   item->OnDownloadRenamedToFinalName(full_path);
   delegate_->UpdatePathForItemInPersistentStore(item, full_path);
@@ -584,7 +584,7 @@
 
   VLOG(20) << __FUNCTION__ << "()"
            << " reason " << InterruptReasonDebugString(reason)
-           << " at offset " << download->received_bytes()
+           << " at offset " << download->GetReceivedBytes()
            << " size = " << size
            << " download = " << download->DebugString(true);
 
@@ -602,7 +602,7 @@
   DownloadItem* download = it->second;
 
   DCHECK(download);
-  DCHECK_EQ(download_id, download->id());
+  DCHECK_EQ(download_id, download->GetId());
 
   return download;
 }
@@ -613,9 +613,9 @@
 
   // Clean up will happen when the history system create callback runs if we
   // don't have a valid db_handle yet.
-  if (download->db_handle() != DownloadItem::kUninitializedHandle) {
-    in_progress_.erase(download->id());
-    active_downloads_.erase(download->id());
+  if (download->GetDbHandle() != DownloadItem::kUninitializedHandle) {
+    in_progress_.erase(download->GetId());
+    active_downloads_.erase(download->GetId());
     UpdateDownloadProgress();  // Reflect removal from in_progress_.
     delegate_->UpdateItemInPersistentStore(download);
   }
@@ -645,8 +645,8 @@
       ++it) {
     DownloadItem* download = *it;
     DCHECK(download);
-    history_downloads_.erase(download->db_handle());
-    save_page_downloads_.erase(download->id());
+    history_downloads_.erase(download->GetDbHandle());
+    save_page_downloads_.erase(download->GetId());
     downloads_.erase(download);
   }
 
@@ -684,8 +684,8 @@
       it != history_downloads_.end();
       ++it) {
     DownloadItem* download = it->second;
-    if (download->start_time() >= remove_begin &&
-        (remove_end.is_null() || download->start_time() < remove_end) &&
+    if (download->GetStartTime() >= remove_begin &&
+        (remove_end.is_null() || download->GetStartTime() < remove_end) &&
         (download->IsComplete() || download->IsCancelled())) {
       AssertQueueStateConsistent(download);
       pending_deletes.push_back(download);
@@ -747,7 +747,7 @@
 bool DownloadManagerImpl::IsDownloadProgressKnown() const {
   for (DownloadMap::const_iterator i = in_progress_.begin();
        i != in_progress_.end(); ++i) {
-    if (i->second->total_bytes() <= 0)
+    if (i->second->GetTotalBytes() <= 0)
       return false;
   }
 
@@ -763,7 +763,7 @@
   int64 received_bytes = 0;
   for (DownloadMap::const_iterator i = in_progress_.begin();
        i != in_progress_.end(); ++i) {
-    received_bytes += i->second->received_bytes();
+    received_bytes += i->second->GetReceivedBytes();
   }
   return received_bytes;
 }
@@ -773,7 +773,7 @@
   int64 total_bytes = 0;
   for (DownloadMap::const_iterator i = in_progress_.begin();
        i != in_progress_.end(); ++i) {
-    total_bytes += i->second->total_bytes();
+    total_bytes += i->second->GetTotalBytes();
   }
   return total_bytes;
 }
@@ -792,7 +792,7 @@
   VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
             << " download = " << download->DebugString(true);
 
-  if (download->prompt_user_for_save_location())
+  if (download->PromptUserForSaveLocation())
     last_download_path_ = path.DirName();
 
   // Make sure the initial file name is set only once.
@@ -834,16 +834,16 @@
   largest_db_handle_in_history_ = 0;
 
   for (size_t i = 0; i < entries->size(); ++i) {
-    DownloadItem* download = new DownloadItem(this, entries->at(i));
+    DownloadItem* download = new DownloadItemImpl(this, entries->at(i));
     // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
-    CHECK(!ContainsKey(history_downloads_, download->db_handle()));
+    CHECK(!ContainsKey(history_downloads_, download->GetDbHandle()));
     downloads_.insert(download);
-    history_downloads_[download->db_handle()] = download;
+    history_downloads_[download->GetDbHandle()] = download;
     VLOG(20) << __FUNCTION__ << "()" << i << ">"
              << " download = " << download->DebugString(true);
 
-    if (download->db_handle() > largest_db_handle_in_history_)
-      largest_db_handle_in_history_ = download->db_handle();
+    if (download->GetDbHandle() > largest_db_handle_in_history_)
+      largest_db_handle_in_history_ = download->GetDbHandle();
   }
   NotifyModelChanged();
   CheckForHistoryFilesRemoval();
@@ -859,13 +859,13 @@
 
   download_stats::RecordHistorySize(history_downloads_.size());
 
-  DCHECK(download->db_handle() == DownloadItem::kUninitializedHandle);
-  download->set_db_handle(db_handle);
+  DCHECK(download->GetDbHandle() == DownloadItem::kUninitializedHandle);
+  download->SetDbHandle(db_handle);
 
   // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/85408
   // is fixed.
-  CHECK(!ContainsKey(history_downloads_, download->db_handle()));
-  history_downloads_[download->db_handle()] = download;
+  CHECK(!ContainsKey(history_downloads_, download->GetDbHandle()));
+  history_downloads_[download->GetDbHandle()] = download;
 
   // Show in the appropriate browser UI.
   // This includes buttons to save or cancel, for a dangerous download.
@@ -905,7 +905,7 @@
   base::debug::Alias(&largest_handle);
   int32 matching_item_download_id
       = (ContainsKey(history_downloads_, db_handle) ?
-         history_downloads_[db_handle]->id() : 0);
+         history_downloads_[db_handle]->GetId() : 0);
   base::debug::Alias(&matching_item_download_id);
 
   CHECK(!ContainsKey(history_downloads_, db_handle));
@@ -966,7 +966,7 @@
   for (DownloadMap::iterator it = history_downloads_.begin();
        it != history_downloads_.end(); ++it) {
     DownloadItem* item = it->second;
-    if (item->id() == download_id)
+    if (item->GetId() == download_id)
       return item;
   }
   return NULL;
@@ -1025,9 +1025,9 @@
 }
 
 void DownloadManagerImpl::SavePageDownloadStarted(DownloadItem* download) {
-  DCHECK(!ContainsKey(save_page_downloads_, download->id()));
+  DCHECK(!ContainsKey(save_page_downloads_, download->GetId()));
   downloads_.insert(download);
-  save_page_downloads_[download->id()] = download;
+  save_page_downloads_[download->GetId()] = download;
 
   // Add this entry to the history service.
   // Additionally, the UI is notified in the callback.
@@ -1077,10 +1077,10 @@
 }
 
 void DownloadManagerImpl::SavePageDownloadFinished(DownloadItem* download) {
-  if (download->db_handle() != DownloadItem::kUninitializedHandle) {
+  if (download->GetDbHandle() != DownloadItem::kUninitializedHandle) {
     delegate_->UpdateItemInPersistentStore(download);
-    DCHECK(ContainsKey(save_page_downloads_, download->id()));
-    save_page_downloads_.erase(download->id());
+    DCHECK(ContainsKey(save_page_downloads_, download->GetId()));
+    save_page_downloads_.erase(download->GetId());
 
     if (download->IsComplete())
       content::NotificationService::current()->Notify(
@@ -1095,7 +1095,7 @@
   int num_unopened = 0;
   for (DownloadMap::iterator it = history_downloads_.begin();
        it != history_downloads_.end(); ++it) {
-    if (it->second->IsComplete() && !it->second->opened())
+    if (it->second->IsComplete() && !it->second->GetOpened())
       ++num_unopened;
   }
   download_stats::RecordOpensOutstanding(num_unopened);
diff --git a/content/browser/download/drag_download_file.cc b/content/browser/download/drag_download_file.cc
index 56898d5..cf245e5 100644
--- a/content/browser/download/drag_download_file.cc
+++ b/content/browser/download/drag_download_file.cc
@@ -174,7 +174,7 @@
   download_manager_->GetTemporaryDownloads(file_path_.DirName(), &downloads);
   for (std::vector<DownloadItem*>::const_iterator i = downloads.begin();
        i != downloads.end(); ++i) {
-    if ((*i)->original_url() == url_) {
+    if ((*i)->GetOriginalUrl() == url_) {
       download_item_ = *i;
       download_item_->AddObserver(this);
       break;
@@ -184,7 +184,8 @@
 
 void DragDownloadFile::OnDownloadUpdated(DownloadItem* download) {
   AssertCurrentlyOnUIThread();
-  if (download->IsCancelled() || download->state() == DownloadItem::REMOVING) {
+  if (download->IsCancelled() ||
+      (download->GetState() == DownloadItem::REMOVING)) {
     RemoveObservers();
     DownloadCompleted(false);
   } else if (download->IsComplete()) {
diff --git a/content/browser/download/mock_download_item.cc b/content/browser/download/mock_download_item.cc
new file mode 100644
index 0000000..e5a0f83
--- /dev/null
+++ b/content/browser/download/mock_download_item.cc
@@ -0,0 +1,8 @@
+// Copyright (c) 2011 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 "content/browser/download/mock_download_item.h"
+
+MockDownloadItem::MockDownloadItem() {}
+MockDownloadItem::~MockDownloadItem() {}
diff --git a/content/browser/download/mock_download_item.h b/content/browser/download/mock_download_item.h
new file mode 100644
index 0000000..4a4ad84
--- /dev/null
+++ b/content/browser/download/mock_download_item.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_DOWNLOAD_MOCK_DOWNLOAD_ITEM_H_
+#define CONTENT_BROWSER_DOWNLOAD_MOCK_DOWNLOAD_ITEM_H_
+
+#include <string>
+#include <vector>
+
+#include "content/browser/download/download_item.h"
+#include "content/browser/download/download_id.h"
+#include "content/browser/download/download_persistent_store_info.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class MockDownloadItem : public DownloadItem {
+ public:
+  MockDownloadItem();
+  virtual ~MockDownloadItem();
+  MOCK_METHOD1(AddObserver, void(DownloadItem::Observer*));
+  MOCK_METHOD1(RemoveObserver, void(DownloadItem::Observer*));
+  MOCK_METHOD0(UpdateObservers, void());
+  MOCK_METHOD0(CanShowInFolder, bool());
+  MOCK_METHOD0(CanOpenDownload, bool());
+  MOCK_METHOD0(ShouldOpenFileBasedOnExtension, bool());
+  MOCK_METHOD0(OpenDownload, void());
+  MOCK_METHOD0(ShowDownloadInShell, void());
+  MOCK_METHOD0(DangerousDownloadValidated, void());
+  MOCK_METHOD1(Update, void(int64));
+  MOCK_METHOD1(Cancel, void(bool));
+  MOCK_METHOD0(MarkAsComplete, void());
+  MOCK_METHOD0(DelayedDownloadOpened, void());
+  MOCK_METHOD2(OnAllDataSaved, void(int64, const std::string&));
+  MOCK_METHOD0(OnDownloadedFileRemoved, void());
+  MOCK_METHOD2(Interrupted, void(int64, InterruptReason));
+  MOCK_METHOD1(Delete, void(DeleteReason));
+  MOCK_METHOD0(Remove, void());
+  MOCK_CONST_METHOD1(TimeRemaining, bool(base::TimeDelta*));
+  MOCK_CONST_METHOD0(CurrentSpeed, int64());
+  MOCK_CONST_METHOD0(PercentComplete, int());
+  MOCK_METHOD1(OnPathDetermined, void(const FilePath&));
+  MOCK_CONST_METHOD0(AllDataSaved, bool());
+  MOCK_METHOD1(SetFileCheckResults, void(const DownloadStateInfo&));
+  MOCK_METHOD1(Rename, void(const FilePath&));
+  MOCK_METHOD0(TogglePause, void());
+  MOCK_METHOD1(OnDownloadCompleting, void(DownloadFileManager*));
+  MOCK_METHOD1(OnDownloadRenamedToFinalName, void(const FilePath&));
+  MOCK_CONST_METHOD1(MatchesQuery, bool(const string16& query));
+  MOCK_CONST_METHOD0(IsPartialDownload, bool());
+  MOCK_CONST_METHOD0(IsInProgress, bool());
+  MOCK_CONST_METHOD0(IsCancelled, bool());
+  MOCK_CONST_METHOD0(IsInterrupted, bool());
+  MOCK_CONST_METHOD0(IsComplete, bool());
+  MOCK_CONST_METHOD0(GetState, DownloadState());
+  MOCK_CONST_METHOD0(GetFullPath, const FilePath&());
+  MOCK_METHOD1(SetPathUniquifier, void(int));
+  MOCK_CONST_METHOD0(GetUrlChain, const std::vector<GURL>&());
+  MOCK_METHOD1(SetTotalBytes, void(int64));
+  MOCK_CONST_METHOD0(GetURL, const GURL&());
+  MOCK_CONST_METHOD0(GetOriginalUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetReferrerUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
+  MOCK_CONST_METHOD0(GetContentDisposition, std::string());
+  MOCK_CONST_METHOD0(GetMimeType, std::string());
+  MOCK_CONST_METHOD0(GetOriginalMimeType, std::string());
+  MOCK_CONST_METHOD0(GetReferrerCharset, std::string());
+  MOCK_CONST_METHOD0(GetTotalBytes, int64());
+  MOCK_CONST_METHOD0(GetReceivedBytes, int64());
+  MOCK_CONST_METHOD0(GetHash, const std::string&());
+  MOCK_CONST_METHOD0(GetId, int32());
+  MOCK_CONST_METHOD0(GetGlobalId, DownloadId());
+  MOCK_CONST_METHOD0(GetStartTime, base::Time());
+  MOCK_CONST_METHOD0(GetEndTime, base::Time());
+  MOCK_METHOD1(SetDbHandle, void(int64));
+  MOCK_CONST_METHOD0(GetDbHandle, int64());
+  MOCK_METHOD0(GetDownloadManager, DownloadManager*());
+  MOCK_CONST_METHOD0(IsPaused, bool());
+  MOCK_CONST_METHOD0(GetOpenWhenComplete, bool());
+  MOCK_METHOD1(SetOpenWhenComplete, void(bool));
+  MOCK_CONST_METHOD0(GetFileExternallyRemoved, bool());
+  MOCK_CONST_METHOD0(GetSafetyState, SafetyState());
+  MOCK_CONST_METHOD0(GetDangerType, DownloadStateInfo::DangerType());
+  MOCK_CONST_METHOD0(IsDangerous, bool());
+  MOCK_METHOD0(MarkFileDangerous, void());
+  MOCK_METHOD0(MarkUrlDangerous, void());
+  MOCK_METHOD0(MarkContentDangerous, void());
+  MOCK_METHOD0(GetAutoOpened, bool());
+  MOCK_CONST_METHOD0(GetTargetName, const FilePath&());
+  MOCK_CONST_METHOD0(PromptUserForSaveLocation, bool());
+  MOCK_CONST_METHOD0(IsOtr, bool());
+  MOCK_CONST_METHOD0(GetSuggestedPath, const FilePath&());
+  MOCK_CONST_METHOD0(IsTemporary, bool());
+  MOCK_METHOD1(SetOpened, void(bool));
+  MOCK_CONST_METHOD0(GetOpened, bool());
+  MOCK_CONST_METHOD0(GetLastReason, InterruptReason());
+  MOCK_CONST_METHOD0(GetPersistentStoreInfo, DownloadPersistentStoreInfo());
+  MOCK_CONST_METHOD0(GetStateInfo, DownloadStateInfo());
+  MOCK_CONST_METHOD0(GetTabContents, TabContents*());
+  MOCK_CONST_METHOD0(GetTargetFilePath, FilePath());
+  MOCK_CONST_METHOD0(GetFileNameToReportUser, FilePath());
+  MOCK_CONST_METHOD0(GetUserVerifiedFilePath, FilePath());
+  MOCK_CONST_METHOD0(NeedsRename, bool());
+  MOCK_METHOD1(OffThreadCancel, void(DownloadFileManager* file_manager));
+  MOCK_CONST_METHOD1(DebugString, std::string(bool));
+  MOCK_METHOD0(MockDownloadOpenForTesting, void());
+};
+#endif  // CONTENT_BROWSER_DOWNLOAD_MOCK_DOWNLOAD_ITEM_H_
diff --git a/content/browser/download/mock_download_manager.cc b/content/browser/download/mock_download_manager.cc
index 40d77283..359eff9 100644
--- a/content/browser/download/mock_download_manager.cc
+++ b/content/browser/download/mock_download_manager.cc
@@ -5,6 +5,7 @@
 #include "content/browser/download/mock_download_manager.h"
 
 #include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_item_impl.h"
 
 MockDownloadManager::MockDownloadManager(
     content::DownloadManagerDelegate* delegate,
@@ -65,20 +66,20 @@
 
 void MockDownloadManager::DownloadCancelledInternal(DownloadItem* download) {
   download->Cancel(true);
-  item_map_.erase(download->id());
-  inactive_item_map_[download->id()] = download;
+  item_map_.erase(download->GetId());
+  inactive_item_map_[download->GetId()] = download;
 }
 
 void MockDownloadManager::RemoveDownload(int64 download_handle) {
 }
 
 bool MockDownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
-  return download->all_data_saved();
+  return download->AllDataSaved();
 }
 
 void MockDownloadManager::MaybeCompleteDownload(DownloadItem* download) {
   if (IsDownloadReadyForCompletion(download))
-    download->OnDownloadRenamedToFinalName(download->full_path());
+    download->OnDownloadRenamedToFinalName(download->GetFullPath());
 }
 
 void MockDownloadManager::OnDownloadRenamedToFinalName(
@@ -150,11 +151,8 @@
     DownloadCreateInfo* info,
     const DownloadRequestHandle& request_handle) {
   item_map_.insert(std::make_pair(
-      info->download_id.local(),
-      new DownloadItem(this,
-                       *info,
-                       new DownloadRequestHandle(request_handle),
-                       false)));
+      info->download_id.local(), new DownloadItemImpl(
+        this, *info, new DownloadRequestHandle(request_handle), false)));
 }
 
 void MockDownloadManager::ClearLastDownloadPath() {
@@ -170,7 +168,7 @@
 }
 
 void MockDownloadManager::MarkDownloadOpened(DownloadItem* download) {
-  download->set_open_when_complete(true);
+  download->SetOpenWhenComplete(true);
 }
 
 void MockDownloadManager::CheckForHistoryFilesRemoval() {
diff --git a/content/browser/download/mock_download_manager_delegate.cc b/content/browser/download/mock_download_manager_delegate.cc
index 4fc719c1..7a03c81 100644
--- a/content/browser/download/mock_download_manager_delegate.cc
+++ b/content/browser/download/mock_download_manager_delegate.cc
@@ -61,7 +61,7 @@
 }
 
 void MockDownloadManagerDelegate::AddItemToPersistentStore(DownloadItem* item) {
-  download_manager_->OnItemAddedToPersistentStore(item->id(), item->id());
+  download_manager_->OnItemAddedToPersistentStore(item->GetId(), item->GetId());
 }
 
 void MockDownloadManagerDelegate::UpdateItemInPersistentStore(
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index 6be5513..cf22feb 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -20,7 +20,7 @@
 #include "base/utf_string_conversions.h"
 #include "content/browser/browser_context.h"
 #include "content/browser/download/download_file_manager.h"
-#include "content/browser/download/download_item.h"
+#include "content/browser/download/download_item_impl.h"
 #include "content/browser/download/download_manager.h"
 #include "content/browser/download/save_file.h"
 #include "content/browser/download/save_file_manager.h"
@@ -266,11 +266,11 @@
   }
 
   // Create the download item, and add ourself as an observer.
-  download_ = new DownloadItem(download_manager_,
-                               saved_main_file_path_,
-                               page_url_,
-                               browser_context->IsOffTheRecord(),
-                               download_manager_->GetNextId());
+  download_ = new DownloadItemImpl(download_manager_,
+                                   saved_main_file_path_,
+                                   page_url_,
+                                   browser_context->IsOffTheRecord(),
+                                   download_manager_->GetNextId());
   download_->AddObserver(this);
 
   // Transfer ownership to the download manager.
@@ -293,7 +293,7 @@
     // Add this item to waiting list.
     waiting_item_queue_.push(save_item);
     all_save_items_count_ = 1;
-    download_->set_total_bytes(1);
+    download_->SetTotalBytes(1);
 
     DoSavingProcess();
   }
@@ -1014,7 +1014,7 @@
 
   // We use total bytes as the total number of files we want to save.
   if (download_)
-    download_->set_total_bytes(all_save_items_count_);
+    download_->SetTotalBytes(all_save_items_count_);
 
   if (all_save_items_count_) {
     // Put all sub-resources to wait list.
@@ -1277,7 +1277,7 @@
   DCHECK(download_manager_);
 
   // Check for removal.
-  if (download->state() == DownloadItem::REMOVING)
+  if (download->GetState() == DownloadItem::REMOVING)
     StopObservation();
 }
 
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 909a044..9cb4b73 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -142,6 +142,8 @@
     'browser/download/download_id_factory.h',
     'browser/download/download_item.cc',
     'browser/download/download_item.h',
+    'browser/download/download_item_impl.cc',
+    'browser/download/download_item_impl.h',
     'browser/download/download_manager.h',
     'browser/download/download_manager_impl.cc',
     'browser/download/download_manager_impl.h',
@@ -164,9 +166,9 @@
     'browser/download/drag_download_file.h',
     'browser/download/drag_download_util.cc',
     'browser/download/drag_download_util.h',
+    'browser/download/interrupt_reason_values.h',
     'browser/download/interrupt_reasons.cc',
     'browser/download/interrupt_reasons.h',
-    'browser/download/interrupt_reason_values.h',
     'browser/download/mhtml_generation_manager.cc',
     'browser/download/mhtml_generation_manager.h',
     'browser/download/save_file.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 3092c9050..520654a 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -35,6 +35,8 @@
         'browser/download/mock_download_file.h',
         'browser/download/mock_download_manager.cc',
         'browser/download/mock_download_manager.h',
+        'browser/download/mock_download_item.cc',
+        'browser/download/mock_download_item.h',
         'browser/download/mock_download_manager_delegate.cc',
         'browser/download/mock_download_manager_delegate.h',
         'browser/geolocation/arbitrator_dependency_factories_for_test.cc',
diff --git a/content/shell/shell_download_manager_delegate.cc b/content/shell/shell_download_manager_delegate.cc
index b70bbcd..4660f0b 100644
--- a/content/shell/shell_download_manager_delegate.cc
+++ b/content/shell/shell_download_manager_delegate.cc
@@ -42,17 +42,17 @@
 bool ShellDownloadManagerDelegate::ShouldStartDownload(int32 download_id) {
   DownloadItem* download =
       download_manager_->GetActiveDownloadItem(download_id);
-  DownloadStateInfo state = download->state_info();
+  DownloadStateInfo state = download->GetStateInfo();
 
   if (!state.force_file_name.empty())
     return true;
 
   FilePath generated_name = net::GenerateFileName(
       download->GetURL(),
-      download->content_disposition(),
-      download->referrer_charset(),
-      download->suggested_filename(),
-      download->mime_type(),
+      download->GetContentDisposition(),
+      download->GetReferrerCharset(),
+      download->GetSuggestedFilename(),
+      download->GetMimeType(),
       "download");
 
   // Since we have no download UI, show the user a dialog always.