// 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_manager.h"

#include <iterator>

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/sys_string_conversions.h"
#include "base/task.h"
#include "build/build_config.h"
#include "content/browser/browser_context.h"
#include "content/browser/browser_thread.h"
#include "content/browser/content_browser_client.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file_manager.h"
#include "content/browser/download/download_item.h"
#include "content/browser/download/download_manager_delegate.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"
#include "content/browser/download/interrupt_reasons.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/notification_service.h"
#include "content/public/browser/notification_types.h"

namespace {

void BeginDownload(
    const GURL& url,
    const GURL& referrer,
    const DownloadSaveInfo& save_info,
    ResourceDispatcherHost* resource_dispatcher_host,
    int render_process_id,
    int render_view_id,
    const content::ResourceContext* context) {
  net::URLRequest* request = new net::URLRequest(url, resource_dispatcher_host);
  request->set_referrer(referrer.spec());
  resource_dispatcher_host->BeginDownload(
      request,
      save_info,
      true,
      DownloadResourceHandler::OnStartedCallback(),
      render_process_id,
      render_view_id,
      *context);
}

}  // namespace

DownloadManager::DownloadManager(DownloadManagerDelegate* delegate,
                                 DownloadStatusUpdater* status_updater)
    : shutdown_needed_(false),
      browser_context_(NULL),
      next_id_(0),
      file_manager_(NULL),
      status_updater_((status_updater != NULL)
                      ? status_updater->AsWeakPtr()
                      : base::WeakPtr<DownloadStatusUpdater>()),
      delegate_(delegate),
      largest_db_handle_in_history_(DownloadItem::kUninitializedHandle) {
  // NOTE(benjhayden): status_updater may be NULL when using
  // TestingBrowserProcess.
  if (status_updater_.get() != NULL)
    status_updater_->AddDelegate(this);
}

DownloadManager::~DownloadManager() {
  DCHECK(!shutdown_needed_);
  if (status_updater_.get() != NULL)
    status_updater_->RemoveDelegate(this);
}

void DownloadManager::Shutdown() {
  VLOG(20) << __FUNCTION__ << "()"
           << " shutdown_needed_ = " << shutdown_needed_;
  if (!shutdown_needed_)
    return;
  shutdown_needed_ = false;

  FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown());
  // TODO(benjhayden): Consider clearing observers_.

  if (file_manager_) {
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
        NewRunnableMethod(file_manager_,
                          &DownloadFileManager::OnDownloadManagerShutdown,
                          make_scoped_refptr(this)));
  }

  AssertContainersConsistent();

  // Go through all downloads in downloads_.  Dangerous ones we need to
  // remove on disk, and in progress ones we need to cancel.
  for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) {
    DownloadItem* download = *it;

    // Save iterator from potential erases in this set done by called code.
    // Iterators after an erasure point are still valid for lists and
    // associative containers such as sets.
    it++;

    if (download->safety_state() == 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
      // removed from the DownloadManager queues and deleted
      // (specifically, DownloadManager::RemoveDownload only
      // removes and deletes it if it's known to the history service)
      // so the only thing we know after calling this function is that
      // the download was deleted if-and-only-if it was removed
      // from all queues.
      download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
    } else if (download->IsPartialDownload()) {
      download->Cancel(false);
      delegate_->UpdateItemInPersistentStore(download);
    }
  }

  // At this point, all dangerous downloads have had their files removed
  // and all in progress downloads have been cancelled.  We can now delete
  // anything left.

  // Copy downloads_ to separate container so as not to set off checks
  // in DownloadItem destruction.
  DownloadSet downloads_to_delete;
  downloads_to_delete.swap(downloads_);

  in_progress_.clear();
  active_downloads_.clear();
  history_downloads_.clear();
  STLDeleteElements(&downloads_to_delete);

  DCHECK(save_page_downloads_.empty());

  file_manager_ = NULL;
  delegate_->Shutdown();

  shutdown_needed_ = false;
}

