15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/history_model_worker.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WorkerTask : public history::HistoryDBTask {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkerTask(
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const syncer::WorkCallback& work,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WaitableEvent* done,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncer::SyncerError* error)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : work_(work), done_(done), error_(error) {}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RunOnDBThread(history::HistoryBackend* backend,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             history::HistoryDatabase* db) OVERRIDE {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error_ = work_.Run();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done_->Signal();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // any code asynchronously on the main thread after completion.
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void DoneRunOnMainThread() OVERRIDE {}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WorkerTask() {}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::WorkCallback work_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitableEvent* done_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncerError* error_;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class AddDBThreadObserverTask : public history::HistoryDBTask {
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  explicit AddDBThreadObserverTask(base::Closure register_callback)
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)     : register_callback_(register_callback) {}
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual bool RunOnDBThread(history::HistoryBackend* backend,
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             history::HistoryDatabase* db) OVERRIDE {
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    register_callback_.Run();
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void DoneRunOnMainThread() OVERRIDE {}
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~AddDBThreadObserverTask() {}
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::Closure register_callback_;
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Post the work task on |history_service|'s DB thread from the UI
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PostWorkerTask(const base::WeakPtr<HistoryService>& history_service,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const syncer::WorkCallback& work,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    CancelableRequestConsumerT<int, 0>* cancelable_consumer,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    WaitableEvent* done,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    syncer::SyncerError* error) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (history_service.get()) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<WorkerTask> task(new WorkerTask(work, done, error));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_service->ScheduleDBTask(task.get(), cancelable_consumer);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error = syncer::CANNOT_DO_WORK;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done->Signal();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryModelWorker::HistoryModelWorker(
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::WeakPtr<HistoryService>& history_service,
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    syncer::WorkerLoopDestructionObserver* observer)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  : syncer::ModelSafeWorker(observer),
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    history_service_(history_service) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(history_service.get());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryModelWorker::RegisterForLoopDestruction() {
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK(history_service_.get());
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  history_service_->ScheduleDBTask(
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      new AddDBThreadObserverTask(
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          base::Bind(&HistoryModelWorker::RegisterOnDBThread, this)),
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      &cancelable_consumer_);
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void HistoryModelWorker::RegisterOnDBThread() {
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->AddDestructionObserver(this);
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SetWorkingLoopToCurrent();
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)syncer::SyncerError HistoryModelWorker::DoWorkAndWaitUntilDoneImpl(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::WorkCallback& work) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncerError error = syncer::UNSET;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              base::Bind(&PostWorkerTask, history_service_,
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         work, &cancelable_consumer_,
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         work_done_or_stopped(),
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         &error))) {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    work_done_or_stopped()->Wait();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = syncer::CANNOT_DO_WORK;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncer::GROUP_HISTORY;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryModelWorker::~HistoryModelWorker() {}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace browser_sync
127