// 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 "components/history/core/browser/history_service.h"

#include <utility>

#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/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/history/core/browser/download_row.h"
#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/history_backend_client.h"
#include "components/history/core/browser/history_client.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_db_task.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/in_memory_history_backend.h"
#include "components/history/core/browser/keyword_search_term.h"
#include "components/history/core/browser/visit_database.h"
#include "components/history/core/browser/visit_delegate.h"
#include "components/history/core/browser/web_history_service.h"
#include "components/history/core/common/thumbnail_score.h"
#include "components/sync/model/sync_error_factory.h"
#include "components/sync/model_impl/proxy_model_type_controller_delegate.h"
#include "components/variations/variations_associated_data.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/page_transition_types.h"

#if defined(OS_IOS)
#include "base/critical_closure.h"
#endif

using base::Time;

namespace history {
namespace {

static const char* kHistoryThreadName = "Chrome_HistoryThread";

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

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

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

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

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

// Used for debugging 807009. This keeps a static of the number of instances of
// AddPageMemoryDebuggingTask that have been created but not destroyed. This
// count corresponds to the number of calls to AddPage() that have not yet been
// processed by the HistoryBackend.
class AddPageMemoryDebuggingTask {
 public:
  // |real_task| is the task to actually call to HistoryBackend.
  explicit AddPageMemoryDebuggingTask(base::OnceClosure real_task)
      : real_task_(std::move(real_task)) {
    base::AutoLock auto_lock(GetLock());
    ++live_count_;
  }

  ~AddPageMemoryDebuggingTask() {
    base::AutoLock auto_lock(GetLock());
    DCHECK_GT(live_count_, 0);
    --live_count_;
  }

  // Called on the background/db-thread to run the closure supplied to the
  // constructor. The instance is deleted right after this call.
  void RunOnDbThread() { std::move(real_task_).Run(); }

  static int live_count() {
    base::AutoLock auto_lock(GetLock());
    return live_count_;
  }

 private:
  static base::Lock& GetLock() {
    static base::NoDestructor<base::Lock> lock;
    return *lock;
  }

  // The number of instances waiting to run.
  static int live_count_;  // Guarded by getLock()

  base::OnceClosure real_task_;

  DISALLOW_COPY_AND_ASSIGN(AddPageMemoryDebuggingTask);
};

// static
int AddPageMemoryDebuggingTask::live_count_ = 0;

class HistoryMemoryDumpProvider : public base::trace_event::MemoryDumpProvider {
 public:
  static HistoryMemoryDumpProvider* Get() {
    if (!instance_)
      instance_ = new HistoryMemoryDumpProvider();
    return instance_;
  }

  // base::trace_event::MemoryDumpProvider:
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override {
    // NOTE: this may be called on any thread, see constructor.
    base::trace_event::MemoryAllocatorDump* dump =
        pmd->CreateAllocatorDump("history/history_service");
    dump->AddScalar("pending_add_pages",
                    base::trace_event::MemoryAllocatorDump::kUnitsObjects,
                    AddPageMemoryDebuggingTask::live_count());
    return true;
  }

 private:
  HistoryMemoryDumpProvider() {
    // NOTE: the nullptr arg means OnMemoryDump() may be called from any
    // thread.
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "HistoryService", nullptr);
  }

  ~HistoryMemoryDumpProvider() override {
    base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
        this);
  }

  static HistoryMemoryDumpProvider* instance_;

  DISALLOW_COPY_AND_ASSIGN(HistoryMemoryDumpProvider);
};

// static
HistoryMemoryDumpProvider* HistoryMemoryDumpProvider::instance_ = nullptr;

}  // 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)
      : history_service_(history_service),
        service_task_runner_(service_task_runner) {}

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

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

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

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

  void NotifyURLsModified(const URLRows& changed_urls) override {
    service_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&HistoryService::NotifyURLsModified,
                                  history_service_, changed_urls));
  }

  void NotifyURLsDeleted(DeletionInfo deletion_info) override {
    service_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&HistoryService::NotifyURLsDeleted,
                                  history_service_, std::move(deletion_info)));
  }

  void NotifyKeywordSearchTermUpdated(const URLRow& row,
                                      KeywordID keyword_id,
                                      const base::string16& term) override {
    service_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&HistoryService::NotifyKeywordSearchTermUpdated,
                       history_service_, row, keyword_id, term));
  }

  void NotifyKeywordSearchTermDeleted(URLID url_id) override {
    service_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&HistoryService::NotifyKeywordSearchTermDeleted,
                       history_service_, url_id));
  }

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

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

