// 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.

// The history system runs on a background thread so that potentially slow
// database operations don't delay the browser. This backend processing is
// represented by HistoryBackend. The HistoryService's job is to dispatch to
// that thread.
//
// Main thread                       History thread
// -----------                       --------------
// HistoryService <----------------> HistoryBackend
//                                   -> HistoryDatabase
//                                      -> SQLite connection to History
//                                   -> ThumbnailDatabase
//                                      -> SQLite connection to Thumbnails
//                                         (and favicons)

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

#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/download_row.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/in_memory_history_backend.h"
#include "chrome/browser/history/in_memory_url_index.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/history/visit_database.h"
#include "chrome/browser/history/visit_filter.h"
#include "chrome/browser/history/web_history_service.h"
#include "chrome/browser/history/web_history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/importer/imported_favicon_usage.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/history/core/browser/history_client.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/in_memory_database.h"
#include "components/history/core/browser/keyword_search_term.h"
#include "components/history/core/common/thumbnail_score.h"
#include "components/visitedlink/browser/visitedlink_master.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/notification_service.h"
#include "sync/api/sync_error_factory.h"
#include "third_party/skia/include/core/SkBitmap.h"

using base::Time;
using history::HistoryBackend;
using history::KeywordID;

namespace {

static const char* kHistoryThreadName = "Chrome_HistoryThread";

void RunWithFaviconResults(
    const favicon_base::FaviconResultsCallback& callback,
    std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) {
  callback.Run(*bitmap_results);
}

void RunWithFaviconResult(
    const favicon_base::FaviconRawBitmapCallback& callback,
    favicon_base::FaviconRawBitmapResult* bitmap_result) {
  callback.Run(*bitmap_result);
}

void RunWithQueryURLResult(const HistoryService::QueryURLCallback& callback,
                           const history::QueryURLResult* result) {
  callback.Run(result->success, result->row, result->visits);
}

void RunWithVisibleVisitCountToHostResult(
    const HistoryService::GetVisibleVisitCountToHostCallback& callback,
    const history::VisibleVisitCountToHostResult* result) {
  callback.Run(result->success, result->count, result->first_visit);
}

// Extract history::URLRows into GURLs for VisitedLinkMaster.
class URLIteratorFromURLRows
    : public visitedlink::VisitedLinkMaster::URLIterator {
 public:
  explicit URLIteratorFromURLRows(const history::URLRows& url_rows)
      : itr_(url_rows.begin()),
        end_(url_rows.end()) {
  }

  const GURL& NextURL() override { return (itr_++)->url(); }

  bool HasNextURL() const override { return itr_ != end_; }

 private:
  history::URLRows::const_iterator itr_;
  history::URLRows::const_iterator end_;

  DISALLOW_COPY_AND_ASSIGN(URLIteratorFromURLRows);
};

// Callback from WebHistoryService::ExpireWebHistory().
void ExpireWebHistoryComplete(bool success) {
  // Ignore the result.
  //
  // TODO(davidben): ExpireLocalAndRemoteHistoryBetween callback should not fire
  // until this completes.
}

}  // namespace

// Sends messages from the backend to us on the main thread. This must be a
// separate class from the history service so that it can hold a reference to
// the history service (otherwise we would have to manually AddRef and
// Release when the Backend has a reference to us).
class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
 public:
  BackendDelegate(
      const base::WeakPtr<HistoryService>& history_service,
      const scoped_refptr<base::SequencedTaskRunner>& service_task_runner,
      Profile* profile)
      : history_service_(history_service),
        service_task_runner_(service_task_runner),
        profile_(profile) {
  }

  void NotifyProfileError(sql::InitStatus init_status) override {
    // Send to the history service on the main thread.
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&HistoryService::NotifyProfileError, history_service_,
                   init_status));
  }

  void SetInMemoryBackend(
      scoped_ptr<history::InMemoryHistoryBackend> backend) override {
    // Send the backend to the history service on the main thread.
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&HistoryService::SetInMemoryBackend, history_service_,
                   base::Passed(&backend)));
  }

  void NotifyAddVisit(const history::BriefVisitInfo& info) override {
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&HistoryService::NotifyAddVisit, history_service_, info));
  }

  void NotifyFaviconChanged(const std::set<GURL>& urls) override {
    // Send the notification to the history service on the main thread.
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(
            &HistoryService::NotifyFaviconChanged, history_service_, urls));
  }

  void NotifyURLVisited(ui::PageTransition transition,
                        const history::URLRow& row,
                        const history::RedirectList& redirects,
                        base::Time visit_time) override {
    service_task_runner_->PostTask(FROM_HERE,
                                   base::Bind(&HistoryService::NotifyURLVisited,
                                              history_service_,
                                              transition,
                                              row,
                                              redirects,
                                              visit_time));
  }

  void BroadcastNotifications(
      int type,
      scoped_ptr<history::HistoryDetails> details) override {
    // Send the notification on the history thread.
    if (content::NotificationService::current()) {
      content::Details<history::HistoryDetails> det(details.get());
      content::NotificationService::current()->Notify(
          type, content::Source<Profile>(profile_), det);
    }
    // Send the notification to the history service on the main thread.
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&HistoryService::BroadcastNotificationsHelper,
                   history_service_, type, base::Passed(&details)));
  }

  void DBLoaded() override {
    service_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&HistoryService::OnDBLoaded, history_service_));
  }

 private:
  const base::WeakPtr<HistoryService> history_service_;
  const scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
  Profile* const profile_;
};

