// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/history/expire_history_backend.h"

#include <algorithm>
#include <functional>
#include <limits>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/bookmarks/bookmark_service.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/archived_database.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/thumbnail_database.h"

using base::Time;
using base::TimeDelta;

namespace history {

namespace {

// The number of days by which the expiration threshold is advanced for items
// that we want to expire early, such as those of AUTO_SUBFRAME transition type.
//
// Early expiration stuff is kept around only for edge cases, as subframes
// don't appear in history and the vast majority of them are ads anyway. The
// main use case for these is if you're on a site with links to different
// frames, you'll be able to see those links as visited, and we'll also be
// able to get redirect information for those URLs.
//
// But since these uses are most valuable when you're actually on the site,
// and because these can take up the bulk of your history, we get a lot of
// space savings by deleting them quickly.
const int kEarlyExpirationAdvanceDays = 3;

// Reads all types of visits starting from beginning of time to the given end
// time. This is the most general reader.
class AllVisitsReader : public ExpiringVisitsReader {
 public:
  virtual bool Read(Time end_time, HistoryDatabase* db,
                    VisitVector* visits, int max_visits) const OVERRIDE {
    DCHECK(db) << "must have a database to operate upon";
    DCHECK(visits) << "visit vector has to exist in order to populate it";

    db->GetAllVisitsInRange(Time(), end_time, max_visits, visits);
    // When we got the maximum number of visits we asked for, we say there could
    // be additional things to expire now.
    return static_cast<int>(visits->size()) == max_visits;
  }
};

// Reads only AUTO_SUBFRAME visits, within a computed range. The range is
// computed as follows:
// * |begin_time| is read from the meta table. This value is updated whenever
//   there are no more additional visits to expire by this reader.
// * |end_time| is advanced forward by a constant (kEarlyExpirationAdvanceDay),
//   but not past the current time.
class AutoSubframeVisitsReader : public ExpiringVisitsReader {
 public:
  virtual bool Read(Time end_time, HistoryDatabase* db,
                    VisitVector* visits, int max_visits) const OVERRIDE {
    DCHECK(db) << "must have a database to operate upon";
    DCHECK(visits) << "visit vector has to exist in order to populate it";

    Time begin_time = db->GetEarlyExpirationThreshold();
    // Advance |end_time| to expire early.
    Time early_end_time = end_time +
        TimeDelta::FromDays(kEarlyExpirationAdvanceDays);

    // We don't want to set the early expiration threshold to a time in the
    // future.
    Time now = Time::Now();
    if (early_end_time > now)
      early_end_time = now;

    db->GetVisitsInRangeForTransition(begin_time, early_end_time,
                                      max_visits,
                                      content::PAGE_TRANSITION_AUTO_SUBFRAME,
                                      visits);
    bool more = static_cast<int>(visits->size()) == max_visits;
    if (!more)
      db->UpdateEarlyExpirationThreshold(early_end_time);

    return more;
  }
};

// Returns true if this visit is worth archiving. Otherwise, this visit is not
// worth saving (for example, subframe navigations and redirects) and we can
// just delete it when it gets old.
bool ShouldArchiveVisit(const VisitRow& visit) {
  int no_qualifier = content::PageTransitionStripQualifier(visit.transition);

  // These types of transitions are always "important" and the user will want
  // to see them.
  if (no_qualifier == content::PAGE_TRANSITION_TYPED ||
      no_qualifier == content::PAGE_TRANSITION_AUTO_BOOKMARK ||
      no_qualifier == content::PAGE_TRANSITION_AUTO_TOPLEVEL)
    return true;

  // Only archive these "less important" transitions when they were the final
  // navigation and not part of a redirect chain.
  if ((no_qualifier == content::PAGE_TRANSITION_LINK ||
       no_qualifier == content::PAGE_TRANSITION_FORM_SUBMIT ||
       no_qualifier == content::PAGE_TRANSITION_KEYWORD ||
       no_qualifier == content::PAGE_TRANSITION_GENERATED) &&
      visit.transition & content::PAGE_TRANSITION_CHAIN_END)
    return true;

  // The transition types we ignore are AUTO_SUBFRAME and MANUAL_SUBFRAME.
  return false;
}

// The number of visits we will expire very time we check for old items. This
// Prevents us from doing too much work any given time.
const int kNumExpirePerIteration = 32;

// The number of seconds between checking for items that should be expired when
// we think there might be more items to expire. This timeout is used when the
// last expiration found at least kNumExpirePerIteration and we want to check
// again "soon."
const int kExpirationDelaySec = 30;

// The number of minutes between checking, as with kExpirationDelaySec, but
// when we didn't find enough things to expire last time. If there was no
// history to expire last iteration, it's likely there is nothing next
// iteration, so we want to wait longer before checking to avoid wasting CPU.
const int kExpirationEmptyDelayMin = 5;

}  // namespace

struct ExpireHistoryBackend::DeleteDependencies {
  // The time range affected. These can be is_null() to be unbounded in one
  // or both directions.
  base::Time begin_time, end_time;