HistoryService::HistoryService() : HistoryService(nullptr, nullptr) {}

HistoryService::HistoryService(std::unique_ptr<HistoryClient> history_client,
                               std::unique_ptr<VisitDelegate> visit_delegate)
    : thread_(variations::GetVariationParamValue("BrowserScheduler",
                                                 "RedirectHistoryService") ==
                      "true"
                  ? nullptr
                  : new base::Thread(kHistoryThreadName)),
      history_client_(std::move(history_client)),
      visit_delegate_(std::move(visit_delegate)),
      backend_loaded_(false),
      weak_ptr_factory_(this) {
  // Make sure the HistoryMemoryDumpProvider is created and registered.
  HistoryMemoryDumpProvider::Get();
}

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_;
}

#if defined(OS_IOS)
void HistoryService::HandleBackgrounding() {
  if (!backend_task_runner_ || !history_backend_.get())
    return;

  ScheduleTask(PRIORITY_NORMAL,
               base::MakeCriticalClosure(base::Bind(
                   &HistoryBackend::PersistState, history_backend_.get())));
}
#endif

void HistoryService::ClearCachedDataForContextID(ContextID context_id) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::ClearCachedDataForContextID,
                              history_backend_, context_id));
}

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

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

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

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

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

  ScheduleTask(PRIORITY_UI,
               base::BindOnce(&HistoryBackend::DeleteAllSearchTermsForKeyword,
                              history_backend_, keyword_id));
}

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

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

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

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

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

base::CancelableTaskTracker::TaskId HistoryService::ScheduleDBTask(
    const base::Location& from_here,
    std::unique_ptr<HistoryDBTask> task,
    base::CancelableTaskTracker* tracker) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  base::CancelableTaskTracker::IsCanceledCallback is_canceled;
  base::CancelableTaskTracker::TaskId task_id =
      tracker->NewTrackedTaskId(&is_canceled);
  // Use base::ThreadTaskRunnerHandler::Get() to get a task runner for
  // the current message loop so that we can forward the call to the method
  // HistoryDBTask::DoneRunOnMainThread() in the correct thread.
  backend_task_runner_->PostTask(
      from_here,
      base::BindOnce(&HistoryBackend::ProcessDBTask, history_backend_,
                     std::move(task), base::ThreadTaskRunnerHandle::Get(),
                     is_canceled));
  return task_id;
}

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

void HistoryService::SetOnBackendDestroyTask(const base::Closure& task) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(
      PRIORITY_NORMAL,
      base::BindOnce(&HistoryBackend::SetOnBackendDestroyTask, history_backend_,
                     base::ThreadTaskRunnerHandle::Get(), task));
}

void HistoryService::TopHosts(size_t num_hosts,
                              const TopHostsCallback& callback) const {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::Bind(&HistoryBackend::TopHosts, history_backend_, num_hosts),
      callback);
}

void HistoryService::GetCountsAndLastVisitForOriginsForTesting(
    const std::set<GURL>& origins,
    const GetCountsAndLastVisitForOriginsCallback& callback) const {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::Bind(&HistoryBackend::GetCountsAndLastVisitForOrigins,
                 history_backend_, origins),
      callback);
}

void HistoryService::HostRankIfAvailable(
    const GURL& url,
    const base::Callback<void(int)>& callback) const {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::Bind(&HistoryBackend::HostRankIfAvailable, history_backend_, url),
      callback);
}

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

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

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

  if (history_client_ && !history_client_->CanAddURL(add_page_args.url))
    return;

  // Inform VisitedDelegate of all links and redirects.
  if (visit_delegate_) {
    if (!add_page_args.redirects.empty()) {
      // We should not be asked to add a page in the middle of a redirect chain,
      // and thus add_page_args.url should be the last element in the array
      // add_page_args.redirects which mean we can use VisitDelegate::AddURLs()
      // with the whole array.
      DCHECK_EQ(add_page_args.url, add_page_args.redirects.back());
      visit_delegate_->AddURLs(add_page_args.redirects);
    } else {
      visit_delegate_->AddURL(add_page_args.url);
    }
  }

  auto real_task =
      base::BindOnce(&HistoryBackend::AddPage, history_backend_, add_page_args);
  std::unique_ptr<AddPageMemoryDebuggingTask> debug_task =
      std::make_unique<AddPageMemoryDebuggingTask>(std::move(real_task));
  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&AddPageMemoryDebuggingTask::RunOnDbThread,
                              std::move(debug_task)));
}

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

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::AddPageNoVisitForBookmark,
                              history_backend_, url, title));
}

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