void DownloadManager::GetTemporaryDownloads(
    const FilePath& dir_path, DownloadVector* result) {
  DCHECK(result);

  for (DownloadMap::iterator it = history_downloads_.begin();
       it != history_downloads_.end(); ++it) {
    if (it->second->is_temporary() &&
        it->second->full_path().DirName() == dir_path)
      result->push_back(it->second);
  }
}

void DownloadManager::GetAllDownloads(
    const FilePath& dir_path, DownloadVector* result) {
  DCHECK(result);

  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))
      result->push_back(it->second);
  }
}

void DownloadManager::SearchDownloads(const string16& query,
                                      DownloadVector* result) {
  string16 query_lower(base::i18n::ToLower(query));

  for (DownloadMap::iterator it = history_downloads_.begin();
       it != history_downloads_.end(); ++it) {
    DownloadItem* download_item = it->second;

    if (download_item->is_temporary())
      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())
      continue;

    if (download_item->MatchesQuery(query_lower))
      result->push_back(download_item);
  }
}

void DownloadManager::OnPersistentStoreGetNextId(int next_id) {
  DVLOG(1) << __FUNCTION__ << " " << next_id;
  base::AutoLock lock(next_id_lock_);
  // TODO(benjhayden) Delay Profile initialization until here, and set next_id_
  // = next_id. The '+=' works for now because these ids are not yet persisted
  // to the database. GetNextId() can allocate zero or more ids starting from 0,
  // then this callback can increment next_id_, and the items with lower ids
  // won't clash with any other items even though there may be items loaded from
  // the history because items from the history don't have valid ids.
  next_id_ += next_id;
}

DownloadId DownloadManager::GetNextId() {
  // May be called on any thread via the GetNextIdThunk.
  // TODO(benjhayden) If otr, forward to parent DM.
  base::AutoLock lock(next_id_lock_);
  return DownloadId(this, next_id_++);
}

DownloadManager::GetNextIdThunkType DownloadManager::GetNextIdThunk() {
  // TODO(benjhayden) If otr, forward to parent DM.
  return base::Bind(&DownloadManager::GetNextId, this);
}

// Query the history service for information about all persisted downloads.
bool DownloadManager::Init(content::BrowserContext* browser_context) {
  DCHECK(browser_context);
  DCHECK(!shutdown_needed_)  << "DownloadManager already initialized.";
  shutdown_needed_ = true;

  browser_context_ = browser_context;

  // In test mode, there may be no ResourceDispatcherHost.  In this case it's
  // safe to avoid setting |file_manager_| because we only call a small set of
  // functions, none of which need it.
  ResourceDispatcherHost* rdh =
      content::GetContentClient()->browser()->GetResourceDispatcherHost();
  if (rdh) {
    file_manager_ = rdh->download_file_manager();
    DCHECK(file_manager_);
  }

  return true;
}

// We have received a message from DownloadFileManager about a new download.
void DownloadManager::StartDownload(int32 download_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (delegate_->ShouldStartDownload(download_id))
    RestartDownload(download_id);
}

void DownloadManager::CheckForHistoryFilesRemoval() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  for (DownloadMap::iterator it = history_downloads_.begin();
       it != history_downloads_.end(); ++it) {
    CheckForFileRemoval(it->second);
  }
}

void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (download_item->IsComplete() &&
      !download_item->file_externally_removed()) {
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        NewRunnableMethod(this,
                          &DownloadManager::CheckForFileRemovalOnFileThread,
                          download_item->db_handle(),
                          download_item->GetTargetFilePath()));
  }
}

void DownloadManager::CheckForFileRemovalOnFileThread(
    int64 db_handle, const FilePath& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  if (!file_util::PathExists(path)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        NewRunnableMethod(this,
                          &DownloadManager::OnFileRemovalDetected,
                          db_handle));
  }
}

