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 "dbus/bus.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/exported_object.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "dbus/message.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/object_manager.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/scoped_dbus_error.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace dbus {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDisconnectedSignal[] = "Disconnected";
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDisconnectedMatchRule[] =
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "type='signal', path='/org/freedesktop/DBus/Local',"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "interface='org.freedesktop.DBus.Local', member='Disconnected'";
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The NameOwnerChanged member in org.freedesktop.DBus
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kNameOwnerChangedSignal[] = "NameOwnerChanged";
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The match rule used to filter for changes to a given service name owner.
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kServiceNameOwnerChangeMatchRule[] =
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "type='signal',interface='org.freedesktop.DBus',"
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "member='NameOwnerChanged',path='/org/freedesktop/DBus',"
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "sender='org.freedesktop.DBus',arg0='%s'";
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The class is used for watching the file descriptor used for D-Bus
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// communication.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Watch : public base::MessagePumpLibevent::Watcher {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit Watch(DBusWatch* watch)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : raw_watch_(watch) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_watch_set_data(raw_watch_, this, NULL);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Watch() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_watch_set_data(raw_watch_, NULL, NULL);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the underlying file descriptor is ready to be watched.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsReadyToBeWatched() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dbus_watch_get_enabled(raw_watch_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts watching the underlying file descriptor.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartWatching() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int file_descriptor = dbus_watch_get_unix_fd(raw_watch_);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int flags = dbus_watch_get_flags(raw_watch_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopForIO::Mode mode = base::MessageLoopForIO::WATCH_READ;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE))
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mode = base::MessageLoopForIO::WATCH_READ_WRITE;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (flags & DBUS_WATCH_READABLE)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mode = base::MessageLoopForIO::WATCH_READ;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (flags & DBUS_WATCH_WRITABLE)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mode = base::MessageLoopForIO::WATCH_WRITE;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool persistent = true;  // Watch persistently.
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        file_descriptor, persistent, mode, &file_descriptor_watcher_, this);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(success) << "Unable to allocate memory";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stops watching the underlying file descriptor.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopWatching() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_descriptor_watcher_.StopWatchingFileDescriptor();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implement MessagePumpLibevent::Watcher.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanReadWithoutBlocking(int file_descriptor) OVERRIDE {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_READABLE);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(success) << "Unable to allocate memory";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implement MessagePumpLibevent::Watcher.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int file_descriptor) OVERRIDE {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_WRITABLE);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(success) << "Unable to allocate memory";
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusWatch* raw_watch_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePumpLibevent::FileDescriptorWatcher file_descriptor_watcher_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The class is used for monitoring the timeout used for D-Bus method
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calls.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unlike Watch, Timeout is a ref counted object, to ensure that |this| of
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the object is is alive when HandleTimeout() is called. It's unlikely
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but it may be possible that HandleTimeout() is called after
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Bus::OnRemoveTimeout(). That's why we don't simply delete the object in
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Bus::OnRemoveTimeout().
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Timeout : public base::RefCountedThreadSafe<Timeout> {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit Timeout(DBusTimeout* timeout)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : raw_timeout_(timeout),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        monitoring_is_active_(false),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is_completed(false) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_timeout_set_data(raw_timeout_, this, NULL);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddRef();  // Balanced on Complete().
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the timeout is ready to be monitored.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsReadyToBeMonitored() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dbus_timeout_get_enabled(raw_timeout_);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts monitoring the timeout.
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void StartMonitoring(Bus* bus) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->PostDelayedTaskToDBusThread(FROM_HERE,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Bind(&Timeout::HandleTimeout,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                this),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     GetInterval());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    monitoring_is_active_ = true;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stops monitoring the timeout.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopMonitoring() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We cannot take back the delayed task we posted in
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // StartMonitoring(), so we just mark the monitoring is inactive now.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    monitoring_is_active_ = false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the interval.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta GetInterval() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::TimeDelta::FromMilliseconds(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus_timeout_get_interval(raw_timeout_));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleans up the raw_timeout and marks that timeout is completed.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the class comment above for why we are doing this.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Complete() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_timeout_set_data(raw_timeout_, NULL, NULL);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_completed = true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Release();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Timeout>;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Timeout() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handles the timeout.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleTimeout() {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the timeout is marked completed, we should do nothing. This can
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // occur if this function is called after Bus::OnRemoveTimeout().
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_completed)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip if monitoring is canceled.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!monitoring_is_active_)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool success = dbus_timeout_handle(raw_timeout_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(success) << "Unable to allocate memory";
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusTimeout* raw_timeout_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool monitoring_is_active_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_completed;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bus::Options::Options()
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : bus_type(SESSION),
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_type(PRIVATE) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bus::Options::~Options() {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bus::Bus(const Options& options)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : bus_type_(options.bus_type),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_type_(options.connection_type),
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus_task_runner_(options.dbus_task_runner),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_shutdown_(false /* manual_reset */, false /* initially_signaled */),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_(NULL),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin_thread_id_(base::PlatformThread::CurrentId()),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      async_operations_set_up_(false),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_completed_(false),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_pending_watches_(0),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_pending_timeouts_(0),
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      address_(options.address),
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      on_disconnected_closure_(options.disconnected_callback) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is safe to call multiple times.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_threads_init_default();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The origin message loop is unnecessary if the client uses synchronous
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // functions only.
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::MessageLoop::current())
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    origin_task_runner_ = base::MessageLoop::current()->message_loop_proxy();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bus::~Bus() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!connection_);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(owned_service_names_.empty());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(match_rules_added_.empty());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(filter_functions_added_.empty());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(registered_object_paths_.empty());
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0, num_pending_watches_);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(satorux): This check fails occasionally in browser_tests for tests
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that run very quickly. Perhaps something does not have time to clean up.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Despite the check failing, the tests seem to run fine. crosbug.com/23416
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DCHECK_EQ(0, num_pending_timeouts_);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ObjectPath& object_path) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetObjectProxyWithOptions(service_name, object_path,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   ObjectProxy::DEFAULT_OPTIONS);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectProxy* Bus::GetObjectProxyWithOptions(const std::string& service_name,
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                            const ObjectPath& object_path,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int options) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnOriginThread();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we already have the requested object proxy.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ObjectProxyTable::key_type key(service_name + object_path.value(),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       options);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObjectProxyTable::iterator iter = object_proxy_table_.find(key);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter != object_proxy_table_.end()) {
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return iter->second.get();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ObjectProxy> object_proxy =
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ObjectProxy(this, service_name, object_path, options);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object_proxy_table_[key] = object_proxy;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return object_proxy.get();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Bus::RemoveObjectProxy(const std::string& service_name,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const ObjectPath& object_path,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const base::Closure& callback) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return RemoveObjectProxyWithOptions(service_name, object_path,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      ObjectProxy::DEFAULT_OPTIONS,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      callback);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Bus::RemoveObjectProxyWithOptions(const std::string& service_name,
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       const ObjectPath& object_path,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int options,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::Closure& callback) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnOriginThread();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if we have the requested object proxy.
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ObjectProxyTable::key_type key(service_name + object_path.value(),
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       options);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ObjectProxyTable::iterator iter = object_proxy_table_.find(key);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != object_proxy_table_.end()) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Object is present. Remove it now and Detach in the DBus thread.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostTaskToDBusThread(FROM_HERE, base::Bind(
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &Bus::RemoveObjectProxyInternal,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this, iter->second, callback));
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    object_proxy_table_.erase(iter);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void Bus::RemoveObjectProxyInternal(scoped_refptr<ObjectProxy> object_proxy,
2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    const base::Closure& callback) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnDBusThread();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_proxy.get()->Detach();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostTaskToOriginThread(FROM_HERE, callback);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExportedObject* Bus::GetExportedObject(const ObjectPath& object_path) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnOriginThread();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we already have the requested exported object.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExportedObjectTable::iterator iter = exported_object_table_.find(object_path);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter != exported_object_table_.end()) {
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return iter->second.get();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExportedObject> exported_object =
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ExportedObject(this, object_path);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exported_object_table_[object_path] = exported_object;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return exported_object.get();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::UnregisterExportedObject(const ObjectPath& object_path) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnOriginThread();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the registered object from the table first, to allow a new
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetExportedObject() call to return a new object, rather than this one.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExportedObjectTable::iterator iter = exported_object_table_.find(object_path);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == exported_object_table_.end())
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExportedObject> exported_object = iter->second;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exported_object_table_.erase(iter);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post the task to perform the final unregistration to the D-Bus thread.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the registration also happens on the D-Bus thread in
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TryRegisterObjectPath(), and the task runner we post to is a
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SequencedTaskRunner, there is a guarantee that this will happen before any
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // future registration call.
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PostTaskToDBusThread(FROM_HERE,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       base::Bind(&Bus::UnregisterExportedObjectInternal,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  this, exported_object));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::UnregisterExportedObjectInternal(
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<ExportedObject> exported_object) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exported_object->Unregister();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ObjectManager* Bus::GetObjectManager(const std::string& service_name,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const ObjectPath& object_path) {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnOriginThread();
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if we already have the requested object manager.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ObjectManagerTable::key_type key(service_name + object_path.value());
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ObjectManagerTable::iterator iter = object_manager_table_.find(key);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != object_manager_table_.end()) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return iter->second.get();
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ObjectManager> object_manager =
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ObjectManager(this, service_name, object_path);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_manager_table_[key] = object_manager;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return object_manager.get();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Bus::RemoveObjectManager(const std::string& service_name,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const ObjectPath& object_path) {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnOriginThread();
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ObjectManagerTable::key_type key(service_name + object_path.value());
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ObjectManagerTable::iterator iter = object_manager_table_.find(key);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == object_manager_table_.end())
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ObjectManager> object_manager = iter->second;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_manager_table_.erase(iter);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Bus::GetManagedObjects() {
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ObjectManagerTable::iterator iter = object_manager_table_.begin();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != object_manager_table_.end(); ++iter) {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iter->second->GetManagedObjects();
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::Connect() {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_bus_get_private() and dbus_bus_get() are blocking calls.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if it's already initialized.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connection_)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDBusError error;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bus_type_ == CUSTOM_ADDRESS) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (connection_type_ == PRIVATE) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_ = dbus_connection_open_private(address_.c_str(), error.get());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_ = dbus_connection_open(address_.c_str(), error.get());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (connection_type_ == PRIVATE) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_ = dbus_bus_get_private(dbus_bus_type, error.get());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_ = dbus_bus_get(dbus_bus_type, error.get());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!connection_) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to connect to the bus: "
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << (error.is_set() ? error.message() : "");
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bus_type_ == CUSTOM_ADDRESS) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should call dbus_bus_register here, otherwise unique name can not be
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // acquired. According to dbus specification, it is responsible to call
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // org.freedesktop.DBus.Hello method at the beging of bus connection to
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // acquire unique name. In the case of dbus_bus_get, dbus_bus_register is
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // called internally.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!dbus_bus_register(connection_, error.get())) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to register the bus component: "
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << (error.is_set() ? error.message() : "");
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We shouldn't exit on the disconnected signal.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_connection_set_exit_on_disconnect(connection_, false);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Watch Disconnected signal.
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddFilterFunction(Bus::OnConnectionDisconnectedFilter, this);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddMatch(kDisconnectedMatchRule, error.get());
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Bus::ClosePrivateConnection() {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // dbus_connection_close is blocking call.
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnDBusThread();
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(PRIVATE, connection_type_)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "non-private connection should not be closed";
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dbus_connection_close(connection_);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::ShutdownAndBlock() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (shutdown_completed_)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // Already shutdowned, just return.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unregister the exported objects.
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExportedObjectTable::iterator iter = exported_object_table_.begin();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != exported_object_table_.end(); ++iter) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->second->Unregister();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release all service names.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator iter = owned_service_names_.begin();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != owned_service_names_.end();) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is a bit tricky but we should increment the iter here as
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ReleaseOwnership() may remove |service_name| from the set.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_name = *iter++;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseOwnership(service_name);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!owned_service_names_.empty()) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to release all service names. # of services left: "
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << owned_service_names_.size();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detach from the remote objects.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ObjectProxyTable::iterator iter = object_proxy_table_.begin();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != object_proxy_table_.end(); ++iter) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->second->Detach();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release object proxies and exported objects here. We should do this
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here rather than in the destructor to avoid memory leaks due to
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cyclic references.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  object_proxy_table_.clear();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exported_object_table_.clear();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Private connection should be closed.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connection_) {
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove Disconnected watcher.
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedDBusError error;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveFilterFunction(Bus::OnConnectionDisconnectedFilter, this);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveMatch(kDisconnectedMatchRule, error.get());
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (connection_type_ == PRIVATE)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ClosePrivateConnection();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // dbus_connection_close() won't unref.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_connection_unref(connection_);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_ = NULL;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutdown_completed_ = true;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::ShutdownOnDBusThreadAndBlock() {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnOriginThread();
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(dbus_task_runner_.get());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskToDBusThread(FROM_HERE, base::Bind(
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Bus::ShutdownOnDBusThreadAndBlockInternal,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/125222
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowWait allow_wait;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the shutdown is complete on the D-Bus thread.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The shutdown should not hang, but set timeout just in case.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTimeoutSecs = 3;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta timeout(base::TimeDelta::FromSeconds(kTimeoutSecs));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool signaled = on_shutdown_.TimedWait(timeout);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, !signaled) << "Failed to shutdown the bus";
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::RequestOwnership(const std::string& service_name,
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           ServiceOwnershipOptions options,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           OnOwnershipCallback on_ownership_callback) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnOriginThread();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskToDBusThread(FROM_HERE, base::Bind(
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Bus::RequestOwnershipInternal,
510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      this, service_name, options, on_ownership_callback));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::RequestOwnershipInternal(const std::string& service_name,
514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   ServiceOwnershipOptions options,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   OnOwnershipCallback on_ownership_callback) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = Connect();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    success = RequestOwnershipAndBlock(service_name, options);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskToOriginThread(FROM_HERE,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::Bind(on_ownership_callback,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    service_name,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    success));
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool Bus::RequestOwnershipAndBlock(const std::string& service_name,
529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   ServiceOwnershipOptions options) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_bus_request_name() is a blocking call.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we already own the service name.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (owned_service_names_.find(service_name) != owned_service_names_.end()) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDBusError error;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int result = dbus_bus_request_name(connection_,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           service_name.c_str(),
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                           options,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           error.get());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to get the ownership of " << service_name << ": "
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << (error.is_set() ? error.message() : "");
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  owned_service_names_.insert(service_name);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::ReleaseOwnership(const std::string& service_name) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_bus_request_name() is a blocking call.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we already own the service name.
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string>::iterator found =
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      owned_service_names_.find(service_name);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == owned_service_names_.end()) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << service_name << " is not owned by the bus";
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDBusError error;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int result = dbus_bus_release_name(connection_, service_name.c_str(),
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           error.get());
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == DBUS_RELEASE_NAME_REPLY_RELEASED) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    owned_service_names_.erase(found);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to release the ownership of " << service_name << ": "
574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << (error.is_set() ? error.message() : "")
575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               << ", result code: " << result;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::SetUpAsyncOperations() {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (async_operations_set_up_)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Process all the incoming data if any, so that OnDispatchStatus() will
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be called when the incoming data is ready.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessAllIncomingDataIfAny();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = dbus_connection_set_watch_functions(connection_,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &Bus::OnAddWatchThunk,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &Bus::OnRemoveWatchThunk,
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &Bus::OnToggleWatchThunk,
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     this,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     NULL);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  success = dbus_connection_set_timeout_functions(connection_,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &Bus::OnAddTimeoutThunk,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &Bus::OnRemoveTimeoutThunk,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &Bus::OnToggleTimeoutThunk,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  this,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  NULL);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_connection_set_dispatch_status_function(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_,
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &Bus::OnDispatchStatusChangedThunk,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  async_operations_set_up_ = true;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusMessage* Bus::SendWithReplyAndBlock(DBusMessage* request,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int timeout_ms,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        DBusError* error) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_connection_send_with_reply_and_block(
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_, request, timeout_ms, error);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::SendWithReply(DBusMessage* request,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DBusPendingCall** pending_call,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int timeout_ms) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_connection_send_with_reply(
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_, request, pending_call, timeout_ms);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::Send(DBusMessage* request, uint32* serial) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_connection_send(connection_, request, serial);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::AddFilterFunction(DBusHandleMessageFunction filter_function,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            void* user_data) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<DBusHandleMessageFunction, void*> filter_data_pair =
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::make_pair(filter_function, user_data);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filter_functions_added_.find(filter_data_pair) !=
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_functions_added_.end()) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Filter function already exists: " << filter_function
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << " with associated data: " << user_data;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_connection_add_filter(
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_, filter_function, user_data, NULL);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_functions_added_.insert(filter_data_pair);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::RemoveFilterFunction(DBusHandleMessageFunction filter_function,
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               void* user_data) {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<DBusHandleMessageFunction, void*> filter_data_pair =
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::make_pair(filter_function, user_data);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filter_functions_added_.find(filter_data_pair) ==
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter_functions_added_.end()) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to remove an unknown filter function: "
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << filter_function
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << " with associated data: " << user_data;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_connection_remove_filter(connection_, filter_function, user_data);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_functions_added_.erase(filter_data_pair);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::AddMatch(const std::string& match_rule, DBusError* error) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, int>::iterator iter =
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      match_rules_added_.find(match_rule);
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter != match_rules_added_.end()) {
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The already existing rule's counter is incremented.
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iter->second++;
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Match rule already exists: " << match_rule;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_bus_add_match(connection_, match_rule.c_str(), error);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  match_rules_added_[match_rule] = 1;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Bus::RemoveMatch(const std::string& match_rule, DBusError* error) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<std::string, int>::iterator iter =
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      match_rules_added_.find(match_rule);
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == match_rules_added_.end()) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Requested to remove an unknown match rule: " << match_rule;
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The rule's counter is decremented and the rule is deleted when reachs 0.
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  iter->second--;
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter->second == 0) {
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus_bus_remove_match(connection_, match_rule.c_str(), error);
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    match_rules_added_.erase(match_rule);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::TryRegisterObjectPath(const ObjectPath& object_path,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const DBusObjectPathVTable* vtable,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                void* user_data,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                DBusError* error) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registered_object_paths_.find(object_path) !=
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registered_object_paths_.end()) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Object path already registered: " << object_path.value();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_connection_try_register_object_path(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_,
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      object_path.value().c_str(),
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vtable,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_data,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registered_object_paths_.insert(object_path);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::UnregisterObjectPath(const ObjectPath& object_path) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(connection_);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (registered_object_paths_.find(object_path) ==
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registered_object_paths_.end()) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Requested to unregister an unknown object path: "
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << object_path.value();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_connection_unregister_object_path(
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_,
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      object_path.value().c_str());
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registered_object_paths_.erase(object_path);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::ShutdownOnDBusThreadAndBlockInternal() {
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShutdownAndBlock();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  on_shutdown_.Signal();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::ProcessAllIncomingDataIfAny() {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As mentioned at the class comment in .h file, connection_ can be NULL.
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!connection_)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It is safe and necessary to call dbus_connection_get_dispatch_status even
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the connection is lost. Otherwise we will miss "Disconnected" signal.
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (crbug.com/174431)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dbus_connection_get_dispatch_status(connection_) ==
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_DISPATCH_DATA_REMAINS) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (dbus_connection_dispatch(connection_) ==
7887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           DBUS_DISPATCH_DATA_REMAINS) {
7897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
793b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void Bus::PostTaskToDBusThreadAndReply(
794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const tracked_objects::Location& from_here,
795b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::Closure& task,
796b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const base::Closure& reply) {
797b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  AssertOnOriginThread();
798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
799b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (dbus_task_runner_.get()) {
800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!dbus_task_runner_->PostTaskAndReply(from_here, task, reply)) {
801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the D-Bus thread message loop";
802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
804b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK(origin_task_runner_.get());
805b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!origin_task_runner_->PostTaskAndReply(from_here, task, reply)) {
806b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the origin message loop";
807b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
808b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
809b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
810b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::PostTaskToOriginThread(const tracked_objects::Location& from_here,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const base::Closure& task) {
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(origin_task_runner_.get());
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!origin_task_runner_->PostTask(from_here, task)) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Failed to post a task to the origin message loop";
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::PostTaskToDBusThread(const tracked_objects::Location& from_here,
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const base::Closure& task) {
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dbus_task_runner_.get()) {
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!dbus_task_runner_->PostTask(from_here, task)) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the D-Bus thread message loop";
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(origin_task_runner_.get());
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!origin_task_runner_->PostTask(from_here, task)) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the origin message loop";
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::PostDelayedTaskToDBusThread(
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& task,
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delay) {
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dbus_task_runner_.get()) {
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!dbus_task_runner_->PostDelayedTask(
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            from_here, task, delay)) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the D-Bus thread message loop";
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(origin_task_runner_.get());
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!origin_task_runner_->PostDelayedTask(from_here, task, delay)) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to post a task to the origin message loop";
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Bus::HasDBusThread() {
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dbus_task_runner_.get() != NULL;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::AssertOnOriginThread() {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::AssertOnDBusThread() {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::AssertIOAllowed();
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dbus_task_runner_.get()) {
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(dbus_task_runner_->RunsTasksOnCurrentThread());
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AssertOnOriginThread();
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string Bus::GetServiceOwnerAndBlock(const std::string& service_name,
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         GetServiceOwnerOption options) {
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AssertOnDBusThread();
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MethodCall get_name_owner_call("org.freedesktop.DBus", "GetNameOwner");
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessageWriter writer(&get_name_owner_call);
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  writer.AppendString(service_name);
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VLOG(1) << "Method call: " << get_name_owner_call.ToString();
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ObjectPath obj_path("/org/freedesktop/DBus");
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!get_name_owner_call.SetDestination("org.freedesktop.DBus") ||
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !get_name_owner_call.SetPath(obj_path)) {
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (options == REPORT_ERRORS)
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Failed to get name owner.";
882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return "";
883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScopedDBusError error;
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DBusMessage* response_message =
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SendWithReplyAndBlock(get_name_owner_call.raw_message(),
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            ObjectProxy::TIMEOUT_USE_DEFAULT,
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            error.get());
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!response_message) {
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (options == REPORT_ERRORS) {
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Failed to get name owner. Got " << error.name() << ": "
893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << error.message();
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return "";
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<Response> response(Response::FromRawMessage(response_message));
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessageReader reader(response.get());
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string service_owner;
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!reader.PopString(&service_owner))
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    service_owner.clear();
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return service_owner;
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void Bus::GetServiceOwner(const std::string& service_name,
908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const GetServiceOwnerCallback& callback) {
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AssertOnOriginThread();
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostTaskToDBusThread(
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&Bus::GetServiceOwnerInternal, this, service_name, callback));
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void Bus::GetServiceOwnerInternal(const std::string& service_name,
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const GetServiceOwnerCallback& callback) {
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AssertOnDBusThread();
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string service_owner;
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (Connect())
922b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    service_owner = GetServiceOwnerAndBlock(service_name, SUPPRESS_ERRORS);
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostTaskToOriginThread(FROM_HERE, base::Bind(callback, service_owner));
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Bus::ListenForServiceOwnerChange(
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& service_name,
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const GetServiceOwnerCallback& callback) {
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssertOnOriginThread();
930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!service_name.empty());
931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!callback.is_null());
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PostTaskToDBusThread(FROM_HERE,
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       base::Bind(&Bus::ListenForServiceOwnerChangeInternal,
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  this, service_name, callback));
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Bus::ListenForServiceOwnerChangeInternal(
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& service_name,
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const GetServiceOwnerCallback& callback) {
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssertOnDBusThread();
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!service_name.empty());
943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!callback.is_null());
944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!Connect() || !SetUpAsyncOperations())
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (service_owner_changed_listener_map_.empty()) {
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool filter_added =
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        AddFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(filter_added);
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ServiceOwnerChangedListenerMap::iterator it =
955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      service_owner_changed_listener_map_.find(service_name);
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == service_owner_changed_listener_map_.end()) {
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Add a match rule for the new service name.
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string name_owner_changed_match_rule =
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::StringPrintf(kServiceNameOwnerChangeMatchRule,
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           service_name.c_str());
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ScopedDBusError error;
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AddMatch(name_owner_changed_match_rule, error.get());
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (error.is_set()) {
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Failed to add match rule for " << service_name
965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << ". Got " << error.name() << ": " << error.message();
966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    service_owner_changed_listener_map_[service_name].push_back(callback);
970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check if the callback has already been added.
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<GetServiceOwnerCallback>& callbacks = it->second;
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < callbacks.size(); ++i) {
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (callbacks[i].Equals(callback))
977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
978868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callbacks.push_back(callback);
980868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
981868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
982868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Bus::UnlistenForServiceOwnerChange(
983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& service_name,
984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const GetServiceOwnerCallback& callback) {
985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssertOnOriginThread();
986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!service_name.empty());
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!callback.is_null());
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
989868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PostTaskToDBusThread(FROM_HERE,
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       base::Bind(&Bus::UnlistenForServiceOwnerChangeInternal,
991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  this, service_name, callback));
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
994868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Bus::UnlistenForServiceOwnerChangeInternal(
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& service_name,
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const GetServiceOwnerCallback& callback) {
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssertOnDBusThread();
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!service_name.empty());
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!callback.is_null());
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ServiceOwnerChangedListenerMap::iterator it =
1002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      service_owner_changed_listener_map_.find(service_name);
1003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == service_owner_changed_listener_map_.end())
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<GetServiceOwnerCallback>& callbacks = it->second;
1007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < callbacks.size(); ++i) {
1008868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (callbacks[i].Equals(callback)) {
1009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      callbacks.erase(callbacks.begin() + i);
1010868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;  // There can be only one.
1011868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1012868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1013868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!callbacks.empty())
1014868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1015868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1016868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Last callback for |service_name| has been removed, remove match rule.
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::string name_owner_changed_match_rule =
1018868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::StringPrintf(kServiceNameOwnerChangeMatchRule,
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         service_name.c_str());
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScopedDBusError error;
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveMatch(name_owner_changed_match_rule, error.get());
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // And remove |service_owner_changed_listener_map_| entry.
1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  service_owner_changed_listener_map_.erase(it);
1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (service_owner_changed_listener_map_.empty()) {
1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool filter_removed =
1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        RemoveFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(filter_removed);
1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // watch will be deleted when raw_watch is removed in OnRemoveWatch().
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Watch* watch = new Watch(raw_watch);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (watch->IsReadyToBeWatched()) {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watch->StartWatching();
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_watches_;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnRemoveWatch(DBusWatch* raw_watch) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Watch* watch = static_cast<Watch*>(dbus_watch_get_data(raw_watch));
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete watch;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --num_pending_watches_;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnToggleWatch(DBusWatch* raw_watch) {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Watch* watch = static_cast<Watch*>(dbus_watch_get_data(raw_watch));
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (watch->IsReadyToBeWatched()) {
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watch->StartWatching();
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's safe to call this if StartWatching() wasn't called, per
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // message_pump_libevent.h.
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    watch->StopWatching();
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dbus_bool_t Bus::OnAddTimeout(DBusTimeout* raw_timeout) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timeout will be deleted when raw_timeout is removed in
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnRemoveTimeoutThunk().
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Timeout* timeout = new Timeout(raw_timeout);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timeout->IsReadyToBeMonitored()) {
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout->StartMonitoring(this);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_timeouts_;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnRemoveTimeout(DBusTimeout* raw_timeout) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Timeout* timeout = static_cast<Timeout*>(dbus_timeout_get_data(raw_timeout));
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timeout->Complete();
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --num_pending_timeouts_;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnToggleTimeout(DBusTimeout* raw_timeout) {
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Timeout* timeout = static_cast<Timeout*>(dbus_timeout_get_data(raw_timeout));
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timeout->IsReadyToBeMonitored()) {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout->StartMonitoring(this);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout->StopMonitoring();
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnDispatchStatusChanged(DBusConnection* connection,
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  DBusDispatchStatus status) {
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(connection, connection_);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertOnDBusThread();
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We cannot call ProcessAllIncomingDataIfAny() here, as calling
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_connection_dispatch() inside DBusDispatchStatusFunction is
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prohibited by the D-Bus library. Hence, we post a task here instead.
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See comments for dbus_connection_set_dispatch_status_function().
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskToDBusThread(FROM_HERE,
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       base::Bind(&Bus::ProcessAllIncomingDataIfAny,
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  this));
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Bus::OnConnectionDisconnected(DBusConnection* connection) {
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssertOnDBusThread();
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!on_disconnected_closure_.is_null())
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PostTaskToOriginThread(FROM_HERE, on_disconnected_closure_);
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!connection)
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!dbus_connection_get_is_connected(connection));
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShutdownAndBlock();
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Bus::OnServiceOwnerChanged(DBusMessage* message) {
1125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(message);
1126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssertOnDBusThread();
1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // |message| will be unrefed on exit of the function. Increment the
1129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // reference so we can use it in Signal::FromRawMessage() below.
1130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dbus_message_ref(message);
1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<Signal> signal(Signal::FromRawMessage(message));
1132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Confirm the validity of the NameOwnerChanged signal.
1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (signal->GetMember() != kNameOwnerChangedSignal ||
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      signal->GetInterface() != DBUS_INTERFACE_DBUS ||
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      signal->GetSender() != DBUS_SERVICE_DBUS) {
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MessageReader reader(signal.get());
1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string service_name;
1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string old_owner;
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string new_owner;
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!reader.PopString(&service_name) ||
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !reader.PopString(&old_owner) ||
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      !reader.PopString(&new_owner)) {
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ServiceOwnerChangedListenerMap::const_iterator it =
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      service_owner_changed_listener_map_.find(service_name);
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (it == service_owner_changed_listener_map_.end())
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::vector<GetServiceOwnerCallback>& callbacks = it->second;
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (size_t i = 0; i < callbacks.size(); ++i) {
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PostTaskToOriginThread(FROM_HERE,
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           base::Bind(callbacks[i], new_owner));
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dbus_bool_t Bus::OnAddWatchThunk(DBusWatch* raw_watch, void* data) {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return self->OnAddWatch(raw_watch);
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnRemoveWatchThunk(DBusWatch* raw_watch, void* data) {
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnRemoveWatch(raw_watch);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnToggleWatchThunk(DBusWatch* raw_watch, void* data) {
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnToggleWatch(raw_watch);
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dbus_bool_t Bus::OnAddTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return self->OnAddTimeout(raw_timeout);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnRemoveTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnRemoveTimeout(raw_timeout);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnToggleTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnToggleTimeout(raw_timeout);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Bus::OnDispatchStatusChangedThunk(DBusConnection* connection,
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       DBusDispatchStatus status,
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       void* data) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bus* self = static_cast<Bus*>(data);
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  self->OnDispatchStatusChanged(connection, status);
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DBusHandlerResult Bus::OnConnectionDisconnectedFilter(
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DBusConnection* connection,
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DBusMessage* message,
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* data) {
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dbus_message_is_signal(message,
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             DBUS_INTERFACE_LOCAL,
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             kDisconnectedSignal)) {
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Bus* self = static_cast<Bus*>(data);
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self->OnConnectionDisconnected(connection);
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return DBUS_HANDLER_RESULT_HANDLED;
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
1222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DBusHandlerResult Bus::OnServiceOwnerChangedFilter(
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DBusConnection* connection,
1224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DBusMessage* message,
1225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void* data) {
1226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (dbus_message_is_signal(message,
1227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             DBUS_INTERFACE_DBUS,
1228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             kNameOwnerChangedSignal)) {
1229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Bus* self = static_cast<Bus*>(data);
1230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    self->OnServiceOwnerChanged(message);
1231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Always return unhandled to let others, e.g. ObjectProxies, handle the same
1233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // signal.
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace dbus
1238