• 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,CancelableRequestConsumerT<int,0> * cancelable_consumer,WaitableEvent * done,syncer::SyncerError * error)67 void PostWorkerTask(const base::WeakPtr<HistoryService>& history_service,
68                     const syncer::WorkCallback& work,
69                     CancelableRequestConsumerT<int, 0>* cancelable_consumer,
70                     WaitableEvent* done,
71                     syncer::SyncerError* error) {
72   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
73   if (history_service.get()) {
74     scoped_refptr<WorkerTask> task(new WorkerTask(work, done, error));
75     history_service->ScheduleDBTask(task.get(), cancelable_consumer);
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 }
91 
RegisterForLoopDestruction()92 void HistoryModelWorker::RegisterForLoopDestruction() {
93   CHECK(history_service_.get());
94   history_service_->ScheduleDBTask(
95       new AddDBThreadObserverTask(
96           base::Bind(&HistoryModelWorker::RegisterOnDBThread, this)),
97       &cancelable_consumer_);
98 }
99 
RegisterOnDBThread()100 void HistoryModelWorker::RegisterOnDBThread() {
101   base::MessageLoop::current()->AddDestructionObserver(this);
102   SetWorkingLoopToCurrent();
103 }
104 
DoWorkAndWaitUntilDoneImpl(const syncer::WorkCallback & work)105 syncer::SyncerError HistoryModelWorker::DoWorkAndWaitUntilDoneImpl(
106     const syncer::WorkCallback& work) {
107   syncer::SyncerError error = syncer::UNSET;
108   if (BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
109                               base::Bind(&PostWorkerTask, history_service_,
110                                          work, &cancelable_consumer_,
111                                          work_done_or_stopped(),
112                                          &error))) {
113     work_done_or_stopped()->Wait();
114   } else {
115     error = syncer::CANNOT_DO_WORK;
116   }
117   return error;
118 }
119 
GetModelSafeGroup()120 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() {
121   return syncer::GROUP_HISTORY;
122 }
123 
~HistoryModelWorker()124 HistoryModelWorker::~HistoryModelWorker() {}
125 
126 }  // namespace browser_sync
127