void DownloadManager::OnFileRemovalDetected(int64 db_handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DownloadMap::iterator it = history_downloads_.find(db_handle);
  if (it != history_downloads_.end()) {
    DownloadItem* download_item = it->second;
    download_item->OnDownloadedFileRemoved();
  }
}

void DownloadManager::RestartDownload(
    int32 download_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DownloadItem* download = GetActiveDownloadItem(download_id);
  if (!download)
    return;

  VLOG(20) << __FUNCTION__ << "()"
           << " download = " << download->DebugString(true);

  FilePath suggested_path = download->suggested_path();

  if (download->prompt_user_for_save_location()) {
    // We must ask the user for the place to put the download.
    DownloadRequestHandle request_handle = download->request_handle();
    TabContents* contents = request_handle.GetTabContents();

    // |id_ptr| will be deleted in either FileSelected() or
    // FileSelectionCancelled().
    int32* id_ptr = new int32;
    *id_ptr = download_id;

    delegate_->ChooseDownloadPath(
        contents, suggested_path, reinterpret_cast<void*>(id_ptr));

    FOR_EACH_OBSERVER(Observer, observers_,
                      SelectFileDialogDisplayed(download_id));
  } else {
    // No prompting for download, just continue with the suggested name.
    ContinueDownloadWithPath(download, suggested_path);
  }
}

void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DownloadItem* download = new DownloadItem(this, *info,
                                            browser_context_->IsOffTheRecord());
  int32 download_id = info->download_id;
  DCHECK(!ContainsKey(in_progress_, download_id));

  // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
  CHECK(!ContainsKey(active_downloads_, download_id));
  downloads_.insert(download);
  active_downloads_[download_id] = download;
}

void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
                                               const FilePath& chosen_file) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(download);

  int32 download_id = download->id();

  // NOTE(ahendrickson) Eventually |active_downloads_| will replace
  // |in_progress_|, but we don't want to change the semantics yet.
  DCHECK(!ContainsKey(in_progress_, download_id));
  DCHECK(ContainsKey(downloads_, download));
  DCHECK(ContainsKey(active_downloads_, download_id));

  // Make sure the initial file name is set only once.
  DCHECK(download->full_path().empty());
  download->OnPathDetermined(chosen_file);

  VLOG(20) << __FUNCTION__ << "()"
           << " download = " << download->DebugString(true);

  in_progress_[download_id] = download;
  UpdateDownloadProgress();  // Reflect entry into in_progress_.

  // Rename to intermediate name.
  FilePath download_path;
  if (!delegate_->OverrideIntermediatePath(download, &download_path))
    download_path = download->full_path();

  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableMethod(
          file_manager_, &DownloadFileManager::RenameInProgressDownloadFile,
          download->global_id(), download_path));

  download->Rename(download_path);

  delegate_->AddItemToPersistentStore(download);
}

void DownloadManager::UpdateDownload(int32 download_id, int64 size) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DownloadMap::iterator it = active_downloads_.find(download_id);
  if (it != active_downloads_.end()) {
    DownloadItem* download = it->second;
    if (download->IsInProgress()) {
      download->Update(size);
      UpdateDownloadProgress();  // Reflect size updates.
      delegate_->UpdateItemInPersistentStore(download);
    }
  }
}

void DownloadManager::OnResponseCompleted(int32 download_id,
                                          int64 size,
                                          const std::string& hash) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
           << " size = " << size;
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // If it's not in active_downloads_, that means it was cancelled; just
  // ignore the notification.
  if (active_downloads_.count(download_id) == 0)
    return;

  DownloadItem* download = active_downloads_[download_id];
  download->OnAllDataSaved(size);

  delegate_->OnResponseCompleted(download, hash);

  MaybeCompleteDownload(download);
}

