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
{
18 const syncer::WorkCallback
& work
,
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();
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
{}
35 ~WorkerTask() override
{}
37 syncer::WorkCallback work_
;
39 syncer::SyncerError
* error_
;
42 class AddDBThreadObserverTask
: public history::HistoryDBTask
{
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();
53 void DoneRunOnMainThread() override
{}
56 ~AddDBThreadObserverTask() override
{}
58 base::Closure register_callback_
;
63 // Post the work task on |history_service|'s DB thread from the UI
66 const base::WeakPtr
<history::HistoryService
>& history_service
,
67 const syncer::WorkCallback
& work
,
68 base::CancelableTaskTracker
* cancelable_tracker
,
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
);
75 *error
= syncer::CANNOT_DO_WORK
;
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();
115 error
= syncer::CANNOT_DO_WORK
;
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