// The history thread is intentionally not a BrowserThread because the
// sync integration unit tests depend on being able to create more than one
// history thread.
HistoryService::HistoryService()
    : thread_(new base::Thread(kHistoryThreadName)),
      history_client_(NULL),
      profile_(NULL),
      backend_loaded_(false),
      no_db_(false),
      weak_ptr_factory_(this) {
}

HistoryService::HistoryService(history::HistoryClient* client, Profile* profile)
    : thread_(new base::Thread(kHistoryThreadName)),
      history_client_(client),
      profile_(profile),
      visitedlink_master_(new visitedlink::VisitedLinkMaster(
          profile, this, true)),
      backend_loaded_(false),
      no_db_(false),
      weak_ptr_factory_(this) {
  DCHECK(profile_);
  registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
                 content::Source<Profile>(profile_));
}

HistoryService::~HistoryService() {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Shutdown the backend. This does nothing if Cleanup was already invoked.
  Cleanup();
}

bool HistoryService::BackendLoaded() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return backend_loaded_;
}

void HistoryService::ClearCachedDataForContextID(
    history::ContextID context_id) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::ClearCachedDataForContextID, context_id);
}

history::URLDatabase* HistoryService::InMemoryDatabase() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return in_memory_backend_ ? in_memory_backend_->db() : NULL;
}

bool HistoryService::GetTypedCountForURL(const GURL& url, int* typed_count) {
  DCHECK(thread_checker_.CalledOnValidThread());
  history::URLRow url_row;
  if (!GetRowForURL(url, &url_row))
    return false;
  *typed_count = url_row.typed_count();
  return true;
}

bool HistoryService::GetLastVisitTimeForURL(const GURL& url,
                                            base::Time* last_visit) {
  DCHECK(thread_checker_.CalledOnValidThread());
  history::URLRow url_row;
  if (!GetRowForURL(url, &url_row))
    return false;
  *last_visit = url_row.last_visit();
  return true;
}

bool HistoryService::GetVisitCountForURL(const GURL& url, int* visit_count) {
  DCHECK(thread_checker_.CalledOnValidThread());
  history::URLRow url_row;
  if (!GetRowForURL(url, &url_row))
    return false;
  *visit_count = url_row.visit_count();
  return true;
}

history::TypedUrlSyncableService* HistoryService::GetTypedUrlSyncableService()
    const {
  return history_backend_->GetTypedUrlSyncableService();
}

void HistoryService::Shutdown() {
  DCHECK(thread_checker_.CalledOnValidThread());
  Cleanup();
}

void HistoryService::SetKeywordSearchTermsForURL(const GURL& url,
                                                 KeywordID keyword_id,
                                                 const base::string16& term) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_UI,
                    &HistoryBackend::SetKeywordSearchTermsForURL,
                    url, keyword_id, term);
}

void HistoryService::DeleteAllSearchTermsForKeyword(KeywordID keyword_id) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  if (in_memory_backend_)
    in_memory_backend_->DeleteAllSearchTermsForKeyword(keyword_id);

  ScheduleAndForget(PRIORITY_UI,
                    &HistoryBackend::DeleteAllSearchTermsForKeyword,
                    keyword_id);
}

