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.
5 #include "chrome/browser/sync/glue/ui_model_worker.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"
15 using content::BrowserThread
;
17 namespace browser_sync
{
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
) {
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.
37 *error_info
= work
.Run();
39 work_done
->Signal(); // Unblock the syncer thread that scheduled us.
44 UIModelWorker::UIModelWorker(syncer::WorkerLoopDestructionObserver
* observer
)
45 : syncer::ModelSafeWorker(observer
) {
48 void UIModelWorker::RegisterForLoopDestruction() {
49 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
50 base::MessageLoop::current()->AddDestructionObserver(this);
51 SetWorkingLoopToCurrent();
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?";
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
;
71 work_done_or_stopped()->Wait();
76 syncer::ModelSafeGroup
UIModelWorker::GetModelSafeGroup() {
77 return syncer::GROUP_UI
;
80 UIModelWorker::~UIModelWorker() {
83 } // namespace browser_sync