Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / sync_driver / glue / history_model_worker.cc
blobb639747967ab72652f3f99cd793a24b4acb69584
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/sync_driver/glue/history_model_worker.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/synchronization/waitable_event.h"
11 using base::WaitableEvent;
13 namespace browser_sync {
15 class WorkerTask : public history::HistoryDBTask {
16 public:
17 WorkerTask(
18 const syncer::WorkCallback& work,
19 WaitableEvent* done,
20 syncer::SyncerError* error)
21 : work_(work), done_(done), error_(error) {}
23 bool RunOnDBThread(history::HistoryBackend* backend,
24 history::HistoryDatabase* db) override {
25 *error_ = work_.Run();
26 done_->Signal();
27 return true;
30 // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run
31 // any code asynchronously on the main thread after completion.
32 void DoneRunOnMainThread() override {}
34 protected:
35 ~WorkerTask() override {}
37 syncer::WorkCallback work_;
38 WaitableEvent* done_;
39 syncer::SyncerError* error_;
42 class AddDBThreadObserverTask : public history::HistoryDBTask {
43 public:
44 explicit AddDBThreadObserverTask(base::Closure register_callback)
45 : register_callback_(register_callback) {}
47 bool RunOnDBThread(history::HistoryBackend* backend,
48 history::HistoryDatabase* db) override {
49 register_callback_.Run();
50 return true;
53 void DoneRunOnMainThread() override {}
55 private:
56 ~AddDBThreadObserverTask() override {}
58 base::Closure register_callback_;
61 namespace {
63 // Post the work task on |history_service|'s DB thread from the UI
64 // thread.
65 void PostWorkerTask(
66 const base::WeakPtr<history::HistoryService>& history_service,
67 const syncer::WorkCallback& work,
68 base::CancelableTaskTracker* cancelable_tracker,
69 WaitableEvent* done,
70 syncer::SyncerError* error) {
71 if (history_service.get()) {
72 scoped_ptr<history::HistoryDBTask> task(new WorkerTask(work, done, error));
73 history_service->ScheduleDBTask(task.Pass(), cancelable_tracker);
74 } else {
75 *error = syncer::CANNOT_DO_WORK;
76 done->Signal();
80 } // namespace
82 HistoryModelWorker::HistoryModelWorker(
83 const base::WeakPtr<history::HistoryService>& history_service,
84 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
85 syncer::WorkerLoopDestructionObserver* observer)
86 : syncer::ModelSafeWorker(observer),
87 history_service_(history_service),
88 ui_thread_(ui_thread) {
89 CHECK(history_service.get());
90 DCHECK(ui_thread_->BelongsToCurrentThread());
91 cancelable_tracker_.reset(new base::CancelableTaskTracker);
94 void HistoryModelWorker::RegisterForLoopDestruction() {
95 CHECK(history_service_.get());
96 history_service_->ScheduleDBTask(
97 scoped_ptr<history::HistoryDBTask>(new AddDBThreadObserverTask(
98 base::Bind(&HistoryModelWorker::RegisterOnDBThread, this))),
99 cancelable_tracker_.get());
102 void HistoryModelWorker::RegisterOnDBThread() {
103 SetWorkingLoopToCurrent();
106 syncer::SyncerError HistoryModelWorker::DoWorkAndWaitUntilDoneImpl(
107 const syncer::WorkCallback& work) {
108 syncer::SyncerError error = syncer::UNSET;
109 if (ui_thread_->PostTask(FROM_HERE,
110 base::Bind(&PostWorkerTask, history_service_, work,
111 cancelable_tracker_.get(),
112 work_done_or_stopped(), &error))) {
113 work_done_or_stopped()->Wait();
114 } else {
115 error = syncer::CANNOT_DO_WORK;
117 return error;
120 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() {
121 return syncer::GROUP_HISTORY;
124 HistoryModelWorker::~HistoryModelWorker() {
125 // The base::CancelableTaskTracker class is not thread-safe and must only be
126 // used from a single thread but the current object may not be destroyed from
127 // the UI thread, so delete it from the UI thread.
128 ui_thread_->DeleteSoon(FROM_HERE, cancelable_tracker_.release());
131 } // namespace browser_sync