void DownloadManager::AssertQueueStateConsistent(DownloadItem* download) {
  // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
  if (download->state() == 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()));
    return;
  }

  // Should be in downloads_ if we're not REMOVING.
  CHECK(ContainsKey(downloads_, download));

  // Check history_downloads_ consistency.
  if (download->db_handle() != DownloadItem::kUninitializedHandle) {
    CHECK(ContainsKey(history_downloads_, download->db_handle()));
  } else {
    // TODO(rdsmith): Somewhat painful; make sure to disable in
    // release builds after resolution of http://crbug.com/85408.
    for (DownloadMap::iterator it = history_downloads_.begin();
         it != history_downloads_.end(); ++it) {
      CHECK(it->second != download);
    }
  }

  int64 state = download->state();
  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 (DownloadItem::IN_PROGRESS == download->state())
    CHECK(ContainsKey(active_downloads_, download->id()));
}

bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
  // If we don't have all the data, the download is not ready for
  // completion.
  if (!download->all_data_saved())
    return false;

  // If the download is dangerous, but not yet validated, it's not ready for
  // completion.
  if (download->safety_state() == 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)
    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)
    return false;

  return true;
}

void DownloadManager::MaybeCompleteDownload(DownloadItem* download) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  VLOG(20) << __FUNCTION__ << "()" << " download = "
           << download->DebugString(false);

  if (!IsDownloadReadyForCompletion(download))
    return;

  // TODO(rdsmith): DCHECK that we only pass through this point
  // once per download.  The natural way to do this is by a state
  // transition on the DownloadItem.

  // 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()));

  VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
           << download->DebugString(false);

  // Remove the id from in_progress
  in_progress_.erase(download->id());
  UpdateDownloadProgress();  // Reflect removal from in_progress_.

  delegate_->UpdateItemInPersistentStore(download);

  // Finish the download.
  download->OnDownloadCompleting(file_manager_);
}

void DownloadManager::DownloadCompleted(int32 download_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DownloadItem* download = GetDownloadItem(download_id);
  DCHECK(download);
  delegate_->UpdateItemInPersistentStore(download);
  active_downloads_.erase(download_id);
  AssertQueueStateConsistent(download);
}

void DownloadManager::OnDownloadRenamedToFinalName(int download_id,
                                                   const FilePath& full_path,
                                                   int uniquifier) {
  VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
           << " full_path = \"" << full_path.value() << "\""
           << " uniquifier = " << uniquifier;
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DownloadItem* item = GetDownloadItem(download_id);
  if (!item)
    return;

  if (item->safety_state() == DownloadItem::SAFE) {
    DCHECK_EQ(0, uniquifier) << "We should not uniquify SAFE downloads twice";
  }

  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, NewRunnableMethod(
      file_manager_,
      &DownloadFileManager::CompleteDownload,
      item->global_id()));

  if (uniquifier)
    item->set_path_uniquifier(uniquifier);

  item->OnDownloadRenamedToFinalName(full_path);
  delegate_->UpdatePathForItemInPersistentStore(item, full_path);
}

void DownloadManager::CancelDownload(int32 download_id) {
  DownloadItem* download = GetActiveDownload(download_id);
  // A cancel at the right time could remove the download from the
  // |active_downloads_| map before we get here.
  if (!download)
    return;

  download->Cancel(true);
}

void DownloadManager::DownloadCancelledInternal(DownloadItem* download) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  VLOG(20) << __FUNCTION__ << "()"
           << " download = " << download->DebugString(true);

  RemoveFromActiveList(download);
  // This function is called from the DownloadItem, so DI state
  // should already have been updated.
  AssertQueueStateConsistent(download);

  download->OffThreadCancel(file_manager_);
}

void DownloadManager::OnDownloadInterrupted(int32 download_id,
                                            int64 size,
                                            InterruptReason reason) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DownloadItem* download = GetActiveDownload(download_id);
  if (!download)
    return;

  VLOG(20) << __FUNCTION__ << "()"
           << " reason " << InterruptReasonDebugString(reason)
           << " at offset " << download->received_bytes()
           << " size = " << size
           << " download = " << download->DebugString(true);

  RemoveFromActiveList(download);
  download->Interrupted(size, reason);
  download->OffThreadCancel(file_manager_);
}

DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DownloadMap::iterator it = active_downloads_.find(download_id);
  if (it == active_downloads_.end())
    return NULL;

  DownloadItem* download = it->second;

  DCHECK(download);
  DCHECK_EQ(download_id, download->id());

  return download;
}

void DownloadManager::RemoveFromActiveList(DownloadItem* download) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(download);

  // 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());
    UpdateDownloadProgress();  // Reflect removal from in_progress_.
    delegate_->UpdateItemInPersistentStore(download);
  }
}

void DownloadManager::SetDownloadManagerDelegate(
    DownloadManagerDelegate* delegate) {
  delegate_ = delegate;
}

void DownloadManager::UpdateDownloadProgress() {
  delegate_->DownloadProgressUpdated();
}

int DownloadManager::RemoveDownloadItems(
    const DownloadVector& pending_deletes) {
  if (pending_deletes.empty())
    return 0;

  // Delete from internal maps.
  for (DownloadVector::const_iterator it = pending_deletes.begin();
      it != pending_deletes.end();
      ++it) {
    DownloadItem* download = *it;
    DCHECK(download);
    history_downloads_.erase(download->db_handle());
    save_page_downloads_.erase(download->id());
    downloads_.erase(download);
  }

  // Tell observers to refresh their views.
  NotifyModelChanged();

  // Delete the download items themselves.
  const int num_deleted = static_cast<int>(pending_deletes.size());
  STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
  return num_deleted;
}

void DownloadManager::RemoveDownload(int64 download_handle) {
  DownloadMap::iterator it = history_downloads_.find(download_handle);
  if (it == history_downloads_.end())
    return;

  // Make history update.
  DownloadItem* download = it->second;
  delegate_->RemoveItemFromPersistentStore(download);

  // Remove from our tables and delete.
  int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
  DCHECK_EQ(1, downloads_count);
}

int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
                                            const base::Time remove_end) {
  delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);

  // All downloads visible to the user will be in the history,
  // so scan that map.
  DownloadVector pending_deletes;
  for (DownloadMap::const_iterator it = history_downloads_.begin();
      it != history_downloads_.end();
      ++it) {
    DownloadItem* download = it->second;
    if (download->start_time() >= remove_begin &&
        (remove_end.is_null() || download->start_time() < remove_end) &&
        (download->IsComplete() || download->IsCancelled())) {
      AssertQueueStateConsistent(download);
      pending_deletes.push_back(download);
    }
  }
  return RemoveDownloadItems(pending_deletes);
}

int DownloadManager::RemoveDownloads(const base::Time remove_begin) {
  return RemoveDownloadsBetween(remove_begin, base::Time());
}

int DownloadManager::RemoveAllDownloads() {
  download_stats::RecordClearAllSize(history_downloads_.size());
  // The null times make the date range unbounded.
  return RemoveDownloadsBetween(base::Time(), base::Time());
}

// Initiate a download of a specific URL. We send the request to the
// ResourceDispatcherHost, and let it send us responses like a regular
// download.
void DownloadManager::DownloadUrl(const GURL& url,
                                  const GURL& referrer,
                                  const std::string& referrer_charset,
                                  TabContents* tab_contents) {
  DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
                    tab_contents);
}

void DownloadManager::DownloadUrlToFile(const GURL& url,
                                        const GURL& referrer,
                                        const std::string& referrer_charset,
                                        const DownloadSaveInfo& save_info,
                                        TabContents* tab_contents) {
  DCHECK(tab_contents);
  ResourceDispatcherHost* resource_dispatcher_host =
      content::GetContentClient()->browser()->GetResourceDispatcherHost();
  // We send a pointer to content::ResourceContext, instead of the usual
  // reference, so that a copy of the object isn't made.
  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
      NewRunnableFunction(&BeginDownload,
                          url,
                          referrer,
                          save_info,
                          resource_dispatcher_host,
                          tab_contents->GetRenderProcessHost()->id(),
                          tab_contents->render_view_host()->routing_id(),
                          &tab_contents->browser_context()->
                              GetResourceContext()));
}

