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 "chromeos/dbus/blocking_method_caller.h"
6
7#include "base/bind.h"
8#include "base/callback_helpers.h"
9#include "base/location.h"
10#include "base/task_runner.h"
11#include "base/threading/thread_restrictions.h"
12#include "dbus/bus.h"
13#include "dbus/object_proxy.h"
14
15namespace chromeos {
16
17namespace {
18
19// This function is a part of CallMethodAndBlock implementation.
20void CallMethodAndBlockInternal(
21    scoped_ptr<dbus::Response>* response,
22    base::ScopedClosureRunner* signaler,
23    dbus::ObjectProxy* proxy,
24    dbus::MethodCall* method_call) {
25  *response = proxy->CallMethodAndBlock(
26      method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
27}
28
29}  // namespace
30
31BlockingMethodCaller::BlockingMethodCaller(dbus::Bus* bus,
32                                           dbus::ObjectProxy* proxy)
33    : bus_(bus),
34      proxy_(proxy),
35      on_blocking_method_call_(false /* manual_reset */,
36                               false /* initially_signaled */) {
37}
38
39BlockingMethodCaller::~BlockingMethodCaller() {
40}
41
42scoped_ptr<dbus::Response> BlockingMethodCaller::CallMethodAndBlock(
43    dbus::MethodCall* method_call) {
44  // on_blocking_method_call_->Signal() will be called when |signaler| is
45  // destroyed.
46  base::Closure signal_task(
47      base::Bind(&base::WaitableEvent::Signal,
48                 base::Unretained(&on_blocking_method_call_)));
49  base::ScopedClosureRunner* signaler =
50      new base::ScopedClosureRunner(signal_task);
51
52  scoped_ptr<dbus::Response> response;
53  bus_->GetDBusTaskRunner()->PostTask(
54      FROM_HERE,
55      base::Bind(&CallMethodAndBlockInternal,
56                 &response,
57                 base::Owned(signaler),
58                 base::Unretained(proxy_),
59                 method_call));
60  // http://crbug.com/125360
61  base::ThreadRestrictions::ScopedAllowWait allow_wait;
62  on_blocking_method_call_.Wait();
63  return response.Pass();
64}
65
66}  // namespace chromeos
67