void HistoryService::DeleteKeywordSearchTermForURL(const GURL& url) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteKeywordSearchTermForURL,
                    url);
}

void HistoryService::DeleteMatchingURLsForKeyword(KeywordID keyword_id,
                                                  const base::string16& term) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteMatchingURLsForKeyword,
                    keyword_id, term);
}

void HistoryService::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::URLsNoLongerBookmarked,
                    urls);
}

void HistoryService::AddObserver(history::HistoryServiceObserver* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  observers_.AddObserver(observer);
}

void HistoryService::RemoveObserver(history::HistoryServiceObserver* observer) {
  DCHECK(thread_checker_.CalledOnValidThread());
  observers_.RemoveObserver(observer);
}

void HistoryService::ScheduleDBTask(scoped_ptr<history::HistoryDBTask> task,
                                    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  base::CancelableTaskTracker::IsCanceledCallback is_canceled;
  tracker->NewTrackedTaskId(&is_canceled);
  // Use base::ThreadTaskRunnerHandler::Get() to get a message loop proxy to
  // the current message loop so that we can forward the call to the method
  // HistoryDBTask::DoneRunOnMainThread in the correct thread.
  thread_->message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&HistoryBackend::ProcessDBTask,
                 history_backend_.get(),
                 base::Passed(&task),
                 base::ThreadTaskRunnerHandle::Get(),
                 is_canceled));
}

void HistoryService::FlushForTest(const base::Closure& flushed) {
  thread_->message_loop_proxy()->PostTaskAndReply(
      FROM_HERE, base::Bind(&base::DoNothing), flushed);
}

void HistoryService::SetOnBackendDestroyTask(const base::Closure& task) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetOnBackendDestroyTask,
                    base::MessageLoop::current(), task);
}

void HistoryService::AddPage(const GURL& url,
                             Time time,
                             history::ContextID context_id,
                             int32 page_id,
                             const GURL& referrer,
                             const history::RedirectList& redirects,
                             ui::PageTransition transition,
                             history::VisitSource visit_source,
                             bool did_replace_entry) {
  DCHECK(thread_checker_.CalledOnValidThread());
  AddPage(
      history::HistoryAddPageArgs(url, time, context_id, page_id, referrer,
                                  redirects, transition, visit_source,
                                  did_replace_entry));
}

void HistoryService::AddPage(const GURL& url,
                             base::Time time,
                             history::VisitSource visit_source) {
  DCHECK(thread_checker_.CalledOnValidThread());
  AddPage(
      history::HistoryAddPageArgs(url, time, NULL, 0, GURL(),
                                  history::RedirectList(),
                                  ui::PAGE_TRANSITION_LINK,
                                  visit_source, false));
}

void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  // Filter out unwanted URLs. We don't add auto-subframe URLs. They are a
  // large part of history (think iframes for ads) and we never display them in
  // history UI. We will still add manual subframes, which are ones the user
  // has clicked on to get.
  if (!CanAddURL(add_page_args.url))
    return;

  // Add link & all redirects to visited link list.
  if (visitedlink_master_) {
    visitedlink_master_->AddURL(add_page_args.url);

    if (!add_page_args.redirects.empty()) {
      // We should not be asked to add a page in the middle of a redirect chain.
      DCHECK_EQ(add_page_args.url,
                add_page_args.redirects[add_page_args.redirects.size() - 1]);

      // We need the !redirects.empty() condition above since size_t is unsigned
      // and will wrap around when we subtract one from a 0 size.
      for (size_t i = 0; i < add_page_args.redirects.size() - 1; i++)
        visitedlink_master_->AddURL(add_page_args.redirects[i]);
    }
  }

  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::AddPage, add_page_args);
}

void HistoryService::AddPageNoVisitForBookmark(const GURL& url,
                                               const base::string16& title) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!CanAddURL(url))
    return;

  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::AddPageNoVisitForBookmark, url, title);
}

void HistoryService::SetPageTitle(const GURL& url,
                                  const base::string16& title) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetPageTitle, url, title);
}

void HistoryService::UpdateWithPageEndTime(history::ContextID context_id,
                                           int32 page_id,
                                           const GURL& url,
                                           Time end_ts) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateWithPageEndTime,
                    context_id, page_id, url, end_ts);
}