  // ----- Filled by DeleteVisitRelatedInfo or manually if a function doesn't
  //       call that function. -----

  // The unique URL rows affected by this delete.
  std::map<URLID, URLRow> affected_urls;

  // ----- Filled by DeleteOneURL -----

  // The URLs deleted during this operation.
  URLRows deleted_urls;

  // The list of all favicon IDs that the affected URLs had. Favicons will be
  // shared between all URLs with the same favicon, so this is the set of IDs
  // that we will need to check when the delete operations are complete.
  std::set<chrome::FaviconID> affected_favicons;

  // The list of all favicon urls that were actually deleted from the thumbnail
  // db.
  std::set<GURL> expired_favicons;
};

ExpireHistoryBackend::ExpireHistoryBackend(
    BroadcastNotificationDelegate* delegate,
    BookmarkService* bookmark_service)
    : delegate_(delegate),
      main_db_(NULL),
      archived_db_(NULL),
      thumb_db_(NULL),
      weak_factory_(this),
      bookmark_service_(bookmark_service) {
}

ExpireHistoryBackend::~ExpireHistoryBackend() {
}

void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db,
                                        ArchivedDatabase* archived_db,
                                        ThumbnailDatabase* thumb_db) {
  main_db_ = main_db;
  archived_db_ = archived_db;
  thumb_db_ = thumb_db;
}

void ExpireHistoryBackend::DeleteURL(const GURL& url) {
  DeleteURLs(std::vector<GURL>(1, url));
}

void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) {
  if (!main_db_)
    return;

  DeleteDependencies dependencies;
  for (std::vector<GURL>::const_iterator url = urls.begin(); url != urls.end();
       ++url) {
    URLRow url_row;
    if (!main_db_->GetRowForURL(*url, &url_row))
      continue;  // Nothing to delete.

    // Collect all the visits and delete them. Note that we don't give
    // up if there are no visits, since the URL could still have an
    // entry that we should delete.  TODO(brettw): bug 1171148: We
    // should also delete from the archived DB.
    VisitVector visits;
    main_db_->GetVisitsForURL(url_row.id(), &visits);

    DeleteVisitRelatedInfo(visits, &dependencies);

    // We skip ExpireURLsForVisits (since we are deleting from the
    // URL, and not starting with visits in a given time range). We
    // therefore need to call the deletion and favicon update
    // functions manually.

    BookmarkService* bookmark_service = GetBookmarkService();
    bool is_bookmarked =
        (bookmark_service && bookmark_service->IsBookmarked(*url));

    DeleteOneURL(url_row, is_bookmarked, &dependencies);
  }

  DeleteFaviconsIfPossible(dependencies.affected_favicons,
                           &dependencies.expired_favicons);

  BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED);
}

void ExpireHistoryBackend::ExpireHistoryBetween(
    const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) {
  if (!main_db_)
    return;

  // Find the affected visits and delete them.
  // TODO(brettw): bug 1171164: We should query the archived database here, too.
  VisitVector visits;
  main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits);
  if (!restrict_urls.empty()) {
    std::set<URLID> url_ids;
    for (std::set<GURL>::const_iterator url = restrict_urls.begin();
        url != restrict_urls.end(); ++url)
      url_ids.insert(main_db_->GetRowForURL(*url, NULL));
    VisitVector all_visits;
    all_visits.swap(visits);
    for (VisitVector::iterator visit = all_visits.begin();
         visit != all_visits.end(); ++visit) {
      if (url_ids.find(visit->url_id) != url_ids.end())
        visits.push_back(*visit);
    }
  }
  ExpireVisits(visits);
}