void HistoryService::UpdateWithPageEndTime(ContextID context_id,
                                           int nav_entry_id,
                                           const GURL& url,
                                           Time end_ts) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(
      PRIORITY_NORMAL,
      base::BindOnce(&HistoryBackend::UpdateWithPageEndTime, history_backend_,
                     context_id, nav_entry_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,
                                        VisitSource visit_source) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  // Filter out unwanted URLs.
  if (history_client_ && !history_client_->CanAddURL(url))
    return;

  // Inform VisitDelegate of the URL.
  if (visit_delegate_)
    visit_delegate_->AddURL(url);

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

  URLRows rows;
  rows.push_back(row);

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::AddPagesWithDetails,
                              history_backend_, rows, visit_source));
}

void HistoryService::AddPagesWithDetails(const URLRows& info,
                                         VisitSource visit_source) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  // Inform the VisitDelegate of the URLs
  if (!info.empty() && visit_delegate_) {
    std::vector<GURL> urls;
    urls.reserve(info.size());
    for (const auto& row : info)
      urls.push_back(row.url());
    visit_delegate_->AddURLs(urls);
  }

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::AddPagesWithDetails,
                              history_backend_, info, visit_source));
}

base::CancelableTaskTracker::TaskId HistoryService::GetFavicon(
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    const std::vector<int>& desired_sizes,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  TRACE_EVENT0("browser", "HistoryService::GetFavicons");
  DCHECK(backend_task_runner_) << "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(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::GetFavicon, history_backend_, icon_url,
                     icon_type, desired_sizes, results),
      base::BindOnce(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetFaviconsForURL(
    const GURL& page_url,
    const favicon_base::IconTypeSet& icon_types,
    const std::vector<int>& desired_sizes,
    bool fallback_to_host,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  TRACE_EVENT0("browser", "HistoryService::GetFaviconsForURL");
  DCHECK(backend_task_runner_) << "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(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::GetFaviconsForURL, history_backend_,
                     page_url, icon_types, desired_sizes, fallback_to_host,
                     results),
      base::BindOnce(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId HistoryService::GetLargestFaviconForURL(
    const GURL& page_url,
    const std::vector<favicon_base::IconTypeSet>& icon_types,
    int minimum_size_in_pixels,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  favicon_base::FaviconRawBitmapResult* result =
      new favicon_base::FaviconRawBitmapResult();
  return tracker->PostTaskAndReply(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::GetLargestFaviconForURL, history_backend_,
                     page_url, icon_types, minimum_size_in_pixels, result),
      base::BindOnce(&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) {
  TRACE_EVENT0("browser", "HistoryService::GetFaviconForID");
  DCHECK(backend_task_runner_) << "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(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::GetFaviconForID, history_backend_,
                     favicon_id, desired_size, results),
      base::BindOnce(&RunWithFaviconResults, callback, base::Owned(results)));
}

base::CancelableTaskTracker::TaskId
HistoryService::UpdateFaviconMappingsAndFetch(
    const base::flat_set<GURL>& page_urls,
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    const std::vector<int>& desired_sizes,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  TRACE_EVENT0("browser", "HistoryService::UpdateFaviconMappingsAndFetch");
  DCHECK(backend_task_runner_) << "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(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::UpdateFaviconMappingsAndFetch,
                     history_backend_, page_urls, icon_url, icon_type,
                     desired_sizes, results),
      base::BindOnce(&RunWithFaviconResults, callback, base::Owned(results)));
}