void HistoryService::AddPageWithDetails(const GURL& url,
                                        const base::string16& title,
                                        int visit_count,
                                        int typed_count,
                                        Time last_visit,
                                        bool hidden,
                                        history::VisitSource visit_source) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  // Filter out unwanted URLs.
  if (!CanAddURL(url))
    return;

  // Add to the visited links system.
  if (visitedlink_master_)
    visitedlink_master_->AddURL(url);

  history::URLRow row(url);
  row.set_title(title);
  row.set_visit_count(visit_count);
  row.set_typed_count(typed_count);
  row.set_last_visit(last_visit);
  row.set_hidden(hidden);

  history::URLRows rows;
  rows.push_back(row);

  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::AddPagesWithDetails, rows, visit_source);
}

void HistoryService::AddPagesWithDetails(const history::URLRows& info,
                                         history::VisitSource visit_source) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  // Add to the visited links system.
  if (visitedlink_master_) {
    std::vector<GURL> urls;
    urls.reserve(info.size());
    for (history::URLRows::const_iterator i = info.begin(); i != info.end();
         ++i)
      urls.push_back(i->url());

    visitedlink_master_->AddURLs(urls);
  }

  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::AddPagesWithDetails, info, visit_source);
}

base::CancelableTaskTracker::TaskId HistoryService::GetFavicons(
    const std::vector<GURL>& icon_urls,
    int icon_types,
    const std::vector<int>& desired_sizes,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<favicon_base::FaviconRawBitmapResult>* results =
      new std::vector<favicon_base::FaviconRawBitmapResult>();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetFavicons,
                 history_backend_.get(),
                 icon_urls,
                 icon_types,
                 desired_sizes,
                 results),
      base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetFaviconsForURL(
    const GURL& page_url,
    int icon_types,
    const std::vector<int>& desired_sizes,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<favicon_base::FaviconRawBitmapResult>* results =
      new std::vector<favicon_base::FaviconRawBitmapResult>();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetFaviconsForURL,
                 history_backend_.get(),
                 page_url,
                 icon_types,
                 desired_sizes,
                 results),
      base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetLargestFaviconForURL(
    const GURL& page_url,
    const std::vector<int>& icon_types,
    int minimum_size_in_pixels,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  favicon_base::FaviconRawBitmapResult* result =
      new favicon_base::FaviconRawBitmapResult();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetLargestFaviconForURL,
                 history_backend_.get(),
                 page_url,
                 icon_types,
                 minimum_size_in_pixels,
                 result),
      base::Bind(&RunWithFaviconResult, callback, base::Owned(result)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetFaviconForID(
    favicon_base::FaviconID favicon_id,
    int desired_size,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<favicon_base::FaviconRawBitmapResult>* results =
      new std::vector<favicon_base::FaviconRawBitmapResult>();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetFaviconForID,
                 history_backend_.get(),
                 favicon_id,
                 desired_size,
                 results),
      base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId
HistoryService::UpdateFaviconMappingsAndFetch(
    const GURL& page_url,
    const std::vector<GURL>& icon_urls,
    int icon_types,
    const std::vector<int>& desired_sizes,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<favicon_base::FaviconRawBitmapResult>* results =
      new std::vector<favicon_base::FaviconRawBitmapResult>();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::UpdateFaviconMappingsAndFetch,
                 history_backend_.get(),
                 page_url,
                 icon_urls,
                 icon_types,
                 desired_sizes,
                 results),
      base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
}

void HistoryService::MergeFavicon(
    const GURL& page_url,
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    scoped_refptr<base::RefCountedMemory> bitmap_data,
    const gfx::Size& pixel_size) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!CanAddURL(page_url))
    return;

  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::MergeFavicon, page_url,
                    icon_url, icon_type, bitmap_data, pixel_size);
}

void HistoryService::SetFavicons(
    const GURL& page_url,
    favicon_base::IconType icon_type,
    const GURL& icon_url,
    const std::vector<SkBitmap>& bitmaps) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!CanAddURL(page_url))
    return;

  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetFavicons, page_url,
      icon_type, icon_url, bitmaps);
}

void HistoryService::SetFaviconsOutOfDateForPage(const GURL& page_url) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::SetFaviconsOutOfDateForPage, page_url);
}

void HistoryService::CloneFavicons(const GURL& old_page_url,
                                   const GURL& new_page_url) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::CloneFavicons,
                    old_page_url, new_page_url);
}

