| Index: chrome/browser/history/history_backend.cc
|
| diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
|
| index c7fc71a026ddcf254be531525021783e990e190b..c72f8c01d969086ed87725711096763af815f977 100644
|
| --- a/chrome/browser/history/history_backend.cc
|
| +++ b/chrome/browser/history/history_backend.cc
|
| @@ -67,6 +67,15 @@ using base::TimeTicks;
|
|
|
| namespace history {
|
|
|
| +namespace {
|
| +void RunUnlessCanceled(
|
| + const base::Closure& closure,
|
| + const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) {
|
| + if (!is_canceled.Run())
|
| + closure.Run();
|
| +}
|
| +} // namespace
|
| +
|
| #if defined(OS_ANDROID)
|
| // How long we keep segment data for in days. Currently 3 months.
|
| // This value needs to be greater or equal to
|
| @@ -155,6 +164,38 @@ class CommitLaterTask : public base::RefCounted<CommitLaterTask> {
|
| scoped_refptr<HistoryBackend> history_backend_;
|
| };
|
|
|
| +// QueuedHistoryDBTask ---------------------------------------------------------
|
| +
|
| +QueuedHistoryDBTask::QueuedHistoryDBTask(
|
| + scoped_refptr<HistoryDBTask> task,
|
| + scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
|
| + const base::CancelableTaskTracker::IsCanceledCallback& is_canceled)
|
| + : task_(task), origin_loop_(origin_loop), is_canceled_(is_canceled) {
|
| + DCHECK(task_);
|
| + DCHECK(origin_loop_);
|
| + DCHECK(!is_canceled_.is_null());
|
| +}
|
| +
|
| +QueuedHistoryDBTask::~QueuedHistoryDBTask() {
|
| +}
|
| +
|
| +bool QueuedHistoryDBTask::is_canceled() {
|
| + return is_canceled_.Run();
|
| +}
|
| +
|
| +bool QueuedHistoryDBTask::RunOnDBThread(HistoryBackend* backend,
|
| + HistoryDatabase* db) {
|
| + return task_->RunOnDBThread(backend, db);
|
| +}
|
| +
|
| +void QueuedHistoryDBTask::DoneRunOnMainThread() {
|
| + origin_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&RunUnlessCanceled,
|
| + base::Bind(&HistoryDBTask::DoneRunOnMainThread, task_),
|
| + is_canceled_));
|
| +}
|
| +
|
| // HistoryBackend --------------------------------------------------------------
|
|
|
| HistoryBackend::HistoryBackend(const base::FilePath& history_dir,
|
| @@ -172,7 +213,7 @@ HistoryBackend::HistoryBackend(const base::FilePath& history_dir,
|
|
|
| HistoryBackend::~HistoryBackend() {
|
| DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup";
|
| - ReleaseDBTasks();
|
| + queued_history_db_tasks_.clear();
|
|
|
| #if defined(OS_ANDROID)
|
| // Release AndroidProviderBackend before other objects.
|
| @@ -2288,43 +2329,36 @@ void HistoryBackend::CancelScheduledCommit() {
|
| void HistoryBackend::ProcessDBTaskImpl() {
|
| if (!db_) {
|
| // db went away, release all the refs.
|
| - ReleaseDBTasks();
|
| + queued_history_db_tasks_.clear();
|
| return;
|
| }
|
|
|
| // Remove any canceled tasks.
|
| - while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) {
|
| - db_task_requests_.front()->Release();
|
| - db_task_requests_.pop_front();
|
| + while (!queued_history_db_tasks_.empty()) {
|
| + QueuedHistoryDBTask& task = queued_history_db_tasks_.front();
|
| + if (!task.is_canceled()) {
|
| + break;
|
| + }
|
| + queued_history_db_tasks_.pop_front();
|
| }
|
| - if (db_task_requests_.empty())
|
| + if (queued_history_db_tasks_.empty())
|
| return;
|
|
|
| // Run the first task.
|
| - HistoryDBTaskRequest* request = db_task_requests_.front();
|
| - db_task_requests_.pop_front();
|
| - if (request->value->RunOnDBThread(this, db_.get())) {
|
| - // The task is done. Notify the callback.
|
| - request->ForwardResult();
|
| - // We AddRef'd the request before adding, need to release it now.
|
| - request->Release();
|
| + QueuedHistoryDBTask task = queued_history_db_tasks_.front();
|
| + queued_history_db_tasks_.pop_front();
|
| + if (task.RunOnDBThread(this, db_.get())) {
|
| + // The task is done, notify the callback.
|
| + task.DoneRunOnMainThread();
|
| } else {
|
| - // Tasks wants to run some more. Schedule it at the end of current tasks.
|
| - db_task_requests_.push_back(request);
|
| - // And process it after an invoke later.
|
| + // The task wants to run some more. Schedule it at the end of the current
|
| + // tasks, and process it after an invoke later.
|
| + queued_history_db_tasks_.insert(queued_history_db_tasks_.end(), task);
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this));
|
| }
|
| }
|
|
|
| -void HistoryBackend::ReleaseDBTasks() {
|
| - for (std::list<HistoryDBTaskRequest*>::iterator i =
|
| - db_task_requests_.begin(); i != db_task_requests_.end(); ++i) {
|
| - (*i)->Release();
|
| - }
|
| - db_task_requests_.clear();
|
| -}
|
| -
|
| ////////////////////////////////////////////////////////////////////////////////
|
| //
|
| // Generic operations
|
| @@ -2505,20 +2539,15 @@ void HistoryBackend::KillHistoryDatabase() {
|
| }
|
|
|
| void HistoryBackend::ProcessDBTask(
|
| - scoped_refptr<HistoryDBTaskRequest> request) {
|
| - DCHECK(request.get());
|
| - if (request->canceled())
|
| - return;
|
| -
|
| - bool task_scheduled = !db_task_requests_.empty();
|
| - // Make sure we up the refcount of the request. ProcessDBTaskImpl will
|
| - // release when done with the task.
|
| - request->AddRef();
|
| - db_task_requests_.push_back(request.get());
|
| - if (!task_scheduled) {
|
| - // No other tasks are scheduled. Process request now.
|
| + scoped_refptr<HistoryDBTask> task,
|
| + scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
|
| + const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) {
|
| + bool scheduled = !queued_history_db_tasks_.empty();
|
| + queued_history_db_tasks_.insert(
|
| + queued_history_db_tasks_.end(),
|
| + QueuedHistoryDBTask(task, origin_loop, is_canceled));
|
| + if (!scheduled)
|
| ProcessDBTaskImpl();
|
| - }
|
| }
|
|
|
| void HistoryBackend::BroadcastNotifications(
|
|
|