void HistoryService::DeleteFaviconMappings(
    const base::flat_set<GURL>& page_urls,
    favicon_base::IconType icon_type) {
  TRACE_EVENT0("browser", "HistoryService::DeleteFaviconMappings");
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::DeleteFaviconMappings,
                              history_backend_, page_urls, icon_type));
}

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) {
  TRACE_EVENT0("browser", "HistoryService::MergeFavicon");
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (history_client_ && !history_client_->CanAddURL(page_url))
    return;

  ScheduleTask(
      PRIORITY_NORMAL,
      base::BindOnce(&HistoryBackend::MergeFavicon, history_backend_, page_url,
                     icon_url, icon_type, bitmap_data, pixel_size));
}

void HistoryService::SetFavicons(const base::flat_set<GURL>& page_urls,
                                 favicon_base::IconType icon_type,
                                 const GURL& icon_url,
                                 const std::vector<SkBitmap>& bitmaps) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  base::flat_set<GURL> page_urls_to_save;
  page_urls_to_save.reserve(page_urls.capacity());
  for (const GURL& page_url : page_urls) {
    if (!history_client_ || history_client_->CanAddURL(page_url))
      page_urls_to_save.insert(page_url);
  }

  if (page_urls_to_save.empty())
    return;

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::SetFavicons, history_backend_,
                              page_urls_to_save, icon_type, icon_url, bitmaps));
}

void HistoryService::CloneFaviconMappingsForPages(
    const GURL& page_url_to_read,
    const favicon_base::IconTypeSet& icon_types,
    const base::flat_set<GURL>& page_urls_to_write) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::CloneFaviconMappingsForPages,
                              history_backend_, page_url_to_read, icon_types,
                              page_urls_to_write));
}

void HistoryService::CanSetOnDemandFavicons(
    const GURL& page_url,
    favicon_base::IconType icon_type,
    base::OnceCallback<void(bool)> callback) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (history_client_ && !history_client_->CanAddURL(page_url)) {
    std::move(callback).Run(false);
    return;
  }

  PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::CanSetOnDemandFavicons, history_backend_,
                     page_url, icon_type),
      std::move(callback));
}

void HistoryService::SetOnDemandFavicons(
    const GURL& page_url,
    favicon_base::IconType icon_type,
    const GURL& icon_url,
    const std::vector<SkBitmap>& bitmaps,
    base::OnceCallback<void(bool)> callback) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  if (history_client_ && !history_client_->CanAddURL(page_url)) {
    std::move(callback).Run(false);
    return;
  }

  PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::SetOnDemandFavicons, history_backend_,
                     page_url, icon_type, icon_url, bitmaps),
      std::move(callback));
}

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

void HistoryService::TouchOnDemandFavicon(const GURL& icon_url) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::TouchOnDemandFavicon,
                              history_backend_, icon_url));
}

void HistoryService::SetImportedFavicons(
    const favicon_base::FaviconUsageDataList& favicon_usage) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(PRIORITY_NORMAL,
               base::BindOnce(&HistoryBackend::SetImportedFavicons,
                              history_backend_, favicon_usage));
}

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

// Statistics ------------------------------------------------------------------

base::CancelableTaskTracker::TaskId HistoryService::GetHistoryCount(
    const Time& begin_time,
    const Time& end_time,
    const GetHistoryCountCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  return tracker->PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::Bind(&HistoryBackend::GetHistoryCount, history_backend_, begin_time,
                 end_time),
      callback);
}

void HistoryService::CountUniqueHostsVisitedLastMonth(
    const GetHistoryCountCallback& callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());

  tracker->PostTaskAndReplyWithResult(
      backend_task_runner_.get(), FROM_HERE,
      base::BindRepeating(&HistoryBackend::CountUniqueHostsVisitedLastMonth,
                          history_backend_),
      callback);
}

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

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

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

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

