2d8bc7d1435d9a875d34e0cf7bb27b9151df9407
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / ui_model_worker.cc
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/ui_model_worker.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "content/public/browser/browser_thread.h"
14
15 using content::BrowserThread;
16
17 namespace browser_sync {
18
19 namespace {
20
21 // A simple callback to signal a waitable event after running a closure.
22 void CallDoWorkAndSignalCallback(const syncer::WorkCallback& work,
23                                  base::WaitableEvent* work_done,
24                                  syncer::SyncerError* error_info) {
25   if (work.is_null()) {
26     // This can happen during tests or cases where there are more than just the
27     // default UIModelWorker in existence and it gets destroyed before
28     // the main UI loop has terminated.  There is no easy way to assert the
29     // loop is running / not running at the moment, so we just provide cancel
30     // semantics here and short-circuit.
31     // TODO(timsteele): Maybe we should have the message loop destruction
32     // observer fire when the loop has ended, just a bit before it
33     // actually gets destroyed.
34     return;
35   }
36
37   *error_info = work.Run();
38
39   work_done->Signal();  // Unblock the syncer thread that scheduled us.
40 }
41
42 }  // namespace
43
44 UIModelWorker::UIModelWorker(syncer::WorkerLoopDestructionObserver* observer)
45     : syncer::ModelSafeWorker(observer) {
46 }
47
48 void UIModelWorker::RegisterForLoopDestruction() {
49   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
50   base::MessageLoop::current()->AddDestructionObserver(this);
51   SetWorkingLoopToCurrent();
52 }
53
54 syncer::SyncerError UIModelWorker::DoWorkAndWaitUntilDoneImpl(
55     const syncer::WorkCallback& work) {
56   syncer::SyncerError error_info;
57   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
58     DLOG(WARNING) << "DoWorkAndWaitUntilDone called from "
59       << "ui_loop_. Probably a nested invocation?";
60     return work.Run();
61   }
62
63   if (!BrowserThread::PostTask(
64       BrowserThread::UI, FROM_HERE,
65       base::Bind(&CallDoWorkAndSignalCallback,
66                  work, work_done_or_stopped(), &error_info))) {
67     DLOG(WARNING) << "Could not post work to UI loop.";
68     error_info = syncer::CANNOT_DO_WORK;
69     return error_info;
70   }
71   work_done_or_stopped()->Wait();
72
73   return error_info;
74 }
75
76 syncer::ModelSafeGroup UIModelWorker::GetModelSafeGroup() {
77   return syncer::GROUP_UI;
78 }
79
80 UIModelWorker::~UIModelWorker() {
81 }
82
83 }  // namespace browser_sync