void HistoryService::SetImportedFavicons(
    const std::vector<ImportedFaviconUsage>& favicon_usage) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::SetImportedFavicons, favicon_usage);
}

base::CancelableTaskTracker::TaskId HistoryService::QueryURL(
    const GURL& url,
    bool want_visits,
    const QueryURLCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::QueryURLResult* query_url_result = new history::QueryURLResult();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryURL,
                 history_backend_.get(),
                 url,
                 want_visits,
                 base::Unretained(query_url_result)),
      base::Bind(
          &RunWithQueryURLResult, callback, base::Owned(query_url_result)));
}

// Downloads -------------------------------------------------------------------

// Handle creation of a download by creating an entry in the history service's
// 'downloads' table.
void HistoryService::CreateDownload(
    const history::DownloadRow& create_info,
    const HistoryService::DownloadCreateCallback& callback) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  PostTaskAndReplyWithResult(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(
          &HistoryBackend::CreateDownload, history_backend_.get(), create_info),
      callback);
}

void HistoryService::GetNextDownloadId(
    const content::DownloadIdCallback& callback) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  PostTaskAndReplyWithResult(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetNextDownloadId, history_backend_.get()),
      callback);
}

// Handle queries for a list of all downloads in the history database's
// 'downloads' table.
void HistoryService::QueryDownloads(
    const DownloadQueryCallback& callback) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  std::vector<history::DownloadRow>* rows =
    new std::vector<history::DownloadRow>();
  scoped_ptr<std::vector<history::DownloadRow> > scoped_rows(rows);
  // Beware! The first Bind() does not simply |scoped_rows.get()| because
  // base::Passed(&scoped_rows) nullifies |scoped_rows|, and compilers do not
  // guarantee that the first Bind's arguments are evaluated before the second
  // Bind's arguments.
  thread_->message_loop_proxy()->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryDownloads, history_backend_.get(), rows),
      base::Bind(callback, base::Passed(&scoped_rows)));
}

// Handle updates for a particular download. This is a 'fire and forget'
// operation, so we don't need to be called back.
void HistoryService::UpdateDownload(const history::DownloadRow& data) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateDownload, data);
}

void HistoryService::RemoveDownloads(const std::set<uint32>& ids) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL,
                    &HistoryBackend::RemoveDownloads, ids);
}

base::CancelableTaskTracker::TaskId HistoryService::QueryHistory(
    const base::string16& text_query,
    const history::QueryOptions& options,
    const QueryHistoryCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::QueryResults* query_results = new history::QueryResults();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryHistory,
                 history_backend_.get(),
                 text_query,
                 options,
                 base::Unretained(query_results)),
      base::Bind(callback, base::Owned(query_results)));
}

base::CancelableTaskTracker::TaskId HistoryService::QueryRedirectsFrom(
    const GURL& from_url,
    const QueryRedirectsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::RedirectList* result = new history::RedirectList();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryRedirectsFrom,
                 history_backend_.get(),
                 from_url,
                 base::Unretained(result)),
      base::Bind(callback, base::Owned(result)));
}

base::CancelableTaskTracker::TaskId HistoryService::QueryRedirectsTo(
    const GURL& to_url,
    const QueryRedirectsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::RedirectList* result = new history::RedirectList();
  return tracker->PostTaskAndReply(thread_->message_loop_proxy().get(),
                                   FROM_HERE,
                                   base::Bind(&HistoryBackend::QueryRedirectsTo,
                                              history_backend_.get(),
                                              to_url,
                                              base::Unretained(result)),
                                   base::Bind(callback, base::Owned(result)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetVisibleVisitCountToHost(
    const GURL& url,
    const GetVisibleVisitCountToHostCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::VisibleVisitCountToHostResult* result =
      new history::VisibleVisitCountToHostResult();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::GetVisibleVisitCountToHost,
                 history_backend_.get(),
                 url,
                 base::Unretained(result)),
      base::Bind(&RunWithVisibleVisitCountToHostResult,
                 callback,
                 base::Owned(result)));
}

base::CancelableTaskTracker::TaskId HistoryService::QueryMostVisitedURLs(
    int result_count,
    int days_back,
    const QueryMostVisitedURLsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::MostVisitedURLList* result = new history::MostVisitedURLList();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryMostVisitedURLs,
                 history_backend_.get(),
                 result_count,
                 days_back,
                 base::Unretained(result)),
      base::Bind(callback, base::Owned(result)));
}

