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: 19 WorkerTask( 20 const syncer::WorkCallback& work, 21 WaitableEvent* done, 22 syncer::SyncerError* error) 23 : work_(work), done_(done), error_(error) {} 24 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. 34 virtual void DoneRunOnMainThread() OVERRIDE {} 35 36 protected: 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: 46 explicit AddDBThreadObserverTask(base::Closure register_callback) 47 : register_callback_(register_callback) {} 48 49 virtual bool RunOnDBThread(history::HistoryBackend* backend, 50 history::HistoryDatabase* db) OVERRIDE { 51 register_callback_.Run(); 52 return true; 53 } 54 55 virtual void DoneRunOnMainThread() OVERRIDE {} 56 57 private: 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. 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 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 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 100 void HistoryModelWorker::RegisterOnDBThread() { 101 base::MessageLoop::current()->AddDestructionObserver(this); 102 SetWorkingLoopToCurrent(); 103 } 104 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 120 syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() { 121 return syncer::GROUP_HISTORY; 122 } 123 124 HistoryModelWorker::~HistoryModelWorker() {} 125 126 } // namespace browser_sync 127