void DownloadManager::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
  observer->ModelChanged();
}

void DownloadManager::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool DownloadManager::IsDownloadProgressKnown() {
  for (DownloadMap::iterator i = in_progress_.begin();
       i != in_progress_.end(); ++i) {
    if (i->second->total_bytes() <= 0)
      return false;
  }

  return true;
}

int64 DownloadManager::GetInProgressDownloadCount() {
  return in_progress_.size();
}

int64 DownloadManager::GetReceivedDownloadBytes() {
  DCHECK(IsDownloadProgressKnown());
  int64 received_bytes = 0;
  for (DownloadMap::iterator i = in_progress_.begin();
       i != in_progress_.end(); ++i) {
    received_bytes += i->second->received_bytes();
  }
  return received_bytes;
}

int64 DownloadManager::GetTotalDownloadBytes() {
  DCHECK(IsDownloadProgressKnown());
  int64 total_bytes = 0;
  for (DownloadMap::iterator i = in_progress_.begin();
       i != in_progress_.end(); ++i) {
    total_bytes += i->second->total_bytes();
  }
  return total_bytes;
}

void DownloadManager::FileSelected(const FilePath& path, void* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  int32* id_ptr = reinterpret_cast<int32*>(params);
  DCHECK(id_ptr != NULL);
  int32 download_id = *id_ptr;
  delete id_ptr;

  DownloadItem* download = GetActiveDownloadItem(download_id);
  if (!download)
    return;
  VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
            << " download = " << download->DebugString(true);

  if (download->prompt_user_for_save_location())
    last_download_path_ = path.DirName();

  // Make sure the initial file name is set only once.
  ContinueDownloadWithPath(download, path);
}

void DownloadManager::FileSelectionCanceled(void* params) {
  // The user didn't pick a place to save the file, so need to cancel the
  // download that's already in progress to the temporary location.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  int32* id_ptr = reinterpret_cast<int32*>(params);
  DCHECK(id_ptr != NULL);
  int32 download_id = *id_ptr;
  delete id_ptr;

  DownloadItem* download = GetActiveDownloadItem(download_id);
  if (!download)
    return;

  VLOG(20) << __FUNCTION__ << "()"
           << " download = " << download->DebugString(true);

  // TODO(ahendrickson) -- This currently has no effect, as the download is
  // not put on the active list until the file selection is complete.  Need
  // to put it on the active list earlier in the process.
  RemoveFromActiveList(download);

  download->OffThreadCancel(file_manager_);
}

// Operations posted to us from the history service ----------------------------

// The history service has retrieved all download entries. 'entries' contains
// 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
void DownloadManager::OnPersistentStoreQueryComplete(
    std::vector<DownloadPersistentStoreInfo>* entries) {
  // TODO(rdsmith): Remove this and related logic when
  // http://crbug.com/85408 is fixed.
  largest_db_handle_in_history_ = 0;

  for (size_t i = 0; i < entries->size(); ++i) {
    DownloadItem* download = new DownloadItem(this, entries->at(i));
    // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
    CHECK(!ContainsKey(history_downloads_, download->db_handle()));
    downloads_.insert(download);
    history_downloads_[download->db_handle()] = 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();
  }
  NotifyModelChanged();
  CheckForHistoryFilesRemoval();
}

