• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/sync/glue/history_model_worker.h"
6 
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"
11 
12 using base::WaitableEvent;
13 using content::BrowserThread;
14 
15 namespace browser_sync {
16 
17 class WorkerTask : public history::HistoryDBTask {
18  public:
WorkerTask(const syncer::WorkCallback & work,WaitableEvent * done,syncer::SyncerError * error)19   WorkerTask(
20       const syncer::WorkCallback& work,
21       WaitableEvent* done,
22       syncer::SyncerError* error)
23     : work_(work), done_(done), error_(error) {}
24 
RunOnDBThread(history::HistoryBackend * backend,history::HistoryDatabase * db)25   virtual bool RunOnDBThread(history::HistoryBackend* backend,
26                              history::HistoryDatabase* db) OVERRIDE {
27     *error_ = work_.Run();
28     done_->Signal();
29     return true;
30   }
31 
32   // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run
33   // any code asynchronously on the main thread after completion.
DoneRunOnMainThread()34   virtual void DoneRunOnMainThread() OVERRIDE {}
35 
36  protected:
~WorkerTask()37   virtual ~WorkerTask() {}
38 
39   syncer::WorkCallback work_;
40   WaitableEvent* done_;
41   syncer::SyncerError* error_;
42 };
43 
44 class AddDBThreadObserverTask : public history::HistoryDBTask {
45  public:
AddDBThreadObserverTask(base::Closure register_callback)46   explicit AddDBThreadObserverTask(base::Closure register_callback)
47      : register_callback_(register_callback) {}
48 
RunOnDBThread(history::HistoryBackend * backend,history::HistoryDatabase * db)49   virtual bool RunOnDBThread(history::HistoryBackend* backend,
50                              history::HistoryDatabase* db) OVERRIDE {
51     register_callback_.Run();
52     return true;
53   }
54 
DoneRunOnMainThread()55   virtual void DoneRunOnMainThread() OVERRIDE {}
56 
57  private:
~AddDBThreadObserverTask()58   virtual ~AddDBThreadObserverTask() {}
59 
60   base::Closure register_callback_;
61 };
62 
63 namespace {
64 
65 // Post the work task on |history_service|'s DB thread from the UI
66 // thread.
PostWorkerTask(const base::WeakPtr<HistoryService> & history_service,const syncer::WorkCallback & work,base::CancelableTaskTracker * cancelable_tracker,WaitableEvent * done,syncer::SyncerError * error)67 void PostWorkerTask(const base::WeakPtr<HistoryService>& history_service,
68                     const syncer::WorkCallback& work,
69                     base::CancelableTaskTracker* cancelable_tracker,
70                     WaitableEvent* done,
71                     syncer::SyncerError* error) {
72   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
73   if (history_service.get()) {
74     scoped_ptr<history::HistoryDBTask> task(new WorkerTask(work, done, error));
75     history_service->ScheduleDBTask(task.Pass(), cancelable_tracker);
76   } else {
77     *error = syncer::CANNOT_DO_WORK;
78     done->Signal();
79   }
80 }
81 
82 }  // namespace
83 
HistoryModelWorker(const base::WeakPtr<HistoryService> & history_service,syncer::WorkerLoopDestructionObserver * observer)84 HistoryModelWorker::HistoryModelWorker(
85     const base::WeakPtr<HistoryService>& history_service,
86     syncer::WorkerLoopDestructionObserver* observer)
87   : syncer::ModelSafeWorker(observer),
88     history_service_(history_service) {
89   CHECK(history_service.get());
90   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91   cancelable_tracker_.reset(new base::CancelableTaskTracker);
92 }
93 
RegisterForLoopDestruction()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());
100 }
101 
RegisterOnDBThread()102 void HistoryModelWorker::RegisterOnDBThread() {
103   SetWorkingLoopToCurrent();
104 }
105 
DoWorkAndWaitUntilDoneImpl(const syncer::WorkCallback & work)106 syncer::SyncerError HistoryModelWorker::DoWorkAndWaitUntilDoneImpl(
107     const syncer::WorkCallback& work) {
108   syncer::SyncerError error = syncer::UNSET;
109   if (BrowserThread::PostTask(BrowserThread::UI,
110                               FROM_HERE,
111                               base::Bind(&PostWorkerTask,
112                                          history_service_,
113                                          work,
114                                          cancelable_tracker_.get(),
115                                          work_done_or_stopped(),
116                                          &error))) {
117     work_done_or_stopped()->Wait();
118   } else {
119     error = syncer::CANNOT_DO_WORK;
120   }
121   return error;
122 }
123 
GetModelSafeGroup()124 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() {
125   return syncer::GROUP_HISTORY;
126 }
127 
~HistoryModelWorker()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());
133 }
134 
135 }  // namespace browser_sync
136