base::CancelableTaskTracker::TaskId HistoryService::QueryFilteredURLs(
    int result_count,
    const history::VisitFilter& filter,
    bool extended_info,
    const QueryFilteredURLsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  history::FilteredURLList* result = new history::FilteredURLList();
  return tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::QueryFilteredURLs,
                 history_backend_.get(),
                 result_count,
                 filter,
                 extended_info,
                 base::Unretained(result)),
      base::Bind(callback, base::Owned(result)));
}

void HistoryService::Cleanup() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_) {
    // We've already cleaned up.
    return;
  }

  weak_ptr_factory_.InvalidateWeakPtrs();

  // Unload the backend.
  if (history_backend_.get()) {
    // Get rid of the in-memory backend.
    in_memory_backend_.reset();

    // Give the InMemoryURLIndex a chance to shutdown.
    // NOTE: In tests, there may be no index.
    if (in_memory_url_index_)
      in_memory_url_index_->ShutDown();

    // The backend's destructor must run on the history thread since it is not
    // threadsafe. So this thread must not be the last thread holding a
    // reference to the backend, or a crash could happen.
    //
    // We have a reference to the history backend. There is also an extra
    // reference held by our delegate installed in the backend, which
    // HistoryBackend::Closing will release. This means if we scheduled a call
    // to HistoryBackend::Closing and *then* released our backend reference,
    // there will be a race between us and the backend's Closing function to see
    // who is the last holder of a reference. If the backend thread's Closing
    // manages to run before we release our backend refptr, the last reference
    // will be held by this thread and the destructor will be called from here.
    //
    // Therefore, we create a closure to run the Closing operation first. This
    // holds a reference to the backend. Then we release our reference, then we
    // schedule the task to run. After the task runs, it will delete its
    // reference from the history thread, ensuring everything works properly.
    //
    // TODO(ajwong): Cleanup HistoryBackend lifetime issues.
    //     See http://crbug.com/99767.
    history_backend_->AddRef();
    base::Closure closing_task =
        base::Bind(&HistoryBackend::Closing, history_backend_.get());
    ScheduleTask(PRIORITY_NORMAL, closing_task);
    closing_task.Reset();
    HistoryBackend* raw_ptr = history_backend_.get();
    history_backend_ = NULL;
    thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
  }

  // Delete the thread, which joins with the background thread. We defensively
  // NULL the pointer before deleting it in case somebody tries to use it
  // during shutdown, but this shouldn't happen.
  base::Thread* thread = thread_;
  thread_ = NULL;
  delete thread;
}

void HistoryService::Observe(int type,
                             const content::NotificationSource& source,
                             const content::NotificationDetails& details) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return;

  switch (type) {
    case chrome::NOTIFICATION_HISTORY_URLS_DELETED: {
      // Update the visited link system for deleted URLs. We will update the
      // visited link system for added URLs as soon as we get the add
      // notification (we don't have to wait for the backend, which allows us to
      // be faster to update the state).
      //
      // For deleted URLs, we don't typically know what will be deleted since
      // delete notifications are by time. We would also like to be more
      // respectful of privacy and never tell the user something is gone when it
      // isn't. Therefore, we update the delete URLs after the fact.
      if (visitedlink_master_) {
        content::Details<history::URLsDeletedDetails> deleted_details(details);

        if (deleted_details->all_history) {
          visitedlink_master_->DeleteAllURLs();
        } else {
          URLIteratorFromURLRows iterator(deleted_details->rows);
          visitedlink_master_->DeleteURLs(&iterator);
        }
      }
      break;
    }

    default:
      NOTREACHED();
  }
}

void HistoryService::RebuildTable(
    const scoped_refptr<URLEnumerator>& enumerator) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::IterateURLs, enumerator);
}

