Bug 1246931: Add DBus I/O helpers, r=shuang
authorThomas Zimmermann <tdz@users.sourceforge.net>
Tue, 12 Apr 2016 16:14:39 +0200
changeset 316608 1fb15d5b02de33b23f747bf668d22cf4949abe01
parent 316607 2af67c46b79965f2322f454f57eb675df364d4cc
child 316609 322af6a2c02ac68e8883ac9f6d8590831476043f
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshuang
bugs1246931
milestone48.0a1
Bug 1246931: Add DBus I/O helpers, r=shuang The I/O helpers for DBus are based on |RawDBusConnection|'s |Send*| and |Watch| methods. Moving them out of this class will make them available to other modules.
ipc/dbus/DBusHelpers.cpp
ipc/dbus/DBusHelpers.h
ipc/dbus/RawDBusConnection.cpp
ipc/dbus/RawDBusConnection.h
ipc/dbus/moz.build
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusHelpers.cpp
@@ -0,0 +1,246 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DBusHelpers.h"
+#include "mozilla/ipc/DBusMessageRefPtr.h"
+#include "mozilla/ipc/DBusPendingCallRefPtr.h"
+#include "mozilla/ipc/DBusWatcher.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/unused.h"
+#include "nsThreadUtils.h"
+
+#undef CHROMIUM_LOG
+#if defined(MOZ_WIDGET_GONK)
+#include <android/log.h>
+#define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args);
+#else
+#define CHROMIUM_LOG(args...)  printf(args);
+#endif
+
+namespace mozilla {
+namespace ipc {
+
+//
+// DBus I/O
+//
+
+namespace {
+
+class Notification final
+{
+public:
+  Notification(DBusReplyCallback aCallback, void* aData)
+    : mCallback(aCallback)
+    , mData(aData)
+  { }
+
+  // Callback function for DBus replies. Only run it on I/O thread.
+  //
+  static void Handle(DBusPendingCall* aCall, void* aData)
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    RefPtr<DBusPendingCall> call = already_AddRefed<DBusPendingCall>(aCall);
+
+    UniquePtr<Notification> ntfn(static_cast<Notification*>(aData));
+
+    RefPtr<DBusMessage> reply = already_AddRefed<DBusMessage>(
+      dbus_pending_call_steal_reply(call));
+
+    // The reply can be null if the timeout has been reached.
+    if (reply) {
+      ntfn->RunCallback(reply);
+    }
+
+    dbus_pending_call_cancel(call);
+  }
+
+private:
+  void RunCallback(DBusMessage* aMessage)
+  {
+    if (mCallback) {
+      mCallback(aMessage, mData);
+    }
+  }
+
+  DBusReplyCallback mCallback;
+  void*             mData;
+};
+
+static already_AddRefed<DBusMessage>
+BuildDBusMessage(const char* aDestination,
+                 const char* aPath,
+                 const char* aIntf,
+                 const char* aFunc,
+                 int aFirstArgType,
+                 va_list aArgs)
+{
+  RefPtr<DBusMessage> msg = already_AddRefed<DBusMessage>(
+    dbus_message_new_method_call(aDestination, aPath, aIntf, aFunc));
+
+  if (!msg) {
+    CHROMIUM_LOG("dbus_message_new_method_call failed");
+    return nullptr;
+  }
+
+  auto success = dbus_message_append_args_valist(msg, aFirstArgType, aArgs);
+
+  if (!success) {
+    CHROMIUM_LOG("dbus_message_append_args_valist failed");
+    return nullptr;
+  }
+
+  return msg.forget();
+}
+
+} // anonymous namespace
+
+nsresult
+DBusWatchConnection(DBusConnection* aConnection)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+
+  auto success =
+    dbus_connection_set_watch_functions(aConnection,
+                                        DBusWatcher::AddWatchFunction,
+                                        DBusWatcher::RemoveWatchFunction,
+                                        DBusWatcher::ToggleWatchFunction,
+                                        aConnection, nullptr);
+  if (!success) {
+    CHROMIUM_LOG("dbus_connection_set_watch_functions failed");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+void
+DBusUnwatchConnection(DBusConnection* aConnection)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+
+  auto success = dbus_connection_set_watch_functions(aConnection,
+                                                     nullptr, nullptr, nullptr,
+                                                     nullptr, nullptr);
+  if (!success) {
+    CHROMIUM_LOG("dbus_connection_set_watch_functions failed");
+  }
+}
+
+nsresult
+DBusSendMessage(DBusConnection* aConnection, DBusMessage* aMessage)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+  MOZ_ASSERT(aMessage);
+
+  auto success = dbus_connection_send(aConnection, aMessage, nullptr);
+
+  if (!success) {
+    CHROMIUM_LOG("dbus_connection_send failed");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback, void* aData,
+                         int aTimeout,
+                         DBusMessage* aMessage)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+  MOZ_ASSERT(aMessage);
+
+  UniquePtr<Notification> ntfn = MakeUnique<Notification>(aCallback, aData);
+
+  auto call = static_cast<DBusPendingCall*>(nullptr);
+
+  auto success = dbus_connection_send_with_reply(aConnection,
+                                                 aMessage,
+                                                 &call,
+                                                 aTimeout);
+  if (!success) {
+    CHROMIUM_LOG("dbus_connection_send_with_reply failed");
+    return NS_ERROR_FAILURE;
+  }
+
+  success = dbus_pending_call_set_notify(call, Notification::Handle,
+                                         ntfn.get(), nullptr);
+  if (!success) {
+    CHROMIUM_LOG("dbus_pending_call_set_notify failed");
+    return NS_ERROR_FAILURE;
+  }
+
+  Unused << ntfn.release(); // Picked up in |Notification::Handle|
+
+  return NS_OK;
+}
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback,
+                         void* aData,
+                         int aTimeout,
+                         const char* aDestination,
+                         const char* aPath,
+                         const char* aIntf,
+                         const char* aFunc,
+                         int aFirstArgType,
+                         va_list aArgs)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+
+  RefPtr<DBusMessage> msg =
+    BuildDBusMessage(aDestination, aPath, aIntf, aFunc, aFirstArgType, aArgs);
+
+  if (!msg) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return DBusSendMessageWithReply(aConnection, aCallback, aData, aTimeout, msg);
+}
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback,
+                         void* aData,
+                         int aTimeout,
+                         const char* aDestination,
+                         const char* aPath,
+                         const char* aIntf,
+                         const char* aFunc,
+                         int aFirstArgType,
+                         ...)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+  MOZ_ASSERT(aConnection);
+
+  va_list args;
+  va_start(args, aFirstArgType);
+
+  auto rv = DBusSendMessageWithReply(aConnection,
+                                     aCallback, aData,
+                                     aTimeout,
+                                     aDestination, aPath, aIntf, aFunc,
+                                     aFirstArgType, args);
+  va_end(args);
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusHelpers.h
@@ -0,0 +1,65 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ipc_DBusHelpers_h
+#define mozilla_ipc_DBusHelpers_h
+
+#include <dbus/dbus.h>
+#include <stdarg.h>
+#include "nsError.h"
+
+namespace mozilla {
+namespace ipc {
+
+//
+// DBus I/O
+//
+
+typedef void (*DBusReplyCallback)(DBusMessage*, void*);
+
+nsresult
+DBusWatchConnection(DBusConnection* aConnection);
+
+void
+DBusUnwatchConnection(DBusConnection* aConnection);
+
+nsresult
+DBusSendMessage(DBusConnection* aConnection, DBusMessage* aMessage);
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback, void* aData,
+                         int aTimeout,
+                         DBusMessage* aMessage);
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback,
+                         void* aData,
+                         int aTimeout,
+                         const char* aDestination,
+                         const char* aPath,
+                         const char* aIntf,
+                         const char* aFunc,
+                         int aFirstArgType,
+                         va_list aArgs);
+
+nsresult
+DBusSendMessageWithReply(DBusConnection* aConnection,
+                         DBusReplyCallback aCallback,
+                         void* aData,
+                         int aTimeout,
+                         const char* aDestination,
+                         const char* aPath,
+                         const char* aIntf,
+                         const char* aFunc,
+                         int aFirstArgType,
+                         ...);
+
+} // namespace ipc
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusHelpers_h
--- a/ipc/dbus/RawDBusConnection.cpp
+++ b/ipc/dbus/RawDBusConnection.cpp
@@ -1,79 +1,23 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "RawDBusConnection.h"
 #include "base/message_loop.h"