void ExpireHistoryBackend::ExpireHistoryForTimes(
    const std::vector<base::Time>& times) {
  // |times| must be in reverse chronological order and have no
  // duplicates, i.e. each member must be earlier than the one before
  // it.
  DCHECK(
      std::adjacent_find(
          times.begin(), times.end(), std::less_equal<base::Time>()) ==
      times.end());

  if (!main_db_)
    return;

  // Find the affected visits and delete them.
  // TODO(brettw): bug 1171164: We should query the archived database here, too.
  VisitVector visits;
  main_db_->GetVisitsForTimes(times, &visits);
  ExpireVisits(visits);
}

void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) {
  if (visits.empty())
    return;

  DeleteDependencies dependencies;
  DeleteVisitRelatedInfo(visits, &dependencies);

  // Delete or update the URLs affected. We want to update the visit counts
  // since this is called by the user who wants to delete their recent history,
  // and we don't want to leave any evidence.
  ExpireURLsForVisits(visits, &dependencies);
  DeleteFaviconsIfPossible(dependencies.affected_favicons,
                           &dependencies.expired_favicons);

  // An is_null begin time means that all history should be deleted.
  BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED);

  // Pick up any bits possibly left over.
  ParanoidExpireHistory();
}

void ExpireHistoryBackend::ArchiveHistoryBefore(Time end_time) {
  if (!main_db_)
    return;

  // Archive as much history as possible before the given date.
  ArchiveSomeOldHistory(end_time, GetAllVisitsReader(),
                        std::numeric_limits<int>::max());
  ParanoidExpireHistory();
}

void ExpireHistoryBackend::InitWorkQueue() {
  DCHECK(work_queue_.empty()) << "queue has to be empty prior to init";

  for (size_t i = 0; i < readers_.size(); i++)
    work_queue_.push(readers_[i]);
}

const ExpiringVisitsReader* ExpireHistoryBackend::GetAllVisitsReader() {
  if (!all_visits_reader_)
    all_visits_reader_.reset(new AllVisitsReader());
  return all_visits_reader_.get();
}

const ExpiringVisitsReader*
    ExpireHistoryBackend::GetAutoSubframeVisitsReader() {
  if (!auto_subframe_visits_reader_)
    auto_subframe_visits_reader_.reset(new AutoSubframeVisitsReader());
  return auto_subframe_visits_reader_.get();
}

void ExpireHistoryBackend::StartArchivingOldStuff(
    TimeDelta expiration_threshold) {
  expiration_threshold_ = expiration_threshold;

  // Remove all readers, just in case this was method was called before.
  readers_.clear();
  // For now, we explicitly add all known readers. If we come up with more
  // reader types (in case we want to expire different types of visits in
  // different ways), we can make it be populated by creator/owner of
  // ExpireHistoryBackend.
  readers_.push_back(GetAllVisitsReader());
  readers_.push_back(GetAutoSubframeVisitsReader());

  // Initialize the queue with all tasks for the first set of iterations.
  InitWorkQueue();
  ScheduleArchive();
}

void ExpireHistoryBackend::DeleteFaviconsIfPossible(
    const std::set<chrome::FaviconID>& favicon_set,
    std::set<GURL>* expired_favicons) {
  if (!thumb_db_)
    return;

  for (std::set<chrome::FaviconID>::const_iterator i = favicon_set.begin();
       i != favicon_set.end(); ++i) {
    if (!thumb_db_->HasMappingFor(*i)) {
      GURL icon_url;
      chrome::IconType icon_type;
      if (thumb_db_->GetFaviconHeader(*i,
                                      &icon_url,
                                      &icon_type) &&
          thumb_db_->DeleteFavicon(*i)) {
        expired_favicons->insert(icon_url);
      }
    }
  }
}