bool HistoryService::Init(const base::FilePath& history_dir, bool no_db) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  base::Thread::Options options;
  options.timer_slack = base::TIMER_SLACK_MAXIMUM;
  if (!thread_->StartWithOptions(options)) {
    Cleanup();
    return false;
  }

  history_dir_ = history_dir;
  no_db_ = no_db;

  if (profile_) {
    std::string languages =
        profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
    in_memory_url_index_.reset(new history::InMemoryURLIndex(
        profile_, this, history_dir_, languages, history_client_));
    in_memory_url_index_->Init();
  }

  // Create the history backend.
  scoped_refptr<HistoryBackend> backend(
      new HistoryBackend(history_dir_,
                         new BackendDelegate(
                             weak_ptr_factory_.GetWeakPtr(),
                             base::ThreadTaskRunnerHandle::Get(),
                             profile_),
                         history_client_));
  history_backend_.swap(backend);

  // There may not be a profile when unit testing.
  std::string languages;
  if (profile_) {
    PrefService* prefs = profile_->GetPrefs();
    languages = prefs->GetString(prefs::kAcceptLanguages);
  }
  ScheduleAndForget(PRIORITY_UI, &HistoryBackend::Init, languages, no_db_);

  if (visitedlink_master_) {
    bool result = visitedlink_master_->Init();
    DCHECK(result);
  }

  return true;
}

void HistoryService::ScheduleAutocomplete(const base::Callback<
    void(history::HistoryBackend*, history::URLDatabase*)>& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleAndForget(
      PRIORITY_UI, &HistoryBackend::ScheduleAutocomplete, callback);
}

void HistoryService::ScheduleTask(SchedulePriority priority,
                                  const base::Closure& task) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(thread_);
  CHECK(thread_->message_loop());
  // TODO(brettw): Do prioritization.
  thread_->message_loop()->PostTask(FROM_HERE, task);
}

// static
bool HistoryService::CanAddURL(const GURL& url) {
  if (!url.is_valid())
    return false;

  // TODO: We should allow kChromeUIScheme URLs if they have been explicitly
  // typed.  Right now, however, these are marked as typed even when triggered
  // by a shortcut or menu action.
  if (url.SchemeIs(url::kJavaScriptScheme) ||
      url.SchemeIs(content::kChromeDevToolsScheme) ||
      url.SchemeIs(content::kChromeUIScheme) ||
      url.SchemeIs(content::kViewSourceScheme) ||
      url.SchemeIs(chrome::kChromeNativeScheme) ||
      url.SchemeIs(chrome::kChromeSearchScheme) ||
      url.SchemeIs(dom_distiller::kDomDistillerScheme))
    return false;

  // Allow all about: and chrome: URLs except about:blank, since the user may
  // like to see "chrome://memory/", etc. in their history and autocomplete.
  if (url == GURL(url::kAboutBlankURL))
    return false;

  return true;
}

base::WeakPtr<HistoryService> HistoryService::AsWeakPtr() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return weak_ptr_factory_.GetWeakPtr();
}

syncer::SyncMergeResult HistoryService::MergeDataAndStartSyncing(
    syncer::ModelType type,
    const syncer::SyncDataList& initial_sync_data,
    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
    scoped_ptr<syncer::SyncErrorFactory> error_handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
  delete_directive_handler_.Start(this, initial_sync_data,
                                  sync_processor.Pass());
  return syncer::SyncMergeResult(type);
}

void HistoryService::StopSyncing(syncer::ModelType type) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
  delete_directive_handler_.Stop();
}

syncer::SyncDataList HistoryService::GetAllSyncData(
    syncer::ModelType type) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
  // TODO(akalin): Keep track of existing delete directives.
  return syncer::SyncDataList();
}

syncer::SyncError HistoryService::ProcessSyncChanges(
    const tracked_objects::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  delete_directive_handler_.ProcessSyncChanges(this, change_list);
  return syncer::SyncError();
}

syncer::SyncError HistoryService::ProcessLocalDeleteDirective(
    const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return delete_directive_handler_.ProcessLocalDeleteDirective(
      delete_directive);
}

void HistoryService::SetInMemoryBackend(
    scoped_ptr<history::InMemoryHistoryBackend> mem_backend) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!in_memory_backend_) << "Setting mem DB twice";
  in_memory_backend_.reset(mem_backend.release());

  // The database requires additional initialization once we own it.
  in_memory_backend_->AttachToHistoryService(profile_, this);
}

void HistoryService::NotifyProfileError(sql::InitStatus init_status) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (history_client_)
    history_client_->NotifyProfileError(init_status);
}

void HistoryService::DeleteURL(const GURL& url) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  // We will update the visited links when we observe the delete notifications.
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURL, url);
}

void HistoryService::DeleteURLsForTest(const std::vector<GURL>& urls) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  // We will update the visited links when we observe the delete
  // notifications.
  ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURLs, urls);
}