void HistoryService::RemoveDownloads(const std::set<uint32_t>& ids) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  ScheduleTask(PRIORITY_NORMAL, base::BindOnce(&HistoryBackend::RemoveDownloads,
                                               history_backend_, ids));
}

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

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

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

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

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

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

  NotifyHistoryServiceBeingDeleted();

  weak_ptr_factory_.InvalidateWeakPtrs();

  // Inform the HistoryClient that we are shuting down.
  if (history_client_)
    history_client_->Shutdown();

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

    // 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_);
    ScheduleTask(PRIORITY_NORMAL, closing_task);
    closing_task.Reset();
    HistoryBackend* raw_ptr = history_backend_.get();
    history_backend_ = nullptr;
    backend_task_runner_->ReleaseSoon(FROM_HERE, raw_ptr);
  }

  // Clear |backend_task_runner_| to make sure it's not used after Cleanup().
  backend_task_runner_ = nullptr;

  // Join the background thread, if any.
  thread_.reset();
}

bool HistoryService::Init(
    bool no_db,
    const HistoryDatabaseParams& history_database_params) {
  TRACE_EVENT0("browser,startup", "HistoryService::Init")
  SCOPED_UMA_HISTOGRAM_TIMER("History.HistoryServiceInitTime");
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!backend_task_runner_);

  if (thread_) {
    base::Thread::Options options;
    options.timer_slack = base::TIMER_SLACK_MAXIMUM;
    if (!thread_->StartWithOptions(options)) {
      Cleanup();
      return false;
    }
    backend_task_runner_ = thread_->task_runner();
  } else {
    backend_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
        {base::MayBlock(), base::WithBaseSyncPrimitives(),
         base::TaskPriority::USER_BLOCKING,
         base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
  }

  // Create the history backend.
  scoped_refptr<HistoryBackend> backend(new HistoryBackend(
      new BackendDelegate(weak_ptr_factory_.GetWeakPtr(),
                          base::ThreadTaskRunnerHandle::Get()),
      history_client_ ? history_client_->CreateBackendClient() : nullptr,
      backend_task_runner_));
  history_backend_.swap(backend);

  ScheduleTask(PRIORITY_UI,
               base::BindOnce(&HistoryBackend::Init, history_backend_, no_db,
                              history_database_params));

  if (visit_delegate_ && !visit_delegate_->Init(this))
    return false;

  if (history_client_)
    history_client_->OnHistoryServiceCreated(this);

  return true;
}

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

void HistoryService::ScheduleTask(SchedulePriority priority,
                                  base::OnceClosure task) {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(backend_task_runner_);
  // TODO(brettw): Do prioritization.
  // NOTE(mastiz): If this implementation changes, be cautious with implications
  // for sync, because a) the sync engine (sync thread) post tasks directly to
  // the task runner via ModelTypeProcessorProxy (which is subtle); and b)
  // ProfileSyncService (UI thread) does the same via
  // ProxyModelTypeControllerDelegate.
  backend_task_runner_->PostTask(FROM_HERE, std::move(task));
}

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,
    std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
    std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
  delete_directive_handler_.Start(this, initial_sync_data,
                                  std::move(sync_processor));
  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 base::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  delete_directive_handler_.ProcessSyncChanges(this, change_list);
  return syncer::SyncError();
}

std::unique_ptr<syncer::ModelTypeControllerDelegate>
HistoryService::GetTypedURLSyncControllerDelegate() {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Note that a callback is bound for GetTypedURLSyncControllerDelegate()
  // because this getter itself must also run in the backend sequence, and the
  // proxy object below will take care of that.
  return std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
      backend_task_runner_,
      base::BindRepeating(&HistoryBackend::GetTypedURLSyncControllerDelegate,
                          base::Unretained(history_backend_.get())));
}

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

void HistoryService::SetInMemoryBackend(
    std::unique_ptr<InMemoryHistoryBackend> mem_backend) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!in_memory_backend_) << "Setting mem DB twice";
  in_memory_backend_ = std::move(mem_backend);

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

void HistoryService::NotifyProfileError(sql::InitStatus init_status,
                                        const std::string& diagnostics) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (history_client_)
    history_client_->NotifyProfileError(init_status, diagnostics);
}

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

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

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

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

void HistoryService::ExpireHistoryBeforeForTesting(
    base::Time end_time,
    base::OnceClosure callback,
    base::CancelableTaskTracker* tracker) {
  DCHECK(backend_task_runner_) << "History service being called after cleanup";
  DCHECK(thread_checker_.CalledOnValidThread());
  tracker->PostTaskAndReply(
      backend_task_runner_.get(), FROM_HERE,
      base::BindOnce(&HistoryBackend::ExpireHistoryBeforeForTesting,
                     history_backend_, end_time),
      std::move(callback));
}