void ExpireHistoryBackend::BroadcastDeleteNotifications(
    DeleteDependencies* dependencies, DeletionType type) {
  if (!dependencies->deleted_urls.empty()) {
    // Broadcast the URL deleted notification. Note that we also broadcast when
    // we were requested to delete everything even if that was a NOP, since
    // some components care to know when history is deleted (it's up to them to
    // determine if they care whether anything was deleted).
    URLsDeletedDetails* deleted_details = new URLsDeletedDetails;
    deleted_details->all_history = false;
    deleted_details->archived = (type == DELETION_ARCHIVED);
    deleted_details->rows = dependencies->deleted_urls;
    deleted_details->favicon_urls = dependencies->expired_favicons;
    delegate_->NotifySyncURLsDeleted(false,
                                     deleted_details->archived,
                                     &deleted_details->rows);
    delegate_->BroadcastNotifications(
        chrome::NOTIFICATION_HISTORY_URLS_DELETED, deleted_details);
  }
}

void ExpireHistoryBackend::DeleteVisitRelatedInfo(
    const VisitVector& visits,
    DeleteDependencies* dependencies) {
  for (size_t i = 0; i < visits.size(); i++) {
    // Delete the visit itself.
    main_db_->DeleteVisit(visits[i]);

    // Add the URL row to the affected URL list.
    std::map<URLID, URLRow>::const_iterator found =
        dependencies->affected_urls.find(visits[i].url_id);
    if (found == dependencies->affected_urls.end()) {
      URLRow row;
      if (!main_db_->GetURLRow(visits[i].url_id, &row))
        continue;
      dependencies->affected_urls[visits[i].url_id] = row;
    }
  }
}

void ExpireHistoryBackend::DeleteOneURL(
    const URLRow& url_row,
    bool is_bookmarked,
    DeleteDependencies* dependencies) {
  main_db_->DeleteSegmentForURL(url_row.id());

  if (!is_bookmarked) {
    dependencies->deleted_urls.push_back(url_row);

    // Delete stuff that references this URL.
    if (thumb_db_) {
      // Collect shared information.
      std::vector<IconMapping> icon_mappings;
      if (thumb_db_->GetIconMappingsForPageURL(url_row.url(), &icon_mappings)) {
        for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
             m != icon_mappings.end(); ++m) {
          dependencies->affected_favicons.insert(m->icon_id);
        }
        // Delete the mapping entries for the url.
        thumb_db_->DeleteIconMappings(url_row.url());
      }
    }
    // Last, delete the URL entry.
    main_db_->DeleteURLRow(url_row.id());
  }
}

URLID ExpireHistoryBackend::ArchiveOneURL(const URLRow& url_row) {
  if (!archived_db_)
    return 0;

  // See if this URL is present in the archived database already. Note that
  // we must look up by ID since the URL ID will be different.
  URLRow archived_row;
  if (archived_db_->GetRowForURL(url_row.url(), &archived_row)) {
    // TODO(sky): bug 1168470, need to archive past search terms.
    // TODO(brettw): should be copy the visit counts over? This will mean that
    // the main DB's visit counts are only for the last 3 months rather than
    // accumulative.
    archived_row.set_last_visit(url_row.last_visit());
    archived_db_->UpdateURLRow(archived_row.id(), archived_row);
    return archived_row.id();
  }

  // This row is not in the archived DB, add it.
  return archived_db_->AddURL(url_row);
}

namespace {

struct ChangedURL {
  ChangedURL() : visit_count(0), typed_count(0) {}
  int visit_count;
  int typed_count;
};

}  // namespace

