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/browser_thread_model_worker.h"
6
7#include "base/bind.h"
8#include "base/synchronization/waitable_event.h"
9#include "content/public/browser/browser_thread.h"
10
11using base::WaitableEvent;
12using content::BrowserThread;
13
14namespace browser_sync {
15
16BrowserThreadModelWorker::BrowserThreadModelWorker(
17    BrowserThread::ID thread, syncer::ModelSafeGroup group,
18    syncer::WorkerLoopDestructionObserver* observer)
19    : ModelSafeWorker(observer),
20      thread_(thread), group_(group) {
21}
22
23syncer::SyncerError BrowserThreadModelWorker::DoWorkAndWaitUntilDoneImpl(
24    const syncer::WorkCallback& work) {
25  syncer::SyncerError error = syncer::UNSET;
26  if (BrowserThread::CurrentlyOn(thread_)) {
27    DLOG(WARNING) << "Already on thread " << thread_;
28    return work.Run();
29  }
30
31  if (!BrowserThread::PostTask(
32      thread_,
33      FROM_HERE,
34      base::Bind(&BrowserThreadModelWorker::CallDoWorkAndSignalTask,
35                 this, work,
36                 work_done_or_stopped(), &error))) {
37    DLOG(WARNING) << "Failed to post task to thread " << thread_;
38    error = syncer::CANNOT_DO_WORK;
39    return error;
40  }
41  work_done_or_stopped()->Wait();
42  return error;
43}
44
45syncer::ModelSafeGroup BrowserThreadModelWorker::GetModelSafeGroup() {
46  return group_;
47}
48
49BrowserThreadModelWorker::~BrowserThreadModelWorker() {}
50
51void BrowserThreadModelWorker::RegisterForLoopDestruction() {
52  if (BrowserThread::CurrentlyOn(thread_)) {
53    SetWorkingLoopToCurrent();
54  } else {
55    BrowserThread::PostTask(
56        thread_, FROM_HERE,
57        Bind(&BrowserThreadModelWorker::RegisterForLoopDestruction, this));
58  }
59}
60
61void BrowserThreadModelWorker::CallDoWorkAndSignalTask(
62    const syncer::WorkCallback& work,
63    WaitableEvent* done,
64    syncer::SyncerError* error) {
65  DCHECK(BrowserThread::CurrentlyOn(thread_));
66  if (!IsStopped())
67    *error = work.Run();
68  done->Signal();
69}
70
71DatabaseModelWorker::DatabaseModelWorker(
72    syncer::WorkerLoopDestructionObserver* observer)
73    : BrowserThreadModelWorker(BrowserThread::DB, syncer::GROUP_DB, observer) {
74}
75
76void DatabaseModelWorker::CallDoWorkAndSignalTask(
77    const syncer::WorkCallback& work,
78    WaitableEvent* done,
79    syncer::SyncerError* error) {
80  BrowserThreadModelWorker::CallDoWorkAndSignalTask(work, done, error);
81}
82
83DatabaseModelWorker::~DatabaseModelWorker() {}
84
85FileModelWorker::FileModelWorker(
86    syncer::WorkerLoopDestructionObserver* observer)
87    : BrowserThreadModelWorker(BrowserThread::FILE, syncer::GROUP_FILE,
88                               observer) {
89}
90
91void FileModelWorker::CallDoWorkAndSignalTask(
92    const syncer::WorkCallback& work,
93    WaitableEvent* done,
94    syncer::SyncerError* error) {
95  BrowserThreadModelWorker::CallDoWorkAndSignalTask(work, done, error);
96}
97
98FileModelWorker::~FileModelWorker() {}
99
100}  // namespace browser_sync
101