void HistoryService::ExpireHistoryBetween(
    const std::set<GURL>& restrict_urls,
    Time begin_time,
    Time end_time,
    const base::Closure& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  tracker->PostTaskAndReply(thread_->message_loop_proxy().get(),
                            FROM_HERE,
                            base::Bind(&HistoryBackend::ExpireHistoryBetween,
                                       history_backend_,
                                       restrict_urls,
                                       begin_time,
                                       end_time),
                            callback);
}

void HistoryService::ExpireHistory(
    const std::vector<history::ExpireHistoryArgs>& expire_list,
    const base::Closure& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(thread_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  tracker->PostTaskAndReply(
      thread_->message_loop_proxy().get(),
      FROM_HERE,
      base::Bind(&HistoryBackend::ExpireHistory, history_backend_, expire_list),
      callback);
}

void HistoryService::ExpireLocalAndRemoteHistoryBetween(
    const std::set<GURL>& restrict_urls,
    Time begin_time,
    Time end_time,
    const base::Closure& callback,
    base::CancelableTaskTracker* tracker) {
  // TODO(dubroy): This should be factored out into a separate class that
  // dispatches deletions to the proper places.

  history::WebHistoryService* web_history =
      WebHistoryServiceFactory::GetForProfile(profile_);
  if (web_history) {
    // TODO(dubroy): This API does not yet support deletion of specific URLs.
    DCHECK(restrict_urls.empty());

    delete_directive_handler_.CreateDeleteDirectives(
        std::set<int64>(), begin_time, end_time);

    // Attempt online deletion from the history server, but ignore the result.
    // Deletion directives ensure that the results will eventually be deleted.
    //
    // TODO(davidben): |callback| should not run until this operation completes
    // too.
    web_history->ExpireHistoryBetween(
        restrict_urls, begin_time, end_time,
        base::Bind(&ExpireWebHistoryComplete));
  }
  ExpireHistoryBetween(restrict_urls, begin_time, end_time, callback, tracker);
}

void HistoryService::BroadcastNotificationsHelper(
    int type,
    scoped_ptr<history::HistoryDetails> details) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // TODO(evanm): this is currently necessitated by generate_profile, which
  // runs without a browser process. generate_profile should really create
  // a browser process, at which point this check can then be nuked.
  if (!g_browser_process)
    return;

  if (!thread_)
    return;

  // The source of all of our notifications is the profile. Note that this
  // pointer is NULL in unit tests.
  content::Source<Profile> source(profile_);

  // The details object just contains the pointer to the object that the
  // backend has allocated for us. The receiver of the notification will cast
  // this to the proper type.
  content::Details<history::HistoryDetails> det(details.get());

  content::NotificationService::current()->Notify(type, source, det);
}

void HistoryService::OnDBLoaded() {
  DCHECK(thread_checker_.CalledOnValidThread());
  backend_loaded_ = true;
  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_HISTORY_LOADED,
      content::Source<Profile>(profile_),
      content::Details<HistoryService>(this));
}

bool HistoryService::GetRowForURL(const GURL& url, history::URLRow* url_row) {
  DCHECK(thread_checker_.CalledOnValidThread());
  history::URLDatabase* db = InMemoryDatabase();
  return db && (db->GetRowForURL(url, url_row) != 0);
}

void HistoryService::NotifyAddVisit(const history::BriefVisitInfo& info) {
  DCHECK(thread_checker_.CalledOnValidThread());
  FOR_EACH_OBSERVER(
      history::HistoryServiceObserver, observers_, OnAddVisit(this, info));
}

void HistoryService::NotifyURLVisited(ui::PageTransition transition,
                                      const history::URLRow& row,
                                      const history::RedirectList& redirects,
                                      base::Time visit_time) {
  DCHECK(thread_checker_.CalledOnValidThread());
  FOR_EACH_OBSERVER(history::HistoryServiceObserver,
                    observers_,
                    OnURLVisited(this, transition, row, redirects, visit_time));
}

scoped_ptr<base::CallbackList<void(const std::set<GURL>&)>::Subscription>
HistoryService::AddFaviconChangedCallback(
    const HistoryService::OnFaviconChangedCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return favicon_changed_callback_list_.Add(callback);
}

void HistoryService::NotifyFaviconChanged(
    const std::set<GURL>& changed_favicons) {
  DCHECK(thread_checker_.CalledOnValidThread());
  favicon_changed_callback_list_.Notify(changed_favicons);
}