void ExpireHistoryBackend::ExpireURLsForVisits(
    const VisitVector& visits,
    DeleteDependencies* dependencies) {
  // First find all unique URLs and the number of visits we're deleting for
  // each one.
  std::map<URLID, ChangedURL> changed_urls;
  for (size_t i = 0; i < visits.size(); i++) {
    ChangedURL& cur = changed_urls[visits[i].url_id];
    // NOTE: This code must stay in sync with HistoryBackend::AddPageVisit().
    // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as
    // typed, which would help eliminate the need for this code (we still would
    // need to handle RELOAD transitions specially, though).
    content::PageTransition transition =
        content::PageTransitionStripQualifier(visits[i].transition);
    if (transition != content::PAGE_TRANSITION_RELOAD)
      cur.visit_count++;
    if ((transition == content::PAGE_TRANSITION_TYPED &&
        !content::PageTransitionIsRedirect(visits[i].transition)) ||
        transition == content::PAGE_TRANSITION_KEYWORD_GENERATED)
      cur.typed_count++;
  }

  // Check each unique URL with deleted visits.
  BookmarkService* bookmark_service = GetBookmarkService();
  for (std::map<URLID, ChangedURL>::const_iterator i = changed_urls.begin();
       i != changed_urls.end(); ++i) {
    // The unique URL rows should already be filled into the dependencies.
    URLRow& url_row = dependencies->affected_urls[i->first];
    if (!url_row.id())
      continue;  // URL row doesn't exist in the database.

    // Check if there are any other visits for this URL and update the time
    // (the time change may not actually be synced to disk below when we're
    // archiving).
    VisitRow last_visit;
    if (main_db_->GetMostRecentVisitForURL(url_row.id(), &last_visit))
      url_row.set_last_visit(last_visit.visit_time);
    else
      url_row.set_last_visit(Time());

    // Don't delete URLs with visits still in the DB, or bookmarked.
    bool is_bookmarked =
        (bookmark_service && bookmark_service->IsBookmarked(url_row.url()));
    if (!is_bookmarked && url_row.last_visit().is_null()) {
      // Not bookmarked and no more visits. Nuke the url.
      DeleteOneURL(url_row, is_bookmarked, dependencies);
    } else {
      // NOTE: The calls to std::max() below are a backstop, but they should
      // never actually be needed unless the database is corrupt (I think).
      url_row.set_visit_count(
          std::max(0, url_row.visit_count() - i->second.visit_count));
      url_row.set_typed_count(
          std::max(0, url_row.typed_count() - i->second.typed_count));

      // Update the db with the new details.
      main_db_->UpdateURLRow(url_row.id(), url_row);
    }
  }
}

void ExpireHistoryBackend::ArchiveURLsAndVisits(
    const VisitVector& visits,
    DeleteDependencies* dependencies) {
  if (!archived_db_ || !main_db_)
    return;

  // Make sure all unique URL rows are added to the dependency list and the
  // archived database. We will also keep the mapping between the main DB URLID
  // and the archived one.
  std::map<URLID, URLID> main_id_to_archived_id;
  for (size_t i = 0; i < visits.size(); i++) {
    std::map<URLID, URLRow>::const_iterator found =
      dependencies->affected_urls.find(visits[i].url_id);
    if (found == dependencies->affected_urls.end()) {
      // Unique URL encountered, archive it.
      URLRow row;  // Row in the main DB.
      URLID archived_id;  // ID in the archived DB.
      if (!main_db_->GetURLRow(visits[i].url_id, &row) ||
          !(archived_id = ArchiveOneURL(row))) {
        // Failure archiving, skip this one.
        continue;
      }

      // Only add URL to the dependency list once we know we successfully
      // archived it.
      main_id_to_archived_id[row.id()] = archived_id;
      dependencies->affected_urls[row.id()] = row;
    }
  }

  // Retrieve the sources for all the archived visits before archiving.
  // The returned visit_sources vector should contain the source for each visit
  // from visits at the same index.
  VisitSourceMap visit_sources;
  main_db_->GetVisitsSource(visits, &visit_sources);

  // Now archive the visits since we know the URL ID to make them reference.
  // The source visit list should still reference the visits in the main DB, but
  // we will update it to reflect only the visits that were successfully
  // archived.
  for (size_t i = 0; i < visits.size(); i++) {
    // Construct the visit that we will add to the archived database. We do
    // not store referring visits since we delete many of the visits when
    // archiving.
    VisitRow cur_visit(visits[i]);
    cur_visit.url_id = main_id_to_archived_id[cur_visit.url_id];
    cur_visit.referring_visit = 0;
    VisitSourceMap::iterator iter = visit_sources.find(visits[i].visit_id);
    archived_db_->AddVisit(
        &cur_visit,
        iter == visit_sources.end() ? SOURCE_BROWSED : iter->second);
    // Ignore failures, we will delete it from the main DB no matter what.
  }
}

