bus.cc 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "dbus/bus.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include "base/bind.h"
  8. #include "base/files/file_descriptor_watcher_posix.h"
  9. #include "base/logging.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/synchronization/waitable_event.h"
  14. #include "base/threading/scoped_blocking_call.h"
  15. #include "base/threading/sequenced_task_runner_handle.h"
  16. #include "base/threading/thread.h"
  17. #include "base/threading/thread_restrictions.h"
  18. #include "base/time/time.h"
  19. #include "base/timer/elapsed_timer.h"
  20. #include "dbus/exported_object.h"
  21. #include "dbus/message.h"
  22. #include "dbus/object_manager.h"
  23. #include "dbus/object_path.h"
  24. #include "dbus/object_proxy.h"
  25. #include "dbus/scoped_dbus_error.h"
  26. namespace dbus {
  27. namespace {
  28. const char kDisconnectedSignal[] = "Disconnected";
  29. const char kDisconnectedMatchRule[] =
  30. "type='signal', path='/org/freedesktop/DBus/Local',"
  31. "interface='org.freedesktop.DBus.Local', member='Disconnected'";
  32. // The NameOwnerChanged member in org.freedesktop.DBus
  33. const char kNameOwnerChangedSignal[] = "NameOwnerChanged";
  34. // The match rule used to filter for changes to a given service name owner.
  35. const char kServiceNameOwnerChangeMatchRule[] =
  36. "type='signal',interface='org.freedesktop.DBus',"
  37. "member='NameOwnerChanged',path='/org/freedesktop/DBus',"
  38. "sender='org.freedesktop.DBus',arg0='%s'";
  39. // The class is used for watching the file descriptor used for D-Bus
  40. // communication.
  41. class Watch {
  42. public:
  43. explicit Watch(DBusWatch* watch) : raw_watch_(watch) {
  44. dbus_watch_set_data(raw_watch_, this, nullptr);
  45. }
  46. Watch(const Watch&) = delete;
  47. Watch& operator=(const Watch&) = delete;
  48. ~Watch() { dbus_watch_set_data(raw_watch_, nullptr, nullptr); }
  49. // Returns true if the underlying file descriptor is ready to be watched.
  50. bool IsReadyToBeWatched() {
  51. return dbus_watch_get_enabled(raw_watch_);
  52. }
  53. // Starts watching the underlying file descriptor.
  54. void StartWatching() {
  55. const int file_descriptor = dbus_watch_get_unix_fd(raw_watch_);
  56. const unsigned int flags = dbus_watch_get_flags(raw_watch_);
  57. // Using base::Unretained(this) is safe because watches are automatically
  58. // canceled when |read_watcher_| and |write_watcher_| are destroyed.
  59. if (flags & DBUS_WATCH_READABLE) {
  60. read_watcher_ = base::FileDescriptorWatcher::WatchReadable(
  61. file_descriptor,
  62. base::BindRepeating(&Watch::OnFileReady, base::Unretained(this),
  63. DBUS_WATCH_READABLE));
  64. }
  65. if (flags & DBUS_WATCH_WRITABLE) {
  66. write_watcher_ = base::FileDescriptorWatcher::WatchWritable(
  67. file_descriptor,
  68. base::BindRepeating(&Watch::OnFileReady, base::Unretained(this),
  69. DBUS_WATCH_WRITABLE));
  70. }
  71. }
  72. // Stops watching the underlying file descriptor.
  73. void StopWatching() {
  74. read_watcher_.reset();
  75. write_watcher_.reset();
  76. }
  77. private:
  78. void OnFileReady(unsigned int flags) {
  79. CHECK(dbus_watch_handle(raw_watch_, flags)) << "Unable to allocate memory";
  80. }
  81. raw_ptr<DBusWatch> raw_watch_;
  82. std::unique_ptr<base::FileDescriptorWatcher::Controller> read_watcher_;
  83. std::unique_ptr<base::FileDescriptorWatcher::Controller> write_watcher_;
  84. };
  85. // The class is used for monitoring the timeout used for D-Bus method
  86. // calls.
  87. class Timeout {
  88. public:
  89. explicit Timeout(DBusTimeout* timeout) : raw_timeout_(timeout) {
  90. // Associated |this| with the underlying DBusTimeout.
  91. dbus_timeout_set_data(raw_timeout_, this, nullptr);
  92. }
  93. Timeout(const Timeout&) = delete;
  94. Timeout& operator=(const Timeout&) = delete;
  95. ~Timeout() {
  96. // Remove the association between |this| and the |raw_timeout_|.
  97. dbus_timeout_set_data(raw_timeout_, nullptr, nullptr);
  98. }
  99. // Returns true if the timeout is ready to be monitored.
  100. bool IsReadyToBeMonitored() {
  101. return dbus_timeout_get_enabled(raw_timeout_);
  102. }
  103. // Starts monitoring the timeout.
  104. void StartMonitoring(Bus* bus) {
  105. bus->GetDBusTaskRunner()->PostDelayedTask(
  106. FROM_HERE,
  107. base::BindOnce(&Timeout::HandleTimeout, weak_ptr_factory_.GetWeakPtr()),
  108. GetInterval());
  109. }
  110. // Stops monitoring the timeout.
  111. void StopMonitoring() { weak_ptr_factory_.InvalidateWeakPtrs(); }
  112. base::TimeDelta GetInterval() {
  113. return base::Milliseconds(dbus_timeout_get_interval(raw_timeout_));
  114. }
  115. private:
  116. // Calls DBus to handle the timeout.
  117. void HandleTimeout() { CHECK(dbus_timeout_handle(raw_timeout_)); }
  118. raw_ptr<DBusTimeout> raw_timeout_;
  119. base::WeakPtrFactory<Timeout> weak_ptr_factory_{this};
  120. };
  121. } // namespace
  122. Bus::Options::Options()
  123. : bus_type(SESSION),
  124. connection_type(PRIVATE) {
  125. }
  126. Bus::Options::~Options() = default;
  127. Bus::Options::Options(Bus::Options&&) = default;
  128. Bus::Options& Bus::Options::operator=(Bus::Options&&) = default;
  129. Bus::Bus(const Options& options)
  130. : bus_type_(options.bus_type),
  131. connection_type_(options.connection_type),
  132. dbus_task_runner_(options.dbus_task_runner),
  133. on_shutdown_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
  134. base::WaitableEvent::InitialState::NOT_SIGNALED),
  135. connection_(nullptr),
  136. origin_thread_id_(base::PlatformThread::CurrentId()),
  137. async_operations_set_up_(false),
  138. shutdown_completed_(false),
  139. num_pending_watches_(0),
  140. num_pending_timeouts_(0),
  141. address_(options.address) {
  142. // This is safe to call multiple times.
  143. dbus_threads_init_default();
  144. // The origin message loop is unnecessary if the client uses synchronous
  145. // functions only.
  146. if (base::SequencedTaskRunnerHandle::IsSet())
  147. origin_task_runner_ = base::SequencedTaskRunnerHandle::Get();
  148. }
  149. Bus::~Bus() {
  150. DCHECK(!connection_);
  151. DCHECK(owned_service_names_.empty());
  152. DCHECK(match_rules_added_.empty());
  153. DCHECK(filter_functions_added_.empty());
  154. DCHECK(registered_object_paths_.empty());
  155. DCHECK_EQ(0, num_pending_watches_);
  156. // TODO(satorux): This check fails occasionally in browser_tests for tests
  157. // that run very quickly. Perhaps something does not have time to clean up.
  158. // Despite the check failing, the tests seem to run fine. crosbug.com/23416
  159. // DCHECK_EQ(0, num_pending_timeouts_);
  160. }
  161. ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
  162. const ObjectPath& object_path) {
  163. return GetObjectProxyWithOptions(service_name, object_path,
  164. ObjectProxy::DEFAULT_OPTIONS);
  165. }
  166. ObjectProxy* Bus::GetObjectProxyWithOptions(const std::string& service_name,
  167. const ObjectPath& object_path,
  168. int options) {
  169. AssertOnOriginThread();
  170. // Check if we already have the requested object proxy.
  171. const ObjectProxyTable::key_type key(service_name + object_path.value(),
  172. options);
  173. ObjectProxyTable::iterator iter = object_proxy_table_.find(key);
  174. if (iter != object_proxy_table_.end()) {
  175. return iter->second.get();
  176. }
  177. scoped_refptr<ObjectProxy> object_proxy =
  178. new ObjectProxy(this, service_name, object_path, options);
  179. object_proxy_table_[key] = object_proxy;
  180. return object_proxy.get();
  181. }
  182. bool Bus::RemoveObjectProxy(const std::string& service_name,
  183. const ObjectPath& object_path,
  184. base::OnceClosure callback) {
  185. return RemoveObjectProxyWithOptions(service_name, object_path,
  186. ObjectProxy::DEFAULT_OPTIONS,
  187. std::move(callback));
  188. }
  189. bool Bus::RemoveObjectProxyWithOptions(const std::string& service_name,
  190. const ObjectPath& object_path,
  191. int options,
  192. base::OnceClosure callback) {
  193. AssertOnOriginThread();
  194. // Check if we have the requested object proxy.
  195. const ObjectProxyTable::key_type key(service_name + object_path.value(),
  196. options);
  197. ObjectProxyTable::iterator iter = object_proxy_table_.find(key);
  198. if (iter != object_proxy_table_.end()) {
  199. scoped_refptr<ObjectProxy> object_proxy = iter->second;
  200. object_proxy_table_.erase(iter);
  201. // Object is present. Remove it now and Detach on the DBus thread.
  202. GetDBusTaskRunner()->PostTask(
  203. FROM_HERE, base::BindOnce(&Bus::RemoveObjectProxyInternal, this,
  204. object_proxy, std::move(callback)));
  205. return true;
  206. }
  207. return false;
  208. }
  209. void Bus::RemoveObjectProxyInternal(scoped_refptr<ObjectProxy> object_proxy,
  210. base::OnceClosure callback) {
  211. AssertOnDBusThread();
  212. object_proxy->Detach();
  213. GetOriginTaskRunner()->PostTask(FROM_HERE, std::move(callback));
  214. }
  215. ExportedObject* Bus::GetExportedObject(const ObjectPath& object_path) {
  216. AssertOnOriginThread();
  217. // Check if we already have the requested exported object.
  218. ExportedObjectTable::iterator iter = exported_object_table_.find(object_path);
  219. if (iter != exported_object_table_.end()) {
  220. return iter->second.get();
  221. }
  222. scoped_refptr<ExportedObject> exported_object =
  223. new ExportedObject(this, object_path);
  224. exported_object_table_[object_path] = exported_object;
  225. return exported_object.get();
  226. }
  227. void Bus::UnregisterExportedObject(const ObjectPath& object_path) {
  228. AssertOnOriginThread();
  229. // Remove the registered object from the table first, to allow a new
  230. // GetExportedObject() call to return a new object, rather than this one.
  231. ExportedObjectTable::iterator iter = exported_object_table_.find(object_path);
  232. if (iter == exported_object_table_.end())
  233. return;
  234. scoped_refptr<ExportedObject> exported_object = iter->second;
  235. exported_object_table_.erase(iter);
  236. // Post the task to perform the final unregistration to the D-Bus thread.
  237. // Since the registration also happens on the D-Bus thread in
  238. // TryRegisterObjectPath(), and the task runner we post to is a
  239. // SequencedTaskRunner, there is a guarantee that this will happen before any
  240. // future registration call.
  241. GetDBusTaskRunner()->PostTask(
  242. FROM_HERE, base::BindOnce(&Bus::UnregisterExportedObjectInternal, this,
  243. exported_object));
  244. }
  245. void Bus::UnregisterExportedObjectInternal(
  246. scoped_refptr<ExportedObject> exported_object) {
  247. AssertOnDBusThread();
  248. exported_object->Unregister();
  249. }
  250. ObjectManager* Bus::GetObjectManager(const std::string& service_name,
  251. const ObjectPath& object_path) {
  252. AssertOnOriginThread();
  253. // Check if we already have the requested object manager.
  254. const ObjectManagerTable::key_type key(service_name + object_path.value());
  255. ObjectManagerTable::iterator iter = object_manager_table_.find(key);
  256. if (iter != object_manager_table_.end()) {
  257. return iter->second.get();
  258. }
  259. scoped_refptr<ObjectManager> object_manager =
  260. ObjectManager::Create(this, service_name, object_path);
  261. object_manager_table_[key] = object_manager;
  262. return object_manager.get();
  263. }
  264. bool Bus::RemoveObjectManager(const std::string& service_name,
  265. const ObjectPath& object_path,
  266. base::OnceClosure callback) {
  267. AssertOnOriginThread();
  268. DCHECK(!callback.is_null());
  269. const ObjectManagerTable::key_type key(service_name + object_path.value());
  270. ObjectManagerTable::iterator iter = object_manager_table_.find(key);
  271. if (iter == object_manager_table_.end())
  272. return false;
  273. // ObjectManager is present. Remove it now and CleanUp on the DBus thread.
  274. scoped_refptr<ObjectManager> object_manager = iter->second;
  275. object_manager_table_.erase(iter);
  276. GetDBusTaskRunner()->PostTask(
  277. FROM_HERE, base::BindOnce(&Bus::RemoveObjectManagerInternal, this,
  278. object_manager, std::move(callback)));
  279. return true;
  280. }
  281. void Bus::RemoveObjectManagerInternal(
  282. scoped_refptr<dbus::ObjectManager> object_manager,
  283. base::OnceClosure callback) {
  284. AssertOnDBusThread();
  285. DCHECK(object_manager.get());
  286. object_manager->CleanUp();
  287. // The ObjectManager has to be deleted on the origin thread since it was
  288. // created there.
  289. GetOriginTaskRunner()->PostTask(
  290. FROM_HERE, base::BindOnce(&Bus::RemoveObjectManagerInternalHelper, this,
  291. object_manager, std::move(callback)));
  292. }
  293. void Bus::RemoveObjectManagerInternalHelper(
  294. scoped_refptr<dbus::ObjectManager> object_manager,
  295. base::OnceClosure callback) {
  296. AssertOnOriginThread();
  297. DCHECK(object_manager);
  298. // Release the object manager and run the callback.
  299. object_manager = nullptr;
  300. std::move(callback).Run();
  301. }
  302. bool Bus::Connect() {
  303. // dbus_bus_get_private() and dbus_bus_get() are blocking calls.
  304. AssertOnDBusThread();
  305. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  306. base::BlockingType::MAY_BLOCK);
  307. // Check if it's already initialized.
  308. if (connection_)
  309. return true;
  310. ScopedDBusError error;
  311. if (bus_type_ == CUSTOM_ADDRESS) {
  312. if (connection_type_ == PRIVATE) {
  313. connection_ = dbus_connection_open_private(address_.c_str(), error.get());
  314. } else {
  315. connection_ = dbus_connection_open(address_.c_str(), error.get());
  316. }
  317. } else {
  318. const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
  319. if (connection_type_ == PRIVATE) {
  320. connection_ = dbus_bus_get_private(dbus_bus_type, error.get());
  321. } else {
  322. connection_ = dbus_bus_get(dbus_bus_type, error.get());
  323. }
  324. }
  325. if (!connection_) {
  326. LOG(ERROR) << "Failed to connect to the bus: "
  327. << (error.is_set() ? error.message() : "");
  328. return false;
  329. }
  330. if (bus_type_ == CUSTOM_ADDRESS) {
  331. // We should call dbus_bus_register here, otherwise unique name can not be
  332. // acquired. According to dbus specification, it is responsible to call
  333. // org.freedesktop.DBus.Hello method at the beging of bus connection to
  334. // acquire unique name. In the case of dbus_bus_get, dbus_bus_register is
  335. // called internally.
  336. if (!dbus_bus_register(connection_, error.get())) {
  337. LOG(ERROR) << "Failed to register the bus component: "
  338. << (error.is_set() ? error.message() : "");
  339. return false;
  340. }
  341. }
  342. // We shouldn't exit on the disconnected signal.
  343. dbus_connection_set_exit_on_disconnect(connection_, false);
  344. // Watch Disconnected signal.
  345. AddFilterFunction(Bus::OnConnectionDisconnectedFilter, this);
  346. AddMatch(kDisconnectedMatchRule, error.get());
  347. return true;
  348. }
  349. void Bus::ClosePrivateConnection() {
  350. // dbus_connection_close is blocking call.
  351. AssertOnDBusThread();
  352. DCHECK_EQ(PRIVATE, connection_type_)
  353. << "non-private connection should not be closed";
  354. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  355. base::BlockingType::MAY_BLOCK);
  356. dbus_connection_close(connection_);
  357. }
  358. void Bus::ShutdownAndBlock() {
  359. AssertOnDBusThread();
  360. if (shutdown_completed_)
  361. return; // Already shutdowned, just return.
  362. // Unregister the exported objects.
  363. for (ExportedObjectTable::iterator iter = exported_object_table_.begin();
  364. iter != exported_object_table_.end(); ++iter) {
  365. iter->second->Unregister();
  366. }
  367. // Release all service names.
  368. for (std::set<std::string>::iterator iter = owned_service_names_.begin();
  369. iter != owned_service_names_.end();) {
  370. // This is a bit tricky but we should increment the iter here as
  371. // ReleaseOwnership() may remove |service_name| from the set.
  372. const std::string& service_name = *iter++;
  373. ReleaseOwnership(service_name);
  374. }
  375. if (!owned_service_names_.empty()) {
  376. LOG(ERROR) << "Failed to release all service names. # of services left: "
  377. << owned_service_names_.size();
  378. }
  379. // Detach from the remote objects.
  380. for (ObjectProxyTable::iterator iter = object_proxy_table_.begin();
  381. iter != object_proxy_table_.end(); ++iter) {
  382. iter->second->Detach();
  383. }
  384. // Clean up the object managers.
  385. for (ObjectManagerTable::iterator iter = object_manager_table_.begin();
  386. iter != object_manager_table_.end(); ++iter) {
  387. iter->second->CleanUp();
  388. }
  389. // Release object proxies and exported objects here. We should do this
  390. // here rather than in the destructor to avoid memory leaks due to
  391. // cyclic references.
  392. object_proxy_table_.clear();
  393. exported_object_table_.clear();
  394. // Private connection should be closed.
  395. if (connection_) {
  396. base::ScopedBlockingCall scoped_blocking_call(
  397. FROM_HERE, base::BlockingType::MAY_BLOCK);
  398. // Remove Disconnected watcher.
  399. ScopedDBusError error;
  400. RemoveFilterFunction(Bus::OnConnectionDisconnectedFilter, this);
  401. RemoveMatch(kDisconnectedMatchRule, error.get());
  402. if (connection_type_ == PRIVATE)
  403. ClosePrivateConnection();
  404. // dbus_connection_close() won't unref.
  405. dbus_connection_unref(connection_);
  406. }
  407. connection_ = nullptr;
  408. shutdown_completed_ = true;
  409. }
  410. void Bus::ShutdownOnDBusThreadAndBlock() {
  411. AssertOnOriginThread();
  412. DCHECK(dbus_task_runner_);
  413. GetDBusTaskRunner()->PostTask(
  414. FROM_HERE,
  415. base::BindOnce(&Bus::ShutdownOnDBusThreadAndBlockInternal, this));
  416. // http://crbug.com/125222
  417. base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
  418. // Wait until the shutdown is complete on the D-Bus thread.
  419. // The shutdown should not hang, but set timeout just in case.
  420. const int kTimeoutSecs = 3;
  421. const base::TimeDelta timeout(base::Seconds(kTimeoutSecs));
  422. const bool signaled = on_shutdown_.TimedWait(timeout);
  423. LOG_IF(ERROR, !signaled) << "Failed to shutdown the bus";
  424. }
  425. void Bus::RequestOwnership(const std::string& service_name,
  426. ServiceOwnershipOptions options,
  427. OnOwnershipCallback on_ownership_callback) {
  428. AssertOnOriginThread();
  429. GetDBusTaskRunner()->PostTask(
  430. FROM_HERE,
  431. base::BindOnce(&Bus::RequestOwnershipInternal, this, service_name,
  432. options, std::move(on_ownership_callback)));
  433. }
  434. void Bus::RequestOwnershipInternal(const std::string& service_name,
  435. ServiceOwnershipOptions options,
  436. OnOwnershipCallback on_ownership_callback) {
  437. AssertOnDBusThread();
  438. bool success = Connect();
  439. if (success)
  440. success = RequestOwnershipAndBlock(service_name, options);
  441. GetOriginTaskRunner()->PostTask(
  442. FROM_HERE,
  443. base::BindOnce(std::move(on_ownership_callback), service_name, success));
  444. }
  445. bool Bus::RequestOwnershipAndBlock(const std::string& service_name,
  446. ServiceOwnershipOptions options) {
  447. DCHECK(connection_);
  448. // dbus_bus_request_name() is a blocking call.
  449. AssertOnDBusThread();
  450. // Check if we already own the service name.
  451. if (owned_service_names_.find(service_name) != owned_service_names_.end()) {
  452. return true;
  453. }
  454. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  455. base::BlockingType::MAY_BLOCK);
  456. ScopedDBusError error;
  457. const int result = dbus_bus_request_name(connection_,
  458. service_name.c_str(),
  459. options,
  460. error.get());
  461. if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
  462. LOG(ERROR) << "Failed to get the ownership of " << service_name << ": "
  463. << (error.is_set() ? error.message() : "");
  464. return false;
  465. }
  466. owned_service_names_.insert(service_name);
  467. return true;
  468. }
  469. bool Bus::ReleaseOwnership(const std::string& service_name) {
  470. DCHECK(connection_);
  471. // dbus_bus_release_name() is a blocking call.
  472. AssertOnDBusThread();
  473. // Check if we already own the service name.
  474. std::set<std::string>::iterator found =
  475. owned_service_names_.find(service_name);
  476. if (found == owned_service_names_.end()) {
  477. LOG(ERROR) << service_name << " is not owned by the bus";
  478. return false;
  479. }
  480. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  481. base::BlockingType::MAY_BLOCK);
  482. ScopedDBusError error;
  483. const int result = dbus_bus_release_name(connection_, service_name.c_str(),
  484. error.get());
  485. if (result == DBUS_RELEASE_NAME_REPLY_RELEASED) {
  486. owned_service_names_.erase(found);
  487. return true;
  488. } else {
  489. LOG(ERROR) << "Failed to release the ownership of " << service_name << ": "
  490. << (error.is_set() ? error.message() : "")
  491. << ", result code: " << result;
  492. return false;
  493. }
  494. }
  495. bool Bus::SetUpAsyncOperations() {
  496. DCHECK(connection_);
  497. AssertOnDBusThread();
  498. if (async_operations_set_up_)
  499. return true;
  500. // Process all the incoming data if any, so that OnDispatchStatus() will
  501. // be called when the incoming data is ready.
  502. ProcessAllIncomingDataIfAny();
  503. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  504. base::BlockingType::MAY_BLOCK);
  505. bool success = dbus_connection_set_watch_functions(
  506. connection_, &Bus::OnAddWatchThunk, &Bus::OnRemoveWatchThunk,
  507. &Bus::OnToggleWatchThunk, this, nullptr);
  508. CHECK(success) << "Unable to allocate memory";
  509. success = dbus_connection_set_timeout_functions(
  510. connection_, &Bus::OnAddTimeoutThunk, &Bus::OnRemoveTimeoutThunk,
  511. &Bus::OnToggleTimeoutThunk, this, nullptr);
  512. CHECK(success) << "Unable to allocate memory";
  513. dbus_connection_set_dispatch_status_function(
  514. connection_, &Bus::OnDispatchStatusChangedThunk, this, nullptr);
  515. async_operations_set_up_ = true;
  516. return true;
  517. }
  518. DBusMessage* Bus::SendWithReplyAndBlock(DBusMessage* request,
  519. int timeout_ms,
  520. DBusError* error) {
  521. DCHECK(connection_);
  522. AssertOnDBusThread();
  523. base::ElapsedTimer elapsed;
  524. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  525. base::BlockingType::MAY_BLOCK);
  526. DBusMessage* reply = dbus_connection_send_with_reply_and_block(
  527. connection_, request, timeout_ms, error);
  528. constexpr base::TimeDelta kLongCall = base::Seconds(1);
  529. LOG_IF(WARNING, elapsed.Elapsed() >= kLongCall)
  530. << "Bus::SendWithReplyAndBlock took "
  531. << elapsed.Elapsed().InMilliseconds() << "ms to process message: "
  532. << "type=" << dbus_message_type_to_string(dbus_message_get_type(request))
  533. << ", path=" << dbus_message_get_path(request)
  534. << ", interface=" << dbus_message_get_interface(request)
  535. << ", member=" << dbus_message_get_member(request);
  536. return reply;
  537. }
  538. void Bus::SendWithReply(DBusMessage* request,
  539. DBusPendingCall** pending_call,
  540. int timeout_ms) {
  541. DCHECK(connection_);
  542. AssertOnDBusThread();
  543. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  544. base::BlockingType::MAY_BLOCK);
  545. const bool success = dbus_connection_send_with_reply(
  546. connection_, request, pending_call, timeout_ms);
  547. CHECK(success) << "Unable to allocate memory";
  548. }
  549. void Bus::Send(DBusMessage* request, uint32_t* serial) {
  550. DCHECK(connection_);
  551. AssertOnDBusThread();
  552. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  553. base::BlockingType::MAY_BLOCK);
  554. const bool success = dbus_connection_send(connection_, request, serial);
  555. CHECK(success) << "Unable to allocate memory";
  556. }
  557. void Bus::AddFilterFunction(DBusHandleMessageFunction filter_function,
  558. void* user_data) {
  559. DCHECK(connection_);
  560. AssertOnDBusThread();
  561. std::pair<DBusHandleMessageFunction, void*> filter_data_pair =
  562. std::make_pair(filter_function, user_data);
  563. if (filter_functions_added_.find(filter_data_pair) !=
  564. filter_functions_added_.end()) {
  565. VLOG(1) << "Filter function already exists: " << filter_function
  566. << " with associated data: " << user_data;
  567. return;
  568. }
  569. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  570. base::BlockingType::MAY_BLOCK);
  571. const bool success = dbus_connection_add_filter(connection_, filter_function,
  572. user_data, nullptr);
  573. CHECK(success) << "Unable to allocate memory";
  574. filter_functions_added_.insert(filter_data_pair);
  575. }
  576. void Bus::RemoveFilterFunction(DBusHandleMessageFunction filter_function,
  577. void* user_data) {
  578. DCHECK(connection_);
  579. AssertOnDBusThread();
  580. std::pair<DBusHandleMessageFunction, void*> filter_data_pair =
  581. std::make_pair(filter_function, user_data);
  582. if (filter_functions_added_.find(filter_data_pair) ==
  583. filter_functions_added_.end()) {
  584. VLOG(1) << "Requested to remove an unknown filter function: "
  585. << filter_function
  586. << " with associated data: " << user_data;
  587. return;
  588. }
  589. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  590. base::BlockingType::MAY_BLOCK);
  591. dbus_connection_remove_filter(connection_, filter_function, user_data);
  592. filter_functions_added_.erase(filter_data_pair);
  593. }
  594. void Bus::AddMatch(const std::string& match_rule, DBusError* error) {
  595. DCHECK(connection_);
  596. AssertOnDBusThread();
  597. std::map<std::string, int>::iterator iter =
  598. match_rules_added_.find(match_rule);
  599. if (iter != match_rules_added_.end()) {
  600. // The already existing rule's counter is incremented.
  601. iter->second++;
  602. VLOG(1) << "Match rule already exists: " << match_rule;
  603. return;
  604. }
  605. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  606. base::BlockingType::MAY_BLOCK);
  607. dbus_bus_add_match(connection_, match_rule.c_str(), error);
  608. match_rules_added_[match_rule] = 1;
  609. }
  610. bool Bus::RemoveMatch(const std::string& match_rule, DBusError* error) {
  611. DCHECK(connection_);
  612. AssertOnDBusThread();
  613. std::map<std::string, int>::iterator iter =
  614. match_rules_added_.find(match_rule);
  615. if (iter == match_rules_added_.end()) {
  616. LOG(ERROR) << "Requested to remove an unknown match rule: " << match_rule;
  617. return false;
  618. }
  619. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  620. base::BlockingType::MAY_BLOCK);
  621. // The rule's counter is decremented and the rule is deleted when reachs 0.
  622. iter->second--;
  623. if (iter->second == 0) {
  624. dbus_bus_remove_match(connection_, match_rule.c_str(), error);
  625. match_rules_added_.erase(match_rule);
  626. }
  627. return true;
  628. }
  629. bool Bus::TryRegisterObjectPath(const ObjectPath& object_path,
  630. const DBusObjectPathVTable* vtable,
  631. void* user_data,
  632. DBusError* error) {
  633. return TryRegisterObjectPathInternal(
  634. object_path, vtable, user_data, error,
  635. dbus_connection_try_register_object_path);
  636. }
  637. bool Bus::TryRegisterFallback(const ObjectPath& object_path,
  638. const DBusObjectPathVTable* vtable,
  639. void* user_data,
  640. DBusError* error) {
  641. return TryRegisterObjectPathInternal(object_path, vtable, user_data, error,
  642. dbus_connection_try_register_fallback);
  643. }
  644. bool Bus::TryRegisterObjectPathInternal(
  645. const ObjectPath& object_path,
  646. const DBusObjectPathVTable* vtable,
  647. void* user_data,
  648. DBusError* error,
  649. TryRegisterObjectPathFunction* register_function) {
  650. DCHECK(connection_);
  651. AssertOnDBusThread();
  652. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  653. base::BlockingType::MAY_BLOCK);
  654. if (registered_object_paths_.find(object_path) !=
  655. registered_object_paths_.end()) {
  656. LOG(ERROR) << "Object path already registered: " << object_path.value();
  657. return false;
  658. }
  659. const bool success = register_function(
  660. connection_, object_path.value().c_str(), vtable, user_data, error);
  661. if (success)
  662. registered_object_paths_.insert(object_path);
  663. return success;
  664. }
  665. void Bus::UnregisterObjectPath(const ObjectPath& object_path) {
  666. DCHECK(connection_);
  667. AssertOnDBusThread();
  668. if (registered_object_paths_.find(object_path) ==
  669. registered_object_paths_.end()) {
  670. LOG(ERROR) << "Requested to unregister an unknown object path: "
  671. << object_path.value();
  672. return;
  673. }
  674. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  675. base::BlockingType::MAY_BLOCK);
  676. const bool success = dbus_connection_unregister_object_path(
  677. connection_,
  678. object_path.value().c_str());
  679. CHECK(success) << "Unable to allocate memory";
  680. registered_object_paths_.erase(object_path);
  681. }
  682. void Bus::ShutdownOnDBusThreadAndBlockInternal() {
  683. AssertOnDBusThread();
  684. ShutdownAndBlock();
  685. on_shutdown_.Signal();
  686. }
  687. void Bus::ProcessAllIncomingDataIfAny() {
  688. AssertOnDBusThread();
  689. // As mentioned at the class comment in .h file, connection_ can be NULL.
  690. if (!connection_)
  691. return;
  692. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  693. base::BlockingType::MAY_BLOCK);
  694. // It is safe and necessary to call dbus_connection_get_dispatch_status even
  695. // if the connection is lost.
  696. if (dbus_connection_get_dispatch_status(connection_) ==
  697. DBUS_DISPATCH_DATA_REMAINS) {
  698. while (dbus_connection_dispatch(connection_) ==
  699. DBUS_DISPATCH_DATA_REMAINS) {
  700. }
  701. }
  702. }
  703. base::SequencedTaskRunner* Bus::GetDBusTaskRunner() {
  704. if (dbus_task_runner_)
  705. return dbus_task_runner_.get();
  706. else
  707. return GetOriginTaskRunner();
  708. }
  709. base::SequencedTaskRunner* Bus::GetOriginTaskRunner() {
  710. DCHECK(origin_task_runner_);
  711. return origin_task_runner_.get();
  712. }
  713. bool Bus::HasDBusThread() {
  714. return dbus_task_runner_ != nullptr;
  715. }
  716. void Bus::AssertOnOriginThread() {
  717. if (origin_task_runner_) {
  718. CHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  719. } else {
  720. CHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
  721. }
  722. }
  723. void Bus::AssertOnDBusThread() {
  724. if (dbus_task_runner_) {
  725. CHECK(dbus_task_runner_->RunsTasksInCurrentSequence());
  726. } else {
  727. AssertOnOriginThread();
  728. }
  729. }
  730. std::string Bus::GetServiceOwnerAndBlock(const std::string& service_name,
  731. GetServiceOwnerOption options) {
  732. AssertOnDBusThread();
  733. MethodCall get_name_owner_call("org.freedesktop.DBus", "GetNameOwner");
  734. MessageWriter writer(&get_name_owner_call);
  735. writer.AppendString(service_name);
  736. VLOG(1) << "Method call: " << get_name_owner_call.ToString();
  737. const ObjectPath obj_path("/org/freedesktop/DBus");
  738. if (!get_name_owner_call.SetDestination("org.freedesktop.DBus") ||
  739. !get_name_owner_call.SetPath(obj_path)) {
  740. if (options == REPORT_ERRORS)
  741. LOG(ERROR) << "Failed to get name owner.";
  742. return "";
  743. }
  744. ScopedDBusError error;
  745. DBusMessage* response_message =
  746. SendWithReplyAndBlock(get_name_owner_call.raw_message(),
  747. ObjectProxy::TIMEOUT_USE_DEFAULT,
  748. error.get());
  749. if (!response_message) {
  750. if (options == REPORT_ERRORS) {
  751. LOG(ERROR) << "Failed to get name owner. Got " << error.name() << ": "
  752. << error.message();
  753. }
  754. return "";
  755. }
  756. std::unique_ptr<Response> response(
  757. Response::FromRawMessage(response_message));
  758. MessageReader reader(response.get());
  759. std::string service_owner;
  760. if (!reader.PopString(&service_owner))
  761. service_owner.clear();
  762. return service_owner;
  763. }
  764. void Bus::GetServiceOwner(const std::string& service_name,
  765. GetServiceOwnerCallback callback) {
  766. AssertOnOriginThread();
  767. GetDBusTaskRunner()->PostTask(
  768. FROM_HERE, base::BindOnce(&Bus::GetServiceOwnerInternal, this,
  769. service_name, std::move(callback)));
  770. }
  771. void Bus::GetServiceOwnerInternal(const std::string& service_name,
  772. GetServiceOwnerCallback callback) {
  773. AssertOnDBusThread();
  774. std::string service_owner;
  775. if (Connect())
  776. service_owner = GetServiceOwnerAndBlock(service_name, SUPPRESS_ERRORS);
  777. GetOriginTaskRunner()->PostTask(
  778. FROM_HERE, base::BindOnce(std::move(callback), service_owner));
  779. }
  780. void Bus::ListenForServiceOwnerChange(
  781. const std::string& service_name,
  782. const ServiceOwnerChangeCallback& callback) {
  783. AssertOnOriginThread();
  784. DCHECK(!service_name.empty());
  785. DCHECK(!callback.is_null());
  786. GetDBusTaskRunner()->PostTask(
  787. FROM_HERE, base::BindOnce(&Bus::ListenForServiceOwnerChangeInternal, this,
  788. service_name, callback));
  789. }
  790. void Bus::ListenForServiceOwnerChangeInternal(
  791. const std::string& service_name,
  792. const ServiceOwnerChangeCallback& callback) {
  793. AssertOnDBusThread();
  794. DCHECK(!service_name.empty());
  795. DCHECK(!callback.is_null());
  796. if (!Connect() || !SetUpAsyncOperations())
  797. return;
  798. if (service_owner_changed_listener_map_.empty())
  799. AddFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
  800. ServiceOwnerChangedListenerMap::iterator it =
  801. service_owner_changed_listener_map_.find(service_name);
  802. if (it == service_owner_changed_listener_map_.end()) {
  803. // Add a match rule for the new service name.
  804. const std::string name_owner_changed_match_rule =
  805. base::StringPrintf(kServiceNameOwnerChangeMatchRule,
  806. service_name.c_str());
  807. ScopedDBusError error;
  808. AddMatch(name_owner_changed_match_rule, error.get());
  809. if (error.is_set()) {
  810. LOG(ERROR) << "Failed to add match rule for " << service_name
  811. << ". Got " << error.name() << ": " << error.message();
  812. return;
  813. }
  814. service_owner_changed_listener_map_[service_name].push_back(callback);
  815. return;
  816. }
  817. // Check if the callback has already been added.
  818. std::vector<ServiceOwnerChangeCallback>& callbacks = it->second;
  819. for (size_t i = 0; i < callbacks.size(); ++i) {
  820. if (callbacks[i] == callback)
  821. return;
  822. }
  823. callbacks.push_back(callback);
  824. }
  825. void Bus::UnlistenForServiceOwnerChange(
  826. const std::string& service_name,
  827. const ServiceOwnerChangeCallback& callback) {
  828. AssertOnOriginThread();
  829. DCHECK(!service_name.empty());
  830. DCHECK(!callback.is_null());
  831. GetDBusTaskRunner()->PostTask(
  832. FROM_HERE, base::BindOnce(&Bus::UnlistenForServiceOwnerChangeInternal,
  833. this, service_name, callback));
  834. }
  835. void Bus::UnlistenForServiceOwnerChangeInternal(
  836. const std::string& service_name,
  837. const ServiceOwnerChangeCallback& callback) {
  838. AssertOnDBusThread();
  839. DCHECK(!service_name.empty());
  840. DCHECK(!callback.is_null());
  841. ServiceOwnerChangedListenerMap::iterator it =
  842. service_owner_changed_listener_map_.find(service_name);
  843. if (it == service_owner_changed_listener_map_.end())
  844. return;
  845. std::vector<ServiceOwnerChangeCallback>& callbacks = it->second;
  846. for (size_t i = 0; i < callbacks.size(); ++i) {
  847. if (callbacks[i] == callback) {
  848. callbacks.erase(callbacks.begin() + i);
  849. break; // There can be only one.
  850. }
  851. }
  852. if (!callbacks.empty())
  853. return;
  854. // Last callback for |service_name| has been removed, remove match rule.
  855. const std::string name_owner_changed_match_rule =
  856. base::StringPrintf(kServiceNameOwnerChangeMatchRule,
  857. service_name.c_str());
  858. ScopedDBusError error;
  859. RemoveMatch(name_owner_changed_match_rule, error.get());
  860. // And remove |service_owner_changed_listener_map_| entry.
  861. service_owner_changed_listener_map_.erase(it);
  862. if (service_owner_changed_listener_map_.empty())
  863. RemoveFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
  864. }
  865. std::string Bus::GetConnectionName() {
  866. if (!connection_)
  867. return "";
  868. return dbus_bus_get_unique_name(connection_);
  869. }
  870. bool Bus::IsConnected() {
  871. return connection_ != nullptr;
  872. }
  873. dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
  874. AssertOnDBusThread();
  875. // watch will be deleted when raw_watch is removed in OnRemoveWatch().
  876. Watch* watch = new Watch(raw_watch);
  877. if (watch->IsReadyToBeWatched()) {
  878. watch->StartWatching();
  879. }
  880. ++num_pending_watches_;
  881. return true;
  882. }
  883. void Bus::OnRemoveWatch(DBusWatch* raw_watch) {
  884. AssertOnDBusThread();
  885. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  886. base::BlockingType::MAY_BLOCK);
  887. Watch* watch = static_cast<Watch*>(dbus_watch_get_data(raw_watch));
  888. delete watch;
  889. --num_pending_watches_;
  890. }
  891. void Bus::OnToggleWatch(DBusWatch* raw_watch) {
  892. AssertOnDBusThread();
  893. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  894. base::BlockingType::MAY_BLOCK);
  895. Watch* watch = static_cast<Watch*>(dbus_watch_get_data(raw_watch));
  896. if (watch->IsReadyToBeWatched())
  897. watch->StartWatching();
  898. else
  899. watch->StopWatching();
  900. }
  901. dbus_bool_t Bus::OnAddTimeout(DBusTimeout* raw_timeout) {
  902. AssertOnDBusThread();
  903. // |timeout| will be deleted by OnRemoveTimeoutThunk().
  904. Timeout* timeout = new Timeout(raw_timeout);
  905. if (timeout->IsReadyToBeMonitored()) {
  906. timeout->StartMonitoring(this);
  907. }
  908. ++num_pending_timeouts_;
  909. return true;
  910. }
  911. void Bus::OnRemoveTimeout(DBusTimeout* raw_timeout) {
  912. AssertOnDBusThread();
  913. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  914. base::BlockingType::MAY_BLOCK);
  915. Timeout* timeout = static_cast<Timeout*>(dbus_timeout_get_data(raw_timeout));
  916. delete timeout;
  917. --num_pending_timeouts_;
  918. }
  919. void Bus::OnToggleTimeout(DBusTimeout* raw_timeout) {
  920. AssertOnDBusThread();
  921. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  922. base::BlockingType::MAY_BLOCK);
  923. Timeout* timeout = static_cast<Timeout*>(dbus_timeout_get_data(raw_timeout));
  924. if (timeout->IsReadyToBeMonitored()) {
  925. timeout->StartMonitoring(this);
  926. } else {
  927. timeout->StopMonitoring();
  928. }
  929. }
  930. void Bus::OnDispatchStatusChanged(DBusConnection* connection,
  931. DBusDispatchStatus status) {
  932. DCHECK_EQ(connection, connection_);
  933. AssertOnDBusThread();
  934. // We cannot call ProcessAllIncomingDataIfAny() here, as calling
  935. // dbus_connection_dispatch() inside DBusDispatchStatusFunction is
  936. // prohibited by the D-Bus library. Hence, we post a task here instead.
  937. // See comments for dbus_connection_set_dispatch_status_function().
  938. GetDBusTaskRunner()->PostTask(
  939. FROM_HERE, base::BindOnce(&Bus::ProcessAllIncomingDataIfAny, this));
  940. }
  941. void Bus::OnServiceOwnerChanged(DBusMessage* message) {
  942. DCHECK(message);
  943. AssertOnDBusThread();
  944. // |message| will be unrefed on exit of the function. Increment the
  945. // reference so we can use it in Signal::FromRawMessage() below.
  946. dbus_message_ref(message);
  947. std::unique_ptr<Signal> signal(Signal::FromRawMessage(message));
  948. // Confirm the validity of the NameOwnerChanged signal.
  949. if (signal->GetMember() != kNameOwnerChangedSignal ||
  950. signal->GetInterface() != DBUS_INTERFACE_DBUS ||
  951. signal->GetSender() != DBUS_SERVICE_DBUS) {
  952. return;
  953. }
  954. MessageReader reader(signal.get());
  955. std::string service_name;
  956. std::string old_owner;
  957. std::string new_owner;
  958. if (!reader.PopString(&service_name) ||
  959. !reader.PopString(&old_owner) ||
  960. !reader.PopString(&new_owner)) {
  961. return;
  962. }
  963. ServiceOwnerChangedListenerMap::const_iterator it =
  964. service_owner_changed_listener_map_.find(service_name);
  965. if (it == service_owner_changed_listener_map_.end())
  966. return;
  967. const std::vector<ServiceOwnerChangeCallback>& callbacks = it->second;
  968. for (size_t i = 0; i < callbacks.size(); ++i) {
  969. GetOriginTaskRunner()->PostTask(FROM_HERE,
  970. base::BindOnce(callbacks[i], new_owner));
  971. }
  972. }
  973. // static
  974. dbus_bool_t Bus::OnAddWatchThunk(DBusWatch* raw_watch, void* data) {
  975. Bus* self = static_cast<Bus*>(data);
  976. return self->OnAddWatch(raw_watch);
  977. }
  978. // static
  979. void Bus::OnRemoveWatchThunk(DBusWatch* raw_watch, void* data) {
  980. Bus* self = static_cast<Bus*>(data);
  981. self->OnRemoveWatch(raw_watch);
  982. }
  983. // static
  984. void Bus::OnToggleWatchThunk(DBusWatch* raw_watch, void* data) {
  985. Bus* self = static_cast<Bus*>(data);
  986. self->OnToggleWatch(raw_watch);
  987. }
  988. // static
  989. dbus_bool_t Bus::OnAddTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
  990. Bus* self = static_cast<Bus*>(data);
  991. return self->OnAddTimeout(raw_timeout);
  992. }
  993. // static
  994. void Bus::OnRemoveTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
  995. Bus* self = static_cast<Bus*>(data);
  996. self->OnRemoveTimeout(raw_timeout);
  997. }
  998. // static
  999. void Bus::OnToggleTimeoutThunk(DBusTimeout* raw_timeout, void* data) {
  1000. Bus* self = static_cast<Bus*>(data);
  1001. self->OnToggleTimeout(raw_timeout);
  1002. }
  1003. // static
  1004. void Bus::OnDispatchStatusChangedThunk(DBusConnection* connection,
  1005. DBusDispatchStatus status,
  1006. void* data) {
  1007. Bus* self = static_cast<Bus*>(data);
  1008. self->OnDispatchStatusChanged(connection, status);
  1009. }
  1010. // static
  1011. DBusHandlerResult Bus::OnConnectionDisconnectedFilter(
  1012. DBusConnection* connection,
  1013. DBusMessage* message,
  1014. void* data) {
  1015. if (dbus_message_is_signal(message,
  1016. DBUS_INTERFACE_LOCAL,
  1017. kDisconnectedSignal)) {
  1018. // Abort when the connection is lost.
  1019. LOG(FATAL) << "D-Bus connection was disconnected. Aborting.";
  1020. }
  1021. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  1022. }
  1023. // static
  1024. DBusHandlerResult Bus::OnServiceOwnerChangedFilter(
  1025. DBusConnection* connection,
  1026. DBusMessage* message,
  1027. void* data) {
  1028. if (dbus_message_is_signal(message,
  1029. DBUS_INTERFACE_DBUS,
  1030. kNameOwnerChangedSignal)) {
  1031. Bus* self = static_cast<Bus*>(data);
  1032. self->OnServiceOwnerChanged(message);
  1033. }
  1034. // Always return unhandled to let others, e.g. ObjectProxies, handle the same
  1035. // signal.
  1036. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  1037. }
  1038. } // namespace dbus