void HistoryService::ExpireLocalAndRemoteHistoryBetween(
    WebHistoryService* web_history,
    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.
  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_t>(),
                                                     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.
    net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
        net::DefinePartialNetworkTrafficAnnotation(
            "web_history_expire_between_dates", "web_history_service", R"(
          semantics {
            description:
              "If a user who syncs their browsing history deletes history "
              "items for a time range, Chrome sends a request to a google.com "
              "host to execute the corresponding deletion serverside."
            trigger:
              "Deleting browsing history for a given time range, e.g. from the "
              "Clear Browsing Data dialog, by an extension, or the "
              "Clear-Site-Data header."
            data:
              "The begin and end timestamps of the selected time range, a "
              "version info token to resolve transaction conflicts, and an "
              "OAuth2 token authenticating the user."
          }
          policy {
            chrome_policy {
              AllowDeletingBrowserHistory {
                AllowDeletingBrowserHistory: false
              }
            }
          })");
    web_history->ExpireHistoryBetween(restrict_urls, begin_time, end_time,
                                      base::Bind(&ExpireWebHistoryComplete),
                                      partial_traffic_annotation);
  }
  ExpireHistoryBetween(restrict_urls, begin_time, end_time, callback, tracker);
}

void HistoryService::OnDBLoaded() {
  DCHECK(thread_checker_.CalledOnValidThread());
  backend_loaded_ = true;
  NotifyHistoryServiceLoaded();
}

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

void HistoryService::NotifyURLsModified(const URLRows& changed_urls) {
  DCHECK(thread_checker_.CalledOnValidThread());
  for (HistoryServiceObserver& observer : observers_)
    observer.OnURLsModified(this, changed_urls);
}

void HistoryService::NotifyURLsDeleted(const DeletionInfo& deletion_info) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!backend_task_runner_)
    return;

  // Inform the VisitDelegate of the deleted URLs. We will inform the delegate
  // of 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 (visit_delegate_) {
    if (deletion_info.IsAllHistory()) {
      visit_delegate_->DeleteAllURLs();
    } else {
      std::vector<GURL> urls;
      urls.reserve(deletion_info.deleted_rows().size());
      for (const auto& row : deletion_info.deleted_rows())
        urls.push_back(row.url());
      visit_delegate_->DeleteURLs(urls);
    }
  }

  for (HistoryServiceObserver& observer : observers_)
    observer.OnURLsDeleted(this, deletion_info);
}

void HistoryService::NotifyHistoryServiceLoaded() {
  DCHECK(thread_checker_.CalledOnValidThread());
  for (HistoryServiceObserver& observer : observers_)
    observer.OnHistoryServiceLoaded(this);
}

void HistoryService::NotifyHistoryServiceBeingDeleted() {
  DCHECK(thread_checker_.CalledOnValidThread());
  for (HistoryServiceObserver& observer : observers_)
    observer.HistoryServiceBeingDeleted(this);
}

void HistoryService::NotifyKeywordSearchTermUpdated(
    const URLRow& row,
    KeywordID keyword_id,
    const base::string16& term) {
  DCHECK(thread_checker_.CalledOnValidThread());
  for (HistoryServiceObserver& observer : observers_)
    observer.OnKeywordSearchTermUpdated(this, row, keyword_id, term);
}

void HistoryService::NotifyKeywordSearchTermDeleted(URLID url_id) {
  DCHECK(thread_checker_.CalledOnValidThread());
  for (HistoryServiceObserver& observer : observers_)
    observer.OnKeywordSearchTermDeleted(this, url_id);
}

std::unique_ptr<
    base::CallbackList<void(const std::set<GURL>&, const GURL&)>::Subscription>
HistoryService::AddFaviconsChangedCallback(
    const HistoryService::OnFaviconsChangedCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  return favicon_changed_callback_list_.Add(callback);
}

void HistoryService::NotifyFaviconsChanged(const std::set<GURL>& page_urls,
                                           const GURL& icon_url) {
  DCHECK(thread_checker_.CalledOnValidThread());
  favicon_changed_callback_list_.Notify(page_urls, icon_url);
}

}  // namespace history