void ExpireHistoryBackend::ScheduleArchive() {
  TimeDelta delay;
  if (work_queue_.empty()) {
    // If work queue is empty, reset the work queue to contain all tasks and
    // schedule next iteration after a longer delay.
    InitWorkQueue();
    delay = TimeDelta::FromMinutes(kExpirationEmptyDelayMin);
  } else {
    delay = TimeDelta::FromSeconds(kExpirationDelaySec);
  }

  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&ExpireHistoryBackend::DoArchiveIteration,
                 weak_factory_.GetWeakPtr()),
      delay);
}

void ExpireHistoryBackend::DoArchiveIteration() {
  DCHECK(!work_queue_.empty()) << "queue has to be non-empty";

  const ExpiringVisitsReader* reader = work_queue_.front();
  bool more_to_expire = ArchiveSomeOldHistory(GetCurrentArchiveTime(), reader,
                                              kNumExpirePerIteration);

  work_queue_.pop();
  // If there are more items to expire, add the reader back to the queue, thus
  // creating a new task for future iterations.
  if (more_to_expire)
    work_queue_.push(reader);

  ScheduleArchive();
}

bool ExpireHistoryBackend::ArchiveSomeOldHistory(
    base::Time end_time,
    const ExpiringVisitsReader* reader,
    int max_visits) {
  if (!main_db_)
    return false;

  // Add an extra time unit to given end time, because
  // GetAllVisitsInRange, et al. queries' end value is non-inclusive.
  Time effective_end_time =
      Time::FromInternalValue(end_time.ToInternalValue() + 1);

  VisitVector affected_visits;
  bool more_to_expire = reader->Read(effective_end_time, main_db_,
                                     &affected_visits, max_visits);

  // Some visits we'll delete while others we'll archive.
  VisitVector deleted_visits, archived_visits;
  for (size_t i = 0; i < affected_visits.size(); i++) {
    if (ShouldArchiveVisit(affected_visits[i]))
      archived_visits.push_back(affected_visits[i]);
    else
      deleted_visits.push_back(affected_visits[i]);
  }

  // Do the actual archiving.
  DeleteDependencies archived_dependencies;
  ArchiveURLsAndVisits(archived_visits, &archived_dependencies);
  DeleteVisitRelatedInfo(archived_visits, &archived_dependencies);

  DeleteDependencies deleted_dependencies;
  DeleteVisitRelatedInfo(deleted_visits, &deleted_dependencies);

  // This will remove or archive all the affected URLs. Must do the deleting
  // cleanup before archiving so the delete dependencies structure references
  // only those URLs that were actually deleted instead of having some visits
  // archived and then the rest deleted.
  ExpireURLsForVisits(deleted_visits, &deleted_dependencies);
  ExpireURLsForVisits(archived_visits, &archived_dependencies);

  // Create a union of all affected favicons (we don't store favicons for
  // archived URLs) and delete them.
  std::set<chrome::FaviconID> affected_favicons(
      archived_dependencies.affected_favicons);
  for (std::set<chrome::FaviconID>::const_iterator i =
           deleted_dependencies.affected_favicons.begin();
       i != deleted_dependencies.affected_favicons.end(); ++i) {
    affected_favicons.insert(*i);
  }
  DeleteFaviconsIfPossible(affected_favicons,
                           &deleted_dependencies.expired_favicons);

  // Send notifications for the stuff that was deleted. These won't normally be
  // in history views since they were subframes, but they will be in the visited
  // link system, which needs to be updated now. This function is smart enough
  // to not do anything if nothing was deleted.
  BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED);

  return more_to_expire;
}

void ExpireHistoryBackend::ParanoidExpireHistory() {
  // TODO(brettw): Bug 1067331: write this to clean up any errors.
}

BookmarkService* ExpireHistoryBackend::GetBookmarkService() {
  // We use the bookmark service to determine if a URL is bookmarked. The
  // bookmark service is loaded on a separate thread and may not be done by the
  // time we get here. We therefor block until the bookmarks have finished
  // loading.
  if (bookmark_service_)
    bookmark_service_->BlockTillLoaded();
  return bookmark_service_;
}

}  // namespace history