+#include "mozilla/ipc/DBusHelpers.h"
 #include "mozilla/ipc/DBusWatcher.h"
-#include "nsThreadUtils.h"
-#include "RawDBusConnection.h"
-
-#ifdef CHROMIUM_LOG
-#undef CHROMIUM_LOG
-#endif
-
-#if defined(MOZ_WIDGET_GONK)
-#include <android/log.h>
-#define CHROMIUM_LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args);
-#else
-#define CHROMIUM_LOG(args...)  printf(args);
-#endif
 
 namespace mozilla {
 namespace ipc {
 
 //
-// Notification
-//
-
-class Notification
-{
-public:
-  Notification(DBusReplyCallback aCallback, void* aData)
-  : mCallback(aCallback),
-    mData(aData)
-  { }
-
-  // Callback function for DBus replies. Only run it on I/O thread.
-  //
-  static void Handle(DBusPendingCall* aCall, void* aData)
-  {
-    MOZ_ASSERT(!NS_IsMainThread());
-    MOZ_ASSERT(MessageLoop::current());
-
-    nsAutoPtr<Notification> ntfn(static_cast<Notification*>(aData));
-
-    // The reply can be non-null if the timeout has been reached.
-    DBusMessage* reply = dbus_pending_call_steal_reply(aCall);
-
-    if (reply) {
-      ntfn->RunCallback(reply);
-      dbus_message_unref(reply);
-    }
-
-    dbus_pending_call_cancel(aCall);
-    dbus_pending_call_unref(aCall);
-  }
-
-private:
-  void RunCallback(DBusMessage* aMessage)
-  {
-    if (mCallback) {
-      mCallback(aMessage, mData);
-    }
-  }
-
-  DBusReplyCallback mCallback;
-  void*             mData;
-};
-
-//
 // RawDBusConnection
 //
 
 bool RawDBusConnection::sDBusIsInit(false);
 
 RawDBusConnection::RawDBusConnection()
 {
 }
@@ -103,120 +47,68 @@ nsresult RawDBusConnection::EstablishDBu
 
   dbus_connection_set_exit_on_disconnect(mConnection, FALSE);
 
   return NS_OK;
 }
 
 bool RawDBusConnection::Watch()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(MessageLoop::current());
 
-  dbus_bool_t success =
-    dbus_connection_set_watch_functions(mConnection,
-                                        DBusWatcher::AddWatchFunction,
-                                        DBusWatcher::RemoveWatchFunction,
-                                        DBusWatcher::ToggleWatchFunction,
-                                        this->GetConnection(), nullptr);
-  NS_ENSURE_TRUE(success == TRUE, false);
-
-  return true;
+  return NS_SUCCEEDED(DBusWatchConnection(mConnection));
 }
 
 bool RawDBusConnection::Send(DBusMessage* aMessage)
 {
-  MOZ_ASSERT(aMessage);
-  MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(MessageLoop::current());
 
-  dbus_bool_t success = dbus_connection_send(mConnection,
-                                             aMessage,
-                                             nullptr);
-  if (success != TRUE) {
+  auto rv = DBusSendMessage(mConnection, aMessage);
+
+  if (NS_FAILED(rv)) {
     dbus_message_unref(aMessage);
     return false;
   }
+
   return true;
 }
 
 bool RawDBusConnection::SendWithReply(DBusReplyCallback aCallback,
                                       void* aData,
                                       int aTimeout,
                                       DBusMessage* aMessage)
 {
-  MOZ_ASSERT(aMessage);
-  MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(MessageLoop::current());
 
-  nsAutoPtr<Notification> ntfn(new Notification(aCallback, aData));
-  NS_ENSURE_TRUE(ntfn, false);
-
-  DBusPendingCall* call;
+  auto rv = DBusSendMessageWithReply(mConnection, aCallback, aData, aTimeout,
+                                     aMessage);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
 
-  dbus_bool_t success = dbus_connection_send_with_reply(mConnection,
-                                                        aMessage,
-                                                        &call,
-                                                        aTimeout);
-  NS_ENSURE_TRUE(success == TRUE, false);
-
-  success = dbus_pending_call_set_notify(call, Notification::Handle,
-                                         ntfn, nullptr);
-  NS_ENSURE_TRUE(success == TRUE, false);
-
-  ntfn.forget();
   dbus_message_unref(aMessage);
 
   return true;
 }
 
 bool RawDBusConnection::SendWithReply(DBusReplyCallback aCallback,
                                       void* aData,
                                       int aTimeout,
                                       const char* aDestination,
                                       const char* aPath,
                                       const char* aIntf,
                                       const char* aFunc,
                                       int aFirstArgType,
                                       ...)
 {
-  MOZ_ASSERT(!NS_IsMainThread());
   va_list args;
+  va_start(args, aFirstArgType);
 
-  va_start(args, aFirstArgType);
-  DBusMessage* msg = BuildDBusMessage(aDestination, aPath, aIntf, aFunc,
-                                      aFirstArgType, args);
+  auto rv = DBusSendMessageWithReply(mConnection, aCallback, aData,
+                                     aTimeout, aDestination, aPath, aIntf,
+                                     aFunc, aFirstArgType, args);
   va_end(args);
 
-  if (!msg) {
-    return false;
-  }
-
-  return SendWithReply(aCallback, aData, aTimeout, msg);
-}
-
-DBusMessage* RawDBusConnection::BuildDBusMessage(const char* aDestination,
-                                                 const char* aPath,
-                                                 const char* aIntf,
-                                                 const char* aFunc,
-                                                 int aFirstArgType,
-                                                 va_list aArgs)
-{
-  DBusMessage* msg = dbus_message_new_method_call(aDestination,
-                                                  aPath, aIntf,
-                                                  aFunc);
-  if (!msg) {
-    CHROMIUM_LOG("Could not allocate D-Bus message object!");
-    return nullptr;
-  }
-
-  /* append arguments */
-  if (!dbus_message_append_args_valist(msg, aFirstArgType, aArgs)) {
-    CHROMIUM_LOG("Could not append argument to method call!");
-    dbus_message_unref(msg);
-    return nullptr;
-  }
-
-  return msg;
+  return NS_SUCCEEDED(rv);
 }
 
 }
 }