void DownloadManager::AddDownloadItemToHistory(DownloadItem* download,
                                               int64 db_handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/85408
  // is fixed.
  CHECK_NE(DownloadItem::kUninitializedHandle, db_handle);

  download_stats::RecordHistorySize(history_downloads_.size());

  DCHECK(download->db_handle() == DownloadItem::kUninitializedHandle);
  download->set_db_handle(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;

  // Show in the appropriate browser UI.
  // This includes buttons to save or cancel, for a dangerous download.
  ShowDownloadInBrowser(download);

  // Inform interested objects about the new download.
  NotifyModelChanged();
}


void DownloadManager::OnItemAddedToPersistentStore(int32 download_id,
                                                   int64 db_handle) {
  if (save_page_downloads_.count(download_id)) {
    OnSavePageItemAddedToPersistentStore(download_id, db_handle);
  } else if (active_downloads_.count(download_id)) {
    OnDownloadItemAddedToPersistentStore(download_id, db_handle);
  }
  // It's valid that we don't find a matching item, i.e. on shutdown.
}

// Once the new DownloadItem's creation info has been committed to the history
// service, we associate the DownloadItem with the db handle, update our
// 'history_downloads_' map and inform observers.
void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id,
                                                           int64 db_handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DownloadItem* download = GetActiveDownloadItem(download_id);
  if (!download)
    return;

  VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
           << " download_id = " << download_id
           << " download = " << download->DebugString(true);

  // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
  int64 largest_handle = largest_db_handle_in_history_;
  base::debug::Alias(&largest_handle);
  int32 matching_item_download_id
      = (ContainsKey(history_downloads_, db_handle) ?
         history_downloads_[db_handle]->id() : 0);
  base::debug::Alias(&matching_item_download_id);

  CHECK(!ContainsKey(history_downloads_, db_handle));

  AddDownloadItemToHistory(download, db_handle);

  // If the download is still in progress, try to complete it.
  //
  // Otherwise, download has been cancelled or interrupted before we've
  // received the DB handle.  We post one final message to the history
  // service so that it can be properly in sync with the DownloadItem's
  // completion status, and also inform any observers so that they get
  // more than just the start notification.
  if (download->IsInProgress()) {
    MaybeCompleteDownload(download);
  } else {
    // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/85408
    // is fixed.
    CHECK(download->IsCancelled())
        << " download = " << download->DebugString(true);
    in_progress_.erase(download_id);
    active_downloads_.erase(download_id);
    delegate_->UpdateItemInPersistentStore(download);
    download->UpdateObservers();
  }
}

void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
  // The 'contents' may no longer exist if the user closed the tab before we
  // get this start completion event.
  DownloadRequestHandle request_handle = download->request_handle();
  TabContents* content = request_handle.GetTabContents();

  // If the contents no longer exists, we ask the embedder to suggest another
  // tab.
  if (!content)
    content = delegate_->GetAlternativeTabContentsToNotifyForDownload();

  if (content)
    content->OnStartDownload(download);
}

// Clears the last download path, used to initialize "save as" dialogs.
void DownloadManager::ClearLastDownloadPath() {
  last_download_path_ = FilePath();
}

void DownloadManager::NotifyModelChanged() {
  FOR_EACH_OBSERVER(Observer, observers_, ModelChanged());
}

DownloadItem* DownloadManager::GetDownloadItem(int download_id) {
  // The |history_downloads_| map is indexed by the download's db_handle,
  // not its id, so we have to iterate.
  for (DownloadMap::iterator it = history_downloads_.begin();
       it != history_downloads_.end(); ++it) {
    DownloadItem* item = it->second;
    if (item->id() == download_id)
      return item;
  }
  return NULL;
}

DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
  DCHECK(ContainsKey(active_downloads_, download_id));
  DownloadItem* download = active_downloads_[download_id];
  DCHECK(download != NULL);
  return download;
}

