1 // Copyright (c) 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 "chrome/browser/sync/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"
10 #include "content/public/browser/browser_thread.h"
12 using base::WaitableEvent
;
13 using content::BrowserThread
;
15 namespace browser_sync
{
17 class WorkerTask
: public history::HistoryDBTask
{
20 const syncer::WorkCallback
& work
,
22 syncer::SyncerError
* error
)
23 : work_(work
), done_(done
), error_(error
) {}
25 bool RunOnDBThread(history::HistoryBackend
* backend
,
26 history::HistoryDatabase
* db
) override
{
27 *error_
= work_
.Run();
32 // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run
33 // any code asynchronously on the main thread after completion.
34 void DoneRunOnMainThread() override
{}
37 ~WorkerTask() override
{}
39 syncer::WorkCallback work_
;
41 syncer::SyncerError
* error_
;
44 class AddDBThreadObserverTask
: public history::HistoryDBTask
{
46 explicit AddDBThreadObserverTask(base::Closure register_callback
)
47 : register_callback_(register_callback
) {}
49 bool RunOnDBThread(history::HistoryBackend
* backend
,
50 history::HistoryDatabase
* db
) override
{
51 register_callback_
.Run();
55 void DoneRunOnMainThread() override
{}
58 ~AddDBThreadObserverTask() override
{}
60 base::Closure register_callback_
;
65 // Post the work task on |history_service|'s DB thread from the UI
68 const base::WeakPtr
<history::HistoryService
>& history_service
,
69 const syncer::WorkCallback
& work
,
70 base::CancelableTaskTracker
* cancelable_tracker
,
72 syncer::SyncerError
* error
) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
74 if (history_service
.get()) {
75 scoped_ptr
<history::HistoryDBTask
> task(new WorkerTask(work
, done
, error
));
76 history_service
->ScheduleDBTask(task
.Pass(), cancelable_tracker
);
78 *error
= syncer::CANNOT_DO_WORK
;
85 HistoryModelWorker::HistoryModelWorker(
86 const base::WeakPtr
<history::HistoryService
>& history_service
,
87 syncer::WorkerLoopDestructionObserver
* observer
)
88 : syncer::ModelSafeWorker(observer
), history_service_(history_service
) {
89 CHECK(history_service
.get());
90 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
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 (BrowserThread::PostTask(BrowserThread::UI
,
111 base::Bind(&PostWorkerTask
,
114 cancelable_tracker_
.get(),
115 work_done_or_stopped(),
117 work_done_or_stopped()->Wait();
119 error
= syncer::CANNOT_DO_WORK
;
124 syncer::ModelSafeGroup
HistoryModelWorker::GetModelSafeGroup() {
125 return syncer::GROUP_HISTORY
;
128 HistoryModelWorker::~HistoryModelWorker() {
129 // The base::CancelableTaskTracker class is not thread-safe and must only be
130 // used from a single thread but the current object may not be destroyed from
131 // the UI thread, so delete it from the UI thread.
132 BrowserThread::DeleteOnUIThread::Destruct(cancelable_tracker_
.release());
135 } // namespace browser_sync