--- a/ipc/dbus/RawDBusConnection.h
+++ b/ipc/dbus/RawDBusConnection.h
@@ -37,21 +37,16 @@ public:
 
   bool SendWithReply(DBusReplyCallback aCallback, void* aData,
                      int aTimeout,
                      const char* aDestination,
                      const char* aPath, const char* aIntf,
                      const char *aFunc, int aFirstArgType, ...);
 
 protected:
-  DBusMessage* BuildDBusMessage(const char* aDestination,
-                                const char* aPath, const char* aIntf,
-                                const char* aFunc, int aFirstArgType,
-                                va_list args);
-
   RefPtr<DBusConnection> mConnection;
 
 private:
   static bool sDBusIsInit;
 };
 
 }
 }
--- a/ipc/dbus/moz.build
+++ b/ipc/dbus/moz.build
@@ -1,24 +1,26 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.ipc += [
     'DBusConnectionRefPtr.h',
+    'DBusHelpers.h',
     'DBusMessageRefPtr.h',
     'DBusPendingCallRefPtr.h',
     'DBusUtils.h',
     'DBusWatcher.h',
     'RawDBusConnection.h',
 ]
 
 SOURCES += [
+    'DBusHelpers.cpp',
     'DBusUtils.cpp',
     'DBusWatcher.cpp',
     'RawDBusConnection.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'