// Confirm that everything in all maps is also in |downloads_|, and that
// everything in |downloads_| is also in some other map.
void DownloadManager::AssertContainersConsistent() const {
#if !defined(NDEBUG)
  // Turn everything into sets.
  const DownloadMap* input_maps[] = {&active_downloads_,
                                     &history_downloads_,
                                     &save_page_downloads_};
  DownloadSet active_set, history_set, save_page_set;
  DownloadSet* all_sets[] = {&active_set, &history_set, &save_page_set};
  DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(all_sets));
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
    for (DownloadMap::const_iterator it = input_maps[i]->begin();
         it != input_maps[i]->end(); ++it) {
      all_sets[i]->insert(&*it->second);
    }
  }

  // Check if each set is fully present in downloads, and create a union.
  DownloadSet downloads_union;
  for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
    DownloadSet remainder;
    std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
    std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
                        downloads_.begin(), downloads_.end(),
                        insert_it);
    DCHECK(remainder.empty());
    std::insert_iterator<DownloadSet>
        insert_union(downloads_union, downloads_union.end());
    std::set_union(downloads_union.begin(), downloads_union.end(),
                   all_sets[i]->begin(), all_sets[i]->end(),
                   insert_union);
  }

  // Is everything in downloads_ present in one of the other sets?
  DownloadSet remainder;
  std::insert_iterator<DownloadSet>
      insert_remainder(remainder, remainder.begin());
  std::set_difference(downloads_.begin(), downloads_.end(),
                      downloads_union.begin(), downloads_union.end(),
                      insert_remainder);
  DCHECK(remainder.empty());
#endif
}

void DownloadManager::SavePageDownloadStarted(DownloadItem* download) {
  DCHECK(!ContainsKey(save_page_downloads_, download->id()));
  downloads_.insert(download);
  save_page_downloads_[download->id()] = download;

  // Add this entry to the history service.
  // Additionally, the UI is notified in the callback.
  delegate_->AddItemToPersistentStore(download);
}

// SavePackage will call SavePageDownloadFinished upon completion/cancellation.
// The history callback will call OnSavePageItemAddedToPersistentStore.
// If the download finishes before the history callback,
// OnSavePageItemAddedToPersistentStore calls SavePageDownloadFinished, ensuring
// that the history event is update regardless of the order in which these two
// events complete.
// If something removes the download item from the download manager (Remove,
// Shutdown) the result will be that the SavePage system will not be able to
// properly update the download item (which no longer exists) or the download
// history, but the action will complete properly anyway.  This may lead to the
// history entry being wrong on a reload of chrome (specifically in the case of
// Initiation -> History Callback -> Removal -> Completion), but there's no way
// to solve that without canceling on Remove (which would then update the DB).

void DownloadManager::OnSavePageItemAddedToPersistentStore(int32 download_id,
                                                           int64 db_handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DownloadMap::const_iterator it = save_page_downloads_.find(download_id);
  // This can happen if the download manager is shutting down and all maps
  // have been cleared.
  if (it == save_page_downloads_.end())
    return;

  DownloadItem* download = it->second;
  if (!download) {
    NOTREACHED();
    return;
  }

  // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
  int64 largest_handle = largest_db_handle_in_history_;
  base::debug::Alias(&largest_handle);
  CHECK(!ContainsKey(history_downloads_, db_handle));

  AddDownloadItemToHistory(download, db_handle);

  // Finalize this download if it finished before the history callback.
  if (!download->IsInProgress())
    SavePageDownloadFinished(download);
}

void DownloadManager::SavePageDownloadFinished(DownloadItem* download) {
  if (download->db_handle() != DownloadItem::kUninitializedHandle) {
    delegate_->UpdateItemInPersistentStore(download);
    DCHECK(ContainsKey(save_page_downloads_, download->id()));
    save_page_downloads_.erase(download->id());

    if (download->IsComplete())
      NotificationService::current()->Notify(
          content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
          content::Source<DownloadManager>(this),
          content::Details<DownloadItem>(download));
  }
}

void DownloadManager::MarkDownloadOpened(DownloadItem* download) {
  delegate_->UpdateItemInPersistentStore(download);
  int num_unopened = 0;
  for (DownloadMap::iterator it = history_downloads_.begin();
       it != history_downloads_.end(); ++it) {
    if (it->second->IsComplete() && !it->second->opened())
      ++num_unopened;
  }
  download_stats::RecordOpensOutstanding(num_unopened);
}
